-
Notifications
You must be signed in to change notification settings - Fork 0
/
render.js
125 lines (100 loc) · 4.5 KB
/
render.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
* Good day, and welcome to render.js.
*
* @module render
*/
import MarkdownIt from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
import markdownItFrontMatter from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
import { createMetaTag } from './modules/utils.js';
/**
* Parsed version of what got passed into us from the JSON md doc header
*/
export let frontMatter = {};
/**
* rendering theme used by Shiki
*/
export let currentTheme = {};
/**
* Generic content renderer using Shiki
*
* Pass in a string, and what that string is, and sending it back hilighted.
*
* @param {string} contentStringToRender
* @param {string} lang (e.g. 'javascript', 'r', 'json', 'md', etc. anything Shiki has)
* @returns string
*/
export async function renderContent(contentStringToRender, lang) {
lang = lang === "svg" ? "xml" : "lang"
const highlighter = await shiki
.getHighlighter({
theme: currentTheme,
langs: [ lang ]
})
return Promise.resolve(
highlighter.codeToHtml(contentStringToRender, { lang: lang })
)
}
/**
* Core renderer (highlighter) for the app. (I should likely refactor this)
*
* @param {string} markdownFile markdown file base name that must be in the 'md/' folder
* @param {string} theme short name of theme that must be in the 'themes/` folder
* @param {string[]} langs array of languages you want the core renderer to be able to handle
* @param {boolean} renderFrontmatter if `true` then generate OG tags;
*/
export async function renderMarkdown(markdownFile, theme, langs = [ 'javascript', 'r', 'json', 'md', 'xml' ], renderFrontmatter = true) {
currentTheme = await d3.json(`./themes/${theme}.json`);
await shiki
.getHighlighter({
theme: currentTheme,
langs: [ 'javascript', 'r', 'json', 'md', 'xml' ]
})
.then(async highlighter => {
const md = new MarkdownIt({
html: true,
highlight: (code, lang) => {
return highlighter.codeToHtml(code, { lang })
}
}).use(markdownItFrontMatter, async fm => {
// extract frontmatter and setup meta tags and title
frontMatter = JSON.parse(fm);
if (renderFrontmatter) {
const matterKeys = Object.keys(frontMatter);
const head = document.getElementsByTagName("head")[ 0 ];
if (matterKeys.includes("title")) {
document.title = frontMatter.title;
head.appendChild(createMetaTag("og:title", frontMatter.title))
head.appendChild(createMetaTag("twitter:title", frontMatter.title))
}
if (matterKeys.includes("og")) {
frontMatter.og.description && head.appendChild(createMetaTag("og:description", frontMatter.og.description))
frontMatter.og.description && head.appendChild(createMetaTag("twitter:description", frontMatter.og.description))
frontMatter.og.url && head.appendChild(createMetaTag("og:site", frontMatter.og.url))
frontMatter.og.site_name && head.appendChild(createMetaTag("og:site_name", frontMatter.og.site_name))
frontMatter.og.image.url && head.appendChild(createMetaTag("og:image:url", frontMatter.og.image.url))
frontMatter.og.image.width && head.appendChild(createMetaTag("og:image:width", frontMatter.og.image.width))
frontMatter.og.image.height && head.appendChild(createMetaTag("og:image:height", frontMatter.og.image.height))
frontMatter.og.image.alt && head.appendChild(createMetaTag("og:image:alt", frontMatter.og.image.alt))
}
if (matterKeys.includes("twitter")) {
frontMatter.twitter.site && head.appendChild(createMetaTag("twitter:site_name", frontMatter.twitter.site))
frontMatter.twitter.domain && head.appendChild(createMetaTag("twitter:domain", frontMatter.twitter.domain))
frontMatter.og.image.url && head.appendChild(createMetaTag("twitter:image", frontMatter.og.image.url))
frontMatter.og.image.url && head.appendChild(createMetaTag("twitter:card", "summary_large_image"))
}
head.appendChild(createMetaTag("article:published_time", new Date().toISOString()))
}
})
// parse the rest of the document and add it to the body
const mdContent = await d3.text(`./md/${markdownFile}.md`);
const readHTML = new DOMParser();
const rendered = md.render(mdContent);
const contentParsed = readHTML.parseFromString(rendered, "text/html");
const bodyContent = contentParsed.getElementsByTagName("body")[ 0 ];
const content = document.getElementById("content")
while (bodyContent.childNodes.length > 0) {
content.appendChild(bodyContent.childNodes[ 0 ]);
}
})
}