plan for ssg

This commit is contained in:
polv committed 2020-12-17 18:35:27 +07:00
1 parent a8867be72c
commit fb69b2710f
73 files changed
+921 -718

No files matched your search

+2 -2
View File
@@ -10,10 +10,10 @@ dotenv.config()
export const CONTENT_PATH = path.resolve(
process.env.CONTENT_PATH ||
(fs.existsSync('../../_posts') ? '../..' : 'content')
(fs.existsSync('../../_post') ? '../..' : 'content')
)
export const srcPath = (
root: '_posts' | '_media' | typeof THEME_FILENAME,
root: '_post' | '_media' | typeof THEME_FILENAME,
...ps: string[]
): string => path.join(CONTENT_PATH, root, ...ps)
+19 -13
View File
@@ -3,10 +3,9 @@ import crypto from 'crypto'
import scopeCss from '@patarapolw/scope-css'
import cheerio from 'cheerio'
import ejs from 'ejs'
import jieba from 'nodejieba'
import showdown from 'showdown'
export class MakeHTML {
export class MakeHtml {
$ = cheerio.load('')
mdConverter = new showdown.Converter({
@@ -18,7 +17,7 @@ export class MakeHTML {
tables: true,
tasklists: true,
// simpleLineBreaks: true,
openLinksInNewWindow: true,
// openLinksInNewWindow: true,
backslashEscapesHTMLTags: true,
emoji: true,
underline: true,
@@ -72,9 +71,8 @@ export class MakeHTML {
async parse(
filename: string
): Promise<{
$: cheerio.Cheerio
html(): string
clean(): string
html: string
text: string
}> {
const id =
'md-' +
@@ -87,6 +85,7 @@ export class MakeHTML {
const $div = this.$(`<div id="${id}">`)
$div.html(await this.getHTML(filename))
$div.find('style').each((_, el) => {
const $el = this.$(el)
const html = $el.html() || ''
@@ -95,14 +94,21 @@ export class MakeHTML {
}
})
$div.find('a').each((_, el) => {
const $el = this.$(el)
const href = $el.attr('href') || ''
if (/^https?:\/\//.test(href)) {
$el.attr({
rel: 'noopener',
target: '_blank',
})
}
})
return {
$: $div,
html: () => {
return this.$('<div>').append($div).html() || ''
},
clean: () => {
return jieba.cutForSearch($div.text() || '').join(' ')
},
html: this.$('<div>').append($div).html() || '',
text: $div.text(),
}
}
+86
View File
@@ -0,0 +1,86 @@
import fg from 'fast-glob'
import fs from 'fs-extra'
import yaml from 'js-yaml'
import lunr from 'lunr'
import jieba from 'nodejieba'
import rimraf from 'rimraf'
import { IPost, db, dbPost, initDatabase, zMatter, zPost } from '../server/db'
import { buildPath, dstMediaPath } from '../server/dir'
import { THEME_FILENAME } from '../server/theme'
import { srcPath } from './dir'
import { MakeHtml } from './make-html'
async function main() {
rimraf.sync(dstMediaPath())
rimraf.sync(buildPath())
await fs.copy(srcPath('_media'), dstMediaPath()).catch((e) => {
// eslint-disable-next-line no-console
console.error(e)
})
await fs.ensureDir(buildPath())
await fs.copyFile(srcPath(THEME_FILENAME), buildPath(THEME_FILENAME))
const files = await fg('**/*.md', {
cwd: srcPath('_post'),
})
const makeHtml = new MakeHtml()
const rawJson: IPost[] = []
await initDatabase()
await Promise.all(
files.map(async (f) => {
const header = zMatter.parse(
yaml.safeLoad(
fs.readFileSync(srcPath('_post', f), 'utf-8').split(/\n---\n/)[0]
)
)
const { html, text } = await makeHtml.parse(srcPath('_post', f))
const p: IPost = {
...header,
date: header.date ? header.date.getTime() : undefined,
createdAt: header.createdAt ? header.createdAt.getTime() : undefined,
updatedAt: header.updatedAt ? header.updatedAt.getTime() : undefined,
path: f.replace(/\.mdx?$/, ''),
excerptHtml: html.split(/<!-- excerpt(?:_separator)? -->/)[0],
contentHtml: html,
content: text,
}
dbPost.insert(zPost.parse(p))
rawJson.push({
...p,
content: jieba.cutForSearch(p.content).join(' '),
})
})
)
db.save()
fs.writeFileSync(
buildPath('idx.json'),
JSON.stringify(
lunr(function () {
this.ref('path')
this.field('title', { boost: 5 })
this.field('tag', { boost: 5 })
this.field('category', { boost: 5 })
this.field('content')
rawJson.map((doc) => {
return this.add(doc)
})
})
)
)
}
if (require.main === module) {
main()
}
-57
View File
@@ -1,57 +0,0 @@
import fg from 'fast-glob'
import fs from 'fs-extra'
import yaml from 'js-yaml'
import rimraf from 'rimraf'
import { Database, IMatter } from '../server/db'
import { builtPath, dstMediaPath } from '../server/dir'
import { THEME_FILENAME } from '../server/theme'
import { srcPath } from './dir'
import { MakeHTML } from './make-html'
async function main() {
rimraf.sync(dstMediaPath())
rimraf.sync(builtPath())
await fs.copy(srcPath('_media'), dstMediaPath())
await fs.ensureDir(builtPath())
await fs.copyFile(srcPath(THEME_FILENAME), builtPath(THEME_FILENAME))
const db = new Database()
db.init()
const files = await fg('**/*.md', {
cwd: srcPath('_posts'),
})
const makeHtml = new MakeHTML()
await Promise.all(
files.map(async (f) => {
const path = f.replace(/\.md$/, '')
const markdown = fs.readFileSync(srcPath('_posts', f), 'utf8')
const [h] = markdown.substr(4).split(/---\n(.*)$/s)
const header = yaml.safeLoad(h) as IMatter
const r = await makeHtml.parse(srcPath('_posts', f))
const contentHtml = r.html()
const excerptHtml = contentHtml.split(
/<!-- excerpt(?:_separator)? -->/
)[0]
db.insert({
...header,
path,
content: r.clean(),
excerptHtml,
contentHtml,
})
})
)
}
if (require.main === module) {
main()
}