tinymist/scripts/link-docs.mjs
2025-06-22 15:30:24 +08:00

146 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { resolve, basename, relative } from "path";
import * as fs from "fs";
import { execSync } from "child_process";
const root = resolve(import.meta.dirname, "..");
const dry = process.argv.includes("--dry");
const bytes2utf8 = new TextDecoder();
/**
* Base64 to UTF-8
* @param encoded Base64 encoded string
* @returns UTF-8 string
*/
export const base64Decode = (encoded) =>
bytes2utf8.decode(Uint8Array.from(atob(encoded), (m) => m.charCodeAt(0)));
const yarn = (cmd, stdio = "inherit") => {
const script = `yarn run ${cmd}`;
if (dry) {
return script;
}
return execSync(script, { stdio });
};
const typlite = (input, output) => {
const assets_flag = dry
? ""
: `--assets-path ${relative(root, resolve(output, "../assets/images/", basename(input.slice(0, -4))))}`;
// return stdout
const res = yarn(`--silent typlite ${assets_flag} --root ${root} ${input} -`, "pipe");
return res.toString();
};
const convert = async (inp, out, opts) => {
const input = resolve(root, inp);
const output = resolve(root, out);
const { before } = opts || {};
const res = typlite(input, output).trim();
if (dry) {
console.log(res);
return;
}
const outputContent = `<!-- This file is generated by scripts/link-docs.mjs from ${inp}. Do not edit manually. -->\n${before || ""}${res}\n`;
await fs.promises.writeFile(output, outputContent);
};
// todo: generate me using typlite.
const maintainerMd = async () => {
const maintainers = JSON.parse(yarn(`--silent maintainers --input=action=maintainers`, "pipe"));
const features = JSON.parse(yarn(`--silent maintainers --input=action=features`, "pipe"));
const output = [];
output.push("<!-- This file is generated by scripts/link-docs.mjs. Do not edit manually. -->\n");
output.push("# Tinymist Maintainers\n\n");
output.push(
"Tinymist [ˈtaɪni mɪst] is an integrated language service for [Typst](https://typst.app/) [taɪpst].",
);
output.push(
"\nThis page is generated from [./MAINTAINERS.typ](./MAINTAINERS.typ) and renders information of [maintainers](#maintainers) and [features.](#features)\n",
);
output.push("## Maintainers\n");
const italicIt = (it) => `*${it}*`;
const featureLink = (it) => {
const feature = features.find((f) => f.name === it);
if (feature) {
return `[${it}](#${it.replace(/\s+/g, "-").toLowerCase()})`;
}
return it;
};
const fsPath = (it) => {
if (!fs.existsSync(it)) {
throw new Error(`Path ${it} does not exist!`);
}
return `[\`${it}\`](./${it})`;
};
for (const maintainer of maintainers) {
output.push(`- [**${maintainer["name"]}**](https://github.com/${maintainer["github-name"]})`);
output.push(` - Email: ${maintainer.email}`);
if (maintainer.maintains.length > 0) {
const rendered = maintainer.maintains.map(featureLink).map(italicIt);
if (rendered.length > 1) {
const last = rendered.pop();
output.push(` - Maintains: ${rendered.join(", ")}, and ${last}`);
} else {
output.push(` - Maintains: ${rendered.join(", ")}`);
}
}
output.push("");
}
output.push("## Features\n");
for (const feature of features) {
output.push(`### ${feature.name}`);
output.push(`${feature.description}`);
output.push(`- Scope: ${feature.scope.map(fsPath).join(", ")}`);
}
const outPath = resolve(root, "MAINTAINERS.md");
const outputContent = output.join("\n");
if (dry) {
console.log(content);
return;
}
await fs.promises.writeFile(outPath, outputContent);
};
const main = async () => {
await Promise.all([
convert("docs/tinymist/introduction.typ", "README.md", {
before: "# Tinymist\n\n",
}),
convert("docs/tinymist/release-instruction.typ", "docs/release-instruction.md", {
before: "# Release Instructions\n\n",
}),
convert("docs/tinymist/frontend/emacs.typ", "editors/emacs/README.md", {
before: "# Tinymist Emacs Support for Typst\n\n",
}),
convert("docs/tinymist/frontend/helix.typ", "editors/helix/README.md", {
before: "# Tinymist Helix Support for Typst\n\n",
}),
convert("docs/tinymist/frontend/neovim.typ", "editors/neovim/README.md", {
before: "# Tinymist Neovim Support for Typst\n\n",
}),
convert("docs/tinymist/frontend/sublime-text.typ", "editors/sublime-text/README.md", {
before: "# Tinymist Sublime Support for Typst\n\n",
}),
convert("docs/tinymist/frontend/vscode.typ", "editors/vscode/README.md", {
before: "# Tinymist Typst VS Code Extension\n\n",
}),
convert("docs/tinymist/frontend/zed.typ", "editors/zed/README.md", {
before: "# Tinymist Zed Support for Typst\n\n",
}),
maintainerMd(),
]);
};
main().catch(console.error);