@fuzdev/fuz_ui 0.203.1 → 0.205.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.
- package/dist/Alert.svelte +31 -17
- package/dist/Alert.svelte.d.ts +8 -2
- package/dist/Alert.svelte.d.ts.map +1 -1
- package/dist/ApiModule.svelte +14 -1
- package/dist/ApiModule.svelte.d.ts.map +1 -1
- package/dist/Card.svelte +28 -10
- package/dist/Card.svelte.d.ts +7 -2
- package/dist/Card.svelte.d.ts.map +1 -1
- package/dist/CopyToClipboard.svelte +5 -1
- 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/DocsLink.svelte +15 -4
- package/dist/DocsLink.svelte.d.ts +8 -1
- package/dist/DocsLink.svelte.d.ts.map +1 -1
- package/dist/DocsMenu.svelte +1 -1
- package/dist/DocsPageLinks.svelte +1 -1
- package/dist/EcosystemLinks.svelte +5 -2
- package/dist/EcosystemLinks.svelte.d.ts +2 -1
- package/dist/EcosystemLinks.svelte.d.ts.map +1 -1
- package/dist/EcosystemLinksPanel.svelte +4 -2
- package/dist/EcosystemLinksPanel.svelte.d.ts +2 -1
- package/dist/EcosystemLinksPanel.svelte.d.ts.map +1 -1
- package/dist/Hashlink.svelte +1 -1
- package/dist/ImgOrSvg.svelte +6 -5
- package/dist/ImgOrSvg.svelte.d.ts +2 -1
- package/dist/ImgOrSvg.svelte.d.ts.map +1 -1
- package/dist/LibraryDetail.svelte +5 -2
- package/dist/LibraryDetail.svelte.d.ts +3 -1
- package/dist/LibraryDetail.svelte.d.ts.map +1 -1
- package/dist/LibrarySummary.svelte +4 -2
- package/dist/LibrarySummary.svelte.d.ts +2 -1
- package/dist/LibrarySummary.svelte.d.ts.map +1 -1
- package/dist/PasteFromClipboard.svelte +3 -1
- package/dist/PasteFromClipboard.svelte.d.ts.map +1 -1
- package/dist/PendingButton.svelte +0 -2
- package/dist/PendingButton.svelte.d.ts.map +1 -1
- package/dist/StyleVariableButton.svelte +5 -1
- package/dist/StyleVariableButton.svelte.d.ts.map +1 -1
- package/dist/Svg.svelte +1 -1
- package/dist/TomeContent.svelte +5 -2
- package/dist/TomeContent.svelte.d.ts +2 -1
- package/dist/TomeContent.svelte.d.ts.map +1 -1
- package/dist/TypeLink.svelte +13 -4
- package/dist/TypeLink.svelte.d.ts +7 -1
- package/dist/TypeLink.svelte.d.ts.map +1 -1
- package/package.json +12 -36
- 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
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auto-URL and auto-path handlers (text-first scanning) for the streaming
|
|
3
|
-
* mdz parser. Operates in two phases:
|
|
4
|
-
*
|
|
5
|
-
* 1. Speculative prefix matching: chars stream as visible text while we
|
|
6
|
-
* verify a `https://` / `http://` prefix.
|
|
7
|
-
* 2. Confirmed mode: chars stream as text and on terminator a `wrap`
|
|
8
|
-
* opcode retroactively wraps the text node in a Link.
|
|
9
|
-
*
|
|
10
|
-
* Paths (`/...`, `./...`, `../...`) skip phase 1 — their prefix is validated
|
|
11
|
-
* by hold (require enough lookahead).
|
|
12
|
-
*
|
|
13
|
-
* @module
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
NEWLINE,
|
|
18
|
-
SPACE,
|
|
19
|
-
TAB,
|
|
20
|
-
PERIOD,
|
|
21
|
-
SLASH,
|
|
22
|
-
ascii_to_lower,
|
|
23
|
-
is_valid_path_char,
|
|
24
|
-
is_word_char,
|
|
25
|
-
match_url_prefix_case_insensitive,
|
|
26
|
-
trim_trailing_punctuation,
|
|
27
|
-
} from './mdz_helpers.js';
|
|
28
|
-
import {
|
|
29
|
-
type MdzStreamParserState,
|
|
30
|
-
type TryResult,
|
|
31
|
-
accumulate_text,
|
|
32
|
-
alloc_id,
|
|
33
|
-
emit,
|
|
34
|
-
ensure_paragraph,
|
|
35
|
-
flush_text,
|
|
36
|
-
offset,
|
|
37
|
-
} from './mdz_stream_parser_state.js';
|
|
38
|
-
|
|
39
|
-
const HTTPS_PREFIX = 'https://';
|
|
40
|
-
const HTTP_PREFIX = 'http://';
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Forced-mode URL detection: the full prefix must be in the buffer.
|
|
44
|
-
* Used at EOF when speculative prefix matching isn't needed.
|
|
45
|
-
* Scheme match is case-insensitive (RFC 3986).
|
|
46
|
-
*/
|
|
47
|
-
export const try_auto_url_forced = (state: MdzStreamParserState): TryResult => {
|
|
48
|
-
if (state.prev_char !== -1 && is_word_char(state.prev_char)) return 'not_match';
|
|
49
|
-
|
|
50
|
-
const prefix_len = match_url_prefix_case_insensitive(state.buffer, state.pos);
|
|
51
|
-
if (prefix_len === 0) return 'not_match';
|
|
52
|
-
|
|
53
|
-
// must have content after protocol
|
|
54
|
-
if (state.pos + prefix_len >= state.buffer.length) return 'not_match';
|
|
55
|
-
const after = state.buffer.charCodeAt(state.pos + prefix_len);
|
|
56
|
-
if (after === SPACE || after === NEWLINE) return 'not_match';
|
|
57
|
-
|
|
58
|
-
return scan_auto_link_forced(state, 'external');
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export const try_auto_path_absolute = (state: MdzStreamParserState, forced = false): TryResult => {
|
|
62
|
-
// must be at word boundary (preceded by space/newline/start)
|
|
63
|
-
if (
|
|
64
|
-
state.prev_char !== -1 &&
|
|
65
|
-
state.prev_char !== SPACE &&
|
|
66
|
-
state.prev_char !== NEWLINE &&
|
|
67
|
-
state.prev_char !== TAB
|
|
68
|
-
) {
|
|
69
|
-
return 'not_match';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// reject // and /space
|
|
73
|
-
if (state.pos + 1 >= state.buffer.length) return forced ? 'not_match' : 'need_more';
|
|
74
|
-
const next = state.buffer.charCodeAt(state.pos + 1);
|
|
75
|
-
if (next === SLASH || next === SPACE || next === NEWLINE || next === TAB) {
|
|
76
|
-
return 'not_match';
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (forced) return scan_auto_link_forced(state, 'internal');
|
|
80
|
-
start_pending_url(state, 'internal');
|
|
81
|
-
return 'consumed';
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export const try_auto_path_relative = (state: MdzStreamParserState, forced = false): TryResult => {
|
|
85
|
-
if (
|
|
86
|
-
state.prev_char !== -1 &&
|
|
87
|
-
state.prev_char !== SPACE &&
|
|
88
|
-
state.prev_char !== NEWLINE &&
|
|
89
|
-
state.prev_char !== TAB
|
|
90
|
-
) {
|
|
91
|
-
return 'not_match';
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// check for ./ or ../
|
|
95
|
-
const remaining = state.buffer.length - state.pos;
|
|
96
|
-
if (remaining < 3) return forced ? 'not_match' : 'need_more';
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
state.buffer.charCodeAt(state.pos + 1) === PERIOD &&
|
|
100
|
-
state.buffer.charCodeAt(state.pos + 2) === SLASH
|
|
101
|
-
) {
|
|
102
|
-
// ../
|
|
103
|
-
if (remaining < 4) return forced ? 'not_match' : 'need_more';
|
|
104
|
-
const after = state.buffer.charCodeAt(state.pos + 3);
|
|
105
|
-
if (after === SPACE || after === NEWLINE || after === TAB || after === SLASH) {
|
|
106
|
-
return 'not_match';
|
|
107
|
-
}
|
|
108
|
-
if (forced) return scan_auto_link_forced(state, 'internal');
|
|
109
|
-
start_pending_url(state, 'internal');
|
|
110
|
-
return 'consumed';
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (state.buffer.charCodeAt(state.pos + 1) === SLASH) {
|
|
114
|
-
// ./
|
|
115
|
-
const after = state.buffer.charCodeAt(state.pos + 2);
|
|
116
|
-
if (after === SPACE || after === NEWLINE || after === TAB || after === SLASH) {
|
|
117
|
-
return 'not_match';
|
|
118
|
-
}
|
|
119
|
-
if (forced) return scan_auto_link_forced(state, 'internal');
|
|
120
|
-
start_pending_url(state, 'internal');
|
|
121
|
-
return 'consumed';
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return 'not_match';
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Start confirmed text-first mode for paths. Prefix already validated by hold.
|
|
129
|
-
* Flushes prior text, resets active_text_id, sets pending_url with confirmed=true.
|
|
130
|
-
*/
|
|
131
|
-
export const start_pending_url = (
|
|
132
|
-
state: MdzStreamParserState,
|
|
133
|
-
link_type: 'external' | 'internal',
|
|
134
|
-
): void => {
|
|
135
|
-
flush_text(state);
|
|
136
|
-
ensure_paragraph(state);
|
|
137
|
-
state.active_text_id = null;
|
|
138
|
-
state.pending_url = {
|
|
139
|
-
url_text: '',
|
|
140
|
-
start: offset(state),
|
|
141
|
-
link_type,
|
|
142
|
-
confirmed: true,
|
|
143
|
-
viable_https: false,
|
|
144
|
-
viable_http: false,
|
|
145
|
-
};
|
|
146
|
-
// don't advance pos — URL chars start at current position, handled by process_url_content
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Start speculative text-first mode for URL prefixes.
|
|
151
|
-
* Chars stream as visible text while we verify `https://` or `http://`.
|
|
152
|
-
* Cancels if prefix doesn't match (text stays as plain text).
|
|
153
|
-
*/
|
|
154
|
-
export const start_speculative_url = (state: MdzStreamParserState): void => {
|
|
155
|
-
flush_text(state);
|
|
156
|
-
ensure_paragraph(state);
|
|
157
|
-
state.active_text_id = null;
|
|
158
|
-
state.pending_url = {
|
|
159
|
-
url_text: '',
|
|
160
|
-
start: offset(state),
|
|
161
|
-
link_type: 'external',
|
|
162
|
-
confirmed: false,
|
|
163
|
-
viable_https: true,
|
|
164
|
-
viable_http: true,
|
|
165
|
-
};
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Speculative URL prefix matching. Checks each char against viable prefixes,
|
|
170
|
-
* streaming as text. Confirms on full match, cancels on mismatch.
|
|
171
|
-
*
|
|
172
|
-
* Scheme letters (`h`, `t`, `p`, `s`) are matched case-insensitively (RFC 3986);
|
|
173
|
-
* the `:` and `//` portion remains literal. Original casing is preserved in
|
|
174
|
-
* the emitted reference.
|
|
175
|
-
*/
|
|
176
|
-
export const process_url_prefix = (state: MdzStreamParserState): void => {
|
|
177
|
-
const pu = state.pending_url!;
|
|
178
|
-
const char_code = state.buffer.charCodeAt(state.pos);
|
|
179
|
-
const pos = pu.url_text.length;
|
|
180
|
-
|
|
181
|
-
// scheme letters (positions 0-4) match case-insensitively;
|
|
182
|
-
// `:` and `/` (positions 5-7 for https, 4-6 for http) are literal.
|
|
183
|
-
const cmp_code = pos < 5 ? ascii_to_lower(char_code) : char_code;
|
|
184
|
-
|
|
185
|
-
// narrow viable prefixes
|
|
186
|
-
if (
|
|
187
|
-
pu.viable_https &&
|
|
188
|
-
(pos >= HTTPS_PREFIX.length || cmp_code !== HTTPS_PREFIX.charCodeAt(pos))
|
|
189
|
-
) {
|
|
190
|
-
pu.viable_https = false;
|
|
191
|
-
}
|
|
192
|
-
if (pu.viable_http && (pos >= HTTP_PREFIX.length || cmp_code !== HTTP_PREFIX.charCodeAt(pos))) {
|
|
193
|
-
pu.viable_http = false;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (!pu.viable_https && !pu.viable_http) {
|
|
197
|
-
// no viable prefix — cancel speculation, don't consume char
|
|
198
|
-
state.pending_url = null;
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// char matches — accumulate as text
|
|
203
|
-
accumulate_text(state, state.buffer[state.pos]!, offset(state));
|
|
204
|
-
pu.url_text += state.buffer[state.pos];
|
|
205
|
-
state.pos++;
|
|
206
|
-
state.column++;
|
|
207
|
-
state.prev_char = char_code;
|
|
208
|
-
|
|
209
|
-
// check if a prefix is fully confirmed
|
|
210
|
-
if (
|
|
211
|
-
(pu.viable_https && pos + 1 === HTTPS_PREFIX.length) ||
|
|
212
|
-
(pu.viable_http && pos + 1 === HTTP_PREFIX.length)
|
|
213
|
-
) {
|
|
214
|
-
pu.confirmed = true;
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Process URL/path chars in text-first mode. Scans path chars,
|
|
220
|
-
* accumulates as visible text. Terminates on space/newline/non-path-char
|
|
221
|
-
* and emits a `wrap` opcode.
|
|
222
|
-
*/
|
|
223
|
-
export const process_url_content = (state: MdzStreamParserState, forced: boolean): void => {
|
|
224
|
-
// speculative prefix matching phase
|
|
225
|
-
if (!state.pending_url!.confirmed) {
|
|
226
|
-
process_url_prefix(state);
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const char_code = state.buffer.charCodeAt(state.pos);
|
|
231
|
-
|
|
232
|
-
// URL terminator
|
|
233
|
-
if (char_code === SPACE || char_code === NEWLINE || !is_valid_path_char(char_code)) {
|
|
234
|
-
flush_text(state);
|
|
235
|
-
complete_pending_url(state);
|
|
236
|
-
// don't consume terminator — outer loop handles it
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// scan URL chars
|
|
241
|
-
const start = state.pos;
|
|
242
|
-
state.pos++;
|
|
243
|
-
while (state.pos < state.buffer.length) {
|
|
244
|
-
const c = state.buffer.charCodeAt(state.pos);
|
|
245
|
-
if (c === SPACE || c === NEWLINE || !is_valid_path_char(c)) break;
|
|
246
|
-
state.pos++;
|
|
247
|
-
}
|
|
248
|
-
const text = state.buffer.slice(start, state.pos);
|
|
249
|
-
accumulate_text(state, text, offset(state, start));
|
|
250
|
-
state.pending_url!.url_text += text;
|
|
251
|
-
state.prev_char = state.buffer.charCodeAt(state.pos - 1);
|
|
252
|
-
state.column += state.pos - start;
|
|
253
|
-
|
|
254
|
-
// at EOF in forced mode, finalize the URL
|
|
255
|
-
if (state.pos >= state.buffer.length && forced) {
|
|
256
|
-
flush_text(state);
|
|
257
|
-
complete_pending_url(state);
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Complete a pending URL: compute reference with trimmed punctuation,
|
|
263
|
-
* emit a `wrap` opcode to retroactively wrap the text node in a Link.
|
|
264
|
-
*/
|
|
265
|
-
export const complete_pending_url = (state: MdzStreamParserState): void => {
|
|
266
|
-
const pu = state.pending_url!;
|
|
267
|
-
state.pending_url = null;
|
|
268
|
-
|
|
269
|
-
const reference = trim_trailing_punctuation(pu.url_text);
|
|
270
|
-
if (reference.length === 0) return; // empty after trimming — text stays as plain text
|
|
271
|
-
|
|
272
|
-
// for external URLs, must have content after protocol prefix
|
|
273
|
-
if (pu.link_type === 'external') {
|
|
274
|
-
const prefix_len = match_url_prefix_case_insensitive(reference, 0);
|
|
275
|
-
if (reference.length < prefix_len + 1) return; // just protocol, no content
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const text_id = state.active_text_id;
|
|
279
|
-
if (text_id === null) return; // no text node to wrap (shouldn't happen)
|
|
280
|
-
|
|
281
|
-
const trim_end = pu.url_text.length - reference.length;
|
|
282
|
-
const wrap_id = alloc_id(state);
|
|
283
|
-
const url_end = pu.start + reference.length;
|
|
284
|
-
|
|
285
|
-
if (trim_end > 0) {
|
|
286
|
-
const trim_id = alloc_id(state);
|
|
287
|
-
emit(state, {
|
|
288
|
-
type: 'wrap',
|
|
289
|
-
id: wrap_id,
|
|
290
|
-
node_type: 'Link',
|
|
291
|
-
target_id: text_id,
|
|
292
|
-
reference,
|
|
293
|
-
link_type: pu.link_type,
|
|
294
|
-
start: pu.start,
|
|
295
|
-
end: url_end,
|
|
296
|
-
trim_end,
|
|
297
|
-
trim_id,
|
|
298
|
-
});
|
|
299
|
-
state.active_text_id = trim_id;
|
|
300
|
-
} else {
|
|
301
|
-
emit(state, {
|
|
302
|
-
type: 'wrap',
|
|
303
|
-
id: wrap_id,
|
|
304
|
-
node_type: 'Link',
|
|
305
|
-
target_id: text_id,
|
|
306
|
-
reference,
|
|
307
|
-
link_type: pu.link_type,
|
|
308
|
-
start: pu.start,
|
|
309
|
-
end: url_end,
|
|
310
|
-
});
|
|
311
|
-
state.active_text_id = null;
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Forced-mode auto-link: scan the full URL/path inline (no streaming needed
|
|
317
|
-
* at EOF). Used when forced=true — the entire URL must be in the buffer.
|
|
318
|
-
*/
|
|
319
|
-
export const scan_auto_link_forced = (
|
|
320
|
-
state: MdzStreamParserState,
|
|
321
|
-
link_type: 'external' | 'internal',
|
|
322
|
-
): TryResult => {
|
|
323
|
-
let i = state.pos;
|
|
324
|
-
while (i < state.buffer.length) {
|
|
325
|
-
const c = state.buffer.charCodeAt(i);
|
|
326
|
-
if (c === SPACE || c === NEWLINE || !is_valid_path_char(c)) break;
|
|
327
|
-
i++;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
let reference = state.buffer.slice(state.pos, i);
|
|
331
|
-
reference = trim_trailing_punctuation(reference);
|
|
332
|
-
if (reference.length === 0) return 'not_match';
|
|
333
|
-
|
|
334
|
-
// for external URLs, must have content after protocol prefix
|
|
335
|
-
if (link_type === 'external') {
|
|
336
|
-
const prefix_len = match_url_prefix_case_insensitive(reference, 0);
|
|
337
|
-
if (reference.length < prefix_len + 1) return 'not_match';
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const end_pos = state.pos + reference.length;
|
|
341
|
-
const link_start = offset(state);
|
|
342
|
-
const link_end = offset(state, end_pos);
|
|
343
|
-
|
|
344
|
-
flush_text(state);
|
|
345
|
-
ensure_paragraph(state);
|
|
346
|
-
|
|
347
|
-
const link_id = alloc_id(state);
|
|
348
|
-
emit(state, {type: 'open', id: link_id, node_type: 'Link', start: link_start});
|
|
349
|
-
const text_id = alloc_id(state);
|
|
350
|
-
emit(state, {
|
|
351
|
-
type: 'text',
|
|
352
|
-
id: text_id,
|
|
353
|
-
content: reference,
|
|
354
|
-
text_type: 'Text',
|
|
355
|
-
start: link_start,
|
|
356
|
-
end: link_end,
|
|
357
|
-
});
|
|
358
|
-
emit(state, {type: 'close', id: link_id, end: link_end, reference, link_type});
|
|
359
|
-
|
|
360
|
-
state.active_text_id = null;
|
|
361
|
-
state.column += end_pos - state.pos;
|
|
362
|
-
state.prev_char = reference.charCodeAt(reference.length - 1);
|
|
363
|
-
state.pos = end_pos;
|
|
364
|
-
return 'consumed';
|
|
365
|
-
};
|