docs: highlight docs site code blocks
This commit is contained in:
parent
c68d285400
commit
e3c4ea61e6
@ -82,6 +82,12 @@ body:not(.home) .doc>h1:first-child{display:none}
|
||||
.doc pre::-webkit-scrollbar{height:8px;width:8px}
|
||||
.doc pre::-webkit-scrollbar-thumb{background:var(--code-scroll);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-c{color:#7f9990;font-style:italic}
|
||||
.doc pre .hl-s{color:#a6e3a1}
|
||||
.doc pre .hl-v{color:#f9c779}
|
||||
.doc pre .hl-f{color:#89c2d9}
|
||||
.doc pre .hl-n{color:#f4a47a}
|
||||
.doc pre .hl-k{color:#cba6f7}
|
||||
.copy{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:34px;height:34px;background:rgba(255,255,255,.06);color:var(--code-fg);border:1px solid rgba(255,255,255,.18);border-radius:8px;padding:0;cursor:pointer;transition:background .15s,border-color .15s,color .15s,opacity .15s}
|
||||
.copy:hover{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.3)}
|
||||
.copy:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
||||
|
||||
61
scripts/docs-site-highlight.mjs
Normal file
61
scripts/docs-site-highlight.mjs
Normal file
@ -0,0 +1,61 @@
|
||||
import { escapeHtml } from "./docs-site-render.mjs";
|
||||
|
||||
export function highlight(lang, source) {
|
||||
const normalized = (lang || "").toLowerCase();
|
||||
if (normalized === "bash" || normalized === "sh" || normalized === "shell") {
|
||||
return tokenize(source, BASH_RULES);
|
||||
}
|
||||
if (normalized === "json") return tokenize(source, JSON_RULES);
|
||||
if (normalized === "sql") return tokenize(source, SQL_RULES);
|
||||
return escapeHtml(source);
|
||||
}
|
||||
|
||||
function tokenize(source, rules) {
|
||||
let out = "";
|
||||
let pending = "";
|
||||
let i = 0;
|
||||
outer: while (i < source.length) {
|
||||
for (const [klass, regex] of rules) {
|
||||
regex.lastIndex = i;
|
||||
const match = regex.exec(source);
|
||||
if (match && match.index === i) {
|
||||
if (pending) {
|
||||
out += escapeHtml(pending);
|
||||
pending = "";
|
||||
}
|
||||
out += `<span class="hl-${klass}">${escapeHtml(match[0])}</span>`;
|
||||
i = regex.lastIndex;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
pending += source[i];
|
||||
i += 1;
|
||||
}
|
||||
if (pending) out += escapeHtml(pending);
|
||||
return out;
|
||||
}
|
||||
|
||||
const BASH_RULES = [
|
||||
["c", /#[^\n]*/y],
|
||||
["s", /"(?:\\[\s\S]|[^"\\])*"/y],
|
||||
["s", /'[^'\n]*'/y],
|
||||
["v", /\$\{[^}\n]+\}|\$[A-Za-z_][A-Za-z0-9_]*|\$[0-9?#@*!$-]/y],
|
||||
["f", /(?<=^|[\s=(\[])--?[A-Za-z][\w-]*/y],
|
||||
["n", /(?<=^|[\s=(:,])\d+(?:\.\d+)?\b/y],
|
||||
["k", /\b(?:if|then|else|elif|fi|while|do|done|for|in|case|esac|function|return|exit|local|export|readonly|set|source|alias|cd|read|exec|trap)\b/y],
|
||||
];
|
||||
|
||||
const JSON_RULES = [
|
||||
["s", /"(?:\\[\s\S]|[^"\\])*"(?=\s*:)/y, "key"],
|
||||
["s", /"(?:\\[\s\S]|[^"\\])*"/y],
|
||||
["n", /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y],
|
||||
["k", /\b(?:true|false|null)\b/y],
|
||||
];
|
||||
|
||||
const SQL_RULES = [
|
||||
["c", /--[^\n]*/y],
|
||||
["c", /\/\*[\s\S]*?\*\//y],
|
||||
["s", /'(?:''|[^'\n])*'/y],
|
||||
["n", /\b\d+(?:\.\d+)?\b/y],
|
||||
["k", /\b(?:SELECT|FROM|WHERE|AND|OR|NOT|NULL|IS|IN|LIKE|BETWEEN|JOIN|LEFT|RIGHT|INNER|OUTER|ON|GROUP|BY|ORDER|HAVING|LIMIT|OFFSET|INSERT|INTO|VALUES|UPDATE|SET|DELETE|CREATE|TABLE|INDEX|VIEW|DROP|ALTER|ADD|COLUMN|PRIMARY|KEY|FOREIGN|REFERENCES|UNIQUE|DEFAULT|AS|CASE|WHEN|THEN|ELSE|END|UNION|ALL|DISTINCT|COUNT|SUM|AVG|MIN|MAX|WITH|PRAGMA|VIRTUAL|USING|MATCH)\b/iy],
|
||||
];
|
||||
@ -1,6 +1,8 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
import { highlight } from "./docs-site-highlight.mjs";
|
||||
|
||||
export function markdownToHtml(markdown, currentRel, rewriteHref) {
|
||||
const lines = markdown.replace(/\r\n/g, "\n").split("\n");
|
||||
const html = [];
|
||||
@ -34,7 +36,7 @@ export function markdownToHtml(markdown, currentRel, rewriteHref) {
|
||||
closeList();
|
||||
flushBlockquote();
|
||||
if (fence) {
|
||||
html.push(`<pre><code class="language-${escapeAttr(fence.lang)}">${escapeHtml(fence.lines.join("\n"))}</code></pre>`);
|
||||
html.push(`<pre><code class="language-${escapeAttr(fence.lang)}">${highlight(fence.lang, fence.lines.join("\n"))}</code></pre>`);
|
||||
fence = null;
|
||||
} else {
|
||||
fence = { lang: fenceMatch[1] || "text", lines: [] };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user