@ankhorage/paradox 0.0.7 → 0.0.9

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,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - 8904673: Handle exports and type members without declaration nodes defensively during analysis.
8
+
9
+ ## 0.0.8
10
+
11
+ ### Patch Changes
12
+
13
+ - 46fd38d: Render Mermaid diagrams visually in the generated static documentation app.
14
+
15
+ The generated `paradox/index.html` now loads Mermaid in the browser, renders diagram blocks visually, and keeps the raw Mermaid source available in a collapsible section for offline fallback, copying, and debugging.
16
+
3
17
  ## 0.0.7
4
18
 
5
19
  ### Patch Changes
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ankhorage/paradox
2
2
 
3
- ![license: MIT](./paradox/badges/license.svg) ![npm: v0.0.6](./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)
3
+ ![license: MIT](./paradox/badges/license.svg) ![npm: v0.0.8](./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)
4
4
 
5
5
  Deterministic documentation generator for TypeScript packages.
6
6
 
@@ -14,7 +14,10 @@ export function analyzeExports(project, options) {
14
14
  const exported = sourceFile.getExportSymbols();
15
15
  for (const symbol of exported) {
16
16
  const resolved = resolveExportSymbol(symbol);
17
- const [decl] = resolved.getDeclarations();
17
+ const decl = getFirstDeclaration(resolved.getDeclarations());
18
+ if (decl === null) {
19
+ continue;
20
+ }
18
21
  const rawComment = getParadoxComment(decl);
19
22
  const parsed = rawComment
20
23
  ? parseParadoxComment(rawComment)
@@ -67,6 +70,10 @@ function getEntryPointSourceFiles(project, options) {
67
70
  })
68
71
  .filter((sourceFile) => sourceFile != null);
69
72
  }
73
+ function getFirstDeclaration(declarations) {
74
+ const [declaration = null] = declarations;
75
+ return declaration;
76
+ }
70
77
  function inferKind(node) {
71
78
  if ('getParameters' in node)
72
79
  return 'function';
@@ -63,24 +63,42 @@ function getSignature(declaration, params, returns) {
63
63
  function getMembers(node) {
64
64
  if (getCallableNode(node) !== null)
65
65
  return [];
66
- return node
67
- .getType()
68
- .getProperties()
69
- .map((property) => {
70
- const [declaration] = property.getDeclarations();
66
+ if (Node.isInterfaceDeclaration(node)) {
67
+ return getMembersFromProperties(node.getType().getProperties());
68
+ }
69
+ if (Node.isTypeAliasDeclaration(node)) {
70
+ const typeNode = node.getTypeNode();
71
+ if (!typeNode || !Node.isTypeLiteral(typeNode))
72
+ return [];
73
+ return getMembersFromProperties(node.getType().getProperties());
74
+ }
75
+ return [];
76
+ }
77
+ function getMembersFromProperties(properties) {
78
+ return properties.flatMap((property) => {
79
+ const declaration = getFirstDeclaration(property.getDeclarations());
80
+ if (declaration === null) {
81
+ return [];
82
+ }
71
83
  const rawComment = getParadoxComment(declaration);
72
84
  const parsed = rawComment
73
85
  ? parseParadoxComment(rawComment)
74
86
  : { description: null, isConfig: false, params: {}, returns: null };
75
- return {
76
- name: property.getName(),
77
- kind: isMemberMethodDeclaration(declaration) ? 'method' : 'property',
78
- type: property.getTypeAtLocation(declaration).getText(declaration),
79
- required: !property.isOptional(),
80
- description: parsed.description,
81
- };
87
+ return [
88
+ {
89
+ name: property.getName(),
90
+ kind: isMemberMethodDeclaration(declaration) ? 'method' : 'property',
91
+ type: property.getTypeAtLocation(declaration).getText(declaration),
92
+ required: !property.isOptional(),
93
+ description: parsed.description,
94
+ },
95
+ ];
82
96
  });
83
97
  }
98
+ function getFirstDeclaration(declarations) {
99
+ const [declaration = null] = declarations;
100
+ return declaration;
101
+ }
84
102
  function getCallableDeclarations(symbol, node) {
85
103
  const declarations = symbol
86
104
  .getDeclarations()
@@ -2,4 +2,4 @@ import type { Node } from 'ts-morph';
2
2
  /***
3
3
  * Reads the nearest Paradox doc comment attached to a declaration.
4
4
  */
5
- export declare function getParadoxComment(node: Node): string | null;
5
+ export declare function getParadoxComment(node: Node | undefined): string | null;
@@ -2,6 +2,8 @@
2
2
  * Reads the nearest Paradox doc comment attached to a declaration.
3
3
  */
4
4
  export function getParadoxComment(node) {
5
+ if (!node)
6
+ return null;
5
7
  const sourceFile = node.getSourceFile();
6
8
  const text = sourceFile.getFullText();
7
9
  const nodeStart = node.getStart(false);
@@ -100,6 +100,8 @@ export function renderHtml({ diagrams, model, }) {
100
100
  padding: 1rem;
101
101
  }
102
102
  .empty { font-style: italic; color: #6f7f9c; }
103
+ .mermaid { margin: 1rem 0; overflow: auto; }
104
+ details > summary { cursor: pointer; color: #5e6d8c; font-size: 0.9rem; margin-top: 0.5rem; user-select: none; }
103
105
  @media (max-width: 900px) {
104
106
  .layout { grid-template-columns: 1fr; }
105
107
  .sidebar { position: static; max-height: none; border-right: 0; border-bottom: 1px solid #d8dfec; }
@@ -169,6 +171,10 @@ export function renderHtml({ diagrams, model, }) {
169
171
  }
170
172
  });
171
173
  </script>
174
+ <script type="module">
175
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
176
+ mermaid.initialize({ startOnLoad: true });
177
+ </script>
172
178
  </body>
173
179
  </html>
174
180
  `,
@@ -270,7 +276,11 @@ function renderDiagramCard(diagram) {
270
276
  return `<article class="item" data-search="${escapeAttribute(`${diagram.title} ${diagram.path}`)}">
271
277
  <h3>${escapeHtml(diagram.title)}</h3>
272
278
  <p class="muted"><code>${escapeHtml(diagram.path)}</code></p>
273
- <pre>${escapeHtml(diagram.content)}</pre>
279
+ <div class="mermaid">${escapeHtml(diagram.content)}</div>
280
+ <details>
281
+ <summary>View Mermaid source</summary>
282
+ <pre>${escapeHtml(diagram.content)}</pre>
283
+ </details>
274
284
  </article>`;
275
285
  }
276
286
  function renderInlineCodeList(values) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/paradox",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "Deterministic documentation generator for TypeScript packages.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {