Skip to content

Commit

Permalink
docs: bump typedoc to 0.26.4 (#9727)
Browse files Browse the repository at this point in the history
closes: #9681
refs: #9729

## Description

- Updates typedoc to latest version
- Adds script to rewrite `/functions` path to `/funcs` to avoid cloudflare/workers-sdk#2240
   - includes renaming files, anchor links in html files, and a base64 encoded navigation state object in a js file

### Security Considerations
n/a

### Scaling Considerations
n/a

### Documentation Considerations
n/a

### Testing Considerations
CI and manual QA

### Upgrade Considerations
n/a
  • Loading branch information
mergify[bot] authored Aug 8, 2024
2 parents e141f05 + 4037399 commit e8c4189
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 46 deletions.
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"prettier-plugin-jsdoc": "^1.3.0",
"prettier-plugin-sh": "^0.14.0",
"type-coverage": "^2.27.1",
"typedoc": "^0.25.13",
"typedoc-plugin-markdown": "^3.17.1",
"typedoc": "^0.26.4",
"typedoc-plugin-markdown": "^4.2.1",
"typescript": "^5.5.3",
"typescript-eslint": "^7.15.0"
},
Expand All @@ -48,8 +48,11 @@
"scripts": {
"clean": "yarn lerna run --no-bail clean",
"check-dependencies": "node ./scripts/check-mismatched-dependencies.cjs",
"docs": "typedoc --tsconfig tsconfig.build.json",
"docs:markdown-for-agoric-documentation-repo": "typedoc --plugin typedoc-plugin-markdown --tsconfig tsconfig.build.json",
"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 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",
"link-cli": "yarn run create-agoric-cli",
"create-agoric-cli": "node ./scripts/create-agoric-cli.cjs",
Expand Down
210 changes: 210 additions & 0 deletions scripts/update-typedoc-functions-path.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#!/usr/bin/env node

/**
* Help us workaround a limitation in Cloudflare Pages that prevents us from
* publishing static files to a top-level `/functions` directory. (Cloudflare
* reserves this namespace for Worker Functions as of
* https://github.com/cloudflare/workers-sdk/pull/2103).
*
* This script -
* 1. renames `/functions` directory to `/function`
* 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.
*
* See https://github.com/Agoric/agoric-sdk/issues/9729 for tracking of the
* issue in this project. If a different solution is arrived at, we can remove
* this file and the accompanying `yarn docs:update-functions-path`.
*/

const fsp = require('fs').promises;
const path = require('path');
const zlib = require('zlib');
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) {
return new Promise((resolve, reject) => {
const base64Data = encodedData.replace(
/^data:application\/octet-stream;base64,/,
'',
);
const buffer = Buffer.from(base64Data, 'base64');

zlib.gunzip(buffer, (err, decompressed) => {
if (err) {
reject(new Error(`Failed to decompress data: ${err.message}`));
return;
}

try {
const jsonData = JSON.parse(decompressed.toString('utf-8'));
resolve(jsonData);
} catch (parseError) {
reject(new Error(`Failed to parse JSON: ${parseError.message}`));
}
});
});
}

// Compresses and encodes the TypeDoc navigation data
function encodeTypeDocNavigation(jsonData) {
return new Promise((resolve, reject) => {
const jsonString = JSON.stringify(jsonData);

zlib.gzip(jsonString, (err, compressed) => {
if (err) {
reject(new Error(`Failed to compress data: ${err.message}`));
return;
}

const base64Data = compressed.toString('base64');
resolve(`data:application/octet-stream;base64,${base64Data}`);
});
});
}

// Recursively updates URLs in the navigation data
function updateUrls(data, searchString, replaceString) {
if (typeof data === 'object' && data !== null) {
for (const key in data) {
if (
typeof data[key] === 'string' &&
data[key].includes(`${searchString}/`)
) {
data[key] = data[key].replace(
new RegExp(`${searchString}/`, 'g'),
`${replaceString}/`,
);
} else if (typeof data[key] === 'object') {
updateUrls(data[key], searchString, replaceString);
}
}
}
return data;
}

// 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()) {
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 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}/`,
)
);
}

/**
* 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}/`,
);
}

/**
* 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".');
}
}

main().catch(e => {
console.error(`Error: ${e.message}`);
process.exit(1);
});
Loading

0 comments on commit e8c4189

Please sign in to comment.