@terra-symposium/docs 0.2.0 → 0.4.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/README.md +7 -1
- package/bin/terra-docs.mjs +78 -23
- package/dist/lib/components/LocalDocsWorkspace.d.ts +3 -0
- package/dist/lib/components/LocalDocsWorkspace.d.ts.map +1 -1
- package/dist/lib/components/LocalDocsWorkspace.js +23 -23
- package/dist/lib/components/LocalDocsWorkspace.js.map +1 -1
- package/dist/lib/components/SiteLayout.d.ts +3 -1
- package/dist/lib/components/SiteLayout.d.ts.map +1 -1
- package/dist/lib/components/SiteLayout.js +2 -2
- package/dist/lib/components/SiteLayout.js.map +1 -1
- package/dist/lib/components/StaticWorkspace.d.ts +4 -1
- package/dist/lib/components/StaticWorkspace.d.ts.map +1 -1
- package/dist/lib/components/StaticWorkspace.js +2 -2
- package/dist/lib/components/StaticWorkspace.js.map +1 -1
- package/dist/lib/components/StrictLocalWorkspaceHarness.d.ts +5 -0
- package/dist/lib/components/StrictLocalWorkspaceHarness.d.ts.map +1 -1
- package/dist/lib/components/StrictLocalWorkspaceHarness.js +14 -1
- package/dist/lib/components/StrictLocalWorkspaceHarness.js.map +1 -1
- package/dist/lib/components/blocks.d.ts +1 -1
- package/dist/lib/components/blocks.d.ts.map +1 -1
- package/dist/lib/components/blocks.js +59 -36
- package/dist/lib/components/blocks.js.map +1 -1
- package/dist/lib/components/navigation.js +1 -1
- package/dist/lib/components/navigation.js.map +1 -1
- package/dist/lib/components/quiz-demo-fixture.d.ts +23 -0
- package/dist/lib/components/quiz-demo-fixture.d.ts.map +1 -0
- package/dist/lib/components/quiz-demo-fixture.js +22 -0
- package/dist/lib/components/quiz-demo-fixture.js.map +1 -0
- package/dist/lib/components/quiz.d.ts +51 -0
- package/dist/lib/components/quiz.d.ts.map +1 -0
- package/dist/lib/components/quiz.js +183 -0
- package/dist/lib/components/quiz.js.map +1 -0
- package/dist/lib/components/terra/Workspace.d.ts.map +1 -1
- package/dist/lib/components/terra/Workspace.js +13 -12
- package/dist/lib/components/terra/Workspace.js.map +1 -1
- package/dist/lib/components/terra/editor/ContentEditor.d.ts.map +1 -1
- package/dist/lib/components/terra/editor/ContentEditor.js +35 -35
- package/dist/lib/components/terra/editor/ContentEditor.js.map +1 -1
- package/dist/lib/components/terra/editor/_blocks.js +6 -6
- package/dist/lib/components/terra/editor/_blocks.js.map +1 -1
- package/dist/lib/components/terra/editor/docs/BlockContext.js +12 -12
- package/dist/lib/components/terra/editor/docs/BlockContext.js.map +1 -1
- package/dist/lib/components/terra/editor/docs/DocsAttachmentPicker.js +6 -6
- package/dist/lib/components/terra/editor/docs/DocsAttachmentPicker.js.map +1 -1
- package/dist/lib/components/terra/editor/docs/TerraToolbar.d.ts.map +1 -1
- package/dist/lib/components/terra/editor/docs/TerraToolbar.js +2 -1
- package/dist/lib/components/terra/editor/docs/TerraToolbar.js.map +1 -1
- package/dist/lib/components/terra/editor/docs/_CodeBlock.js +10 -10
- package/dist/lib/components/terra/editor/docs/_CodeBlock.js.map +1 -1
- package/dist/lib/components/terra/editor/terra-content.styles.d.ts +1 -1
- package/dist/lib/components/terra/editor/terra-content.styles.d.ts.map +1 -1
- package/dist/lib/components/terra/editor/terra-content.styles.js +1 -1
- package/dist/lib/components/terra/editor/terra-content.styles.js.map +1 -1
- package/dist/lib/components/terra/flow/Nodes.js +7 -7
- package/dist/lib/components/terra/flow/Nodes.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_attachments.d.ts.map +1 -1
- package/dist/lib/components/terra/pages/docs/_attachments.js +11 -11
- package/dist/lib/components/terra/pages/docs/_attachments.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_blocks.js +2 -2
- package/dist/lib/components/terra/pages/docs/_blocks.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_editable.d.ts.map +1 -1
- package/dist/lib/components/terra/pages/docs/_editable.js +2 -2
- package/dist/lib/components/terra/pages/docs/_editable.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_icons.d.ts +1 -0
- package/dist/lib/components/terra/pages/docs/_icons.d.ts.map +1 -1
- package/dist/lib/components/terra/pages/docs/_icons.js +1 -0
- package/dist/lib/components/terra/pages/docs/_icons.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_main.d.ts.map +1 -1
- package/dist/lib/components/terra/pages/docs/_main.js +48 -16
- package/dist/lib/components/terra/pages/docs/_main.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_sidebar.js +2 -2
- package/dist/lib/components/terra/pages/docs/_sidebar.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_toc.js +1 -1
- package/dist/lib/components/terra/pages/docs/_toc.js.map +1 -1
- package/dist/lib/components/terra/pages/docs/_toolbar.d.ts.map +1 -1
- package/dist/lib/components/terra/pages/docs/_toolbar.js +12 -9
- package/dist/lib/components/terra/pages/docs/_toolbar.js.map +1 -1
- package/dist/lib/components/workspace-demo-fixture.d.ts.map +1 -1
- package/dist/lib/components/workspace-demo-fixture.js +51 -53
- package/dist/lib/components/workspace-demo-fixture.js.map +1 -1
- package/dist/lib/lib/host-runtime.js +3 -3
- package/dist/lib/lib/host-runtime.js.map +1 -1
- package/dist/lib/lib/host.d.ts +4 -1
- package/dist/lib/lib/host.d.ts.map +1 -1
- package/dist/lib/lib/index.d.ts +3 -0
- package/dist/lib/lib/index.d.ts.map +1 -1
- package/dist/lib/lib/index.js +2 -0
- package/dist/lib/lib/index.js.map +1 -1
- package/dist/lib/lib/markdown-model.d.ts.map +1 -1
- package/dist/lib/lib/markdown-model.js +106 -107
- package/dist/lib/lib/markdown-model.js.map +1 -1
- package/dist/lib/lib/markdown.js +4 -4
- package/dist/lib/lib/markdown.js.map +1 -1
- package/dist/lib/lib/schema.d.ts +2 -2
- package/dist/lib/lib/terra/custom-components.d.ts +1 -1
- package/dist/lib/lib/terra/custom-components.d.ts.map +1 -1
- package/dist/lib/lib/terra/custom-components.js +2 -2
- package/dist/lib/lib/terra/custom-components.js.map +1 -1
- package/dist/lib/lib/terra/docs/editor-dom.d.ts.map +1 -1
- package/dist/lib/lib/terra/docs/editor-dom.js +2 -2
- package/dist/lib/lib/terra/docs/editor-dom.js.map +1 -1
- package/dist/lib/lib/terra/docs/workspace.d.ts +14 -12
- package/dist/lib/lib/terra/docs/workspace.d.ts.map +1 -1
- package/dist/lib/lib/terra/docs/workspace.js +5 -5
- package/dist/lib/lib/terra/docs/workspace.js.map +1 -1
- package/dist/lib/lib/terra/runtime/action-proxy.d.ts +1 -1
- package/dist/lib/lib/terra/runtime/action-proxy.d.ts.map +1 -1
- package/dist/lib/lib/terra/runtime/action-proxy.js +2 -2
- package/dist/lib/lib/terra/runtime/action-proxy.js.map +1 -1
- package/dist/lib/lib/terra/runtime/content/markdown.d.ts +0 -7
- package/dist/lib/lib/terra/runtime/content/markdown.d.ts.map +1 -1
- package/dist/lib/lib/terra/runtime/content/markdown.js +0 -7
- package/dist/lib/lib/terra/runtime/content/markdown.js.map +1 -1
- package/dist/lib/lib/terra/runtime/nodes.js +3 -3
- package/dist/lib/lib/terra/runtime/nodes.js.map +1 -1
- package/dist/lib/lib/terra/runtime/runtime.d.ts +1 -2
- package/dist/lib/lib/terra/runtime/runtime.d.ts.map +1 -1
- package/dist/lib/lib/terra/runtime/runtime.js +3 -8
- package/dist/lib/lib/terra/runtime/runtime.js.map +1 -1
- package/dist/lib/lib/terra/runtime/shared.d.ts.map +1 -1
- package/dist/lib/lib/terra/runtime/shared.js +6 -6
- package/dist/lib/lib/terra/runtime/shared.js.map +1 -1
- package/dist/lib/lib/terra/runtime/types.d.ts +6 -0
- package/dist/lib/lib/terra/runtime/types.d.ts.map +1 -1
- package/dist/lib/lib/terra/runtime/types.js +1 -0
- package/dist/lib/lib/terra/runtime/types.js.map +1 -1
- package/dist/lib/style.css +2 -2
- package/package.json +8 -12
- package/site/astro.config.mjs +27 -22
- package/site/docs-content-plugin.mjs +4 -1
- package/site/src/components/DocsSiteSearch.tsx +51 -33
- package/site/src/components/QuizDemo.tsx +62 -0
- package/site/src/lib/catalog.ts +12 -4
- package/site/src/pages/[...slug].astro +3 -9
- package/site/src/pages/quiz-demo.astro +50 -0
- package/src/components/navigation.tsx +2 -2
- package/src/components/quiz-demo-fixture.ts +23 -0
- package/bin/generate-skills.mjs +0 -188
- package/site/src/components/SkillsExplorer.tsx +0 -236
|
@@ -25,7 +25,7 @@ function restoreInlineMathPlaceholders(value) {
|
|
|
25
25
|
return code === undefined ? placeholder : `$${code}$`;
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
|
-
function
|
|
28
|
+
function withGenInlineMathTokens(tokens) {
|
|
29
29
|
const result = [];
|
|
30
30
|
for (const token of tokens ?? []) {
|
|
31
31
|
if (!['text', 'escape'].includes(token.type)) {
|
|
@@ -131,10 +131,10 @@ function withInlineMathTokens(tokens, inlineMath) {
|
|
|
131
131
|
function inline(tokens, markDefs, inlineMath = true, inheritedMarks = []) {
|
|
132
132
|
if (!tokens)
|
|
133
133
|
return [];
|
|
134
|
-
let
|
|
134
|
+
let aMarks = [...inheritedMarks];
|
|
135
135
|
const result = [];
|
|
136
|
-
const addMark = (items, mark) => items.map((
|
|
137
|
-
for (const token of withInlineMathTokens(inlineMath ?
|
|
136
|
+
const addMark = (items, mark) => items.map((i) => (i._type === 'span' ? { ...i, marks: [...i.marks, mark] } : i));
|
|
137
|
+
for (const token of withInlineMathTokens(inlineMath ? withGenInlineMathTokens(tokens) : tokens, inlineMath)) {
|
|
138
138
|
if (token.type === 'docsMath') {
|
|
139
139
|
result.push({ _type: 'math', _key: key(), code: token.text ?? '', inline: true });
|
|
140
140
|
continue;
|
|
@@ -152,39 +152,39 @@ function inline(tokens, markDefs, inlineMath = true, inheritedMarks = []) {
|
|
|
152
152
|
? 'strong'
|
|
153
153
|
: 'strike-through';
|
|
154
154
|
if (tag[1])
|
|
155
|
-
|
|
155
|
+
aMarks = aMarks.filter((i) => i !== mark);
|
|
156
156
|
else
|
|
157
|
-
|
|
157
|
+
aMarks = [...aMarks, mark];
|
|
158
158
|
continue;
|
|
159
159
|
}
|
|
160
160
|
if (/^<br\s*\/?>$/i.test(token.raw)) {
|
|
161
|
-
result.push(span('\n',
|
|
161
|
+
result.push(span('\n', aMarks));
|
|
162
162
|
continue;
|
|
163
163
|
}
|
|
164
|
-
result.push(span(token.raw,
|
|
164
|
+
result.push(span(token.raw, aMarks));
|
|
165
165
|
continue;
|
|
166
166
|
}
|
|
167
167
|
if (token.type === 'strong') {
|
|
168
|
-
result.push(...addMark(inline(token.tokens, markDefs, inlineMath,
|
|
168
|
+
result.push(...addMark(inline(token.tokens, markDefs, inlineMath, aMarks), 'strong'));
|
|
169
169
|
continue;
|
|
170
170
|
}
|
|
171
171
|
if (token.type === 'em') {
|
|
172
|
-
result.push(...addMark(inline(token.tokens, markDefs, inlineMath,
|
|
172
|
+
result.push(...addMark(inline(token.tokens, markDefs, inlineMath, aMarks), 'em'));
|
|
173
173
|
continue;
|
|
174
174
|
}
|
|
175
175
|
if (token.type === 'del') {
|
|
176
|
-
result.push(...addMark(inline(token.tokens, markDefs, inlineMath,
|
|
176
|
+
result.push(...addMark(inline(token.tokens, markDefs, inlineMath, aMarks), 'strike-through'));
|
|
177
177
|
continue;
|
|
178
178
|
}
|
|
179
179
|
if (token.type === 'link') {
|
|
180
180
|
const href = typeof token.href === 'string' ? token.href : '';
|
|
181
181
|
if (!href || !/^(?:https?:\/\/|mailto:|tel:|\/|\.\.?\/|#)/i.test(href)) {
|
|
182
|
-
result.push(span(token.raw,
|
|
182
|
+
result.push(span(token.raw, aMarks));
|
|
183
183
|
continue;
|
|
184
184
|
}
|
|
185
185
|
const mark = key();
|
|
186
186
|
markDefs.push({ _type: 'link', _key: mark, href });
|
|
187
|
-
const linked = addMark(inline(token.tokens, markDefs, inlineMath,
|
|
187
|
+
const linked = addMark(inline(token.tokens, markDefs, inlineMath, aMarks), mark);
|
|
188
188
|
const joined = [];
|
|
189
189
|
for (const item of linked) {
|
|
190
190
|
const previous = joined.at(-1);
|
|
@@ -200,8 +200,8 @@ function inline(tokens, markDefs, inlineMath = true, inheritedMarks = []) {
|
|
|
200
200
|
}
|
|
201
201
|
if (token.type === 'text' || token.type === 'escape') {
|
|
202
202
|
const tokenText = token.text ?? token.raw;
|
|
203
|
-
if (
|
|
204
|
-
result.push(span(decodeHtml(tokenText),
|
|
203
|
+
if (aMarks.includes('code')) {
|
|
204
|
+
result.push(span(decodeHtml(tokenText), aMarks));
|
|
205
205
|
continue;
|
|
206
206
|
}
|
|
207
207
|
const pieces = tokenText.split(/(\$[^$\n]+\$)/g).filter(Boolean);
|
|
@@ -212,19 +212,19 @@ function inline(tokens, markDefs, inlineMath = true, inheritedMarks = []) {
|
|
|
212
212
|
code: piece.slice(1, -1),
|
|
213
213
|
inline: true,
|
|
214
214
|
}
|
|
215
|
-
: span(piece,
|
|
215
|
+
: span(piece, aMarks)));
|
|
216
216
|
continue;
|
|
217
217
|
}
|
|
218
218
|
if (token.type === 'codespan') {
|
|
219
|
-
result.push(span(token.text ?? token.raw, [...
|
|
219
|
+
result.push(span(token.text ?? token.raw, [...aMarks, 'code']));
|
|
220
220
|
continue;
|
|
221
221
|
}
|
|
222
222
|
if (token.type === 'br') {
|
|
223
|
-
result.push(span('\n',
|
|
223
|
+
result.push(span('\n', aMarks));
|
|
224
224
|
continue;
|
|
225
225
|
}
|
|
226
226
|
// Images in the middle of prose have no Portable Text inline equivalent. Keep their source.
|
|
227
|
-
result.push(span(token.raw,
|
|
227
|
+
result.push(span(token.raw, aMarks));
|
|
228
228
|
}
|
|
229
229
|
return result;
|
|
230
230
|
}
|
|
@@ -390,7 +390,7 @@ function structuredBlockRanges(source) {
|
|
|
390
390
|
.map((match) => ({ start: match.index ?? 0, end: (match.index ?? 0) + match[0].length }))
|
|
391
391
|
.sort((a, b) => a.start - b.start);
|
|
392
392
|
}
|
|
393
|
-
function
|
|
393
|
+
function readBracedExpr(source, start) {
|
|
394
394
|
if (source[start] !== '{')
|
|
395
395
|
return undefined;
|
|
396
396
|
let depth = 1;
|
|
@@ -422,7 +422,7 @@ function readBracedExpression(source, start) {
|
|
|
422
422
|
}
|
|
423
423
|
function readJsxTagEnd(source, start) {
|
|
424
424
|
let quote;
|
|
425
|
-
let
|
|
425
|
+
let exprDepth = 0;
|
|
426
426
|
for (let index = start + 1; index < source.length; index += 1) {
|
|
427
427
|
const char = source[index];
|
|
428
428
|
if (quote) {
|
|
@@ -439,10 +439,10 @@ function readJsxTagEnd(source, start) {
|
|
|
439
439
|
continue;
|
|
440
440
|
}
|
|
441
441
|
if (char === '{')
|
|
442
|
-
|
|
443
|
-
else if (char === '}' &&
|
|
444
|
-
|
|
445
|
-
else if (char === '>' &&
|
|
442
|
+
exprDepth += 1;
|
|
443
|
+
else if (char === '}' && exprDepth > 0)
|
|
444
|
+
exprDepth -= 1;
|
|
445
|
+
else if (char === '>' && exprDepth === 0)
|
|
446
446
|
return index + 1;
|
|
447
447
|
}
|
|
448
448
|
return undefined;
|
|
@@ -477,8 +477,8 @@ function parseJsxLiteral(source) {
|
|
|
477
477
|
return undefined;
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
|
-
function
|
|
481
|
-
const
|
|
480
|
+
function parseJsxAttrs(source) {
|
|
481
|
+
const attrs = {};
|
|
482
482
|
let index = 0;
|
|
483
483
|
while (index < source.length) {
|
|
484
484
|
while (/\s/.test(source[index] ?? ''))
|
|
@@ -492,7 +492,7 @@ function parseJsxAttributes(source) {
|
|
|
492
492
|
while (/\s/.test(source[index] ?? ''))
|
|
493
493
|
index += 1;
|
|
494
494
|
if (source[index] !== '=') {
|
|
495
|
-
|
|
495
|
+
attrs[name] = true;
|
|
496
496
|
continue;
|
|
497
497
|
}
|
|
498
498
|
index += 1;
|
|
@@ -513,15 +513,15 @@ function parseJsxAttributes(source) {
|
|
|
513
513
|
}
|
|
514
514
|
index += 1;
|
|
515
515
|
}
|
|
516
|
-
|
|
516
|
+
attrs[name] = parseJsxLiteral(source.slice(start, index));
|
|
517
517
|
continue;
|
|
518
518
|
}
|
|
519
519
|
if (source[index] === '{') {
|
|
520
|
-
const
|
|
521
|
-
if (!
|
|
520
|
+
const expr = readBracedExpr(source, index);
|
|
521
|
+
if (!expr)
|
|
522
522
|
break;
|
|
523
|
-
|
|
524
|
-
index =
|
|
523
|
+
attrs[name] = parseJsxLiteral(expr.value);
|
|
524
|
+
index = expr.end;
|
|
525
525
|
continue;
|
|
526
526
|
}
|
|
527
527
|
const bare = source.slice(index).match(/^[^\s/>]+/)?.[0];
|
|
@@ -529,10 +529,10 @@ function parseJsxAttributes(source) {
|
|
|
529
529
|
index += 1;
|
|
530
530
|
continue;
|
|
531
531
|
}
|
|
532
|
-
|
|
532
|
+
attrs[name] = parseJsxLiteral(bare);
|
|
533
533
|
index += bare.length;
|
|
534
534
|
}
|
|
535
|
-
return
|
|
535
|
+
return attrs;
|
|
536
536
|
}
|
|
537
537
|
function readJsxOpeningTag(source, start) {
|
|
538
538
|
if (source[start] !== '<')
|
|
@@ -548,18 +548,18 @@ function readJsxOpeningTag(source, start) {
|
|
|
548
548
|
const selfClosing = /\/\s*$/.test(shell);
|
|
549
549
|
return {
|
|
550
550
|
name,
|
|
551
|
-
attributes:
|
|
551
|
+
attributes: parseJsxAttrs(shell.replace(/\/\s*$/, '')),
|
|
552
552
|
end,
|
|
553
553
|
selfClosing,
|
|
554
554
|
};
|
|
555
555
|
}
|
|
556
|
-
function
|
|
556
|
+
function codeBodyExpr(source, start) {
|
|
557
557
|
const first = source.slice(start).match(/^\s*\{/);
|
|
558
558
|
if (!first)
|
|
559
559
|
return undefined;
|
|
560
|
-
const
|
|
561
|
-
const body = source.slice(
|
|
562
|
-
return body ?
|
|
560
|
+
const exprStart = start + first[0].length - 1;
|
|
561
|
+
const body = source.slice(exprStart + 1).match(/^\s*`/);
|
|
562
|
+
return body ? readBracedExpr(source, exprStart) : undefined;
|
|
563
563
|
}
|
|
564
564
|
function jsxComponentEnd(source, opening) {
|
|
565
565
|
return jsxComponentRange(source, opening)?.end ?? source.length;
|
|
@@ -567,20 +567,20 @@ function jsxComponentEnd(source, opening) {
|
|
|
567
567
|
function jsxComponentRange(source, opening) {
|
|
568
568
|
if (opening.selfClosing)
|
|
569
569
|
return { bodyEnd: opening.end, end: opening.end };
|
|
570
|
-
const
|
|
570
|
+
const expr = opening.name === 'Code' ? codeBodyExpr(source, opening.end) : undefined;
|
|
571
571
|
const closePattern = new RegExp(`<\\/${opening.name}\\s*>`, 'g');
|
|
572
|
-
closePattern.lastIndex =
|
|
572
|
+
closePattern.lastIndex = expr?.end ?? opening.end;
|
|
573
573
|
const close = closePattern.exec(source);
|
|
574
574
|
if (opening.name === 'Code') {
|
|
575
575
|
// Older exported leaves can omit an end tag before the next Code block. Treat that next
|
|
576
576
|
// opening tag as the boundary instead of swallowing every following code sample.
|
|
577
|
-
const
|
|
578
|
-
if (
|
|
579
|
-
return { bodyEnd:
|
|
577
|
+
const nOpening = source.indexOf('<Code', expr?.end ?? opening.end);
|
|
578
|
+
if (nOpening !== -1 && (!close || nOpening < close.index))
|
|
579
|
+
return { bodyEnd: nOpening, end: nOpening };
|
|
580
580
|
}
|
|
581
581
|
return close ? { bodyEnd: close.index, end: close.index + close[0].length } : undefined;
|
|
582
582
|
}
|
|
583
|
-
function
|
|
583
|
+
function parseArrayAttr(value) {
|
|
584
584
|
if (Array.isArray(value))
|
|
585
585
|
return value;
|
|
586
586
|
if (typeof value !== 'string')
|
|
@@ -593,51 +593,51 @@ function parseArrayAttribute(value) {
|
|
|
593
593
|
return undefined;
|
|
594
594
|
}
|
|
595
595
|
}
|
|
596
|
-
function componentBlock(name,
|
|
597
|
-
const
|
|
598
|
-
const bodyValue =
|
|
596
|
+
function componentBlock(name, attrs, body) {
|
|
597
|
+
const expr = codeBodyExpr(body, 0);
|
|
598
|
+
const bodyValue = expr ? parseJsxLiteral(expr.value) : decodeHtml(body.trim());
|
|
599
599
|
if (name === 'Nodes') {
|
|
600
|
-
const nodes =
|
|
601
|
-
const edges =
|
|
602
|
-
if (('nodes' in
|
|
600
|
+
const nodes = parseArrayAttr(attrs.nodes);
|
|
601
|
+
const edges = parseArrayAttr(attrs.edges);
|
|
602
|
+
if (('nodes' in attrs && !nodes) || ('edges' in attrs && !edges))
|
|
603
603
|
return undefined;
|
|
604
604
|
return {
|
|
605
605
|
_type: 'nodes',
|
|
606
606
|
_key: key(),
|
|
607
|
-
...
|
|
607
|
+
...attrs,
|
|
608
608
|
nodes: Array.isArray(nodes) ? nodes : [],
|
|
609
609
|
edges: Array.isArray(edges) ? edges : [],
|
|
610
610
|
};
|
|
611
611
|
}
|
|
612
612
|
if (name === 'Code') {
|
|
613
|
-
const
|
|
614
|
-
const source = typeof
|
|
615
|
-
const
|
|
613
|
+
const lang = typeof attrs.language === 'string' ? attrs.language : '';
|
|
614
|
+
const source = typeof attrs.source === 'string' ? attrs.source : undefined;
|
|
615
|
+
const codeAttr = typeof attrs.code === 'string' ? attrs.code : undefined;
|
|
616
616
|
const value = typeof bodyValue === 'string'
|
|
617
617
|
? bodyValue.replace(/^\r?\n/, '').replace(/\r?\n$/, '')
|
|
618
|
-
: (
|
|
618
|
+
: (codeAttr ?? '');
|
|
619
619
|
return {
|
|
620
620
|
_type: 'code',
|
|
621
621
|
_key: key(),
|
|
622
|
-
language,
|
|
622
|
+
language: lang,
|
|
623
623
|
...(source ? { source } : {}),
|
|
624
|
-
value: value ||
|
|
624
|
+
value: value || codeAttr || '',
|
|
625
625
|
};
|
|
626
626
|
}
|
|
627
627
|
if (name === 'Embed')
|
|
628
628
|
return {
|
|
629
629
|
_type: 'embed',
|
|
630
630
|
_key: key(),
|
|
631
|
-
...
|
|
632
|
-
src: typeof
|
|
633
|
-
title: typeof
|
|
631
|
+
...attrs,
|
|
632
|
+
src: typeof attrs.src === 'string' ? attrs.src : '',
|
|
633
|
+
title: typeof attrs.title === 'string' ? attrs.title : '',
|
|
634
634
|
};
|
|
635
635
|
if (name === 'TsDocs')
|
|
636
636
|
return {
|
|
637
637
|
_type: 'tsDocs',
|
|
638
638
|
_key: key(),
|
|
639
|
-
...
|
|
640
|
-
scope: typeof
|
|
639
|
+
...attrs,
|
|
640
|
+
scope: typeof attrs.scope === 'string' ? attrs.scope : '',
|
|
641
641
|
};
|
|
642
642
|
return undefined;
|
|
643
643
|
}
|
|
@@ -814,8 +814,8 @@ function decodeHtmlRepeated(value) {
|
|
|
814
814
|
}
|
|
815
815
|
return current;
|
|
816
816
|
}
|
|
817
|
-
function
|
|
818
|
-
const match =
|
|
817
|
+
function htmlAttr(attrs, name) {
|
|
818
|
+
const match = attrs.match(new RegExp(`\\b${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`, 'i'));
|
|
819
819
|
const value = match?.[1] ?? match?.[2] ?? match?.[3];
|
|
820
820
|
return value === undefined ? undefined : decodeHtml(value);
|
|
821
821
|
}
|
|
@@ -887,7 +887,7 @@ function htmlToMarkdown(source, inlineMath) {
|
|
|
887
887
|
}
|
|
888
888
|
const closing = /^<\//.test(raw);
|
|
889
889
|
const selfClosing = /\/\s*>$/.test(raw);
|
|
890
|
-
const
|
|
890
|
+
const attrs = match[2] ?? '';
|
|
891
891
|
output += escapeHtmlTableText(source.slice(copiedUntil, index), inlineMath);
|
|
892
892
|
copiedUntil = tagPattern.lastIndex;
|
|
893
893
|
if (closing) {
|
|
@@ -903,9 +903,9 @@ function htmlToMarkdown(source, inlineMath) {
|
|
|
903
903
|
continue;
|
|
904
904
|
}
|
|
905
905
|
if (name === 'img') {
|
|
906
|
-
const alt =
|
|
907
|
-
const src =
|
|
908
|
-
const title =
|
|
906
|
+
const alt = htmlAttr(attrs, 'alt') ?? 'image';
|
|
907
|
+
const src = htmlAttr(attrs, 'src') ?? '';
|
|
908
|
+
const title = htmlAttr(attrs, 'title');
|
|
909
909
|
const escapedTitle = title?.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
910
910
|
output += src
|
|
911
911
|
? `}${escapedTitle ? ` "${escapedTitle}"` : ''})`
|
|
@@ -929,7 +929,7 @@ function htmlToMarkdown(source, inlineMath) {
|
|
|
929
929
|
let open = '';
|
|
930
930
|
let close = '';
|
|
931
931
|
if (name === 'a') {
|
|
932
|
-
const href =
|
|
932
|
+
const href = htmlAttr(attrs, 'href');
|
|
933
933
|
if (href)
|
|
934
934
|
[open, close] = ['[', `](${markdownDestination(href)})`];
|
|
935
935
|
}
|
|
@@ -1018,14 +1018,14 @@ function tableBlock(rows, markdown, options, header = 'Table') {
|
|
|
1018
1018
|
})),
|
|
1019
1019
|
};
|
|
1020
1020
|
}
|
|
1021
|
-
function
|
|
1021
|
+
function markdownImgsAsBlocks(source, options, blocks) {
|
|
1022
1022
|
if (!enabled(options, 'docImage'))
|
|
1023
1023
|
return source;
|
|
1024
|
-
const
|
|
1024
|
+
const imgs = [];
|
|
1025
1025
|
const visit = (tokens, insideLink = false) => {
|
|
1026
1026
|
for (const token of tokens ?? []) {
|
|
1027
1027
|
if (token.type === 'image' && !insideLink)
|
|
1028
|
-
|
|
1028
|
+
imgs.push(token);
|
|
1029
1029
|
else if (token.tokens)
|
|
1030
1030
|
visit(token.tokens, insideLink || token.type === 'link');
|
|
1031
1031
|
}
|
|
@@ -1033,17 +1033,17 @@ function markdownImagesAsBlocks(source, options, blocks) {
|
|
|
1033
1033
|
visit(marked.lexer(source, { gfm: true }));
|
|
1034
1034
|
let result = source;
|
|
1035
1035
|
let cursor = 0;
|
|
1036
|
-
for (const
|
|
1037
|
-
const raw =
|
|
1036
|
+
for (const img of imgs) {
|
|
1037
|
+
const raw = img.raw;
|
|
1038
1038
|
const index = result.indexOf(raw, cursor);
|
|
1039
|
-
if (index < 0 || typeof
|
|
1039
|
+
if (index < 0 || typeof img.href !== 'string')
|
|
1040
1040
|
continue;
|
|
1041
1041
|
const block = {
|
|
1042
1042
|
_type: 'docImage',
|
|
1043
1043
|
_key: key(),
|
|
1044
|
-
alt:
|
|
1045
|
-
url:
|
|
1046
|
-
...(
|
|
1044
|
+
alt: img.text ?? '',
|
|
1045
|
+
url: img.href,
|
|
1046
|
+
...(img.title ? { title: img.title } : {}),
|
|
1047
1047
|
markdown: raw,
|
|
1048
1048
|
};
|
|
1049
1049
|
const placeholder = richPlaceholder(blocks, block);
|
|
@@ -1065,7 +1065,7 @@ function htmlTableBlock(source, options, blocks) {
|
|
|
1065
1065
|
const original = blocks[Number(indexText)];
|
|
1066
1066
|
return original ? richPlaceholder(cellBlocks, original) : placeholder;
|
|
1067
1067
|
});
|
|
1068
|
-
const cellMarkdown =
|
|
1068
|
+
const cellMarkdown = markdownImgsAsBlocks(cellMarkdownWithBlocks, options, cellBlocks);
|
|
1069
1069
|
return {
|
|
1070
1070
|
_type: 'cell',
|
|
1071
1071
|
_key: key(),
|
|
@@ -1143,11 +1143,11 @@ function parseGroupedItems(source, options, blocks) {
|
|
|
1143
1143
|
for (let index = 0; index < markers.length; index += 1) {
|
|
1144
1144
|
const marker = markers[index];
|
|
1145
1145
|
const bodyStart = (marker.index ?? 0) + marker[0].length;
|
|
1146
|
-
const
|
|
1146
|
+
const nStart = markers[index + 1]?.index ?? source.length;
|
|
1147
1147
|
const closing = /^:::terra-item-end[ \t]*\r?$/gm;
|
|
1148
1148
|
closing.lastIndex = bodyStart;
|
|
1149
1149
|
const end = closing.exec(source);
|
|
1150
|
-
if (!end || end.index >=
|
|
1150
|
+
if (!end || end.index >= nStart || source.slice(end.index + end[0].length, nStart).trim())
|
|
1151
1151
|
return undefined;
|
|
1152
1152
|
let title;
|
|
1153
1153
|
try {
|
|
@@ -1225,9 +1225,9 @@ function parseMarkdown(markdown, options, blocks) {
|
|
|
1225
1225
|
try {
|
|
1226
1226
|
const data = parseYaml(payload);
|
|
1227
1227
|
if (data && data._type === type) {
|
|
1228
|
-
const
|
|
1228
|
+
const norm = type === 'table' ? parseMarkdownTableCells(data, options, blocks) : data;
|
|
1229
1229
|
return enabled(options, type)
|
|
1230
|
-
? richPlaceholder(blocks,
|
|
1230
|
+
? richPlaceholder(blocks, norm)
|
|
1231
1231
|
: rawPlaceholder(blocks, source);
|
|
1232
1232
|
}
|
|
1233
1233
|
}
|
|
@@ -1304,16 +1304,16 @@ function parseMarkdown(markdown, options, blocks) {
|
|
|
1304
1304
|
continue;
|
|
1305
1305
|
}
|
|
1306
1306
|
if (token.type === 'paragraph') {
|
|
1307
|
-
const
|
|
1307
|
+
const img = token.tokens?.length === 1 && token.tokens[0]?.type === 'image'
|
|
1308
1308
|
? token.tokens[0]
|
|
1309
1309
|
: undefined;
|
|
1310
|
-
if (
|
|
1310
|
+
if (img && enabled(options, 'docImage')) {
|
|
1311
1311
|
result.push({
|
|
1312
1312
|
_type: 'docImage',
|
|
1313
1313
|
_key: key(),
|
|
1314
|
-
alt:
|
|
1315
|
-
url:
|
|
1316
|
-
...(
|
|
1314
|
+
alt: img.text ?? '',
|
|
1315
|
+
url: img.href ?? '',
|
|
1316
|
+
...(img.title ? { title: img.title } : {}),
|
|
1317
1317
|
markdown: token.raw,
|
|
1318
1318
|
});
|
|
1319
1319
|
continue;
|
|
@@ -1600,15 +1600,15 @@ function escapeTableAutolinks(markdown) {
|
|
|
1600
1600
|
.replace(/\b((?:https?|ftp)):\/\//gi, '$1://')
|
|
1601
1601
|
.replace(/\b(www)\./gi, '$1.')
|
|
1602
1602
|
.replace(/\b([A-Z0-9._%+-]+)@([A-Z0-9.-]+\.[A-Z]{2,})\b/gi, '$1@$2');
|
|
1603
|
-
return escaped.replace(/DOCSTABLEPROTECTED(\d+)TOKEN/g, (_match,
|
|
1603
|
+
return escaped.replace(/DOCSTABLEPROTECTED(\d+)TOKEN/g, (_match, i) => protectedParts[Number(i)] ?? _match);
|
|
1604
1604
|
}
|
|
1605
1605
|
function tableToMarkdown(block) {
|
|
1606
1606
|
const rows = Array.isArray(block.rows) ? block.rows : [];
|
|
1607
1607
|
const fallback = richBlockDirective(block);
|
|
1608
1608
|
if (!rows.length)
|
|
1609
1609
|
return fallback;
|
|
1610
|
-
const
|
|
1611
|
-
const rectangular =
|
|
1610
|
+
const colCounts = rows.map((row) => (Array.isArray(row.cells) ? row.cells.length : 0));
|
|
1611
|
+
const rectangular = colCounts.every((count) => count === colCounts[0]);
|
|
1612
1612
|
const simpleRows = rectangular &&
|
|
1613
1613
|
rows.every((row) => {
|
|
1614
1614
|
if (row._type !== 'row' || !onlyOwnFields(row, ['_type', '_key', 'cells']))
|
|
@@ -1768,15 +1768,15 @@ function emptyPortableTextParagraph(value) {
|
|
|
1768
1768
|
}
|
|
1769
1769
|
function semanticMarkdownValue(value) {
|
|
1770
1770
|
if (Array.isArray(value))
|
|
1771
|
-
return value.filter((
|
|
1771
|
+
return value.filter((i) => !emptyPortableTextParagraph(i)).map(semanticMarkdownValue);
|
|
1772
1772
|
if (!value || typeof value !== 'object')
|
|
1773
1773
|
return value;
|
|
1774
1774
|
const block = value;
|
|
1775
1775
|
const type = block._type;
|
|
1776
1776
|
if (type === 'block' || type === 'terraBlock') {
|
|
1777
1777
|
const definitions = new Map((Array.isArray(block.markDefs) ? block.markDefs : [])
|
|
1778
|
-
.filter((
|
|
1779
|
-
.map((
|
|
1778
|
+
.filter((i) => Boolean(i) && typeof i === 'object')
|
|
1779
|
+
.map((i) => [String(i._key ?? ''), semanticMarkdownValue(i)]));
|
|
1780
1780
|
const children = [];
|
|
1781
1781
|
for (const child of Array.isArray(block.children) ? block.children : []) {
|
|
1782
1782
|
if (!child || typeof child !== 'object') {
|
|
@@ -1822,8 +1822,8 @@ function semanticMarkdownValue(value) {
|
|
|
1822
1822
|
'children',
|
|
1823
1823
|
].includes(name))
|
|
1824
1824
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
1825
|
-
.map(([name,
|
|
1826
|
-
const markDefs = [...definitions.values()].map((
|
|
1825
|
+
.map(([name, i]) => [name, semanticMarkdownValue(i)]));
|
|
1826
|
+
const markDefs = [...definitions.values()].map((i) => JSON.stringify(i)).sort();
|
|
1827
1827
|
return {
|
|
1828
1828
|
...extra,
|
|
1829
1829
|
_type: 'textBlock',
|
|
@@ -1837,9 +1837,8 @@ function semanticMarkdownValue(value) {
|
|
|
1837
1837
|
// Empty, metadata-free Portable Text paragraphs have no visible Markdown
|
|
1838
1838
|
// representation. Ignore them in all nested block arrays (including callouts
|
|
1839
1839
|
// and table cells), while retaining the original records in the source archive.
|
|
1840
|
-
const
|
|
1841
|
-
const
|
|
1842
|
-
const extra = Object.fromEntries(Object.entries(semanticBlock)
|
|
1840
|
+
const nestedContent = Array.isArray(block.content) ? block.content : undefined;
|
|
1841
|
+
const extra = Object.fromEntries(Object.entries(block)
|
|
1843
1842
|
.filter(([name]) => !['_key', '_rev', '_createdAt', '_updatedAt', '_system'].includes(name))
|
|
1844
1843
|
.filter(([name]) => !(name === '_type' && type === 'item'))
|
|
1845
1844
|
.filter(([name]) => !(name === 'markdown' && nestedContent))
|
|
@@ -1851,7 +1850,7 @@ function semanticMarkdownValue(value) {
|
|
|
1851
1850
|
.filter(([name]) => !(name === 'markdown' && ['math', 'docImage', 'table'].includes(String(type))))
|
|
1852
1851
|
.filter(([name]) => !(name === 'markdown' && type === 'code' && ('value' in block || 'source' in block)))
|
|
1853
1852
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
1854
|
-
.map(([name,
|
|
1853
|
+
.map(([name, i]) => [name, semanticMarkdownValue(i)]));
|
|
1855
1854
|
return extra;
|
|
1856
1855
|
}
|
|
1857
1856
|
function markdownPreservesValue(value, markdown) {
|
|
@@ -1879,11 +1878,11 @@ function colonFence(contents, minimum = 4) {
|
|
|
1879
1878
|
const largest = contents.flatMap((content) => [...content.matchAll(/^(:+)(?:[ \t].*)?$/gm)].map((match) => match[1].length));
|
|
1880
1879
|
return ':'.repeat(Math.max(minimum, 1 + Math.max(0, ...largest)));
|
|
1881
1880
|
}
|
|
1882
|
-
function codeFence(code,
|
|
1881
|
+
function codeFence(code, lang) {
|
|
1883
1882
|
const tick = String.fromCharCode(96);
|
|
1884
1883
|
const runs = code.match(new RegExp(tick + '+', 'g')) ?? [];
|
|
1885
1884
|
const fence = tick.repeat(Math.max(3, 1 + Math.max(0, ...runs.map((run) => run.length))));
|
|
1886
|
-
const suffix =
|
|
1885
|
+
const suffix = lang ? lang : '';
|
|
1887
1886
|
return fence + suffix + '\n' + code.replace(/\n+$/, '') + '\n' + fence;
|
|
1888
1887
|
}
|
|
1889
1888
|
/** Serialize readable Markdown where it is faithful and typed source where it is not. */
|
|
@@ -1932,8 +1931,8 @@ export function docsValueToMarkdown(value) {
|
|
|
1932
1931
|
continue;
|
|
1933
1932
|
}
|
|
1934
1933
|
if (item._type === 'code' && !extra) {
|
|
1935
|
-
const
|
|
1936
|
-
if (
|
|
1934
|
+
const lang = String(item.language ?? '');
|
|
1935
|
+
if (lang && !/^[A-Za-z0-9_+.-]+$/.test(lang)) {
|
|
1937
1936
|
result.push(richBlockDirective(item));
|
|
1938
1937
|
}
|
|
1939
1938
|
else if (typeof item.markdown === 'string' &&
|
|
@@ -1943,7 +1942,7 @@ export function docsValueToMarkdown(value) {
|
|
|
1943
1942
|
result.push(markdownPreservesValue(item, item.markdown) ? item.markdown : richBlockDirective(item));
|
|
1944
1943
|
}
|
|
1945
1944
|
else {
|
|
1946
|
-
const markdown = codeFence(String(item.value ?? item.source ?? ''),
|
|
1945
|
+
const markdown = codeFence(String(item.value ?? item.source ?? ''), lang);
|
|
1947
1946
|
result.push(markdownPreservesValue(item, markdown) ? markdown : richBlockDirective(item));
|
|
1948
1947
|
}
|
|
1949
1948
|
continue;
|