The bot docs converter points upstream Discord invites at Hanzo's server

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-09-25 23:58:52 -07:00
co-authored by Hanzo Dev
parent 3559d21c74
commit fb991d3403
2 changed files with 37 additions and 3 deletions
+19 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { mdxSafe } from './convert-docs';
import { mdxSafe, relink } from './convert-docs';
// Markdown the bot repo writes on purpose, which MDX reads as JSX and refuses:
// a page that does not parse is not rendered at all.
@@ -40,3 +40,21 @@ describe('markdown made MDX-safe', () => {
expect(mdxSafe(guide)).toBe(guide);
});
});
// The upstream docs invite a reader into the upstream community; ours invite
// them into Hanzo's. Only the invite moves: a name written on purpose stays.
describe('links to the community', () => {
it("point an upstream Discord invite at Hanzo's server", () => {
expect(relink('Ask in Discord: [https://discord.gg/clawd](https://discord.gg/clawd)')).toBe(
'Ask in Discord: [https://discord.gg/XthHQQj](https://discord.gg/XthHQQj)',
);
expect(relink('[#showcase](https://discord.gg/clawd) or channels.discord.gg/bot')).toBe(
'[#showcase](https://discord.gg/XthHQQj) or discord.gg/XthHQQj',
);
});
it('leave every other name as written', () => {
const doc = 'Run `hanzo bot migrate openclaw`; the `clawdbot` shim reads ~/.openclaw.';
expect(relink(doc)).toBe(doc);
});
});
+18 -2
View File
@@ -15,6 +15,11 @@
* on purpose — the migration guide's `hanzo bot migrate openclaw` and
* `~/.openclaw`, the `clawdbot` compatibility shim in install/updating — and the
* map turned each into a command, a path or a fact that does not exist.
*
* Links are the exception, because a link is an address and not a claim: an
* invite to the upstream community server sends a Hanzo Bot reader somewhere
* that is not ours. `relink` points each at Hanzo's server and touches nothing
* else.
*/
import { readdir, readFile, writeFile, mkdir } from 'fs/promises';
@@ -38,6 +43,17 @@ const SKIP_FILES = new Set([
'Gemfile', 'Gemfile.lock', '_layouts', '_includes',
]);
/** The community invites the upstream docs still carry, and Hanzo's server. */
const INVITES: [RegExp, string][] = [
[/\bdiscord\.gg\/(?:clawd|hanzo)\b/g, 'discord.gg/XthHQQj'],
[/\bchannels\.discord\.gg\/bot\b/g, 'discord.gg/XthHQQj'],
];
/** A doc with every upstream community invite pointed at Hanzo's server. */
export function relink(doc: string): string {
return INVITES.reduce((d, [from, to]) => d.replace(from, to), doc);
}
// Category display names and ordering
const CATEGORY_META: Record<string, { title: string; pages?: string[] }> = {
install: {
@@ -252,7 +268,7 @@ async function convertFile(srcPath: string) {
const destPath = join(DEST, mapped);
await mkdir(dirname(destPath), { recursive: true });
let content = await readFile(srcPath, 'utf-8');
content = mdxSafe(convertFrontmatter(content));
content = mdxSafe(convertFrontmatter(relink(content)));
await writeFile(destPath, content, 'utf-8');
console.log(` ${relPath} → ${mapped}`);
return;
@@ -265,7 +281,7 @@ async function convertFile(srcPath: string) {
await mkdir(dirname(destPath), { recursive: true });
let content = await readFile(srcPath, 'utf-8');
content = mdxSafe(convertFrontmatter(content));
content = mdxSafe(convertFrontmatter(relink(content)));
await writeFile(destPath, content, 'utf-8');
console.log(` ${relPath} → ${destRel}`);