Skip to content

Commit f6803da

Browse files
committed
docs: polish docs site code blocks
1 parent 0132c82 commit f6803da

2 files changed

Lines changed: 106 additions & 12 deletions

File tree

scripts/build-docs-site.mjs

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const cname = readCname();
1919
const siteBase = cname ? `https://${cname}` : "";
2020

2121
const productName = "acpx";
22-
const productTagline = "Talk to coding agents from the command line";
22+
const productTagline = "Talk to agents from the command line";
2323
const productDescription =
2424
"Headless CLI client for the Agent Client Protocol — persistent multi-turn sessions, queue-aware prompts, structured output, and multi-step flows for Codex, Claude, Pi, OpenClaw, and any ACP-capable agent.";
2525
const installCommand = "npm install -g acpx";
@@ -33,6 +33,51 @@ const sections = [
3333
["Reference", ["CLI.md", "exit-codes.md", "VISION.md"]],
3434
];
3535

36+
const HIGHLIGHT_ALIASES = {
37+
sh: "bash",
38+
shell: "bash",
39+
zsh: "bash",
40+
console: "bash",
41+
js: "ts",
42+
javascript: "ts",
43+
typescript: "ts",
44+
jsonc: "json",
45+
};
46+
47+
const HIGHLIGHT_RULES = {
48+
bash: [
49+
[/#[^\n]*/g, "com"],
50+
[/'(?:[^'\\]|\\.)*'/g, "str"],
51+
[/"(?:[^"\\]|\\.)*"/g, "str"],
52+
[/`[^`]*`/g, "str"],
53+
[/\$\{[^}]+\}|\$\w+/g, "var"],
54+
[/\B-{1,2}[A-Za-z][\w-]*/g, "flag"],
55+
[/\b\d+\b/g, "num"],
56+
[/[|&;<>]+/g, "op"],
57+
],
58+
json: [
59+
[/"(?:[^"\\]|\\.)*"(?=\s*:)/g, "prop"],
60+
[/"(?:[^"\\]|\\.)*"/g, "str"],
61+
[/-?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/g, "num"],
62+
[/\b(?:true|false|null)\b/g, "lit"],
63+
[/[{}[\],:]/g, "op"],
64+
],
65+
ts: [
66+
[/\/\/[^\n]*/g, "com"],
67+
[/\/\*[\s\S]*?\*\//g, "com"],
68+
[/'(?:[^'\\]|\\.)*'/g, "str"],
69+
[/"(?:[^"\\]|\\.)*"/g, "str"],
70+
[/`(?:[^`\\]|\\.)*`/g, "str"],
71+
[
72+
/\b(?:const|let|var|function|return|import|export|from|default|async|await|if|else|for|while|switch|case|break|continue|new|class|interface|type|extends|implements|public|private|protected|readonly|as|in|of|typeof|instanceof|this|void|never)\b/g,
73+
"kw",
74+
],
75+
[/\b(?:true|false|null|undefined)\b/g, "lit"],
76+
[/-?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/g, "num"],
77+
[/\b[A-Z][A-Za-z0-9_]*\b/g, "typ"],
78+
],
79+
};
80+
3681
// Internal architecture notes and stray dev docs are not part of the user-facing site.
3782
// They remain in the repo and are reachable from GitHub.
3883
const buildExcludes = [
@@ -261,7 +306,7 @@ function markdownToHtml(markdown, currentRel) {
261306
flushBlockquote();
262307
if (fence) {
263308
html.push(
264-
`<pre><code class="language-${escapeAttr(fence.lang)}">${escapeHtml(fence.lines.join("\n"))}</code></pre>`,
309+
`<pre><code class="language-${escapeAttr(fence.lang)}">${highlight(fence.lines.join("\n"), fence.lang)}</code></pre>`,
265310
);
266311
fence = null;
267312
} else {
@@ -463,7 +508,7 @@ function homeHero(page) {
463508
];
464509
return `<header class="home-hero">
465510
<p class="eyebrow"><span class="dot" aria-hidden="true"></span> Agent Client Protocol · Headless CLI</p>
466-
<h1>Talk to coding agents <span class="accent">from the command line</span></h1>
511+
<h1>Talk to agents <span class="accent">from the command line</span></h1>
467512
<p class="lede">${escapeHtml(description)}</p>
468513
<div class="home-cta">
469514
<a class="btn btn-primary" href="${quickstartRel}">Quickstart</a>
@@ -656,6 +701,37 @@ function escapeAttr(value) {
656701
return escapeHtml(value);
657702
}
658703

704+
function highlight(code, lang) {
705+
const resolved = HIGHLIGHT_ALIASES[lang] || lang;
706+
const rules = HIGHLIGHT_RULES[resolved];
707+
if (!rules) {
708+
return escapeHtml(code);
709+
}
710+
let out = "";
711+
let i = 0;
712+
while (i < code.length) {
713+
let bestKind = null;
714+
let bestText = null;
715+
for (const [re, kind] of rules) {
716+
re.lastIndex = i;
717+
const m = re.exec(code);
718+
if (m && m.index === i) {
719+
bestKind = kind;
720+
bestText = m[0];
721+
break;
722+
}
723+
}
724+
if (bestText !== null) {
725+
out += `<span class="hl-${bestKind}">${escapeHtml(bestText)}</span>`;
726+
i += bestText.length;
727+
} else {
728+
out += escapeHtml(code[i]);
729+
i += 1;
730+
}
731+
}
732+
return out;
733+
}
734+
659735
function validateLinks(outputDir) {
660736
const failures = [];
661737
const placeholderHrefs = /^(url|path|file|dir|name)$/i;

scripts/docs-site-assets.mjs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,13 @@ a:hover{text-decoration:underline;text-underline-offset:.2em}
5656
.sidebar-head{display:flex;align-items:center;gap:10px;margin-bottom:24px}
5757
.brand{display:flex;align-items:center;gap:11px;color:var(--ink);text-decoration:none;flex:1;min-width:0}
5858
.brand:hover{text-decoration:none}
59-
.brand .mark{flex:0 0 30px;width:30px;height:30px;border-radius:8px;background:var(--ink);position:relative;overflow:hidden;display:grid;place-items:center;color:#7dd3fc;font:700 14px/1 "JetBrains Mono","SF Mono",ui-monospace,monospace;letter-spacing:0}
60-
.brand .mark::before{content:"";position:absolute;inset:0;background:linear-gradient(135deg,rgba(14,165,233,.35),transparent 55%,rgba(168,85,247,.35));pointer-events:none}
61-
.brand .mark span{position:relative;z-index:1}
59+
.brand .mark{flex:0 0 34px;width:34px;height:34px;border-radius:9px;background:var(--ink);position:relative;overflow:hidden;display:grid;place-items:center;box-shadow:0 1px 0 rgba(255,255,255,.05) inset,0 8px 24px -10px rgba(14,165,233,.45)}
60+
.brand .mark::before{content:"";position:absolute;inset:0;background:radial-gradient(120% 120% at 0% 0%,rgba(14,165,233,.55),transparent 55%),radial-gradient(120% 120% at 100% 100%,rgba(168,85,247,.55),transparent 55%);pointer-events:none}
61+
.brand .mark::after{content:"";position:absolute;inset:1px;border-radius:8px;border:1px solid rgba(255,255,255,.08);pointer-events:none}
62+
.brand .mark svg{position:relative;z-index:1;width:20px;height:20px;display:block}
63+
.brand .mark .cursor{transform-origin:center;animation:acpx-blink 1.2s steps(2,jump-none) infinite}
64+
@keyframes acpx-blink{0%,49%{opacity:1}50%,100%{opacity:.25}}
65+
@media (prefers-reduced-motion: reduce){.brand .mark .cursor{animation:none}}
6266
.brand strong{display:block;font-size:1.05rem;line-height:1.1;font-weight:600;letter-spacing:0;color:var(--ink)}
6367
.brand small{display:block;color:var(--muted);font-size:.74rem;margin-top:3px;font-weight:400}
6468
.theme-toggle{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:34px;height:34px;border-radius:8px;border:1px solid var(--line);background:var(--paper);color:var(--muted);cursor:pointer;padding:0;transition:border-color .15s,color .15s,background-color .15s,transform .12s}
@@ -130,6 +134,16 @@ body:not(.home) .doc>h1:first-child{display:none}
130134
.doc pre::-webkit-scrollbar{height:8px;width:8px}
131135
.doc pre::-webkit-scrollbar-thumb{background:#334155;border-radius:8px}
132136
.doc pre code{display:block;background:transparent;border:0;color:inherit;padding:0;font-size:1em;white-space:pre}
137+
.doc pre .hl-com{color:#7a8597;font-style:italic}
138+
.doc pre .hl-str{color:#86efac}
139+
.doc pre .hl-num{color:#fbbf24}
140+
.doc pre .hl-kw{color:#c4b5fd;font-weight:500}
141+
.doc pre .hl-lit{color:#f0abfc}
142+
.doc pre .hl-flag{color:#7dd3fc}
143+
.doc pre .hl-var{color:#fca5a5}
144+
.doc pre .hl-prop{color:#7dd3fc}
145+
.doc pre .hl-op{color:#94a3b8}
146+
.doc pre .hl-typ{color:#fde68a}
133147
.doc pre .copy{position:absolute;top:8px;right:8px;background:rgba(255,255,255,.06);color:var(--code-fg);border:1px solid rgba(255,255,255,.16);border-radius:6px;padding:3px 9px;font:500 .7rem/1 "Inter",sans-serif;cursor:pointer;opacity:0;transition:opacity .15s,background .15s,border-color .15s}
134148
.doc pre:hover .copy,.doc pre .copy:focus{opacity:1}
135149
.doc pre .copy:hover{background:rgba(255,255,255,.12)}
@@ -259,20 +273,24 @@ export function themeToggleHtml() {
259273
}
260274

261275
export function brandMarkHtml() {
262-
return `<span class="mark" aria-hidden="true"><span>&gt;_</span></span>`;
276+
return `<span class="mark" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 7.5 L11 12 L5 16.5" stroke="#7dd3fc" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/><rect class="cursor" x="13" y="14.6" width="7" height="2.4" rx="1.2" fill="#c4b5fd"/></svg></span>`;
263277
}
264278

265279
export function faviconSvg() {
266280
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="acpx">
267281
<defs>
268-
<linearGradient id="g" x1="0" y1="0" x2="64" y2="64" gradientUnits="userSpaceOnUse">
282+
<linearGradient id="bg" x1="0" y1="0" x2="64" y2="64" gradientUnits="userSpaceOnUse">
283+
<stop offset="0" stop-color="#0b0e14"/>
284+
<stop offset="1" stop-color="#1a2230"/>
285+
</linearGradient>
286+
<linearGradient id="ring" x1="0" y1="0" x2="64" y2="64" gradientUnits="userSpaceOnUse">
269287
<stop offset="0" stop-color="#0ea5e9"/>
270288
<stop offset="1" stop-color="#a855f7"/>
271289
</linearGradient>
272290
</defs>
273-
<rect width="64" height="64" rx="14" fill="#0b0e14"/>
274-
<rect x="2" y="2" width="60" height="60" rx="13" fill="none" stroke="url(#g)" stroke-width="1.5" opacity="0.45"/>
275-
<path d="M16 22 L24 32 L16 42" fill="none" stroke="#7dd3fc" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
276-
<rect x="28" y="38" width="22" height="3.6" rx="1.8" fill="#a855f7"/>
291+
<rect width="64" height="64" rx="14" fill="url(#bg)"/>
292+
<rect x="1.5" y="1.5" width="61" height="61" rx="13" fill="none" stroke="url(#ring)" stroke-width="2" opacity="0.7"/>
293+
<path d="M14 18 L28 32 L14 46" fill="none" stroke="#7dd3fc" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
294+
<rect x="32" y="40" width="20" height="6" rx="3" fill="#c4b5fd"/>
277295
</svg>`;
278296
}

0 commit comments

Comments
 (0)