genUpdateInfoHtml.js
1 /** 2 * @file generates release notes for auto-updates 3 * 4 * Usage: 5 * 6 * 1. generate changelog during bump: 7 * node ./utils/genUpdateInfoHtml.js 8 * 9 * 2. generate changelog for a specific version: 10 * node ./utils/genUpdateInfoHtml.js -v 0.1.26 --range v0.1.25..v0.1.26 11 */ 12 13 // @ts-check 14 15 import fs from 'node:fs/promises'; 16 import path from 'node:path'; 17 import { fileURLToPath } from 'node:url'; 18 import { parseArgs } from 'node:util'; 19 import { codeToANSI } from '@shikijs/cli'; 20 import { runGitCliff } from 'git-cliff'; 21 import { toHtml } from 'hast-util-to-html'; 22 import { h } from 'hastscript'; 23 import { fromMarkdown } from 'mdast-util-from-markdown'; 24 import { toHast } from 'mdast-util-to-hast'; 25 import rehypeMinifyWhitespace from 'rehype-minify-whitespace'; 26 import { remove } from 'unist-util-remove'; 27 28 import pkg from '../package.json' with { type: 'json' }; 29 30 const ROOT_PATH = path.dirname(path.dirname(fileURLToPath(import.meta.url))); 31 const RELEASE_NOTES_DIR = path.join(ROOT_PATH, 'docs', 'release-notes'); 32 33 const { 34 values: { version, range }, 35 } = parseArgs({ 36 options: { 37 version: { 38 type: 'string', 39 short: 'v', 40 default: pkg.version, 41 }, 42 range: { 43 type: 'string', 44 }, 45 }, 46 }); 47 48 if (!version) { 49 throw new RangeError(`\`--version\` is required, got \`${JSON.stringify(version)}\``); 50 } 51 52 const newVersionMarkdown = ( 53 await runGitCliff(range ? [range] : ['--unreleased'], { 54 stdio: ['ignore', 'pipe', 'inherit'], 55 }) 56 ).stdout; 57 58 const mdTree = fromMarkdown(newVersionMarkdown); 59 60 remove(mdTree, [ 61 { type: 'heading', depth: 1 }, 62 { type: 'heading', depth: 2 }, 63 ]); 64 65 const htmlTree = h(null, [ 66 { type: 'doctype' }, 67 h('html', { lang: 'en' }, [ 68 h('head', [h('meta', { charSet: 'UTF-8' }), h('title', [`v${version} release notes`])]), 69 h('body', toHast(mdTree)), 70 ]), 71 ]); 72 73 rehypeMinifyWhitespace()(htmlTree); 74 75 const html = toHtml(htmlTree); 76 77 const htmlPath = path.join(RELEASE_NOTES_DIR, `${version}.html`); 78 79 console.log('Writing to', path.relative(ROOT_PATH, htmlPath)); 80 console.log(); 81 console.log(await codeToANSI(html, 'html', 'ayu-dark')); 82 83 await fs.mkdir(RELEASE_NOTES_DIR, { recursive: true }); 84 await fs.writeFile(htmlPath, `${html}\n`, { encoding: 'utf8' });