docs: safe syntax highlighting (0.61.0)
- minimal dep-free highlighter for fenced code blocks: strings (green), numbers (amber), keywords (purple) - deliberately NO comment rule, so '//' inside URLs (https://, wss://) is never mis-colored or mangled — the common micro-highlighter pitfall - applied in the DocsApp post-render pass alongside the copy buttons; the copy button still yields the exact original text - verified live: 22 tokens colored, both https:// and wss:// URLs preserved byte-for-byte, code intact
This commit is contained in:
parent
cf67af7131
commit
2d00cb4e63
@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0e0a14" />
|
||||
<meta name="description" content="amerc is the agent mercenary tavern — hire, run, publish, and remotely deliver AI agents across software boundaries. No infrastructure, just skills." />
|
||||
<meta name="version" content="0.60.0-canvasperf" />
|
||||
<meta name="version" content="0.61.0-syntax" />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="icon" href="/app-192.png" type="image/png" sizes="192x192" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "amerc-site",
|
||||
"version": "0.60.0-canvasperf",
|
||||
"version": "0.61.0-syntax",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@ -6,6 +6,22 @@ import { copyToast } from './toast.js';
|
||||
|
||||
marked.setOptions({ breaks: true });
|
||||
|
||||
// Minimal, safe syntax highlighter: strings, numbers, keywords only.
|
||||
// No comment rule on purpose — '//' inside URLs (https://) must never be eaten.
|
||||
const esc = (s) => s.replace(/[&<>]/g, (c) => ({ '&': '&', '<': '<', '>': '>' }[c]));
|
||||
const HL_RE = /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)|(\b\d+(?:\.\d+)?\b)|\b(const|let|var|function|return|while|do|done|if|then|else|fi|for|true|false|null|async|await|new|export|import|setInterval|setTimeout|fetch|sleep|curl|JSON|Math|console)\b/g;
|
||||
function highlightCode(code) {
|
||||
let out = '', last = 0, m;
|
||||
HL_RE.lastIndex = 0;
|
||||
while ((m = HL_RE.exec(code))) {
|
||||
out += esc(code.slice(last, m.index));
|
||||
const cls = m[1] ? 'hl-str' : m[2] ? 'hl-num' : 'hl-kw';
|
||||
out += `<span class="${cls}">${esc(m[0])}</span>`;
|
||||
last = m.index + m[0].length;
|
||||
}
|
||||
return out + esc(code.slice(last));
|
||||
}
|
||||
|
||||
function DocsWorkspace({ canEdit }) {
|
||||
const [docs, setDocs] = useState([]);
|
||||
const [sel, setSel] = useState(null);
|
||||
@ -30,6 +46,8 @@ function DocsWorkspace({ canEdit }) {
|
||||
if (!el || editing) return;
|
||||
el.querySelectorAll('pre').forEach((pre) => {
|
||||
if (pre.parentElement?.classList.contains('docs-code')) return;
|
||||
const codeEl = pre.querySelector('code') || pre;
|
||||
codeEl.innerHTML = highlightCode(codeEl.textContent);
|
||||
const wrap = document.createElement('div'); wrap.className = 'docs-code';
|
||||
const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'docs-copy'; btn.textContent = 'copy';
|
||||
btn.addEventListener('click', () => copyToast(pre.innerText, 'Copied'));
|
||||
|
||||
@ -7,7 +7,7 @@ import Account from './Account.jsx';
|
||||
import TavernGame from './TavernGame.jsx';
|
||||
import { api } from './api.js';
|
||||
|
||||
const RELEASE = '0.60.0-canvasperf';
|
||||
const RELEASE = '0.61.0-syntax';
|
||||
|
||||
const NAV = [
|
||||
{ id: 'home', label: 'Tavern' },
|
||||
|
||||
@ -1426,3 +1426,8 @@ button {
|
||||
/* keyboard focus indicators — visible for keyboard users only (a11y, 0.59) */
|
||||
:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
|
||||
.gm-cta-primary:focus-visible, .px-action:focus-visible { outline-color: #f3d27a; }
|
||||
|
||||
/* docs syntax highlight tokens (0.61) */
|
||||
.docs-render pre code .hl-str { color: #9ce5a4; }
|
||||
.docs-render pre code .hl-num { color: #f0b86a; }
|
||||
.docs-render pre code .hl-kw { color: #c79aef; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user