From 6a8fc0a5c0f89c12dcf4b879b67a25607147a20c Mon Sep 17 00:00:00 2001 From: artheru Date: Wed, 10 Jun 2026 08:17:15 +0800 Subject: [PATCH] docs: code-block copy buttons + 'Connect your broker' guide (0.58.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix fenced code blocks: reset the doubled inline-code background on 'pre code', readable monospace styling (applies to all technical docs) - DocsApp decorates rendered code blocks with a hover copy button - seed a 'Connect your broker' guide (guides/) — the lasting reference for the supply-side last mile: heartbeat loop (curl + Node) to stay online, the relay WebSocket, and how it fits together (accurate from the API) - verified live on docs.amerc.ai: guide renders, 3 code blocks, 3 copy buttons wired, clean styling --- index.html | 2 +- package.json | 2 +- src/DocsApp.jsx | 18 ++++++++++++++++-- src/Scene2D.jsx | 2 +- src/styles.css | 9 +++++++++ 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 4fcb18d..552fd1c 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + diff --git a/package.json b/package.json index dddc323..11fb711 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amerc-site", - "version": "0.57.0-loadstates", + "version": "0.58.0-docscode", "private": true, "type": "module", "scripts": { diff --git a/src/DocsApp.jsx b/src/DocsApp.jsx index b438fa6..545154e 100644 --- a/src/DocsApp.jsx +++ b/src/DocsApp.jsx @@ -1,7 +1,8 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { marked } from 'marked'; import ConsoleShell from './ConsoleShell.jsx'; import { api } from './api.js'; +import { copyToast } from './toast.js'; marked.setOptions({ breaks: true }); @@ -13,6 +14,7 @@ function DocsWorkspace({ canEdit }) { const [draft, setDraft] = useState({ title: '', folder: '', body: '' }); const [err, setErr] = useState(''); const [q, setQ] = useState(''); + const renderRef = useRef(null); const loadList = useCallback(async () => { try { const d = await api('/docs'); setDocs(d.docs || []); } catch (e) { setErr(e.message); } @@ -22,6 +24,18 @@ function DocsWorkspace({ canEdit }) { if (sel == null) { setDoc(null); return; } api(`/docs/${sel}`).then((d) => { setDoc(d.doc); setDraft({ title: d.doc.title, folder: d.doc.folder, body: d.doc.body }); setEditing(false); }).catch((e) => setErr(e.message)); }, [sel]); + // decorate rendered code blocks with a hover copy button + useEffect(() => { + const el = renderRef.current; + if (!el || editing) return; + el.querySelectorAll('pre').forEach((pre) => { + if (pre.parentElement?.classList.contains('docs-code')) return; + 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')); + pre.parentNode.insertBefore(wrap, pre); wrap.appendChild(btn); wrap.appendChild(pre); + }); + }, [doc, editing]); const create = async () => { const title = window.prompt('Document title', 'New document'); if (!title) return; @@ -73,7 +87,7 @@ function DocsWorkspace({ canEdit }) {

updated by {doc.updated_by || '—'}

{editing ?