Skip to content

Commit

Permalink
feat(syntax-highlight): do client side, support more languages (#11654)
Browse files Browse the repository at this point in the history
Co-authored-by: Florian Dieminger <me@fiji-flo.de>
  • Loading branch information
LeoMcA and fiji-flo committed Sep 16, 2024
1 parent 6b75edd commit 253ef1f
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 176 deletions.
4 changes: 2 additions & 2 deletions build/blog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
postProcessSmallerHeadingIDs,
} from "./utils.js";
import { slugToFolder } from "../libs/slug-utils/index.js";
import { syntaxHighlight } from "./syntax-highlight.js";
import { wrapCodeExamples } from "./code-headers.js";
import { wrapTables } from "./wrap-tables.js";
import { Doc } from "../libs/types/document.js";
import { extractSections } from "./extract-sections.js";
Expand Down Expand Up @@ -391,7 +391,7 @@ export async function buildPost(
doc.hasMathML = true;
}
$("div.hidden").remove();
syntaxHighlight($, doc);
wrapCodeExamples($);
injectNoTranslate($);
injectLoadingLazyAttributes($);
postProcessExternalLinks($);
Expand Down
45 changes: 45 additions & 0 deletions build/code-headers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as cheerio from "cheerio";

// Over the years we have accumulated some weird <pre> tags whose
// brush is more or less "junk".
// TODO: Perhaps, if you have a doc with <pre> tags that matches
// this, it should become a flaw.
const IGNORE = new Set(["none", "text", "plain", "unix"]);

/**
* Mutate the `$` instance by adding headers to <pre> tags containing code blocks.
*
*/
export function wrapCodeExamples($: cheerio.CheerioAPI) {
// Our content will be like this: `<pre class="brush:js">` or
// `<pre class="brush: js">` so we're technically not looking for an exact
// match. The wildcard would technically match `<pre class="brushetta">`
// too. But within the loop, we do a more careful regex on the class name
// and only proceed if it's something sensible.
$("pre[class*=brush]").each((_, element) => {
// The language is whatever string comes after the `brush(:)`
// portion of the class name.
const $pre = $(element);

const className = $pre.attr("class").toLowerCase();
const match = className.match(/brush:?\s*([\w_-]+)/);
if (!match) {
return;
}
const name = match[1].replace("-nolint", "");
if (IGNORE.has(name)) {
// Seems to exist a couple of these in our docs. Just bail.
return;
}
const code = $pre.text();
$pre.wrapAll(`<div class='code-example'></div>`);
if (!$pre.hasClass("hidden")) {
$(
`<div class='example-header'><span class="language-name">${name}</span></div>`
).insertBefore($pre);
}
const $code = $("<code>").text(code);

$pre.empty().append($code);
});
}
4 changes: 2 additions & 2 deletions build/curriculum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { DocParent } from "../libs/types/document.js";
import { CURRICULUM_TITLE, DEFAULT_LOCALE } from "../libs/constants/index.js";
import * as kumascript from "../kumascript/index.js";
import LANGUAGES_RAW from "../libs/languages/index.js";
import { syntaxHighlight } from "./syntax-highlight.js";
import { wrapCodeExamples } from "./code-headers.js";
import {
escapeRegExp,
injectLoadingLazyAttributes,
Expand Down Expand Up @@ -321,7 +321,7 @@ export async function buildCurriculumPage(
doc.hasMathML = true;
}
$("div.hidden").remove();
syntaxHighlight($, doc);
wrapCodeExamples($);
injectNoTranslate($);
injectLoadingLazyAttributes($);
postProcessCurriculumLinks($, (p: string | undefined) => {
Expand Down
6 changes: 3 additions & 3 deletions build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
} from "./flaws/index.js";
import { checkImageReferences, checkImageWidths } from "./check-images.js";
import { getPageTitle } from "./page-title.js";
import { syntaxHighlight } from "./syntax-highlight.js";
import { wrapCodeExamples } from "./code-headers.js";
import { formatNotecards } from "./format-notecards.js";
import buildOptions from "./build-options.js";
import LANGUAGES_RAW from "../libs/languages/index.js";
Expand Down Expand Up @@ -456,8 +456,8 @@ export async function buildDocument(
plainHTML = $.html();
}

// Apply syntax highlighting all <pre> tags.
syntaxHighlight($, doc);
// Add headers to all <pre> tags with code.
wrapCodeExamples($);

// Post process HTML so that the right elements gets tagged so they
// *don't* get translated by tools like Google Translate.
Expand Down
139 changes: 0 additions & 139 deletions build/syntax-highlight.ts

This file was deleted.

7 changes: 2 additions & 5 deletions client/src/blog/post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ import {
BlogPostLimitedMetadata,
AuthorMetadata,
} from "../../../libs/types/blog";
import {
useCopyExamplesToClipboardAndAIExplain,
useRunSample,
} from "../document/hooks";
import { useDecorateCodeExamples, useRunSample } from "../document/hooks";
import { DEFAULT_LOCALE } from "../../../libs/constants";
import { SignUpSection as NewsletterSignUp } from "../newsletter";
import { TOC } from "../document/organisms/toc";
Expand Down Expand Up @@ -190,7 +187,7 @@ export function BlogPost(props: HydrationData) {
);
const { doc, blogMeta } = data || props || {};
useRunSample(doc);
useCopyExamplesToClipboardAndAIExplain(doc);
useDecorateCodeExamples(doc);
return (
<>
{doc && blogMeta && (
Expand Down
Loading

0 comments on commit 253ef1f

Please sign in to comment.