@fuzdev/fuz_ui 0.204.0 → 0.205.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApiModule.svelte +14 -1
- package/dist/ApiModule.svelte.d.ts.map +1 -1
- package/dist/Breadcrumb.svelte +2 -2
- package/dist/Card.svelte +1 -7
- package/dist/ColorSchemeInput.svelte +1 -2
- package/dist/ContextmenuEntry.svelte +1 -3
- package/dist/ContextmenuLinkEntry.svelte +1 -4
- package/dist/ContextmenuSeparator.svelte +1 -1
- package/dist/ContextmenuSubmenu.svelte +1 -2
- package/dist/CopyToClipboard.svelte +5 -5
- package/dist/CopyToClipboard.svelte.d.ts.map +1 -1
- package/dist/DeclarationDetail.svelte +15 -4
- package/dist/DeclarationDetail.svelte.d.ts.map +1 -1
- package/dist/Dialog.svelte +1 -2
- package/dist/DialogContent.svelte +1 -1
- package/dist/DocsList.svelte +1 -1
- package/dist/DocsMenu.svelte +1 -1
- package/dist/DocsPageLinks.svelte +9 -8
- package/dist/DocsPageLinks.svelte.d.ts.map +1 -1
- package/dist/DocsPrimaryNav.svelte +1 -1
- package/dist/DocsSecondaryNav.svelte +1 -1
- package/dist/EcosystemLinks.svelte +1 -1
- package/dist/LibraryDetail.svelte +10 -7
- package/dist/LibraryDetail.svelte.d.ts.map +1 -1
- package/dist/LibrarySummary.svelte +1 -2
- package/dist/PendingAnimation.svelte +6 -4
- package/dist/PendingAnimation.svelte.d.ts.map +1 -1
- package/dist/PendingButton.svelte +1 -2
- package/dist/StyleVariableButton.svelte +1 -2
- package/dist/Svg.svelte +1 -1
- package/dist/ThemeInput.svelte +1 -2
- package/dist/TomeSectionHeader.svelte +1 -1
- package/package.json +14 -38
- package/dist/Mdz.svelte +0 -34
- package/dist/Mdz.svelte.d.ts +0 -11
- package/dist/Mdz.svelte.d.ts.map +0 -1
- package/dist/MdzNodeView.svelte +0 -107
- package/dist/MdzNodeView.svelte.d.ts +0 -9
- package/dist/MdzNodeView.svelte.d.ts.map +0 -1
- package/dist/MdzPrecompiled.svelte +0 -30
- package/dist/MdzPrecompiled.svelte.d.ts +0 -11
- package/dist/MdzPrecompiled.svelte.d.ts.map +0 -1
- package/dist/MdzRoot.svelte +0 -30
- package/dist/MdzRoot.svelte.d.ts +0 -12
- package/dist/MdzRoot.svelte.d.ts.map +0 -1
- package/dist/MdzStream.svelte +0 -32
- package/dist/MdzStream.svelte.d.ts +0 -12
- package/dist/MdzStream.svelte.d.ts.map +0 -1
- package/dist/MdzStreamNodeView.svelte +0 -106
- package/dist/MdzStreamNodeView.svelte.d.ts +0 -9
- package/dist/MdzStreamNodeView.svelte.d.ts.map +0 -1
- package/dist/mdz.d.ts +0 -112
- package/dist/mdz.d.ts.map +0 -1
- package/dist/mdz.js +0 -1186
- package/dist/mdz_components.d.ts +0 -63
- package/dist/mdz_components.d.ts.map +0 -1
- package/dist/mdz_components.js +0 -32
- package/dist/mdz_helpers.d.ts +0 -164
- package/dist/mdz_helpers.d.ts.map +0 -1
- package/dist/mdz_helpers.js +0 -424
- package/dist/mdz_lexer.d.ts +0 -93
- package/dist/mdz_lexer.d.ts.map +0 -1
- package/dist/mdz_lexer.js +0 -732
- package/dist/mdz_opcodes.d.ts +0 -174
- package/dist/mdz_opcodes.d.ts.map +0 -1
- package/dist/mdz_opcodes.js +0 -14
- package/dist/mdz_opcodes_to_nodes.d.ts +0 -20
- package/dist/mdz_opcodes_to_nodes.d.ts.map +0 -1
- package/dist/mdz_opcodes_to_nodes.js +0 -332
- package/dist/mdz_stream_parser.d.ts +0 -80
- package/dist/mdz_stream_parser.d.ts.map +0 -1
- package/dist/mdz_stream_parser.js +0 -354
- package/dist/mdz_stream_parser_block.d.ts +0 -76
- package/dist/mdz_stream_parser_block.d.ts.map +0 -1
- package/dist/mdz_stream_parser_block.js +0 -458
- package/dist/mdz_stream_parser_inline.d.ts +0 -52
- package/dist/mdz_stream_parser_inline.d.ts.map +0 -1
- package/dist/mdz_stream_parser_inline.js +0 -378
- package/dist/mdz_stream_parser_link.d.ts +0 -22
- package/dist/mdz_stream_parser_link.d.ts.map +0 -1
- package/dist/mdz_stream_parser_link.js +0 -215
- package/dist/mdz_stream_parser_state.d.ts +0 -187
- package/dist/mdz_stream_parser_state.d.ts.map +0 -1
- package/dist/mdz_stream_parser_state.js +0 -398
- package/dist/mdz_stream_parser_text.d.ts +0 -14
- package/dist/mdz_stream_parser_text.d.ts.map +0 -1
- package/dist/mdz_stream_parser_text.js +0 -50
- package/dist/mdz_stream_parser_url.d.ts +0 -60
- package/dist/mdz_stream_parser_url.d.ts.map +0 -1
- package/dist/mdz_stream_parser_url.js +0 -307
- package/dist/mdz_stream_state.svelte.d.ts +0 -44
- package/dist/mdz_stream_state.svelte.d.ts.map +0 -1
- package/dist/mdz_stream_state.svelte.js +0 -357
- package/dist/mdz_to_svelte.d.ts +0 -41
- package/dist/mdz_to_svelte.d.ts.map +0 -1
- package/dist/mdz_to_svelte.js +0 -100
- package/dist/mdz_token_parser.d.ts +0 -14
- package/dist/mdz_token_parser.d.ts.map +0 -1
- package/dist/mdz_token_parser.js +0 -344
- package/dist/svelte_preprocess_mdz.d.ts +0 -65
- package/dist/svelte_preprocess_mdz.d.ts.map +0 -1
- package/dist/svelte_preprocess_mdz.js +0 -529
- package/dist/tsdoc_mdz.d.ts +0 -45
- package/dist/tsdoc_mdz.d.ts.map +0 -1
- package/dist/tsdoc_mdz.js +0 -88
- package/src/lib/mdz.ts +0 -1532
- package/src/lib/mdz_components.ts +0 -64
- package/src/lib/mdz_helpers.ts +0 -449
- package/src/lib/mdz_lexer.ts +0 -1012
- package/src/lib/mdz_opcodes.ts +0 -205
- package/src/lib/mdz_opcodes_to_nodes.ts +0 -375
- package/src/lib/mdz_stream_parser.ts +0 -415
- package/src/lib/mdz_stream_parser_block.ts +0 -532
- package/src/lib/mdz_stream_parser_inline.ts +0 -414
- package/src/lib/mdz_stream_parser_link.ts +0 -271
- package/src/lib/mdz_stream_parser_state.ts +0 -539
- package/src/lib/mdz_stream_parser_text.ts +0 -77
- package/src/lib/mdz_stream_parser_url.ts +0 -365
- package/src/lib/mdz_stream_state.svelte.ts +0 -387
- package/src/lib/mdz_to_svelte.ts +0 -141
- package/src/lib/mdz_token_parser.ts +0 -434
- package/src/lib/svelte_preprocess_mdz.ts +0 -742
- package/src/lib/tsdoc_mdz.ts +0 -97
package/dist/mdz_helpers.js
DELETED
|
@@ -1,424 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared constants and pure helper functions for mdz parsers.
|
|
3
|
-
*
|
|
4
|
-
* Used by both the single-pass parser (`mdz.ts`) and the two-phase
|
|
5
|
-
* lexer+parser (`mdz_lexer.ts` + `mdz_token_parser.ts`).
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import { slugify } from '@fuzdev/fuz_util/path.js';
|
|
10
|
-
// Character codes for performance
|
|
11
|
-
export const BACKTICK = 96; // `
|
|
12
|
-
export const ASTERISK = 42; // *
|
|
13
|
-
export const UNDERSCORE = 95; // _
|
|
14
|
-
export const TILDE = 126; // ~
|
|
15
|
-
export const NEWLINE = 10; // \n
|
|
16
|
-
export const HYPHEN = 45; // -
|
|
17
|
-
export const HASH = 35; // #
|
|
18
|
-
export const SPACE = 32; // (space)
|
|
19
|
-
export const TAB = 9; // \t
|
|
20
|
-
export const LEFT_ANGLE = 60; // <
|
|
21
|
-
export const RIGHT_ANGLE = 62; // >
|
|
22
|
-
export const SLASH = 47; // /
|
|
23
|
-
export const LEFT_BRACKET = 91; // [
|
|
24
|
-
export const RIGHT_BRACKET = 93; // ]
|
|
25
|
-
export const LEFT_PAREN = 40; // (
|
|
26
|
-
export const RIGHT_PAREN = 41; // )
|
|
27
|
-
export const COLON = 58; // :
|
|
28
|
-
export const PERIOD = 46; // .
|
|
29
|
-
export const COMMA = 44; // ,
|
|
30
|
-
export const SEMICOLON = 59; // ;
|
|
31
|
-
export const EXCLAMATION = 33; // !
|
|
32
|
-
export const QUESTION = 63; // ?
|
|
33
|
-
// RFC 3986 URI characters
|
|
34
|
-
export const DOLLAR = 36; // $
|
|
35
|
-
export const PERCENT = 37; // %
|
|
36
|
-
export const AMPERSAND = 38; // &
|
|
37
|
-
export const APOSTROPHE = 39; // '
|
|
38
|
-
export const PLUS = 43; // +
|
|
39
|
-
export const EQUALS = 61; // =
|
|
40
|
-
export const AT = 64; // @
|
|
41
|
-
// Character ranges
|
|
42
|
-
export const A_UPPER = 65; // A
|
|
43
|
-
export const Z_UPPER = 90; // Z
|
|
44
|
-
export const A_LOWER = 97; // a
|
|
45
|
-
export const Z_LOWER = 122; // z
|
|
46
|
-
export const ZERO = 48; // 0
|
|
47
|
-
export const NINE = 57; // 9
|
|
48
|
-
// mdz specification constants
|
|
49
|
-
export const HR_HYPHEN_COUNT = 3; // Horizontal rule requires exactly 3 hyphens
|
|
50
|
-
export const MIN_CODEBLOCK_BACKTICKS = 3; // Code blocks require minimum 3 backticks
|
|
51
|
-
export const MAX_HEADING_LEVEL = 6; // Headings support levels 1-6
|
|
52
|
-
export const HTTPS_PREFIX_LENGTH = 8; // Length of "https://"
|
|
53
|
-
export const HTTP_PREFIX_LENGTH = 7; // Length of "http://"
|
|
54
|
-
export const H_LOWER = 104; // h
|
|
55
|
-
export const H_UPPER = 72; // H
|
|
56
|
-
/**
|
|
57
|
-
* Lowercase an ASCII letter code; passes other chars through.
|
|
58
|
-
* Mirrors the `[A-Z] → [a-z]` shift without touching non-ASCII.
|
|
59
|
-
*/
|
|
60
|
-
export const ascii_to_lower = (char_code) => char_code >= A_UPPER && char_code <= Z_UPPER ? char_code + 32 : char_code;
|
|
61
|
-
/**
|
|
62
|
-
* Case-insensitive URL scheme prefix check. Returns the prefix length
|
|
63
|
-
* (8 for `https://`, 7 for `http://`) or 0 if neither matches at `pos`.
|
|
64
|
-
*
|
|
65
|
-
* URI schemes are case-insensitive per RFC 3986 §3.1, and mobile keyboards
|
|
66
|
-
* routinely auto-capitalize the first letter of a sentence, producing
|
|
67
|
-
* `Https://` etc. The original case is preserved in the emitted reference —
|
|
68
|
-
* browsers normalize schemes themselves.
|
|
69
|
-
*/
|
|
70
|
-
export const match_url_prefix_case_insensitive = (s, pos) => {
|
|
71
|
-
if (pos + HTTP_PREFIX_LENGTH > s.length)
|
|
72
|
-
return 0;
|
|
73
|
-
// h | H
|
|
74
|
-
if (ascii_to_lower(s.charCodeAt(pos)) !== H_LOWER)
|
|
75
|
-
return 0;
|
|
76
|
-
// 'ttps://' (7 chars) or 'ttp://' (6 chars)
|
|
77
|
-
if (ascii_to_lower(s.charCodeAt(pos + 1)) === 116 /* t */ &&
|
|
78
|
-
ascii_to_lower(s.charCodeAt(pos + 2)) === 116 /* t */ &&
|
|
79
|
-
ascii_to_lower(s.charCodeAt(pos + 3)) === 112 /* p */) {
|
|
80
|
-
if (pos + HTTPS_PREFIX_LENGTH <= s.length &&
|
|
81
|
-
ascii_to_lower(s.charCodeAt(pos + 4)) === 115 /* s */ &&
|
|
82
|
-
s.charCodeAt(pos + 5) === COLON &&
|
|
83
|
-
s.charCodeAt(pos + 6) === SLASH &&
|
|
84
|
-
s.charCodeAt(pos + 7) === SLASH) {
|
|
85
|
-
return HTTPS_PREFIX_LENGTH;
|
|
86
|
-
}
|
|
87
|
-
if (s.charCodeAt(pos + 4) === COLON &&
|
|
88
|
-
s.charCodeAt(pos + 5) === SLASH &&
|
|
89
|
-
s.charCodeAt(pos + 6) === SLASH) {
|
|
90
|
-
return HTTP_PREFIX_LENGTH;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return 0;
|
|
94
|
-
};
|
|
95
|
-
/**
|
|
96
|
-
* Check if character code is a letter (A-Z, a-z).
|
|
97
|
-
*/
|
|
98
|
-
export const is_letter = (char_code) => (char_code >= A_UPPER && char_code <= Z_UPPER) || (char_code >= A_LOWER && char_code <= Z_LOWER);
|
|
99
|
-
/**
|
|
100
|
-
* Check if character code is valid for tag name (letter, number, hyphen, underscore).
|
|
101
|
-
*/
|
|
102
|
-
export const is_tag_name_char = (char_code) => is_letter(char_code) ||
|
|
103
|
-
(char_code >= ZERO && char_code <= NINE) ||
|
|
104
|
-
char_code === HYPHEN ||
|
|
105
|
-
char_code === UNDERSCORE;
|
|
106
|
-
/**
|
|
107
|
-
* Check if character is part of a word for word boundary detection.
|
|
108
|
-
* Used to prevent intraword emphasis with `_` and `~` delimiters.
|
|
109
|
-
*
|
|
110
|
-
* Only alphanumeric characters (A-Z, a-z, 0-9) are word characters.
|
|
111
|
-
* Formatting delimiters (`*`, `_`, `~`) fall outside all three ranges,
|
|
112
|
-
* so they're naturally excluded without explicit checks.
|
|
113
|
-
*
|
|
114
|
-
* This prevents false positives with snake_case identifiers while allowing
|
|
115
|
-
* adjacent formatting like `**bold**_italic_`.
|
|
116
|
-
*/
|
|
117
|
-
export const is_word_char = (char_code) => (char_code >= A_UPPER && char_code <= Z_UPPER) ||
|
|
118
|
-
(char_code >= A_LOWER && char_code <= Z_LOWER) ||
|
|
119
|
-
(char_code >= ZERO && char_code <= NINE);
|
|
120
|
-
/**
|
|
121
|
-
* Lookup table for valid URI path characters per RFC 3986.
|
|
122
|
-
* Replaces a 16-comparison chain with a single array access.
|
|
123
|
-
*
|
|
124
|
-
* Valid characters:
|
|
125
|
-
* - unreserved: A-Z a-z 0-9 - . _ ~
|
|
126
|
-
* - sub-delims: ! $ & ' ( ) * + , ; =
|
|
127
|
-
* - path allowed: : @
|
|
128
|
-
* - separators: / ? #
|
|
129
|
-
* - percent-encoding: %
|
|
130
|
-
*/
|
|
131
|
-
const PATH_CHAR_TABLE = (() => {
|
|
132
|
-
const t = new Uint8Array(128);
|
|
133
|
-
for (let i = A_UPPER; i <= Z_UPPER; i++)
|
|
134
|
-
t[i] = 1;
|
|
135
|
-
for (let i = A_LOWER; i <= Z_LOWER; i++)
|
|
136
|
-
t[i] = 1;
|
|
137
|
-
for (let i = ZERO; i <= NINE; i++)
|
|
138
|
-
t[i] = 1;
|
|
139
|
-
// unreserved: - . _ ~
|
|
140
|
-
t[HYPHEN] = 1;
|
|
141
|
-
t[PERIOD] = 1;
|
|
142
|
-
t[UNDERSCORE] = 1;
|
|
143
|
-
t[TILDE] = 1;
|
|
144
|
-
// sub-delims: ! $ & ' ( ) * + , ; =
|
|
145
|
-
t[EXCLAMATION] = 1;
|
|
146
|
-
t[DOLLAR] = 1;
|
|
147
|
-
t[AMPERSAND] = 1;
|
|
148
|
-
t[APOSTROPHE] = 1;
|
|
149
|
-
t[LEFT_PAREN] = 1;
|
|
150
|
-
t[RIGHT_PAREN] = 1;
|
|
151
|
-
t[ASTERISK] = 1;
|
|
152
|
-
t[PLUS] = 1;
|
|
153
|
-
t[COMMA] = 1;
|
|
154
|
-
t[SEMICOLON] = 1;
|
|
155
|
-
t[EQUALS] = 1;
|
|
156
|
-
// path allowed: : @
|
|
157
|
-
t[COLON] = 1;
|
|
158
|
-
t[AT] = 1;
|
|
159
|
-
// separators: / ? #
|
|
160
|
-
t[SLASH] = 1;
|
|
161
|
-
t[QUESTION] = 1;
|
|
162
|
-
t[HASH] = 1;
|
|
163
|
-
// percent-encoding: %
|
|
164
|
-
t[PERCENT] = 1;
|
|
165
|
-
return t;
|
|
166
|
-
})();
|
|
167
|
-
export const is_valid_path_char = (char_code) => char_code < 128 && PATH_CHAR_TABLE[char_code] === 1;
|
|
168
|
-
/**
|
|
169
|
-
* Trim trailing punctuation from URL/path per RFC 3986 and GFM rules.
|
|
170
|
-
* - Trims simple trailing: .,;:!?]
|
|
171
|
-
* - Balanced logic for () only (valid in path components)
|
|
172
|
-
*
|
|
173
|
-
* Note on `]`: the mdz parsers (`mdz.ts`, `mdz_stream_parser_url.ts`,
|
|
174
|
-
* `mdz_lexer.ts`) scan URL/path chars through `is_valid_path_char`, which
|
|
175
|
-
* already rejects `]` — so it can never reach this function via parser flow.
|
|
176
|
-
* The `]` branch here is for external callers using this helper directly on
|
|
177
|
-
* arbitrary URL-ish input (it is part of the published `@fuzdev/fuz_ui`
|
|
178
|
-
* surface, see `mdz_helpers.test.ts` for direct coverage).
|
|
179
|
-
*
|
|
180
|
-
* Optimized to avoid O(n²) string slicing - tracks end index and slices once at the end.
|
|
181
|
-
*/
|
|
182
|
-
export const trim_trailing_punctuation = (url) => {
|
|
183
|
-
let end = url.length;
|
|
184
|
-
while (end > 0) {
|
|
185
|
-
const last_char = url.charCodeAt(end - 1);
|
|
186
|
-
if (last_char === PERIOD ||
|
|
187
|
-
last_char === COMMA ||
|
|
188
|
-
last_char === SEMICOLON ||
|
|
189
|
-
last_char === COLON ||
|
|
190
|
-
last_char === EXCLAMATION ||
|
|
191
|
-
last_char === QUESTION ||
|
|
192
|
-
last_char === RIGHT_BRACKET) {
|
|
193
|
-
end--;
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
break;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
// Handle balanced parentheses ONLY (parens are valid in URI path components)
|
|
200
|
-
// Only count parens when the trimmed URL ends with ')' — otherwise the
|
|
201
|
-
// trailing-paren loop below can't trim anything.
|
|
202
|
-
if (end > 0 && url.charCodeAt(end - 1) === RIGHT_PAREN) {
|
|
203
|
-
let open_count = 0;
|
|
204
|
-
let close_count = 0;
|
|
205
|
-
for (let i = 0; i < end; i++) {
|
|
206
|
-
const char = url.charCodeAt(i);
|
|
207
|
-
if (char === LEFT_PAREN)
|
|
208
|
-
open_count++;
|
|
209
|
-
if (char === RIGHT_PAREN)
|
|
210
|
-
close_count++;
|
|
211
|
-
}
|
|
212
|
-
// Trim unmatched trailing closing parens
|
|
213
|
-
while (end > 0 && close_count > open_count) {
|
|
214
|
-
const last_char = url.charCodeAt(end - 1);
|
|
215
|
-
if (last_char === RIGHT_PAREN) {
|
|
216
|
-
end--;
|
|
217
|
-
close_count--;
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
// Return original string if no trimming, otherwise slice once
|
|
225
|
-
return end === url.length ? url : url.slice(0, end);
|
|
226
|
-
};
|
|
227
|
-
/**
|
|
228
|
-
* Extract a single tag (component or element) if it's the only non-whitespace content.
|
|
229
|
-
* Returns the tag node if paragraph wrapping should be skipped (MDX convention),
|
|
230
|
-
* or null if the content should be wrapped in a paragraph.
|
|
231
|
-
*/
|
|
232
|
-
/**
|
|
233
|
-
* Check if position in text is the start of an absolute path (starts with `/`).
|
|
234
|
-
* Must be preceded by whitespace or be at the start of the string.
|
|
235
|
-
* Rejects `//` (comments/protocol-relative) and slash followed by whitespace.
|
|
236
|
-
*/
|
|
237
|
-
export const is_at_absolute_path = (text, index) => {
|
|
238
|
-
if (text.charCodeAt(index) !== SLASH)
|
|
239
|
-
return false;
|
|
240
|
-
if (index > 0) {
|
|
241
|
-
const prev_char = text.charCodeAt(index - 1);
|
|
242
|
-
if (prev_char !== SPACE && prev_char !== NEWLINE && prev_char !== TAB)
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
if (index + 1 >= text.length)
|
|
246
|
-
return false;
|
|
247
|
-
const next_char = text.charCodeAt(index + 1);
|
|
248
|
-
return next_char !== SLASH && next_char !== SPACE && next_char !== NEWLINE && next_char !== TAB;
|
|
249
|
-
};
|
|
250
|
-
/**
|
|
251
|
-
* Check if position in text is the start of a relative path (`./` or `../`).
|
|
252
|
-
* Must be preceded by whitespace or be at the start of the string.
|
|
253
|
-
* Rejects prefix followed by whitespace, slash, or end of string.
|
|
254
|
-
*/
|
|
255
|
-
export const is_at_relative_path = (text, index) => {
|
|
256
|
-
if (text.charCodeAt(index) !== PERIOD)
|
|
257
|
-
return false;
|
|
258
|
-
if (index > 0) {
|
|
259
|
-
const prev_char = text.charCodeAt(index - 1);
|
|
260
|
-
if (prev_char !== SPACE && prev_char !== NEWLINE && prev_char !== TAB)
|
|
261
|
-
return false;
|
|
262
|
-
}
|
|
263
|
-
const remaining = text.length - index;
|
|
264
|
-
// Check for ../ (at least 4 chars: ../x)
|
|
265
|
-
if (remaining >= 4 &&
|
|
266
|
-
text.charCodeAt(index + 1) === PERIOD &&
|
|
267
|
-
text.charCodeAt(index + 2) === SLASH) {
|
|
268
|
-
const after = text.charCodeAt(index + 3);
|
|
269
|
-
return after !== SPACE && after !== NEWLINE && after !== TAB && after !== SLASH;
|
|
270
|
-
}
|
|
271
|
-
// Check for ./ (at least 3 chars: ./x)
|
|
272
|
-
if (remaining >= 3 && text.charCodeAt(index + 1) === SLASH) {
|
|
273
|
-
const after = text.charCodeAt(index + 2);
|
|
274
|
-
return after !== SPACE && after !== NEWLINE && after !== TAB && after !== SLASH;
|
|
275
|
-
}
|
|
276
|
-
return false;
|
|
277
|
-
};
|
|
278
|
-
/**
|
|
279
|
-
* Extracts plain text content from an array of mdz nodes, recursing into children.
|
|
280
|
-
*/
|
|
281
|
-
export const mdz_text_content = (nodes) => nodes
|
|
282
|
-
.map((n) => ('children' in n ? mdz_text_content(n.children) : 'content' in n ? n.content : ''))
|
|
283
|
-
.join('');
|
|
284
|
-
/**
|
|
285
|
-
* Generates a lowercase slug id for a heading from its child nodes.
|
|
286
|
-
* Follows standard markdown conventions (GitHub, etc.) where heading IDs are lowercased.
|
|
287
|
-
* For case-preserving IDs (e.g. API declarations), see `docs_slugify` in `docs_helpers.svelte.ts`.
|
|
288
|
-
*/
|
|
289
|
-
export const mdz_heading_id = (nodes) => slugify(mdz_text_content(nodes), false);
|
|
290
|
-
/**
|
|
291
|
-
* Generates a lowercase slug id for a heading from plain text content.
|
|
292
|
-
* Used by the streaming parser which tracks text content directly
|
|
293
|
-
* rather than building `MdzNode[]` trees.
|
|
294
|
-
*/
|
|
295
|
-
export const mdz_heading_id_from_text = (text) => slugify(text, false);
|
|
296
|
-
/**
|
|
297
|
-
* Check if a string is a URL (`https://` or `http://`).
|
|
298
|
-
* Requires at least one valid character after the protocol.
|
|
299
|
-
* Rejects whitespace and characters that can't start a valid hostname.
|
|
300
|
-
*/
|
|
301
|
-
const URL_PATTERN = /^https?:\/\/[^\s)\]}<>.,:/?#!]/i;
|
|
302
|
-
export const mdz_is_url = (s) => URL_PATTERN.test(s);
|
|
303
|
-
/**
|
|
304
|
-
* Check if a link reference is safe to use as an `href` attribute.
|
|
305
|
-
* References without a colon are always safe (paths, fragments, queries).
|
|
306
|
-
* References with a colon must use `http(s)://` — rejects `javascript:`, `data:`, etc.
|
|
307
|
-
*/
|
|
308
|
-
const SAFE_PROTOCOL_PATTERN = /^https?:\/\//i;
|
|
309
|
-
export const mdz_is_safe_reference = (reference) => !reference.includes(':') || SAFE_PROTOCOL_PATTERN.test(reference);
|
|
310
|
-
/**
|
|
311
|
-
* Resolves a relative path (`./` or `../`) against a base path.
|
|
312
|
-
* The base is treated as a directory regardless of trailing slash
|
|
313
|
-
* (`'/docs/mdz'` and `'/docs/mdz/'` behave identically).
|
|
314
|
-
* Handles embedded `.` and `..` segments within the reference
|
|
315
|
-
* (e.g., `'./a/../b'` → navigates up then down).
|
|
316
|
-
* Clamps at root — excess `..` segments stop at `/` rather than escaping.
|
|
317
|
-
*
|
|
318
|
-
* @param reference - a relative path starting with `./` or `../`
|
|
319
|
-
* @param base - An absolute base path (e.g., `'/docs/mdz/'`). Empty string is treated as root.
|
|
320
|
-
* @returns an absolute resolved path (e.g., `'/docs/mdz/grammar'`)
|
|
321
|
-
*/
|
|
322
|
-
export const resolve_relative_path = (reference, base) => {
|
|
323
|
-
const segments = base.split('/');
|
|
324
|
-
// Remove trailing empty from split (e.g., '/docs/mdz/' → ['', 'docs', 'mdz', ''])
|
|
325
|
-
// but keep the root segment ([''] from '' base or ['', ''] from '/').
|
|
326
|
-
if (segments.length > 1 && segments.at(-1) === '')
|
|
327
|
-
segments.pop();
|
|
328
|
-
const trailing = reference.endsWith('/');
|
|
329
|
-
for (const segment of reference.split('/')) {
|
|
330
|
-
if (segment === '.' || segment === '')
|
|
331
|
-
continue;
|
|
332
|
-
if (segment === '..') {
|
|
333
|
-
if (segments.length > 1)
|
|
334
|
-
segments.pop(); // clamp at root
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
segments.push(segment);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
if (trailing)
|
|
341
|
-
segments.push('');
|
|
342
|
-
return segments.join('/');
|
|
343
|
-
};
|
|
344
|
-
/**
|
|
345
|
-
* Push a node into a children array, coalescing with the previous Text node.
|
|
346
|
-
* Mutates `prev.content` and `prev.end` when both are Text, avoiding array growth
|
|
347
|
-
* and an extra allocation. Callers must own `dest` and not retain references to
|
|
348
|
-
* the prior last element across the call.
|
|
349
|
-
*/
|
|
350
|
-
export const mdz_push_merging_text = (dest, node) => {
|
|
351
|
-
if (node.type === 'Text') {
|
|
352
|
-
const last = dest[dest.length - 1];
|
|
353
|
-
if (last?.type === 'Text') {
|
|
354
|
-
last.content += node.content;
|
|
355
|
-
last.end = node.end;
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
dest.push(node);
|
|
360
|
-
};
|
|
361
|
-
/**
|
|
362
|
-
* Return a new array with adjacent Text nodes merged into single nodes.
|
|
363
|
-
* Fast path: returns the original array when no merging is needed.
|
|
364
|
-
*/
|
|
365
|
-
export const mdz_merge_adjacent_text = (nodes) => {
|
|
366
|
-
if (nodes.length <= 1)
|
|
367
|
-
return nodes;
|
|
368
|
-
let needs_merge = false;
|
|
369
|
-
for (let i = 1; i < nodes.length; i++) {
|
|
370
|
-
if (nodes[i - 1].type === 'Text' && nodes[i].type === 'Text') {
|
|
371
|
-
needs_merge = true;
|
|
372
|
-
break;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
if (!needs_merge)
|
|
376
|
-
return nodes;
|
|
377
|
-
const merged = [];
|
|
378
|
-
let pending = null;
|
|
379
|
-
for (const node of nodes) {
|
|
380
|
-
if (node.type === 'Text') {
|
|
381
|
-
if (pending) {
|
|
382
|
-
pending = {
|
|
383
|
-
type: 'Text',
|
|
384
|
-
content: pending.content + node.content,
|
|
385
|
-
start: pending.start,
|
|
386
|
-
end: node.end,
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
pending = { ...node };
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
else {
|
|
394
|
-
if (pending) {
|
|
395
|
-
merged.push(pending);
|
|
396
|
-
pending = null;
|
|
397
|
-
}
|
|
398
|
-
merged.push(node);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (pending)
|
|
402
|
-
merged.push(pending);
|
|
403
|
-
return merged;
|
|
404
|
-
};
|
|
405
|
-
export const extract_single_tag = (nodes) => {
|
|
406
|
-
let tag = null;
|
|
407
|
-
for (const node of nodes) {
|
|
408
|
-
if (node.type === 'Component' || node.type === 'Element') {
|
|
409
|
-
if (tag)
|
|
410
|
-
return null; // Multiple tags
|
|
411
|
-
tag = node;
|
|
412
|
-
}
|
|
413
|
-
else if (node.type === 'Text') {
|
|
414
|
-
// Allow only whitespace-only text nodes
|
|
415
|
-
if (node.content.trim() !== '')
|
|
416
|
-
return null;
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
// Any other node type means not a single tag
|
|
420
|
-
return null;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
return tag;
|
|
424
|
-
};
|
package/dist/mdz_lexer.d.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* mdz lexer — tokenizes input into a flat `MdzToken[]` stream.
|
|
3
|
-
*
|
|
4
|
-
* Phase 1 of the two-phase lexer+parser alternative to the single-pass parser
|
|
5
|
-
* in `mdz.ts`. Phase 2 is in `mdz_token_parser.ts`.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
export interface MdzTokenBase {
|
|
10
|
-
start: number;
|
|
11
|
-
end: number;
|
|
12
|
-
}
|
|
13
|
-
export type MdzToken = MdzTokenText | MdzTokenCode | MdzTokenCodeblock | MdzTokenBoldOpen | MdzTokenBoldClose | MdzTokenItalicOpen | MdzTokenItalicClose | MdzTokenStrikethroughOpen | MdzTokenStrikethroughClose | MdzTokenLinkTextOpen | MdzTokenLinkTextClose | MdzTokenLinkRef | MdzTokenAutolink | MdzTokenHeadingStart | MdzTokenHr | MdzTokenTagOpen | MdzTokenTagSelfClose | MdzTokenTagClose | MdzTokenHeadingEnd | MdzTokenParagraphBreak;
|
|
14
|
-
export interface MdzTokenText extends MdzTokenBase {
|
|
15
|
-
type: 'text';
|
|
16
|
-
content: string;
|
|
17
|
-
}
|
|
18
|
-
export interface MdzTokenCode extends MdzTokenBase {
|
|
19
|
-
type: 'code';
|
|
20
|
-
content: string;
|
|
21
|
-
}
|
|
22
|
-
export interface MdzTokenCodeblock extends MdzTokenBase {
|
|
23
|
-
type: 'codeblock';
|
|
24
|
-
lang: string | null;
|
|
25
|
-
content: string;
|
|
26
|
-
}
|
|
27
|
-
export interface MdzTokenBoldOpen extends MdzTokenBase {
|
|
28
|
-
type: 'bold_open';
|
|
29
|
-
}
|
|
30
|
-
export interface MdzTokenBoldClose extends MdzTokenBase {
|
|
31
|
-
type: 'bold_close';
|
|
32
|
-
}
|
|
33
|
-
export interface MdzTokenItalicOpen extends MdzTokenBase {
|
|
34
|
-
type: 'italic_open';
|
|
35
|
-
}
|
|
36
|
-
export interface MdzTokenItalicClose extends MdzTokenBase {
|
|
37
|
-
type: 'italic_close';
|
|
38
|
-
}
|
|
39
|
-
export interface MdzTokenStrikethroughOpen extends MdzTokenBase {
|
|
40
|
-
type: 'strikethrough_open';
|
|
41
|
-
}
|
|
42
|
-
export interface MdzTokenStrikethroughClose extends MdzTokenBase {
|
|
43
|
-
type: 'strikethrough_close';
|
|
44
|
-
}
|
|
45
|
-
export interface MdzTokenLinkTextOpen extends MdzTokenBase {
|
|
46
|
-
type: 'link_text_open';
|
|
47
|
-
}
|
|
48
|
-
export interface MdzTokenLinkTextClose extends MdzTokenBase {
|
|
49
|
-
type: 'link_text_close';
|
|
50
|
-
}
|
|
51
|
-
export interface MdzTokenLinkRef extends MdzTokenBase {
|
|
52
|
-
type: 'link_ref';
|
|
53
|
-
reference: string;
|
|
54
|
-
link_type: 'external' | 'internal';
|
|
55
|
-
}
|
|
56
|
-
export interface MdzTokenAutolink extends MdzTokenBase {
|
|
57
|
-
type: 'autolink';
|
|
58
|
-
reference: string;
|
|
59
|
-
link_type: 'external' | 'internal';
|
|
60
|
-
}
|
|
61
|
-
export interface MdzTokenHeadingStart extends MdzTokenBase {
|
|
62
|
-
type: 'heading_start';
|
|
63
|
-
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
64
|
-
}
|
|
65
|
-
export interface MdzTokenHr extends MdzTokenBase {
|
|
66
|
-
type: 'hr';
|
|
67
|
-
}
|
|
68
|
-
export interface MdzTokenTagOpen extends MdzTokenBase {
|
|
69
|
-
type: 'tag_open';
|
|
70
|
-
name: string;
|
|
71
|
-
is_component: boolean;
|
|
72
|
-
}
|
|
73
|
-
export interface MdzTokenTagSelfClose extends MdzTokenBase {
|
|
74
|
-
type: 'tag_self_close';
|
|
75
|
-
name: string;
|
|
76
|
-
is_component: boolean;
|
|
77
|
-
}
|
|
78
|
-
export interface MdzTokenTagClose extends MdzTokenBase {
|
|
79
|
-
type: 'tag_close';
|
|
80
|
-
name: string;
|
|
81
|
-
}
|
|
82
|
-
export interface MdzTokenHeadingEnd extends MdzTokenBase {
|
|
83
|
-
type: 'heading_end';
|
|
84
|
-
}
|
|
85
|
-
export interface MdzTokenParagraphBreak extends MdzTokenBase {
|
|
86
|
-
type: 'paragraph_break';
|
|
87
|
-
}
|
|
88
|
-
export declare class MdzLexer {
|
|
89
|
-
#private;
|
|
90
|
-
constructor(text: string);
|
|
91
|
-
tokenize(): Array<MdzToken>;
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=mdz_lexer.d.ts.map
|
package/dist/mdz_lexer.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mdz_lexer.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_lexer.ts"],"names":[],"mappings":"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"}
|