summaryrefslogtreecommitdiffhomepage
path: root/vhosts/blog/nuldoc-src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-03-29 00:47:55 +0900
committernsfisis <nsfisis@gmail.com>2025-03-29 00:55:14 +0900
commitd30dfc89bf1b673b2fdc0638766b930adaec228c (patch)
tree739d8826451947adfeb526ef1adeb1db397a9af4 /vhosts/blog/nuldoc-src
parentf65ec15aaf8fc46685c39d721cab82f64baead8c (diff)
downloadnsfisis.dev-d30dfc89bf1b673b2fdc0638766b930adaec228c.tar.gz
nsfisis.dev-d30dfc89bf1b673b2fdc0638766b930adaec228c.tar.zst
nsfisis.dev-d30dfc89bf1b673b2fdc0638766b930adaec228c.zip
feat(blog/nuldoc): migrate syntax highlighter from highlight.js to shiki.js
Diffstat (limited to 'vhosts/blog/nuldoc-src')
-rw-r--r--vhosts/blog/nuldoc-src/components/PageLayout.tsx4
-rw-r--r--vhosts/blog/nuldoc-src/dom.ts22
-rw-r--r--vhosts/blog/nuldoc-src/ndoc/parse.ts2
-rw-r--r--vhosts/blog/nuldoc-src/ndoc/to_html.ts71
-rw-r--r--vhosts/blog/nuldoc-src/types/highlight-js.d.ts15
5 files changed, 43 insertions, 71 deletions
diff --git a/vhosts/blog/nuldoc-src/components/PageLayout.tsx b/vhosts/blog/nuldoc-src/components/PageLayout.tsx
index c7145e0a..1cd0aebf 100644
--- a/vhosts/blog/nuldoc-src/components/PageLayout.tsx
+++ b/vhosts/blog/nuldoc-src/components/PageLayout.tsx
@@ -20,7 +20,7 @@ export default function PageLayout(
metaKeywords,
metaTitle,
metaAtomFeedHref,
- requiresSyntaxHighlight,
+ requiresSyntaxHighlight: _,
config,
children,
}: Props,
@@ -54,8 +54,6 @@ export default function PageLayout(
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<title>{metaTitle}</title>
<StaticStylesheet fileName="/style.css" config={config} />
- {requiresSyntaxHighlight &&
- <StaticStylesheet fileName="/hl.css" config={config} />}
</head>
{children}
</html>
diff --git a/vhosts/blog/nuldoc-src/dom.ts b/vhosts/blog/nuldoc-src/dom.ts
index 478cbc6c..ed7ffd31 100644
--- a/vhosts/blog/nuldoc-src/dom.ts
+++ b/vhosts/blog/nuldoc-src/dom.ts
@@ -69,6 +69,15 @@ export function forEachChild(e: Element, f: (n: Node) => void) {
}
}
+export async function forEachChildAsync(
+ e: Element,
+ f: (n: Node) => Promise<void>,
+): Promise<void> {
+ for (const c of e.children) {
+ await f(c);
+ }
+}
+
export function forEachChildRecursively(e: Element, f: (n: Node) => void) {
const g = (c: Node) => {
f(c);
@@ -78,3 +87,16 @@ export function forEachChildRecursively(e: Element, f: (n: Node) => void) {
};
forEachChild(e, g);
}
+
+export async function forEachChildRecursivelyAsync(
+ e: Element,
+ f: (n: Node) => Promise<void>,
+): Promise<void> {
+ const g = async (c: Node) => {
+ await f(c);
+ if (c.kind === "element") {
+ await forEachChildAsync(c, g);
+ }
+ };
+ await forEachChildAsync(e, g);
+}
diff --git a/vhosts/blog/nuldoc-src/ndoc/parse.ts b/vhosts/blog/nuldoc-src/ndoc/parse.ts
index 10b3309b..4bb96f4d 100644
--- a/vhosts/blog/nuldoc-src/ndoc/parse.ts
+++ b/vhosts/blog/nuldoc-src/ndoc/parse.ts
@@ -19,7 +19,7 @@ export async function parseNulDocFile(
const meta = parseMetadata(parts[1]);
const root = parseXmlString("<?xml ?>" + parts[2]);
const doc = createNewDocumentFromRootElement(root, meta, filePath, config);
- return toHtml(doc);
+ return await toHtml(doc);
} catch (e) {
if (e instanceof Error) {
e.message = `${e.message} in ${filePath}`;
diff --git a/vhosts/blog/nuldoc-src/ndoc/to_html.ts b/vhosts/blog/nuldoc-src/ndoc/to_html.ts
index bf556655..d4630d59 100644
--- a/vhosts/blog/nuldoc-src/ndoc/to_html.ts
+++ b/vhosts/blog/nuldoc-src/ndoc/to_html.ts
@@ -1,30 +1,28 @@
-// @deno-types="../types/highlight-js.d.ts"
-import hljs from "highlight.js";
+import { BundledLanguage, bundledLanguages, codeToHtml } from "shiki";
import { Document } from "./document.ts";
import { NuldocError } from "../errors.ts";
import {
addClass,
Element,
- findFirstChildElement,
forEachChild,
forEachChildRecursively,
+ forEachChildRecursivelyAsync,
Node,
RawHTML,
Text,
} from "../dom.ts";
-export default function toHtml(doc: Document): Document {
+export default async function toHtml(doc: Document): Promise<Document> {
removeUnnecessaryTextNode(doc);
transformLinkLikeToAnchorElement(doc);
transformSectionIdAttribute(doc);
setSectionTitleAnchor(doc);
transformSectionTitleElement(doc);
- transformCodeBlockElement(doc);
transformNoteElement(doc);
addAttributesToExternalLinkElement(doc);
setDefaultLangAttribute(doc);
traverseFootnotes(doc);
- highlightPrograms(doc);
+ await transformAndHighlightCodeBlockElement(doc);
return doc;
}
@@ -163,24 +161,6 @@ function transformSectionTitleElement(doc: Document) {
forEachChild(doc.root, g);
}
-function transformCodeBlockElement(doc: Document) {
- forEachChildRecursively(doc.root, (n) => {
- if (n.kind !== "element" || n.name !== "codeblock") {
- return;
- }
-
- n.name = "pre";
- addClass(n, "highlight");
- const codeElement: Element = {
- kind: "element",
- name: "code",
- attributes: new Map(),
- children: n.children,
- };
- n.children = [codeElement];
- });
-}
-
function transformNoteElement(doc: Document) {
forEachChildRecursively(doc.root, (n) => {
if (n.kind !== "element" || n.name !== "note") {
@@ -254,40 +234,27 @@ function traverseFootnotes(doc: Document) {
});
}
-function highlightPrograms(doc: Document) {
- forEachChildRecursively(doc.root, (n) => {
- if (n.kind !== "element" || n.name !== "pre") {
- return;
- }
- const preClass = n.attributes.get("class") || "";
- if (!preClass.includes("highlight")) {
- return;
- }
- const codeElement = findFirstChildElement(n, "code");
- if (!codeElement) {
- return;
- }
- const language = n.attributes.get("language");
- if (!language) {
+async function transformAndHighlightCodeBlockElement(doc: Document) {
+ await forEachChildRecursivelyAsync(doc.root, async (n) => {
+ if (n.kind !== "element" || n.name !== "codeblock") {
return;
}
- const sourceCodeNode = codeElement.children[0] as Text | RawHTML;
- const sourceCode = sourceCodeNode.content;
- if (!hljs.getLanguage(language)) {
- if (language === "zsh") {
- // highlight.js does not have a language definition for zsh.
- hljs.registerAliases("zsh", { languageName: "bash" });
- } else {
- return;
- }
- }
+ const language = n.attributes.get("language") || "text";
+ const sourceCodeNode = n.children[0] as Text | RawHTML;
+ const sourceCode = sourceCodeNode.content;
- const highlighted =
- hljs.highlight(sourceCode, { language: language }).value;
+ const highlighted = await codeToHtml(sourceCode, {
+ lang: language in bundledLanguages ? language as BundledLanguage : "text",
+ theme: "github-light",
+ colorReplacements: {
+ "#fff": "#f5f5f5",
+ },
+ });
sourceCodeNode.content = highlighted;
sourceCodeNode.raw = true;
- codeElement.attributes.set("class", "highlight");
+ n.name = "div";
+ n.attributes.set("class", "codeblock");
});
}
diff --git a/vhosts/blog/nuldoc-src/types/highlight-js.d.ts b/vhosts/blog/nuldoc-src/types/highlight-js.d.ts
deleted file mode 100644
index 67007b53..00000000
--- a/vhosts/blog/nuldoc-src/types/highlight-js.d.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-declare module "highlight.js" {
- function registerAliases(
- aliases: string | string[],
- language: { languageName: string },
- ): void;
-
- function getLanguage(
- name: string,
- ): string | undefined;
-
- function highlight(
- code: string,
- options: { language: string },
- ): { value: string };
-}