docs_vue2/one/build/changelog.js
2021-09-25 23:32:02 +08:00

136 lines
3.1 KiB
JavaScript

import { readFileSync } from 'fs'
import cheerio from 'cheerio'
import { render } from './page'
const VERSION_RE = /^(\d+\.\d+\.\d+(?:-[a-z]+(?:\.\d+)?)?)(?:\s+"([^"]+)")?$/i
function getVersion (title = '') {
const [, version, codeName] = title.trim().match(VERSION_RE) || []
if (!version) {
return null
}
return [version, codeName]
}
const TYPE_MAP = {
'โš ๏ธ': 'breaking',
'๐Ÿ’ก': 'feature',
'๐Ÿž': 'bugfix',
'๐Ÿงช': 'experimental'
}
const TYPE_KEYS = Object.keys(TYPE_MAP)
function getChangeType (title) {
const t = title.trim()
const key = TYPE_KEYS.find(key => t.includes(key))
if (!key) {
return null
}
return TYPE_MAP[key]
}
const TAG_RE = /#([^\s]+)$/
function getTags (comment) {
return comment
.trim()
.split(/\s+/)
.map(token => {
const [, tag] = token.match(TAG_RE) || []
return tag
})
.filter(tag => !!tag)
}
const EDIT_TYPE_RE = /^\[([+-^])\]/
const EDIT_TYPE_MAP = {
'-': 'remove',
'+': 'add',
'^': 'modify'
}
function getEditType (text) {
const [, sign] = text.match(EDIT_TYPE_RE) || []
if (sign) {
return EDIT_TYPE_MAP[sign]
}
return null
}
function trim (text) {
return text.trim().replace(/^\n+|\n+$/g, '')
}
function extract (html) {
const changelog = []
const $ = cheerio.load(html)
const $versions = $('h2')
$versions.each((_, el) => {
const $version = $(el)
const [version, codeName] = getVersion($(el).text()) || []
const versionLog = {
version,
codeName,
changeset: []
}
const $types = $version.nextUntil('h2', 'h3')
if ($types.length === 0) {
throw new Error(`No change type found for version ${version}`)
}
let type
$types.each((_, el) => {
const $type = $(el)
type = getChangeType($type.text())
const $changeset = $type.next('ul').children()
if ($changeset.length === 0) {
throw new Error(`No changeset found for version ${version}`)
}
$changeset.each((_, el) => {
const $change = $(el)
const tags = $change
.contents()
.toArray()
.map(el => {
if (el.type === 'comment') {
return getTags(el.data)
}
return []
})
.reduce((all, current) => all.concat(current), [])
$change.contents().filter((_, el) => el.type === 'comment').remove()
$change.find('*').contents().filter((_, el) => el.type === 'comment').remove()
const $container = trim($change.html()).startsWith('<p>') ? $change.children('p').first() : $change
let html = trim($container.html())
const editType = getEditType($container.text())
html = html.replace(EDIT_TYPE_RE, '')
$container.html(html)
versionLog.changeset.push({
type,
tags,
editType,
content: trim($change.html())
})
})
})
changelog.push(versionLog)
})
return changelog
}
export function getChangelogData () {
const changelogPath = require.resolve('veui/CHANGELOG.md')
const raw = readFileSync(changelogPath, 'utf8')
const { contents } = render(raw, changelogPath)
return extract(contents)
}