add blog
This commit is contained in:
1 parent
36338ed0d7
commit
7fe8f5d154
96 files changed
+21326
No files matched your search
@@ -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()
|
||||
}
|
||||
Reference in new issue
Block a user