Skip to content
Draft
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
1,798 changes: 1,096 additions & 702 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
"recma-jsx": "^1.0.1",
"rehype-raw": "^7.0.0",
"rehype-recma": "^1.0.0",
"json-schema-to-typescript": "^15.0.4",
"jsonc-parser": "^3.3.1",
"rehype-stringify": "^10.0.1",
"remark-gfm": "^4.0.1",
"remark-parse": "^11.0.0",
Expand Down
6 changes: 6 additions & 0 deletions src/generators/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import manPage from './man-page/index.mjs';
import metadata from './metadata/index.mjs';
import oramaDb from './orama-db/index.mjs';
import web from './web/index.mjs';
import json from './json/index.mjs';
import jsonAll from './json-all/index.mjs';

export const publicGenerators = {
'json-simple': jsonSimple,
Expand All @@ -27,6 +29,10 @@ export const publicGenerators = {
'orama-db': oramaDb,
'llms-txt': llmsTxt,
web,
'jsx-ast': jsxAst,
metadata,
json,
'json-all': jsonAll,
};

// These ones are special since they don't produce standard output,
Expand Down
17 changes: 17 additions & 0 deletions src/generators/json-all/__tests__/version.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

import test from 'node:test';
import assert from 'node:assert';
import jsonAll from '../../json-all/index.mjs';
import json from '../index.mjs';
import { generateJsonSchema } from '../util/generateJsonSchema.mjs';

test('json-all generator matches json generator version match', () => {
assert.strictEqual(jsonAll.version, json.version);
});

test('schema version matches generator version', () => {
const schema = generateJsonSchema();

assert.strictEqual(schema.$id, `nodejs-api-doc-all@v${jsonAll.version}`);

Check failure on line 16 in src/generators/json-all/__tests__/version.test.mjs

View workflow job for this annotation

GitHub Actions / Test & Coverage

schema version matches generator version

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: actual expected '[email protected]' at TestContext.<anonymous> (file:///home/runner/work/doc-kit/doc-kit/src/generators/json-all/__tests__/version.test.mjs:16:10) at Test.runInAsyncScope (node:async_hooks:214:14) at Test.run (node:internal/test_runner/test:1047:25) at Test.processPendingSubtests (node:internal/test_runner/test:744:18) at Test.postRun (node:internal/test_runner/test:1173:19) at Test.run (node:internal/test_runner/test:1101:12) at async startSubtestAfterBootstrap (node:internal/test_runner/harness:296:3) { generatedMessage: true, code: 'ERR_ASSERTION', actual: '[email protected]', expected: '[email protected]', operator: 'strictEqual', diff: 'simple' }
});
78 changes: 78 additions & 0 deletions src/generators/json-all/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// @ts-check
'use strict';

import { writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { DOC_NODE_VERSION } from '../../constants.mjs';
import { generateJsonSchema } from './util/generateJsonSchema.mjs';

// TODO add test w/ https://www.npmjs.com/package/jsonschema

/**
* TODO docs
*
* @typedef {Array<ApiDocMetadataEntry>} Input
*
* @type {GeneratorMetadata<Input, object>}
*/
export default {
name: 'json-all',

// This should be kept in sync with the JSON schema version for this
// generator AND the `json` generator
version: '2.0.0',

description: 'TODO',

dependsOn: 'json',

/**
* Generates a JSON file.
*
* @param {Input} input
* @param {Partial<GeneratorOptions>} param1
* @returns {Promise<object>}
*/
async generate(input, { output }) {
const generatedValue = {
$schema: `https://nodejs.org/docs/${DOC_NODE_VERSION}/api/node-doc-all-schema.jsonc`,
modules: [],
text: [],
};

const propertiesToIgnore = ['$schema', 'source'];

input.forEach(section => {
const copiedSection = {};

Object.keys(section).forEach(key => {
if (!propertiesToIgnore.includes(key)) {
copiedSection[key] = section[key];
}
});

switch (section.type) {
case 'module':
generatedValue.modules.push(copiedSection);
break;
case 'text':
generatedValue.text.push(copiedSection);
break;
default:
throw new TypeError(`unsupported root section type ${section.type}`);
}
});

if (output) {
const schema = generateJsonSchema();

// Write the parsed JSON schema to the output directory
await writeFile(
join(output, 'node-doc-schema.json'),
JSON.stringify(schema)
);
}

return generatedValue;
},
};
24 changes: 24 additions & 0 deletions src/generators/json-all/util/generateJsonSchema.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

import { DOC_NODE_VERSION } from '../../../constants.mjs';
import jsonAll from '../index.mjs';

const JSON_SCHEMA_URL = `https://nodejs.org/docs/${DOC_NODE_VERSION}/api/node-doc-schema.json`;

export const generateJsonSchema = () => ({
$schema: 'http://json-schema.org/draft-07/schema#',
$id: `nodejs-api-doc-all@${jsonAll.version}`,
title: 'Node.js API Documentation Schema (All)',
readOnly: true,

properties: {
modules: {
type: 'array',
items: { $ref: `${JSON_SCHEMA_URL}/#/definitions/Module` },
},
text: {
type: 'array',
items: { $ref: `${JSON_SCHEMA_URL}/#/definitions/Text` },
},
},
});
18 changes: 18 additions & 0 deletions src/generators/json/__tests__/version.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

import test from 'node:test';
import assert from 'node:assert';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { parse as jsoncParse } from 'jsonc-parser';
import json from '../index.mjs';

test('schema version matches generator version ', async () => {
const schemaString = await readFile(
join(import.meta.dirname, '..', 'schema.jsonc'),
'utf8'
);
const schema = await jsoncParse(schemaString);

assert.strictEqual(schema.$id, `nodejs-api-doc@v${json.version}`);
});
14 changes: 14 additions & 0 deletions src/generators/json/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

// Grabs the default value if present
export const DEFAULT_EXPRESSION = /^(D|d)efault(s|):$/;

// Grabs the type and description of one of the formats for event types
export const EVENT_TYPE_DESCRIPTION_EXTRACTOR = /{(.*)}(.*)/;

// Grabs return type and optional description for a method signature
// Accepts the following:
// Returns: {string}
// Returns {string}
// Returns: {string} bla bla bla
export const METHOD_RETURN_TYPE_EXTRACTOR = /^Returns(:?) {(.*)}( .*)?$/;
195 changes: 195 additions & 0 deletions src/generators/json/generated.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/* eslint-disable */
/**
* This file was automatically generated by json-schema-to-typescript.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run json-schema-to-typescript to regenerate this file.
*/

export type NodeJsAPIDocumentationSchema = DocumentRoot & (Module | Text);
/**
* A JavaScript module.
*/
export type Module = SectionBase & {
type: 'module';
/**
* https://jsdoc.app/tags-module
*/
'@module': string;
/**
* Classes exported from this module.
*/
classes?: Class[];
/**
* Methods exported from this module.
*/
methods?: Method[];
/**
* APIs that are available globally.
*/
globals?: (Class | Method)[];
properties?: Property[];
events?: Event[];
[k: string]: unknown;
};
export type Text = SectionBase;
/**
* Node.js version number
*/
export type NodeCoreVersion = string;
export type Class = SectionBase & {
type: 'class';
'@constructor': MethodSignature[];
methods: Method[];
staticMethods: Method[];
properties: Property[];
events?: Event[];
[k: string]: unknown;
};
/**
* A JavaScript function.
*/
export type Method = SectionBase & {
type: 'method';
signatures: MethodSignature[];
[k: string]: unknown;
};
/**
* A property on a JavaScript object or class.
*/
export type Property = SectionBase & {
type: 'property';
/**
* JavaScript type of the property.
*/
'@type'?: string | [string, ...string[]];
/**
* Is this property modifiable by user code?
*/
mutable?: boolean;
[k: string]: unknown;
};
/**
* An event that can be emitted by the parent object or class.
*/
export type Event = SectionBase & {
type: 'event';
parameters: MethodParameter[];
[k: string]: unknown;
};

/**
* Common properties found at the root of each document.
*/
export interface DocumentRoot {
/**
* The path to the Markdown source used to generate this document. It is relative to the Node.js repository root.
*/
source: string;
[k: string]: unknown;
}
/**
* Common properties found in each section of a document.
*/
export interface SectionBase {
/**
* Type of the section
*/
type: 'module' | 'class' | 'method' | 'property' | 'event' | 'text';
/**
* https://jsdoc.app/tags-name
*/
'@name': string;
/**
* Description of the section.
*/
description?: string;
/**
* https://jsdoc.app/tags-see
*/
'@see'?: string;
/**
* Sections that just hold further text on this section.
*/
text?: Text[];
/**
* https://jsdoc.app/tags-example
*/
'@example'?: string | string[];
/**
* https://jsdoc.app/tags-deprecated
*/
'@deprecated'?: NodeCoreVersion[];
stability?: Stability;
/**
* The changes this API has underwent.
*/
changes?: Change[];
/**
* https://jsdoc.app/tags-since
*/
'@since'?: NodeCoreVersion[];
napiVersion?: number[];
/**
* Versions that this was removed in.
*/
removedIn?: NodeCoreVersion[];
[k: string]: unknown;
}
/**
* Describes the stability of an object.
*/
export interface Stability {
/**
* The stability value.
*/
value: number;
/**
* Textual representation of the stability.
*/
text: string;
[k: string]: unknown;
}
export interface Change {
version: NodeCoreVersion[];
/**
* URL to the PR that introduced this change.
*/
prUrl?: string;
/**
* Description of the change.
*/
description: string;
[k: string]: unknown;
}
export interface MethodSignature {
parameters?: MethodParameter[];
'@returns'?: MethodReturnType;
[k: string]: unknown;
}
export interface MethodParameter {
/**
* Name of the parameter.
*/
'@name': string;
/**
* Type of the parameter
*/
'@type': string | [string, ...string[]];
description?: string;
/**
* The parameter's default value
*/
'@default'?: string;
[k: string]: unknown;
}
/**
* A method signature's return type.
*/
export interface MethodReturnType {
description?: string;
/**
* The method signature's return type.
*/
'@type': string | [string, ...string[]];
[k: string]: unknown;
}
Loading
Loading