Files
zhdiary/packages/nuxt/scripts/make-html.ts
T
2020-12-16 01:12:41 +07:00

99 lines
2.2 KiB
TypeScript

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 {
$ = cheerio.load('')
mdConverter = new showdown.Converter({
noHeaderId: true,
parseImgDimensions: true,
simplifiedAutoLink: true,
// literalMidWordUnderscores: true,
strikethrough: true,
tables: true,
tasklists: true,
// simpleLineBreaks: true,
openLinksInNewWindow: true,
backslashEscapesHTMLTags: true,
emoji: true,
underline: true,
metadata: true,
})
constructor() {
/**
* ! For some reasons default underscore italic fails to render...
*/
this.mdConverter.addExtension(
{
type: 'lang',
regex: /([^\\])_{1}(.*?[^\\])_{1}/g,
replace: '$1<i>$2</i>',
},
'underscore-italic'
)
}
async parse(
filename: string
): Promise<{
$: cheerio.Cheerio
html(): string
clean(): string
}> {
const id =
'md-' +
crypto
.createHash('sha256')
.update(filename)
.digest()
.toString('hex')
.substr(8)
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() || ''
if (html.trim()) {
$el.html(scopeCss(html, `#${id}`))
}
})
return {
$: $div,
html() {
return $div.html() || ''
},
clean() {
return jieba.cutForSearch($div.text() || '').join(' ')
},
}
}
private async getHTML(filename: string) {
return this.mdConverter.makeHtml(
await ejs.renderFile(filename, {
youtube: (id: string) =>
this.$('<div>')
.html(
/* html */ `
<div style="padding-top:56.25%">
<iframe src="https://www.youtube.com/embed/${id}"
frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
style="width:100%; height:100%"></iframe>
</div>`
)
.html(),
})
)
}
}