@fuzdev/fuz_ui 0.198.1 → 0.200.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 (113) hide show
  1. package/dist/ApiDeclarationList.svelte +2 -1
  2. package/dist/ApiDeclarationList.svelte.d.ts.map +1 -1
  3. package/dist/ApiIndex.svelte +2 -2
  4. package/dist/ApiModule.svelte +3 -3
  5. package/dist/DeclarationDetail.svelte +145 -90
  6. package/dist/DeclarationDetail.svelte.d.ts.map +1 -1
  7. package/dist/LibraryDetail.svelte +14 -16
  8. package/dist/LibraryDetail.svelte.d.ts.map +1 -1
  9. package/dist/LibrarySummary.svelte +12 -12
  10. package/dist/Mdz.svelte +2 -2
  11. package/dist/MdzNodeView.svelte +8 -6
  12. package/dist/MdzNodeView.svelte.d.ts.map +1 -1
  13. package/dist/MdzRoot.svelte +30 -0
  14. package/dist/MdzRoot.svelte.d.ts +12 -0
  15. package/dist/MdzRoot.svelte.d.ts.map +1 -0
  16. package/dist/MdzStream.svelte +32 -0
  17. package/dist/MdzStream.svelte.d.ts +12 -0
  18. package/dist/MdzStream.svelte.d.ts.map +1 -0
  19. package/dist/MdzStreamNodeView.svelte +106 -0
  20. package/dist/MdzStreamNodeView.svelte.d.ts +9 -0
  21. package/dist/MdzStreamNodeView.svelte.d.ts.map +1 -0
  22. package/dist/ProjectLinks.svelte +1 -1
  23. package/dist/api_search.svelte.d.ts.map +1 -1
  24. package/dist/api_search.svelte.js +4 -2
  25. package/dist/declaration.svelte.d.ts +11 -0
  26. package/dist/declaration.svelte.d.ts.map +1 -1
  27. package/dist/declaration.svelte.js +15 -3
  28. package/dist/library.svelte.d.ts +9 -70
  29. package/dist/library.svelte.d.ts.map +1 -1
  30. package/dist/library.svelte.js +24 -18
  31. package/dist/library_helpers.d.ts +3 -3
  32. package/dist/library_helpers.js +3 -3
  33. package/dist/mdz.d.ts.map +1 -1
  34. package/dist/mdz.js +37 -29
  35. package/dist/mdz_components.d.ts +37 -23
  36. package/dist/mdz_components.d.ts.map +1 -1
  37. package/dist/mdz_components.js +16 -4
  38. package/dist/mdz_helpers.d.ts +46 -14
  39. package/dist/mdz_helpers.d.ts.map +1 -1
  40. package/dist/mdz_helpers.js +189 -56
  41. package/dist/mdz_lexer.d.ts.map +1 -1
  42. package/dist/mdz_lexer.js +18 -22
  43. package/dist/mdz_opcodes.d.ts +174 -0
  44. package/dist/mdz_opcodes.d.ts.map +1 -0
  45. package/dist/mdz_opcodes.js +14 -0
  46. package/dist/mdz_opcodes_to_nodes.d.ts +20 -0
  47. package/dist/mdz_opcodes_to_nodes.d.ts.map +1 -0
  48. package/dist/mdz_opcodes_to_nodes.js +332 -0
  49. package/dist/mdz_stream_parser.d.ts +80 -0
  50. package/dist/mdz_stream_parser.d.ts.map +1 -0
  51. package/dist/mdz_stream_parser.js +354 -0
  52. package/dist/mdz_stream_parser_block.d.ts +76 -0
  53. package/dist/mdz_stream_parser_block.d.ts.map +1 -0
  54. package/dist/mdz_stream_parser_block.js +458 -0
  55. package/dist/mdz_stream_parser_inline.d.ts +52 -0
  56. package/dist/mdz_stream_parser_inline.d.ts.map +1 -0
  57. package/dist/mdz_stream_parser_inline.js +378 -0
  58. package/dist/mdz_stream_parser_link.d.ts +22 -0
  59. package/dist/mdz_stream_parser_link.d.ts.map +1 -0
  60. package/dist/mdz_stream_parser_link.js +215 -0
  61. package/dist/mdz_stream_parser_state.d.ts +187 -0
  62. package/dist/mdz_stream_parser_state.d.ts.map +1 -0
  63. package/dist/mdz_stream_parser_state.js +398 -0
  64. package/dist/mdz_stream_parser_text.d.ts +14 -0
  65. package/dist/mdz_stream_parser_text.d.ts.map +1 -0
  66. package/dist/mdz_stream_parser_text.js +50 -0
  67. package/dist/mdz_stream_parser_url.d.ts +60 -0
  68. package/dist/mdz_stream_parser_url.d.ts.map +1 -0
  69. package/dist/mdz_stream_parser_url.js +307 -0
  70. package/dist/mdz_stream_state.svelte.d.ts +44 -0
  71. package/dist/mdz_stream_state.svelte.d.ts.map +1 -0
  72. package/dist/mdz_stream_state.svelte.js +357 -0
  73. package/dist/mdz_token_parser.d.ts.map +1 -1
  74. package/dist/mdz_token_parser.js +8 -39
  75. package/dist/module.svelte.d.ts +2 -0
  76. package/dist/module.svelte.d.ts.map +1 -1
  77. package/dist/module.svelte.js +3 -1
  78. package/dist/site.svelte.d.ts +13 -0
  79. package/dist/site.svelte.d.ts.map +1 -1
  80. package/dist/site.svelte.js +8 -2
  81. package/dist/tsdoc_mdz.d.ts +2 -2
  82. package/dist/tsdoc_mdz.js +2 -2
  83. package/dist/vite_plugin_pkg_json.d.ts +63 -0
  84. package/dist/vite_plugin_pkg_json.d.ts.map +1 -0
  85. package/dist/vite_plugin_pkg_json.js +126 -0
  86. package/package.json +8 -7
  87. package/src/lib/api_search.svelte.ts +4 -2
  88. package/src/lib/declaration.svelte.ts +18 -3
  89. package/src/lib/library.svelte.ts +37 -20
  90. package/src/lib/library_helpers.ts +3 -3
  91. package/src/lib/mdz.ts +38 -29
  92. package/src/lib/mdz_components.ts +40 -19
  93. package/src/lib/mdz_helpers.ts +199 -56
  94. package/src/lib/mdz_lexer.ts +18 -20
  95. package/src/lib/mdz_opcodes.ts +205 -0
  96. package/src/lib/mdz_opcodes_to_nodes.ts +375 -0
  97. package/src/lib/mdz_stream_parser.ts +415 -0
  98. package/src/lib/mdz_stream_parser_block.ts +532 -0
  99. package/src/lib/mdz_stream_parser_inline.ts +414 -0
  100. package/src/lib/mdz_stream_parser_link.ts +271 -0
  101. package/src/lib/mdz_stream_parser_state.ts +539 -0
  102. package/src/lib/mdz_stream_parser_text.ts +77 -0
  103. package/src/lib/mdz_stream_parser_url.ts +365 -0
  104. package/src/lib/mdz_stream_state.svelte.ts +387 -0
  105. package/src/lib/mdz_token_parser.ts +13 -40
  106. package/src/lib/module.svelte.ts +5 -1
  107. package/src/lib/site.svelte.ts +17 -2
  108. package/src/lib/tsdoc_mdz.ts +2 -2
  109. package/src/lib/vite_plugin_pkg_json.ts +142 -0
  110. package/dist/package_helpers.d.ts +0 -150
  111. package/dist/package_helpers.d.ts.map +0 -1
  112. package/dist/package_helpers.js +0 -179
  113. package/src/lib/package_helpers.ts +0 -186
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import type {SvelteHTMLElements} from 'svelte/elements';
3
+
4
+ import MdzStreamNodeView from './MdzStreamNodeView.svelte';
5
+ import {mdz_base_context, set_mdz_context_with_fallback} from './mdz_components.js';
6
+ import type {MdzStreamState} from './mdz_stream_state.svelte.js';
7
+
8
+ const {
9
+ state,
10
+ inline = false,
11
+ nowrap = false,
12
+ base,
13
+ ...rest
14
+ }: (SvelteHTMLElements['div'] | SvelteHTMLElements['span']) & {
15
+ state: MdzStreamState;
16
+ inline?: boolean;
17
+ nowrap?: boolean;
18
+ base?: string;
19
+ } = $props();
20
+
21
+ set_mdz_context_with_fallback(mdz_base_context, () => base);
22
+ </script>
23
+
24
+ <svelte:element
25
+ this={inline ? 'span' : 'div'}
26
+ {...rest}
27
+ style:white-space={nowrap ? 'pre' : 'pre-wrap'}
28
+ >
29
+ {#each state.root as node (node.id)}
30
+ <MdzStreamNodeView {node} />
31
+ {/each}
32
+ </svelte:element>
@@ -0,0 +1,12 @@
1
+ import type { SvelteHTMLElements } from 'svelte/elements';
2
+ import type { MdzStreamState } from './mdz_stream_state.svelte.js';
3
+ type $$ComponentProps = (SvelteHTMLElements['div'] | SvelteHTMLElements['span']) & {
4
+ state: MdzStreamState;
5
+ inline?: boolean;
6
+ nowrap?: boolean;
7
+ base?: string;
8
+ };
9
+ declare const MdzStream: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type MdzStream = ReturnType<typeof MdzStream>;
11
+ export default MdzStream;
12
+ //# sourceMappingURL=MdzStream.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MdzStream.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/MdzStream.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAIxD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAEhE,KAAK,gBAAgB,GAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,GAAG;IACnF,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AA2BH,QAAA,MAAM,SAAS,sDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -0,0 +1,106 @@
1
+ <script lang="ts">
2
+ import Code from '@fuzdev/fuz_code/Code.svelte';
3
+ import {resolve} from '$app/paths';
4
+
5
+ import {resolve_relative_path, mdz_is_safe_reference} from './mdz_helpers.js';
6
+ import DocsLink from './DocsLink.svelte';
7
+ import MdzStreamNodeView from './MdzStreamNodeView.svelte';
8
+ import {
9
+ mdz_components_context,
10
+ mdz_elements_context,
11
+ mdz_base_context,
12
+ } from './mdz_components.js';
13
+ import type {MdzStreamNode} from './mdz_stream_state.svelte.js';
14
+
15
+ const {
16
+ node,
17
+ }: {
18
+ node: MdzStreamNode;
19
+ } = $props();
20
+
21
+ const get_components = mdz_components_context.get_maybe();
22
+ const get_elements = mdz_elements_context.get_maybe();
23
+ const get_mdz_base = mdz_base_context.get_maybe();
24
+ </script>
25
+
26
+ {#if node.type === 'Element'}
27
+ {@const element_config = get_elements?.()?.get(node.name ?? '')}
28
+ {#if element_config !== undefined}
29
+ <svelte:element this={node.name}>
30
+ {#if node.children.length > 0}
31
+ {@render render_children(node.children)}
32
+ {/if}
33
+ </svelte:element>
34
+ {:else}
35
+ {@render render_unregistered_tag(node.name ?? '', node.children)}
36
+ {/if}
37
+ {:else if node.type === 'Component'}
38
+ {@const Component = get_components?.()?.get(node.name ?? '')}
39
+ {#if Component}
40
+ <Component>
41
+ {#if node.children.length > 0}
42
+ {@render render_children(node.children)}
43
+ {/if}
44
+ </Component>
45
+ {:else}
46
+ {@render render_unregistered_tag(node.name ?? '', node.children)}
47
+ {/if}
48
+ {:else if node.type === 'Text'}
49
+ {node.content}
50
+ {:else if node.type === 'Code'}
51
+ <DocsLink reference={node.content} />
52
+ {:else if node.type === 'Bold'}
53
+ <strong>{@render render_children(node.children)}</strong>
54
+ {:else if node.type === 'Italic'}
55
+ <em>{@render render_children(node.children)}</em>
56
+ {:else if node.type === 'Strikethrough'}
57
+ <s>{@render render_children(node.children)}</s>
58
+ {:else if node.type === 'Link'}
59
+ {@const reference = node.reference ?? ''}
60
+ {#if !mdz_is_safe_reference(reference)}
61
+ {@render render_children(node.children)}
62
+ {:else if node.link_type === 'internal'}
63
+ {@const skip_resolve = reference.startsWith('#') || reference.startsWith('?')}
64
+ {@const mdz_base = get_mdz_base?.()}
65
+ {#if reference.startsWith('.') && mdz_base}
66
+ {@const resolved = resolve_relative_path(reference, mdz_base)}
67
+ <a href={resolve(resolved as any)}>{@render render_children(node.children)}</a>
68
+ {:else if skip_resolve || reference.startsWith('.')}
69
+ <!-- Fragment, query, and relative links without base skip resolve() -->
70
+ <!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
71
+ <a href={reference}>{@render render_children(node.children)}</a>
72
+ {:else}
73
+ <a href={resolve(reference as any)}>{@render render_children(node.children)}</a>
74
+ {/if}
75
+ {:else}
76
+ <!-- external link -->
77
+ <!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
78
+ <a href={reference} target="_blank" rel="noopener">{@render render_children(node.children)}</a>
79
+ {/if}
80
+ {:else if node.type === 'Paragraph'}
81
+ <p>{@render render_children(node.children)}</p>
82
+ {:else if node.type === 'Hr'}
83
+ <hr />
84
+ {:else if node.type === 'Heading'}
85
+ <svelte:element this={`h${node.level}`} id={node.heading_id}>
86
+ {@render render_children(node.children)}
87
+ </svelte:element>
88
+ {:else if node.type === 'Codeblock'}
89
+ <Code lang={node.lang} content={node.content} />
90
+ {/if}
91
+
92
+ {#snippet render_children(nodes: Array<MdzStreamNode>)}
93
+ {#each nodes as node (node.id)}
94
+ <MdzStreamNodeView {node} />
95
+ {/each}
96
+ {/snippet}
97
+
98
+ {#snippet render_unregistered_tag(name: string, children: Array<MdzStreamNode>)}
99
+ {#if children.length > 0}
100
+ <code class="color_c_50">&lt;{name}&gt;</code>{@render render_children(children)}<code
101
+ class="color_c_50">&lt;/{name}&gt;</code
102
+ >
103
+ {:else}
104
+ <code class="color_c_50">&lt;{name} /&gt;</code>
105
+ {/if}
106
+ {/snippet}
@@ -0,0 +1,9 @@
1
+ import MdzStreamNodeView from './MdzStreamNodeView.svelte';
2
+ import type { MdzStreamNode } from './mdz_stream_state.svelte.js';
3
+ type $$ComponentProps = {
4
+ node: MdzStreamNode;
5
+ };
6
+ declare const MdzStreamNodeView: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type MdzStreamNodeView = ReturnType<typeof MdzStreamNodeView>;
8
+ export default MdzStreamNodeView;
9
+ //# sourceMappingURL=MdzStreamNodeView.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MdzStreamNodeView.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/MdzStreamNodeView.svelte"],"names":[],"mappings":"AAQA,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAM3D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAE/D,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,aAAa,CAAC;CACpB,CAAC;AAsGH,QAAA,MAAM,iBAAiB,sDAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
@@ -35,8 +35,8 @@
35
35
  {name: 'fuz_css', url: 'https://css.fuz.dev/', logo: logo_fuz_css, description: 'CSS framework and design system', glyph: '🌿', color_class: 'color_b_50'},
36
36
  {name: 'fuz_ui', url: 'https://ui.fuz.dev/', logo: logo_fuz_ui, description: 'Svelte UI library', glyph: '🧶', color_class: 'color_c_50'},
37
37
  {name: 'fuz_template', url: 'https://template.fuz.dev/', logo: logo_fuz_template, description: 'a static web app and Node library template with TypeScript, Svelte, SvelteKit, Vite, esbuild, Fuz, and Gro', glyph: '❄', color_class: 'color_h_50'},
38
- {name: 'fuz_code', url: 'https://code.fuz.dev/', logo: logo_fuz_code, description: 'syntax styling utilities and components for TypeScript, Svelte, SvelteKit', glyph: '🎨', color_class: 'color_g_50'},
39
38
  {name: 'fuz_blog', url: 'https://blog.fuz.dev/', logo: logo_fuz_blog, description: 'blog software from scratch with SvelteKit', glyph: '🖊️', color_class: 'color_e_50'},
39
+ {name: 'fuz_code', url: 'https://code.fuz.dev/', logo: logo_fuz_code, description: 'syntax styling utilities and components for TypeScript, Svelte, SvelteKit', glyph: '🎨', color_class: 'color_g_50'},
40
40
  {name: 'fuz_mastodon', url: 'https://mastodon.fuz.dev/', logo: logo_fuz_mastodon, description: 'Mastodon components and helpers for Svelte, SvelteKit, and Fuz', glyph: '🦣', color_class: 'color_d_50'},
41
41
  {name: 'fuz_gitops', url: 'https://gitops.fuz.dev/', logo: logo_fuz_gitops, description: 'a tool for managing many repos', glyph: '🪄', color_class: 'color_a_50'},
42
42
  {name: 'fuz_docs', url: 'https://docs.fuz.dev/', logo: logo_fuz_docs, description: 'AI-generated documentation and skills for the Fuz stack', glyph: '📜', color_class: 'color_i_50'},
@@ -1 +1 @@
1
- {"version":3,"file":"api_search.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/api_search.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAE/C,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IACxB,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QACR,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACnB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KACxB,CAAC;IACF,YAAY,EAAE;QACb,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QACxB,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;KAC7B,CAAC;CACF;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,OAAO,KAAG,cA8CpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gCAAgC,GAC5C,cAAc,KAAK,CAAC,WAAW,CAAC,KAC9B,sBAyCF,CAAC"}
1
+ {"version":3,"file":"api_search.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/api_search.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAE/C,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IACxB,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QACR,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACnB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KACxB,CAAC;IACF,YAAY,EAAE;QACb,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QACxB,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;KAC7B,CAAC;CACF;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,OAAO,KAAG,cA+CpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gCAAgC,GAC5C,cAAc,KAAK,CAAC,WAAW,CAAC,KAC9B,sBA0CF,CAAC"}
@@ -19,7 +19,8 @@ export const create_api_search = (library) => {
19
19
  const all_declarations = $derived(library.declarations);
20
20
  const filtered_declarations = $derived.by(() => {
21
21
  const items = query.trim() ? library.search_declarations(query) : all_declarations;
22
- return items.sort((a, b) => a.name.localeCompare(b.name));
22
+ // spread before sort — `items` may be the shared source array
23
+ return [...items].sort((a, b) => a.name.localeCompare(b.name));
23
24
  });
24
25
  return {
25
26
  get query() {
@@ -54,8 +55,9 @@ export const create_module_declaration_search = (declarations) => {
54
55
  const all = $derived(declarations);
55
56
  const filtered = $derived.by(() => {
56
57
  const trimmed_query = query.trim();
58
+ // spread before sort — `all` is the shared source array
57
59
  if (!trimmed_query)
58
- return all.sort((a, b) => a.name.localeCompare(b.name));
60
+ return [...all].sort((a, b) => a.name.localeCompare(b.name));
59
61
  const terms = trimmed_query.toLowerCase().split(/\s+/);
60
62
  const items = all.filter((d) => {
61
63
  const name_lower = d.name.toLowerCase();
@@ -293,10 +293,21 @@ export declare class Declaration {
293
293
  module: string;
294
294
  name: string;
295
295
  } | undefined;
296
+ /**
297
+ * Other modules that also export this declaration (re-export paths
298
+ * relative to src/lib). Absent when only exported from its defining module.
299
+ */
300
+ also_exported_from: string[] | undefined;
296
301
  /**
297
302
  * Mutation documentation from `@mutates` tags, mapping parameter names to descriptions.
298
303
  */
299
304
  mutates: Record<string, string> | undefined;
305
+ /**
306
+ * Svelte reactivity flavor (`$state`, `$state.raw`, `$derived`, `$derived.by`)
307
+ * when this variable is initialized with a value-producing rune.
308
+ * Present on `variable` kind only.
309
+ */
310
+ reactivity: "$state" | "$state.raw" | "$derived" | "$derived.by" | undefined;
300
311
  has_examples: boolean;
301
312
  is_deprecated: boolean;
302
313
  has_documentation: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"declaration.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/declaration.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,oBAAoB,EAKpB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAc/C;;;;;;;;;;GAUG;AACH,qBAAa,WAAW;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAiB;IACxC,QAAQ,CAAC,gBAAgB,EAAE,oBAAoB,CAAiB;IAEhE,OAAO,wCAAiC;IAExC;;OAEG;IACH,WAAW,SAA8B;IAEzC,IAAI,SAAwC;IAC5C,IAAI,4GAAwC;IAE5C;;OAEG;IACH,UAAU,qBAQR;IAEF;;OAEG;IACH,OAAO,SAAoF;IAE3F;;OAEG;IACH,gBAAgB,SAQd;IAEF;;OAEG;IACH,YAAY,qBAIV;IAEF;;OAEG;IAGH,YAAY,SAKV;IAEF,cAAc,qBAAiD;IAC/D,WAAW,qBAA8C;IACzD,kBAAkB,qBAAqD;IACvE,UAAU;;;;;;;;oBAAmF;IAC7F,KAAK;;;;;;;;;;;;;;;;;;;;;;;;oBAAkF;IACvF,WAAW,qBAAgE;IAC3E,kBAAkB,qBAAuE;IACzF,cAAc;;;;QAAuD;IACrE,YAAY,gCAA6E;IACzF,gBAAgB,uBAAuE;IACvF,MAAM;;;QAAgD;IACtD,KAAK,qBAAyC;IAC9C,QAAQ,WAAkD;IAC1D,QAAQ,WAAiD;IACzD;;OAEG;IACH,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAA6E;IAEpF;;;OAGG;IACH,UAAU,uBAAuE;IAEjF;;;OAGG;IACH,gBAAgB,sBAAsE;IAEtF;;;OAGG;IACH,SAAS;;;;;;;;;;;;;;;;;;;oBAAiF;IAE1F;;OAEG;IACH,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAA2C;IAEnD;;OAEG;IACH,OAAO,qCAA2C;IAElD,YAAY,UAAsC;IAClD,aAAa,UAAuC;IACpD,iBAAiB,UAAgC;IACjD,cAAc,UAA+D;IAC7E,SAAS,UAAqD;IAC9D,YAAY,UAA4C;gBAE5C,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,oBAAoB;CAIlE"}
1
+ {"version":3,"file":"declaration.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/declaration.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,oBAAoB,EAMpB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAc/C;;;;;;;;;;GAUG;AACH,qBAAa,WAAW;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAiB;IACxC,QAAQ,CAAC,gBAAgB,EAAE,oBAAoB,CAAiB;IAEhE,OAAO,wCAAiC;IAExC;;OAEG;IACH,WAAW,SAA8B;IAEzC,IAAI,SAAwC;IAC5C,IAAI,4GAAwC;IAE5C;;OAEG;IACH,UAAU,qBAQR;IAEF;;OAEG;IACH,OAAO,SAAoF;IAE3F;;OAEG;IACH,gBAAgB,SAQd;IAEF;;OAEG;IACH,YAAY,qBAIV;IAEF;;OAEG;IAGH,YAAY,SAKV;IAEF,cAAc,qBAAiD;IAC/D,WAAW,qBAA8C;IACzD,kBAAkB,qBAAqD;IACvE,UAAU;;;;;;;;oBAAmF;IAC7F,KAAK;;;;;;;;;;;;;;;;;;;;;;;;oBAAkF;IACvF,WAAW,qBAAgE;IAC3E,kBAAkB,qBAAuE;IACzF,cAAc;;;;QAAuD;IACrE,YAAY,gCAA6E;IACzF,gBAAgB,uBAAuE;IACvF,MAAM;;;QAAgD;IACtD,KAAK,qBAAyC;IAC9C,QAAQ,WAAkD;IAC1D,QAAQ,WAAiD;IACzD;;OAEG;IACH,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAA6E;IAEpF;;;OAGG;IACH,UAAU,uBAAuE;IAEjF;;;OAGG;IACH,gBAAgB,sBAAsE;IAEtF;;;OAGG;IACH,SAAS;;;;;;;;;;;;;;;;;;;oBAAiF;IAE1F;;OAEG;IACH,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAA2C;IAEnD;;;OAGG;IACH,kBAAkB,uBAA6E;IAE/F;;OAEG;IACH,OAAO,qCAA2C;IAElD;;;;OAIG;IACH,UAAU,mEAAoE;IAE9E,YAAY,UAAsC;IAElD,aAAa,UAAmD;IAChE,iBAAiB,UAAgC;IACjD,cAAc,UAA+D;IAC7E,SAAS,UAAqD;IAC9D,YAAY,UAA4C;gBAE5C,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,oBAAoB;CAIlE"}
@@ -1,5 +1,5 @@
1
1
  import { generateImport, getDisplayName } from 'svelte-docinfo/declaration-helpers.js';
2
- import { url_github_file } from './package_helpers.js';
2
+ import { url_github_file } from '@fuzdev/fuz_util/package_helpers.js';
3
3
  // The `virtual:svelte-docinfo` module is serialized with svelte-docinfo's
4
4
  // `compactReplacer`, which strips empty default arrays — so the runtime data
5
5
  // is the `*Input` shape (defaulted arrays optional), not the parsed `*Json`
@@ -46,7 +46,7 @@ export class Declaration {
46
46
  import_statement = $derived(
47
47
  // `generateImport` reads only `name`/`kind`/path, none of the defaulted
48
48
  // arrays, so asserting the parsed shape here is sound.
49
- generateImport(this.declaration_json, this.module_path, this.library.package_json.name));
49
+ generateImport(this.declaration_json, this.module_path, this.library.pkg_json.name));
50
50
  /**
51
51
  * Public documentation link (if homepage_url is available).
52
52
  */
@@ -99,12 +99,24 @@ export class Declaration {
99
99
  * Re-export alias info when this declaration is a renamed re-export.
100
100
  */
101
101
  alias_of = $derived(this.declaration_json.aliasOf);
102
+ /**
103
+ * Other modules that also export this declaration (re-export paths
104
+ * relative to src/lib). Absent when only exported from its defining module.
105
+ */
106
+ also_exported_from = $derived(field(this.declaration_json, 'alsoExportedFrom'));
102
107
  /**
103
108
  * Mutation documentation from `@mutates` tags, mapping parameter names to descriptions.
104
109
  */
105
110
  mutates = $derived(this.declaration_json.mutates);
111
+ /**
112
+ * Svelte reactivity flavor (`$state`, `$state.raw`, `$derived`, `$derived.by`)
113
+ * when this variable is initialized with a value-producing rune.
114
+ * Present on `variable` kind only.
115
+ */
116
+ reactivity = $derived(field(this.declaration_json, 'reactivity'));
106
117
  has_examples = $derived(this.examples.length > 0);
107
- is_deprecated = $derived(!!this.deprecated_message);
118
+ // presence, not truthiness — a bare `@deprecated` (no message text) arrives as `''`
119
+ is_deprecated = $derived(this.deprecated_message !== undefined);
108
120
  has_documentation = $derived(!!this.doc_comment);
109
121
  has_parameters = $derived(!!(this.parameters && this.parameters.length > 0));
110
122
  has_props = $derived(!!(this.props && this.props.length > 0));
@@ -1,4 +1,5 @@
1
1
  import type { LibraryJson } from '@fuzdev/fuz_util/library_json.js';
2
+ import type { Url } from '@fuzdev/fuz_util/url.js';
2
3
  import { Declaration } from './declaration.svelte.js';
3
4
  import { Module } from './module.svelte.js';
4
5
  export declare const library_context: {
@@ -27,83 +28,21 @@ export declare class Library {
27
28
  * Default `''` preserves single-package behavior.
28
29
  */
29
30
  readonly url_prefix: string;
30
- readonly package_json: {
31
- [x: string]: unknown;
32
- name: string;
33
- version?: string | undefined;
34
- private?: boolean | undefined;
35
- description?: string | undefined;
36
- tagline?: string | undefined;
37
- glyph?: string | undefined;
38
- logo?: string | undefined;
39
- logo_alt?: string | undefined;
40
- license?: string | undefined;
41
- scripts?: Record<string, string> | undefined;
42
- homepage?: string | undefined;
43
- author?: string | {
44
- [x: string]: unknown;
45
- name: string;
46
- email?: string | undefined;
47
- url?: string | undefined;
48
- } | undefined;
49
- repository?: string | {
50
- [x: string]: unknown;
51
- type: string;
52
- url: string;
53
- directory?: string | undefined;
54
- } | undefined;
55
- contributors?: (string | {
56
- [x: string]: unknown;
57
- name: string;
58
- email?: string | undefined;
59
- url?: string | undefined;
60
- })[] | undefined;
61
- bugs?: string | {
62
- [x: string]: unknown;
63
- url?: string | undefined;
64
- email?: string | undefined;
65
- } | undefined;
66
- funding?: string | {
67
- [x: string]: unknown;
68
- type: string;
69
- url: string;
70
- } | (string | {
71
- [x: string]: unknown;
72
- type: string;
73
- url: string;
74
- })[] | undefined;
75
- keywords?: string[] | undefined;
76
- type?: string | undefined;
77
- engines?: Record<string, string> | undefined;
78
- os?: string[] | undefined;
79
- cpu?: string[] | undefined;
80
- dependencies?: Record<string, string> | undefined;
81
- devDependencies?: Record<string, string> | undefined;
82
- peerDependencies?: Record<string, string> | undefined;
83
- peerDependenciesMeta?: Record<string, {
84
- [x: string]: unknown;
85
- optional: boolean;
86
- }> | undefined;
87
- optionalDependencies?: Record<string, string> | undefined;
88
- bin?: Record<string, string> | undefined;
89
- sideEffects?: string[] | undefined;
90
- files?: string[] | undefined;
91
- main?: string | undefined;
92
- exports?: string | Record<string, unknown> | null | undefined;
93
- };
31
+ readonly pkg_json: import("@fuzdev/fuz_util/pkg_json.js").PkgJson;
94
32
  readonly source_json: import("@fuzdev/fuz_util/library_json.js").SourceJson;
95
33
  readonly name: string;
96
34
  readonly repo_name: string;
97
- readonly repo_url: import("@fuzdev/fuz_util/url.js").Url;
35
+ /** Non-null — the constructor rejects a `pkg_json` without a parseable `repository`. */
36
+ readonly repo_url: Url;
98
37
  readonly owner_name: string | null;
99
- readonly homepage_url: import("@fuzdev/fuz_util/url.js").Url | null;
100
- readonly logo_url: import("@fuzdev/fuz_util/url.js").Url | null;
38
+ readonly homepage_url: Url | null;
39
+ readonly logo_url: Url | null;
101
40
  readonly logo_alt: string;
102
- readonly npm_url: import("@fuzdev/fuz_util/url.js").Url | null;
103
- readonly changelog_url: import("@fuzdev/fuz_util/url.js").Url | null;
104
41
  readonly published: boolean;
42
+ readonly npm_url: Url | null;
43
+ readonly changelog_url: Url | null;
105
44
  /**
106
- * Organization URL (e.g., 'https://github.com/ryanatkn').
45
+ * Organization URL (e.g., 'https://github.com/ryanatkn'), built from `owner_name`.
107
46
  */
108
47
  readonly org_url: string | null;
109
48
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"library.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAIlE,OAAO,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAE1C,eAAO,MAAM,eAAe;;;;CAA4B,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,OAAO,KAAG,MAGzD,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,OAAO;IACnB,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAiB;IAEnD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAA4C;IACjE,QAAQ,CAAC,WAAW,wDAA2C;IAE/D,QAAQ,CAAC,IAAI,SAAoC;IACjD,QAAQ,CAAC,SAAS,SAAyC;IAC3D,QAAQ,CAAC,QAAQ,wCAAwC;IACzD,QAAQ,CAAC,UAAU,gBAA0C;IAC7D,QAAQ,CAAC,YAAY,+CAA4C;IACjE,QAAQ,CAAC,QAAQ,+CAAwC;IACzD,QAAQ,CAAC,QAAQ,SAAwC;IACzD,QAAQ,CAAC,OAAO,+CAAuC;IACvD,QAAQ,CAAC,aAAa,+CAA6C;IACnE,QAAQ,CAAC,SAAS,UAAyC;IAE3D;;OAEG;IACH,QAAQ,CAAC,OAAO,gBAMd;IAEF;;OAEG;IACH,QAAQ,CAAC,OAAO,WAId;IAEF;;OAEG;IACH,QAAQ,CAAC,cAAc,WAErB;IAEF;;OAEG;IACH,QAAQ,CAAC,YAAY,gBAAmE;IAExF;;OAEG;IACH,QAAQ,CAAC,cAAc,sBAA2D;IAElF;;OAEG;IACH,QAAQ,CAAC,mBAAmB,2BAAgE;gBAEhF,YAAY,EAAE,WAAW,EAAE,UAAU,SAAK;IAKtD;;;OAGG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI;IAW5D;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC;CAGtD"}
1
+ {"version":3,"file":"library.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAElE,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,yBAAyB,CAAC;AAGjD,OAAO,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAW1C,eAAO,MAAM,eAAe;;;;CAA4B,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,OAAO,KAAG,MAGzD,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,OAAO;IACnB,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAiB;IAEnD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,QAAQ,iDAAwC;IACzD,QAAQ,CAAC,WAAW,wDAA2C;IAI/D,QAAQ,CAAC,IAAI,SAAgC;IAC7C,QAAQ,CAAC,SAAS,SAAiD;IACnE,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAuD;IAC7E,QAAQ,CAAC,UAAU,gBAAkD;IACrE,QAAQ,CAAC,YAAY,EAAE,GAAG,GAAG,IAAI,CAA4C;IAC7E,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI,CAA6D;IAC1F,QAAQ,CAAC,QAAQ,SAAoE;IACrF,QAAQ,CAAC,SAAS,UAAiD;IACnE,QAAQ,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CAAgE;IAC5F,QAAQ,CAAC,aAAa,EAAE,GAAG,GAAG,IAAI,CAEhC;IAEF;;OAEG;IACH,QAAQ,CAAC,OAAO,gBAA8E;IAE9F;;OAEG;IACH,QAAQ,CAAC,OAAO,WAId;IAEF;;OAEG;IACH,QAAQ,CAAC,cAAc,WAErB;IAEF;;OAEG;IACH,QAAQ,CAAC,YAAY,gBAAmE;IAExF;;OAEG;IACH,QAAQ,CAAC,cAAc,sBAA2D;IAElF;;OAEG;IACH,QAAQ,CAAC,mBAAmB,2BAAgE;gBAEhF,YAAY,EAAE,WAAW,EAAE,UAAU,SAAK;IAatD;;;OAGG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI;IAW5D;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC;CAGtD"}
@@ -2,6 +2,7 @@ import { ensure_start, strip_end } from '@fuzdev/fuz_util/string.js';
2
2
  import { create_context } from './context_helpers.js';
3
3
  import { Declaration } from './declaration.svelte.js';
4
4
  import { Module } from './module.svelte.js';
5
+ import { package_is_published, repo_name_parse, repo_url_github_owner, repo_url_parse, url_github_file, url_logo, url_npm_package, } from '@fuzdev/fuz_util/package_helpers.js';
5
6
  export const library_context = create_context();
6
7
  /**
7
8
  * Normalizes a URL prefix: ensures leading `/`, strips trailing `/`, returns `''` for falsy and non-string values.
@@ -28,31 +29,30 @@ export class Library {
28
29
  * Default `''` preserves single-package behavior.
29
30
  */
30
31
  url_prefix;
31
- package_json = $derived(this.library_json.package_json);
32
+ pkg_json = $derived(this.library_json.pkg_json);
32
33
  source_json = $derived(this.library_json.source_json);
33
- name = $derived(this.library_json.name);
34
- repo_name = $derived(this.library_json.repo_name);
35
- repo_url = $derived(this.library_json.repo_url);
36
- owner_name = $derived(this.library_json.owner_name);
37
- homepage_url = $derived(this.library_json.homepage_url);
38
- logo_url = $derived(this.library_json.logo_url);
39
- logo_alt = $derived(this.library_json.logo_alt);
40
- npm_url = $derived(this.library_json.npm_url);
41
- changelog_url = $derived(this.library_json.changelog_url);
42
- published = $derived(this.library_json.published);
34
+ // Everything below is derived from `pkg_json` — `LibraryJson` stores only the
35
+ // raw `pkg_json`/`source_json` pair, so derivation lives in exactly one place.
36
+ name = $derived(this.pkg_json.name);
37
+ repo_name = $derived(repo_name_parse(this.pkg_json.name));
38
+ /** Non-null — the constructor rejects a `pkg_json` without a parseable `repository`. */
39
+ repo_url = $derived(repo_url_parse(this.pkg_json.repository));
40
+ owner_name = $derived(repo_url_github_owner(this.repo_url));
41
+ homepage_url = $derived(this.pkg_json.homepage ?? null);
42
+ logo_url = $derived(url_logo(this.homepage_url, this.pkg_json.logo));
43
+ logo_alt = $derived(this.pkg_json.logo_alt ?? `logo for ${this.repo_name}`);
44
+ published = $derived(package_is_published(this.pkg_json));
45
+ npm_url = $derived(this.published ? url_npm_package(this.name) : null);
46
+ changelog_url = $derived(this.published ? url_github_file(this.repo_url, 'CHANGELOG.md') : null);
43
47
  /**
44
- * Organization URL (e.g., 'https://github.com/ryanatkn').
48
+ * Organization URL (e.g., 'https://github.com/ryanatkn'), built from `owner_name`.
45
49
  */
46
- org_url = $derived(this.repo_url && this.repo_name
47
- ? this.repo_url.endsWith('/' + this.repo_name)
48
- ? this.repo_url.slice(0, -this.repo_name.length - 1)
49
- : null
50
- : null);
50
+ org_url = $derived(this.owner_name ? 'https://github.com/' + this.owner_name : null);
51
51
  /**
52
52
  * All modules as rich `Module` instances.
53
53
  */
54
54
  modules = $derived(this.source_json.modules
55
- ? this.source_json.modules.map((module_json) => new Module(this, module_json)) // TODO: remove cast when fuz_util SourceJson uses svelte-docinfo types
55
+ ? this.source_json.modules.map((module_json) => new Module(this, module_json))
56
56
  : []);
57
57
  /**
58
58
  * All modules sorted alphabetically by path.
@@ -71,6 +71,12 @@ export class Library {
71
71
  */
72
72
  declaration_by_name = $derived(new Map(this.declarations.map((d) => [d.name, d])));
73
73
  constructor(library_json, url_prefix = '') {
74
+ // `repo_url` is exposed non-null and several derived URLs depend on it, so
75
+ // fail loud here rather than letting a missing/unparseable repository surface
76
+ // as a downstream `null`.
77
+ if (repo_url_parse(library_json.pkg_json.repository) === null) {
78
+ throw Error(`failed to construct Library - pkg_json for "${library_json.pkg_json.name}" has no parseable \`repository\``);
79
+ }
74
80
  this.library_json = library_json;
75
81
  this.url_prefix = parse_library_url_prefix(url_prefix);
76
82
  }
@@ -4,7 +4,7 @@
4
4
  * Runtime UI helpers for building URLs in the library documentation system.
5
5
  * These depend on fuz_ui's documentation paths and SvelteKit's runtime state.
6
6
  *
7
- * For generic package/repository URL helpers, see `package_helpers.ts`.
7
+ * For generic package/repository URL helpers, see `@fuzdev/fuz_util/package_helpers.js`.
8
8
  *
9
9
  * @module
10
10
  */
@@ -19,8 +19,8 @@
19
19
  *
20
20
  * @example
21
21
  * ```ts
22
- * // Assuming page.url.origin is 'https://example.com'
23
- * url_to_root_relative('https://example.com/docs/api')
22
+ * // Assuming page.url.origin is 'https://fuz.dev'
23
+ * url_to_root_relative('https://fuz.dev/docs/api')
24
24
  * // => '/docs/api'
25
25
  * ```
26
26
  */
@@ -4,7 +4,7 @@
4
4
  * Runtime UI helpers for building URLs in the library documentation system.
5
5
  * These depend on fuz_ui's documentation paths and SvelteKit's runtime state.
6
6
  *
7
- * For generic package/repository URL helpers, see `package_helpers.ts`.
7
+ * For generic package/repository URL helpers, see `@fuzdev/fuz_util/package_helpers.js`.
8
8
  *
9
9
  * @module
10
10
  */
@@ -21,8 +21,8 @@ import { page } from '$app/state';
21
21
  *
22
22
  * @example
23
23
  * ```ts
24
- * // Assuming page.url.origin is 'https://example.com'
25
- * url_to_root_relative('https://example.com/docs/api')
24
+ * // Assuming page.url.origin is 'https://fuz.dev'
25
+ * url_to_root_relative('https://fuz.dev/docs/api')
26
26
  * // => '/docs/api'
27
27
  * ```
28
28
  */
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAyCH;;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,EAAE,EAAE,MAAM,CAAC;IACX,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;AAED;;;;GAIG;AACH,qBAAa,SAAS;;gBAQT,QAAQ,EAAE,MAAM;IAI5B;;;;;;OAMG;IACH,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;CAyzCvB"}
1
+ {"version":3,"file":"mdz.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA0CH;;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,EAAE,EAAE,MAAM,CAAC;IACX,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;AAED;;;;GAIG;AACH,qBAAa,SAAS;;gBAQT,QAAQ,EAAE,MAAM;IAI5B;;;;;;OAMG;IACH,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;CAi0CvB"}
package/dist/mdz.js CHANGED
@@ -28,7 +28,7 @@
28
28
  *
29
29
  * @module
30
30
  */
31
- import { BACKTICK, ASTERISK, UNDERSCORE, TILDE, NEWLINE, HYPHEN, HASH, SPACE, TAB, LEFT_ANGLE, RIGHT_ANGLE, SLASH, LEFT_BRACKET, RIGHT_BRACKET, LEFT_PAREN, RIGHT_PAREN, A_UPPER, Z_UPPER, HR_HYPHEN_COUNT, MIN_CODEBLOCK_BACKTICKS, MAX_HEADING_LEVEL, HTTPS_PREFIX_LENGTH, HTTP_PREFIX_LENGTH, is_letter, is_tag_name_char, is_word_char, PERIOD, is_valid_path_char, trim_trailing_punctuation, is_at_absolute_path, is_at_relative_path, extract_single_tag, mdz_heading_id, mdz_is_url, } from './mdz_helpers.js';
31
+ import { BACKTICK, ASTERISK, UNDERSCORE, TILDE, NEWLINE, HYPHEN, HASH, SPACE, TAB, LEFT_ANGLE, RIGHT_ANGLE, SLASH, LEFT_BRACKET, RIGHT_BRACKET, LEFT_PAREN, RIGHT_PAREN, A_UPPER, Z_UPPER, HR_HYPHEN_COUNT, MIN_CODEBLOCK_BACKTICKS, MAX_HEADING_LEVEL, match_url_prefix_case_insensitive, is_letter, is_tag_name_char, is_word_char, PERIOD, is_valid_path_char, trim_trailing_punctuation, is_at_absolute_path, is_at_relative_path, extract_single_tag, mdz_heading_id, mdz_is_url, mdz_is_safe_reference, mdz_push_merging_text, } from './mdz_helpers.js';
32
32
  // TODO design incremental parsing or some system that preserves Svelte components across re-renders when possible
33
33
  /**
34
34
  * Parses text to an array of `MdzNode`.
@@ -479,6 +479,18 @@ export class MdzParser {
479
479
  };
480
480
  }
481
481
  }
482
+ // Reject unsafe protocols (javascript:, data:, etc.) — fall back to text.
483
+ // `is_valid_path_char` permits `:` so a malicious `[x](javascript:...)` would
484
+ // otherwise pass character validation and reach the renderer.
485
+ if (!mdz_is_safe_reference(reference)) {
486
+ this.#index = start + 1;
487
+ return {
488
+ type: 'Text',
489
+ content: '[',
490
+ start,
491
+ end: this.#index,
492
+ };
493
+ }
482
494
  this.#index = close_paren + 1;
483
495
  // Determine link type (external vs internal)
484
496
  const link_type = mdz_is_url(reference) ? 'external' : 'internal';
@@ -663,27 +675,28 @@ export class MdzParser {
663
675
  }
664
676
  /**
665
677
  * Check if current position is the start of an external URL (`https://` or `http://`).
678
+ *
679
+ * Requires the preceding character (if any) to not be a word character. This
680
+ * matches the streaming parser and the spec's "false negatives over false
681
+ * positives" policy — `xhttps://...` is treated as plain text rather than
682
+ * `x` followed by a link.
683
+ *
684
+ * Scheme matching is case-insensitive (RFC 3986 §3.1); the original casing
685
+ * is preserved in the emitted reference.
666
686
  */
667
687
  #is_at_url() {
668
- if (this.#match('https://')) {
669
- // Check for protocol-only (e.g., just "https://")
670
- // Must have at least one non-whitespace character after protocol
671
- if (this.#index + HTTPS_PREFIX_LENGTH >= this.#template.length) {
672
- return false;
673
- }
674
- const next_char = this.#template.charCodeAt(this.#index + HTTPS_PREFIX_LENGTH);
675
- return next_char !== SPACE && next_char !== NEWLINE;
676
- }
677
- if (this.#match('http://')) {
678
- // Check for protocol-only (e.g., just "http://")
679
- // Must have at least one non-whitespace character after protocol
680
- if (this.#index + HTTP_PREFIX_LENGTH >= this.#template.length) {
681
- return false;
682
- }
683
- const next_char = this.#template.charCodeAt(this.#index + HTTP_PREFIX_LENGTH);
684
- return next_char !== SPACE && next_char !== NEWLINE;
688
+ // word boundary check: skip when preceded by [A-Za-z0-9]
689
+ if (this.#index > 0 && is_word_char(this.#template.charCodeAt(this.#index - 1))) {
690
+ return false;
685
691
  }
686
- return false;
692
+ const prefix_len = match_url_prefix_case_insensitive(this.#template, this.#index);
693
+ if (prefix_len === 0)
694
+ return false;
695
+ // Must have at least one non-whitespace character after protocol
696
+ if (this.#index + prefix_len >= this.#template.length)
697
+ return false;
698
+ const next_char = this.#template.charCodeAt(this.#index + prefix_len);
699
+ return next_char !== SPACE && next_char !== NEWLINE;
687
700
  }
688
701
  /**
689
702
  * Parse auto-detected external URL (`https://` or `http://`).
@@ -691,13 +704,8 @@ export class MdzParser {
691
704
  */
692
705
  #parse_auto_link_url() {
693
706
  const start = this.#index;
694
- // Consume protocol
695
- if (this.#match('https://')) {
696
- this.#index += HTTPS_PREFIX_LENGTH;
697
- }
698
- else if (this.#match('http://')) {
699
- this.#index += HTTP_PREFIX_LENGTH;
700
- }
707
+ // Consume protocol (case-insensitive match; original casing preserved in reference)
708
+ this.#index += match_url_prefix_case_insensitive(this.#template, this.#index);
701
709
  // Collect URL characters using RFC 3986 whitelist
702
710
  // Stop at whitespace or any character invalid in URIs
703
711
  while (this.#index < this.#template.length) {
@@ -797,7 +805,7 @@ export class MdzParser {
797
805
  }
798
806
  }
799
807
  // Check for URL or internal absolute/relative path mid-text (char code guard avoids startsWith on every char)
800
- if ((char_code === 104 /* h */ && this.#is_at_url()) ||
808
+ if (((char_code === 104 /* h */ || char_code === 72) /* H */ && this.#is_at_url()) ||
801
809
  (char_code === SLASH && is_at_absolute_path(this.#template, this.#index)) ||
802
810
  (char_code === PERIOD && is_at_relative_path(this.#template, this.#index))) {
803
811
  break;
@@ -851,8 +859,8 @@ export class MdzParser {
851
859
  // Paragraph break interrupts inline formatting
852
860
  break;
853
861
  }
854
- const node = this.#parse_node();
855
- nodes.push(node);
862
+ // merge adjacent Text nodes (e.g., text + failed delimiter + text)
863
+ mdz_push_merging_text(nodes, this.#parse_node());
856
864
  }
857
865
  // Restore previous boundary
858
866
  this.#max_search_index = saved_max_search_index;