1- import yaml from 'yaml' ;
21import { marked } from 'marked' ;
32import Prism from 'prismjs' ;
43import loadLanguages from 'prismjs/components/' ;
54import { parse } from 'node-html-parser' ;
65import { replace } from './gh-emoji/index.js' ;
76import { textToBase64 } from '../../src/components/controllers/repl/query-encode.js' ;
7+ import { parseFrontmatter } from '../../src/lib/frontmatter.js' ;
88
99// Prism will always load `markup`, `css`, `clike` and `javascript` by default.
1010// Any additional languages we need should be loaded here
@@ -38,41 +38,23 @@ export async function precompileMarkdown(content, path) {
3838 * @param {string } path
3939 */
4040function parseContent ( content , path ) {
41- /** @type {import('../../src/types.d.ts').ContentMetaData } */
42- let meta = { } ;
43-
44- // Find YAML FrontMatter preceeding a markdown document
45- const FRONT_MATTER_REG = / ^ \s * - - - \n \s * ( [ \s \S ] * ?) \s * \n - - - \n / i;
46-
47- const matches = content . match ( FRONT_MATTER_REG ) ;
48- if ( ! matches ) throw new Error ( `Missing YAML FrontMatter in ${ path } ` ) ;
49- try {
50- meta = yaml . parse ( '---\n' + matches [ 1 ] . replace ( / ^ / gm, ' ' ) + '\n' ) ;
51- if ( ! meta . title ) {
52- throw new Error ( `Missing title in YAML FrontMatter for ${ path } ` ) ;
53- }
54- if ( ! meta . description ) {
55- //console.warn(`Missing description in FrontMatter for ${path}`);
56- }
57- } catch ( e ) {
58- throw new Error ( `Error parsing YAML FrontMatter in ${ path } ` ) ;
59- }
41+ const { body, meta } = parseFrontmatter ( content , path , true ) ;
6042
61- content = content . replace ( FRONT_MATTER_REG , '' ) ;
43+ let processedContent = body ;
6244
6345 if ( path . includes ( '/guide/' ) ) {
64- meta . toc = generateToc ( content ) ;
46+ meta . toc = generateToc ( processedContent ) ;
6547 }
6648
6749 // extract tutorial setup, initial and final code blocks
6850 if ( / t u t o r i a l \/ \d / . test ( path ) ) {
69- const { markdown, tutorial } = extractTutorialCodeBlocks ( content ) ;
70- content = markdown ;
51+ const { markdown, tutorial } = extractTutorialCodeBlocks ( processedContent ) ;
52+ processedContent = markdown ;
7153 meta . tutorial = tutorial ;
7254 }
7355
7456 return {
75- content,
57+ content : processedContent ,
7658 meta
7759 } ;
7860}
@@ -121,10 +103,12 @@ marked.use({
121103
122104 Prism . languages [ lang ] == null
123105 ? console . warn ( `No Prism highlighter for language: ${ lang } ` )
124- : text = Prism . highlight ( code , Prism . languages [ lang ] , lang ) ;
106+ : ( text = Prism . highlight ( code , Prism . languages [ lang ] , lang ) ) ;
125107
126108 const runInReplLink = runInRepl
127- ? `<a class="repl-link" href="/repl?code=${ encodeURIComponent ( textToBase64 ( source ) ) } ">Run in REPL</a>`
109+ ? `<a class="repl-link" href="/repl?code=${ encodeURIComponent (
110+ textToBase64 ( source )
111+ ) } ">Run in REPL</a>`
128112 : '' ;
129113
130114 return `
@@ -227,7 +211,9 @@ function highlightCodeBlocks(data) {
227211 const doc = parse ( data . html , { blockTextElements : { code : true } } ) ;
228212
229213 // Only get the pre blocks that haven't already been highlighted
230- const codeBlocks = doc . querySelectorAll ( 'pre:not([class="highlight"]):has(> code[class])' ) ;
214+ const codeBlocks = doc . querySelectorAll (
215+ 'pre:not([class="highlight"]):has(> code[class])'
216+ ) ;
231217 for ( const block of codeBlocks ) {
232218 const child = block . childNodes [ 0 ] ;
233219
@@ -243,24 +229,31 @@ function highlightCodeBlocks(data) {
243229 * and switch it back to `\n` for the code content after marked is through with it.
244230 * We only do this on the home/index page at the moment.
245231 */
246- const rawCodeBlockText = unescapeHTML ( child . innerText . trim ( ) . replace ( '<br>' , '\n' ) ) ;
232+ const rawCodeBlockText = unescapeHTML (
233+ child . innerText . trim ( ) . replace ( '<br>' , '\n' )
234+ ) ;
247235 const [ code , source , runInRepl ] = processRepl ( rawCodeBlockText ) ;
248236
249237 const lang = child . getAttribute ( 'class' ) . replace ( 'language-' , '' ) ;
250238
251239 Prism . languages [ lang ] == null
252240 ? console . warn ( `No Prism highlighter for language: ${ lang } ` )
253- : child . innerHTML = Prism . highlight ( code , Prism . languages [ lang ] , lang ) ;
241+ : ( child . innerHTML = Prism . highlight ( code , Prism . languages [ lang ] , lang ) ) ;
254242
255- block . insertAdjacentHTML ( 'beforebegin' , '<div class="highlight-container">' ) ;
243+ block . insertAdjacentHTML (
244+ 'beforebegin' ,
245+ '<div class="highlight-container">'
246+ ) ;
256247 const container = block . previousSibling ;
257248 container . appendChild ( block ) ;
258249 block . setAttribute ( 'class' , 'highlight' ) ;
259250
260251 if ( runInRepl ) {
261252 block . insertAdjacentHTML (
262253 'afterend' ,
263- `<a class="repl-link" href="/repl?code=${ encodeURIComponent ( textToBase64 ( source ) ) } ">
254+ `<a class="repl-link" href="/repl?code=${ encodeURIComponent (
255+ textToBase64 ( source )
256+ ) } ">
264257 Run in REPL
265258 </a>`
266259 ) ;
@@ -271,7 +264,6 @@ function highlightCodeBlocks(data) {
271264 return data ;
272265}
273266
274-
275267/**
276268 * Marked escapes HTML entities, which is normally great,
277269 * but we want to feed the raw code into Prism for highlighting.
@@ -280,12 +272,12 @@ function highlightCodeBlocks(data) {
280272 * @returns {string }
281273 */
282274function unescapeHTML ( str ) {
283- return str
284- . replace ( / & a m p ; / g, '&' )
285- . replace ( / & l t ; / g, '<' )
286- . replace ( / & g t ; / g, '>' )
287- . replace ( / & q u o t ; / g, '"' )
288- . replace ( / & # 3 9 ; / g, "'" ) ;
275+ return str
276+ . replace ( / & a m p ; / g, '&' )
277+ . replace ( / & l t ; / g, '<' )
278+ . replace ( / & g t ; / g, '>' )
279+ . replace ( / & q u o t ; / g, '"' )
280+ . replace ( / & # 3 9 ; / g, "'" ) ;
289281}
290282
291283/**
0 commit comments