11#!/usr/bin/env node
22
33const fs = require ( "fs" ) . promises ;
4+ const fsSync = require ( "fs" ) ;
45const path = require ( "path" ) ;
56const { execSync } = require ( "child_process" ) ;
67const { glob } = require ( "glob" ) ;
@@ -61,7 +62,7 @@ async function convertAdocFiles(directory) {
6162 await fs . writeFile ( tempFile , content , "utf8" ) ;
6263
6364 // Run downdoc
64- execSync ( `bunx downdoc "${ tempFile } "` , { stdio : "pipe" } ) ;
65+ execSync ( `pnpm dlx downdoc "${ tempFile } "` , { stdio : "pipe" } ) ;
6566
6667 // Find the generated .md file
6768 const tempMdFile = path . join ( dir , `temp_${ filename } .md` ) ;
@@ -91,70 +92,67 @@ async function convertAdocFiles(directory) {
9192 // Fix xref: links - remove xref: and convert .adoc to .mdx
9293 mdContent = mdContent . replace (
9394 / x r e f : \[ ( [ ^ \] ] + ) \] \( ( [ ^ ) ] + ) \) / g,
94- "[$1]($2)"
95+ "[$1]($2)" ,
9596 ) ;
9697
9798 // Fix .adoc internal links to .mdx
9899 mdContent = mdContent . replace (
99100 / \] \( ( [ ^ ) ] + ) \. a d o c ( [ ^ ) ] * ) \) / g,
100- "]($1.mdx$2)"
101+ "]($1.mdx$2)" ,
101102 ) ;
102103
103104 // Fix curly bracket file references {filename} -> filename
104- mdContent = mdContent . replace (
105- / \{ ( [ ^ } ] + ) \} / g,
106- "$1"
107- ) ;
105+ mdContent = mdContent . replace ( / \{ ( [ ^ } ] + ) \} / g, "$1" ) ;
108106
109107 // Fix HTML-style callouts <dl><dt><strong>📌 NOTE</strong></dt><dd> ... </dd></dl>
110108 // Handle multi-line callouts by using a more permissive pattern
111109 mdContent = mdContent . replace (
112- / < d l > < d t > < s t r o n g > [ 📌 🔔 ℹ ️ ] \s * ( N O T E | T I P | I N F O ) < \/ s t r o n g > < \/ d t > < d d > ( [ \s \S ] * ?) < \/ d d > < \/ d l > / g ,
113- "<Callout>\n$2\n</Callout>"
110+ / < d l > < d t > < s t r o n g > [ 📌 🔔 ℹ ️ ] \s * ( N O T E | T I P | I N F O ) < \/ s t r o n g > < \/ d t > < d d > ( [ \s \S ] * ?) < \/ d d > < \/ d l > / gu ,
111+ "<Callout>\n$2\n</Callout>" ,
114112 ) ;
115113
116114 mdContent = mdContent . replace (
117115 / < d l > < d t > < s t r o n g > [ ⚠ ️ 🚨 ❗ ] \s * ( W A R N I N G | I M P O R T A N T | C A U T I O N | D A N G E R ) < \/ s t r o n g > < \/ d t > < d d > ( [ \s \S ] * ?) < \/ d d > < \/ d l > / g,
118- "<Callout type='warn'>\n$2\n</Callout>"
116+ "<Callout type='warn'>\n$2\n</Callout>" ,
119117 ) ;
120118
121119 // Handle cases where </dd></dl> might be missing or malformed
122120 mdContent = mdContent . replace (
123- / < d l > < d t > < s t r o n g > [ 📌 🔔 ℹ ️ ] \s * ( N O T E | T I P | I N F O ) < \/ s t r o n g > < \/ d t > < d d > ( [ \s \S ] * ?) (? = \n \n | < d l > | $ ) / g ,
124- "<Callout>\n$2\n</Callout>"
121+ / < d l > < d t > < s t r o n g > [ 📌 🔔 ℹ ️ ] \s * ( N O T E | T I P | I N F O ) < \/ s t r o n g > < \/ d t > < d d > ( [ \s \S ] * ?) (? = \n \n | < d l > | $ ) / gu ,
122+ "<Callout>\n$2\n</Callout>" ,
125123 ) ;
126124
127125 mdContent = mdContent . replace (
128126 / < d l > < d t > < s t r o n g > [ ⚠ ️ 🚨 ❗ ] \s * ( W A R N I N G | I M P O R T A N T | C A U T I O N | D A N G E R ) < \/ s t r o n g > < \/ d t > < d d > ( [ \s \S ] * ?) (? = \n \n | < d l > | $ ) / g,
129- "<Callout type='warn'>\n$2\n</Callout>"
127+ "<Callout type='warn'>\n$2\n</Callout>" ,
130128 ) ;
131129
132130 // Fix xref patterns with complex anchors like xref:#ISRC6-\\__execute__[...]
133131 mdContent = mdContent . replace (
134132 / x r e f : # ( [ ^ [ \] ] + ) \[ ( [ ^ \] ] + ) \] / g,
135- "[$2](#$1)"
133+ "[$2](#$1)" ,
136134 ) ;
137135
138136 // Fix simple xref patterns
139- mdContent = mdContent . replace (
140- / x r e f : ( [ ^ [ \s ] + ) \[ ( [ ^ \] ] + ) \] / g,
141- "[$2]($1)"
142- ) ;
137+ mdContent = mdContent . replace ( / x r e f : ( [ ^ [ \s ] + ) \[ ( [ ^ \] ] + ) \] / g, "[$2]($1)" ) ;
143138
144139 // Clean up orphaned HTML tags from malformed callouts
145140 // Handle orphaned <dl><dt><strong>EMOJI TYPE</strong></dt><dd> without closing tags
146141 mdContent = mdContent . replace (
147- / < d l > < d t > < s t r o n g > [ 📌 🔔 ℹ ️ ] \s * ( N O T E | T I P | I N F O ) < \/ s t r o n g > < \/ d t > < d d > \s * \n ( [ \s \S ] * ?) (? = \n \n | < d l > | $ ) / g ,
148- "<Callout>\n$2\n</Callout>"
142+ / < d l > < d t > < s t r o n g > [ 📌 🔔 ℹ ️ ] \s * ( N O T E | T I P | I N F O ) < \/ s t r o n g > < \/ d t > < d d > \s * \n ( [ \s \S ] * ?) (? = \n \n | < d l > | $ ) / gu ,
143+ "<Callout>\n$2\n</Callout>" ,
149144 ) ;
150145
151146 mdContent = mdContent . replace (
152147 / < d l > < d t > < s t r o n g > [ ⚠ ️ 🚨 ❗ ] \s * ( W A R N I N G | I M P O R T A N T | C A U T I O N | D A N G E R ) < \/ s t r o n g > < \/ d t > < d d > \s * \n ( [ \s \S ] * ?) (? = \n \n | < d l > | $ ) / g,
153- "<Callout type='warn'>\n$2\n</Callout>"
148+ "<Callout type='warn'>\n$2\n</Callout>" ,
154149 ) ;
155150
156151 // Clean up any remaining orphaned HTML tags
157- mdContent = mdContent . replace ( / < d l > < d t > < s t r o n g > .* ?< \/ s t r o n g > < \/ d t > < d d > / g, "" ) ;
152+ mdContent = mdContent . replace (
153+ / < d l > < d t > < s t r o n g > .* ?< \/ s t r o n g > < \/ d t > < d d > / g,
154+ "" ,
155+ ) ;
158156 mdContent = mdContent . replace ( / < \/ d d > < \/ d l > / g, "" ) ;
159157 mdContent = mdContent . replace ( / < d d > / g, "" ) ;
160158 mdContent = mdContent . replace ( / < \/ d d > / g, "" ) ;
@@ -172,12 +170,13 @@ async function convertAdocFiles(directory) {
172170 const title = headerMatch ? headerMatch [ 1 ] . trim ( ) : filename ;
173171
174172 // Remove the first H1 from content
175- const contentWithoutFirstH1 = mdContent . replace ( / ^ # + \s + .+ $ / m, '' ) . replace ( / ^ \n + / , '' ) ;
173+ const contentWithoutFirstH1 = mdContent
174+ . replace ( / ^ # + \s + .+ $ / m, "" )
175+ . replace ( / ^ \n + / , "" ) ;
176176
177177 // Create MDX with frontmatter
178178 const mdxContent = `---
179179title: ${ title }
180- description: ${ title }
181180---
182181
183182${ contentWithoutFirstH1 } `;
@@ -196,5 +195,43 @@ ${contentWithoutFirstH1}`;
196195 }
197196}
198197
198+ // Process files to remove curly brackets after conversion
199+ function processFile ( filePath ) {
200+ try {
201+ const content = fsSync . readFileSync ( filePath , "utf8" ) ;
202+ // Preserve brackets inside code fences (```...```)
203+ const modifiedContent = content . replace ( / ` ` ` [ \s \S ] * ?` ` ` | [ { } ] / g, ( match ) => {
204+ // If match contains newlines or starts with ```, it's a code block - preserve it
205+ return match . includes ( "\n" ) || match . startsWith ( "```" ) ? match : "" ;
206+ } ) ;
207+ fsSync . writeFileSync ( filePath , modifiedContent , "utf8" ) ;
208+ console . log ( `Processed: ${ filePath } ` ) ;
209+ } catch ( error ) {
210+ console . error ( `Error processing ${ filePath } : ${ error . message } ` ) ;
211+ }
212+ }
213+
214+ function crawlDirectory ( dirPath ) {
215+ try {
216+ const items = fsSync . readdirSync ( dirPath ) ;
217+
218+ for ( const item of items ) {
219+ const itemPath = path . join ( dirPath , item ) ;
220+ const stats = fsSync . statSync ( itemPath ) ;
221+
222+ if ( stats . isDirectory ( ) ) {
223+ crawlDirectory ( itemPath ) ;
224+ } else if ( stats . isFile ( ) ) {
225+ processFile ( itemPath ) ;
226+ }
227+ }
228+ } catch ( error ) {
229+ console . error ( `Error crawling directory ${ dirPath } : ${ error . message } ` ) ;
230+ }
231+ }
232+
199233const directory = process . argv [ 2 ] ;
200234convertAdocFiles ( directory ) . catch ( console . error ) ;
235+
236+ // Run bracket processing after conversion
237+ crawlDirectory ( directory ) ;
0 commit comments