diff --git a/scripts/build-docs-site.mjs b/scripts/build-docs-site.mjs index 9672b84..face219 100644 --- a/scripts/build-docs-site.mjs +++ b/scripts/build-docs-site.mjs @@ -19,7 +19,7 @@ const cname = readCname(); const siteBase = cname ? `https://${cname}` : ""; const productName = "acpx"; -const productTagline = "Talk to coding agents from the command line"; +const productTagline = "Talk to agents from the command line"; const productDescription = "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."; const installCommand = "npm install -g acpx"; @@ -33,6 +33,51 @@ const sections = [ ["Reference", ["CLI.md", "exit-codes.md", "VISION.md"]], ]; +const HIGHLIGHT_ALIASES = { + sh: "bash", + shell: "bash", + zsh: "bash", + console: "bash", + js: "ts", + javascript: "ts", + typescript: "ts", + jsonc: "json", +}; + +const HIGHLIGHT_RULES = { + bash: [ + [/#[^\n]*/g, "com"], + [/'(?:[^'\\]|\\.)*'/g, "str"], + [/"(?:[^"\\]|\\.)*"/g, "str"], + [/`[^`]*`/g, "str"], + [/\$\{[^}]+\}|\$\w+/g, "var"], + [/\B-{1,2}[A-Za-z][\w-]*/g, "flag"], + [/\b\d+\b/g, "num"], + [/[|&;<>]+/g, "op"], + ], + json: [ + [/"(?:[^"\\]|\\.)*"(?=\s*:)/g, "prop"], + [/"(?:[^"\\]|\\.)*"/g, "str"], + [/-?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/g, "num"], + [/\b(?:true|false|null)\b/g, "lit"], + [/[{}[\],:]/g, "op"], + ], + ts: [ + [/\/\/[^\n]*/g, "com"], + [/\/\*[\s\S]*?\*\//g, "com"], + [/'(?:[^'\\]|\\.)*'/g, "str"], + [/"(?:[^"\\]|\\.)*"/g, "str"], + [/`(?:[^`\\]|\\.)*`/g, "str"], + [ + /\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, + "kw", + ], + [/\b(?:true|false|null|undefined)\b/g, "lit"], + [/-?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/g, "num"], + [/\b[A-Z][A-Za-z0-9_]*\b/g, "typ"], + ], +}; + // Internal architecture notes and stray dev docs are not part of the user-facing site. // They remain in the repo and are reachable from GitHub. const buildExcludes = [ @@ -261,7 +306,7 @@ function markdownToHtml(markdown, currentRel) { flushBlockquote(); if (fence) { html.push( - `
${escapeHtml(fence.lines.join("\n"))}
`, + `
${highlight(fence.lines.join("\n"), fence.lang)}
`, ); fence = null; } else { @@ -463,7 +508,7 @@ function homeHero(page) { ]; return `

Agent Client Protocol · Headless CLI

-

Talk to coding agents from the command line

+

Talk to agents from the command line

${escapeHtml(description)}

Quickstart @@ -656,6 +701,37 @@ function escapeAttr(value) { return escapeHtml(value); } +function highlight(code, lang) { + const resolved = HIGHLIGHT_ALIASES[lang] || lang; + const rules = HIGHLIGHT_RULES[resolved]; + if (!rules) { + return escapeHtml(code); + } + let out = ""; + let i = 0; + while (i < code.length) { + let bestKind = null; + let bestText = null; + for (const [re, kind] of rules) { + re.lastIndex = i; + const m = re.exec(code); + if (m && m.index === i) { + bestKind = kind; + bestText = m[0]; + break; + } + } + if (bestText !== null) { + out += `${escapeHtml(bestText)}`; + i += bestText.length; + } else { + out += escapeHtml(code[i]); + i += 1; + } + } + return out; +} + function validateLinks(outputDir) { const failures = []; const placeholderHrefs = /^(url|path|file|dir|name)$/i; diff --git a/scripts/docs-site-assets.mjs b/scripts/docs-site-assets.mjs index eb4e94c..f3ee146 100644 --- a/scripts/docs-site-assets.mjs +++ b/scripts/docs-site-assets.mjs @@ -56,9 +56,13 @@ a:hover{text-decoration:underline;text-underline-offset:.2em} .sidebar-head{display:flex;align-items:center;gap:10px;margin-bottom:24px} .brand{display:flex;align-items:center;gap:11px;color:var(--ink);text-decoration:none;flex:1;min-width:0} .brand:hover{text-decoration:none} -.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} -.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} -.brand .mark span{position:relative;z-index:1} +.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)} +.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} +.brand .mark::after{content:"";position:absolute;inset:1px;border-radius:8px;border:1px solid rgba(255,255,255,.08);pointer-events:none} +.brand .mark svg{position:relative;z-index:1;width:20px;height:20px;display:block} +.brand .mark .cursor{transform-origin:center;animation:acpx-blink 1.2s steps(2,jump-none) infinite} +@keyframes acpx-blink{0%,49%{opacity:1}50%,100%{opacity:.25}} +@media (prefers-reduced-motion: reduce){.brand .mark .cursor{animation:none}} .brand strong{display:block;font-size:1.05rem;line-height:1.1;font-weight:600;letter-spacing:0;color:var(--ink)} .brand small{display:block;color:var(--muted);font-size:.74rem;margin-top:3px;font-weight:400} .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} .doc pre::-webkit-scrollbar{height:8px;width:8px} .doc pre::-webkit-scrollbar-thumb{background:#334155;border-radius:8px} .doc pre code{display:block;background:transparent;border:0;color:inherit;padding:0;font-size:1em;white-space:pre} +.doc pre .hl-com{color:#7a8597;font-style:italic} +.doc pre .hl-str{color:#86efac} +.doc pre .hl-num{color:#fbbf24} +.doc pre .hl-kw{color:#c4b5fd;font-weight:500} +.doc pre .hl-lit{color:#f0abfc} +.doc pre .hl-flag{color:#7dd3fc} +.doc pre .hl-var{color:#fca5a5} +.doc pre .hl-prop{color:#7dd3fc} +.doc pre .hl-op{color:#94a3b8} +.doc pre .hl-typ{color:#fde68a} .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} .doc pre:hover .copy,.doc pre .copy:focus{opacity:1} .doc pre .copy:hover{background:rgba(255,255,255,.12)} @@ -259,20 +273,24 @@ export function themeToggleHtml() { } export function brandMarkHtml() { - return ``; + return ``; } export function faviconSvg() { return ` - + + + + + - - - - + + + + `; }