Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6,172 changes: 3,903 additions & 2,269 deletions docs/docs-developers/docs/aztec-js/aztec_js_reference.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/docs-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ excalidraw
existant
explicity
faceid
fastforward
favo
FDIV
fdiv
Expand Down
15 changes: 11 additions & 4 deletions docs/scripts/aztecjs_reference_generation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,21 @@ The generated documentation follows this hierarchy:
```markdown
## Account # H2: Folder/Module
---
### File: `account/account.ts` # H3: File
### `account/account.ts` # H3: File
#### AccountContract # H4: Export (Class/Interface/Type)
**Type:** Class
##### constructor # H5: Member (Method/Property)
##### Methods # H5: Subsection
###### deploy # H6: Specific method
#### Methods # H4: Member group
##### createAuthWit # H5: Member (Method/Property/Getter)
```

Docusaurus derives a heading's anchor from every heading before it, so the table of contents can
only be written once the body is known. `transform_to_markdown.py` renders every heading through
`MarkdownGenerator.heading()`, which claims the anchor as the heading is emitted; one written as a
plain string instead would misdirect table of contents links rather than break them: the link still
resolves, just to the wrong section, so nothing downstream reports it. `generate()` re-reads the page
it just rendered and raises unless its headings are exactly the ones `heading()` emitted, so a
heading added any other way fails the build instead.

## Configuration

### Customization
Expand Down
48 changes: 43 additions & 5 deletions docs/scripts/aztecjs_reference_generation/parse_typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ const ts = require('typescript');
const fs = require('fs');
const path = require('path');

// readdirSync returns entries in filesystem order, and localeCompare depends on the runtime's
// locale data, so either one can order the reference differently on another machine. Comparing
// code units keeps the generated page identical everywhere the same sources are parsed.
const byName = (a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0);

// The reference documents aztec.js on its own, so the checker resolves relative imports only.
// Resolving @aztec/* would make every inferred return type depend on which sibling packages the
// environment has built, and a page generated against one build state silently differs from a page
// generated against another. Types that cross a package boundary have to be annotated in the source.
function relativeImportsOnlyHost(compilerOptions) {
const host = ts.createCompilerHost(compilerOptions, true);
host.resolveModuleNameLiterals = (literals, containingFile) =>
literals.map(literal =>
literal.text.startsWith('.')
? ts.resolveModuleName(literal.text, containingFile, compilerOptions, host)
: { resolvedModule: undefined }
);
return host;
}

/**
* JSDoc Validator - validates JSDoc completeness and correctness
*/
Expand Down Expand Up @@ -162,7 +182,10 @@ class TypeScriptParser {
constructor(sourcePath, options = {}) {
this.sourcePath = path.resolve(sourcePath);
this.options = {
excludeDirs: ['api', 'node_modules', '__tests__', 'test'],
// protocol_contracts is gitignored build output, generated from the compiled Noir protocol
// contracts. Documenting it would make this page unverifiable from a checkout and would tie
// it to noir-projects, so a Noir contract change would leave the committed page stale.
excludeDirs: ['api', 'node_modules', '__tests__', 'test', 'protocol_contracts'],
excludeFiles: ['.test.ts', '.test.tsx', 'index.ts'],
validate: false, // Enable validation
...options
Expand Down Expand Up @@ -227,7 +250,7 @@ class TypeScriptParser {
const entries = fs.readdirSync(dirPath, { withFileTypes: true });

// Get directories first
const dirs = entries.filter(e => e.isDirectory());
const dirs = entries.filter(e => e.isDirectory()).sort(byName);

for (const dir of dirs) {
const dirName = dir.name;
Expand Down Expand Up @@ -289,7 +312,7 @@ class TypeScriptParser {
}
}

return files.sort((a, b) => a.name.localeCompare(b.name));
return files.sort(byName);
}

/**
Expand Down Expand Up @@ -329,7 +352,7 @@ class TypeScriptParser {
}
}

program = ts.createProgram([filePath], compilerOptions);
program = ts.createProgram([filePath], compilerOptions, relativeImportsOnlyHost(compilerOptions));
this.typeChecker = program.getTypeChecker();
// Use the source file from the program (required for type checking)
sourceFile = program.getSourceFile(filePath);
Expand Down Expand Up @@ -589,7 +612,22 @@ class TypeScriptParser {
for (const element of node.exportClause.elements) {
const name = element.name.getText(sourceFile);
const isTypeOnly = element.isTypeOnly || node.isTypeOnly;
const moduleSpecifier = node.moduleSpecifier ? node.moduleSpecifier.getText(sourceFile).replace(/['"]/g, '') : '';

// `export { foo }` with no `from` publishes a local declaration rather than re-exporting
// one, so there is no source module to send a reader to. Documenting it as a re-export
// would name an empty module and claim a type of `Re-export`.
if (!node.moduleSpecifier) {
exports.push({
kind: isTypeOnly ? 'type' : 'const',
name: name,
signature: isTypeOnly ? `export type { ${name} }` : `export { ${name} }`,
jsdoc: { description: '', tags: [] },
type: '',
});
continue;
}

const moduleSpecifier = node.moduleSpecifier.getText(sourceFile).replace(/['"]/g, '');

// Create a simple re-export entry with improved documentation
const description = isTypeOnly
Expand Down
Loading
Loading