@tanstack/markdown 0.0.13 → 0.0.15
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 +22 -2
- package/dist/extensions/callouts.d.ts.map +1 -1
- package/dist/extensions/callouts.js +0 -5
- package/dist/extensions/comment-components.d.ts.map +1 -1
- package/dist/extensions/comment-components.js +16 -34
- package/dist/extensions/headings.js +8 -7
- package/dist/extensions/shared.d.ts.map +1 -1
- package/dist/extensions/shared.js +2 -9
- package/dist/extensions/tabs.d.ts.map +1 -1
- package/dist/extensions/tabs.js +11 -18
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +33 -34
- package/dist/inline.d.ts.map +1 -1
- package/dist/inline.js +106 -212
- package/dist/octane.d.ts.map +1 -1
- package/dist/octane.js +28 -23
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +166 -194
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +45 -37
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +6 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +37 -25
- package/package.json +11 -1
- package/skills/custom-extensions/SKILL.md +11 -4
- package/skills/docs-features/SKILL.md +1 -1
- package/skills/docs-features/references/docs-metadata.md +1 -1
- package/skills/octane-rendering/SKILL.md +1 -1
- package/skills/production-pipelines/SKILL.md +10 -2
- package/skills/react-rendering/SKILL.md +1 -1
- package/skills/render-markdown/SKILL.md +1 -1
- package/skills/render-markdown/references/ast-and-options.md +8 -3
package/dist/inline.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { footnoteId, normalizeReferenceLabel, sanitizeUrl } from './utils.js';
|
|
1
|
+
import { footnoteId, normalizeReferenceLabel, parseDestination, plainText, sanitizeUrl } from './utils.js';
|
|
2
2
|
export function parseInline(value, options = {}) {
|
|
3
|
-
|
|
4
|
-
let result = mergeText(nodes);
|
|
3
|
+
let result = parseInlineRaw(value, options);
|
|
5
4
|
for (const extension of options.extensions ?? []) {
|
|
6
5
|
result = extension.transformInline?.(result, { options }) ?? result;
|
|
7
6
|
}
|
|
@@ -9,7 +8,8 @@ export function parseInline(value, options = {}) {
|
|
|
9
8
|
}
|
|
10
9
|
const maxInlineDepth = 32;
|
|
11
10
|
const scansPerCharacter = 16;
|
|
12
|
-
|
|
11
|
+
const inlineMarker = /[\\`!\[_*~<]/g;
|
|
12
|
+
function parseInlineRaw(value, options, budget = { scans: Math.max(value.length * scansPerCharacter, 1024), depth: 0, links: 0 }) {
|
|
13
13
|
if (budget.depth >= maxInlineDepth)
|
|
14
14
|
return value ? [{ type: 'text', value }] : [];
|
|
15
15
|
budget.depth++;
|
|
@@ -32,7 +32,7 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
|
|
|
32
32
|
index += 2;
|
|
33
33
|
continue;
|
|
34
34
|
}
|
|
35
|
-
if (next && /[
|
|
35
|
+
if (next && /[!-/:-@\[-`{-~]/.test(next)) {
|
|
36
36
|
text += next;
|
|
37
37
|
index += 2;
|
|
38
38
|
continue;
|
|
@@ -45,7 +45,8 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
|
|
|
45
45
|
pushText();
|
|
46
46
|
nodes.push({
|
|
47
47
|
type: 'inlineCode',
|
|
48
|
-
|
|
48
|
+
// Strip one padding space at each end, except in an all-space span.
|
|
49
|
+
value: value.slice(index + tickCount, close).replace(/\n/g, ' ').replace(/^ (?! *$)(.*) $/s, '$1'),
|
|
49
50
|
});
|
|
50
51
|
index = close + tickCount;
|
|
51
52
|
continue;
|
|
@@ -54,44 +55,45 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
|
|
|
54
55
|
index += tickCount;
|
|
55
56
|
continue;
|
|
56
57
|
}
|
|
57
|
-
if (char === '!' && next === '[') {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
pushText();
|
|
61
|
-
nodes.push({
|
|
62
|
-
type: 'image',
|
|
63
|
-
src: sanitizeUrl(parsed.href),
|
|
64
|
-
alt: textFromMarkdown(parsed.label, budget),
|
|
65
|
-
...(parsed.title ? { title: parsed.title } : {}),
|
|
66
|
-
});
|
|
67
|
-
index = parsed.end;
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (char === '[') {
|
|
72
|
-
const footnote = parseFootnoteReference(value, index, options, budget);
|
|
58
|
+
if (char === '[' || (char === '!' && next === '[')) {
|
|
59
|
+
const image = char === '!';
|
|
60
|
+
const footnote = next === '^' && parseFootnoteReference(value, index, options, budget);
|
|
73
61
|
if (footnote) {
|
|
74
62
|
pushText();
|
|
75
63
|
nodes.push(footnote.node);
|
|
64
|
+
budget.links++;
|
|
76
65
|
index = footnote.end;
|
|
77
66
|
continue;
|
|
78
67
|
}
|
|
79
|
-
const parsed = parseLinkish(value, index, options, budget);
|
|
68
|
+
const parsed = parseLinkish(value, index + Number(image), options, budget);
|
|
80
69
|
if (parsed) {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
70
|
+
const links = budget.links;
|
|
71
|
+
const children = parseInlineRaw(parsed.label, image ? (options.references ? { references: options.references } : {}) : options, budget);
|
|
72
|
+
const nested = !image && budget.links !== links;
|
|
73
|
+
const defaultUrl = sanitizeUrl(parsed.href);
|
|
74
|
+
const href = options.urlTransform ? options.urlTransform(parsed.href, image ? 'image' : 'link', defaultUrl) : defaultUrl;
|
|
75
|
+
if (href !== null && (image || (!nested && (href || !parsed.href)))) {
|
|
76
|
+
pushText();
|
|
84
77
|
nodes.push({
|
|
85
|
-
type: 'link',
|
|
86
|
-
href,
|
|
78
|
+
...(image ? { type: 'image', src: href, alt: plainText(children) } : { type: 'link', href, children }),
|
|
87
79
|
...(parsed.title ? { title: parsed.title } : {}),
|
|
88
|
-
children: parseInlineRaw(parsed.label, options, budget),
|
|
89
80
|
});
|
|
90
81
|
}
|
|
91
82
|
else {
|
|
92
|
-
|
|
83
|
+
if (nested)
|
|
84
|
+
text += '[';
|
|
85
|
+
for (const child of children) {
|
|
86
|
+
if (child.type === 'text')
|
|
87
|
+
text += child.value;
|
|
88
|
+
else {
|
|
89
|
+
pushText();
|
|
90
|
+
nodes.push(child);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
// An inner link disables its outer opener, but not the trailing markup.
|
|
95
|
+
budget.links = image ? links : budget.links + 1;
|
|
96
|
+
index = nested ? index + parsed.label.length + 1 : parsed.end;
|
|
95
97
|
continue;
|
|
96
98
|
}
|
|
97
99
|
}
|
|
@@ -107,65 +109,28 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
|
|
|
107
109
|
continue;
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
|
-
if ((char === '*' && next === '*') || (char === '_' && next === '_')) {
|
|
111
|
-
const close = char === '_' && !canUseUnderscore(value, index, 2, true) ? -1 : findDelimiter(value, index + 2, char + char, budget);
|
|
112
|
-
if (close !== -1) {
|
|
113
|
-
pushText();
|
|
114
|
-
nodes.push({
|
|
115
|
-
type: 'strong',
|
|
116
|
-
children: parseInlineRaw(value.slice(index + 2, close), options, budget),
|
|
117
|
-
});
|
|
118
|
-
index = close + 2;
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
text += char + next;
|
|
122
|
-
index += 2;
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
112
|
if (char === '~' && next === '~' && value[index + 2] === '~') {
|
|
126
113
|
const run = countRun(value, index, '~');
|
|
127
114
|
text += value.slice(index, index + run);
|
|
128
115
|
index += run;
|
|
129
116
|
continue;
|
|
130
117
|
}
|
|
131
|
-
if (char === '
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
pushText();
|
|
135
|
-
nodes.push({
|
|
136
|
-
type: 'strike',
|
|
137
|
-
children: parseInlineRaw(value.slice(index + 2, close), options, budget),
|
|
138
|
-
});
|
|
139
|
-
index = close + 2;
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
text += '~~';
|
|
143
|
-
index += 2;
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
if (char === '~') {
|
|
147
|
-
const close = findSingleTildeDelimiter(value, index + 1, budget);
|
|
118
|
+
if (char === '*' || char === '_' || char === '~') {
|
|
119
|
+
const size = next === char ? 2 : 1;
|
|
120
|
+
const close = char === '_' && !canUseUnderscore(value, index, size, true) ? -1 : findDelimiter(value, index + size, char.repeat(size), budget);
|
|
148
121
|
if (close !== -1) {
|
|
149
122
|
pushText();
|
|
150
123
|
nodes.push({
|
|
151
|
-
type: 'strike',
|
|
152
|
-
children: parseInlineRaw(value.slice(index +
|
|
124
|
+
type: char === '~' ? 'strike' : size === 2 ? 'strong' : 'emphasis',
|
|
125
|
+
children: parseInlineRaw(value.slice(index + size, close), options, budget),
|
|
153
126
|
});
|
|
154
|
-
index = close +
|
|
155
|
-
continue;
|
|
127
|
+
index = close + size;
|
|
156
128
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (close !== -1) {
|
|
161
|
-
pushText();
|
|
162
|
-
nodes.push({
|
|
163
|
-
type: 'emphasis',
|
|
164
|
-
children: parseInlineRaw(value.slice(index + 1, close), options, budget),
|
|
165
|
-
});
|
|
166
|
-
index = close + 1;
|
|
167
|
-
continue;
|
|
129
|
+
else {
|
|
130
|
+
text += char.repeat(size);
|
|
131
|
+
index += size;
|
|
168
132
|
}
|
|
133
|
+
continue;
|
|
169
134
|
}
|
|
170
135
|
if (char === '<' && options.allowHtml) {
|
|
171
136
|
const close = findCharacter(value, index + 1, '>', budget);
|
|
@@ -176,16 +141,17 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
|
|
|
176
141
|
continue;
|
|
177
142
|
}
|
|
178
143
|
}
|
|
179
|
-
|
|
180
|
-
index
|
|
144
|
+
// Reset after recursive parsing; exhausted budgets still allow escapes.
|
|
145
|
+
inlineMarker.lastIndex = index + 1;
|
|
146
|
+
const end = budget.scans > 0 ? inlineMarker.exec(value)?.index ?? value.length : value.indexOf('\\', index + 1);
|
|
147
|
+
text += value.slice(index, end < 0 ? value.length : end);
|
|
148
|
+
index = end < 0 ? value.length : end;
|
|
181
149
|
}
|
|
182
150
|
pushText();
|
|
183
151
|
budget.depth--;
|
|
184
152
|
return nodes;
|
|
185
153
|
}
|
|
186
154
|
function parseFootnoteReference(value, open, options, budget) {
|
|
187
|
-
if (value[open + 1] !== '^')
|
|
188
|
-
return undefined;
|
|
189
155
|
const close = findCharacter(value, open + 2, ']', budget);
|
|
190
156
|
if (close === -1)
|
|
191
157
|
return undefined;
|
|
@@ -194,19 +160,17 @@ function parseFootnoteReference(value, open, options, budget) {
|
|
|
194
160
|
const definition = options.footnotes?.[key];
|
|
195
161
|
if (!definition || !options.footnoteOrder)
|
|
196
162
|
return undefined;
|
|
197
|
-
let
|
|
198
|
-
if (
|
|
199
|
-
options.footnoteOrder.push(key);
|
|
200
|
-
orderIndex = options.footnoteOrder.length - 1;
|
|
201
|
-
}
|
|
163
|
+
let number = options.footnoteOrder.indexOf(key) + 1;
|
|
164
|
+
if (!number)
|
|
165
|
+
number = options.footnoteOrder.push(key);
|
|
202
166
|
const referenceIndex = (options.footnoteCounts?.[key] ?? 0) + 1;
|
|
203
167
|
if (options.footnoteCounts)
|
|
204
168
|
options.footnoteCounts[key] = referenceIndex;
|
|
205
169
|
return {
|
|
206
170
|
node: {
|
|
207
171
|
type: 'footnoteReference',
|
|
208
|
-
id: definition.id ??
|
|
209
|
-
number
|
|
172
|
+
id: definition.id ?? footnoteId(definition.label),
|
|
173
|
+
number,
|
|
210
174
|
...(referenceIndex > 1 ? { referenceIndex } : {}),
|
|
211
175
|
},
|
|
212
176
|
end: close + 1,
|
|
@@ -217,72 +181,49 @@ function parseLinkish(value, open, options, budget) {
|
|
|
217
181
|
if (closeBracket === -1)
|
|
218
182
|
return undefined;
|
|
219
183
|
const label = value.slice(open + 1, closeBracket);
|
|
220
|
-
|
|
221
|
-
|
|
184
|
+
let end = closeBracket + 1;
|
|
185
|
+
let definition;
|
|
186
|
+
if (value[end] === '(') {
|
|
187
|
+
const closeParen = findBalanced(value, end, '(', ')', budget);
|
|
222
188
|
if (closeParen === -1)
|
|
223
189
|
return undefined;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (!parsed)
|
|
227
|
-
return undefined;
|
|
228
|
-
return {
|
|
229
|
-
label,
|
|
230
|
-
href: parsed.href,
|
|
231
|
-
...(parsed.title ? { title: parsed.title } : {}),
|
|
232
|
-
end: closeParen + 1,
|
|
233
|
-
};
|
|
190
|
+
definition = parseDestination(value.slice(end + 1, closeParen).trim());
|
|
191
|
+
end = closeParen + 1;
|
|
234
192
|
}
|
|
235
|
-
if (value[
|
|
236
|
-
const closeReference = findBalanced(value,
|
|
193
|
+
else if (value[end] === '[') {
|
|
194
|
+
const closeReference = findBalanced(value, end, '[', ']', budget);
|
|
237
195
|
if (closeReference === -1)
|
|
238
196
|
return undefined;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
label,
|
|
245
|
-
href: definition.href,
|
|
246
|
-
...(definition.title ? { title: definition.title } : {}),
|
|
247
|
-
end: closeReference + 1,
|
|
248
|
-
};
|
|
197
|
+
definition = options.references?.[normalizeReferenceLabel(value.slice(end + 1, closeReference) || label)];
|
|
198
|
+
end = closeReference + 1;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
definition = options.references?.[normalizeReferenceLabel(label)];
|
|
249
202
|
}
|
|
250
|
-
const definition = options.references?.[normalizeReferenceLabel(label)];
|
|
251
203
|
if (definition) {
|
|
252
204
|
return {
|
|
205
|
+
...definition,
|
|
253
206
|
label,
|
|
254
|
-
|
|
255
|
-
...(definition.title ? { title: definition.title } : {}),
|
|
256
|
-
end: closeBracket + 1,
|
|
207
|
+
end,
|
|
257
208
|
};
|
|
258
209
|
}
|
|
259
210
|
return undefined;
|
|
260
211
|
}
|
|
261
212
|
function isInlineHtml(value) {
|
|
262
|
-
|
|
263
|
-
return true;
|
|
264
|
-
if (/^<\?[\s\S]*\?>$/.test(value) || /^<![A-Z][\s\S]*>$/.test(value) || /^<!\[CDATA\[[\s\S]*\]\]>$/.test(value))
|
|
265
|
-
return true;
|
|
266
|
-
if (/^<\/[A-Za-z][\w:-]*\s*>$/.test(value))
|
|
267
|
-
return true;
|
|
268
|
-
return /^<[A-Za-z][\w:-]*(?:\s+[A-Za-z_:][\w:.-]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?)*\s*\/?>$/.test(value);
|
|
269
|
-
}
|
|
270
|
-
function parseDestination(value) {
|
|
271
|
-
const match = value.match(/^(\S+)(?:\s+["']([^"']*)["'])?$/);
|
|
272
|
-
if (!match)
|
|
273
|
-
return { href: value };
|
|
274
|
-
return {
|
|
275
|
-
href: match[1].replace(/^<|>$/g, ''),
|
|
276
|
-
...(match[2] ? { title: match[2] } : {}),
|
|
277
|
-
};
|
|
213
|
+
return /^<(?:!--(?:[\s\S]*--|-?)|\?[\s\S]*\?|![A-Z][\s\S]*|!\[CDATA\[[\s\S]*\]\]|\/[A-Za-z][\w:-]*\s*|[A-Za-z][\w:-]*(?:\s+[A-Za-z_:][\w:.-]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?)*\s*\/?)>$/.test(value);
|
|
278
214
|
}
|
|
279
215
|
function findBalanced(value, openIndex, open, close, budget) {
|
|
216
|
+
// Reject missing closers with a native search, charging the same shared budget.
|
|
217
|
+
if (findCharacter(value, openIndex + 1, close, budget) === -1)
|
|
218
|
+
return -1;
|
|
280
219
|
let depth = 0;
|
|
281
220
|
for (let index = openIndex; index < value.length; index++) {
|
|
282
|
-
if (
|
|
221
|
+
if (--budget.scans < 0)
|
|
283
222
|
return -1;
|
|
284
|
-
if (value[index
|
|
223
|
+
if (value[index] === '\\') {
|
|
224
|
+
index++;
|
|
285
225
|
continue;
|
|
226
|
+
}
|
|
286
227
|
if (value[index] === open)
|
|
287
228
|
depth++;
|
|
288
229
|
if (value[index] === close) {
|
|
@@ -296,110 +237,63 @@ function findBalanced(value, openIndex, open, close, budget) {
|
|
|
296
237
|
function countRun(value, index, char, budget) {
|
|
297
238
|
let count = 0;
|
|
298
239
|
while (value[index + count] === char) {
|
|
299
|
-
if (budget &&
|
|
240
|
+
if (budget && --budget.scans < 0)
|
|
300
241
|
break;
|
|
301
242
|
count++;
|
|
302
243
|
}
|
|
303
244
|
return count;
|
|
304
245
|
}
|
|
305
246
|
function findClosingRun(value, start, char, count, budget) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (
|
|
310
|
-
continue;
|
|
311
|
-
if (countRun(value, index, char, budget) >= count)
|
|
247
|
+
let index = start;
|
|
248
|
+
while ((index = findCharacter(value, index, char, budget)) !== -1) {
|
|
249
|
+
const size = countRun(value, index, char, budget);
|
|
250
|
+
if (size === count)
|
|
312
251
|
return index;
|
|
252
|
+
index += size;
|
|
313
253
|
}
|
|
314
254
|
return -1;
|
|
315
255
|
}
|
|
316
256
|
function findDelimiter(value, start, delimiter, budget) {
|
|
257
|
+
if (delimiter === '~' && /[\s\d]/.test(value[start] ?? ''))
|
|
258
|
+
return -1;
|
|
317
259
|
for (let index = start; index < value.length; index++) {
|
|
318
|
-
if (
|
|
260
|
+
if (--budget.scans < 0)
|
|
319
261
|
return -1;
|
|
320
|
-
if (value[index
|
|
262
|
+
if (value[index] === '\\') {
|
|
263
|
+
index++;
|
|
321
264
|
continue;
|
|
265
|
+
}
|
|
322
266
|
if (!value.startsWith(delimiter, index))
|
|
323
267
|
continue;
|
|
324
|
-
if (
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
268
|
+
if (delimiter[0] === '~') {
|
|
269
|
+
if (value[index - 1] === '~' || value[index + delimiter.length] === '~')
|
|
270
|
+
continue;
|
|
271
|
+
if (delimiter === '~' && /\s/.test(value[index - 1] ?? ''))
|
|
272
|
+
return -1;
|
|
273
|
+
}
|
|
274
|
+
else if (value[index + 1] === delimiter) {
|
|
275
|
+
const size = countRun(value, index, delimiter, budget);
|
|
276
|
+
const close = findDelimiter(value, index + size, delimiter.repeat(size), budget);
|
|
277
|
+
if (close > index + size) {
|
|
278
|
+
index = close + size - 1;
|
|
328
279
|
continue;
|
|
329
280
|
}
|
|
330
281
|
}
|
|
331
|
-
if (delimiter === '~~' && (value[index - 1] === '~' || value[index + 2] === '~'))
|
|
332
|
-
continue;
|
|
333
282
|
if (delimiter[0] === '_' && !canUseUnderscore(value, index, delimiter.length, false))
|
|
334
283
|
continue;
|
|
335
284
|
return index;
|
|
336
285
|
}
|
|
337
286
|
return -1;
|
|
338
287
|
}
|
|
339
|
-
function findSingleTildeDelimiter(value, start, budget) {
|
|
340
|
-
if (isWhitespace(value[start] ?? '') || /\d/.test(value[start] ?? ''))
|
|
341
|
-
return -1;
|
|
342
|
-
for (let index = start; index < value.length; index++) {
|
|
343
|
-
if (!takeScan(budget))
|
|
344
|
-
return -1;
|
|
345
|
-
if (value[index - 1] === '\\')
|
|
346
|
-
continue;
|
|
347
|
-
if (value[index] !== '~')
|
|
348
|
-
continue;
|
|
349
|
-
if (value[index - 1] === '~')
|
|
350
|
-
continue;
|
|
351
|
-
if (value[index + 1] === '~')
|
|
352
|
-
continue;
|
|
353
|
-
if (isWhitespace(value[index - 1] ?? ''))
|
|
354
|
-
return -1;
|
|
355
|
-
return index;
|
|
356
|
-
}
|
|
357
|
-
return -1;
|
|
358
|
-
}
|
|
359
288
|
function findCharacter(value, start, character, budget) {
|
|
360
|
-
for (let index = start; index < value.length; index++) {
|
|
361
|
-
if (!takeScan(budget))
|
|
362
|
-
return -1;
|
|
363
|
-
if (value[index] === character)
|
|
364
|
-
return index;
|
|
365
|
-
}
|
|
366
|
-
return -1;
|
|
367
|
-
}
|
|
368
|
-
function takeScan(budget) {
|
|
369
289
|
if (budget.scans <= 0)
|
|
370
|
-
return
|
|
371
|
-
|
|
372
|
-
|
|
290
|
+
return -1;
|
|
291
|
+
const index = value.indexOf(character, start);
|
|
292
|
+
budget.scans -= (index < 0 ? value.length : index + 1) - start;
|
|
293
|
+
return budget.scans < 0 ? -1 : index;
|
|
373
294
|
}
|
|
374
295
|
function canUseUnderscore(value, index, size, opening) {
|
|
375
|
-
const
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
const rightFlanking = !isDelimiterWhitespace(before) && (!isPunctuation(before) || isDelimiterWhitespace(after) || isPunctuation(after));
|
|
379
|
-
return opening ? leftFlanking && (!rightFlanking || isPunctuation(before)) : rightFlanking && (!leftFlanking || isPunctuation(after));
|
|
380
|
-
}
|
|
381
|
-
function isDelimiterWhitespace(value) {
|
|
382
|
-
return value === undefined || /\s/.test(value);
|
|
383
|
-
}
|
|
384
|
-
function isPunctuation(value) {
|
|
385
|
-
return value !== undefined && /[^\p{L}\p{N}\s]/u.test(value);
|
|
386
|
-
}
|
|
387
|
-
function isWhitespace(value) {
|
|
388
|
-
return /\s/.test(value);
|
|
389
|
-
}
|
|
390
|
-
function textFromMarkdown(value, budget) {
|
|
391
|
-
return parseInlineRaw(value, {}, budget).map(node => (node.type === 'text' || node.type === 'inlineCode' ? node.value : '')).join('');
|
|
392
|
-
}
|
|
393
|
-
function mergeText(nodes) {
|
|
394
|
-
const result = [];
|
|
395
|
-
for (const node of nodes) {
|
|
396
|
-
const previous = result.at(-1);
|
|
397
|
-
if (previous?.type === 'text' && node.type === 'text') {
|
|
398
|
-
previous.value += node.value;
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
result.push(node);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return result;
|
|
296
|
+
const inside = value[opening ? index + size : index - 1];
|
|
297
|
+
const outside = value[opening ? index - 1 : index + size];
|
|
298
|
+
return inside !== undefined && !/\s/.test(inside) && (outside === undefined || /[^\p{L}\p{N}]/u.test(outside));
|
|
405
299
|
}
|
package/dist/octane.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"octane.d.ts","sourceRoot":"","sources":["../src/octane.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"octane.d.ts","sourceRoot":"","sources":["../src/octane.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAG1E,OAAO,KAAK,EAAE,SAAS,EAAwD,UAAU,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAE1J,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAExE,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,UAAU,CAAC,EAAE,YAAY,CAAA;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,qBAAqB;IAC1D,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,aAAa,GAAG,iBAAiB,CAEnF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,qBAA0B,GAAG,UAAU,EAAE,CAG5G;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,qBAA0B,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,iBAAiB,CA+DvH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,qBAA0B,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CA0ClH"}
|
package/dist/octane.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fragment, createElement } from 'octane';
|
|
2
2
|
import { parseMarkdown } from './parser.js';
|
|
3
|
+
import { footnoteReferenceId } from './utils.js';
|
|
3
4
|
export function Markdown({ children, ...options }) {
|
|
4
5
|
return createElement(Fragment, null, ...renderMarkdownOctane(children, options));
|
|
5
6
|
}
|
|
@@ -17,7 +18,7 @@ export function renderBlockOctane(node, options = {}, key) {
|
|
|
17
18
|
return renderCodeBlockOctane(node, options, key);
|
|
18
19
|
case 'list': {
|
|
19
20
|
const tag = node.ordered ? 'ol' : 'ul';
|
|
20
|
-
return h(options, tag, { key, ...(node.ordered && node.start && node.start !== 1 ? { start: node.start } : {}) }, node.items.map((item, index) => h(options, 'li', { key: index }, renderListItemChildrenOctane(item.children, item.checked, node.loose, options, `${index}`))));
|
|
21
|
+
return h(options, tag, { key, ...(node.ordered && node.start !== undefined && node.start !== 1 ? { start: node.start } : {}) }, node.items.map((item, index) => h(options, 'li', { key: index }, renderListItemChildrenOctane(item.children, item.checked, node.loose, options, `${index}`))));
|
|
21
22
|
}
|
|
22
23
|
case 'blockquote':
|
|
23
24
|
return h(options, 'blockquote', { key }, node.children.map((child, index) => renderBlockOctane(child, options, `${key}:${index}`)));
|
|
@@ -53,7 +54,7 @@ export function renderInlineOctane(node, options = {}, key) {
|
|
|
53
54
|
return h(options, 'del', { key }, renderInlines(node.children, options));
|
|
54
55
|
case 'footnoteReference':
|
|
55
56
|
return h(options, 'sup', { key }, h(options, 'a', {
|
|
56
|
-
id: `user-content-fnref-${footnoteReferenceId(node)}`,
|
|
57
|
+
id: `user-content-fnref-${footnoteReferenceId(node.id, node.referenceIndex)}`,
|
|
57
58
|
'data-footnote-ref': '',
|
|
58
59
|
'aria-describedby': 'footnote-label',
|
|
59
60
|
href: `#user-content-fn-${node.id}`,
|
|
@@ -68,6 +69,8 @@ export function renderInlineOctane(node, options = {}, key) {
|
|
|
68
69
|
return options.allowHtml
|
|
69
70
|
? h(options, 'span', { key, dangerouslySetInnerHTML: { __html: node.value } })
|
|
70
71
|
: node.value;
|
|
72
|
+
case 'inlineComponent':
|
|
73
|
+
return renderComponentOctane(node, options, key);
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
function renderInlines(nodes, options) {
|
|
@@ -81,6 +84,7 @@ function renderCodeBlockOctane(node, options, key) {
|
|
|
81
84
|
? {
|
|
82
85
|
dangerouslySetInnerHTML: {
|
|
83
86
|
__html: highlighter(node.value, lang, {
|
|
87
|
+
...(node.meta && { meta: node.meta }),
|
|
84
88
|
...(node.highlightLines && { highlightLines: node.highlightLines }),
|
|
85
89
|
...(options.codeLineNumbers !== undefined && { lineNumbers: options.codeLineNumbers }),
|
|
86
90
|
}),
|
|
@@ -90,6 +94,7 @@ function renderCodeBlockOctane(node, options, key) {
|
|
|
90
94
|
const pre = h(options, 'pre', {
|
|
91
95
|
className: `tm-code${options.codeLineNumbers ? ' tm-code--line-numbers' : ''}`,
|
|
92
96
|
'data-lang': lang,
|
|
97
|
+
...(node.meta ? { 'data-meta': node.meta } : {}),
|
|
93
98
|
...(node.title ? { 'data-code-title': node.title } : {}),
|
|
94
99
|
...(node.file ? { 'data-filename': node.file } : {}),
|
|
95
100
|
...(node.framework ? { 'data-framework': node.framework } : {}),
|
|
@@ -99,8 +104,7 @@ function renderCodeBlockOctane(node, options, key) {
|
|
|
99
104
|
return h(options, 'figure', { key, className: 'tm-code-frame', 'data-lang': lang }, h(options, 'figcaption', null, node.title), pre);
|
|
100
105
|
}
|
|
101
106
|
function renderListItemChildrenOctane(children, checked, loose, options, key) {
|
|
102
|
-
|
|
103
|
-
const task = checked === undefined
|
|
107
|
+
let result = checked === undefined
|
|
104
108
|
? []
|
|
105
109
|
: [
|
|
106
110
|
h(options, 'input', {
|
|
@@ -112,17 +116,18 @@ function renderListItemChildrenOctane(children, checked, loose, options, key) {
|
|
|
112
116
|
}),
|
|
113
117
|
' ',
|
|
114
118
|
];
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
for (let index = 0; index < children.length; index++) {
|
|
120
|
+
const child = children[index];
|
|
121
|
+
if (child.type === 'paragraph' && (!loose || index === 0)) {
|
|
122
|
+
for (const inline of renderInlines(child.children, options))
|
|
123
|
+
result.push(inline);
|
|
124
|
+
if (loose)
|
|
125
|
+
result = [h(options, 'p', { key: `${key}:paragraph` }, result)];
|
|
126
|
+
}
|
|
127
|
+
else
|
|
128
|
+
result.push(renderBlockOctane(child, options, `${key}:${index}`));
|
|
121
129
|
}
|
|
122
|
-
return
|
|
123
|
-
}
|
|
124
|
-
function renderListChildOctane(child, loose, options, key) {
|
|
125
|
-
return !loose && child.type === 'paragraph' ? renderInlines(child.children, options) : [renderBlockOctane(child, options, key)];
|
|
130
|
+
return result;
|
|
126
131
|
}
|
|
127
132
|
function renderTableCellOctane(tag, cell, align, options, key) {
|
|
128
133
|
return h(options, tag, { key, ...(align ? { style: { textAlign: align } } : {}) }, renderInlines(cell.children, options));
|
|
@@ -133,19 +138,20 @@ function renderFootnotesOctane(items, options, key) {
|
|
|
133
138
|
function renderFootnoteItemOctane(item, options) {
|
|
134
139
|
const lastIndex = item.children.length - 1;
|
|
135
140
|
const backrefs = renderFootnoteBackrefsOctane(item, options);
|
|
136
|
-
|
|
137
|
-
return [h(options, 'p', { key: 'backref-wrapper' }, backrefs.slice(1))];
|
|
138
|
-
return item.children.map((child, index) => {
|
|
141
|
+
const result = item.children.map((child, index) => {
|
|
139
142
|
if (index === lastIndex && child.type === 'paragraph') {
|
|
140
143
|
return h(options, 'p', { key: index }, renderInlines(child.children, options), backrefs);
|
|
141
144
|
}
|
|
142
145
|
return renderBlockOctane(child, options, `${index}`);
|
|
143
146
|
});
|
|
147
|
+
if (item.children[lastIndex]?.type !== 'paragraph')
|
|
148
|
+
result.push(h(options, 'p', { key: 'backref-wrapper' }, backrefs.slice(1)));
|
|
149
|
+
return result;
|
|
144
150
|
}
|
|
145
151
|
function renderFootnoteBackrefsOctane(item, options) {
|
|
146
152
|
const result = [];
|
|
147
153
|
for (let index = 1; index <= (item.referenceCount ?? 1); index++) {
|
|
148
|
-
const referenceId =
|
|
154
|
+
const referenceId = footnoteReferenceId(item.id, index);
|
|
149
155
|
const label = index === 1 ? `${item.number}` : `${item.number}-${index}`;
|
|
150
156
|
result.push(' ', h(options, 'a', {
|
|
151
157
|
key: index,
|
|
@@ -157,15 +163,12 @@ function renderFootnoteBackrefsOctane(item, options) {
|
|
|
157
163
|
}
|
|
158
164
|
return result;
|
|
159
165
|
}
|
|
160
|
-
function footnoteReferenceId(node) {
|
|
161
|
-
return node.referenceIndex && node.referenceIndex > 1 ? `${node.id}-${node.referenceIndex}` : node.id;
|
|
162
|
-
}
|
|
163
166
|
function h(options, tag, props, ...children) {
|
|
164
167
|
const component = typeof tag === 'string' ? options.components?.[tag] ?? tag : tag;
|
|
165
168
|
return createElement(component, props ?? undefined, ...children);
|
|
166
169
|
}
|
|
167
170
|
function renderComponentOctane(node, options, key) {
|
|
168
|
-
const tag = node.tagName ?? 'md-comment-component';
|
|
171
|
+
const tag = node.tagName ?? (node.type === 'inlineComponent' ? 'span' : 'md-comment-component');
|
|
169
172
|
const props = {
|
|
170
173
|
...(node.properties ?? {}),
|
|
171
174
|
};
|
|
@@ -174,7 +177,9 @@ function renderComponentOctane(node, options, key) {
|
|
|
174
177
|
if (!props['data-attributes'])
|
|
175
178
|
props['data-attributes'] = JSON.stringify(node.attributes);
|
|
176
179
|
}
|
|
177
|
-
return h(options, tag, { key, ...props }, node.
|
|
180
|
+
return h(options, tag, { key, ...props }, node.type === 'inlineComponent'
|
|
181
|
+
? renderInlines(node.children, options)
|
|
182
|
+
: node.children.map((child, index) => renderBlockOctane(child, options, `${key}:${index}`)));
|
|
178
183
|
}
|
|
179
184
|
function renderHeadingAnchorOctane(id, options) {
|
|
180
185
|
if (!id || !options.headingAnchors)
|
package/dist/parser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAQV,gBAAgB,EAChB,YAAY,EAGb,MAAM,YAAY,CAAA;AAWnB,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAQV,gBAAgB,EAChB,YAAY,EAGb,MAAM,YAAY,CAAA;AAWnB,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,gBAAgB,CA0C5F"}
|