From 653be290bb55b634d4d43f5a2beba1c6e71bb078 Mon Sep 17 00:00:00 2001 From: Declan Chidlow Date: Thu, 17 Oct 2024 20:12:26 +0800 Subject: [PATCH] Begin updating codeblocks (update js and fix line numbers) --- docs/scripts/syntax-highlighting.js | 47 ++++++++++++--------- docs/styles/type/code.css | 20 ++++----- input/global/scripts/syntax-highlighting.js | 47 ++++++++++++--------- input/global/styles/type/code.css | 20 ++++----- 4 files changed, 70 insertions(+), 64 deletions(-) diff --git a/docs/scripts/syntax-highlighting.js b/docs/scripts/syntax-highlighting.js index 1bb3026..500307b 100644 --- a/docs/scripts/syntax-highlighting.js +++ b/docs/scripts/syntax-highlighting.js @@ -1,39 +1,46 @@ // Based on https://brandur.org/fragments/shiki - -import { codeToHtml } from "https://esm.sh/shiki@1.10.0"; +import { codeToHtml } from "https://esm.sh/shiki@1.22.0"; const htmlEscapes = new Map([ ["&", "&"], ["<", "<"], [">", ">"], + [""", '"'], + ["'", "'"], ]); function unescapeHTMLEntities(str) { - for (const [escaped, unescaped] of htmlEscapes) { - str = str.replaceAll(escaped, unescaped); - } - return str; + return str.replace(/&(?:amp|lt|gt|quot|#39);/g, (match) => htmlEscapes.get(match)); } -const processCodeBlock = async (codeBlock) => { - const classNames = codeBlock.getAttribute("class"); - if (!classNames) return; - - const language = classNames - .split(" ") - .map((c) => c.split("-")) - .find(([prefix]) => prefix === "language") - ?.slice(1) - .join("-") - .toLowerCase(); +const getLanguageFromClassNames = (classNames) => { + if (!classNames) return null; + const languageClass = classNames.split(" ").find((c) => c.startsWith("language-")); + return languageClass ? languageClass.slice(9).toLowerCase() : null; +}; +const processCodeBlock = async (codeBlock) => { + const language = getLanguageFromClassNames(codeBlock.className); if (!language) return; - const code = unescapeHTMLEntities(codeBlock.innerHTML); - codeBlock.parentElement.outerHTML = await codeToHtml(code, { + const code = unescapeHTMLEntities(codeBlock.textContent.trim()); + const highlightedCode = await codeToHtml(code, { lang: language, theme: "vitesse-dark", }); + + const tempElement = document.createElement("div"); + tempElement.innerHTML = highlightedCode; + codeBlock.parentElement.replaceWith(tempElement.firstElementChild); +}; + +const highlightAllCodeBlocks = async () => { + const codeBlocks = document.querySelectorAll("pre code"); + await Promise.all(Array.from(codeBlocks).map(processCodeBlock)); }; -await Promise.all(Array.from(document.querySelectorAll("pre code")).map(processCodeBlock)); +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", highlightAllCodeBlocks); +} else { + await highlightAllCodeBlocks(); +} diff --git a/docs/styles/type/code.css b/docs/styles/type/code.css index ecad293..2b7a149 100644 --- a/docs/styles/type/code.css +++ b/docs/styles/type/code.css @@ -9,6 +9,7 @@ pre { code { background: none; + padding: 0; } } @@ -25,17 +26,12 @@ code { counter-reset: step; counter-increment: step 0; - .line { - &::before { - content: counter(step); - counter-increment: step; - width: 1rem; - margin-right: 1.5rem; - display: inline-block; - text-align: right; - } - &:last-child::before { - content: none; - } + .line::before { + content: counter(step); + counter-increment: step; + width: 1rem; + margin-right: 1.5rem; + display: inline-block; + text-align: right; } } diff --git a/input/global/scripts/syntax-highlighting.js b/input/global/scripts/syntax-highlighting.js index 1bb3026..500307b 100644 --- a/input/global/scripts/syntax-highlighting.js +++ b/input/global/scripts/syntax-highlighting.js @@ -1,39 +1,46 @@ // Based on https://brandur.org/fragments/shiki - -import { codeToHtml } from "https://esm.sh/shiki@1.10.0"; +import { codeToHtml } from "https://esm.sh/shiki@1.22.0"; const htmlEscapes = new Map([ ["&", "&"], ["<", "<"], [">", ">"], + [""", '"'], + ["'", "'"], ]); function unescapeHTMLEntities(str) { - for (const [escaped, unescaped] of htmlEscapes) { - str = str.replaceAll(escaped, unescaped); - } - return str; + return str.replace(/&(?:amp|lt|gt|quot|#39);/g, (match) => htmlEscapes.get(match)); } -const processCodeBlock = async (codeBlock) => { - const classNames = codeBlock.getAttribute("class"); - if (!classNames) return; - - const language = classNames - .split(" ") - .map((c) => c.split("-")) - .find(([prefix]) => prefix === "language") - ?.slice(1) - .join("-") - .toLowerCase(); +const getLanguageFromClassNames = (classNames) => { + if (!classNames) return null; + const languageClass = classNames.split(" ").find((c) => c.startsWith("language-")); + return languageClass ? languageClass.slice(9).toLowerCase() : null; +}; +const processCodeBlock = async (codeBlock) => { + const language = getLanguageFromClassNames(codeBlock.className); if (!language) return; - const code = unescapeHTMLEntities(codeBlock.innerHTML); - codeBlock.parentElement.outerHTML = await codeToHtml(code, { + const code = unescapeHTMLEntities(codeBlock.textContent.trim()); + const highlightedCode = await codeToHtml(code, { lang: language, theme: "vitesse-dark", }); + + const tempElement = document.createElement("div"); + tempElement.innerHTML = highlightedCode; + codeBlock.parentElement.replaceWith(tempElement.firstElementChild); +}; + +const highlightAllCodeBlocks = async () => { + const codeBlocks = document.querySelectorAll("pre code"); + await Promise.all(Array.from(codeBlocks).map(processCodeBlock)); }; -await Promise.all(Array.from(document.querySelectorAll("pre code")).map(processCodeBlock)); +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", highlightAllCodeBlocks); +} else { + await highlightAllCodeBlocks(); +} diff --git a/input/global/styles/type/code.css b/input/global/styles/type/code.css index ecad293..2b7a149 100644 --- a/input/global/styles/type/code.css +++ b/input/global/styles/type/code.css @@ -9,6 +9,7 @@ pre { code { background: none; + padding: 0; } } @@ -25,17 +26,12 @@ code { counter-reset: step; counter-increment: step 0; - .line { - &::before { - content: counter(step); - counter-increment: step; - width: 1rem; - margin-right: 1.5rem; - display: inline-block; - text-align: right; - } - &:last-child::before { - content: none; - } + .line::before { + content: counter(step); + counter-increment: step; + width: 1rem; + margin-right: 1.5rem; + display: inline-block; + text-align: right; } }