diff --git a/package.json b/package.json index 4dda7d51248e..d964835cf104 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "check-dependencies": "node ./scripts/check-mismatched-dependencies.cjs", "docs": "run-s docs:build docs:update-functions-path", "docs:build": "typedoc --tsconfig tsconfig.build.json", - "docs:markdown-for-agoric-documentation-repo": "run-s docs:markdown-build docs:update-functions-path", + "docs:markdown-for-agoric-documentation-repo": "run-s docs:markdown-build 'docs:update-functions-path md'", "docs:markdown-build": "typedoc --plugin typedoc-plugin-markdown --tsconfig tsconfig.build.json", "docs:update-functions-path": "node ./scripts/update-typedoc-functions-path.cjs", "lerna": "lerna", diff --git a/scripts/update-typedoc-functions-path.cjs b/scripts/update-typedoc-functions-path.cjs index 7804889a0e82..734df479437f 100644 --- a/scripts/update-typedoc-functions-path.cjs +++ b/scripts/update-typedoc-functions-path.cjs @@ -11,6 +11,9 @@ * 2. updates generated urls in html files to reference new url path * 3. updates base64 encoded navigation state to reference new url path * + * If an `md` argument is supplied - versus the optional default `html` document - + * a different set of logic will run to update paths are links for markdown files. + * * See https://github.com/TypeStrong/typedoc/issues/2111 for more solutions * on how to workaround this. * @@ -22,15 +25,20 @@ const fsp = require('fs').promises; const path = require('path'); const zlib = require('zlib'); - -const navigationFilePath = path.join( - __dirname, - '..', - 'api-docs', - 'assets', - 'navigation.js', -); -const apiDocsDir = path.join(__dirname, '..', 'api-docs'); +const process = require('process'); + +const config = { + oldDirName: 'functions', + newDirName: 'funcs', + apiDocsDir: path.join(__dirname, '..', 'api-docs'), + navigationFilePath: path.join( + __dirname, + '..', + 'api-docs', + 'assets', + 'navigation.js', + ), +}; // Decodes and decompresses the TypeDoc navigation data function decodeTypeDocNavigation(encodedData) { @@ -94,64 +102,109 @@ function updateUrls(data, searchString, replaceString) { return data; } -// Updates href links in HTML files -async function updateHtmlFiles(dir, searchString, replaceString) { +// Updates js-based navigation state +async function updateNavigationFile() { + const fileContent = await fsp.readFile(config.navigationFilePath, 'utf8'); + const match = fileContent.match(/window\.navigationData = "(.*?)"/); + if (!match) { + throw new Error('Navigation data not found in file'); + } + const encodedData = match[1]; + + const decodedData = await decodeTypeDocNavigation(encodedData); + const updatedData = updateUrls( + decodedData, + config.oldDirName, + config.newDirName, + ); + const newEncodedData = await encodeTypeDocNavigation(updatedData); + const newFileContent = `window.navigationData = "${newEncodedData}"`; + await fsp.writeFile(config.navigationFilePath, newFileContent); + console.log('Navigation file updated successfully'); +} + +/** + * Updates files in a directory + * @param {string} dir - Directory to update + * @param {string} fileExtension - File extension to process + * @param {Function} updateFunction - Function to update file content + */ +async function updateFiles(dir, fileExtension, updateFunction) { const files = await fsp.readdir(dir); for (const file of files) { const filePath = path.join(dir, file); const stat = await fsp.stat(filePath); if (stat.isDirectory()) { - await updateHtmlFiles(filePath, searchString, replaceString); - } else if (path.extname(file) === '.html') { - let content = await fsp.readFile(filePath, 'utf8'); - if (content.includes(`/${searchString}/`)) { - content = content.replace( - new RegExp(`/${searchString}/`, 'g'), - `/${replaceString}/`, - ); - await fsp.writeFile(filePath, content); + if (file === config.oldDirName) { + const newPath = path.join(dir, config.newDirName); + await fsp.rename(filePath, newPath); + console.log(`Renamed directory: ${filePath} to ${newPath}`); + await updateFiles(newPath, fileExtension, updateFunction); + } else { + await updateFiles(filePath, fileExtension, updateFunction); + } + } else if (path.extname(file) === fileExtension) { + const content = await fsp.readFile(filePath, 'utf8'); + const updatedContent = updateFunction(content); + if (content !== updatedContent) { + await fsp.writeFile(filePath, updatedContent); console.log(`Updated: ${filePath}`); } } } } -// Updates the navigation file and HTML files in the api-docs directory -// replacing /function file names and url references with /funcs -async function updateNavigationAndHtmlFiles( - searchString = 'functions', - replaceString = 'funcs', -) { - await null; - try { - // Rename the directory - const oldDirPath = path.join(apiDocsDir, searchString); - const newDirPath = path.join(apiDocsDir, replaceString); - await fsp.rename(oldDirPath, newDirPath); - console.log(`Directory renamed from ${searchString} to ${replaceString}`); - - // Update navigation file - const fileContent = await fsp.readFile(navigationFilePath, 'utf8'); - const match = fileContent.match(/window\.navigationData = "(.*?)"/); - if (!match) { - throw new Error('Navigation data not found in file'); - } - const encodedData = match[1]; - - const decodedData = await decodeTypeDocNavigation(encodedData); - const updatedData = updateUrls(decodedData, searchString, replaceString); - const newEncodedData = await encodeTypeDocNavigation(updatedData); - const newFileContent = `window.navigationData = "${newEncodedData}"`; - await fsp.writeFile(navigationFilePath, newFileContent); +/** + * Updates content in Markdown files + * @param {string} content - The Markdown content to update + * @returns {string} - The updated Markdown content + */ +function updateMarkdownContentLinks(content) { + return ( + content + // Update links like [text](functions/file.md) + .replace( + new RegExp(`\\[(.*?)\\]\\(${config.oldDirName}/`, 'g'), + `[$1](${config.newDirName}/`, + ) + // Update links like [text](../functions/file.md) + .replace( + new RegExp(`\\[(.*?)\\]\\(\\.\\./${config.oldDirName}/`, 'g'), + `[$1](../${config.newDirName}/`, + ) + ); +} - console.log('Navigation file updated successfully'); +/** + * Updates content in HTML files + * @param {string} content - The HTML content to update + * @returns {string} - The updated HTML content + */ +function updateHtmlContentLinks(content) { + return content.replace( + new RegExp(`/${config.oldDirName}/`, 'g'), + `/${config.newDirName}/`, + ); +} - // Update HTML files - await updateHtmlFiles(apiDocsDir, searchString, replaceString); - console.log('HTML files updated successfully'); - } catch (error) { - console.error('Error updating files:', error); +/** + * Main function to run the script + */ +async function main() { + const fileType = process.argv[2] || 'html'; + await null; + switch (fileType) { + case 'html': + await updateFiles(config.apiDocsDir, '.html', updateHtmlContentLinks); + return updateNavigationFile(); + case 'md': + return updateFiles(config.apiDocsDir, '.md', updateMarkdownContentLinks); + default: + throw new Error('Invalid file type. Use "html" or "md".'); } } -updateNavigationAndHtmlFiles().catch(e => console.error(e)); +main().catch(e => { + console.error(`Error: ${e.message}`); + process.exit(1); +});