1- const fs = require ( 'fs' ) ;
1+ const fs = require ( 'fs' ) . promises ;
22const path = require ( 'path' ) ;
33const glob = require ( 'glob' ) ;
4- const { execSync } = require ( 'child_process ' ) ;
5-
4+ const util = require ( 'util ' ) ;
5+ const exec = util . promisify ( require ( 'child_process' ) . exec ) ;
66
77const SRC_DIR = './src' ;
88const BUILD_DIR = './build' ;
9-
10- // Temp dir will automatically be removed after markdown is generated
119const TEMP_DIR = path . join ( BUILD_DIR , 'temp' ) ;
1210const MD_FILES_DIR = path . join ( './docs' , 'API-Reference' ) ;
1311
12+ const globPromise = util . promisify ( glob ) ;
13+
1414/**
15- * Responsible to get the JS Files,
16- * that are to be included in API DOCS
17- * @returns {[] } list of JS Files that are to be included in API Docs
15+ * Responsible to get the JS Files that are to be included in API DOCS
16+ * @returns {Promise<string[]> } Promise resolving to list of JS Files for API Docs
1817 */
19- function getJsFiles ( ) {
20- // this gives all the JS Files, from src direcotry
21- const allJsFiles = glob . sync ( `${ SRC_DIR } /**/*.js` ) ;
22-
23- // those files that are to be included in API Docs
18+ async function getJsFiles ( ) {
19+ const allJsFiles = await globPromise ( `${ SRC_DIR } /**/*.js` ) ;
2420 const requiredJSfiles = [ ] ;
2521
26- for ( const file of allJsFiles ) {
27- // make sure it is a file, and not a dir
28- if ( fs . statSync ( file ) . isFile ( ) ) {
29- const content = fs . readFileSync ( file , 'utf-8' ) ;
30-
31- // we check for this line, as we only need
32- // those files that has this line.
22+ await Promise . all ( allJsFiles . map ( async ( file ) => {
23+ const stats = await fs . stat ( file ) ;
24+ if ( stats . isFile ( ) ) {
25+ const content = await fs . readFile ( file , 'utf-8' ) ;
3326 if ( content . includes ( '@INCLUDE_IN_API_DOCS' ) ) {
3427 requiredJSfiles . push ( file ) ;
3528 }
3629 }
37- }
30+ } ) ) ;
31+
3832 return requiredJSfiles ;
3933}
4034
4135/**
42- * responsible to create a directory
43- * @param {string path } dirPath creates dir at the given path
36+ * Creates a directory
37+ * @param {string } dirPath creates dir at the given path
4438 */
45- function createDir ( dirPath ) {
46- fs . mkdirSync ( dirPath , { recursive : true } ) ;
39+ async function createDir ( dirPath ) {
40+ await fs . mkdir ( dirPath , { recursive : true } ) ;
4741}
4842
4943/**
50- * responsible to delete a directory
51- * @param {string path } dirPath deletes dir from the given path
44+ * Deletes a directory
45+ * @param {string } dirPath deletes dir from the given path
5246 */
53- function removeDir ( dirPath ) {
54- fs . rmSync ( dirPath , { recursive : true , force : true } ) ;
47+ async function removeDir ( dirPath ) {
48+ await fs . rm ( dirPath , { recursive : true , force : true } ) ;
5549}
5650
5751/**
58- * This function adjusts JavaScript content
59- * to ensure compatibility with jsdoc-to-markdown.
60- * @param {string } content The content of the file, i.e. to be modified
52+ * Adjusts JavaScript content for compatibility with jsdoc-to-markdown
53+ * @param {string } content The content to be modified
6154 * @param {string } fileName To replace the define block with this name
6255 * @returns {string } Updated content
6356 */
6457function modifyJs ( content , fileName ) {
65-
66- // remove function wrapper
6758 if ( content . includes ( '\n(function () {' ) ) {
68-
69- content = content . replace (
70- / \( f u n c t i o n \( \) \{ / ,
71- ''
72- ) ;
73-
74- // Remove matching closing parentheses
59+ content = content . replace ( / \( f u n c t i o n \( \) \{ / , '' ) ;
7560 if ( content . trim ( ) . endsWith ( '}());' ) ) {
7661 content = content . trim ( ) . slice ( 0 , - 5 ) ;
7762 }
7863
79- // Clean up any leftover unmatched brackets
80- // removing `function wrapper` leads to an unmatched ' }' and ')'
81- // this logic just removes the unmatched brackets.
8264 let bracketCount = 0 ;
8365 for ( let indx = 0 ; indx < content . length ; indx ++ ) {
8466 if ( content [ indx ] === '{' ) {
@@ -90,48 +72,33 @@ function modifyJs(content, fileName) {
9072 while ( content [ indx ] && content [ indx ] !== ')' ) {
9173 indx -- ;
9274 }
93- content = content . slice ( 0 , indx )
94- + content . slice ( tempIndx + 1 ) ;
75+ content = content . slice ( 0 , indx ) + content . slice ( tempIndx + 1 ) ;
9576 bracketCount ++ ;
9677 break ;
9778 }
9879 }
9980 }
10081 } else if ( content . includes ( 'define(function' ) ) {
101-
102- // remove define blocks
103- content = content . replace (
104- / d e f i n e \( f u n c t i o n \s * \( [ ^ ) ] * \) \s * { / ,
105- ''
106- ) ;
107-
108- // remove trailing braces from define block
82+ content = content . replace ( / d e f i n e \( f u n c t i o n \s * \( [ ^ ) ] * \) \s * { / , '' ) ;
10983 if ( content . trim ( ) . endsWith ( '});' ) ) {
11084 content = content . trim ( ) . slice ( 0 , - 3 ) ;
11185 }
11286 }
113-
11487 return content ;
11588}
11689
117-
11890/**
119- * When generating markdown from JSDoc,
120- * some unwanted tags gets generated at the top of the MD file,
121- * we need to remove it, as it causes compatibility issues with docusaurus
122- * Also adds import statements at the top of every file
91+ * Modifies markdown content for compatibility with docusaurus
12392 * @param {string } content markdown file content
12493 * @param {string } relativePath Relative path of the file from MD_FILES_DIR
12594 * @returns {string } updated markdown file content
12695 */
12796function modifyMarkdown ( content , relativePath ) {
128- // to start the markdown from '<a' tag
12997 const anchorIndex = content . indexOf ( '<a name' ) ;
13098 if ( anchorIndex !== - 1 ) {
13199 content = content . slice ( anchorIndex ) ;
132100 }
133101
134- // Add the import statement
135102 const modulePath = path . join (
136103 path . dirname ( relativePath ) ,
137104 path . basename ( relativePath , '.md' )
@@ -141,66 +108,69 @@ function modifyMarkdown(content, relativePath) {
141108 `\`\`\`js\nconst ${ path . basename ( relativePath , '.md' ) } = ` +
142109 `brackets.getModule("${ modulePath } ")\n\`\`\`\n\n` ;
143110
144- content = content . replace ( / ~ / g, '.' ) ;
145-
146- // Combine the import statement with the modified content
147- return importStatement + content ;
111+ return importStatement + content . replace ( / ~ / g, '.' ) ;
148112}
149113
150-
151114/**
152115 * Generates markdown documentation for a given JavaScript file
153116 * @param {string } file Path to the JavaScript file
154117 * @param {string } relativePath Relative path of the file from SRC_DIR
155118 */
156- function generateMarkdown ( file , relativePath ) {
157- let content = fs . readFileSync ( file , 'utf-8' ) ;
119+ async function generateMarkdown ( file , relativePath ) {
120+ const content = await fs . readFile ( file , 'utf-8' ) ;
158121 const fileName = path . basename ( file , '.js' ) ;
159122
160- // update the JS file to make it compatible with JsDoc-to-MD library
161- content = modifyJs ( content , fileName ) ;
162- fs . writeFileSync ( file , content , 'utf-8' ) ;
123+ const modifiedContent = modifyJs ( content , fileName ) ;
124+ await fs . writeFile ( file , modifiedContent , 'utf-8' ) ;
163125
164- // generate the markdown on the required directory
165126 const outputDir = path . join ( MD_FILES_DIR , relativePath ) ;
166- createDir ( outputDir ) ;
127+ await createDir ( outputDir ) ;
128+
167129 const outputFileName = path . join ( outputDir , `${ fileName } .md` ) ;
168- execSync ( `npx jsdoc-to-markdown ${ file } > ${ outputFileName } ` ) ;
130+ await exec ( `npx jsdoc-to-markdown ${ file } > ${ outputFileName } ` ) ;
169131
170- // update the MD file to make it compatible with Docusaurus and add import statement
171- let markdownContent = fs . readFileSync ( outputFileName , 'utf-8' ) ;
132+ const markdownContent = await fs . readFile ( outputFileName , 'utf-8' ) ;
172133 const updatedMarkdownContent = modifyMarkdown ( markdownContent , path . join ( relativePath , fileName ) ) ;
173- fs . writeFileSync ( outputFileName , updatedMarkdownContent , 'utf-8' ) ;
134+ await fs . writeFile ( outputFileName , updatedMarkdownContent , 'utf-8' ) ;
174135}
175136
176-
177137/**
178138 * Handles the execution and control flow of the program
179139 */
180- function driver ( ) {
181- const jsFiles = getJsFiles ( ) ;
182- console . log ( "Fetched all required JS files" ) ;
183-
184- createDir ( TEMP_DIR ) ;
185- createDir ( MD_FILES_DIR ) ;
186-
187- for ( const file of jsFiles ) {
188- const relativePath = path . relative ( SRC_DIR , path . dirname ( file ) ) ;
189- const tempDirPath = path . join ( TEMP_DIR , relativePath ) ;
190- createDir ( tempDirPath ) ;
191-
192- // copy the file from src to temp dir for modifications
193- const fileName = path . basename ( file ) ;
194- const destPath = path . join ( tempDirPath , fileName ) ;
195- fs . copyFileSync ( file , destPath ) ;
140+ async function driver ( ) {
141+ try {
142+ console . log ( "Fetching required JS files..." ) ;
143+ const jsFiles = await getJsFiles ( ) ;
144+ console . log ( `Found ${ jsFiles . length } files to process` ) ;
145+
146+ await createDir ( TEMP_DIR ) ;
147+ await createDir ( MD_FILES_DIR ) ;
148+
149+ // Process files in batches to avoid overwhelming the system
150+ const BATCH_SIZE = 12 ;
151+ for ( let i = 0 ; i < jsFiles . length ; i += BATCH_SIZE ) {
152+ const batch = jsFiles . slice ( i , i + BATCH_SIZE ) ;
153+ await Promise . all ( batch . map ( async ( file ) => {
154+ const relativePath = path . relative ( SRC_DIR , path . dirname ( file ) ) ;
155+ const tempDirPath = path . join ( TEMP_DIR , relativePath ) ;
156+ await createDir ( tempDirPath ) ;
157+
158+ const fileName = path . basename ( file ) ;
159+ const destPath = path . join ( tempDirPath , fileName ) ;
160+ await fs . copyFile ( file , destPath ) ;
161+
162+ await generateMarkdown ( destPath , relativePath ) ;
163+ console . log ( `Processed ${ file } ` ) ;
164+ } ) ) ;
165+ }
196166
197- generateMarkdown ( destPath , relativePath ) ;
198- console . log ( `${ file } successfully converted to Markdown` ) ;
167+ await removeDir ( TEMP_DIR ) ;
168+ console . log ( "All files processed successfully!" ) ;
169+ } catch ( error ) {
170+ console . error ( "An error occurred:" , error ) ;
171+ // Cleanup temp directory in case of error
172+ await removeDir ( TEMP_DIR ) . catch ( ( ) => { } ) ;
199173 }
200-
201- removeDir ( TEMP_DIR ) ;
202-
203- console . log ( "All set!!!" ) ;
204174}
205175
206- driver ( ) ;
176+ driver ( ) . catch ( console . error ) ;
0 commit comments