@fuzdev/fuz_ui 0.174.0 → 0.176.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 (61) hide show
  1. package/README.md +1 -1
  2. package/dist/Alert.svelte +2 -0
  3. package/dist/Alert.svelte.d.ts.map +1 -1
  4. package/dist/ApiModule.svelte +5 -6
  5. package/dist/ApiModule.svelte.d.ts.map +1 -1
  6. package/dist/DeclarationDetail.svelte +2 -1
  7. package/dist/DeclarationDetail.svelte.d.ts.map +1 -1
  8. package/dist/Details.svelte +2 -0
  9. package/dist/Details.svelte.d.ts.map +1 -1
  10. package/dist/EcosystemLinks.svelte +3 -3
  11. package/dist/EcosystemLinks.svelte.d.ts +1 -1
  12. package/dist/EcosystemLinks.svelte.d.ts.map +1 -1
  13. package/dist/Themed.svelte +2 -0
  14. package/dist/Themed.svelte.d.ts.map +1 -1
  15. package/dist/analysis_context.d.ts +195 -0
  16. package/dist/analysis_context.d.ts.map +1 -0
  17. package/dist/analysis_context.js +134 -0
  18. package/dist/library_analysis.d.ts +112 -0
  19. package/dist/library_analysis.d.ts.map +1 -0
  20. package/dist/library_analysis.js +106 -0
  21. package/dist/library_gen.d.ts +73 -5
  22. package/dist/library_gen.d.ts.map +1 -1
  23. package/dist/library_gen.js +130 -68
  24. package/dist/library_gen_helpers.d.ts +81 -72
  25. package/dist/library_gen_helpers.d.ts.map +1 -1
  26. package/dist/library_gen_helpers.js +115 -156
  27. package/dist/library_gen_output.d.ts +34 -0
  28. package/dist/library_gen_output.d.ts.map +1 -0
  29. package/dist/library_gen_output.js +40 -0
  30. package/dist/mdz.d.ts +3 -0
  31. package/dist/mdz.d.ts.map +1 -1
  32. package/dist/mdz.js +12 -3
  33. package/dist/module_helpers.d.ts +246 -24
  34. package/dist/module_helpers.d.ts.map +1 -1
  35. package/dist/module_helpers.js +250 -42
  36. package/dist/svelte_helpers.d.ts +65 -10
  37. package/dist/svelte_helpers.d.ts.map +1 -1
  38. package/dist/svelte_helpers.js +171 -49
  39. package/dist/ts_helpers.d.ts +132 -61
  40. package/dist/ts_helpers.d.ts.map +1 -1
  41. package/dist/ts_helpers.js +423 -282
  42. package/dist/tsdoc_helpers.d.ts +11 -0
  43. package/dist/tsdoc_helpers.d.ts.map +1 -1
  44. package/dist/tsdoc_helpers.js +22 -47
  45. package/dist/tsdoc_mdz.d.ts +36 -0
  46. package/dist/tsdoc_mdz.d.ts.map +1 -0
  47. package/dist/tsdoc_mdz.js +56 -0
  48. package/dist/vite_plugin_library_well_known.js +5 -5
  49. package/package.json +12 -7
  50. package/src/lib/analysis_context.ts +250 -0
  51. package/src/lib/library_analysis.ts +168 -0
  52. package/src/lib/library_gen.ts +199 -83
  53. package/src/lib/library_gen_helpers.ts +148 -215
  54. package/src/lib/library_gen_output.ts +63 -0
  55. package/src/lib/mdz.ts +13 -4
  56. package/src/lib/module_helpers.ts +392 -47
  57. package/src/lib/svelte_helpers.ts +291 -55
  58. package/src/lib/ts_helpers.ts +538 -338
  59. package/src/lib/tsdoc_helpers.ts +24 -49
  60. package/src/lib/tsdoc_mdz.ts +62 -0
  61. package/src/lib/vite_plugin_library_well_known.ts +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"library_gen_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_gen_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,UAAU,EAAE,UAAU,EAAC,MAAM,iCAAiC,CAAC;AAE5E,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAErD,OAAO,EAA4B,KAAK,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAS7E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,oDAAoD;IACpD,MAAM,EAAE,UAAU,CAAC;IACnB,mEAAmE;IACnE,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAChC;AAED;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,GAAI,aAAa,UAAU,EAAE,KAAK,MAAM,KAAG,IAyCzF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,KAAK,CAAC,UAAU,CAAC,KAAG,KAAK,CAAC,UAAU,CAErF,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,GACrC,cAAc,WAAW,EACzB,aAAa,UAAU,KACrB,gBAuBF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAC5C,OAAO,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC5B,KAAK,MAAM,KACT,KAAK,CAAC,QAAQ,CAwBhB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,GAC3C,UAAU,QAAQ,EAClB,aAAa,MAAM,EACnB,SAAS,EAAE,CAAC,WAAW,KACrB,UAaF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,GAC/C,UAAU,QAAQ,EAClB,aAAa,EAAE,CAAC,UAAU,EAC1B,aAAa,MAAM,EACnB,SAAS,EAAE,CAAC,WAAW,KACrB,cA0BF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAC5C,UAAU,QAAQ,KAChB;IAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAuBzD,CAAC"}
1
+ {"version":3,"file":"library_gen_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_gen_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,eAAe,EAAE,UAAU,EAAE,UAAU,EAAC,MAAM,iCAAiC,CAAC;AAE7F,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,mBAAmB,EAIxB,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,qCAAqC;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,uBAAuB,GACnC,aAAa,UAAU,KACrB,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,CA0BlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,KAAK,CAAC,UAAU,CAAC,KAAG,KAAK,CAAC,UAAU,CAEjF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IACjC,kDAAkD;IAClD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qDAAqD;IACrD,SAAS,EAAE,YAAY,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,wBAAwB,GACpC,aAAa,UAAU,EACvB,sBAAsB,KAAK,CAAC,iBAAiB,CAAC,KAC5C,IAgCF,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,4BAA4B,GACxC,OAAO,QAAQ,CAAC,cAAc,CAAC,EAC/B,SAAS,mBAAmB,EAC5B,MAAM,MAAM,KACV,KAAK,CAAC,cAAc,CA0BtB,CAAC"}
@@ -1,198 +1,157 @@
1
1
  /**
2
- * Build-time helpers for library metadata generation.
2
+ * Library metadata generation helpers - pipeline orchestration.
3
3
  *
4
- * These functions handle Gro-specific concerns like file collection and dependency
5
- * graph extraction. Core analysis logic has been extracted to reusable helpers:
4
+ * These functions handle collection, validation, and transformation of library metadata
5
+ * during the generation pipeline. They are internal to the generation process.
6
6
  *
7
- * - `ts_helpers.ts` - `ts_analyze_module_exports`
8
- * - `svelte_helpers.ts` - `svelte_analyze_file`
9
- * - `module_helpers.ts` - path utilities and source detection
7
+ * For source analysis (the consumer-facing API), see `library_analysis.ts`.
10
8
  *
11
- * Design philosophy: Fail fast with clear errors rather than silently producing invalid
12
- * metadata. All validation errors halt the build immediately with actionable messages.
9
+ * Pipeline stages:
10
+ * 1. **Collection** - `library_collect_source_files` gathers and filters source files
11
+ * 2. **Analysis** - `library_analyze_module` (in library_analysis.ts) extracts metadata
12
+ * 3. **Validation** - `library_find_duplicates` checks flat namespace constraints
13
+ * 4. **Transformation** - `library_merge_re_exports` resolves re-export relationships
14
+ * 5. **Output** - `library_sort_modules` prepares deterministic output
13
15
  *
14
- * @see library_gen.ts for the main generation task
15
- * @see @fuzdev/fuz_util/source_json.js for type definitions
16
- * @see ts_helpers.ts for reusable TypeScript analysis
17
- * @see svelte_helpers.ts for reusable Svelte component analysis
16
+ * @see library_analysis.ts for the analysis entry point
17
+ * @see library_gen_output.ts for output file generation (JSON/TS wrapper)
18
+ * @see library_gen.ts for the main generation task (Gro-specific)
19
+ *
20
+ * @module
18
21
  */
19
- import { library_json_parse } from '@fuzdev/fuz_util/library_json.js';
20
- import { ts_analyze_module_exports } from './ts_helpers.js';
21
- import { svelte_analyze_file } from './svelte_helpers.js';
22
- import { module_extract_path, module_is_typescript, module_is_svelte, module_matches_source, } from './module_helpers.js';
22
+ import { module_is_source, module_validate_source_options, module_get_source_root, } from './module_helpers.js';
23
23
  /**
24
- * Validates that no declaration names are duplicated across modules.
25
- * The flat namespace is intentional - duplicates should fail fast.
24
+ * Find duplicate declaration names across modules.
25
+ *
26
+ * Returns a Map of declaration names to their full metadata (only includes duplicates).
27
+ * Callers can decide how to handle duplicates (throw, warn, ignore).
26
28
  *
27
- * @throws Error if duplicate declaration names are found
29
+ * @example
30
+ * const duplicates = library_find_duplicates(source_json);
31
+ * if (duplicates.size > 0) {
32
+ * for (const [name, occurrences] of duplicates) {
33
+ * console.error(`"${name}" found in:`);
34
+ * for (const {declaration, module} of occurrences) {
35
+ * console.error(` - ${module}:${declaration.source_line} (${declaration.kind})`);
36
+ * }
37
+ * }
38
+ * throw new Error(`Found ${duplicates.size} duplicate declaration names`);
39
+ * }
28
40
  */
29
- export const library_gen_validate_no_duplicates = (source_json, log) => {
30
- const declaration_locations = new Map();
31
- // Collect all declaration names and their locations
41
+ export const library_find_duplicates = (source_json) => {
42
+ const all_occurrences = new Map();
43
+ // Collect all declaration names and their full metadata
32
44
  for (const mod of source_json.modules ?? []) {
33
45
  for (const declaration of mod.declarations ?? []) {
34
46
  const name = declaration.name;
35
- if (!declaration_locations.has(name)) {
36
- declaration_locations.set(name, []);
47
+ if (!all_occurrences.has(name)) {
48
+ all_occurrences.set(name, []);
37
49
  }
38
- declaration_locations.get(name).push({
50
+ all_occurrences.get(name).push({
51
+ declaration,
39
52
  module: mod.path,
40
- kind: declaration.kind,
41
53
  });
42
54
  }
43
55
  }
44
- // Check for duplicates
45
- const duplicates = [];
46
- for (const [name, locations] of declaration_locations.entries()) {
47
- if (locations.length > 1) {
48
- duplicates.push({ name, locations });
49
- }
50
- }
51
- if (duplicates.length > 0) {
52
- log.error('Duplicate declaration names detected in flat namespace:');
53
- for (const { name, locations } of duplicates) {
54
- log.error(` "${name}" found in:`);
55
- for (const { module, kind } of locations) {
56
- log.error(` - ${module} (${kind})`);
57
- }
56
+ // Filter to only duplicates
57
+ const duplicates = new Map();
58
+ for (const [name, occurrences] of all_occurrences) {
59
+ if (occurrences.length > 1) {
60
+ duplicates.set(name, occurrences);
58
61
  }
59
- throw new Error(`Found ${duplicates.length} duplicate declaration name${duplicates.length === 1 ? '' : 's'} across modules. ` +
60
- 'The flat namespace requires unique names. To resolve: ' +
61
- '(1) rename one of the conflicting declarations, or ' +
62
- '(2) add /** @nodocs */ to exclude from documentation. ' +
63
- 'See CLAUDE.md "Declaration namespacing" section for details.');
64
62
  }
63
+ return duplicates;
65
64
  };
66
65
  /**
67
66
  * Sort modules alphabetically by path for deterministic output and cleaner diffs.
68
67
  */
69
- export const library_gen_sort_modules = (modules) => {
68
+ export const library_sort_modules = (modules) => {
70
69
  return modules.slice().sort((a, b) => a.path.localeCompare(b.path));
71
70
  };
72
71
  /**
73
- * Generate the library.json and library.ts file contents.
74
- * Parses at generation time so runtime only needs the pre-computed result.
72
+ * Build `also_exported_from` arrays from collected re-export data.
75
73
  *
76
- * Returns JSON + .ts wrapper because:
77
- * - JSON is natively importable by Node.js and Vite without TypeScript loaders
78
- * - Works in CI environments that don't have TS compilation
79
- * - The .ts wrapper validates with zod and exports with proper types
80
- * (JSON imports get widened types like `string` instead of literal unions)
81
- */
82
- export const library_gen_generate_json = (package_json, source_json) => {
83
- const is_this_fuz_util = package_json.name === '@fuzdev/fuz_util';
84
- const fuz_util_prefix = is_this_fuz_util ? './' : '@fuzdev/fuz_util/';
85
- // Parse at generation time, not runtime
86
- const library_json = library_json_parse(package_json, source_json);
87
- const json_content = JSON.stringify(library_json, null, '\t') + '\n';
88
- const banner = '// generated by library.gen.ts - do not edit';
89
- const ts_content = `${banner}
90
-
91
- import type {LibraryJson} from '${fuz_util_prefix}library_json.js';
92
-
93
- import json from './library.json' with {type: 'json'};
94
-
95
- export const library_json: LibraryJson = json as LibraryJson;
96
-
97
- ${banner}
98
- `;
99
- return { json_content, ts_content };
100
- };
101
- /**
102
- * Collect and filter source files from filer.
74
+ * This function resolves the two-phase re-export problem:
103
75
  *
104
- * Returns disknodes for TypeScript/JS files and Svelte components from src/lib, excluding test files.
105
- * Returns an empty array with a warning if no source files are found.
106
- */
107
- export const library_gen_collect_source_files = (files, log) => {
108
- log.info(`filer has ${files.size} files total`);
109
- const source_disknodes = [];
110
- for (const [id, disknode] of files.entries()) {
111
- if (module_matches_source(id)) {
112
- // Include TypeScript/JS files and Svelte components
113
- if (module_is_typescript(id) || module_is_svelte(id)) {
114
- source_disknodes.push(disknode);
115
- }
116
- }
117
- }
118
- log.info(`found ${source_disknodes.length} source files to analyze`);
119
- if (source_disknodes.length === 0) {
120
- log.warn('No source files found in src/lib - generating empty library metadata');
121
- return [];
122
- }
123
- // Sort for deterministic output (stable alphabetical module ordering)
124
- source_disknodes.sort((a, b) => a.id.localeCompare(b.id));
125
- return source_disknodes;
126
- };
127
- /**
128
- * Analyze a Svelte component file and extract metadata.
76
+ * **Problem**: When module A re-exports from module B, we discover this while
77
+ * analyzing A, but need to update B's declarations. However, B may already be
78
+ * processed or may be processed later.
129
79
  *
130
- * Uses `svelte_analyze_file` for core analysis, then adds
131
- * Gro-specific dependency information from the disknode.
132
- */
133
- export const library_gen_analyze_svelte_file = (disknode, module_path, checker) => {
134
- // Use the extracted helper for core analysis
135
- const declaration_json = svelte_analyze_file(disknode.id, module_path, checker);
136
- // Extract dependencies and dependents (Gro-specific)
137
- const { dependencies, dependents } = library_gen_extract_dependencies(disknode);
138
- return {
139
- path: module_path,
140
- declarations: [declaration_json],
141
- dependencies: dependencies.length > 0 ? dependencies : undefined,
142
- dependents: dependents.length > 0 ? dependents : undefined,
143
- };
144
- };
145
- /**
146
- * Analyze a TypeScript file and extract all declarations.
80
+ * **Solution**: Collect all re-exports in phase 1, then merge them in phase 2
81
+ * after all modules are analyzed.
147
82
  *
148
- * Uses `ts_analyze_module_exports` for core analysis, then adds
149
- * Gro-specific dependency information from the disknode.
83
+ * @example
84
+ * // helpers.ts exports: foo, bar
85
+ * // index.ts does: export {foo, bar} from './helpers.js'
86
+ * //
87
+ * // After processing:
88
+ * // - helpers.ts foo declaration gets: also_exported_from: ['index.ts']
89
+ * // - helpers.ts bar declaration gets: also_exported_from: ['index.ts']
150
90
  *
151
- * Returns both the module metadata and re-export information for post-processing.
91
+ * @param source_json The source JSON with all modules (will be mutated)
92
+ * @param collected_re_exports Array of re-exports collected during phase 1
93
+ * @mutates source_json - adds `also_exported_from` to declarations
152
94
  */
153
- export const library_gen_analyze_typescript_file = (disknode, source_file, module_path, checker) => {
154
- // Use the extracted helper for core analysis
155
- const { module_comment, declarations, re_exports } = ts_analyze_module_exports(source_file, checker);
156
- const mod = {
157
- path: module_path,
158
- declarations,
159
- };
160
- if (module_comment) {
161
- mod.module_comment = module_comment;
162
- }
163
- // Extract dependencies and dependents (Gro-specific)
164
- const { dependencies, dependents } = library_gen_extract_dependencies(disknode);
165
- if (dependencies.length > 0) {
166
- mod.dependencies = dependencies;
95
+ export const library_merge_re_exports = (source_json, collected_re_exports) => {
96
+ // Group re-exports by original module and declaration name
97
+ // Structure: Map<original_module_path, Map<declaration_name, Array<re_exporting_module_path>>>
98
+ const re_export_map = new Map();
99
+ for (const { re_exporting_module, re_export } of collected_re_exports) {
100
+ const { name, original_module } = re_export;
101
+ if (!re_export_map.has(original_module)) {
102
+ re_export_map.set(original_module, new Map());
103
+ }
104
+ const module_map = re_export_map.get(original_module);
105
+ if (!module_map.has(name)) {
106
+ module_map.set(name, []);
107
+ }
108
+ module_map.get(name).push(re_exporting_module);
167
109
  }
168
- if (dependents.length > 0) {
169
- mod.dependents = dependents;
110
+ // Merge into original declarations
111
+ for (const mod of source_json.modules ?? []) {
112
+ const module_re_exports = re_export_map.get(mod.path);
113
+ if (!module_re_exports)
114
+ continue;
115
+ for (const declaration of mod.declarations ?? []) {
116
+ const re_exporters = module_re_exports.get(declaration.name);
117
+ if (re_exporters?.length) {
118
+ // Sort for deterministic output
119
+ declaration.also_exported_from = re_exporters.sort();
120
+ }
121
+ }
170
122
  }
171
- return { module: mod, re_exports };
172
123
  };
173
124
  /**
174
- * Extract dependencies and dependents for a module from the filer's dependency graph.
125
+ * Collect and filter source files.
126
+ *
127
+ * Returns source files for TypeScript/JS files and Svelte components, excluding test files.
128
+ * Returns an empty array with a warning if no source files are found.
175
129
  *
176
- * Filters to only include source modules from src/lib (excludes external packages, node_modules, tests).
177
- * Returns sorted arrays of module paths (relative to src/lib) for deterministic output.
130
+ * File types are determined by `options.get_analyzer`. By default, `.ts`, `.js`, and `.svelte`
131
+ * files are supported. Customize `get_analyzer` to support additional file types like `.svx`.
132
+ *
133
+ * @param files Iterable of source file info (from Gro filer, file system, or other source)
134
+ * @param options Module source options for filtering
135
+ * @param log Optional logger for status messages
178
136
  */
179
- export const library_gen_extract_dependencies = (disknode) => {
180
- const dependencies = [];
181
- const dependents = [];
182
- // Extract dependencies (files this module imports)
183
- for (const dep_id of disknode.dependencies.keys()) {
184
- if (module_matches_source(dep_id)) {
185
- dependencies.push(module_extract_path(dep_id));
137
+ export const library_collect_source_files = (files, options, log) => {
138
+ // Validate options early to fail fast on misconfiguration
139
+ module_validate_source_options(options);
140
+ const all_files = Array.from(files);
141
+ log?.info(`received ${all_files.length} files total`);
142
+ const source_files = [];
143
+ for (const file of all_files) {
144
+ if (module_is_source(file.id, options)) {
145
+ source_files.push(file);
186
146
  }
187
147
  }
188
- // Extract dependents (files that import this module)
189
- for (const dependent_id of disknode.dependents.keys()) {
190
- if (module_matches_source(dependent_id)) {
191
- dependents.push(module_extract_path(dependent_id));
192
- }
148
+ log?.info(`found ${source_files.length} source files to analyze`);
149
+ if (source_files.length === 0) {
150
+ const effective_root = module_get_source_root(options);
151
+ log?.warn(`No source files found in ${effective_root} - generating empty library metadata`);
152
+ return [];
193
153
  }
194
- // Sort for deterministic output
195
- dependencies.sort();
196
- dependents.sort();
197
- return { dependencies, dependents };
154
+ // Sort for deterministic output (stable alphabetical module ordering)
155
+ source_files.sort((a, b) => a.id.localeCompare(b.id));
156
+ return source_files;
198
157
  };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Library output generation.
3
+ *
4
+ * Generates the library.json and library.ts files from analyzed metadata.
5
+ *
6
+ * @see library_gen_helpers.ts for orchestration functions
7
+ * @see library_gen.ts for the main generation task (Gro-specific)
8
+ *
9
+ * @module
10
+ */
11
+ import type { PackageJson } from '@fuzdev/fuz_util/package_json.js';
12
+ import type { SourceJson } from '@fuzdev/fuz_util/source_json.js';
13
+ /**
14
+ * Result of generating library files.
15
+ * Contains both the JSON data and the TypeScript wrapper file.
16
+ */
17
+ export interface LibraryGenResult {
18
+ /** JSON content for library.json */
19
+ json_content: string;
20
+ /** TypeScript wrapper content for library.ts */
21
+ ts_content: string;
22
+ }
23
+ /**
24
+ * Generate the library.json and library.ts file contents.
25
+ * Parses at generation time so runtime only needs the pre-computed result.
26
+ *
27
+ * Returns JSON + .ts wrapper because:
28
+ * - JSON is natively importable by Node.js and Vite without TypeScript loaders
29
+ * - Works in CI environments that don't have TS compilation
30
+ * - The .ts wrapper validates with zod and exports with proper types
31
+ * (JSON imports get widened types like `string` instead of literal unions)
32
+ */
33
+ export declare const library_generate_json: (package_json: PackageJson, source_json: SourceJson) => LibraryGenResult;
34
+ //# sourceMappingURL=library_gen_output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library_gen_output.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_gen_output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iCAAiC,CAAC;AAGhE;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,GACjC,cAAc,WAAW,EACzB,aAAa,UAAU,KACrB,gBAuBF,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Library output generation.
3
+ *
4
+ * Generates the library.json and library.ts files from analyzed metadata.
5
+ *
6
+ * @see library_gen_helpers.ts for orchestration functions
7
+ * @see library_gen.ts for the main generation task (Gro-specific)
8
+ *
9
+ * @module
10
+ */
11
+ import { library_json_parse } from '@fuzdev/fuz_util/library_json.js';
12
+ /**
13
+ * Generate the library.json and library.ts file contents.
14
+ * Parses at generation time so runtime only needs the pre-computed result.
15
+ *
16
+ * Returns JSON + .ts wrapper because:
17
+ * - JSON is natively importable by Node.js and Vite without TypeScript loaders
18
+ * - Works in CI environments that don't have TS compilation
19
+ * - The .ts wrapper validates with zod and exports with proper types
20
+ * (JSON imports get widened types like `string` instead of literal unions)
21
+ */
22
+ export const library_generate_json = (package_json, source_json) => {
23
+ const is_this_fuz_util = package_json.name === '@fuzdev/fuz_util';
24
+ const fuz_util_prefix = is_this_fuz_util ? './' : '@fuzdev/fuz_util/';
25
+ // Parse at generation time, not runtime
26
+ const library_json = library_json_parse(package_json, source_json);
27
+ const json_content = JSON.stringify(library_json, null, '\t') + '\n';
28
+ const banner = '// generated by library.gen.ts - do not edit';
29
+ const ts_content = `${banner}
30
+
31
+ import type {LibraryJson} from '${fuz_util_prefix}library_json.js';
32
+
33
+ import json from './library.json' with {type: 'json'};
34
+
35
+ export const library_json: LibraryJson = json as LibraryJson;
36
+
37
+ ${banner}
38
+ `;
39
+ return { json_content, ts_content };
40
+ };
package/dist/mdz.d.ts CHANGED
@@ -25,6 +25,8 @@
25
25
  * ## Status
26
26
  *
27
27
  * This is an early proof of concept with missing features and edge cases.
28
+ *
29
+ * @module
28
30
  */
29
31
  /**
30
32
  * Parses text to an array of `MdzNode`.
@@ -103,4 +105,5 @@ export declare class MdzParser {
103
105
  */
104
106
  parse(): Array<MdzNode>;
105
107
  }
108
+ export declare const mdz_is_url: (s: string) => boolean;
106
109
  //# sourceMappingURL=mdz.d.ts.map
package/dist/mdz.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mdz.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,KAAK,CAAC,OAAO,CAAgC,CAAC;AAEvF,MAAM,MAAM,OAAO,GAChB,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,WAAW,GACX,aAAa,GACb,oBAAoB,GACpB,WAAW,GACX,gBAAgB,GAChB,SAAS,GACT,cAAc,GACd,cAAc,GACd,gBAAgB,CAAC;AAEpB,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,aAAc,SAAQ,WAAW;IACjD,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACxD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACzB,SAAS,EAAE,UAAU,GAAG,UAAU,CAAC;CACnC;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC7C,IAAI,EAAE,IAAI,CAAC;CACX;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW;IAClD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW;IAClD,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AA+CD;;;;GAIG;AACH,qBAAa,SAAS;;gBAQT,QAAQ,EAAE,MAAM;IAI5B;;;OAGG;IACH,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;CA+lDvB"}
1
+ {"version":3,"file":"mdz.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,KAAK,CAAC,OAAO,CAAgC,CAAC;AAEvF,MAAM,MAAM,OAAO,GAChB,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,WAAW,GACX,aAAa,GACb,oBAAoB,GACpB,WAAW,GACX,gBAAgB,GAChB,SAAS,GACT,cAAc,GACd,cAAc,GACd,gBAAgB,CAAC;AAEpB,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,aAAc,SAAQ,WAAW;IACjD,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACxD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACzB,SAAS,EAAE,UAAU,GAAG,UAAU,CAAC;CACnC;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC7C,IAAI,EAAE,IAAI,CAAC;CACX;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW;IAClD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW;IAClD,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACpD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CACzB;AA+CD;;;;GAIG;AACH,qBAAa,SAAS;;gBAQT,QAAQ,EAAE,MAAM;IAI5B;;;OAGG;IACH,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;CA8lDvB;AAQD,eAAO,MAAM,UAAU,GAAI,GAAG,MAAM,KAAG,OAA8B,CAAC"}
package/dist/mdz.js CHANGED
@@ -25,6 +25,8 @@
25
25
  * ## Status
26
26
  *
27
27
  * This is an early proof of concept with missing features and edge cases.
28
+ *
29
+ * @module
28
30
  */
29
31
  // TODO design incremental parsing or some system that preserves Svelte components across re-renders when possible
30
32
  /**
@@ -489,7 +491,7 @@ export class MdzParser {
489
491
  }
490
492
  this.#index = close_paren + 1;
491
493
  // Determine link type (external vs internal)
492
- const link_type = reference.startsWith('https://') || reference.startsWith('http://') ? 'external' : 'internal';
494
+ const link_type = mdz_is_url(reference) ? 'external' : 'internal';
493
495
  return {
494
496
  type: 'Link',
495
497
  reference,
@@ -841,7 +843,7 @@ export class MdzParser {
841
843
  char_code === PERCENT);
842
844
  }
843
845
  /**
844
- * Check if current position is the start of an external URL (https:// or http://).
846
+ * Check if current position is the start of an external URL (`https://` or `http://`).
845
847
  */
846
848
  #is_at_url() {
847
849
  if (this.#match('https://')) {
@@ -889,7 +891,7 @@ export class MdzParser {
889
891
  return next_char !== SLASH && next_char !== SPACE && next_char !== NEWLINE;
890
892
  }
891
893
  /**
892
- * Parse auto-detected external URL (https:// or http://).
894
+ * Parse auto-detected external URL (`https://` or `http://`).
893
895
  * Uses RFC 3986 whitelist validation for valid URI characters.
894
896
  */
895
897
  #parse_auto_link_url() {
@@ -1479,3 +1481,10 @@ export class MdzParser {
1479
1481
  throw Error('Code block not properly closed');
1480
1482
  }
1481
1483
  }
1484
+ /**
1485
+ * Check if a string is a URL (`https://` or `http://`).
1486
+ * Requires at least one valid character after the protocol.
1487
+ * Rejects whitespace and characters that can't start a valid hostname.
1488
+ */
1489
+ const URL_PATTERN = /^https?:\/\/[^\s)\]}<>.,:/?#!]/;
1490
+ export const mdz_is_url = (s) => URL_PATTERN.test(s);