1- import {
2- Root ,
3- Paragraph ,
4- RootContent ,
5- RootContentMap ,
6- InlineCode ,
7- Code ,
8- } from "mdast" ;
91import { ILoader } from "../_types" ;
102import { createLoader } from "../_utils" ;
113import { PlaceholderedMdx , RawMdx } from "./_types" ;
12- import { traverseMdast } from "./_utils" ;
134import { md5 } from "../../utils/md5" ;
145import { unified } from "unified" ;
156import remarkParse from "remark-parse" ;
@@ -35,63 +26,19 @@ function extractCodePlaceholders(content: string): {
3526 content : string ;
3627 codePlaceholders : Record < string , string > ;
3728} {
38- let shouldSearchForPlaceholders = true ;
3929 let finalContent = content ;
4030 const codePlaceholders : Record < string , string > = { } ;
4131
42- while ( shouldSearchForPlaceholders ) {
43- const ast = parseMdast ( finalContent ) ;
32+ const codeBlockRegex = / ^ ` ` ` . * \n ( [ \s \S ] * ? ) ^ ` ` ` $ / gm ;
33+ const codeBlockMatches = finalContent . matchAll ( codeBlockRegex ) ;
4434
45- traverseMdast ( ast , ( _node ) => {
46- shouldSearchForPlaceholders = false ;
35+ for ( const match of codeBlockMatches ) {
36+ const codeBlock = match [ 0 ] ;
37+ const codeBlockHash = md5 ( codeBlock ) ;
38+ const placeholderId = `---CODE_PLACEHOLDER_${ codeBlockHash } ---` ;
4739
48- if ( _node . type === "code" ) {
49- const node = _node as Code ;
50-
51- const nodeContentStartLine = node . position ?. start . line ;
52- const nodeContentEndLine = node . position ?. end . line ;
53-
54- if ( ! nodeContentStartLine || ! nodeContentEndLine ) {
55- return ;
56- }
57-
58- const nodeContentPreStartLine = nodeContentStartLine - 1 ;
59- const nodeContentPostEndLine = nodeContentEndLine + 1 ;
60-
61- const nodeContent = finalContent
62- . split ( "\n" )
63- . slice ( nodeContentPreStartLine , nodeContentPostEndLine )
64- . join ( "\n" ) ;
65-
66- const nodeContentHash = md5 ( nodeContent ) ;
67- const placeholderId = `__PLACEHOLDER_${ nodeContentHash } __` ;
68-
69- codePlaceholders [ placeholderId ] = nodeContent ;
70- finalContent = finalContent . replace ( nodeContent , placeholderId ) ;
71- shouldSearchForPlaceholders = true ;
72- } else if ( _node . type === "inlineCode" ) {
73- const node = _node as InlineCode ;
74-
75- const nodeContentStartIndex = node . position ?. start . offset ;
76- const nodeContentEndIndex = node . position ?. end . offset ;
77-
78- if ( ! nodeContentStartIndex || ! nodeContentEndIndex ) {
79- return ;
80- }
81-
82- const nodeContent = finalContent . slice (
83- nodeContentStartIndex ,
84- nodeContentEndIndex ,
85- ) ;
86-
87- const nodeContentHash = md5 ( nodeContent ) ;
88- const placeholderId = `__PLACEHOLDER_${ nodeContentHash } __` ;
89-
90- codePlaceholders [ placeholderId ] = nodeContent ;
91- finalContent = finalContent . replace ( nodeContent , placeholderId ) ;
92- shouldSearchForPlaceholders = true ;
93- }
94- } ) ;
40+ codePlaceholders [ placeholderId ] = codeBlock ;
41+ finalContent = finalContent . replace ( codeBlock , placeholderId ) ;
9542 }
9643
9744 return {
@@ -101,49 +48,25 @@ function extractCodePlaceholders(content: string): {
10148}
10249
10350export default function createMdxCodePlaceholderLoader ( ) : ILoader <
104- RawMdx ,
105- PlaceholderedMdx
51+ string ,
52+ string
10653> {
10754 return createLoader ( {
10855 async pull ( locale , input ) {
109- const { frontmatter = { } , content = "" } = input || {
110- frontmatter : { } ,
111- content : "" ,
112- } ;
113-
114- const { content : resultContent , codePlaceholders } =
115- extractCodePlaceholders ( content ) ;
116-
117- return {
118- frontmatter,
119- content : resultContent ,
120- codePlaceholders,
121- } ;
56+ const response = extractCodePlaceholders ( input ) ;
57+ return response . content ;
12258 } ,
12359
12460 async push ( locale , data , originalInput ) {
125- // Re-create the placeholders map from the original (unmodified) input so we
126- // can rely on a stable mapping even if `data.codePlaceholders` was lost or
127- // tampered with by other loaders in the chain.
128- const { codePlaceholders } = extractCodePlaceholders (
129- originalInput ?. content ?? "" ,
130- ) ;
61+ const response = extractCodePlaceholders ( originalInput ?? "" ) ;
13162
132- let finalContent = data . content ;
133- // Restore code from placeholders
134- for ( const [ placeholder , original ] of Object . entries ( codePlaceholders ) ) {
135- // Use String.replaceAll with a replacer function to restore the original code.
136- // A replacer function is used to avoid any special replacement pattern
137- // interpretation (e.g. "$&", "$$", etc.) that could occur if `original`
138- // contains `$` characters.
139- finalContent = finalContent . replaceAll ( placeholder , ( ) => original ) ;
63+ let result = data ;
64+ for ( const [ placeholder , original ] of Object . entries (
65+ response . codePlaceholders ,
66+ ) ) {
67+ result = result . replaceAll ( placeholder , original ) ;
14068 }
14169
142- const result : RawMdx = {
143- frontmatter : data . frontmatter ,
144- content : finalContent ,
145- } ;
146-
14770 return result ;
14871 } ,
14972 } ) ;
0 commit comments