@tanstack/markdown 0.0.13 → 0.0.14
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.js +25 -32
- package/dist/inline.d.ts.map +1 -1
- package/dist/inline.js +104 -211
- package/dist/octane.d.ts.map +1 -1
- package/dist/octane.js +20 -21
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +51 -72
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +20 -21
- package/dist/utils.d.ts +6 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +33 -23
- package/package.json +6 -1
- package/skills/custom-extensions/SKILL.md +1 -1
- package/skills/docs-features/SKILL.md +1 -1
- package/skills/octane-rendering/SKILL.md +1 -1
- package/skills/production-pipelines/SKILL.md +2 -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 +1 -1
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,44 @@ 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) {
|
|
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;
|
|
81
73
|
const href = sanitizeUrl(parsed.href);
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
if (image || (!nested && (href || !parsed.href))) {
|
|
75
|
+
pushText();
|
|
84
76
|
nodes.push({
|
|
85
|
-
type: 'link',
|
|
86
|
-
href,
|
|
77
|
+
...(image ? { type: 'image', src: href, alt: plainText(children) } : { type: 'link', href, children }),
|
|
87
78
|
...(parsed.title ? { title: parsed.title } : {}),
|
|
88
|
-
children: parseInlineRaw(parsed.label, options, budget),
|
|
89
79
|
});
|
|
90
80
|
}
|
|
91
81
|
else {
|
|
92
|
-
|
|
82
|
+
if (nested)
|
|
83
|
+
text += '[';
|
|
84
|
+
for (const child of children) {
|
|
85
|
+
if (child.type === 'text')
|
|
86
|
+
text += child.value;
|
|
87
|
+
else {
|
|
88
|
+
pushText();
|
|
89
|
+
nodes.push(child);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
93
92
|
}
|
|
94
|
-
|
|
93
|
+
// An inner link disables its outer opener, but not the trailing markup.
|
|
94
|
+
budget.links = image ? links : budget.links + 1;
|
|
95
|
+
index = nested ? index + parsed.label.length + 1 : parsed.end;
|
|
95
96
|
continue;
|
|
96
97
|
}
|
|
97
98
|
}
|
|
@@ -107,65 +108,28 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
|
|
|
107
108
|
continue;
|
|
108
109
|
}
|
|
109
110
|
}
|
|
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
111
|
if (char === '~' && next === '~' && value[index + 2] === '~') {
|
|
126
112
|
const run = countRun(value, index, '~');
|
|
127
113
|
text += value.slice(index, index + run);
|
|
128
114
|
index += run;
|
|
129
115
|
continue;
|
|
130
116
|
}
|
|
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);
|
|
117
|
+
if (char === '*' || char === '_' || char === '~') {
|
|
118
|
+
const size = next === char ? 2 : 1;
|
|
119
|
+
const close = char === '_' && !canUseUnderscore(value, index, size, true) ? -1 : findDelimiter(value, index + size, char.repeat(size), budget);
|
|
148
120
|
if (close !== -1) {
|
|
149
121
|
pushText();
|
|
150
122
|
nodes.push({
|
|
151
|
-
type: 'strike',
|
|
152
|
-
children: parseInlineRaw(value.slice(index +
|
|
123
|
+
type: char === '~' ? 'strike' : size === 2 ? 'strong' : 'emphasis',
|
|
124
|
+
children: parseInlineRaw(value.slice(index + size, close), options, budget),
|
|
153
125
|
});
|
|
154
|
-
index = close +
|
|
155
|
-
continue;
|
|
126
|
+
index = close + size;
|
|
156
127
|
}
|
|
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;
|
|
128
|
+
else {
|
|
129
|
+
text += char.repeat(size);
|
|
130
|
+
index += size;
|
|
168
131
|
}
|
|
132
|
+
continue;
|
|
169
133
|
}
|
|
170
134
|
if (char === '<' && options.allowHtml) {
|
|
171
135
|
const close = findCharacter(value, index + 1, '>', budget);
|
|
@@ -176,16 +140,17 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
|
|
|
176
140
|
continue;
|
|
177
141
|
}
|
|
178
142
|
}
|
|
179
|
-
|
|
180
|
-
index
|
|
143
|
+
// Reset after recursive parsing; exhausted budgets still allow escapes.
|
|
144
|
+
inlineMarker.lastIndex = index + 1;
|
|
145
|
+
const end = budget.scans > 0 ? inlineMarker.exec(value)?.index ?? value.length : value.indexOf('\\', index + 1);
|
|
146
|
+
text += value.slice(index, end < 0 ? value.length : end);
|
|
147
|
+
index = end < 0 ? value.length : end;
|
|
181
148
|
}
|
|
182
149
|
pushText();
|
|
183
150
|
budget.depth--;
|
|
184
151
|
return nodes;
|
|
185
152
|
}
|
|
186
153
|
function parseFootnoteReference(value, open, options, budget) {
|
|
187
|
-
if (value[open + 1] !== '^')
|
|
188
|
-
return undefined;
|
|
189
154
|
const close = findCharacter(value, open + 2, ']', budget);
|
|
190
155
|
if (close === -1)
|
|
191
156
|
return undefined;
|
|
@@ -194,19 +159,17 @@ function parseFootnoteReference(value, open, options, budget) {
|
|
|
194
159
|
const definition = options.footnotes?.[key];
|
|
195
160
|
if (!definition || !options.footnoteOrder)
|
|
196
161
|
return undefined;
|
|
197
|
-
let
|
|
198
|
-
if (
|
|
199
|
-
options.footnoteOrder.push(key);
|
|
200
|
-
orderIndex = options.footnoteOrder.length - 1;
|
|
201
|
-
}
|
|
162
|
+
let number = options.footnoteOrder.indexOf(key) + 1;
|
|
163
|
+
if (!number)
|
|
164
|
+
number = options.footnoteOrder.push(key);
|
|
202
165
|
const referenceIndex = (options.footnoteCounts?.[key] ?? 0) + 1;
|
|
203
166
|
if (options.footnoteCounts)
|
|
204
167
|
options.footnoteCounts[key] = referenceIndex;
|
|
205
168
|
return {
|
|
206
169
|
node: {
|
|
207
170
|
type: 'footnoteReference',
|
|
208
|
-
id: definition.id ??
|
|
209
|
-
number
|
|
171
|
+
id: definition.id ?? footnoteId(definition.label),
|
|
172
|
+
number,
|
|
210
173
|
...(referenceIndex > 1 ? { referenceIndex } : {}),
|
|
211
174
|
},
|
|
212
175
|
end: close + 1,
|
|
@@ -217,72 +180,49 @@ function parseLinkish(value, open, options, budget) {
|
|
|
217
180
|
if (closeBracket === -1)
|
|
218
181
|
return undefined;
|
|
219
182
|
const label = value.slice(open + 1, closeBracket);
|
|
220
|
-
|
|
221
|
-
|
|
183
|
+
let end = closeBracket + 1;
|
|
184
|
+
let definition;
|
|
185
|
+
if (value[end] === '(') {
|
|
186
|
+
const closeParen = findBalanced(value, end, '(', ')', budget);
|
|
222
187
|
if (closeParen === -1)
|
|
223
188
|
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
|
-
};
|
|
189
|
+
definition = parseDestination(value.slice(end + 1, closeParen).trim());
|
|
190
|
+
end = closeParen + 1;
|
|
234
191
|
}
|
|
235
|
-
if (value[
|
|
236
|
-
const closeReference = findBalanced(value,
|
|
192
|
+
else if (value[end] === '[') {
|
|
193
|
+
const closeReference = findBalanced(value, end, '[', ']', budget);
|
|
237
194
|
if (closeReference === -1)
|
|
238
195
|
return undefined;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
label,
|
|
245
|
-
href: definition.href,
|
|
246
|
-
...(definition.title ? { title: definition.title } : {}),
|
|
247
|
-
end: closeReference + 1,
|
|
248
|
-
};
|
|
196
|
+
definition = options.references?.[normalizeReferenceLabel(value.slice(end + 1, closeReference) || label)];
|
|
197
|
+
end = closeReference + 1;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
definition = options.references?.[normalizeReferenceLabel(label)];
|
|
249
201
|
}
|
|
250
|
-
const definition = options.references?.[normalizeReferenceLabel(label)];
|
|
251
202
|
if (definition) {
|
|
252
203
|
return {
|
|
204
|
+
...definition,
|
|
253
205
|
label,
|
|
254
|
-
|
|
255
|
-
...(definition.title ? { title: definition.title } : {}),
|
|
256
|
-
end: closeBracket + 1,
|
|
206
|
+
end,
|
|
257
207
|
};
|
|
258
208
|
}
|
|
259
209
|
return undefined;
|
|
260
210
|
}
|
|
261
211
|
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
|
-
};
|
|
212
|
+
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
213
|
}
|
|
279
214
|
function findBalanced(value, openIndex, open, close, budget) {
|
|
215
|
+
// Reject missing closers with a native search, charging the same shared budget.
|
|
216
|
+
if (findCharacter(value, openIndex + 1, close, budget) === -1)
|
|
217
|
+
return -1;
|
|
280
218
|
let depth = 0;
|
|
281
219
|
for (let index = openIndex; index < value.length; index++) {
|
|
282
|
-
if (
|
|
220
|
+
if (--budget.scans < 0)
|
|
283
221
|
return -1;
|
|
284
|
-
if (value[index
|
|
222
|
+
if (value[index] === '\\') {
|
|
223
|
+
index++;
|
|
285
224
|
continue;
|
|
225
|
+
}
|
|
286
226
|
if (value[index] === open)
|
|
287
227
|
depth++;
|
|
288
228
|
if (value[index] === close) {
|
|
@@ -296,110 +236,63 @@ function findBalanced(value, openIndex, open, close, budget) {
|
|
|
296
236
|
function countRun(value, index, char, budget) {
|
|
297
237
|
let count = 0;
|
|
298
238
|
while (value[index + count] === char) {
|
|
299
|
-
if (budget &&
|
|
239
|
+
if (budget && --budget.scans < 0)
|
|
300
240
|
break;
|
|
301
241
|
count++;
|
|
302
242
|
}
|
|
303
243
|
return count;
|
|
304
244
|
}
|
|
305
245
|
function findClosingRun(value, start, char, count, budget) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (
|
|
310
|
-
continue;
|
|
311
|
-
if (countRun(value, index, char, budget) >= count)
|
|
246
|
+
let index = start;
|
|
247
|
+
while ((index = findCharacter(value, index, char, budget)) !== -1) {
|
|
248
|
+
const size = countRun(value, index, char, budget);
|
|
249
|
+
if (size === count)
|
|
312
250
|
return index;
|
|
251
|
+
index += size;
|
|
313
252
|
}
|
|
314
253
|
return -1;
|
|
315
254
|
}
|
|
316
255
|
function findDelimiter(value, start, delimiter, budget) {
|
|
256
|
+
if (delimiter === '~' && /[\s\d]/.test(value[start] ?? ''))
|
|
257
|
+
return -1;
|
|
317
258
|
for (let index = start; index < value.length; index++) {
|
|
318
|
-
if (
|
|
259
|
+
if (--budget.scans < 0)
|
|
319
260
|
return -1;
|
|
320
|
-
if (value[index
|
|
261
|
+
if (value[index] === '\\') {
|
|
262
|
+
index++;
|
|
321
263
|
continue;
|
|
264
|
+
}
|
|
322
265
|
if (!value.startsWith(delimiter, index))
|
|
323
266
|
continue;
|
|
324
|
-
if (
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
267
|
+
if (delimiter[0] === '~') {
|
|
268
|
+
if (value[index - 1] === '~' || value[index + delimiter.length] === '~')
|
|
269
|
+
continue;
|
|
270
|
+
if (delimiter === '~' && /\s/.test(value[index - 1] ?? ''))
|
|
271
|
+
return -1;
|
|
272
|
+
}
|
|
273
|
+
else if (value[index + 1] === delimiter) {
|
|
274
|
+
const size = countRun(value, index, delimiter, budget);
|
|
275
|
+
const close = findDelimiter(value, index + size, delimiter.repeat(size), budget);
|
|
276
|
+
if (close > index + size) {
|
|
277
|
+
index = close + size - 1;
|
|
328
278
|
continue;
|
|
329
279
|
}
|
|
330
280
|
}
|
|
331
|
-
if (delimiter === '~~' && (value[index - 1] === '~' || value[index + 2] === '~'))
|
|
332
|
-
continue;
|
|
333
281
|
if (delimiter[0] === '_' && !canUseUnderscore(value, index, delimiter.length, false))
|
|
334
282
|
continue;
|
|
335
283
|
return index;
|
|
336
284
|
}
|
|
337
285
|
return -1;
|
|
338
286
|
}
|
|
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
287
|
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
288
|
if (budget.scans <= 0)
|
|
370
|
-
return
|
|
371
|
-
|
|
372
|
-
|
|
289
|
+
return -1;
|
|
290
|
+
const index = value.indexOf(character, start);
|
|
291
|
+
budget.scans -= (index < 0 ? value.length : index + 1) - start;
|
|
292
|
+
return budget.scans < 0 ? -1 : index;
|
|
373
293
|
}
|
|
374
294
|
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;
|
|
295
|
+
const inside = value[opening ? index + size : index - 1];
|
|
296
|
+
const outside = value[opening ? index - 1 : index + size];
|
|
297
|
+
return inside !== undefined && !/\s/.test(inside) && (outside === undefined || /[^\p{L}\p{N}]/u.test(outside));
|
|
405
298
|
}
|
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,EAAmC,UAAU,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAErI,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,CAwClH"}
|
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}`,
|
|
@@ -99,8 +100,7 @@ function renderCodeBlockOctane(node, options, key) {
|
|
|
99
100
|
return h(options, 'figure', { key, className: 'tm-code-frame', 'data-lang': lang }, h(options, 'figcaption', null, node.title), pre);
|
|
100
101
|
}
|
|
101
102
|
function renderListItemChildrenOctane(children, checked, loose, options, key) {
|
|
102
|
-
|
|
103
|
-
const task = checked === undefined
|
|
103
|
+
let result = checked === undefined
|
|
104
104
|
? []
|
|
105
105
|
: [
|
|
106
106
|
h(options, 'input', {
|
|
@@ -112,17 +112,18 @@ function renderListItemChildrenOctane(children, checked, loose, options, key) {
|
|
|
112
112
|
}),
|
|
113
113
|
' ',
|
|
114
114
|
];
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
115
|
+
for (let index = 0; index < children.length; index++) {
|
|
116
|
+
const child = children[index];
|
|
117
|
+
if (child.type === 'paragraph' && (!loose || index === 0)) {
|
|
118
|
+
for (const inline of renderInlines(child.children, options))
|
|
119
|
+
result.push(inline);
|
|
120
|
+
if (loose)
|
|
121
|
+
result = [h(options, 'p', { key: `${key}:paragraph` }, result)];
|
|
122
|
+
}
|
|
123
|
+
else
|
|
124
|
+
result.push(renderBlockOctane(child, options, `${key}:${index}`));
|
|
121
125
|
}
|
|
122
|
-
return
|
|
123
|
-
}
|
|
124
|
-
function renderListChildOctane(child, loose, options, key) {
|
|
125
|
-
return !loose && child.type === 'paragraph' ? renderInlines(child.children, options) : [renderBlockOctane(child, options, key)];
|
|
126
|
+
return result;
|
|
126
127
|
}
|
|
127
128
|
function renderTableCellOctane(tag, cell, align, options, key) {
|
|
128
129
|
return h(options, tag, { key, ...(align ? { style: { textAlign: align } } : {}) }, renderInlines(cell.children, options));
|
|
@@ -133,19 +134,20 @@ function renderFootnotesOctane(items, options, key) {
|
|
|
133
134
|
function renderFootnoteItemOctane(item, options) {
|
|
134
135
|
const lastIndex = item.children.length - 1;
|
|
135
136
|
const backrefs = renderFootnoteBackrefsOctane(item, options);
|
|
136
|
-
|
|
137
|
-
return [h(options, 'p', { key: 'backref-wrapper' }, backrefs.slice(1))];
|
|
138
|
-
return item.children.map((child, index) => {
|
|
137
|
+
const result = item.children.map((child, index) => {
|
|
139
138
|
if (index === lastIndex && child.type === 'paragraph') {
|
|
140
139
|
return h(options, 'p', { key: index }, renderInlines(child.children, options), backrefs);
|
|
141
140
|
}
|
|
142
141
|
return renderBlockOctane(child, options, `${index}`);
|
|
143
142
|
});
|
|
143
|
+
if (item.children[lastIndex]?.type !== 'paragraph')
|
|
144
|
+
result.push(h(options, 'p', { key: 'backref-wrapper' }, backrefs.slice(1)));
|
|
145
|
+
return result;
|
|
144
146
|
}
|
|
145
147
|
function renderFootnoteBackrefsOctane(item, options) {
|
|
146
148
|
const result = [];
|
|
147
149
|
for (let index = 1; index <= (item.referenceCount ?? 1); index++) {
|
|
148
|
-
const referenceId =
|
|
150
|
+
const referenceId = footnoteReferenceId(item.id, index);
|
|
149
151
|
const label = index === 1 ? `${item.number}` : `${item.number}-${index}`;
|
|
150
152
|
result.push(' ', h(options, 'a', {
|
|
151
153
|
key: index,
|
|
@@ -157,9 +159,6 @@ function renderFootnoteBackrefsOctane(item, options) {
|
|
|
157
159
|
}
|
|
158
160
|
return result;
|
|
159
161
|
}
|
|
160
|
-
function footnoteReferenceId(node) {
|
|
161
|
-
return node.referenceIndex && node.referenceIndex > 1 ? `${node.id}-${node.referenceIndex}` : node.id;
|
|
162
|
-
}
|
|
163
162
|
function h(options, tag, props, ...children) {
|
|
164
163
|
const component = typeof tag === 'string' ? options.components?.[tag] ?? tag : tag;
|
|
165
164
|
return createElement(component, props ?? undefined, ...children);
|
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"}
|