This commit is contained in:
Pacharapol Withayasakpunt committed 2019-12-25 00:11:26 +07:00
1 parent 36338ed0d7
commit 7fe8f5d154
96 files changed
+21326

No files matched your search

+173
View File
@@ -0,0 +1,173 @@
import path from 'path'
import matter from 'gray-matter'
import moment from 'moment'
import fs from 'fs-extra'
// @ts-ignore
import shortHash from 'short-hash'
import stringify from 'fast-json-stable-stringify'
import glob from 'fast-glob'
export type DataType = 'posts' | 'slides'
export interface IData {
teaser?: string
full: string
}
export default class ApiBuilder {
_hash: Record<DataType, Record<string, string>> = {
posts: {},
slides: {},
}
_tag: Record<DataType, Record<string, number>> = {
posts: {},
slides: {},
}
_header: Record<DataType, any[]> = {
posts: [],
slides: [],
}
_data: Record<DataType, Record<string, IData>> = {
posts: {},
slides: {},
}
loadFile (dirName: DataType, fileName: string) {
const ROOT = path.join('data', dirName)
const raw = fs.readFileSync(path.join(ROOT, fileName), 'utf8')
const m = matter(raw)
const p = path.parse(fileName)
m.data = {
...m.data,
name: p.name,
path: fileName,
}
if (m.data.date) {
let mm = moment(m.data.date)
mm = mm.add(-mm.utcOffset(), 'minute')
Object.assign(m.data, {
date: mm.toISOString(),
y: mm.format('YYYY'),
mo: mm.format('MM'),
})
}
let data: IData = {
full: m.content,
}
if (dirName === 'posts') {
const [teaser, remaining] = m.content.split(/\n===\n(.+)/s)
data = {
teaser,
full: `${teaser}\n${remaining || ''}`,
}
}
return {
header: m.data,
data,
}
}
loadDir (dirName: DataType) {
const ROOT = path.join('data', dirName)
const now = new Date().toISOString()
glob.sync('**/*.md', {
cwd: ROOT,
}).map((f) => {
const { header, data } = this.loadFile(dirName, f)
this._hash[dirName][f] = shortHash(data.full)
if (dirName === 'posts' && header.date && header.date < now && header.path.startsWith('blog/')) {
if (Array.isArray(header.tag)) {
for (const t of header.tag) {
this._tag[dirName][t] = (this._tag[dirName][t] || 0) + 1
}
}
}
this._header[dirName].push(header)
this._data[dirName][f] = data
})
this._header[dirName] = this._header[dirName].sort((h1, h2) => {
if (typeof h1.date === 'string' && typeof h2.date === 'string') {
return -h1.date.localeCompare(h2.date)
}
return 0
})
this._hash[dirName]._header = shortHash(stringify(this._header[dirName]))
return {
header: this._header[dirName],
hash: this._hash[dirName]._header,
tag: this._tag[dirName],
}
}
emit () {
const dst = 'static/build'
this.loadDir('posts')
this.loadDir('slides')
/**
* Emit hash
*/
console.log('Emitting hash')
fs.ensureDirSync(`${dst}/hash`)
fs.writeFileSync(`${dst}/hash/posts.json`, JSON.stringify(this._hash.posts))
fs.writeFileSync(`${dst}/hash/slides.json`, JSON.stringify(this._hash.slides))
/**
* Emit header
*/
console.log('Emitting header')
fs.ensureDirSync(`${dst}/header`)
fs.writeFileSync(`${dst}/header/posts.json`, JSON.stringify(this._header.posts))
fs.writeFileSync(`${dst}/header/slides.json`, JSON.stringify(this._header.slides))
/**
* Emit tag
*/
console.log('Emitting tag')
fs.ensureDirSync(`${dst}/tag`)
fs.writeFileSync(`${dst}/tag/posts.json`, JSON.stringify(this._tag.posts))
/**
* Emit posts
*/
console.log('Emitting blog entries')
for (const [p, data] of Object.entries(this._data.posts)) {
fs.ensureFileSync(`${dst}/teaser/${p}`)
fs.ensureFileSync(`${dst}/full/${p}`)
fs.writeFileSync(`${dst}/teaser/${p}`, data.teaser)
fs.writeFileSync(`${dst}/full/${p}`, data.full)
}
/**
* Emit slides
*/
console.log('Emitting slides')
for (const [p, data] of Object.entries(this._data.slides)) {
fs.ensureFileSync(`${dst}/slides/${p}`)
fs.writeFileSync(`${dst}/slides/${p}`, data.full)
}
}
}
if (typeof require !== 'undefined' && require.main === module) {
new ApiBuilder().emit()
}