@ankhorage/paradox 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +31 -25
- package/dist/analyze/analyze.d.ts +3 -0
- package/dist/analyze/analyze.js +12 -0
- package/dist/analyze/badges.js +51 -0
- package/dist/analyze/exports.d.ts +1 -1
- package/dist/analyze/exports.js +24 -0
- package/dist/analyze/modules.js +6 -0
- package/dist/analyze/sourceFunctions.d.ts +6 -0
- package/dist/analyze/sourceFunctions.js +64 -0
- package/dist/analyze/types.d.ts +11 -1
- package/dist/analyze/usage.d.ts +3 -0
- package/dist/analyze/usage.js +6 -0
- package/dist/analyze/utils/getExportMetadata.d.ts +1 -1
- package/dist/analyze/utils/getExportMetadata.js +143 -2
- package/dist/analyze/utils/getParadoxComment.d.ts +2 -2
- package/dist/analyze/utils/getParadoxComment.js +26 -1
- package/dist/doc-tags/registry.d.ts +39 -0
- package/dist/doc-tags/registry.js +45 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/model/buildModel.d.ts +12 -0
- package/dist/model/buildModel.js +25 -0
- package/dist/model/types.d.ts +11 -1
- package/dist/paths/policy.d.ts +12 -0
- package/dist/paths/policy.js +27 -2
- package/dist/render/renderers/html.js +233 -60
- package/dist/render/renderers/markdown.js +47 -26
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fd606af: Move documentation tag metadata into a typed registry, stop rendering Paradox tag docs by default in consumer READMEs, and add structured table rendering for documented const array exports.
|
|
8
|
+
|
|
9
|
+
## 0.1.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 0255235: Full documentation of repo
|
|
14
|
+
|
|
3
15
|
## 0.1.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/paradox
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Deterministic documentation generator for TypeScript packages.
|
|
9
9
|
|
|
@@ -64,29 +64,6 @@ sequenceDiagram
|
|
|
64
64
|
|
|
65
65
|
</details>
|
|
66
66
|
|
|
67
|
-
## Documentation Tags
|
|
68
|
-
|
|
69
|
-
<details>
|
|
70
|
-
<summary>@readme</summary>
|
|
71
|
-
|
|
72
|
-
Includes a documentation block or exported symbol in README output.
|
|
73
|
-
|
|
74
|
-
</details>
|
|
75
|
-
|
|
76
|
-
<details>
|
|
77
|
-
<summary>@config</summary>
|
|
78
|
-
|
|
79
|
-
Marks a type or interface as part of the Paradox configuration model. `@config` alone does not imply README inclusion; use `@config` plus `@readme` for README output.
|
|
80
|
-
|
|
81
|
-
</details>
|
|
82
|
-
|
|
83
|
-
<details>
|
|
84
|
-
<summary>@example</summary>
|
|
85
|
-
|
|
86
|
-
Adds a titled fenced code example to the generated documentation for a symbol.
|
|
87
|
-
|
|
88
|
-
</details>
|
|
89
|
-
|
|
90
67
|
## Configuration
|
|
91
68
|
|
|
92
69
|
Create a `paradox.config.ts` file:
|
|
@@ -119,6 +96,7 @@ export default defineParadoxConfig({
|
|
|
119
96
|
- [Architecture overview](./paradox/diagrams/architecture-overview.mmd)
|
|
120
97
|
- [Module relationships](./paradox/diagrams/module-relationships.mmd)
|
|
121
98
|
- [Export graph](./paradox/diagrams/export-graph.mmd)
|
|
99
|
+
- [isParadoxDocTagName sequence](./paradox/diagrams/sequences/is-paradox-doc-tag-name.mmd)
|
|
122
100
|
- [paradox sequence](./paradox/diagrams/sequences/paradox.mmd)
|
|
123
101
|
|
|
124
102
|
## Architecture preview
|
|
@@ -142,6 +120,7 @@ graph TD
|
|
|
142
120
|
module_src_analyze_analyze_ts --> module_src_analyze_semantic_exports_ts
|
|
143
121
|
module_src_analyze_analyze_ts --> module_src_analyze_semantic_graphs_ts
|
|
144
122
|
module_src_analyze_analyze_ts --> module_src_analyze_sequenceScenarios_ts
|
|
123
|
+
module_src_analyze_analyze_ts --> module_src_analyze_sourceFunctions_ts
|
|
145
124
|
module_src_analyze_analyze_ts --> module_src_analyze_types_ts
|
|
146
125
|
module_src_analyze_analyze_ts --> module_src_analyze_usage_ts
|
|
147
126
|
module_src_analyze_analyze_ts --> module_src_config_types_ts
|
|
@@ -224,6 +203,11 @@ graph TD
|
|
|
224
203
|
module_src_analyze_sequenceScenarios_ts --> module_src_analyze_usage_ts
|
|
225
204
|
module_src_analyze_sequenceScenarios_ts --> module_src_analyze_utils_getParadoxComment_ts
|
|
226
205
|
module_src_analyze_sequenceScenarios_ts --> module_src_analyze_utils_parseParadoxComment_ts
|
|
206
|
+
module_src_analyze_sourceFunctions_ts["src/analyze/sourceFunctions.ts"]
|
|
207
|
+
package__ankhorage_paradox -.-> module_src_analyze_sourceFunctions_ts
|
|
208
|
+
module_src_analyze_sourceFunctions_ts --> module_src_analyze_types_ts
|
|
209
|
+
module_src_analyze_sourceFunctions_ts --> module_src_analyze_utils_getParadoxComment_ts
|
|
210
|
+
module_src_analyze_sourceFunctions_ts --> module_src_analyze_utils_parseParadoxComment_ts
|
|
227
211
|
module_src_analyze_types_ts["src/analyze/types.ts"]
|
|
228
212
|
package__ankhorage_paradox -.-> module_src_analyze_types_ts
|
|
229
213
|
module_src_analyze_usage_ts["src/analyze/usage.ts"]
|
|
@@ -261,6 +245,8 @@ graph TD
|
|
|
261
245
|
module_src_config_defineParadoxConfig_ts --> module_src_config_types_ts
|
|
262
246
|
module_src_config_types_ts["src/config/types.ts"]
|
|
263
247
|
package__ankhorage_paradox -.-> module_src_config_types_ts
|
|
248
|
+
module_src_doc_tags_registry_ts["src/doc-tags/registry.ts"]
|
|
249
|
+
package__ankhorage_paradox -.-> module_src_doc_tags_registry_ts
|
|
264
250
|
module_src_index_ts["src/index.ts"]
|
|
265
251
|
module_src_model_buildModel_ts["src/model/buildModel.ts"]
|
|
266
252
|
package__ankhorage_paradox -.-> module_src_model_buildModel_ts
|
|
@@ -316,7 +302,7 @@ graph TD
|
|
|
316
302
|
|
|
317
303
|
## Public API
|
|
318
304
|
|
|
319
|
-
###
|
|
305
|
+
### Config
|
|
320
306
|
|
|
321
307
|
<details>
|
|
322
308
|
<summary>defineParadoxConfig</summary>
|
|
@@ -342,3 +328,23 @@ Module: `src/config/types.ts`
|
|
|
342
328
|
Source: `src/config/types.ts:7:1`
|
|
343
329
|
|
|
344
330
|
</details>
|
|
331
|
+
|
|
332
|
+
### Documentation
|
|
333
|
+
|
|
334
|
+
<details>
|
|
335
|
+
<summary>PARADOX_DOC_TAGS</summary>
|
|
336
|
+
|
|
337
|
+
Supported Paradox documentation tags.
|
|
338
|
+
|
|
339
|
+
Paradox supports doc tags inside triple-star documentation comments.
|
|
340
|
+
|
|
341
|
+
| name | syntax | description | applies to | repeatable | handler |
|
|
342
|
+
| --------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ---------- | -------------- |
|
|
343
|
+
| `readme` | `@readme` | Includes a documentation block or exported symbol in README output. | block, symbol | no | `markReadme` |
|
|
344
|
+
| `config` | `@config` | Marks a type or interface as part of the Paradox configuration model. @config alone does not imply README inclusion; use @config plus @readme for README output. | interface, type | no | `markConfig` |
|
|
345
|
+
| `example` | `@example` | Adds a titled fenced code example to the generated documentation for a symbol. | symbol | yes | `parseExample` |
|
|
346
|
+
|
|
347
|
+
Module: `src/doc-tags/registry.ts`
|
|
348
|
+
Source: `src/doc-tags/registry.ts:8:14`
|
|
349
|
+
|
|
350
|
+
</details>
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ParadoxConfig } from '../config/types.js';
|
|
2
2
|
import type { AnalysisResult } from './types.js';
|
|
3
|
+
/***
|
|
4
|
+
* Analyzes a package and returns the complete documentation input model.
|
|
5
|
+
*/
|
|
3
6
|
export declare function analyze(config: ParadoxConfig, runtime: {
|
|
4
7
|
packageRoot: string;
|
|
5
8
|
}): Promise<AnalysisResult>;
|
package/dist/analyze/analyze.js
CHANGED
|
@@ -9,7 +9,11 @@ import { createTypeScriptProgram } from './semantic/createTypeScriptProgram.js';
|
|
|
9
9
|
import { collectTypeMembers, resolveTypeReference } from './semantic/exports.js';
|
|
10
10
|
import { collectCallGraph, collectComponentCompositionGraph, collectImportGraph, } from './semantic/graphs.js';
|
|
11
11
|
import { analyzeSequenceScenarios } from './sequenceScenarios.js';
|
|
12
|
+
import { analyzeSourceFunctions } from './sourceFunctions.js';
|
|
12
13
|
import { createUsageFromPackageJson } from './usage.js';
|
|
14
|
+
/***
|
|
15
|
+
* Analyzes a package and returns the complete documentation input model.
|
|
16
|
+
*/
|
|
13
17
|
export async function analyze(config, runtime) {
|
|
14
18
|
const root = runtime.packageRoot;
|
|
15
19
|
const pkg = await readPackageJson(root);
|
|
@@ -21,6 +25,7 @@ export async function analyze(config, runtime) {
|
|
|
21
25
|
const { config: configMetadata, exports } = analyzeExports(project, { root, entrypoints });
|
|
22
26
|
const components = analyzeComponents(exports, { program });
|
|
23
27
|
const modules = analyzeModules(project, { root, entrypoints });
|
|
28
|
+
const sourceFunctions = analyzeSourceFunctions(project, root);
|
|
24
29
|
const sequenceScenarios = analyzeSequenceScenarios({ project, root, pkg, exports });
|
|
25
30
|
const configExport = configMetadata
|
|
26
31
|
? (exports.find((entry) => entry.name === configMetadata.exportName) ?? null)
|
|
@@ -49,6 +54,7 @@ export async function analyze(config, runtime) {
|
|
|
49
54
|
description: config.docs?.description ?? pkg.description ?? null,
|
|
50
55
|
exports,
|
|
51
56
|
components,
|
|
57
|
+
sourceFunctions,
|
|
52
58
|
entrypoints: entrypoints.map((entrypoint) => entrypoint.replaceAll('\\', '/')).sort(),
|
|
53
59
|
modules,
|
|
54
60
|
badges,
|
|
@@ -64,6 +70,9 @@ export async function analyze(config, runtime) {
|
|
|
64
70
|
graphs,
|
|
65
71
|
};
|
|
66
72
|
}
|
|
73
|
+
/***
|
|
74
|
+
* Converts semantic type members into serializable analysis output.
|
|
75
|
+
*/
|
|
67
76
|
function mapTypeMembers(members) {
|
|
68
77
|
return members.map((member) => ({
|
|
69
78
|
name: member.name,
|
|
@@ -75,6 +84,9 @@ function mapTypeMembers(members) {
|
|
|
75
84
|
...(member.children ? { children: mapTypeMembers(member.children) } : {}),
|
|
76
85
|
}));
|
|
77
86
|
}
|
|
87
|
+
/***
|
|
88
|
+
* Reads package metadata from the analyzed package root.
|
|
89
|
+
*/
|
|
78
90
|
async function readPackageJson(root) {
|
|
79
91
|
const raw = await readFile(join(root, 'package.json'), 'utf-8');
|
|
80
92
|
return JSON.parse(raw);
|
package/dist/analyze/badges.js
CHANGED
|
@@ -132,6 +132,9 @@ export async function analyzeBadges(root, pkg) {
|
|
|
132
132
|
});
|
|
133
133
|
return sortBadges(badges);
|
|
134
134
|
}
|
|
135
|
+
/***
|
|
136
|
+
* Checks whether any candidate file exists under the repository root.
|
|
137
|
+
*/
|
|
135
138
|
async function hasAnyFile(root, paths) {
|
|
136
139
|
for (const relativePath of paths) {
|
|
137
140
|
if (await fileExists(join(root, relativePath))) {
|
|
@@ -140,18 +143,30 @@ async function hasAnyFile(root, paths) {
|
|
|
140
143
|
}
|
|
141
144
|
return false;
|
|
142
145
|
}
|
|
146
|
+
/***
|
|
147
|
+
* Reads tsconfig metadata and detects strict TypeScript mode.
|
|
148
|
+
*/
|
|
143
149
|
async function hasTypeScriptStrictMode(root) {
|
|
144
150
|
const tsconfig = await readJsonFile(join(root, 'tsconfig.json'));
|
|
145
151
|
return tsconfig?.compilerOptions?.strict === true;
|
|
146
152
|
}
|
|
153
|
+
/***
|
|
154
|
+
* Reads the line coverage percentage from a coverage summary file when present.
|
|
155
|
+
*/
|
|
147
156
|
async function readCoveragePercent(root) {
|
|
148
157
|
const coverage = await readJsonFile(join(root, 'coverage', 'coverage-summary.json'));
|
|
149
158
|
const value = coverage?.total?.lines?.pct;
|
|
150
159
|
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
151
160
|
}
|
|
161
|
+
/***
|
|
162
|
+
* Formats integer and fractional percentages for badge labels.
|
|
163
|
+
*/
|
|
152
164
|
function formatPercent(value) {
|
|
153
165
|
return Number.isInteger(value) ? `${value}` : value.toFixed(1);
|
|
154
166
|
}
|
|
167
|
+
/***
|
|
168
|
+
* Selects the coverage badge color from the coverage percentage.
|
|
169
|
+
*/
|
|
155
170
|
function getCoverageColor(value) {
|
|
156
171
|
if (value >= 90)
|
|
157
172
|
return '0a7f3f';
|
|
@@ -161,12 +176,21 @@ function getCoverageColor(value) {
|
|
|
161
176
|
return 'ca8a04';
|
|
162
177
|
return 'dc2626';
|
|
163
178
|
}
|
|
179
|
+
/***
|
|
180
|
+
* Checks whether a named package script is configured.
|
|
181
|
+
*/
|
|
164
182
|
function hasScript(pkg, name) {
|
|
165
183
|
return typeof pkg.scripts?.[name] === 'string' && pkg.scripts[name].length > 0;
|
|
166
184
|
}
|
|
185
|
+
/***
|
|
186
|
+
* Checks whether a package script contains a specific command fragment.
|
|
187
|
+
*/
|
|
167
188
|
function scriptContains(pkg, name, command) {
|
|
168
189
|
return pkg.scripts?.[name]?.includes(command) ?? false;
|
|
169
190
|
}
|
|
191
|
+
/***
|
|
192
|
+
* Detects whether package metadata or workflows indicate Bun support.
|
|
193
|
+
*/
|
|
170
194
|
function supportsBun(pkg, workflowFiles) {
|
|
171
195
|
if (pkg.packageManager?.startsWith('bun@') ?? false) {
|
|
172
196
|
return true;
|
|
@@ -178,6 +202,9 @@ function supportsBun(pkg, workflowFiles) {
|
|
|
178
202
|
workflow.includes('bun install') ||
|
|
179
203
|
/\bbun(?:x)?\b/.test(workflow));
|
|
180
204
|
}
|
|
205
|
+
/***
|
|
206
|
+
* Checks whether any workflow file invokes a named package script.
|
|
207
|
+
*/
|
|
181
208
|
function workflowRunsScript(workflowFiles, scriptName) {
|
|
182
209
|
const escaped = escapeRegExp(scriptName);
|
|
183
210
|
const patterns = [
|
|
@@ -188,9 +215,15 @@ function workflowRunsScript(workflowFiles, scriptName) {
|
|
|
188
215
|
];
|
|
189
216
|
return workflowFiles.some((workflow) => patterns.some((pattern) => pattern.test(workflow)));
|
|
190
217
|
}
|
|
218
|
+
/***
|
|
219
|
+
* Escapes regular expression syntax in a script name.
|
|
220
|
+
*/
|
|
191
221
|
function escapeRegExp(value) {
|
|
192
222
|
return value.replaceAll(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
193
223
|
}
|
|
224
|
+
/***
|
|
225
|
+
* Reads all GitHub Actions workflow files from the repository.
|
|
226
|
+
*/
|
|
194
227
|
async function readWorkflowFiles(root) {
|
|
195
228
|
const workflowsPath = join(root, '.github', 'workflows');
|
|
196
229
|
const entries = await readDirectory(workflowsPath);
|
|
@@ -200,6 +233,9 @@ async function readWorkflowFiles(root) {
|
|
|
200
233
|
.map((entry) => readFile(join(workflowsPath, entry), 'utf-8')));
|
|
201
234
|
return contents;
|
|
202
235
|
}
|
|
236
|
+
/***
|
|
237
|
+
* Reads a directory and treats a missing path as an empty directory.
|
|
238
|
+
*/
|
|
203
239
|
async function readDirectory(path) {
|
|
204
240
|
try {
|
|
205
241
|
return await readdir(path);
|
|
@@ -211,9 +247,15 @@ async function readDirectory(path) {
|
|
|
211
247
|
throw new Error(`Unable to read workflow directory: ${path}`, { cause: error });
|
|
212
248
|
}
|
|
213
249
|
}
|
|
250
|
+
/***
|
|
251
|
+
* Checks whether an unknown error is a file-not-found filesystem error.
|
|
252
|
+
*/
|
|
214
253
|
function isNotFoundError(error) {
|
|
215
254
|
return typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT';
|
|
216
255
|
}
|
|
256
|
+
/***
|
|
257
|
+
* Reads and parses a JSON file, returning null when the file does not exist.
|
|
258
|
+
*/
|
|
217
259
|
async function readJsonFile(path) {
|
|
218
260
|
let content;
|
|
219
261
|
try {
|
|
@@ -232,6 +274,9 @@ async function readJsonFile(path) {
|
|
|
232
274
|
throw new Error(`Unable to parse JSON metadata file: ${path}`, { cause: error });
|
|
233
275
|
}
|
|
234
276
|
}
|
|
277
|
+
/***
|
|
278
|
+
* Checks whether a filesystem path exists.
|
|
279
|
+
*/
|
|
235
280
|
async function fileExists(path) {
|
|
236
281
|
try {
|
|
237
282
|
await access(path);
|
|
@@ -244,12 +289,18 @@ async function fileExists(path) {
|
|
|
244
289
|
throw error;
|
|
245
290
|
}
|
|
246
291
|
}
|
|
292
|
+
/***
|
|
293
|
+
* Sorts badges into the stable preferred display order.
|
|
294
|
+
*/
|
|
247
295
|
function sortBadges(badges) {
|
|
248
296
|
return [...badges].sort((left, right) => {
|
|
249
297
|
const order = getBadgeOrder(left.id) - getBadgeOrder(right.id);
|
|
250
298
|
return order !== 0 ? order : left.id.localeCompare(right.id);
|
|
251
299
|
});
|
|
252
300
|
}
|
|
301
|
+
/***
|
|
302
|
+
* Returns the configured display order index for a badge id.
|
|
303
|
+
*/
|
|
253
304
|
function getBadgeOrder(id) {
|
|
254
305
|
const index = BADGE_ORDER.indexOf(id);
|
|
255
306
|
return index === -1 ? BADGE_ORDER.length : index;
|
package/dist/analyze/exports.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isAbsolute, join, normalize, relative } from 'node:path';
|
|
2
|
+
import { Node } from 'ts-morph';
|
|
2
3
|
import { getExportMetadata } from './utils/getExportMetadata.js';
|
|
3
4
|
import { getParadoxComment } from './utils/getParadoxComment.js';
|
|
4
5
|
import { parseParadoxComment } from './utils/parseParadoxComment.js';
|
|
@@ -48,6 +49,9 @@ export function analyzeExports(project, options) {
|
|
|
48
49
|
]),
|
|
49
50
|
signatures: existing.signatures.length > 0 ? existing.signatures : metadata.signatures,
|
|
50
51
|
members: existing.members.length > 0 ? existing.members : metadata.members,
|
|
52
|
+
structuredRows: existing.structuredRows.length > 0
|
|
53
|
+
? existing.structuredRows
|
|
54
|
+
: metadata.structuredRows,
|
|
51
55
|
}
|
|
52
56
|
: {
|
|
53
57
|
name,
|
|
@@ -65,6 +69,9 @@ export function analyzeExports(project, options) {
|
|
|
65
69
|
config,
|
|
66
70
|
};
|
|
67
71
|
}
|
|
72
|
+
/***
|
|
73
|
+
* Resolves configured entrypoint paths to source files in the TypeScript project.
|
|
74
|
+
*/
|
|
68
75
|
function getEntryPointSourceFiles(project, options) {
|
|
69
76
|
return options.entrypoints
|
|
70
77
|
.map((entrypoint) => {
|
|
@@ -73,23 +80,40 @@ function getEntryPointSourceFiles(project, options) {
|
|
|
73
80
|
})
|
|
74
81
|
.filter((sourceFile) => sourceFile != null);
|
|
75
82
|
}
|
|
83
|
+
/***
|
|
84
|
+
* Returns the first declaration for a symbol, or null when none exists.
|
|
85
|
+
*/
|
|
76
86
|
function getFirstDeclaration(declarations) {
|
|
77
87
|
const [declaration = null] = declarations;
|
|
78
88
|
return declaration;
|
|
79
89
|
}
|
|
90
|
+
/***
|
|
91
|
+
* Infers the public export kind from the declaration shape.
|
|
92
|
+
*/
|
|
80
93
|
function inferKind(node) {
|
|
81
94
|
if ('getParameters' in node)
|
|
82
95
|
return 'function';
|
|
83
96
|
if ('getProperties' in node || 'getMembers' in node)
|
|
84
97
|
return 'type';
|
|
98
|
+
if (Node.isVariableDeclaration(node))
|
|
99
|
+
return 'value';
|
|
85
100
|
return 'unknown';
|
|
86
101
|
}
|
|
102
|
+
/***
|
|
103
|
+
* Returns unique string values sorted for deterministic generated output.
|
|
104
|
+
*/
|
|
87
105
|
function uniqueSorted(values) {
|
|
88
106
|
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
89
107
|
}
|
|
108
|
+
/***
|
|
109
|
+
* Normalizes platform-specific path separators for generated documentation output.
|
|
110
|
+
*/
|
|
90
111
|
function toPosixPath(path) {
|
|
91
112
|
return path.replaceAll('\\', '/');
|
|
92
113
|
}
|
|
114
|
+
/***
|
|
115
|
+
* Creates empty documentation metadata for exports without Paradox comments.
|
|
116
|
+
*/
|
|
93
117
|
function createEmptyMetadata() {
|
|
94
118
|
return {
|
|
95
119
|
description: null,
|
package/dist/analyze/modules.js
CHANGED
|
@@ -36,9 +36,15 @@ export function analyzeModules(project, options) {
|
|
|
36
36
|
})
|
|
37
37
|
.sort((left, right) => left.path.localeCompare(right.path));
|
|
38
38
|
}
|
|
39
|
+
/***
|
|
40
|
+
* Returns unique string values sorted for deterministic generated output.
|
|
41
|
+
*/
|
|
39
42
|
function uniqueSorted(values) {
|
|
40
43
|
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
41
44
|
}
|
|
45
|
+
/***
|
|
46
|
+
* Normalizes platform-specific path separators for generated documentation output.
|
|
47
|
+
*/
|
|
42
48
|
function toPosixPath(path) {
|
|
43
49
|
return path.replaceAll('\\', '/');
|
|
44
50
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Project } from 'ts-morph';
|
|
2
|
+
import type { AnalysisSourceFunction } from './types.js';
|
|
3
|
+
/***
|
|
4
|
+
* Collects callable declarations from analyzed source files for source-area documentation.
|
|
5
|
+
*/
|
|
6
|
+
export declare function analyzeSourceFunctions(project: Project, root: string): AnalysisSourceFunction[];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
import { Node } from 'ts-morph';
|
|
3
|
+
import { getParadoxComment } from './utils/getParadoxComment.js';
|
|
4
|
+
import { parseParadoxComment } from './utils/parseParadoxComment.js';
|
|
5
|
+
/***
|
|
6
|
+
* Collects callable declarations from analyzed source files for source-area documentation.
|
|
7
|
+
*/
|
|
8
|
+
export function analyzeSourceFunctions(project, root) {
|
|
9
|
+
return project
|
|
10
|
+
.getSourceFiles()
|
|
11
|
+
.flatMap((sourceFile) => {
|
|
12
|
+
if (sourceFile.isDeclarationFile())
|
|
13
|
+
return [];
|
|
14
|
+
const filePath = toPosixPath(relative(root, sourceFile.getFilePath()));
|
|
15
|
+
if (!filePath.startsWith('src/'))
|
|
16
|
+
return [];
|
|
17
|
+
return sourceFile.getDescendants().flatMap((node) => {
|
|
18
|
+
if (Node.isFunctionDeclaration(node)) {
|
|
19
|
+
const name = node.getName();
|
|
20
|
+
if (name === undefined)
|
|
21
|
+
return [];
|
|
22
|
+
return [createSourceFunction(name, node, root)];
|
|
23
|
+
}
|
|
24
|
+
if (Node.isVariableDeclaration(node)) {
|
|
25
|
+
const initializer = node.getInitializer();
|
|
26
|
+
if (initializer === undefined ||
|
|
27
|
+
(!Node.isArrowFunction(initializer) && !Node.isFunctionExpression(initializer))) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return [createSourceFunction(node.getName(), node, root)];
|
|
31
|
+
}
|
|
32
|
+
return [];
|
|
33
|
+
});
|
|
34
|
+
})
|
|
35
|
+
.sort((left, right) => left.sourceLocation.filePath === right.sourceLocation.filePath
|
|
36
|
+
? left.sourceLocation.line - right.sourceLocation.line
|
|
37
|
+
: left.sourceLocation.filePath.localeCompare(right.sourceLocation.filePath));
|
|
38
|
+
}
|
|
39
|
+
/***
|
|
40
|
+
* Converts a callable declaration into source documentation metadata.
|
|
41
|
+
*/
|
|
42
|
+
function createSourceFunction(name, node, root) {
|
|
43
|
+
const sourceFile = node.getSourceFile();
|
|
44
|
+
const { column, line } = sourceFile.getLineAndColumnAtPos(node.getStart(false));
|
|
45
|
+
const rawComment = getParadoxComment(node);
|
|
46
|
+
const parsedComment = rawComment
|
|
47
|
+
? parseParadoxComment(rawComment)
|
|
48
|
+
: { description: null, isReadme: false };
|
|
49
|
+
return {
|
|
50
|
+
name,
|
|
51
|
+
description: parsedComment.description,
|
|
52
|
+
sourceLocation: {
|
|
53
|
+
filePath: toPosixPath(relative(root, sourceFile.getFilePath())),
|
|
54
|
+
line,
|
|
55
|
+
column,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/***
|
|
60
|
+
* Normalizes platform-specific path separators for generated documentation output.
|
|
61
|
+
*/
|
|
62
|
+
function toPosixPath(path) {
|
|
63
|
+
return path.replaceAll('\\', '/');
|
|
64
|
+
}
|
package/dist/analyze/types.d.ts
CHANGED
|
@@ -34,19 +34,23 @@ export interface AnalysisMember {
|
|
|
34
34
|
inheritedFrom?: string;
|
|
35
35
|
children?: AnalysisMember[];
|
|
36
36
|
}
|
|
37
|
+
export interface AnalysisStructuredRow {
|
|
38
|
+
values: Record<string, string>;
|
|
39
|
+
}
|
|
37
40
|
export interface AnalysisExport {
|
|
38
41
|
name: string;
|
|
39
42
|
node: Node;
|
|
40
43
|
description: string | null;
|
|
41
44
|
isReadme: boolean;
|
|
42
45
|
examples: AnalysisExample[];
|
|
43
|
-
kind: 'function' | 'type' | 'unknown';
|
|
46
|
+
kind: 'function' | 'type' | 'value' | 'unknown';
|
|
44
47
|
modulePath: string;
|
|
45
48
|
sourceLocation: AnalysisSourceLocation;
|
|
46
49
|
exportPaths: string[];
|
|
47
50
|
relatedSymbols: string[];
|
|
48
51
|
signatures: AnalysisSignature[];
|
|
49
52
|
members: AnalysisMember[];
|
|
53
|
+
structuredRows: AnalysisStructuredRow[];
|
|
50
54
|
}
|
|
51
55
|
/***
|
|
52
56
|
* Describes one React component and its extracted props.
|
|
@@ -95,6 +99,11 @@ export interface AnalysisSequenceScenario {
|
|
|
95
99
|
description: string | null;
|
|
96
100
|
isReadme: boolean;
|
|
97
101
|
}
|
|
102
|
+
export interface AnalysisSourceFunction {
|
|
103
|
+
name: string;
|
|
104
|
+
description: string | null;
|
|
105
|
+
sourceLocation: AnalysisSourceLocation;
|
|
106
|
+
}
|
|
98
107
|
interface AnalysisTypeMember {
|
|
99
108
|
name: string;
|
|
100
109
|
type: string;
|
|
@@ -141,6 +150,7 @@ export interface AnalysisResult {
|
|
|
141
150
|
description: string | null;
|
|
142
151
|
exports: AnalysisExport[];
|
|
143
152
|
components: AnalysisComponent[];
|
|
153
|
+
sourceFunctions: AnalysisSourceFunction[];
|
|
144
154
|
entrypoints: string[];
|
|
145
155
|
modules: AnalysisModule[];
|
|
146
156
|
badges: AnalysisBadge[];
|
package/dist/analyze/usage.d.ts
CHANGED
|
@@ -10,4 +10,7 @@ export interface PackageJsonModel {
|
|
|
10
10
|
eslintConfig?: unknown;
|
|
11
11
|
prettier?: unknown;
|
|
12
12
|
}
|
|
13
|
+
/***
|
|
14
|
+
* Builds installation and executable usage commands from package metadata.
|
|
15
|
+
*/
|
|
13
16
|
export declare function createUsageFromPackageJson(pkg: PackageJsonModel): AnalysisUsage | null;
|
package/dist/analyze/usage.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Builds installation and executable usage commands from package metadata.
|
|
3
|
+
*/
|
|
1
4
|
export function createUsageFromPackageJson(pkg) {
|
|
2
5
|
if (pkg.bin == null)
|
|
3
6
|
return null;
|
|
@@ -35,6 +38,9 @@ export function createUsageFromPackageJson(pkg) {
|
|
|
35
38
|
})),
|
|
36
39
|
};
|
|
37
40
|
}
|
|
41
|
+
/***
|
|
42
|
+
* Extracts the unscoped package name from a package id.
|
|
43
|
+
*/
|
|
38
44
|
function getPackageBaseName(packageName) {
|
|
39
45
|
return packageName.split('/').pop() ?? packageName;
|
|
40
46
|
}
|
|
@@ -9,4 +9,4 @@ export declare function getExportMetadata(options: {
|
|
|
9
9
|
root: string;
|
|
10
10
|
entrypointPath: string;
|
|
11
11
|
symbol: MorphSymbol;
|
|
12
|
-
}): Pick<AnalysisExport, 'exportPaths' | 'members' | 'modulePath' | 'relatedSymbols' | 'signatures' | 'sourceLocation'>;
|
|
12
|
+
}): Pick<AnalysisExport, 'exportPaths' | 'members' | 'modulePath' | 'relatedSymbols' | 'signatures' | 'sourceLocation' | 'structuredRows'>;
|