diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Post.ts | 70 | ||||
-rw-r--r-- | lib/generateApi.ts | 49 | ||||
-rw-r--r-- | lib/getPost.ts | 7 | ||||
-rw-r--r-- | lib/getPosts.ts | 5 | ||||
-rw-r--r-- | lib/index.ts | 2 | ||||
-rw-r--r-- | lib/interfaces.ts | 35 | ||||
-rw-r--r-- | lib/parsePost.ts | 46 | ||||
-rw-r--r-- | lib/utils.ts | 14 |
8 files changed, 143 insertions, 85 deletions
diff --git a/lib/Post.ts b/lib/Post.ts new file mode 100644 index 0000000..27a6cb9 --- /dev/null +++ b/lib/Post.ts @@ -0,0 +1,70 @@ +import * as fs from 'fs'; +import { JSDOM } from 'jsdom'; + +const frontmatter = require('front-matter'); +const md = require('markdown-it')(); + +import { dateToPath, dateToString } from './utils'; +import { Date, FrontMatterObject, PostApiEntry, Meta } from './interfaces'; + +export default class Post { + date: Date; + fileTitle: string; + fileContent: string; + post: FrontMatterObject; + + constructor(filePath: string) { + let [year, month, day, title] = filePath.split('/').splice(-4, 4); + this.fileTitle = title.substr(0, title.lastIndexOf('.')); + this.date = { year, month, day }; + this.fileContent = fs.readFileSync(filePath, 'utf-8'); + this.post = frontmatter(this.fileContent); + } + + toApi(): PostApiEntry { + const { author, title, additionalMeta } = this.getMeta(); + const { description, html } = this.getPostContent(); + return { + date: dateToString(this.date), + author, + title, + path: `/kronika/${dateToPath(this.date)}/${this.fileTitle}`, + description, + meta: additionalMeta, + content: html, + }; + } + + getMeta(): Meta { + const { attributes } = this.post; + const author: string = attributes.author; + delete attributes.author; + const title: string = attributes.title; + delete attributes.title; + return { + author, + title, + additionalMeta: attributes, + }; + } + + getPostContent() { + const { body } = this.post; + const html = `<div>${md.render(body)}</div>`; + const description = this.getDescription(html); + + return { + html, + description, + }; + } + + getDescription(html: string): string { + const { document } = new JSDOM(`<div>${html}</div>`).window; + const elements = document.getElementsByTagName('p'); + + const description = elements[1].textContent; + + return description || ''; + } +} diff --git a/lib/generateApi.ts b/lib/generateApi.ts index 836fa2a..cade7e4 100644 --- a/lib/generateApi.ts +++ b/lib/generateApi.ts @@ -1,29 +1,30 @@ -import fs from "fs"; -import path from "path"; -import { Post } from "./interfaces"; +import fs from 'fs'; +import path from 'path'; +import Post from './Post'; +import { dateToPath } from './utils'; function mkDirByPathSync(targetDir: string) { const sep = path.sep; - const initDir = path.isAbsolute(targetDir) ? sep : ""; - const baseDir = "."; + const initDir = path.isAbsolute(targetDir) ? sep : ''; + const baseDir = '.'; return targetDir.split(sep).reduce((parentDir, childDir) => { const curDir = path.resolve(baseDir, parentDir, childDir); try { fs.mkdirSync(curDir); } catch (err) { - if (err.code === "EEXIST") { + if (err.code === 'EEXIST') { // curDir already exists! return curDir; } // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows. - if (err.code === "ENOENT") { + if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure. throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`); } - const caughtErr = ["EACCES", "EPERM", "EISDIR"].indexOf(err.code) > -1; + const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1; if (!caughtErr || (caughtErr && targetDir === curDir)) { throw err; // Throw if it's just the last created dir. } @@ -34,26 +35,38 @@ function mkDirByPathSync(targetDir: string) { } export function saveApiEntry(post: Post, path: string) { - const { year, month, day } = post.date; - const dir = `${path}/api/posts/${year}/${month}/${day}`; + const dir = `${path}/api/posts/${dateToPath(post.date)}`; mkDirByPathSync(dir); - const apiEntry = { - title: post.title, - date: `${year}-${month}-${day}`, - content: post.content.html, - meta: post.content.meta - }; + const apiEntry = post.toApi(); - fs.writeFile(`${dir}/${post.title}.json`, JSON.stringify(apiEntry), err => + fs.writeFile( + `${dir}/${post.fileTitle}.json`, + JSON.stringify(apiEntry), + (err) => (err ? console.log(err) : null) + ); +} + +/* + * This function generates paged api index on path `/api/paged-posts` + */ +function generateApiIndex(posts: Array<Post>, path: string) { + const parsedPosts = posts.map((post) => { + const apiEntry = post.toApi(); + delete apiEntry.content; + return apiEntry; + }); + const filePath = `${path}/api/posts.json`; + fs.writeFile(filePath, JSON.stringify(parsedPosts), (err) => err ? console.log(err) : null ); } export function generateApi(posts: Array<Post>, path: string) { try { - posts.forEach(post => saveApiEntry(post, path)); + generateApiIndex(posts, path); + posts.forEach((post) => saveApiEntry(post, path)); } catch (err) { console.log(err); } diff --git a/lib/getPost.ts b/lib/getPost.ts index 2555215..6e90b1f 100644 --- a/lib/getPost.ts +++ b/lib/getPost.ts @@ -1,5 +1,4 @@ -import { parsePost } from "./parsePost"; -import { Post } from "./interfaces"; +import Post from "./Post"; interface getPostArgument { year: string; @@ -14,6 +13,6 @@ export function getPost( ): Post { const filePath = `${path}/${year}/${month}/${day}/${title}.md`; - const post = parsePost(filePath); - return post; + const post = new Post(filePath); + return post; } diff --git a/lib/getPosts.ts b/lib/getPosts.ts index c363c67..814f6d8 100644 --- a/lib/getPosts.ts +++ b/lib/getPosts.ts @@ -1,5 +1,4 @@ -import { Post } from "./interfaces"; -import { parsePost } from "./parsePost"; +import Post from "./Post"; import { readDir } from "./utils"; function getPosts(path: string): Array<Post> { @@ -14,7 +13,7 @@ function getPosts(path: string): Array<Post> { files.forEach((file: string) => { const fsRoute = `${path}/${year}/${month}/${day}/${file}`; try { - const post = parsePost(fsRoute); + const post = new Post(fsRoute); routesArray.push(post); } catch (err) { console.log(err); diff --git a/lib/index.ts b/lib/index.ts index f9647bc..4bf4dd3 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,7 +1,7 @@ import { getPost as apiGetPost } from "./getPost"; import { getPosts as apiGetPosts } from "./getPosts"; import { generateApi as apiGenerateApi } from "./generateApi" -import { Post } from "./interfaces"; +import Post from "./Post"; export default class Kronikarz { postPath: string; diff --git a/lib/interfaces.ts b/lib/interfaces.ts index 1d598c6..974765f 100644 --- a/lib/interfaces.ts +++ b/lib/interfaces.ts @@ -1,24 +1,33 @@ -interface Date { +export interface Date { year: string; month: string; day: string; } -interface Meta { - [key: string]: string; +/*export interface Meta { + [key: string]: object; +}*/ + +export interface Meta { + title: string; + author: string; + additionalMeta: object; } -export interface PostContent { - html: string; - markdown: string; - description: string; - meta: Meta; +export interface FrontMatterObject { + body: string; + attributes: Meta; } -export interface Post { - date: Date; +export interface PostApiListEntry { + date: string; + author: string; title: string; - content: PostContent; - filePath: string; - route: string; + path: string; + description: string; + meta: object; +} + +export interface PostApiEntry extends PostApiListEntry { + content: string; } diff --git a/lib/parsePost.ts b/lib/parsePost.ts deleted file mode 100644 index 2f5f2b9..0000000 --- a/lib/parsePost.ts +++ /dev/null @@ -1,46 +0,0 @@ -import * as fs from "fs"; -import { JSDOM } from "jsdom"; -import { Post, PostContent } from "./interfaces"; - -const frontmatter = require("front-matter"); -const md = require("markdown-it")(); - -function getDescription(html: string): string { - const { document } = new JSDOM(`<div>${html}</div>`).window; - const elements = document.getElementsByTagName("p"); - - const description = elements[1].textContent; - - return description || ""; -} - -function getPostContent(fileContent: string): PostContent { - const post = frontmatter(fileContent); - - const markdown = post.body; - const html = `<div>${md.render(markdown)}</div>`; - const description = getDescription(html); - - return { - html, - markdown, - description, - meta: post.attributes - }; -} - -export function parsePost(filePath: string): Post { - let [year, month, day, title] = filePath.split("/").splice(-4, 4); - title = title.substr(0, title.lastIndexOf(".")); - const date = { year, month, day }; - const fileContent = fs.readFileSync(filePath, "utf-8"); - const content = getPostContent(fileContent); - - return { - date, - title, - content, - filePath, - route: `/kronika/${year}/${month}/${day}/${title}` - }; -} diff --git a/lib/utils.ts b/lib/utils.ts index 23a3947..f75c0e4 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,4 +1,6 @@ import * as fs from "fs"; +import { Date } from './interfaces'; +import Post from './Post' export function readDir(path: string): Array<string> { if (fs.existsSync(path)) { @@ -7,3 +9,15 @@ export function readDir(path: string): Array<string> { throw `Path "${path}" doesn't exist`; } } + +export function sortPosts(posts: Array<Post>): Array<Post> { + return posts; +} + +export function dateToString({ year, month, day }: Date): string { + return `${year}-${month}-${day}` +} + +export function dateToPath({ year, month, day }: Date): string { + return `${year}/${month}/${day}` +} |