@@ -3,63 +3,72 @@ import type {TemplateRenderer} from "./template.js";
33
44const mi = MarkdownIt ( { html : true , linkify : true , typographer : true } ) ;
55
6- export const md : TemplateRenderer & { document ?: Document } = ( template , ...values ) => {
7- const { document = window . document } = md ;
8- let source = template [ 0 ] ;
9- let fragment : DocumentFragment | null = null ;
10- let partIndex = - 1 ;
11- const parts : Node [ ] = [ ] ;
6+ export function MarkdownRenderer ( {
7+ document = window . document
8+ } : {
9+ document ?: Document ;
10+ } = { } ) : TemplateRenderer < HTMLElement > {
11+ return function ( template , ...values ) {
12+ let source = template [ 0 ] ;
13+ let fragment : DocumentFragment | null = null ;
14+ let partIndex = - 1 ;
15+ const parts : Node [ ] = [ ] ;
1216
13- // Concatenate the text using comments as placeholders.
14- for ( let i = 0 , n = values . length ; i < n ; ++ i ) {
15- const value = values [ i ] ;
16- if ( value instanceof Node ) {
17- parts [ ++ partIndex ] = value ;
18- source += `<!--o:${ partIndex } -->` ;
19- } else if ( Array . isArray ( value ) ) {
20- for ( const node of value ) {
21- if ( node instanceof Node ) {
22- if ( fragment === null ) {
23- parts [ ++ partIndex ] = fragment = document . createDocumentFragment ( ) ;
24- source += `<!--o:${ partIndex } -->` ;
17+ // Concatenate the text using comments as placeholders.
18+ for ( let i = 0 , n = values . length ; i < n ; ++ i ) {
19+ const value = values [ i ] ;
20+ if ( value instanceof Node ) {
21+ parts [ ++ partIndex ] = value ;
22+ source += `<!--o:${ partIndex } -->` ;
23+ } else if ( Array . isArray ( value ) ) {
24+ for ( const node of value ) {
25+ if ( node instanceof Node ) {
26+ if ( fragment === null ) {
27+ parts [ ++ partIndex ] = fragment = document . createDocumentFragment ( ) ;
28+ source += `<!--o:${ partIndex } -->` ;
29+ }
30+ fragment . appendChild ( node ) ;
31+ } else {
32+ fragment = null ;
33+ source += node ;
2534 }
26- fragment . appendChild ( node ) ;
27- } else {
28- fragment = null ;
29- source += node ;
3035 }
36+ fragment = null ;
37+ } else {
38+ source += value ;
3139 }
32- fragment = null ;
33- } else {
34- source += value ;
40+ source += template [ i + 1 ] ;
3541 }
36- source += template [ i + 1 ] ;
37- }
3842
39- // Render the text.
40- const root = document . createElement ( "div" ) ;
41- root . innerHTML = mi . render ( source ) ;
43+ // Render the text.
44+ const root = document . createElement ( "div" ) ;
45+ root . innerHTML = mi . render ( source ) ;
4246
43- // Walk the rendered content to replace comment placeholders.
44- if ( ++ partIndex > 0 ) {
45- const nodes = new Array < Comment > ( partIndex ) ;
46- const walker = document . createTreeWalker ( root , NodeFilter . SHOW_COMMENT , null ) ;
47- while ( walker . nextNode ( ) ) {
48- const node = walker . currentNode as Comment ;
49- if ( / ^ o : \d + $ / . test ( node . nodeValue ! ) ) {
50- nodes [ + node . nodeValue ! . slice ( 2 ) ] = node ;
47+ // Walk the rendered content to replace comment placeholders.
48+ if ( ++ partIndex > 0 ) {
49+ const nodes = new Array < Comment > ( partIndex ) ;
50+ const walker = document . createTreeWalker ( root , NodeFilter . SHOW_COMMENT , null ) ;
51+ while ( walker . nextNode ( ) ) {
52+ const node = walker . currentNode as Comment ;
53+ if ( / ^ o : \d + $ / . test ( node . nodeValue ! ) ) {
54+ nodes [ + node . nodeValue ! . slice ( 2 ) ] = node ;
55+ }
56+ }
57+ for ( let i = 0 ; i < partIndex ; ++ i ) {
58+ const node = nodes [ i ] ;
59+ node . parentNode ?. replaceChild ( parts [ i ] , node ) ;
5160 }
5261 }
53- for ( let i = 0 ; i < partIndex ; ++ i ) {
54- const node = nodes [ i ] ;
55- node . parentNode ?. replaceChild ( parts [ i ] , node ) ;
56- }
57- }
5862
59- const codes = root . querySelectorAll < HTMLElement > ( "code[class^=language-]" ) ;
60- if ( codes . length > 0 ) {
61- import ( "./highlight.js" ) . then ( ( { highlight} ) => codes . forEach ( highlight ) ) ;
62- }
63+ return root ;
64+ } ;
65+ }
66+
67+ let renderer : TemplateRenderer < HTMLElement > | undefined ;
6368
69+ export const md : TemplateRenderer = ( template , ...values ) => {
70+ const root = ( renderer ??= MarkdownRenderer ( ) ) ( template , ...values ) ;
71+ const codes = root . querySelectorAll < HTMLElement > ( "code[class^=language-]" ) ;
72+ if ( codes . length > 0 ) import ( "./highlight.js" ) . then ( ( { highlight} ) => codes . forEach ( highlight ) ) ;
6473 return root . childNodes . length === 1 ? root . removeChild ( root . firstChild ! ) : root ;
6574} ;
0 commit comments