feat: add some highlighting to markdown renderer

This commit is contained in:
2023-08-02 17:21:03 +02:00
parent 21871a72e6
commit 70d16913f3
10 changed files with 485 additions and 15 deletions

View File

@ -1,12 +1,13 @@
import { unified } from "https://esm.sh/unified@10.1.2";
import { render } from "https://deno.land/x/gfm@0.2.5/mod.ts";
import "https://esm.sh/prismjs@1.29.0/components/prism-typescript?no-check";
import "https://esm.sh/prismjs@1.29.0/components/prism-bash?no-check";
import "https://esm.sh/prismjs@1.29.0/components/prism-rust?no-check";
import remarkParse from "https://esm.sh/remark-parse@10.0.2";
import remarkStringify from "https://esm.sh/remark-stringify@10.0.3";
import remarkFrontmatter, {
Root,
} from "https://esm.sh/remark-frontmatter@4.0.1";
import remarkRehype from "https://esm.sh/remark-rehype@10.1.0";
import rehypeSanitize from "https://esm.sh/rehype-sanitize@5.0.1";
import rehypeStringify from "https://esm.sh/rehype-stringify@9.0.3";
import * as cache from "@lib/cache/documents.ts";
import { SILVERBULLET_SERVER } from "@lib/env.ts";
import { fixRenderedMarkdown } from "@lib/helpers.ts";
@ -90,14 +91,9 @@ export function parseDocument(doc: string) {
}
export function renderMarkdown(doc: string) {
const out = unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeSanitize)
.use(rehypeStringify)
.processSync(doc);
return String(out);
return render(doc, {
allowMath: true,
});
}
export type ParsedDocument = ReturnType<typeof parseDocument>;

79
lib/highlight.ts Normal file
View File

@ -0,0 +1,79 @@
import { refractor } from "https://esm.sh/refractor@4.8.1";
import { visit } from "https://esm.sh/unist-util-visit@5.0.0";
import { toString } from "https://esm.sh/hast-util-to-string@2.0.0";
import jsx from "https://esm.sh/refractor/lang/jsx";
import javascript from "https://esm.sh/refractor/lang/javascript";
import css from "https://esm.sh/refractor/lang/css";
import cssExtras from "https://esm.sh/refractor/lang/css-extras";
import jsExtras from "https://esm.sh/refractor/lang/js-extras";
import sql from "https://esm.sh/refractor/lang/sql";
import typescript from "https://esm.sh/refractor/lang/typescript";
import swift from "https://esm.sh/refractor/lang/swift";
import objectivec from "https://esm.sh/refractor/lang/objectivec";
import markdown from "https://esm.sh/refractor/lang/markdown";
import json from "https://esm.sh/refractor/lang/json";
refractor.register(jsx);
refractor.register(json);
refractor.register(typescript);
refractor.register(javascript);
refractor.register(css);
refractor.register(cssExtras);
refractor.register(jsExtras);
refractor.register(sql);
refractor.register(swift);
refractor.register(objectivec);
refractor.register(markdown);
refractor.alias({ jsx: ["js"] });
refractor.alias({typescript:["ts"]})
const getLanguage = (node) => {
const className = node.properties.className || [];
for (const classListItem of className) {
if (classListItem.slice(0, 9) === "language-") {
return classListItem.slice(9).toLowerCase();
}
}
return null;
};
const rehypePrism = (options) => {
options = options || {};
return (tree) => {
visit(tree, "element", visitor);
};
function visitor(node, index, parent) {
if (!parent || parent.tagName !== "pre" || node.tagName !== "code") {
return;
}
const lang = getLanguage(node);
if (lang === null) {
return;
}
let result;
try {
parent.properties.className = (parent.properties.className || []).concat(
"language-" + lang,
);
result = refractor.highlight(toString(node), lang);
} catch (err) {
if (options.ignoreMissing && /Unknown language/.test(err.message)) {
return;
}
throw err;
}
node.children = result;
}
};
export default rehypePrism;

View File

@ -35,8 +35,7 @@ export const isYoutubeLink = (link: string) => {
try {
const url = new URL(link);
return ["youtu.be", "youtube.com","www.youtube.com" ].includes(url.hostname);
} catch (err) {
console.log(err);
} catch (_err) {
return false;
}
};