@ankhorage/paradox 0.1.19 → 0.1.21

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.21
4
+
5
+ ### Patch Changes
6
+
7
+ - b7cd8b9: Normalize package-local absolute import types emitted through React component prop analysis by carrying the analyzed package root into the existing type-text normalizer.
8
+
9
+ ## 0.1.20
10
+
11
+ ### Patch Changes
12
+
13
+ - 112f1f0: Normalize absolute TypeScript import-type paths to deterministic package or package-relative specifiers in generated documentation.
14
+
3
15
  ## 0.1.19
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/paradox
5
5
 
6
- ![license: MIT](./paradox/badges/license.svg) ![npm: v0.1.19](./paradox/badges/npm.svg) ![runtime: bun](./paradox/badges/runtime.svg) ![typescript: strict](./paradox/badges/typescript.svg) ![eslint: checked](./paradox/badges/eslint.svg) ![prettier: checked](./paradox/badges/prettier.svg) ![build: checked](./paradox/badges/build.svg) ![tests: checked](./paradox/badges/tests.svg) ![docs: paradox](./paradox/badges/docs.svg)
6
+ ![license: MIT](./paradox/badges/license.svg) ![npm: v0.1.21](./paradox/badges/npm.svg) ![runtime: bun](./paradox/badges/runtime.svg) ![typescript: strict](./paradox/badges/typescript.svg) ![eslint: checked](./paradox/badges/eslint.svg) ![prettier: checked](./paradox/badges/prettier.svg) ![build: checked](./paradox/badges/build.svg) ![tests: checked](./paradox/badges/tests.svg) ![docs: paradox](./paradox/badges/docs.svg)
7
7
 
8
8
  Deterministic documentation generator for TypeScript packages.
9
9
 
@@ -21,7 +21,7 @@ export function analyzeComponents(exports, options = {}) {
21
21
  description: member.description ?? null,
22
22
  })) ?? [];
23
23
  const propsType = getComponentPropsType(e.node);
24
- const legacyProps = propsType != null ? getPropsFromType(propsType) : [];
24
+ const legacyProps = propsType != null ? getPropsFromType(propsType, options.program?.root) : [];
25
25
  const props = analyzerProps.length > 0 ? analyzerProps : legacyProps;
26
26
  components.push({
27
27
  name: e.name,
@@ -1,6 +1,7 @@
1
1
  import { relative } from 'node:path';
2
2
  import { Node, } from 'ts-morph';
3
3
  import { getParadoxComment } from './getParadoxComment.js';
4
+ import { normalizeTypeText } from './normalizeTypeText.js';
4
5
  import { parseParadoxComment } from './parseParadoxComment.js';
5
6
  /***
6
7
  * Extracts computed metadata for an exported declaration.
@@ -8,8 +9,8 @@ import { parseParadoxComment } from './parseParadoxComment.js';
8
9
  export function getExportMetadata(options) {
9
10
  const modulePath = toPosixPath(relative(options.root, options.node.getSourceFile().getFilePath()));
10
11
  const sourceLocation = getSourceLocation(options.node, options.root);
11
- const signatures = getSignatures(options.symbol, options.node);
12
- const members = getMembers(options.node);
12
+ const signatures = getSignatures(options.symbol, options.node, options.root);
13
+ const members = getMembers(options.node, options.root);
13
14
  const structuredRows = getStructuredRows(options.node, options.name);
14
15
  const relatedSymbols = collectRelatedSymbols(options.name, signatures.flatMap((signature) => [
15
16
  ...signature.parameters.map((parameter) => parameter.type),
@@ -40,9 +41,9 @@ function getSourceLocation(node, root) {
40
41
  /***
41
42
  * Extracts callable signatures for exported functions and callable values.
42
43
  */
43
- function getSignatures(symbol, node) {
44
+ function getSignatures(symbol, node, root) {
44
45
  const parsed = readParadoxMetadata(node);
45
- const signatures = getCallableDeclarations(symbol, node).map((declaration) => getSignature(declaration, parsed.params, parsed.returns));
46
+ const signatures = getCallableDeclarations(symbol, node).map((declaration) => getSignature(declaration, parsed.params, parsed.returns, root));
46
47
  return uniqueBy(signatures.filter((signature) => signature.parameters.length > 0 ||
47
48
  signature.returnType !== null ||
48
49
  signature.returnDescription !== null), (signature) => signature.label);
@@ -50,17 +51,17 @@ function getSignatures(symbol, node) {
50
51
  /***
51
52
  * Builds one normalized call signature from a callable declaration.
52
53
  */
53
- function getSignature(declaration, params, returns) {
54
+ function getSignature(declaration, params, returns, root) {
54
55
  const normalizedParameters = declaration.getParameters().map((parameter) => {
55
56
  const parameterDescription = params[parameter.getName()];
56
57
  return {
57
58
  name: parameter.getName(),
58
- type: parameter.getType().getText(parameter),
59
+ type: normalizeTypeText(parameter.getType().getText(parameter), root),
59
60
  required: !parameter.isOptional(),
60
61
  description: parameterDescription ? parameterDescription.trim() : null,
61
62
  };
62
63
  });
63
- const returnType = declaration.getReturnType().getText(declaration);
64
+ const returnType = normalizeTypeText(declaration.getReturnType().getText(declaration), root);
64
65
  const parameterLabel = normalizedParameters
65
66
  .map((parameter) => `${parameter.name}${parameter.required ? '' : '?'}: ${parameter.type}`)
66
67
  .join(', ');
@@ -74,24 +75,24 @@ function getSignature(declaration, params, returns) {
74
75
  /***
75
76
  * Extracts members for interface and type literal exports.
76
77
  */
77
- function getMembers(node) {
78
+ function getMembers(node, root) {
78
79
  if (getCallableNode(node) !== null)
79
80
  return [];
80
81
  if (Node.isInterfaceDeclaration(node)) {
81
- return getMembersFromProperties(node.getType().getProperties());
82
+ return getMembersFromProperties(node.getType().getProperties(), root);
82
83
  }
83
84
  if (Node.isTypeAliasDeclaration(node)) {
84
85
  const typeNode = node.getTypeNode();
85
86
  if (!typeNode || !Node.isTypeLiteral(typeNode))
86
87
  return [];
87
- return getMembersFromProperties(node.getType().getProperties());
88
+ return getMembersFromProperties(node.getType().getProperties(), root);
88
89
  }
89
90
  return [];
90
91
  }
91
92
  /***
92
93
  * Converts TypeScript properties into documented member metadata.
93
94
  */
94
- function getMembersFromProperties(properties) {
95
+ function getMembersFromProperties(properties, root) {
95
96
  return properties.flatMap((property) => {
96
97
  const declaration = getFirstDeclaration(property.getDeclarations());
97
98
  if (declaration === null) {
@@ -112,7 +113,7 @@ function getMembersFromProperties(properties) {
112
113
  {
113
114
  name: property.getName(),
114
115
  kind: isMemberMethodDeclaration(declaration) ? 'method' : 'property',
115
- type: property.getTypeAtLocation(declaration).getText(declaration),
116
+ type: normalizeTypeText(property.getTypeAtLocation(declaration).getText(declaration), root),
116
117
  required: !property.isOptional(),
117
118
  description: parsed.description,
118
119
  },
@@ -3,4 +3,4 @@ import type { AnalysisComponent } from '../types.js';
3
3
  /***
4
4
  * Extracts prop names, types, required flags, and descriptions from a type.
5
5
  */
6
- export declare function getPropsFromType(type: Type): AnalysisComponent['props'];
6
+ export declare function getPropsFromType(type: Type, packageRoot?: string): AnalysisComponent['props'];
@@ -1,9 +1,10 @@
1
1
  import { getParadoxComment } from './getParadoxComment.js';
2
+ import { normalizeTypeText } from './normalizeTypeText.js';
2
3
  import { parseParadoxComment } from './parseParadoxComment.js';
3
4
  /***
4
5
  * Extracts prop names, types, required flags, and descriptions from a type.
5
6
  */
6
- export function getPropsFromType(type) {
7
+ export function getPropsFromType(type, packageRoot) {
7
8
  return type.getProperties().map((property) => {
8
9
  const [declaration] = property.getDeclarations();
9
10
  const propertyType = property.getTypeAtLocation(declaration);
@@ -13,7 +14,7 @@ export function getPropsFromType(type) {
13
14
  : { description: null, isConfig: false, params: {}, returns: null };
14
15
  return {
15
16
  name: property.getName(),
16
- type: propertyType.getText(declaration),
17
+ type: normalizeTypeText(propertyType.getText(declaration), packageRoot),
17
18
  required: !property.isOptional(),
18
19
  description: parsed.description,
19
20
  };
@@ -0,0 +1,4 @@
1
+ /***
2
+ * Removes machine-specific absolute paths from TypeScript import type text.
3
+ */
4
+ export declare function normalizeTypeText(typeText: string, packageRoot?: string): string;
@@ -0,0 +1,33 @@
1
+ /***
2
+ * Removes machine-specific absolute paths from TypeScript import type text.
3
+ */
4
+ export function normalizeTypeText(typeText, packageRoot) {
5
+ let normalized = '';
6
+ let cursor = 0;
7
+ for (const match of typeText.matchAll(/import\((['"])([^'"]+)\1\)/g)) {
8
+ const [fullMatch, quote, importPath] = match;
9
+ normalized += typeText.slice(cursor, match.index);
10
+ normalized += `import(${quote}${normalizeImportPath(importPath, packageRoot)}${quote})`;
11
+ cursor = match.index + fullMatch.length;
12
+ }
13
+ return normalized + typeText.slice(cursor);
14
+ }
15
+ function normalizeImportPath(importPath, packageRoot) {
16
+ const normalizedPath = toPosixPath(importPath);
17
+ const nodeModulesMarker = '/node_modules/';
18
+ const nodeModulesIndex = normalizedPath.lastIndexOf(nodeModulesMarker);
19
+ if (nodeModulesIndex >= 0) {
20
+ return normalizedPath.slice(nodeModulesIndex + nodeModulesMarker.length);
21
+ }
22
+ if (normalizedPath.startsWith('node_modules/')) {
23
+ return normalizedPath.slice('node_modules/'.length);
24
+ }
25
+ const normalizedRoot = packageRoot ? toPosixPath(packageRoot).replace(/\/$/, '') : null;
26
+ if (normalizedRoot && normalizedPath.startsWith(`${normalizedRoot}/`)) {
27
+ return `./${normalizedPath.slice(normalizedRoot.length + 1)}`;
28
+ }
29
+ return normalizedPath;
30
+ }
31
+ function toPosixPath(value) {
32
+ return value.replaceAll('\\', '/');
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/paradox",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Deterministic documentation generator for TypeScript packages.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {