@fuzdev/fuz_ui 0.193.1 → 0.195.0

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.
Files changed (86) hide show
  1. package/dist/DeclarationDetail.svelte +139 -64
  2. package/dist/DeclarationDetail.svelte.d.ts +9 -0
  3. package/dist/DeclarationDetail.svelte.d.ts.map +1 -1
  4. package/dist/LibraryDetail.svelte +14 -10
  5. package/dist/LibraryDetail.svelte.d.ts +7 -0
  6. package/dist/LibraryDetail.svelte.d.ts.map +1 -1
  7. package/dist/Spiders.svelte +4 -2
  8. package/dist/Spiders.svelte.d.ts +2 -1
  9. package/dist/Spiders.svelte.d.ts.map +1 -1
  10. package/dist/StyleVariableButton.svelte +1 -1
  11. package/dist/contextmenu_state.svelte.d.ts +14 -14
  12. package/dist/contextmenu_state.svelte.d.ts.map +1 -1
  13. package/dist/contextmenu_state.svelte.js +3 -3
  14. package/dist/declaration.svelte.d.ts +233 -25
  15. package/dist/declaration.svelte.d.ts.map +1 -1
  16. package/dist/declaration.svelte.js +71 -23
  17. package/dist/docs_helpers.svelte.d.ts +5 -5
  18. package/dist/docs_helpers.svelte.d.ts.map +1 -1
  19. package/dist/docs_helpers.svelte.js +1 -1
  20. package/dist/library.svelte.d.ts +5 -5
  21. package/dist/library.svelte.d.ts.map +1 -1
  22. package/dist/library.svelte.js +2 -2
  23. package/dist/library_gen.d.ts +24 -17
  24. package/dist/library_gen.d.ts.map +1 -1
  25. package/dist/library_gen.js +52 -32
  26. package/dist/library_output.d.ts +5 -4
  27. package/dist/library_output.d.ts.map +1 -1
  28. package/dist/library_output.js +11 -8
  29. package/dist/mdz_components.d.ts +16 -16
  30. package/dist/mdz_components.d.ts.map +1 -1
  31. package/dist/module.svelte.d.ts +21 -7
  32. package/dist/module.svelte.d.ts.map +1 -1
  33. package/dist/module.svelte.js +26 -11
  34. package/dist/style_variable_helpers.svelte.d.ts +4 -4
  35. package/dist/style_variable_helpers.svelte.d.ts.map +1 -1
  36. package/dist/style_variable_helpers.svelte.js +1 -1
  37. package/dist/tome.d.ts +10 -10
  38. package/dist/tome.d.ts.map +1 -1
  39. package/dist/tome.js +2 -2
  40. package/dist/tsdoc_mdz.d.ts +6 -1
  41. package/dist/tsdoc_mdz.d.ts.map +1 -1
  42. package/dist/tsdoc_mdz.js +23 -2
  43. package/package.json +11 -9
  44. package/src/lib/contextmenu_state.svelte.ts +6 -6
  45. package/src/lib/declaration.svelte.ts +90 -35
  46. package/src/lib/docs_helpers.svelte.ts +2 -2
  47. package/src/lib/library.svelte.ts +3 -3
  48. package/src/lib/library_gen.ts +65 -42
  49. package/src/lib/library_output.ts +11 -8
  50. package/src/lib/mdz_components.ts +18 -18
  51. package/src/lib/module.svelte.ts +29 -16
  52. package/src/lib/style_variable_helpers.svelte.ts +2 -2
  53. package/src/lib/tome.ts +4 -4
  54. package/src/lib/tsdoc_mdz.ts +25 -2
  55. package/dist/analysis_context.d.ts +0 -199
  56. package/dist/analysis_context.d.ts.map +0 -1
  57. package/dist/analysis_context.js +0 -138
  58. package/dist/library_analysis.d.ts +0 -112
  59. package/dist/library_analysis.d.ts.map +0 -1
  60. package/dist/library_analysis.js +0 -106
  61. package/dist/library_generate.d.ts +0 -94
  62. package/dist/library_generate.d.ts.map +0 -1
  63. package/dist/library_generate.js +0 -147
  64. package/dist/library_pipeline.d.ts +0 -113
  65. package/dist/library_pipeline.d.ts.map +0 -1
  66. package/dist/library_pipeline.js +0 -160
  67. package/dist/module_helpers.d.ts +0 -334
  68. package/dist/module_helpers.d.ts.map +0 -1
  69. package/dist/module_helpers.js +0 -317
  70. package/dist/svelte_helpers.d.ts +0 -92
  71. package/dist/svelte_helpers.d.ts.map +0 -1
  72. package/dist/svelte_helpers.js +0 -367
  73. package/dist/ts_helpers.d.ts +0 -181
  74. package/dist/ts_helpers.d.ts.map +0 -1
  75. package/dist/ts_helpers.js +0 -674
  76. package/dist/tsdoc_helpers.d.ts +0 -119
  77. package/dist/tsdoc_helpers.d.ts.map +0 -1
  78. package/dist/tsdoc_helpers.js +0 -207
  79. package/src/lib/analysis_context.ts +0 -254
  80. package/src/lib/library_analysis.ts +0 -168
  81. package/src/lib/library_generate.ts +0 -215
  82. package/src/lib/library_pipeline.ts +0 -221
  83. package/src/lib/module_helpers.ts +0 -501
  84. package/src/lib/svelte_helpers.ts +0 -539
  85. package/src/lib/ts_helpers.ts +0 -862
  86. package/src/lib/tsdoc_helpers.ts +0 -246
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_ui",
3
- "version": "0.193.1",
3
+ "version": "0.195.0",
4
4
  "description": "Svelte UI library",
5
5
  "tagline": "friendly user zystem",
6
6
  "glyph": "🧶",
@@ -33,13 +33,13 @@
33
33
  },
34
34
  "type": "module",
35
35
  "engines": {
36
- "node": ">=22.15"
36
+ "node": ">=24.14"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@fuzdev/fuz_code": ">=0.45.1",
40
40
  "@fuzdev/fuz_css": ">=0.53.0",
41
- "@fuzdev/fuz_util": ">=0.52.0",
42
- "@fuzdev/gro": ">=0.195.0",
41
+ "@fuzdev/fuz_util": "file:../fuz_util",
42
+ "@fuzdev/gro": "file:../gro",
43
43
  "@jridgewell/trace-mapping": "^0.3",
44
44
  "@sveltejs/kit": "^2.47.3",
45
45
  "@types/estree": "^1",
@@ -80,15 +80,16 @@
80
80
  },
81
81
  "devDependencies": {
82
82
  "@changesets/changelog-git": "^0.2.1",
83
+ "@fuzdev/blake3_wasm": "^0.1.0",
83
84
  "@fuzdev/fuz_code": "^0.45.1",
84
- "@fuzdev/fuz_css": "^0.59.0",
85
+ "@fuzdev/fuz_css": "^0.60.0",
85
86
  "@fuzdev/fuz_util": "^0.61.1",
86
87
  "@fuzdev/gro": "^0.199.1",
87
88
  "@jridgewell/trace-mapping": "^0.3.31",
88
89
  "@ryanatkn/eslint-config": "^0.12.1",
89
90
  "@sveltejs/acorn-typescript": "^1.0.9",
90
91
  "@sveltejs/adapter-static": "^3.0.10",
91
- "@sveltejs/kit": "^2.55.0",
92
+ "@sveltejs/kit": "^2.61.1",
92
93
  "@sveltejs/package": "^2.5.7",
93
94
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
94
95
  "@types/estree": "^1.0.8",
@@ -101,9 +102,10 @@
101
102
  "magic-string": "^0.30.21",
102
103
  "prettier": "^3.7.4",
103
104
  "prettier-plugin-svelte": "^3.5.1",
104
- "svelte": "^5.55.0",
105
- "svelte-check": "^4.4.5",
106
- "svelte2tsx": "^0.7.52",
105
+ "svelte": "^5.55.10",
106
+ "svelte-check": "^4.4.8",
107
+ "svelte-docinfo": "^0.1.0",
108
+ "svelte2tsx": "^0.7.55",
107
109
  "tslib": "^2.8.1",
108
110
  "typescript": "^5.9.3",
109
111
  "typescript-eslint": "^8.48.1",
@@ -10,6 +10,12 @@ import {Dimensions} from './dimensions.svelte.js';
10
10
  import {create_context} from './context_helpers.js';
11
11
  import {url_to_root_relative} from './library_helpers.js';
12
12
 
13
+ export const contextmenu_context = create_context<() => ContextmenuState>();
14
+
15
+ export const contextmenu_submenu_context = create_context<SubmenuState>();
16
+
17
+ export const contextmenu_dimensions_context = create_context(() => new Dimensions());
18
+
13
19
  export type ContextmenuParams =
14
20
  | Snippet
15
21
  // TODO maybe this should be generic?
@@ -475,12 +481,6 @@ const contextmenu_query_params = (
475
481
  return params;
476
482
  };
477
483
 
478
- export const contextmenu_context = create_context<() => ContextmenuState>();
479
-
480
- export const contextmenu_submenu_context = create_context<SubmenuState>();
481
-
482
- export const contextmenu_dimensions_context = create_context(() => new Dimensions());
483
-
484
484
  // Global registry of non-scoped contextmenu roots (only used in DEV)
485
485
  const non_scoped_roots: Set<symbol> = new Set();
486
486
 
@@ -1,20 +1,40 @@
1
- import {
2
- type DeclarationJson,
3
- declaration_generate_import,
4
- declaration_get_display_name,
5
- } from '@fuzdev/fuz_util/source_json.js';
1
+ import type {
2
+ DeclarationJson,
3
+ DeclarationJsonInput,
4
+ MemberJsonInput,
5
+ ParameterJsonInput,
6
+ ComponentPropJsonInput,
7
+ OverloadJsonInput,
8
+ } from 'svelte-docinfo/types.js';
9
+ import {generateImport, getDisplayName} from 'svelte-docinfo/declaration-helpers.js';
6
10
 
7
11
  import type {Module} from './module.svelte.js';
8
12
  import {url_github_file} from './package_helpers.js';
9
13
 
10
- /* eslint-disable @typescript-eslint/no-deprecated */
14
+ // `library.json` is serialized with svelte-docinfo's `compactReplacer`, which
15
+ // strips empty default arrays — so the on-disk data is the `*Input` shape
16
+ // (defaulted arrays optional), not the parsed `*Json` shape. Typing it as
17
+ // input makes TypeScript force a guard on every defaulted-array read.
18
+ //
19
+ // Helper to access kind-specific fields on the discriminated union.
20
+ // At runtime the field is present or undefined; TypeScript needs the cast.
21
+ const field = <T>(decl: DeclarationJsonInput, key: string): T | undefined =>
22
+ (decl as Record<string, unknown>)[key] as T | undefined;
11
23
 
12
24
  /**
13
25
  * Rich runtime representation of an exported declaration.
26
+ *
27
+ * Wraps svelte-docinfo's `DeclarationJson` discriminated union (on `kind`)
28
+ * with Svelte 5 reactive derivations and computed URLs.
29
+ * Kind-specific fields are accessed via the `field()` helper since
30
+ * not all fields exist on all variants.
31
+ *
32
+ * @see {@link https://github.com/ryanatkn/svelte-docinfo svelte-docinfo} for the analysis library
33
+ * @see `DeclarationDetail.svelte` for the rendering component
14
34
  */
15
35
  export class Declaration {
16
36
  readonly module: Module = $state.raw()!;
17
- readonly declaration_json: DeclarationJson = $state.raw()!;
37
+ readonly declaration_json: DeclarationJsonInput = $state.raw()!;
18
38
 
19
39
  library = $derived(this.module.library);
20
40
 
@@ -30,11 +50,11 @@ export class Declaration {
30
50
  * GitHub source URL with line number.
31
51
  */
32
52
  url_github = $derived(
33
- this.library.repo_url && this.declaration_json.source_line
53
+ this.library.repo_url && this.declaration_json.sourceLine
34
54
  ? url_github_file(
35
55
  this.library.repo_url,
36
56
  `src/lib/${this.module_path}`,
37
- this.declaration_json.source_line,
57
+ this.declaration_json.sourceLine,
38
58
  )
39
59
  : undefined,
40
60
  );
@@ -48,8 +68,10 @@ export class Declaration {
48
68
  * Generated TypeScript import statement.
49
69
  */
50
70
  import_statement = $derived(
51
- declaration_generate_import(
52
- this.declaration_json,
71
+ // `generateImport` reads only `name`/`kind`/path, none of the defaulted
72
+ // arrays, so asserting the parsed shape here is sound.
73
+ generateImport(
74
+ this.declaration_json as DeclarationJson,
53
75
  this.module_path,
54
76
  this.library.package_json.name,
55
77
  ),
@@ -67,37 +89,70 @@ export class Declaration {
67
89
  /**
68
90
  * Display name with generic parameters.
69
91
  */
70
- display_name = $derived(declaration_get_display_name(this.declaration_json));
71
-
72
- type_signature = $derived(this.declaration_json.type_signature);
73
- doc_comment = $derived(this.declaration_json.doc_comment);
74
- deprecated_message = $derived(this.declaration_json.deprecated_message);
75
- parameters = $derived(this.declaration_json.parameters);
76
- props = $derived(this.declaration_json.props);
77
- return_type = $derived(this.declaration_json.return_type);
78
- return_description = $derived(this.declaration_json.return_description);
79
- generic_params = $derived(this.declaration_json.generic_params);
80
- extends = $derived(this.declaration_json.extends);
81
- implements = $derived(this.declaration_json.implements);
82
- throws = $derived(this.declaration_json.throws);
83
- since = $derived(this.declaration_json.since);
84
- examples = $derived(this.declaration_json.examples);
85
- see_also = $derived(this.declaration_json.see_also);
86
- members: Array<DeclarationJson> | undefined = $derived(
87
- this.declaration_json.members as Array<DeclarationJson> | undefined,
88
- );
89
- properties: Array<DeclarationJson> | undefined = $derived(
90
- this.declaration_json.properties as Array<DeclarationJson> | undefined,
92
+ // `getDisplayName` reads `genericParams` unguarded, so feed it the defaulted
93
+ // value rather than the raw (possibly-absent) input field.
94
+ display_name = $derived(
95
+ getDisplayName({
96
+ ...this.declaration_json,
97
+ genericParams: this.declaration_json.genericParams ?? [],
98
+ } as DeclarationJson),
91
99
  );
92
100
 
93
- has_examples = $derived(!!(this.examples && this.examples.length > 0));
101
+ type_signature = $derived(this.declaration_json.typeSignature);
102
+ doc_comment = $derived(this.declaration_json.docComment);
103
+ deprecated_message = $derived(this.declaration_json.deprecatedMessage);
104
+ parameters = $derived(field<Array<ParameterJsonInput>>(this.declaration_json, 'parameters'));
105
+ props = $derived(field<Array<ComponentPropJsonInput>>(this.declaration_json, 'props'));
106
+ return_type = $derived(field<string>(this.declaration_json, 'returnType'));
107
+ return_description = $derived(field<string>(this.declaration_json, 'returnDescription'));
108
+ generic_params = $derived(this.declaration_json.genericParams ?? []);
109
+ extends_type = $derived(field<string | Array<string>>(this.declaration_json, 'extends'));
110
+ implements_types = $derived(field<Array<string>>(this.declaration_json, 'implements'));
111
+ throws = $derived(this.declaration_json.throws ?? []);
112
+ since = $derived(this.declaration_json.since);
113
+ examples = $derived(this.declaration_json.examples ?? []);
114
+ see_also = $derived(this.declaration_json.seeAlso ?? []);
115
+ /**
116
+ * Nested members for classes, interfaces, types, and enums.
117
+ */
118
+ members = $derived(field<Array<MemberJsonInput>>(this.declaration_json, 'members'));
119
+
120
+ /**
121
+ * Intersection types whose properties are external (filtered out of props/members).
122
+ * Present on `component` and `type` kinds.
123
+ */
124
+ intersects = $derived(field<Array<string>>(this.declaration_json, 'intersects'));
125
+
126
+ /**
127
+ * Whether a component accepts children via props or template usage.
128
+ * Present on `component` kind only.
129
+ */
130
+ accepts_children = $derived(field<boolean>(this.declaration_json, 'acceptsChildren'));
131
+
132
+ /**
133
+ * Function overload signatures when multiple public overloads exist.
134
+ * Present on `function` and `snippet` kinds, and on function/constructor members.
135
+ */
136
+ overloads = $derived(field<Array<OverloadJsonInput>>(this.declaration_json, 'overloads'));
137
+
138
+ /**
139
+ * Re-export alias info when this declaration is a renamed re-export.
140
+ */
141
+ alias_of = $derived(this.declaration_json.aliasOf);
142
+
143
+ /**
144
+ * Mutation documentation from `@mutates` tags, mapping parameter names to descriptions.
145
+ */
146
+ mutates = $derived(this.declaration_json.mutates);
147
+
148
+ has_examples = $derived(this.examples.length > 0);
94
149
  is_deprecated = $derived(!!this.deprecated_message);
95
150
  has_documentation = $derived(!!this.doc_comment);
96
151
  has_parameters = $derived(!!(this.parameters && this.parameters.length > 0));
97
152
  has_props = $derived(!!(this.props && this.props.length > 0));
98
- has_generics = $derived(!!(this.generic_params && this.generic_params.length > 0));
153
+ has_generics = $derived(this.generic_params.length > 0);
99
154
 
100
- constructor(module: Module, declaration_json: DeclarationJson) {
155
+ constructor(module: Module, declaration_json: DeclarationJsonInput) {
101
156
  this.module = module;
102
157
  this.declaration_json = declaration_json;
103
158
  }
@@ -4,6 +4,8 @@ import {ensure_end, ensure_start} from '@fuzdev/fuz_util/string.js';
4
4
 
5
5
  import {create_context} from './context_helpers.js';
6
6
 
7
+ export const docs_links_context = create_context<DocsLinks>();
8
+
7
9
  /**
8
10
  * Convert a string to a URL-safe fragment identifier, preserving case.
9
11
  * Unlike `slugify` from `@fuzdev/fuz_util/path.js` which lowercases,
@@ -42,8 +44,6 @@ export const to_docs_path_info = (
42
44
  return {path, path_is_selected, path_segment};
43
45
  };
44
46
 
45
- export const docs_links_context = create_context<DocsLinks>();
46
-
47
47
  export type DocsLinkTag = 'h2' | 'h3' | 'h4';
48
48
 
49
49
  export interface DocsLinkInfo {
@@ -5,6 +5,8 @@ import {create_context} from './context_helpers.js';
5
5
  import {Declaration} from './declaration.svelte.js';
6
6
  import {Module} from './module.svelte.js';
7
7
 
8
+ export const library_context = create_context<Library>();
9
+
8
10
  /**
9
11
  * Normalizes a URL prefix: ensures leading `/`, strips trailing `/`, returns `''` for falsy and non-string values.
10
12
  */
@@ -62,7 +64,7 @@ export class Library {
62
64
  */
63
65
  readonly modules = $derived(
64
66
  this.source_json.modules
65
- ? this.source_json.modules.map((module_json) => new Module(this, module_json))
67
+ ? this.source_json.modules.map((module_json) => new Module(this, module_json as any)) // TODO: remove cast when fuz_util SourceJson uses svelte-docinfo types
66
68
  : [],
67
69
  );
68
70
 
@@ -116,8 +118,6 @@ export class Library {
116
118
  }
117
119
  }
118
120
 
119
- export const library_context = create_context<Library>();
120
-
121
121
  /**
122
122
  * Search declarations by query string with multi-term AND logic.
123
123
  */
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * Gro-specific library metadata generation.
3
3
  *
4
- * This module provides Gro integration for library generation. It wraps the generic
5
- * `library_generate` function with Gro's `Gen` interface and provides adapters for
6
- * converting Gro's `Disknode` to the build-tool agnostic `SourceFileInfo`.
4
+ * This module provides Gro integration for library generation. It uses svelte-docinfo's
5
+ * pure analysis (`analyze`) and wraps the results with fuz_ui's opinionated
6
+ * LibraryJson format (GitHub/npm metadata).
7
7
  *
8
- * For build-tool agnostic usage, see `library_generate.ts`.
8
+ * For build-tool agnostic usage, see `svelte-docinfo`.
9
9
  *
10
- * @see `library_generate.ts` for the generic generation entry point
11
- * @see `library_pipeline.ts` for pipeline helpers
12
- * @see `library_output.ts` for output file generation
10
+ * @see svelte-docinfo/analyze.js for the generic analysis entry point
11
+ * @see svelte-docinfo/postprocess.js for post-processing helpers
12
+ * @see library_output.js for output file generation
13
13
  *
14
14
  * @module
15
15
  */
@@ -17,17 +17,18 @@
17
17
  import type {Gen} from '@fuzdev/gro';
18
18
  import {package_json_load} from '@fuzdev/gro/package_json.js';
19
19
  import type {Disknode} from '@fuzdev/gro/disknode.js';
20
-
21
20
  import {
22
- type SourceFileInfo,
21
+ analyze,
22
+ createSourceOptions,
23
23
  type ModuleSourceOptions,
24
- type ModuleSourcePartial,
25
- module_create_source_options,
26
- module_validate_source_options,
27
- module_is_source,
28
- module_get_source_root,
29
- } from './module_helpers.js';
30
- import {library_generate, type OnDuplicatesCallback} from './library_generate.js';
24
+ type OnDuplicatesCallback,
25
+ type SourceFileInfo,
26
+ type SourceOptionsDefaults,
27
+ } from 'svelte-docinfo';
28
+ import {normalizeSourceOptions, isSource, getSourceRoot} from 'svelte-docinfo/source-config.js';
29
+ import type {SourceJson} from '@fuzdev/fuz_util/source_json.js';
30
+
31
+ import {library_generate_output} from './library_output.js';
31
32
 
32
33
  /** Options for Gro library generation. */
33
34
  export interface LibraryGenOptions {
@@ -38,17 +39,17 @@ export interface LibraryGenOptions {
38
39
  * merged with defaults. The `project_root` is automatically set to
39
40
  * `process.cwd()` if not provided.
40
41
  */
41
- source?: ModuleSourceOptions | Partial<ModuleSourcePartial>;
42
+ source?: ModuleSourceOptions | Partial<SourceOptionsDefaults>;
42
43
  /**
43
44
  * Callback invoked when duplicate declaration names are found.
44
45
  *
45
46
  * Consumers decide how to handle duplicates: throw, warn, or ignore.
46
- * Use `library_throw_on_duplicates` for strict flat namespace enforcement.
47
+ * Use `throwOnDuplicates` for strict flat namespace enforcement.
47
48
  *
48
49
  * @example
49
50
  * ```ts
50
51
  * // Throw on duplicates (strict flat namespace)
51
- * library_gen({ on_duplicates: library_throw_on_duplicates });
52
+ * library_gen({ on_duplicates: throwOnDuplicates });
52
53
  *
53
54
  * // Warn but continue
54
55
  * library_gen({
@@ -66,7 +67,13 @@ export interface LibraryGenOptions {
66
67
  /**
67
68
  * Convert Gro's `Disknode` to the build-tool agnostic `SourceFileInfo` interface.
68
69
  *
69
- * Use this when you want to analyze files using Gro's filer directly.
70
+ * Use this when you want to analyze files using Gro's filer directly. The
71
+ * `dependencies` field is populated from the filer's forward-edge graph — the
72
+ * svelte-docinfo session honors it as pre-resolved input and skips its own
73
+ * lex+resolve pass for these files, avoiding duplicate work the filer already did.
74
+ *
75
+ * Reverse edges (`dependents`) are not threaded through — svelte-docinfo
76
+ * computes them internally from the forward edges of the owned set.
70
77
  *
71
78
  * @throws Error if disknode has no content (should be loaded by Gro filer)
72
79
  */
@@ -80,7 +87,6 @@ export const source_file_from_disknode = (disknode: Disknode): SourceFileInfo =>
80
87
  id: disknode.id,
81
88
  content: disknode.contents,
82
89
  dependencies: [...disknode.dependencies.keys()],
83
- dependents: [...disknode.dependents.keys()],
84
90
  };
85
91
  };
86
92
 
@@ -88,7 +94,7 @@ export const source_file_from_disknode = (disknode: Disknode): SourceFileInfo =>
88
94
  * Collect source files from Gro disknodes, filtering BEFORE conversion to `SourceFileInfo`.
89
95
  *
90
96
  * This avoids errors from files outside source directories (like test fixtures that may
91
- * have malformed paths or missing content). The filtering uses `module_is_source` which
97
+ * have malformed paths or missing content). The filtering uses `isSource` which
92
98
  * checks `source_paths` to only include files in configured source directories.
93
99
  *
94
100
  * @param disknodes - iterator of Gro disknodes from filer
@@ -100,8 +106,10 @@ export const library_collect_source_files_from_disknodes = (
100
106
  options: ModuleSourceOptions,
101
107
  log?: {info: (...args: Array<unknown>) => void; warn: (...args: Array<unknown>) => void},
102
108
  ): Array<SourceFileInfo> => {
103
- // Validate options early to fail fast on misconfiguration
104
- module_validate_source_options(options);
109
+ // Normalize options (throws on invalid config) and use the normalized form
110
+ // for downstream `isSource` / `getSourceRoot` calls, so callers that pass
111
+ // raw options (not via `createSourceOptions`) get consistent path handling.
112
+ const normalized_options = normalizeSourceOptions(options);
105
113
 
106
114
  const all_disknodes = Array.from(disknodes);
107
115
  log?.info(`received ${all_disknodes.length} files total from filer`);
@@ -110,7 +118,7 @@ export const library_collect_source_files_from_disknodes = (
110
118
  for (const disknode of all_disknodes) {
111
119
  // Filter by source_paths BEFORE trying to convert
112
120
  // This avoids errors from test fixtures or other non-source files
113
- if (!module_is_source(disknode.id, options)) {
121
+ if (!isSource(disknode.id, normalized_options)) {
114
122
  continue;
115
123
  }
116
124
  source_files.push(source_file_from_disknode(disknode));
@@ -119,7 +127,7 @@ export const library_collect_source_files_from_disknodes = (
119
127
  log?.info(`found ${source_files.length} source files to analyze`);
120
128
 
121
129
  if (source_files.length === 0) {
122
- const effective_root = module_get_source_root(options);
130
+ const effective_root = getSourceRoot(normalized_options);
123
131
  log?.warn(`No source files found in ${effective_root} - generating empty library metadata`);
124
132
  return [];
125
133
  }
@@ -135,10 +143,12 @@ export const library_collect_source_files_from_disknodes = (
135
143
  *
136
144
  * This is the Gro-specific entry point. It handles:
137
145
  * - Reading files from Gro's filer
138
- * - Loading `package.json` via Gro utilities
139
- * - Returning output in Gro's `Gen` format
146
+ * - Loading package.json via Gro utilities
147
+ * - Analyzing source with svelte-docinfo (pure analysis)
148
+ * - Wrapping with LibraryJson (GitHub/npm metadata)
149
+ * - Returning output in Gro's Gen format
140
150
  *
141
- * For build-tool agnostic usage, use `library_generate` directly.
151
+ * For build-tool agnostic usage, use `analyze` directly.
142
152
  *
143
153
  * Usage in a `.gen.ts` file:
144
154
  *
@@ -158,9 +168,9 @@ export const library_gen = (options?: LibraryGenOptions): Gen => {
158
168
 
159
169
  // Build source options with project_root from cwd
160
170
  const source_options: ModuleSourceOptions =
161
- options?.source && 'project_root' in options.source
171
+ options?.source && 'projectRoot' in options.source
162
172
  ? options.source
163
- : module_create_source_options(process.cwd(), options?.source);
173
+ : createSourceOptions(process.cwd(), options?.source);
164
174
 
165
175
  // Ensure filer is initialized
166
176
  await filer.init();
@@ -175,22 +185,35 @@ export const library_gen = (options?: LibraryGenOptions): Gen => {
175
185
  log,
176
186
  );
177
187
 
178
- // Use generic library_generate for the actual work
179
- const result = library_generate({
180
- source_files,
181
- package_json,
182
- source_options,
183
- on_duplicates: options?.on_duplicates,
184
- log,
188
+ // Get pure analysis from svelte-docinfo (no package metadata).
189
+ const {modules} = await analyze({
190
+ sourceFiles: source_files,
191
+ sourceOptions: source_options,
192
+ onDuplicates: options?.on_duplicates,
193
+ log: log as any, // Type cast needed due to workspace dependency duplication
185
194
  });
186
195
 
196
+ if (!package_json.version) {
197
+ throw new Error('package.json is missing required "version" field');
198
+ }
199
+ // Wrap modules with package metadata (fuz_ui's own SourceJson type)
200
+ const source_json: SourceJson = {
201
+ name: package_json.name,
202
+ version: package_json.version,
203
+ repository:
204
+ typeof package_json.repository === 'string'
205
+ ? package_json.repository
206
+ : package_json.repository?.url,
207
+ modules: modules as any, // TODO: remove cast when fuz_util SourceJson uses svelte-docinfo types
208
+ };
209
+
210
+ // Generate output files with fuz_ui's LibraryJson wrapper
211
+ const {json_content, ts_content} = library_generate_output(package_json, source_json);
212
+
187
213
  log.info('library metadata generation complete');
188
214
 
189
215
  // Return array of files in Gro's expected format
190
- return [
191
- {content: result.ts_content},
192
- {content: result.json_content, filename: 'library.json'},
193
- ];
216
+ return [{content: ts_content}, {content: json_content, filename: 'library.json'}];
194
217
  },
195
218
  };
196
219
  };
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Library output generation.
3
3
  *
4
- * Generates the `library.json` and `library.ts` files from analyzed metadata.
4
+ * Generates the library.json and library.ts files from analyzed metadata.
5
+ * Uses svelte-docinfo's `compactReplacer` to strip Zod default values
6
+ * (empty arrays, false booleans) for compact JSON output.
5
7
  *
6
- * @see `library_generate.ts` for the main generation entry point
7
- * @see `library_pipeline.ts` for pipeline orchestration functions
8
- * @see `library_gen.ts` for Gro-specific integration
8
+ * @see `library_gen.ts` for the main generation entry point
9
+ * @see {@link https://github.com/ryanatkn/svelte-docinfo svelte-docinfo} for the analysis library
9
10
  *
10
11
  * @module
11
12
  */
@@ -13,6 +14,7 @@
13
14
  import type {PackageJson} from '@fuzdev/fuz_util/package_json.js';
14
15
  import type {SourceJson} from '@fuzdev/fuz_util/source_json.js';
15
16
  import {library_json_parse, type LibraryJson} from '@fuzdev/fuz_util/library_json.js';
17
+ import {compactReplacer} from 'svelte-docinfo';
16
18
 
17
19
  /**
18
20
  * Result of generating library output files.
@@ -39,11 +41,12 @@ export const library_generate_output = (
39
41
  package_json: PackageJson,
40
42
  source_json: SourceJson,
41
43
  ): LibraryOutputResult => {
42
- const is_this_fuz_util = package_json.name === '@fuzdev/fuz_util';
43
- const fuz_util_prefix = is_this_fuz_util ? './' : '@fuzdev/fuz_util/';
44
+ // Compact source_json (strips Zod default values like empty arrays and false booleans)
45
+ // Only applied to source_json, not the outer library_json package metadata
46
+ const compacted_source_json = JSON.parse(JSON.stringify(source_json, compactReplacer));
44
47
 
45
48
  // Parse at generation time, not runtime
46
- const library_json: LibraryJson = library_json_parse(package_json, source_json);
49
+ const library_json: LibraryJson = library_json_parse(package_json, compacted_source_json);
47
50
 
48
51
  const json_content = JSON.stringify(library_json, null, '\t') + '\n';
49
52
 
@@ -51,7 +54,7 @@ export const library_generate_output = (
51
54
 
52
55
  const ts_content = `${banner}
53
56
 
54
- import type {LibraryJson} from '${fuz_util_prefix}library_json.js';
57
+ import type {LibraryJson} from '@fuzdev/fuz_util/library_json.js';
55
58
 
56
59
  import json from './library.json' with {type: 'json'};
57
60
 
@@ -2,24 +2,6 @@ import type {Component} from 'svelte';
2
2
 
3
3
  import {create_context} from './context_helpers.js';
4
4
 
5
- /**
6
- * Component registry for custom Svelte components that can be used in mdz content.
7
- *
8
- * For example, registering 'Alert' allows using `<Alert>...</Alert>` in mdz content.
9
- *
10
- * The Map values are the Svelte component constructors.
11
- */
12
- export type MdzComponents = Map<string, Component<any, any>>; // TODO support params
13
-
14
- /**
15
- * Element registry for HTML elements that can be used in mdz content.
16
- *
17
- * For example, registering 'div' allows using `<div>...</div>` in mdz content.
18
- *
19
- * The Map values are boolean placeholders for future configuration options.
20
- */
21
- export type MdzElements = Map<string, boolean>;
22
-
23
5
  /**
24
6
  * Context for providing custom mdz components.
25
7
  * Must be set by the application using mdz.
@@ -41,3 +23,21 @@ export const mdz_elements_context = create_context<MdzElements>();
41
23
  * When not set, relative paths use raw hrefs (browser resolves them).
42
24
  */
43
25
  export const mdz_base_context = create_context<() => string | undefined>();
26
+
27
+ /**
28
+ * Component registry for custom Svelte components that can be used in mdz content.
29
+ *
30
+ * For example, registering 'Alert' allows using `<Alert>...</Alert>` in mdz content.
31
+ *
32
+ * The Map values are the Svelte component constructors.
33
+ */
34
+ export type MdzComponents = Map<string, Component<any, any>>; // TODO support params
35
+
36
+ /**
37
+ * Element registry for HTML elements that can be used in mdz content.
38
+ *
39
+ * For example, registering 'div' allows using `<div>...</div>` in mdz content.
40
+ *
41
+ * The Map values are boolean placeholders for future configuration options.
42
+ */
43
+ export type MdzElements = Map<string, boolean>;