@vesk/runtime 0.0.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/README.md +23 -0
- package/dist/action.d.ts +43 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +84 -0
- package/dist/bindings.d.ts +4 -0
- package/dist/bindings.d.ts.map +1 -0
- package/dist/bindings.js +137 -0
- package/dist/context.d.ts +15 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +34 -0
- package/dist/experiment.d.ts +17 -0
- package/dist/experiment.d.ts.map +1 -0
- package/dist/experiment.js +71 -0
- package/dist/form.d.ts +36 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +278 -0
- package/dist/hmr-client.d.ts +1 -0
- package/dist/hmr-client.d.ts.map +1 -0
- package/dist/hmr-client.js +273 -0
- package/dist/hydrate.d.ts +34 -0
- package/dist/hydrate.d.ts.map +1 -0
- package/dist/hydrate.js +248 -0
- package/dist/image.d.ts +19 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +51 -0
- package/dist/index-client.d.ts +16 -0
- package/dist/index-client.d.ts.map +1 -0
- package/dist/index-client.js +15 -0
- package/dist/index-server.d.ts +15 -0
- package/dist/index-server.d.ts.map +1 -0
- package/dist/index-server.js +14 -0
- package/dist/isr.d.ts +27 -0
- package/dist/isr.d.ts.map +1 -0
- package/dist/isr.js +143 -0
- package/dist/md.d.ts +17 -0
- package/dist/md.d.ts.map +1 -0
- package/dist/md.js +507 -0
- package/dist/package.json +23 -0
- package/dist/portal.d.ts +8 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +20 -0
- package/dist/reconcile.d.ts +3 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +66 -0
- package/dist/request.d.ts +188 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +624 -0
- package/dist/resource.d.ts +47 -0
- package/dist/resource.d.ts.map +1 -0
- package/dist/resource.js +502 -0
- package/dist/ripple-blocks.d.ts +18 -0
- package/dist/ripple-blocks.d.ts.map +1 -0
- package/dist/ripple-blocks.js +184 -0
- package/dist/ripple-constants.d.ts +42 -0
- package/dist/ripple-constants.d.ts.map +1 -0
- package/dist/ripple-constants.js +41 -0
- package/dist/ripple-runtime.d.ts +125 -0
- package/dist/ripple-runtime.d.ts.map +1 -0
- package/dist/ripple-runtime.js +891 -0
- package/dist/ripple-utils.d.ts +12 -0
- package/dist/ripple-utils.d.ts.map +1 -0
- package/dist/ripple-utils.js +10 -0
- package/dist/router-components.d.ts +83 -0
- package/dist/router-components.d.ts.map +1 -0
- package/dist/router-components.js +320 -0
- package/dist/router-match.d.ts +40 -0
- package/dist/router-match.d.ts.map +1 -0
- package/dist/router-match.js +158 -0
- package/dist/router.d.ts +56 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +1330 -0
- package/dist/seo.d.ts +94 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +138 -0
- package/dist/suspense.d.ts +1 -0
- package/dist/suspense.d.ts.map +1 -0
- package/dist/suspense.js +14 -0
- package/dist/track.d.ts +20 -0
- package/dist/track.d.ts.map +1 -0
- package/dist/track.js +124 -0
- package/package.json +55 -0
package/dist/md.js
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
// =============================================================
|
|
2
|
+
// Markdown rendering for <Md content={...} />.
|
|
3
|
+
//
|
|
4
|
+
// Tokenizer-based (no regex) — mirrors the compiler's no-regex
|
|
5
|
+
// rule for source-text handling. Raw HTML is never passed through;
|
|
6
|
+
// everything is escaped so content is safe to render as-is.
|
|
7
|
+
// =============================================================
|
|
8
|
+
export function escapeHtml(s) {
|
|
9
|
+
let out = '';
|
|
10
|
+
for (let i = 0; i < s.length; i++) {
|
|
11
|
+
const ch = s[i];
|
|
12
|
+
if (ch === '&')
|
|
13
|
+
out += '&';
|
|
14
|
+
else if (ch === '<')
|
|
15
|
+
out += '<';
|
|
16
|
+
else if (ch === '>')
|
|
17
|
+
out += '>';
|
|
18
|
+
else if (ch === '"')
|
|
19
|
+
out += '"';
|
|
20
|
+
else
|
|
21
|
+
out += ch;
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
function isBlank(line) {
|
|
26
|
+
for (let i = 0; i < line.length; i++) {
|
|
27
|
+
const ch = line[i];
|
|
28
|
+
if (ch !== ' ' && ch !== '\t')
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function leadingSpaces(line) {
|
|
34
|
+
let n = 0;
|
|
35
|
+
for (let i = 0; i < line.length; i++) {
|
|
36
|
+
if (line[i] === '\t')
|
|
37
|
+
n += 4 - (n % 4);
|
|
38
|
+
else if (line[i] === ' ')
|
|
39
|
+
n++;
|
|
40
|
+
else
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
return n;
|
|
44
|
+
}
|
|
45
|
+
function headingLevel(line) {
|
|
46
|
+
let n = 0;
|
|
47
|
+
while (n < line.length && line[n] === '#')
|
|
48
|
+
n++;
|
|
49
|
+
if (n === 0 || n > 6)
|
|
50
|
+
return 0;
|
|
51
|
+
if (n < line.length && (line[n] === ' ' || line[n] === '\t'))
|
|
52
|
+
return n;
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
function isHr(line) {
|
|
56
|
+
const t = line.trim();
|
|
57
|
+
if (t.length < 3)
|
|
58
|
+
return false;
|
|
59
|
+
const ch = t[0];
|
|
60
|
+
if (ch !== '-' && ch !== '*' && ch !== '_')
|
|
61
|
+
return false;
|
|
62
|
+
for (let i = 1; i < t.length; i++) {
|
|
63
|
+
if (t[i] !== ch && t[i] !== ' ')
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
function fenceInfo(line) {
|
|
69
|
+
const t = line.trim();
|
|
70
|
+
const ch = t[0];
|
|
71
|
+
if (ch !== '`' && ch !== '~')
|
|
72
|
+
return null;
|
|
73
|
+
let n = 0;
|
|
74
|
+
while (n < t.length && t[n] === ch)
|
|
75
|
+
n++;
|
|
76
|
+
if (n < 3)
|
|
77
|
+
return null;
|
|
78
|
+
return { char: ch, len: n, lang: t.slice(n).trim() };
|
|
79
|
+
}
|
|
80
|
+
function isFenceClose(line, char, len) {
|
|
81
|
+
const t = line.trim();
|
|
82
|
+
if (t[0] !== char)
|
|
83
|
+
return false;
|
|
84
|
+
let n = 0;
|
|
85
|
+
while (n < t.length && t[n] === char)
|
|
86
|
+
n++;
|
|
87
|
+
if (n < len)
|
|
88
|
+
return false;
|
|
89
|
+
for (let i = n; i < t.length; i++) {
|
|
90
|
+
if (t[i] !== ' ')
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function parseListMarker(line) {
|
|
96
|
+
const indent = leadingSpaces(line);
|
|
97
|
+
let i = indent;
|
|
98
|
+
const ch = line[i];
|
|
99
|
+
if (ch === '-' || ch === '*' || ch === '+') {
|
|
100
|
+
if (i + 1 < line.length && (line[i + 1] === ' ' || line[i + 1] === '\t')) {
|
|
101
|
+
return { ordered: false, number: 0, indent, contentStart: i + 2 };
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
let num = 0;
|
|
106
|
+
const digitsStart = i;
|
|
107
|
+
while (i < line.length && line[i] >= '0' && line[i] <= '9') {
|
|
108
|
+
num = num * 10 + (line.charCodeAt(i) - 48);
|
|
109
|
+
i++;
|
|
110
|
+
}
|
|
111
|
+
if (i === digitsStart)
|
|
112
|
+
return null;
|
|
113
|
+
if (i < line.length && line[i] === '.' && i + 1 < line.length && (line[i + 1] === ' ' || line[i + 1] === '\t')) {
|
|
114
|
+
return { ordered: true, number: num, indent, contentStart: i + 2 };
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
function parseBlocks(lines) {
|
|
119
|
+
const blocks = [];
|
|
120
|
+
let i = 0;
|
|
121
|
+
while (i < lines.length) {
|
|
122
|
+
const line = lines[i];
|
|
123
|
+
if (isBlank(line)) {
|
|
124
|
+
i++;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const trimmed = line.trim();
|
|
128
|
+
const indent = leadingSpaces(line);
|
|
129
|
+
const fence = fenceInfo(trimmed);
|
|
130
|
+
if (fence) {
|
|
131
|
+
const codeLines = [];
|
|
132
|
+
i++;
|
|
133
|
+
while (i < lines.length) {
|
|
134
|
+
const l = lines[i];
|
|
135
|
+
if (isFenceClose(l, fence.char, fence.len)) {
|
|
136
|
+
i++;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
codeLines.push(l);
|
|
140
|
+
i++;
|
|
141
|
+
}
|
|
142
|
+
blocks.push({ type: 'code', code: codeLines.join('\n'), lang: fence.lang });
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (indent >= 4) {
|
|
146
|
+
const codeLines = [];
|
|
147
|
+
while (i < lines.length) {
|
|
148
|
+
const l = lines[i];
|
|
149
|
+
if (isBlank(l)) {
|
|
150
|
+
codeLines.push('');
|
|
151
|
+
i++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const lIndent = leadingSpaces(l);
|
|
155
|
+
if (lIndent < 4)
|
|
156
|
+
break;
|
|
157
|
+
codeLines.push(l.slice(4));
|
|
158
|
+
i++;
|
|
159
|
+
}
|
|
160
|
+
while (codeLines.length > 0 && codeLines[codeLines.length - 1] === '')
|
|
161
|
+
codeLines.pop();
|
|
162
|
+
blocks.push({ type: 'code', code: codeLines.join('\n'), lang: '' });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const level = headingLevel(line);
|
|
166
|
+
if (level > 0) {
|
|
167
|
+
blocks.push({ type: 'heading', level, text: line.slice(level).trim() });
|
|
168
|
+
i++;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (isHr(line)) {
|
|
172
|
+
blocks.push({ type: 'hr' });
|
|
173
|
+
i++;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (trimmed[0] === '>') {
|
|
177
|
+
const quoteLines = [];
|
|
178
|
+
while (i < lines.length) {
|
|
179
|
+
const l = lines[i];
|
|
180
|
+
const t = l.trim();
|
|
181
|
+
if (isBlank(l))
|
|
182
|
+
break;
|
|
183
|
+
if (t[0] !== '>')
|
|
184
|
+
break;
|
|
185
|
+
let rest = t.length > 1 ? t.slice(1) : '';
|
|
186
|
+
if (rest[0] === ' ')
|
|
187
|
+
rest = rest.slice(1);
|
|
188
|
+
quoteLines.push(rest);
|
|
189
|
+
i++;
|
|
190
|
+
}
|
|
191
|
+
blocks.push({ type: 'blockquote', blocks: parseBlocks(quoteLines) });
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const marker = parseListMarker(line);
|
|
195
|
+
if (marker) {
|
|
196
|
+
const list = {
|
|
197
|
+
type: 'list',
|
|
198
|
+
ordered: marker.ordered,
|
|
199
|
+
items: [],
|
|
200
|
+
};
|
|
201
|
+
while (i < lines.length) {
|
|
202
|
+
const l = lines[i];
|
|
203
|
+
const m = parseListMarker(l);
|
|
204
|
+
if (!m)
|
|
205
|
+
break;
|
|
206
|
+
if (m.ordered !== list.ordered)
|
|
207
|
+
break;
|
|
208
|
+
const contentIndent = m.contentStart;
|
|
209
|
+
const itemLines = [l.slice(m.contentStart)];
|
|
210
|
+
i++;
|
|
211
|
+
while (i < lines.length) {
|
|
212
|
+
const c = lines[i];
|
|
213
|
+
if (isBlank(c)) {
|
|
214
|
+
i++;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const cm = parseListMarker(c);
|
|
218
|
+
const cIndent = leadingSpaces(c);
|
|
219
|
+
if (cm && cIndent < contentIndent && cm.ordered === m.ordered)
|
|
220
|
+
break;
|
|
221
|
+
if (cIndent >= contentIndent) {
|
|
222
|
+
itemLines.push(c.slice(Math.min(c.length, contentIndent)));
|
|
223
|
+
i++;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
list.items.push({ blocks: parseBlocks(itemLines) });
|
|
229
|
+
}
|
|
230
|
+
blocks.push(list);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
const paraLines = [trimmed];
|
|
234
|
+
i++;
|
|
235
|
+
while (i < lines.length) {
|
|
236
|
+
const l = lines[i];
|
|
237
|
+
if (isBlank(l))
|
|
238
|
+
break;
|
|
239
|
+
const t = l.trim();
|
|
240
|
+
if (headingLevel(l) > 0)
|
|
241
|
+
break;
|
|
242
|
+
if (isHr(l))
|
|
243
|
+
break;
|
|
244
|
+
if (fenceInfo(t))
|
|
245
|
+
break;
|
|
246
|
+
if (t[0] === '>')
|
|
247
|
+
break;
|
|
248
|
+
if (parseListMarker(l))
|
|
249
|
+
break;
|
|
250
|
+
if (leadingSpaces(l) >= 4)
|
|
251
|
+
break;
|
|
252
|
+
paraLines.push(t);
|
|
253
|
+
i++;
|
|
254
|
+
}
|
|
255
|
+
blocks.push({ type: 'paragraph', text: paraLines.join(' ') });
|
|
256
|
+
}
|
|
257
|
+
return blocks;
|
|
258
|
+
}
|
|
259
|
+
function renderListItem(item) {
|
|
260
|
+
const blocks = item.blocks;
|
|
261
|
+
if (blocks.length === 1 && blocks[0].type === 'paragraph') {
|
|
262
|
+
return `<li>${renderInline(blocks[0].text)}</li>`;
|
|
263
|
+
}
|
|
264
|
+
const parts = [];
|
|
265
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
266
|
+
const b = blocks[i];
|
|
267
|
+
if (i === 0 && b.type === 'paragraph') {
|
|
268
|
+
parts.push(renderInline(b.text));
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
parts.push(renderBlock(b));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return `<li>${parts.join('\n')}</li>`;
|
|
275
|
+
}
|
|
276
|
+
function renderBlock(b) {
|
|
277
|
+
if (b.type === 'paragraph') {
|
|
278
|
+
return `<p>${renderInline(b.text)}</p>`;
|
|
279
|
+
}
|
|
280
|
+
if (b.type === 'heading') {
|
|
281
|
+
return `<h${b.level}>${renderInline(b.text)}</h${b.level}>`;
|
|
282
|
+
}
|
|
283
|
+
if (b.type === 'hr') {
|
|
284
|
+
return '<hr />';
|
|
285
|
+
}
|
|
286
|
+
if (b.type === 'code') {
|
|
287
|
+
const lang = b.lang ? ` class="language-${escapeHtml(b.lang)}"` : '';
|
|
288
|
+
return `<pre><code${lang}>${escapeHtml(b.code)}</code></pre>`;
|
|
289
|
+
}
|
|
290
|
+
if (b.type === 'blockquote') {
|
|
291
|
+
return `<blockquote>${renderBlocks(b.blocks)}</blockquote>`;
|
|
292
|
+
}
|
|
293
|
+
return renderList(b);
|
|
294
|
+
}
|
|
295
|
+
function renderList(b) {
|
|
296
|
+
const tag = b.ordered ? 'ol' : 'ul';
|
|
297
|
+
const items = b.items.map(renderListItem).join('\n');
|
|
298
|
+
return `<${tag}>\n${items}\n</${tag}>`;
|
|
299
|
+
}
|
|
300
|
+
function renderBlocks(blocks) {
|
|
301
|
+
const out = [];
|
|
302
|
+
for (const b of blocks) {
|
|
303
|
+
out.push(renderBlock(b));
|
|
304
|
+
}
|
|
305
|
+
return out.join('\n');
|
|
306
|
+
}
|
|
307
|
+
function parseLink(text, start) {
|
|
308
|
+
let i = start;
|
|
309
|
+
let isImage = false;
|
|
310
|
+
if (text[i] === '!' && text[i + 1] === '[') {
|
|
311
|
+
isImage = true;
|
|
312
|
+
i++;
|
|
313
|
+
}
|
|
314
|
+
if (text[i] !== '[')
|
|
315
|
+
return null;
|
|
316
|
+
i++;
|
|
317
|
+
let depth = 1;
|
|
318
|
+
let labelEnd = -1;
|
|
319
|
+
let j = i;
|
|
320
|
+
while (j < text.length) {
|
|
321
|
+
if (text[j] === '[')
|
|
322
|
+
depth++;
|
|
323
|
+
else if (text[j] === ']') {
|
|
324
|
+
depth--;
|
|
325
|
+
if (depth === 0) {
|
|
326
|
+
labelEnd = j;
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
j++;
|
|
331
|
+
}
|
|
332
|
+
if (labelEnd === -1)
|
|
333
|
+
return null;
|
|
334
|
+
const label = text.slice(i, labelEnd);
|
|
335
|
+
j = labelEnd + 1;
|
|
336
|
+
if (text[j] !== '(')
|
|
337
|
+
return null;
|
|
338
|
+
j++;
|
|
339
|
+
while (j < text.length && text[j] === ' ')
|
|
340
|
+
j++;
|
|
341
|
+
const urlStart = j;
|
|
342
|
+
depth = 1;
|
|
343
|
+
let urlEnd = -1;
|
|
344
|
+
while (j < text.length) {
|
|
345
|
+
if (text[j] === '(')
|
|
346
|
+
depth++;
|
|
347
|
+
else if (text[j] === ')') {
|
|
348
|
+
depth--;
|
|
349
|
+
if (depth === 0) {
|
|
350
|
+
urlEnd = j;
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
j++;
|
|
355
|
+
}
|
|
356
|
+
if (urlEnd === -1)
|
|
357
|
+
return null;
|
|
358
|
+
const url = text.slice(urlStart, urlEnd).trim();
|
|
359
|
+
if (url === '')
|
|
360
|
+
return null;
|
|
361
|
+
return { text: label, url, alt: label, image: isImage, end: urlEnd + 1 };
|
|
362
|
+
}
|
|
363
|
+
function findDelimiter(text, from, delim) {
|
|
364
|
+
return text.indexOf(delim, from);
|
|
365
|
+
}
|
|
366
|
+
function renderInline(text) {
|
|
367
|
+
let out = '';
|
|
368
|
+
let i = 0;
|
|
369
|
+
while (i < text.length) {
|
|
370
|
+
const ch = text[i];
|
|
371
|
+
if (ch === '\\' && i + 1 < text.length) {
|
|
372
|
+
out += escapeHtml(text[i + 1]);
|
|
373
|
+
i += 2;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (ch === '`') {
|
|
377
|
+
let n = 0;
|
|
378
|
+
while (i + n < text.length && text[i + n] === '`')
|
|
379
|
+
n++;
|
|
380
|
+
const delim = '`'.repeat(n);
|
|
381
|
+
const close = findDelimiter(text, i + n, delim);
|
|
382
|
+
if (close !== -1) {
|
|
383
|
+
let code = text.slice(i + n, close);
|
|
384
|
+
code = code.split('\n').join(' ');
|
|
385
|
+
out += `<code>${escapeHtml(code)}</code>`;
|
|
386
|
+
i = close + n;
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
out += '`';
|
|
390
|
+
i++;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
if (ch === '~' && text[i + 1] === '~') {
|
|
394
|
+
const close = findDelimiter(text, i + 2, '~~');
|
|
395
|
+
if (close !== -1 && close > i + 2) {
|
|
396
|
+
out += `<del>${renderInline(text.slice(i + 2, close))}</del>`;
|
|
397
|
+
i = close + 2;
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
out += '~';
|
|
401
|
+
i++;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (ch === '*' || ch === '_') {
|
|
405
|
+
const next = text[i + 1];
|
|
406
|
+
if (next !== ' ' && next !== '\t' && next !== undefined) {
|
|
407
|
+
const inner = tryEmphasis(text, i);
|
|
408
|
+
if (inner) {
|
|
409
|
+
out += inner.html;
|
|
410
|
+
i = inner.end;
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
out += ch;
|
|
415
|
+
i++;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (ch === '[' || (ch === '!' && text[i + 1] === '[')) {
|
|
419
|
+
const link = parseLink(text, i);
|
|
420
|
+
if (link) {
|
|
421
|
+
if (link.image) {
|
|
422
|
+
out += `<img src="${escapeHtml(link.url)}" alt="${escapeHtml(link.alt)}" />`;
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
out += `<a href="${escapeHtml(link.url)}">${renderInline(link.text)}</a>`;
|
|
426
|
+
}
|
|
427
|
+
i = link.end;
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
out += escapeHtml(ch);
|
|
432
|
+
i++;
|
|
433
|
+
}
|
|
434
|
+
return out;
|
|
435
|
+
}
|
|
436
|
+
function tryEmphasis(text, start) {
|
|
437
|
+
const ch = text[start];
|
|
438
|
+
if (text[start + 1] === ch) {
|
|
439
|
+
let j = start + 2;
|
|
440
|
+
while (j < text.length) {
|
|
441
|
+
if (text[j] === ch && text[j + 1] === ch) {
|
|
442
|
+
if (j > start + 2 && (text[j - 1] === ' ' || text[j - 1] === '\t')) {
|
|
443
|
+
j += 2;
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
return { html: `<strong>${renderInline(text.slice(start + 2, j))}</strong>`, end: j + 2 };
|
|
447
|
+
}
|
|
448
|
+
j++;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
let j = start + 1;
|
|
452
|
+
while (j < text.length) {
|
|
453
|
+
if (text[j] === ch) {
|
|
454
|
+
if (j > start + 1 && (text[j - 1] === ' ' || text[j - 1] === '\t')) {
|
|
455
|
+
j++;
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
return { html: `<em>${renderInline(text.slice(start + 1, j))}</em>`, end: j + 1 };
|
|
459
|
+
}
|
|
460
|
+
j++;
|
|
461
|
+
}
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
export function renderMarkdown(md) {
|
|
465
|
+
const lines = String(md == null ? '' : md).split('\n');
|
|
466
|
+
return renderBlocks(parseBlocks(lines));
|
|
467
|
+
}
|
|
468
|
+
function mdIsSSR() {
|
|
469
|
+
return typeof document === 'undefined';
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Renders markdown as HTML. On the server it returns an HTML string; on the
|
|
473
|
+
* client it claims the SSR-rendered subtree during hydration (or builds a
|
|
474
|
+
* fresh wrapper element for SPA navigation).
|
|
475
|
+
*/
|
|
476
|
+
export function Md(props, _registry, hydrate) {
|
|
477
|
+
const content = props.content == null ? '' : String(props.content);
|
|
478
|
+
const html = renderMarkdown(content);
|
|
479
|
+
const className = props.className != null ? String(props.className) : props.class != null ? String(props.class) : '';
|
|
480
|
+
const style = props.style != null ? String(props.style) : '';
|
|
481
|
+
if (mdIsSSR()) {
|
|
482
|
+
const attrs = className ? ` class="${escapeHtml(className)}"` : '';
|
|
483
|
+
const styleAttr = style ? ` style="${style.split('"').join('"')}"` : '';
|
|
484
|
+
return `<div${attrs}${styleAttr}>${html}</div>`;
|
|
485
|
+
}
|
|
486
|
+
if (hydrate && typeof hydrate.nextElement === 'function') {
|
|
487
|
+
let el = hydrate.nextElement('div');
|
|
488
|
+
if (el && !el.parentNode && hydrate.root) {
|
|
489
|
+
const existing = hydrate.root.querySelector('div');
|
|
490
|
+
if (existing)
|
|
491
|
+
el = existing;
|
|
492
|
+
}
|
|
493
|
+
el.innerHTML = html;
|
|
494
|
+
if (className)
|
|
495
|
+
el.className = className;
|
|
496
|
+
if (style)
|
|
497
|
+
el.style.cssText = style;
|
|
498
|
+
return document.createDocumentFragment();
|
|
499
|
+
}
|
|
500
|
+
const div = document.createElement('div');
|
|
501
|
+
div.innerHTML = html;
|
|
502
|
+
if (className)
|
|
503
|
+
div.className = className;
|
|
504
|
+
if (style)
|
|
505
|
+
div.style.cssText = style;
|
|
506
|
+
return div;
|
|
507
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vesk/runtime",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./index-client.js",
|
|
6
|
+
"types": "./index-client.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./index-client.d.ts",
|
|
10
|
+
"default": "./index-client.js"
|
|
11
|
+
},
|
|
12
|
+
"./client": {
|
|
13
|
+
"types": "./index-client.d.ts",
|
|
14
|
+
"default": "./index-client.js"
|
|
15
|
+
},
|
|
16
|
+
"./server": {
|
|
17
|
+
"types": "./index-server.d.ts",
|
|
18
|
+
"default": "./index-server.js"
|
|
19
|
+
},
|
|
20
|
+
"./src/*": "./*.js",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/dist/portal.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface PortalProps {
|
|
2
|
+
target: string | HTMLElement;
|
|
3
|
+
children?: Node | ((frag: DocumentFragment) => void);
|
|
4
|
+
[k: string]: unknown;
|
|
5
|
+
}
|
|
6
|
+
export declare function Portal(props: PortalProps, _registry?: Map<string, unknown>, _ctx?: unknown): Node | string;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=portal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../src/portal.ts"],"names":[],"mappings":"AAAA,UAAU,WAAW;IACpB,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACrB;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,MAAM,CAgB1G"}
|
package/dist/portal.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function Portal(props, _registry, _ctx) {
|
|
2
|
+
if (typeof document === 'undefined')
|
|
3
|
+
return '';
|
|
4
|
+
const target = typeof props.target === 'string'
|
|
5
|
+
? document.querySelector(props.target)
|
|
6
|
+
: props.target;
|
|
7
|
+
if (!target)
|
|
8
|
+
return document.createComment('portal: no target');
|
|
9
|
+
if (props.children != null) {
|
|
10
|
+
if (typeof props.children === 'function') {
|
|
11
|
+
const frag = document.createDocumentFragment();
|
|
12
|
+
props.children(frag);
|
|
13
|
+
target.appendChild(frag);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
target.appendChild(props.children);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return document.createComment('portal');
|
|
20
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Block } from '@vesk/runtime/src/ripple-runtime';
|
|
2
|
+
export declare function reconcile<T>(anchor: Node, endAnchor: Node, items: T[], keyFn: (item: T) => string, createItem: (item: T, index: number, effs: Block[]) => void): (newItems: T[]) => void;
|
|
3
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AAO9D,wBAAgB,SAAS,CAAC,CAAC,EAC1B,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAC1B,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,GACzD,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,IAAI,CA8CzB"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { destroy_block } from '@vesk/runtime/src/ripple-blocks';
|
|
2
|
+
export function reconcile(anchor, endAnchor, items, keyFn, createItem) {
|
|
3
|
+
const parent = anchor.parentNode;
|
|
4
|
+
const map = new Map();
|
|
5
|
+
for (let i = 0; i < items.length; i++) {
|
|
6
|
+
const item = items[i];
|
|
7
|
+
const key = keyFn(item);
|
|
8
|
+
const marker = document.createComment('k:' + key);
|
|
9
|
+
const effs = [];
|
|
10
|
+
parent.insertBefore(marker, endAnchor);
|
|
11
|
+
createItem(item, i, effs);
|
|
12
|
+
map.set(key, { marker, effs });
|
|
13
|
+
}
|
|
14
|
+
return (newItems) => {
|
|
15
|
+
const newKeys = newItems.map(keyFn);
|
|
16
|
+
const newSet = new Set(newKeys);
|
|
17
|
+
for (const [key, { marker, effs }] of map) {
|
|
18
|
+
if (!newSet.has(key)) {
|
|
19
|
+
removeRange(marker, endAnchor);
|
|
20
|
+
marker.remove();
|
|
21
|
+
for (const e of effs)
|
|
22
|
+
destroy_block(e);
|
|
23
|
+
map.delete(key);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
let ref = endAnchor;
|
|
27
|
+
for (let i = newKeys.length - 1; i >= 0; i--) {
|
|
28
|
+
const key = newKeys[i];
|
|
29
|
+
let entry = map.get(key);
|
|
30
|
+
if (entry) {
|
|
31
|
+
if (entry.marker.nextSibling !== ref) {
|
|
32
|
+
moveBefore(entry.marker, endAnchor, ref);
|
|
33
|
+
}
|
|
34
|
+
ref = entry.marker;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const marker = document.createComment('k:' + key);
|
|
38
|
+
const effs = [];
|
|
39
|
+
parent.insertBefore(marker, ref);
|
|
40
|
+
createItem(newItems[i], i, effs);
|
|
41
|
+
map.set(key, { marker, effs });
|
|
42
|
+
ref = marker;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function removeRange(start, end) {
|
|
48
|
+
let n = start.nextSibling;
|
|
49
|
+
while (n && n !== end && !(n.nodeType === 8 && n.nodeValue && n.nodeValue.startsWith('k:'))) {
|
|
50
|
+
const next = n.nextSibling;
|
|
51
|
+
n.remove();
|
|
52
|
+
n = next;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function moveBefore(marker, endAnchor, ref) {
|
|
56
|
+
const nodes = [];
|
|
57
|
+
let n = marker.nextSibling;
|
|
58
|
+
while (n && n !== endAnchor && !(n.nodeType === 8 && n.nodeValue && n.nodeValue.startsWith('k:'))) {
|
|
59
|
+
nodes.push(n);
|
|
60
|
+
n = n.nextSibling;
|
|
61
|
+
}
|
|
62
|
+
const parent = marker.parentNode;
|
|
63
|
+
parent.insertBefore(marker, ref);
|
|
64
|
+
for (const node of nodes)
|
|
65
|
+
parent.insertBefore(node, ref);
|
|
66
|
+
}
|