@readme/markdown 14.11.4 → 14.12.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/components/HTMLBlock/index.tsx +12 -10
- package/dist/main.js +2055 -1886
- package/dist/main.node.js +2054 -1885
- package/dist/main.node.js.map +1 -1
- package/dist/processor/compile/text.d.ts +4 -0
- package/dist/processor/transform/mdxish/components/mdx-blocks.d.ts +4 -0
- package/dist/processor/transform/mdxish/components/utils.d.ts +13 -1
- package/dist/processor/transform/mdxish/mdxish-html-blocks.d.ts +7 -6
- package/dist/processor/transform/mdxish/normalize-closing-tag-whitespace.d.ts +13 -0
- package/dist/processor/transform/mdxish/terminate-html-flow-blocks.d.ts +3 -17
- package/dist/render-fixture.node.js +2055 -1886
- package/dist/render-fixture.node.js.map +1 -1
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
2
2
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
3
|
-
module.exports = factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("
|
|
3
|
+
module.exports = factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("react"), require("react-dom"));
|
|
4
4
|
else if(typeof define === 'function' && define.amd)
|
|
5
|
-
define(["@readme/syntax-highlighter", "@readme/variable", "@tippyjs/react", "acorn", "
|
|
5
|
+
define(["@readme/syntax-highlighter", "@readme/variable", "@tippyjs/react", "acorn", "react", "react-dom"], factory);
|
|
6
6
|
else {
|
|
7
|
-
var a = typeof exports === 'object' ? factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("
|
|
7
|
+
var a = typeof exports === 'object' ? factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("react"), require("react-dom")) : factory(root["@readme/syntax-highlighter"], root["@readme/variable"], root["@tippyjs/react"], root["acorn"], root["React"], root["ReactDOM"]);
|
|
8
8
|
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
|
9
9
|
}
|
|
10
|
-
})(self, (__WEBPACK_EXTERNAL_MODULE__3966__, __WEBPACK_EXTERNAL_MODULE__8167__, __WEBPACK_EXTERNAL_MODULE__4189__, __WEBPACK_EXTERNAL_MODULE__6473__,
|
|
10
|
+
})(self, (__WEBPACK_EXTERNAL_MODULE__3966__, __WEBPACK_EXTERNAL_MODULE__8167__, __WEBPACK_EXTERNAL_MODULE__4189__, __WEBPACK_EXTERNAL_MODULE__6473__, __WEBPACK_EXTERNAL_MODULE__1307__, __WEBPACK_EXTERNAL_MODULE__8759__) => {
|
|
11
11
|
return /******/ (() => { // webpackBootstrap
|
|
12
12
|
/******/ var __webpack_modules__ = ({
|
|
13
13
|
|
|
@@ -11327,6 +11327,14 @@ module.exports = function () {
|
|
|
11327
11327
|
};
|
|
11328
11328
|
|
|
11329
11329
|
|
|
11330
|
+
/***/ }),
|
|
11331
|
+
|
|
11332
|
+
/***/ 9446:
|
|
11333
|
+
/***/ ((module) => {
|
|
11334
|
+
|
|
11335
|
+
"use strict";
|
|
11336
|
+
module.exports = import("mermaid");;
|
|
11337
|
+
|
|
11330
11338
|
/***/ }),
|
|
11331
11339
|
|
|
11332
11340
|
/***/ 3966:
|
|
@@ -11361,14 +11369,6 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__6473__;
|
|
|
11361
11369
|
|
|
11362
11370
|
/***/ }),
|
|
11363
11371
|
|
|
11364
|
-
/***/ 1387:
|
|
11365
|
-
/***/ ((module) => {
|
|
11366
|
-
|
|
11367
|
-
"use strict";
|
|
11368
|
-
module.exports = __WEBPACK_EXTERNAL_MODULE__1387__;
|
|
11369
|
-
|
|
11370
|
-
/***/ }),
|
|
11371
|
-
|
|
11372
11372
|
/***/ 1307:
|
|
11373
11373
|
/***/ ((module) => {
|
|
11374
11374
|
|
|
@@ -11975,7 +11975,7 @@ function queueMermaidNode(node, theme) {
|
|
|
11975
11975
|
const nodes = [...mermaidQueue];
|
|
11976
11976
|
mermaidQueue = [];
|
|
11977
11977
|
mermaidFlushTimer = null;
|
|
11978
|
-
const module = await Promise.resolve(/* import() */).then(__webpack_require__.
|
|
11978
|
+
const module = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 9446));
|
|
11979
11979
|
mermaid = module.default;
|
|
11980
11980
|
mermaid.initialize({
|
|
11981
11981
|
startOnLoad: false,
|
|
@@ -12211,17 +12211,12 @@ const extractScripts = (html = '') => {
|
|
|
12211
12211
|
return [cleaned, () => scripts.map(js => window.eval(js))];
|
|
12212
12212
|
};
|
|
12213
12213
|
const HTMLBlock = ({ children = '', html: htmlProp, runScripts, safeMode: safeModeRaw = false }) => {
|
|
12214
|
-
// Determine HTML source: MDXish uses html prop (from HAST), MDX uses children
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
if (typeof children !== 'string') {
|
|
12221
|
-
throw new TypeError('HTMLBlock: children must be a string');
|
|
12222
|
-
}
|
|
12223
|
-
html = children;
|
|
12224
|
-
}
|
|
12214
|
+
// Determine HTML source: MDXish uses html prop (from HAST), MDX uses children.
|
|
12215
|
+
// A non-string child (no html prop) can't be injected as raw HTML — see the
|
|
12216
|
+
// fail-soft fallback below.
|
|
12217
|
+
const htmlSource = htmlProp !== undefined ? htmlProp : children;
|
|
12218
|
+
const nonStringChildren = typeof htmlSource !== 'string';
|
|
12219
|
+
const html = nonStringChildren ? '' : htmlSource;
|
|
12225
12220
|
// eslint-disable-next-line no-param-reassign
|
|
12226
12221
|
runScripts = typeof runScripts !== 'boolean' ? runScripts === 'true' : runScripts;
|
|
12227
12222
|
// In MDX mode, safeMode is passed in as a boolean from JSX parsing
|
|
@@ -12232,6 +12227,11 @@ const HTMLBlock = ({ children = '', html: htmlProp, runScripts, safeMode: safeMo
|
|
|
12232
12227
|
if (typeof window !== 'undefined' && typeof runScripts === 'boolean' && runScripts)
|
|
12233
12228
|
exec();
|
|
12234
12229
|
}, [runScripts, exec]);
|
|
12230
|
+
if (nonStringChildren) {
|
|
12231
|
+
// Fail soft: a non-string child (e.g. JSX that wasn't serialized back to a
|
|
12232
|
+
// raw string) should never throw, so render the child nodes directly
|
|
12233
|
+
return external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("div", { className: "rdmd-html" }, children);
|
|
12234
|
+
}
|
|
12235
12235
|
if (safeMode) {
|
|
12236
12236
|
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("pre", { className: "html-unsafe" },
|
|
12237
12237
|
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("code", null, html)));
|
|
@@ -76446,6 +76446,9 @@ const TOP_LEVEL_TABLE_TAG_RE = /^<(?:table|Table)(?=[\s/>])/;
|
|
|
76446
76446
|
* Uses `walkTags` so `<table>`s inside code spans / fenced blocks (masked away)
|
|
76447
76447
|
* are never matched.
|
|
76448
76448
|
*
|
|
76449
|
+
* `<table>`s inside an `<HTMLBlock>` body are also ignored: that body is opaque
|
|
76450
|
+
* raw HTML, so lifting a table out of it would corrupt the block.
|
|
76451
|
+
*
|
|
76449
76452
|
* Note: An implicitly-closed table (no `</table>`, so htmlparser2 synthesizes the
|
|
76450
76453
|
* close at a later tag) is skipped: splitting there would swallow whatever
|
|
76451
76454
|
* followed the table into the fragment and drop it, so we leave such a node
|
|
@@ -76453,21 +76456,35 @@ const TOP_LEVEL_TABLE_TAG_RE = /^<(?:table|Table)(?=[\s/>])/;
|
|
|
76453
76456
|
*/
|
|
76454
76457
|
const findTableRanges = (html) => {
|
|
76455
76458
|
const ranges = [];
|
|
76456
|
-
let
|
|
76459
|
+
let tableDepth = 0;
|
|
76460
|
+
let htmlBlockDepth = 0;
|
|
76457
76461
|
let start = 0;
|
|
76458
76462
|
walkTags(html, {
|
|
76459
|
-
onOpen: ({ name, start: openStart, isStrayCloser }) => {
|
|
76460
|
-
if (
|
|
76463
|
+
onOpen: ({ name, start: openStart, isSelfClosing, isStrayCloser }) => {
|
|
76464
|
+
if (isStrayCloser)
|
|
76461
76465
|
return;
|
|
76462
|
-
|
|
76466
|
+
// `<HTMLBlock/>` has no body to protect; only a real open enters one.
|
|
76467
|
+
if (name === 'HTMLBlock') {
|
|
76468
|
+
if (!isSelfClosing)
|
|
76469
|
+
htmlBlockDepth += 1;
|
|
76470
|
+
return;
|
|
76471
|
+
}
|
|
76472
|
+
if (htmlBlockDepth > 0 || name.toLowerCase() !== 'table')
|
|
76473
|
+
return;
|
|
76474
|
+
if (tableDepth === 0)
|
|
76463
76475
|
start = openStart;
|
|
76464
|
-
|
|
76476
|
+
tableDepth += 1;
|
|
76465
76477
|
},
|
|
76466
76478
|
onClose: ({ name, end, implicit }) => {
|
|
76467
|
-
if (
|
|
76479
|
+
if (name === 'HTMLBlock') {
|
|
76480
|
+
if (!implicit && htmlBlockDepth > 0)
|
|
76481
|
+
htmlBlockDepth -= 1;
|
|
76468
76482
|
return;
|
|
76469
|
-
|
|
76470
|
-
if (
|
|
76483
|
+
}
|
|
76484
|
+
if (implicit || htmlBlockDepth > 0 || name.toLowerCase() !== 'table' || tableDepth === 0)
|
|
76485
|
+
return;
|
|
76486
|
+
tableDepth -= 1;
|
|
76487
|
+
if (tableDepth === 0)
|
|
76471
76488
|
ranges.push({ start, end });
|
|
76472
76489
|
},
|
|
76473
76490
|
});
|
|
@@ -76487,7 +76504,9 @@ const splitHtmlWithNestedTables = (node) => {
|
|
|
76487
76504
|
// This is a top-level table, so we don't need to split it
|
|
76488
76505
|
if (TOP_LEVEL_TABLE_TAG_RE.test(value))
|
|
76489
76506
|
return null;
|
|
76490
|
-
// No table text anywhere
|
|
76507
|
+
// No table text anywhere → skip the htmlparser2 walk entirely. (A `<table>` that
|
|
76508
|
+
// only appears inside an `<HTMLBlock>` body still yields no ranges below, so it's
|
|
76509
|
+
// left whole for `mdxishHtmlBlocks` to convert to an html-block next.)
|
|
76491
76510
|
if (!/<\/?table/i.test(value))
|
|
76492
76511
|
return null;
|
|
76493
76512
|
const ranges = findTableRanges(value);
|
|
@@ -97322,6 +97341,19 @@ const compile_list_item_listItem = (node, parent, state, info) => {
|
|
|
97322
97341
|
const plain_plain = (node) => node.value;
|
|
97323
97342
|
/* harmony default export */ const compile_plain = (plain_plain);
|
|
97324
97343
|
|
|
97344
|
+
;// ./processor/compile/text.ts
|
|
97345
|
+
|
|
97346
|
+
// A `_` flanked by word characters can never open or close emphasis under
|
|
97347
|
+
// CommonMark's flanking rules, so the escape mdast-util-to-markdown adds to
|
|
97348
|
+
// intraword underscores is unnecessary and only produces noisy `\_` diffs.
|
|
97349
|
+
// Uses Unicode letter/number classes so non-ASCII words (e.g. `é_pay`) match.
|
|
97350
|
+
const INTRAWORD_UNDERSCORE_ESCAPE = /(?<=[\p{L}\p{N}_])\\_(?=[\p{L}\p{N}_]|\\_)/gu;
|
|
97351
|
+
const compile_text_text = (node, parent, state, info) => {
|
|
97352
|
+
const serialized = handle.text(node, parent, state, info);
|
|
97353
|
+
return serialized.replace(INTRAWORD_UNDERSCORE_ESCAPE, '_');
|
|
97354
|
+
};
|
|
97355
|
+
/* harmony default export */ const compile_text = (compile_text_text);
|
|
97356
|
+
|
|
97325
97357
|
;// ./processor/compile/index.ts
|
|
97326
97358
|
|
|
97327
97359
|
|
|
@@ -97334,11 +97366,11 @@ const plain_plain = (node) => node.value;
|
|
|
97334
97366
|
|
|
97335
97367
|
|
|
97336
97368
|
|
|
97369
|
+
|
|
97337
97370
|
function compilers(mdxish = false) {
|
|
97338
97371
|
const data = this.data();
|
|
97339
97372
|
const toMarkdownExtensions = data.toMarkdownExtensions || (data.toMarkdownExtensions = []);
|
|
97340
97373
|
const handlers = {
|
|
97341
|
-
...(mdxish && { [NodeTypes.anchor]: compile_anchor }),
|
|
97342
97374
|
[NodeTypes.callout]: compile_callout,
|
|
97343
97375
|
[NodeTypes.codeTabs]: compile_code_tabs,
|
|
97344
97376
|
[NodeTypes.embedBlock]: compile_embed,
|
|
@@ -97346,15 +97378,18 @@ function compilers(mdxish = false) {
|
|
|
97346
97378
|
[NodeTypes.glossary]: compile_compatibility,
|
|
97347
97379
|
[NodeTypes.htmlBlock]: html_block,
|
|
97348
97380
|
[NodeTypes.reusableContent]: compile_compatibility,
|
|
97349
|
-
...(mdxish && { [NodeTypes.variable]: compile_variable }),
|
|
97350
97381
|
embed: compile_compatibility,
|
|
97351
97382
|
escape: compile_compatibility,
|
|
97352
97383
|
figure: compile_compatibility,
|
|
97353
97384
|
html: compile_compatibility,
|
|
97354
97385
|
i: compile_compatibility,
|
|
97355
|
-
...(mdxish && { listItem: list_item }),
|
|
97356
97386
|
plain: compile_plain,
|
|
97357
97387
|
yaml: compile_compatibility,
|
|
97388
|
+
// needed only for mdxish
|
|
97389
|
+
...(mdxish && { [NodeTypes.anchor]: compile_anchor }),
|
|
97390
|
+
...(mdxish && { listItem: list_item }),
|
|
97391
|
+
...(mdxish && { text: compile_text }),
|
|
97392
|
+
...(mdxish && { [NodeTypes.variable]: compile_variable }),
|
|
97358
97393
|
};
|
|
97359
97394
|
toMarkdownExtensions.push({ extensions: [{ handlers }] });
|
|
97360
97395
|
}
|
|
@@ -99633,6 +99668,55 @@ function emptyTaskListItemFromMarkdown() {
|
|
|
99633
99668
|
};
|
|
99634
99669
|
}
|
|
99635
99670
|
|
|
99671
|
+
;// ./lib/mdast-util/jsx-table/index.ts
|
|
99672
|
+
const jsx_table_contextMap = new WeakMap();
|
|
99673
|
+
function findJsxTableToken() {
|
|
99674
|
+
const events = this.tokenStack;
|
|
99675
|
+
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
99676
|
+
if (events[i][0].type === 'jsxTable')
|
|
99677
|
+
return events[i][0];
|
|
99678
|
+
}
|
|
99679
|
+
return undefined;
|
|
99680
|
+
}
|
|
99681
|
+
function enterJsxTable(token) {
|
|
99682
|
+
jsx_table_contextMap.set(token, { chunks: [], lastEndLine: token.start.line });
|
|
99683
|
+
this.enter({ type: 'html', value: '' }, token);
|
|
99684
|
+
}
|
|
99685
|
+
function exitJsxTableData(token) {
|
|
99686
|
+
const tableToken = findJsxTableToken.call(this);
|
|
99687
|
+
if (!tableToken)
|
|
99688
|
+
return;
|
|
99689
|
+
const ctx = jsx_table_contextMap.get(tableToken);
|
|
99690
|
+
if (ctx) {
|
|
99691
|
+
const gap = token.start.line - ctx.lastEndLine;
|
|
99692
|
+
if (ctx.chunks.length > 0 && gap > 0) {
|
|
99693
|
+
ctx.chunks.push('\n'.repeat(gap));
|
|
99694
|
+
}
|
|
99695
|
+
ctx.chunks.push(this.sliceSerialize(token));
|
|
99696
|
+
ctx.lastEndLine = token.end.line;
|
|
99697
|
+
}
|
|
99698
|
+
}
|
|
99699
|
+
function exitJsxTable(token) {
|
|
99700
|
+
const ctx = jsx_table_contextMap.get(token);
|
|
99701
|
+
const node = this.stack[this.stack.length - 1];
|
|
99702
|
+
if (ctx) {
|
|
99703
|
+
node.value = ctx.chunks.join('');
|
|
99704
|
+
jsx_table_contextMap.delete(token);
|
|
99705
|
+
}
|
|
99706
|
+
this.exit(token);
|
|
99707
|
+
}
|
|
99708
|
+
function jsxTableFromMarkdown() {
|
|
99709
|
+
return {
|
|
99710
|
+
enter: {
|
|
99711
|
+
jsxTable: enterJsxTable,
|
|
99712
|
+
},
|
|
99713
|
+
exit: {
|
|
99714
|
+
jsxTableData: exitJsxTableData,
|
|
99715
|
+
jsxTable: exitJsxTable,
|
|
99716
|
+
},
|
|
99717
|
+
};
|
|
99718
|
+
}
|
|
99719
|
+
|
|
99636
99720
|
;// ./lib/mdast-util/magic-block/index.ts
|
|
99637
99721
|
const magic_block_contextMap = new WeakMap();
|
|
99638
99722
|
/**
|
|
@@ -99822,867 +99906,16 @@ function mdxComponentFromMarkdown() {
|
|
|
99822
99906
|
};
|
|
99823
99907
|
}
|
|
99824
99908
|
|
|
99825
|
-
;// ./
|
|
99826
|
-
|
|
99827
|
-
|
|
99828
|
-
/**
|
|
99829
|
-
* Known magic block types that the tokenizer will recognize.
|
|
99830
|
-
* Unknown types will not be tokenized as magic blocks.
|
|
99831
|
-
*/
|
|
99832
|
-
const KNOWN_BLOCK_TYPES = new Set([
|
|
99833
|
-
'code',
|
|
99834
|
-
'api-header',
|
|
99835
|
-
'image',
|
|
99836
|
-
'callout',
|
|
99837
|
-
'parameters',
|
|
99838
|
-
'table',
|
|
99839
|
-
'embed',
|
|
99840
|
-
'html',
|
|
99841
|
-
'recipe',
|
|
99842
|
-
'tutorial-tile',
|
|
99843
|
-
]);
|
|
99844
|
-
/**
|
|
99845
|
-
* Check if a character is valid for a magic block type identifier.
|
|
99846
|
-
* Types can contain alphanumeric characters and hyphens (e.g., "api-header", "tutorial-tile")
|
|
99847
|
-
*/
|
|
99848
|
-
function isTypeChar(code) {
|
|
99849
|
-
return asciiAlphanumeric(code) || code === codes.dash;
|
|
99850
|
-
}
|
|
99851
|
-
/**
|
|
99852
|
-
* Creates the opening marker state machine: [block:
|
|
99853
|
-
* Returns the first state function to start parsing.
|
|
99854
|
-
*/
|
|
99855
|
-
function createOpeningMarkerParser(effects, nok, onComplete) {
|
|
99856
|
-
const expectB = (code) => {
|
|
99857
|
-
if (code !== codes.lowercaseB)
|
|
99858
|
-
return nok(code);
|
|
99859
|
-
effects.consume(code);
|
|
99860
|
-
return expectL;
|
|
99861
|
-
};
|
|
99862
|
-
const expectL = (code) => {
|
|
99863
|
-
if (code !== codes.lowercaseL)
|
|
99864
|
-
return nok(code);
|
|
99865
|
-
effects.consume(code);
|
|
99866
|
-
return expectO;
|
|
99867
|
-
};
|
|
99868
|
-
const expectO = (code) => {
|
|
99869
|
-
if (code !== codes.lowercaseO)
|
|
99870
|
-
return nok(code);
|
|
99871
|
-
effects.consume(code);
|
|
99872
|
-
return expectC;
|
|
99873
|
-
};
|
|
99874
|
-
const expectC = (code) => {
|
|
99875
|
-
if (code !== codes.lowercaseC)
|
|
99876
|
-
return nok(code);
|
|
99877
|
-
effects.consume(code);
|
|
99878
|
-
return expectK;
|
|
99879
|
-
};
|
|
99880
|
-
const expectK = (code) => {
|
|
99881
|
-
if (code !== codes.lowercaseK)
|
|
99882
|
-
return nok(code);
|
|
99883
|
-
effects.consume(code);
|
|
99884
|
-
return expectColon;
|
|
99885
|
-
};
|
|
99886
|
-
const expectColon = (code) => {
|
|
99887
|
-
if (code !== codes.colon)
|
|
99888
|
-
return nok(code);
|
|
99889
|
-
effects.consume(code);
|
|
99890
|
-
effects.exit('magicBlockMarkerStart');
|
|
99891
|
-
effects.enter('magicBlockType');
|
|
99892
|
-
return onComplete;
|
|
99893
|
-
};
|
|
99894
|
-
return expectB;
|
|
99895
|
-
}
|
|
99896
|
-
/**
|
|
99897
|
-
* Creates the type capture state machine.
|
|
99898
|
-
* Captures type characters until ] and validates against known types.
|
|
99899
|
-
*/
|
|
99900
|
-
function createTypeCaptureParser(effects, nok, onComplete, blockTypeRef) {
|
|
99901
|
-
const captureTypeFirst = (code) => {
|
|
99902
|
-
// Reject empty type name [block:]
|
|
99903
|
-
if (code === codes.rightSquareBracket) {
|
|
99904
|
-
return nok(code);
|
|
99905
|
-
}
|
|
99906
|
-
if (isTypeChar(code)) {
|
|
99907
|
-
blockTypeRef.value += String.fromCharCode(code);
|
|
99908
|
-
effects.consume(code);
|
|
99909
|
-
return captureType;
|
|
99910
|
-
}
|
|
99911
|
-
return nok(code);
|
|
99912
|
-
};
|
|
99913
|
-
const captureType = (code) => {
|
|
99914
|
-
if (code === codes.rightSquareBracket) {
|
|
99915
|
-
if (!KNOWN_BLOCK_TYPES.has(blockTypeRef.value)) {
|
|
99916
|
-
return nok(code);
|
|
99917
|
-
}
|
|
99918
|
-
effects.exit('magicBlockType');
|
|
99919
|
-
effects.enter('magicBlockMarkerTypeEnd');
|
|
99920
|
-
effects.consume(code);
|
|
99921
|
-
effects.exit('magicBlockMarkerTypeEnd');
|
|
99922
|
-
return onComplete;
|
|
99923
|
-
}
|
|
99924
|
-
if (isTypeChar(code)) {
|
|
99925
|
-
blockTypeRef.value += String.fromCharCode(code);
|
|
99926
|
-
effects.consume(code);
|
|
99927
|
-
return captureType;
|
|
99928
|
-
}
|
|
99929
|
-
return nok(code);
|
|
99930
|
-
};
|
|
99931
|
-
return { first: captureTypeFirst, remaining: captureType };
|
|
99932
|
-
}
|
|
99933
|
-
/**
|
|
99934
|
-
* Creates the closing marker state machine: /block]
|
|
99935
|
-
* Handles partial matches by calling onMismatch to fall back to data capture.
|
|
99936
|
-
*/
|
|
99937
|
-
function createClosingMarkerParser(effects, onSuccess, onMismatch, onEof, jsonState) {
|
|
99938
|
-
const handleMismatch = (code) => {
|
|
99939
|
-
if (jsonState && code === codes.quotationMark) {
|
|
99940
|
-
jsonState.inString = true;
|
|
99941
|
-
}
|
|
99942
|
-
return onMismatch(code);
|
|
99943
|
-
};
|
|
99944
|
-
const expectSlash = (code) => {
|
|
99945
|
-
if (code === null)
|
|
99946
|
-
return onEof(code);
|
|
99947
|
-
if (code !== codes.slash)
|
|
99948
|
-
return handleMismatch(code);
|
|
99949
|
-
effects.consume(code);
|
|
99950
|
-
return expectB;
|
|
99951
|
-
};
|
|
99952
|
-
const expectB = (code) => {
|
|
99953
|
-
if (code === null)
|
|
99954
|
-
return onEof(code);
|
|
99955
|
-
if (code !== codes.lowercaseB)
|
|
99956
|
-
return handleMismatch(code);
|
|
99957
|
-
effects.consume(code);
|
|
99958
|
-
return expectL;
|
|
99959
|
-
};
|
|
99960
|
-
const expectL = (code) => {
|
|
99961
|
-
if (code === null)
|
|
99962
|
-
return onEof(code);
|
|
99963
|
-
if (code !== codes.lowercaseL)
|
|
99964
|
-
return handleMismatch(code);
|
|
99965
|
-
effects.consume(code);
|
|
99966
|
-
return expectO;
|
|
99967
|
-
};
|
|
99968
|
-
const expectO = (code) => {
|
|
99969
|
-
if (code === null)
|
|
99970
|
-
return onEof(code);
|
|
99971
|
-
if (code !== codes.lowercaseO)
|
|
99972
|
-
return handleMismatch(code);
|
|
99973
|
-
effects.consume(code);
|
|
99974
|
-
return expectC;
|
|
99975
|
-
};
|
|
99976
|
-
const expectC = (code) => {
|
|
99977
|
-
if (code === null)
|
|
99978
|
-
return onEof(code);
|
|
99979
|
-
if (code !== codes.lowercaseC)
|
|
99980
|
-
return handleMismatch(code);
|
|
99981
|
-
effects.consume(code);
|
|
99982
|
-
return expectK;
|
|
99983
|
-
};
|
|
99984
|
-
const expectK = (code) => {
|
|
99985
|
-
if (code === null)
|
|
99986
|
-
return onEof(code);
|
|
99987
|
-
if (code !== codes.lowercaseK)
|
|
99988
|
-
return handleMismatch(code);
|
|
99989
|
-
effects.consume(code);
|
|
99990
|
-
return expectBracket;
|
|
99991
|
-
};
|
|
99992
|
-
const expectBracket = (code) => {
|
|
99993
|
-
if (code === null)
|
|
99994
|
-
return onEof(code);
|
|
99995
|
-
if (code !== codes.rightSquareBracket)
|
|
99996
|
-
return handleMismatch(code);
|
|
99997
|
-
effects.consume(code);
|
|
99998
|
-
return onSuccess;
|
|
99999
|
-
};
|
|
100000
|
-
return { expectSlash };
|
|
100001
|
-
}
|
|
100002
|
-
/**
|
|
100003
|
-
* Partial construct for checking non-lazy continuation.
|
|
100004
|
-
* This is used by the flow tokenizer to check if we can continue
|
|
100005
|
-
* parsing on the next line.
|
|
100006
|
-
*/
|
|
100007
|
-
const syntax_nonLazyContinuation = {
|
|
100008
|
-
partial: true,
|
|
100009
|
-
tokenize: syntax_tokenizeNonLazyContinuation,
|
|
100010
|
-
};
|
|
100011
|
-
/**
|
|
100012
|
-
* Tokenizer for non-lazy continuation checking.
|
|
100013
|
-
* Returns ok if the next line is non-lazy (can continue), nok if lazy.
|
|
100014
|
-
*/
|
|
100015
|
-
function syntax_tokenizeNonLazyContinuation(effects, ok, nok) {
|
|
100016
|
-
const lineStart = (code) => {
|
|
100017
|
-
// `this` here refers to the micromark parser
|
|
100018
|
-
// since we are just passing functions as references and not actually calling them
|
|
100019
|
-
// micromarks's internal parser will call this automatically with appropriate arguments
|
|
100020
|
-
return this.parser.lazy[this.now().line] ? nok(code) : ok(code);
|
|
100021
|
-
};
|
|
100022
|
-
const start = (code) => {
|
|
100023
|
-
if (code === null) {
|
|
100024
|
-
return nok(code);
|
|
100025
|
-
}
|
|
100026
|
-
if (!markdownLineEnding(code)) {
|
|
100027
|
-
return nok(code);
|
|
100028
|
-
}
|
|
100029
|
-
effects.enter('magicBlockLineEnding');
|
|
100030
|
-
effects.consume(code);
|
|
100031
|
-
effects.exit('magicBlockLineEnding');
|
|
100032
|
-
return lineStart;
|
|
100033
|
-
};
|
|
100034
|
-
return start;
|
|
100035
|
-
}
|
|
99909
|
+
;// ./node_modules/micromark-util-symbol/lib/types.js
|
|
100036
99910
|
/**
|
|
100037
|
-
*
|
|
100038
|
-
*
|
|
100039
|
-
* This extension handles both single-line and multiline magic blocks:
|
|
100040
|
-
* - Flow construct (concrete): Handles block-level multiline magic blocks at document level
|
|
100041
|
-
* - Text construct: Handles inline magic blocks in lists, paragraphs, etc.
|
|
99911
|
+
* This module is compiled away!
|
|
100042
99912
|
*
|
|
100043
|
-
*
|
|
100044
|
-
*
|
|
100045
|
-
|
|
100046
|
-
|
|
100047
|
-
|
|
100048
|
-
|
|
100049
|
-
// Marked as concrete to prevent interruption by containers
|
|
100050
|
-
flow: {
|
|
100051
|
-
[codes.leftSquareBracket]: {
|
|
100052
|
-
name: 'magicBlock',
|
|
100053
|
-
concrete: true,
|
|
100054
|
-
tokenize: tokenizeMagicBlockFlow,
|
|
100055
|
-
},
|
|
100056
|
-
},
|
|
100057
|
-
// Text construct - handles magic blocks in inline contexts (lists, paragraphs)
|
|
100058
|
-
text: {
|
|
100059
|
-
[codes.leftSquareBracket]: {
|
|
100060
|
-
name: 'magicBlock',
|
|
100061
|
-
tokenize: tokenizeMagicBlockText,
|
|
100062
|
-
},
|
|
100063
|
-
},
|
|
100064
|
-
};
|
|
100065
|
-
}
|
|
100066
|
-
/**
|
|
100067
|
-
* Flow tokenizer for block-level magic blocks (multiline).
|
|
100068
|
-
* Uses the continuation checking pattern from code fences.
|
|
100069
|
-
*/
|
|
100070
|
-
function tokenizeMagicBlockFlow(effects, ok, nok) {
|
|
100071
|
-
// State for tracking JSON content
|
|
100072
|
-
const jsonState = { escapeNext: false, inString: false };
|
|
100073
|
-
const blockTypeRef = { value: '' };
|
|
100074
|
-
let seenOpenBrace = false;
|
|
100075
|
-
// Create shared parsers for opening marker and type capture
|
|
100076
|
-
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
100077
|
-
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
100078
|
-
return start;
|
|
100079
|
-
function start(code) {
|
|
100080
|
-
if (code !== codes.leftSquareBracket)
|
|
100081
|
-
return nok(code);
|
|
100082
|
-
effects.enter('magicBlock');
|
|
100083
|
-
effects.enter('magicBlockMarkerStart');
|
|
100084
|
-
effects.consume(code);
|
|
100085
|
-
return openingMarkerParser;
|
|
100086
|
-
}
|
|
100087
|
-
/**
|
|
100088
|
-
* State before data content - handles line endings or starts data capture.
|
|
100089
|
-
*/
|
|
100090
|
-
function beforeData(code) {
|
|
100091
|
-
// EOF - magic block must be closed
|
|
100092
|
-
if (code === null) {
|
|
100093
|
-
effects.exit('magicBlock');
|
|
100094
|
-
return nok(code);
|
|
100095
|
-
}
|
|
100096
|
-
// Line ending before any data - check continuation
|
|
100097
|
-
if (markdownLineEnding(code)) {
|
|
100098
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100099
|
-
}
|
|
100100
|
-
// Check for closing marker directly (without entering data)
|
|
100101
|
-
// This handles cases like [block:type]\n{}\n\n[/block] where there are
|
|
100102
|
-
// newlines after the data object
|
|
100103
|
-
if (code === codes.leftSquareBracket) {
|
|
100104
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100105
|
-
effects.consume(code);
|
|
100106
|
-
return expectSlashFromContinuation;
|
|
100107
|
-
}
|
|
100108
|
-
// If we've already seen the opening brace, just continue capturing data
|
|
100109
|
-
if (seenOpenBrace) {
|
|
100110
|
-
effects.enter('magicBlockData');
|
|
100111
|
-
return captureData(code);
|
|
100112
|
-
}
|
|
100113
|
-
// Skip whitespace (spaces/tabs) before the data - stay in beforeData
|
|
100114
|
-
// Don't enter magicBlockData token yet until we confirm there's a '{'
|
|
100115
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100116
|
-
return beforeDataWhitespace(code);
|
|
100117
|
-
}
|
|
100118
|
-
// Data must start with '{' for valid JSON
|
|
100119
|
-
if (code !== codes.leftCurlyBrace) {
|
|
100120
|
-
effects.exit('magicBlock');
|
|
100121
|
-
return nok(code);
|
|
100122
|
-
}
|
|
100123
|
-
// We have '{' - enter data token and start capturing
|
|
100124
|
-
seenOpenBrace = true;
|
|
100125
|
-
effects.enter('magicBlockData');
|
|
100126
|
-
return captureData(code);
|
|
100127
|
-
}
|
|
100128
|
-
/**
|
|
100129
|
-
* Consume whitespace before the data without creating a token.
|
|
100130
|
-
* Uses a temporary token to satisfy micromark's requirement.
|
|
100131
|
-
*/
|
|
100132
|
-
function beforeDataWhitespace(code) {
|
|
100133
|
-
if (code === null) {
|
|
100134
|
-
effects.exit('magicBlock');
|
|
100135
|
-
return nok(code);
|
|
100136
|
-
}
|
|
100137
|
-
if (markdownLineEnding(code)) {
|
|
100138
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100139
|
-
}
|
|
100140
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100141
|
-
// We need to consume this but can't without a token - use magicBlockData
|
|
100142
|
-
// and track that we haven't seen '{' yet
|
|
100143
|
-
effects.enter('magicBlockData');
|
|
100144
|
-
effects.consume(code);
|
|
100145
|
-
return beforeDataWhitespaceContinue;
|
|
100146
|
-
}
|
|
100147
|
-
if (code === codes.leftCurlyBrace) {
|
|
100148
|
-
seenOpenBrace = true;
|
|
100149
|
-
effects.enter('magicBlockData');
|
|
100150
|
-
return captureData(code);
|
|
100151
|
-
}
|
|
100152
|
-
effects.exit('magicBlock');
|
|
100153
|
-
return nok(code);
|
|
100154
|
-
}
|
|
100155
|
-
/**
|
|
100156
|
-
* Continue consuming whitespace or validate the opening brace.
|
|
100157
|
-
*/
|
|
100158
|
-
function beforeDataWhitespaceContinue(code) {
|
|
100159
|
-
if (code === null) {
|
|
100160
|
-
effects.exit('magicBlockData');
|
|
100161
|
-
effects.exit('magicBlock');
|
|
100162
|
-
return nok(code);
|
|
100163
|
-
}
|
|
100164
|
-
if (markdownLineEnding(code)) {
|
|
100165
|
-
effects.exit('magicBlockData');
|
|
100166
|
-
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100167
|
-
}
|
|
100168
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100169
|
-
effects.consume(code);
|
|
100170
|
-
return beforeDataWhitespaceContinue;
|
|
100171
|
-
}
|
|
100172
|
-
if (code === codes.leftCurlyBrace) {
|
|
100173
|
-
seenOpenBrace = true;
|
|
100174
|
-
return captureData(code);
|
|
100175
|
-
}
|
|
100176
|
-
effects.exit('magicBlockData');
|
|
100177
|
-
effects.exit('magicBlock');
|
|
100178
|
-
return nok(code);
|
|
100179
|
-
}
|
|
100180
|
-
/**
|
|
100181
|
-
* Continuation OK before we've entered data token.
|
|
100182
|
-
*/
|
|
100183
|
-
function continuationOkBeforeData(code) {
|
|
100184
|
-
effects.enter('magicBlockLineEnding');
|
|
100185
|
-
effects.consume(code);
|
|
100186
|
-
effects.exit('magicBlockLineEnding');
|
|
100187
|
-
return beforeData; // Stay in beforeData state - don't enter magicBlockData yet
|
|
100188
|
-
}
|
|
100189
|
-
function captureData(code) {
|
|
100190
|
-
// EOF - magic block must be closed
|
|
100191
|
-
if (code === null) {
|
|
100192
|
-
effects.exit('magicBlockData');
|
|
100193
|
-
effects.exit('magicBlock');
|
|
100194
|
-
return nok(code);
|
|
100195
|
-
}
|
|
100196
|
-
// At line ending, check if we can continue on the next line
|
|
100197
|
-
if (markdownLineEnding(code)) {
|
|
100198
|
-
effects.exit('magicBlockData');
|
|
100199
|
-
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100200
|
-
}
|
|
100201
|
-
if (jsonState.escapeNext) {
|
|
100202
|
-
jsonState.escapeNext = false;
|
|
100203
|
-
effects.consume(code);
|
|
100204
|
-
return captureData;
|
|
100205
|
-
}
|
|
100206
|
-
if (jsonState.inString) {
|
|
100207
|
-
if (code === codes.backslash) {
|
|
100208
|
-
jsonState.escapeNext = true;
|
|
100209
|
-
effects.consume(code);
|
|
100210
|
-
return captureData;
|
|
100211
|
-
}
|
|
100212
|
-
if (code === codes.quotationMark) {
|
|
100213
|
-
jsonState.inString = false;
|
|
100214
|
-
}
|
|
100215
|
-
effects.consume(code);
|
|
100216
|
-
return captureData;
|
|
100217
|
-
}
|
|
100218
|
-
if (code === codes.quotationMark) {
|
|
100219
|
-
jsonState.inString = true;
|
|
100220
|
-
effects.consume(code);
|
|
100221
|
-
return captureData;
|
|
100222
|
-
}
|
|
100223
|
-
if (code === codes.leftSquareBracket) {
|
|
100224
|
-
effects.exit('magicBlockData');
|
|
100225
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100226
|
-
effects.consume(code);
|
|
100227
|
-
return expectSlash;
|
|
100228
|
-
}
|
|
100229
|
-
effects.consume(code);
|
|
100230
|
-
return captureData;
|
|
100231
|
-
}
|
|
100232
|
-
/**
|
|
100233
|
-
* Called when non-lazy continuation check passes - we can continue parsing.
|
|
100234
|
-
*/
|
|
100235
|
-
function continuationOk(code) {
|
|
100236
|
-
// Consume the line ending
|
|
100237
|
-
effects.enter('magicBlockLineEnding');
|
|
100238
|
-
effects.consume(code);
|
|
100239
|
-
effects.exit('magicBlockLineEnding');
|
|
100240
|
-
return continuationStart;
|
|
100241
|
-
}
|
|
100242
|
-
/**
|
|
100243
|
-
* Start of continuation line - check for more line endings, closing marker, or start capturing data.
|
|
100244
|
-
*/
|
|
100245
|
-
function continuationStart(code) {
|
|
100246
|
-
// Handle consecutive line endings
|
|
100247
|
-
if (code === null) {
|
|
100248
|
-
effects.exit('magicBlock');
|
|
100249
|
-
return nok(code);
|
|
100250
|
-
}
|
|
100251
|
-
if (markdownLineEnding(code)) {
|
|
100252
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100253
|
-
}
|
|
100254
|
-
// Check if this is the start of the closing marker [/block]
|
|
100255
|
-
// If so, handle it directly without entering magicBlockData
|
|
100256
|
-
if (code === codes.leftSquareBracket) {
|
|
100257
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100258
|
-
effects.consume(code);
|
|
100259
|
-
return expectSlashFromContinuation;
|
|
100260
|
-
}
|
|
100261
|
-
effects.enter('magicBlockData');
|
|
100262
|
-
return captureData(code);
|
|
100263
|
-
}
|
|
100264
|
-
/**
|
|
100265
|
-
* Check for closing marker slash when coming from continuation.
|
|
100266
|
-
* If not a closing marker, create an empty data token and continue.
|
|
100267
|
-
*/
|
|
100268
|
-
function expectSlashFromContinuation(code) {
|
|
100269
|
-
if (code === null) {
|
|
100270
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100271
|
-
effects.exit('magicBlock');
|
|
100272
|
-
return nok(code);
|
|
100273
|
-
}
|
|
100274
|
-
if (markdownLineEnding(code)) {
|
|
100275
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100276
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100277
|
-
}
|
|
100278
|
-
if (code === codes.slash) {
|
|
100279
|
-
effects.consume(code);
|
|
100280
|
-
return expectClosingB;
|
|
100281
|
-
}
|
|
100282
|
-
// Not a closing marker - this is data content
|
|
100283
|
-
// Exit marker and enter data
|
|
100284
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100285
|
-
effects.enter('magicBlockData');
|
|
100286
|
-
// The [ was consumed by the marker, so we need to conceptually "have it" in our data
|
|
100287
|
-
// But since we already consumed it into the marker, we need a different approach
|
|
100288
|
-
// Re-classify: consume this character as data and continue
|
|
100289
|
-
if (code === codes.quotationMark)
|
|
100290
|
-
jsonState.inString = true;
|
|
100291
|
-
effects.consume(code);
|
|
100292
|
-
return captureData;
|
|
100293
|
-
}
|
|
100294
|
-
function expectSlash(code) {
|
|
100295
|
-
if (code === null) {
|
|
100296
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100297
|
-
effects.exit('magicBlock');
|
|
100298
|
-
return nok(code);
|
|
100299
|
-
}
|
|
100300
|
-
// At line ending during marker parsing
|
|
100301
|
-
if (markdownLineEnding(code)) {
|
|
100302
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100303
|
-
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100304
|
-
}
|
|
100305
|
-
if (code !== codes.slash) {
|
|
100306
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100307
|
-
effects.enter('magicBlockData');
|
|
100308
|
-
if (code === codes.quotationMark)
|
|
100309
|
-
jsonState.inString = true;
|
|
100310
|
-
effects.consume(code);
|
|
100311
|
-
return captureData;
|
|
100312
|
-
}
|
|
100313
|
-
effects.consume(code);
|
|
100314
|
-
return expectClosingB;
|
|
100315
|
-
}
|
|
100316
|
-
function expectClosingB(code) {
|
|
100317
|
-
if (code === null) {
|
|
100318
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100319
|
-
effects.exit('magicBlock');
|
|
100320
|
-
return nok(code);
|
|
100321
|
-
}
|
|
100322
|
-
if (code !== codes.lowercaseB) {
|
|
100323
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100324
|
-
effects.enter('magicBlockData');
|
|
100325
|
-
if (code === codes.quotationMark)
|
|
100326
|
-
jsonState.inString = true;
|
|
100327
|
-
effects.consume(code);
|
|
100328
|
-
return captureData;
|
|
100329
|
-
}
|
|
100330
|
-
effects.consume(code);
|
|
100331
|
-
return expectClosingL;
|
|
100332
|
-
}
|
|
100333
|
-
function expectClosingL(code) {
|
|
100334
|
-
if (code === null) {
|
|
100335
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100336
|
-
effects.exit('magicBlock');
|
|
100337
|
-
return nok(code);
|
|
100338
|
-
}
|
|
100339
|
-
if (code !== codes.lowercaseL) {
|
|
100340
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100341
|
-
effects.enter('magicBlockData');
|
|
100342
|
-
if (code === codes.quotationMark)
|
|
100343
|
-
jsonState.inString = true;
|
|
100344
|
-
effects.consume(code);
|
|
100345
|
-
return captureData;
|
|
100346
|
-
}
|
|
100347
|
-
effects.consume(code);
|
|
100348
|
-
return expectClosingO;
|
|
100349
|
-
}
|
|
100350
|
-
function expectClosingO(code) {
|
|
100351
|
-
if (code === null) {
|
|
100352
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100353
|
-
effects.exit('magicBlock');
|
|
100354
|
-
return nok(code);
|
|
100355
|
-
}
|
|
100356
|
-
if (code !== codes.lowercaseO) {
|
|
100357
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100358
|
-
effects.enter('magicBlockData');
|
|
100359
|
-
if (code === codes.quotationMark)
|
|
100360
|
-
jsonState.inString = true;
|
|
100361
|
-
effects.consume(code);
|
|
100362
|
-
return captureData;
|
|
100363
|
-
}
|
|
100364
|
-
effects.consume(code);
|
|
100365
|
-
return expectClosingC;
|
|
100366
|
-
}
|
|
100367
|
-
function expectClosingC(code) {
|
|
100368
|
-
if (code === null) {
|
|
100369
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100370
|
-
effects.exit('magicBlock');
|
|
100371
|
-
return nok(code);
|
|
100372
|
-
}
|
|
100373
|
-
if (code !== codes.lowercaseC) {
|
|
100374
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100375
|
-
effects.enter('magicBlockData');
|
|
100376
|
-
if (code === codes.quotationMark)
|
|
100377
|
-
jsonState.inString = true;
|
|
100378
|
-
effects.consume(code);
|
|
100379
|
-
return captureData;
|
|
100380
|
-
}
|
|
100381
|
-
effects.consume(code);
|
|
100382
|
-
return expectClosingK;
|
|
100383
|
-
}
|
|
100384
|
-
function expectClosingK(code) {
|
|
100385
|
-
if (code === null) {
|
|
100386
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100387
|
-
effects.exit('magicBlock');
|
|
100388
|
-
return nok(code);
|
|
100389
|
-
}
|
|
100390
|
-
if (code !== codes.lowercaseK) {
|
|
100391
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100392
|
-
effects.enter('magicBlockData');
|
|
100393
|
-
if (code === codes.quotationMark)
|
|
100394
|
-
jsonState.inString = true;
|
|
100395
|
-
effects.consume(code);
|
|
100396
|
-
return captureData;
|
|
100397
|
-
}
|
|
100398
|
-
effects.consume(code);
|
|
100399
|
-
return expectClosingBracket;
|
|
100400
|
-
}
|
|
100401
|
-
function expectClosingBracket(code) {
|
|
100402
|
-
if (code === null) {
|
|
100403
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100404
|
-
effects.exit('magicBlock');
|
|
100405
|
-
return nok(code);
|
|
100406
|
-
}
|
|
100407
|
-
if (code !== codes.rightSquareBracket) {
|
|
100408
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100409
|
-
effects.enter('magicBlockData');
|
|
100410
|
-
if (code === codes.quotationMark)
|
|
100411
|
-
jsonState.inString = true;
|
|
100412
|
-
effects.consume(code);
|
|
100413
|
-
return captureData;
|
|
100414
|
-
}
|
|
100415
|
-
effects.consume(code);
|
|
100416
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100417
|
-
// Check for trailing whitespace on the same line
|
|
100418
|
-
return consumeTrailing;
|
|
100419
|
-
}
|
|
100420
|
-
/**
|
|
100421
|
-
* Consume trailing whitespace (spaces/tabs) on the same line after [/block].
|
|
100422
|
-
* For concrete flow constructs, we must end at eol/eof or fail.
|
|
100423
|
-
* Trailing whitespace is consumed; other content causes nok (text tokenizer handles it).
|
|
100424
|
-
*/
|
|
100425
|
-
function consumeTrailing(code) {
|
|
100426
|
-
// End of file - done
|
|
100427
|
-
if (code === null) {
|
|
100428
|
-
effects.exit('magicBlock');
|
|
100429
|
-
return ok(code);
|
|
100430
|
-
}
|
|
100431
|
-
// Line ending - done
|
|
100432
|
-
if (markdownLineEnding(code)) {
|
|
100433
|
-
effects.exit('magicBlock');
|
|
100434
|
-
return ok(code);
|
|
100435
|
-
}
|
|
100436
|
-
// Space or tab - consume as trailing whitespace
|
|
100437
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100438
|
-
effects.enter('magicBlockTrailing');
|
|
100439
|
-
effects.consume(code);
|
|
100440
|
-
return consumeTrailingContinue;
|
|
100441
|
-
}
|
|
100442
|
-
// Any other character - fail flow tokenizer, let text tokenizer handle it
|
|
100443
|
-
effects.exit('magicBlock');
|
|
100444
|
-
return nok(code);
|
|
100445
|
-
}
|
|
100446
|
-
/**
|
|
100447
|
-
* Continue consuming trailing whitespace.
|
|
100448
|
-
*/
|
|
100449
|
-
function consumeTrailingContinue(code) {
|
|
100450
|
-
// End of file - done
|
|
100451
|
-
if (code === null) {
|
|
100452
|
-
effects.exit('magicBlockTrailing');
|
|
100453
|
-
effects.exit('magicBlock');
|
|
100454
|
-
return ok(code);
|
|
100455
|
-
}
|
|
100456
|
-
// Line ending - done
|
|
100457
|
-
if (markdownLineEnding(code)) {
|
|
100458
|
-
effects.exit('magicBlockTrailing');
|
|
100459
|
-
effects.exit('magicBlock');
|
|
100460
|
-
return ok(code);
|
|
100461
|
-
}
|
|
100462
|
-
// More space or tab - keep consuming
|
|
100463
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100464
|
-
effects.consume(code);
|
|
100465
|
-
return consumeTrailingContinue;
|
|
100466
|
-
}
|
|
100467
|
-
// Non-whitespace after whitespace - fail flow tokenizer
|
|
100468
|
-
effects.exit('magicBlockTrailing');
|
|
100469
|
-
effects.exit('magicBlock');
|
|
100470
|
-
return nok(code);
|
|
100471
|
-
}
|
|
100472
|
-
/**
|
|
100473
|
-
* Called when we can't continue (lazy line or EOF) - exit the construct.
|
|
100474
|
-
*/
|
|
100475
|
-
function after(code) {
|
|
100476
|
-
effects.exit('magicBlock');
|
|
100477
|
-
return nok(code);
|
|
100478
|
-
}
|
|
100479
|
-
}
|
|
100480
|
-
/**
|
|
100481
|
-
* Text tokenizer for single-line magic blocks only.
|
|
100482
|
-
* Used in inline contexts like list items and paragraphs.
|
|
100483
|
-
* Multiline blocks are handled by the flow tokenizer.
|
|
100484
|
-
*/
|
|
100485
|
-
function tokenizeMagicBlockText(effects, ok, nok) {
|
|
100486
|
-
// State for tracking JSON content
|
|
100487
|
-
const jsonState = { escapeNext: false, inString: false };
|
|
100488
|
-
const blockTypeRef = { value: '' };
|
|
100489
|
-
let seenOpenBrace = false;
|
|
100490
|
-
// Create shared parsers for opening marker and type capture
|
|
100491
|
-
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
100492
|
-
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
100493
|
-
// Success handler for closing marker - exits tokens and returns ok
|
|
100494
|
-
const closingSuccess = (code) => {
|
|
100495
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100496
|
-
effects.exit('magicBlock');
|
|
100497
|
-
return ok(code);
|
|
100498
|
-
};
|
|
100499
|
-
// Mismatch handler - falls back to data capture
|
|
100500
|
-
const closingMismatch = (code) => {
|
|
100501
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100502
|
-
effects.enter('magicBlockData');
|
|
100503
|
-
if (code === codes.quotationMark)
|
|
100504
|
-
jsonState.inString = true;
|
|
100505
|
-
effects.consume(code);
|
|
100506
|
-
return captureData;
|
|
100507
|
-
};
|
|
100508
|
-
// EOF handler
|
|
100509
|
-
const closingEof = (_code) => nok(_code);
|
|
100510
|
-
// Create closing marker parsers
|
|
100511
|
-
const closingFromBeforeData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
100512
|
-
const closingFromData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
100513
|
-
return start;
|
|
100514
|
-
function start(code) {
|
|
100515
|
-
if (code !== codes.leftSquareBracket)
|
|
100516
|
-
return nok(code);
|
|
100517
|
-
effects.enter('magicBlock');
|
|
100518
|
-
effects.enter('magicBlockMarkerStart');
|
|
100519
|
-
effects.consume(code);
|
|
100520
|
-
return openingMarkerParser;
|
|
100521
|
-
}
|
|
100522
|
-
/**
|
|
100523
|
-
* State before data content - handles line endings before entering data token.
|
|
100524
|
-
* Whitespace before '{' is allowed.
|
|
100525
|
-
*/
|
|
100526
|
-
function beforeData(code) {
|
|
100527
|
-
// Fail on EOF - magic block must be closed
|
|
100528
|
-
if (code === null) {
|
|
100529
|
-
return nok(code);
|
|
100530
|
-
}
|
|
100531
|
-
// Handle line endings before any data - consume them without entering data token
|
|
100532
|
-
if (markdownLineEnding(code)) {
|
|
100533
|
-
effects.enter('magicBlockLineEnding');
|
|
100534
|
-
effects.consume(code);
|
|
100535
|
-
effects.exit('magicBlockLineEnding');
|
|
100536
|
-
return beforeData;
|
|
100537
|
-
}
|
|
100538
|
-
// Check for closing marker directly (without entering data)
|
|
100539
|
-
if (code === codes.leftSquareBracket) {
|
|
100540
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100541
|
-
effects.consume(code);
|
|
100542
|
-
return closingFromBeforeData.expectSlash;
|
|
100543
|
-
}
|
|
100544
|
-
// If we've already seen the opening brace, just continue capturing data
|
|
100545
|
-
if (seenOpenBrace) {
|
|
100546
|
-
effects.enter('magicBlockData');
|
|
100547
|
-
return captureData(code);
|
|
100548
|
-
}
|
|
100549
|
-
// Skip whitespace (spaces/tabs) before the data
|
|
100550
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100551
|
-
return beforeDataWhitespace(code);
|
|
100552
|
-
}
|
|
100553
|
-
// Data must start with '{' for valid JSON
|
|
100554
|
-
if (code !== codes.leftCurlyBrace) {
|
|
100555
|
-
return nok(code);
|
|
100556
|
-
}
|
|
100557
|
-
// We have '{' - enter data token and start capturing
|
|
100558
|
-
seenOpenBrace = true;
|
|
100559
|
-
effects.enter('magicBlockData');
|
|
100560
|
-
return captureData(code);
|
|
100561
|
-
}
|
|
100562
|
-
/**
|
|
100563
|
-
* Consume whitespace before the data.
|
|
100564
|
-
*/
|
|
100565
|
-
function beforeDataWhitespace(code) {
|
|
100566
|
-
if (code === null) {
|
|
100567
|
-
return nok(code);
|
|
100568
|
-
}
|
|
100569
|
-
if (markdownLineEnding(code)) {
|
|
100570
|
-
effects.enter('magicBlockLineEnding');
|
|
100571
|
-
effects.consume(code);
|
|
100572
|
-
effects.exit('magicBlockLineEnding');
|
|
100573
|
-
return beforeData;
|
|
100574
|
-
}
|
|
100575
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100576
|
-
effects.enter('magicBlockData');
|
|
100577
|
-
effects.consume(code);
|
|
100578
|
-
return beforeDataWhitespaceContinue;
|
|
100579
|
-
}
|
|
100580
|
-
if (code === codes.leftCurlyBrace) {
|
|
100581
|
-
seenOpenBrace = true;
|
|
100582
|
-
effects.enter('magicBlockData');
|
|
100583
|
-
return captureData(code);
|
|
100584
|
-
}
|
|
100585
|
-
return nok(code);
|
|
100586
|
-
}
|
|
100587
|
-
/**
|
|
100588
|
-
* Continue consuming whitespace or validate the opening brace.
|
|
100589
|
-
*/
|
|
100590
|
-
function beforeDataWhitespaceContinue(code) {
|
|
100591
|
-
if (code === null) {
|
|
100592
|
-
effects.exit('magicBlockData');
|
|
100593
|
-
return nok(code);
|
|
100594
|
-
}
|
|
100595
|
-
if (markdownLineEnding(code)) {
|
|
100596
|
-
effects.exit('magicBlockData');
|
|
100597
|
-
effects.enter('magicBlockLineEnding');
|
|
100598
|
-
effects.consume(code);
|
|
100599
|
-
effects.exit('magicBlockLineEnding');
|
|
100600
|
-
return beforeData;
|
|
100601
|
-
}
|
|
100602
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100603
|
-
effects.consume(code);
|
|
100604
|
-
return beforeDataWhitespaceContinue;
|
|
100605
|
-
}
|
|
100606
|
-
if (code === codes.leftCurlyBrace) {
|
|
100607
|
-
seenOpenBrace = true;
|
|
100608
|
-
return captureData(code);
|
|
100609
|
-
}
|
|
100610
|
-
effects.exit('magicBlockData');
|
|
100611
|
-
return nok(code);
|
|
100612
|
-
}
|
|
100613
|
-
function captureData(code) {
|
|
100614
|
-
// Fail on EOF - magic block must be closed
|
|
100615
|
-
if (code === null) {
|
|
100616
|
-
effects.exit('magicBlockData');
|
|
100617
|
-
return nok(code);
|
|
100618
|
-
}
|
|
100619
|
-
// Handle multiline magic blocks within text/paragraphs
|
|
100620
|
-
// Exit data, consume line ending with proper token, then re-enter data
|
|
100621
|
-
if (markdownLineEnding(code)) {
|
|
100622
|
-
effects.exit('magicBlockData');
|
|
100623
|
-
effects.enter('magicBlockLineEnding');
|
|
100624
|
-
effects.consume(code);
|
|
100625
|
-
effects.exit('magicBlockLineEnding');
|
|
100626
|
-
return beforeData; // Go back to beforeData to handle potential empty lines
|
|
100627
|
-
}
|
|
100628
|
-
if (jsonState.escapeNext) {
|
|
100629
|
-
jsonState.escapeNext = false;
|
|
100630
|
-
effects.consume(code);
|
|
100631
|
-
return captureData;
|
|
100632
|
-
}
|
|
100633
|
-
if (jsonState.inString) {
|
|
100634
|
-
if (code === codes.backslash) {
|
|
100635
|
-
jsonState.escapeNext = true;
|
|
100636
|
-
effects.consume(code);
|
|
100637
|
-
return captureData;
|
|
100638
|
-
}
|
|
100639
|
-
if (code === codes.quotationMark) {
|
|
100640
|
-
jsonState.inString = false;
|
|
100641
|
-
}
|
|
100642
|
-
effects.consume(code);
|
|
100643
|
-
return captureData;
|
|
100644
|
-
}
|
|
100645
|
-
if (code === codes.quotationMark) {
|
|
100646
|
-
jsonState.inString = true;
|
|
100647
|
-
effects.consume(code);
|
|
100648
|
-
return captureData;
|
|
100649
|
-
}
|
|
100650
|
-
if (code === codes.leftSquareBracket) {
|
|
100651
|
-
effects.exit('magicBlockData');
|
|
100652
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100653
|
-
effects.consume(code);
|
|
100654
|
-
return closingFromData.expectSlash;
|
|
100655
|
-
}
|
|
100656
|
-
effects.consume(code);
|
|
100657
|
-
return captureData;
|
|
100658
|
-
}
|
|
100659
|
-
}
|
|
100660
|
-
/* harmony default export */ const syntax = ((/* unused pure expression or super */ null && (magicBlock)));
|
|
100661
|
-
|
|
100662
|
-
;// ./lib/micromark/magic-block/index.ts
|
|
100663
|
-
/**
|
|
100664
|
-
* Micromark extension for magic block syntax.
|
|
100665
|
-
*
|
|
100666
|
-
* Usage:
|
|
100667
|
-
* ```ts
|
|
100668
|
-
* import { magicBlock } from './lib/micromark/magic-block';
|
|
100669
|
-
*
|
|
100670
|
-
* const processor = unified()
|
|
100671
|
-
* .data('micromarkExtensions', [magicBlock()])
|
|
100672
|
-
* ```
|
|
100673
|
-
*/
|
|
100674
|
-
|
|
100675
|
-
|
|
100676
|
-
;// ./node_modules/micromark-util-symbol/lib/types.js
|
|
100677
|
-
/**
|
|
100678
|
-
* This module is compiled away!
|
|
100679
|
-
*
|
|
100680
|
-
* Here is the list of all types of tokens exposed by micromark, with a short
|
|
100681
|
-
* explanation of what they include and where they are found.
|
|
100682
|
-
* In picking names, generally, the rule is to be as explicit as possible
|
|
100683
|
-
* instead of reusing names.
|
|
100684
|
-
* For example, there is a `definitionDestination` and a `resourceDestination`,
|
|
100685
|
-
* instead of one shared name.
|
|
99913
|
+
* Here is the list of all types of tokens exposed by micromark, with a short
|
|
99914
|
+
* explanation of what they include and where they are found.
|
|
99915
|
+
* In picking names, generally, the rule is to be as explicit as possible
|
|
99916
|
+
* instead of reusing names.
|
|
99917
|
+
* For example, there is a `definitionDestination` and a `resourceDestination`,
|
|
99918
|
+
* instead of one shared name.
|
|
100686
99919
|
*/
|
|
100687
99920
|
|
|
100688
99921
|
// Note: when changing the next record, you must also change `TokenTypeMap`
|
|
@@ -101128,36 +100361,18 @@ const types_types = /** @type {const} */ ({
|
|
|
101128
100361
|
chunkString: 'chunkString'
|
|
101129
100362
|
})
|
|
101130
100363
|
|
|
101131
|
-
;// ./lib/micromark/
|
|
101132
|
-
|
|
101133
|
-
|
|
101134
|
-
|
|
100364
|
+
;// ./lib/micromark/jsx-table/syntax.ts
|
|
101135
100365
|
|
|
101136
100366
|
|
|
101137
|
-
// Raw tags (type-1: pre/script/style/textarea) and block tags (type-6: div,
|
|
101138
|
-
// section, …) always start a block, so they stay flow even with trailing
|
|
101139
|
-
// content. Other lowercase tags (i, span, …) follow the type-7 rule and only
|
|
101140
|
-
// stay flow when nothing trails the close tag.
|
|
101141
|
-
const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
|
|
101142
|
-
// Lowercase type-6 block tags claimable in flow even without a `{…}` attribute, so
|
|
101143
|
-
// blank lines between nested JSX siblings don't fragment the block. Excludes table
|
|
101144
|
-
// tags (mdxishTables owns their blank lines) and voids (never close).
|
|
101145
|
-
const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
|
|
101146
100367
|
const syntax_nonLazyContinuationStart = {
|
|
101147
100368
|
tokenize: syntax_tokenizeNonLazyContinuationStart,
|
|
101148
100369
|
partial: true,
|
|
101149
100370
|
};
|
|
101150
|
-
|
|
101151
|
-
// that merely starts with a tag? Run via `effects.check` so it never consumes.
|
|
101152
|
-
const markupOnlyContinuation = {
|
|
101153
|
-
tokenize: tokenizeMarkupOnlyContinuation,
|
|
101154
|
-
partial: true,
|
|
101155
|
-
};
|
|
101156
|
-
function resolveToMdxComponent(events) {
|
|
100371
|
+
function resolveToJsxTable(events) {
|
|
101157
100372
|
let index = events.length;
|
|
101158
100373
|
while (index > 0) {
|
|
101159
100374
|
index -= 1;
|
|
101160
|
-
if (events[index][0] === 'enter' && events[index][1].type === '
|
|
100375
|
+
if (events[index][0] === 'enter' && events[index][1].type === 'jsxTable') {
|
|
101161
100376
|
break;
|
|
101162
100377
|
}
|
|
101163
100378
|
}
|
|
@@ -101168,49 +100383,1155 @@ function resolveToMdxComponent(events) {
|
|
|
101168
100383
|
}
|
|
101169
100384
|
return events;
|
|
101170
100385
|
}
|
|
101171
|
-
const
|
|
101172
|
-
name: '
|
|
101173
|
-
tokenize:
|
|
101174
|
-
resolveTo:
|
|
100386
|
+
const jsxTableConstruct = {
|
|
100387
|
+
name: 'jsxTable',
|
|
100388
|
+
tokenize: tokenizeJsxTable,
|
|
100389
|
+
resolveTo: resolveToJsxTable,
|
|
101175
100390
|
concrete: true,
|
|
101176
100391
|
};
|
|
101177
|
-
|
|
101178
|
-
|
|
101179
|
-
|
|
101180
|
-
|
|
101181
|
-
|
|
101182
|
-
|
|
101183
|
-
|
|
101184
|
-
|
|
101185
|
-
|
|
101186
|
-
|
|
101187
|
-
|
|
101188
|
-
|
|
101189
|
-
|
|
101190
|
-
|
|
101191
|
-
|
|
101192
|
-
|
|
101193
|
-
|
|
101194
|
-
|
|
101195
|
-
function
|
|
101196
|
-
|
|
101197
|
-
|
|
101198
|
-
|
|
101199
|
-
|
|
101200
|
-
|
|
101201
|
-
|
|
101202
|
-
|
|
101203
|
-
|
|
101204
|
-
|
|
101205
|
-
|
|
101206
|
-
|
|
101207
|
-
|
|
101208
|
-
|
|
101209
|
-
|
|
101210
|
-
|
|
101211
|
-
|
|
101212
|
-
|
|
101213
|
-
|
|
100392
|
+
function tokenizeJsxTable(effects, ok, nok) {
|
|
100393
|
+
let codeSpanOpenSize = 0;
|
|
100394
|
+
let codeSpanCloseSize = 0;
|
|
100395
|
+
let depth = 1;
|
|
100396
|
+
const ABLE_SUFFIX = [codes.lowercaseA, codes.lowercaseB, codes.lowercaseL, codes.lowercaseE];
|
|
100397
|
+
/** Build a state chain that matches a sequence of character codes. */
|
|
100398
|
+
function matchChars(chars, onMatch, onFail) {
|
|
100399
|
+
if (chars.length === 0)
|
|
100400
|
+
return onMatch;
|
|
100401
|
+
return ((code) => {
|
|
100402
|
+
if (code === chars[0]) {
|
|
100403
|
+
effects.consume(code);
|
|
100404
|
+
return matchChars(chars.slice(1), onMatch, onFail);
|
|
100405
|
+
}
|
|
100406
|
+
return onFail(code);
|
|
100407
|
+
});
|
|
100408
|
+
}
|
|
100409
|
+
return start;
|
|
100410
|
+
function start(code) {
|
|
100411
|
+
if (code !== codes.lessThan)
|
|
100412
|
+
return nok(code);
|
|
100413
|
+
effects.enter('jsxTable');
|
|
100414
|
+
effects.enter('jsxTableData');
|
|
100415
|
+
effects.consume(code);
|
|
100416
|
+
return afterLessThan;
|
|
100417
|
+
}
|
|
100418
|
+
function afterLessThan(code) {
|
|
100419
|
+
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
100420
|
+
effects.consume(code);
|
|
100421
|
+
return matchChars(ABLE_SUFFIX, afterTagName, nok);
|
|
100422
|
+
}
|
|
100423
|
+
return nok(code);
|
|
100424
|
+
}
|
|
100425
|
+
function afterTagName(code) {
|
|
100426
|
+
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
100427
|
+
effects.consume(code);
|
|
100428
|
+
return body;
|
|
100429
|
+
}
|
|
100430
|
+
return nok(code);
|
|
100431
|
+
}
|
|
100432
|
+
function body(code) {
|
|
100433
|
+
// Reject unclosed <Table> so it falls back to normal HTML block parsing
|
|
100434
|
+
// instead of swallowing all subsequent content to EOF
|
|
100435
|
+
if (code === null) {
|
|
100436
|
+
return nok(code);
|
|
100437
|
+
}
|
|
100438
|
+
if (markdownLineEnding(code)) {
|
|
100439
|
+
effects.exit('jsxTableData');
|
|
100440
|
+
return continuationStart(code);
|
|
100441
|
+
}
|
|
100442
|
+
if (code === codes.backslash) {
|
|
100443
|
+
effects.consume(code);
|
|
100444
|
+
return escapedChar;
|
|
100445
|
+
}
|
|
100446
|
+
if (code === codes.lessThan) {
|
|
100447
|
+
effects.consume(code);
|
|
100448
|
+
return closeSlash;
|
|
100449
|
+
}
|
|
100450
|
+
// Skip over backtick code spans so `</Table>` in inline code isn't
|
|
100451
|
+
// treated as the closing tag
|
|
100452
|
+
if (code === codes.graveAccent) {
|
|
100453
|
+
codeSpanOpenSize = 0;
|
|
100454
|
+
return countOpenTicks(code);
|
|
100455
|
+
}
|
|
100456
|
+
effects.consume(code);
|
|
100457
|
+
return body;
|
|
100458
|
+
}
|
|
100459
|
+
function countOpenTicks(code) {
|
|
100460
|
+
if (code === codes.graveAccent) {
|
|
100461
|
+
codeSpanOpenSize += 1;
|
|
100462
|
+
effects.consume(code);
|
|
100463
|
+
return countOpenTicks;
|
|
100464
|
+
}
|
|
100465
|
+
return inCodeSpan(code);
|
|
100466
|
+
}
|
|
100467
|
+
function inCodeSpan(code) {
|
|
100468
|
+
if (code === null || markdownLineEnding(code))
|
|
100469
|
+
return body(code);
|
|
100470
|
+
if (code === codes.graveAccent) {
|
|
100471
|
+
codeSpanCloseSize = 0;
|
|
100472
|
+
return countCloseTicks(code);
|
|
100473
|
+
}
|
|
100474
|
+
effects.consume(code);
|
|
100475
|
+
return inCodeSpan;
|
|
100476
|
+
}
|
|
100477
|
+
function countCloseTicks(code) {
|
|
100478
|
+
if (code === codes.graveAccent) {
|
|
100479
|
+
codeSpanCloseSize += 1;
|
|
100480
|
+
effects.consume(code);
|
|
100481
|
+
return countCloseTicks;
|
|
100482
|
+
}
|
|
100483
|
+
return codeSpanCloseSize === codeSpanOpenSize ? body(code) : inCodeSpan(code);
|
|
100484
|
+
}
|
|
100485
|
+
function escapedChar(code) {
|
|
100486
|
+
if (code === null || markdownLineEnding(code)) {
|
|
100487
|
+
return body(code);
|
|
100488
|
+
}
|
|
100489
|
+
effects.consume(code);
|
|
100490
|
+
return body;
|
|
100491
|
+
}
|
|
100492
|
+
function closeSlash(code) {
|
|
100493
|
+
if (code === codes.slash) {
|
|
100494
|
+
effects.consume(code);
|
|
100495
|
+
return closeTagFirstChar;
|
|
100496
|
+
}
|
|
100497
|
+
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
100498
|
+
effects.consume(code);
|
|
100499
|
+
return matchChars(ABLE_SUFFIX, openAfterTagName, body);
|
|
100500
|
+
}
|
|
100501
|
+
return body(code);
|
|
100502
|
+
}
|
|
100503
|
+
function closeTagFirstChar(code) {
|
|
100504
|
+
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
100505
|
+
effects.consume(code);
|
|
100506
|
+
return matchChars(ABLE_SUFFIX, closeGt, body);
|
|
100507
|
+
}
|
|
100508
|
+
return body(code);
|
|
100509
|
+
}
|
|
100510
|
+
function openAfterTagName(code) {
|
|
100511
|
+
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
100512
|
+
depth += 1;
|
|
100513
|
+
effects.consume(code);
|
|
100514
|
+
return body;
|
|
100515
|
+
}
|
|
100516
|
+
return body(code);
|
|
100517
|
+
}
|
|
100518
|
+
function closeGt(code) {
|
|
100519
|
+
if (code === codes.greaterThan) {
|
|
100520
|
+
depth -= 1;
|
|
100521
|
+
effects.consume(code);
|
|
100522
|
+
if (depth === 0) {
|
|
100523
|
+
return afterClose;
|
|
100524
|
+
}
|
|
100525
|
+
return body;
|
|
100526
|
+
}
|
|
100527
|
+
return body(code);
|
|
100528
|
+
}
|
|
100529
|
+
function afterClose(code) {
|
|
100530
|
+
if (code === null || markdownLineEnding(code)) {
|
|
100531
|
+
effects.exit('jsxTableData');
|
|
100532
|
+
effects.exit('jsxTable');
|
|
100533
|
+
return ok(code);
|
|
100534
|
+
}
|
|
100535
|
+
effects.consume(code);
|
|
100536
|
+
return afterClose;
|
|
100537
|
+
}
|
|
100538
|
+
// Line ending handling — follows the htmlFlow pattern
|
|
100539
|
+
function continuationStart(code) {
|
|
100540
|
+
return effects.check(syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
100541
|
+
}
|
|
100542
|
+
function continuationStartNonLazy(code) {
|
|
100543
|
+
effects.enter(types_types.lineEnding);
|
|
100544
|
+
effects.consume(code);
|
|
100545
|
+
effects.exit(types_types.lineEnding);
|
|
100546
|
+
return continuationBefore;
|
|
100547
|
+
}
|
|
100548
|
+
function continuationBefore(code) {
|
|
100549
|
+
if (code === null || markdownLineEnding(code)) {
|
|
100550
|
+
return continuationStart(code);
|
|
100551
|
+
}
|
|
100552
|
+
effects.enter('jsxTableData');
|
|
100553
|
+
return body(code);
|
|
100554
|
+
}
|
|
100555
|
+
function continuationAfter(code) {
|
|
100556
|
+
// At EOF without </Table>, reject so content isn't swallowed
|
|
100557
|
+
if (code === null) {
|
|
100558
|
+
return nok(code);
|
|
100559
|
+
}
|
|
100560
|
+
effects.exit('jsxTable');
|
|
100561
|
+
return ok(code);
|
|
100562
|
+
}
|
|
100563
|
+
}
|
|
100564
|
+
function syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
100565
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
100566
|
+
const self = this;
|
|
100567
|
+
return start;
|
|
100568
|
+
function start(code) {
|
|
100569
|
+
if (markdownLineEnding(code)) {
|
|
100570
|
+
effects.enter(types_types.lineEnding);
|
|
100571
|
+
effects.consume(code);
|
|
100572
|
+
effects.exit(types_types.lineEnding);
|
|
100573
|
+
return after;
|
|
100574
|
+
}
|
|
100575
|
+
return nok(code);
|
|
100576
|
+
}
|
|
100577
|
+
function after(code) {
|
|
100578
|
+
if (self.parser.lazy[self.now().line]) {
|
|
100579
|
+
return nok(code);
|
|
100580
|
+
}
|
|
100581
|
+
return ok(code);
|
|
100582
|
+
}
|
|
100583
|
+
}
|
|
100584
|
+
/**
|
|
100585
|
+
* Micromark extension that tokenizes `<Table>...</Table>` and `<table>...</table>`
|
|
100586
|
+
* as a single flow block.
|
|
100587
|
+
*
|
|
100588
|
+
* Prevents CommonMark HTML block type 6 from fragmenting table blocks at blank lines.
|
|
100589
|
+
*/
|
|
100590
|
+
function jsxTable() {
|
|
100591
|
+
return {
|
|
100592
|
+
flow: {
|
|
100593
|
+
[codes.lessThan]: [jsxTableConstruct],
|
|
100594
|
+
},
|
|
100595
|
+
};
|
|
100596
|
+
}
|
|
100597
|
+
|
|
100598
|
+
;// ./lib/micromark/jsx-table/index.ts
|
|
100599
|
+
|
|
100600
|
+
|
|
100601
|
+
;// ./lib/micromark/magic-block/syntax.ts
|
|
100602
|
+
|
|
100603
|
+
|
|
100604
|
+
/**
|
|
100605
|
+
* Known magic block types that the tokenizer will recognize.
|
|
100606
|
+
* Unknown types will not be tokenized as magic blocks.
|
|
100607
|
+
*/
|
|
100608
|
+
const KNOWN_BLOCK_TYPES = new Set([
|
|
100609
|
+
'code',
|
|
100610
|
+
'api-header',
|
|
100611
|
+
'image',
|
|
100612
|
+
'callout',
|
|
100613
|
+
'parameters',
|
|
100614
|
+
'table',
|
|
100615
|
+
'embed',
|
|
100616
|
+
'html',
|
|
100617
|
+
'recipe',
|
|
100618
|
+
'tutorial-tile',
|
|
100619
|
+
]);
|
|
100620
|
+
/**
|
|
100621
|
+
* Check if a character is valid for a magic block type identifier.
|
|
100622
|
+
* Types can contain alphanumeric characters and hyphens (e.g., "api-header", "tutorial-tile")
|
|
100623
|
+
*/
|
|
100624
|
+
function isTypeChar(code) {
|
|
100625
|
+
return asciiAlphanumeric(code) || code === codes.dash;
|
|
100626
|
+
}
|
|
100627
|
+
/**
|
|
100628
|
+
* Creates the opening marker state machine: [block:
|
|
100629
|
+
* Returns the first state function to start parsing.
|
|
100630
|
+
*/
|
|
100631
|
+
function createOpeningMarkerParser(effects, nok, onComplete) {
|
|
100632
|
+
const expectB = (code) => {
|
|
100633
|
+
if (code !== codes.lowercaseB)
|
|
100634
|
+
return nok(code);
|
|
100635
|
+
effects.consume(code);
|
|
100636
|
+
return expectL;
|
|
100637
|
+
};
|
|
100638
|
+
const expectL = (code) => {
|
|
100639
|
+
if (code !== codes.lowercaseL)
|
|
100640
|
+
return nok(code);
|
|
100641
|
+
effects.consume(code);
|
|
100642
|
+
return expectO;
|
|
100643
|
+
};
|
|
100644
|
+
const expectO = (code) => {
|
|
100645
|
+
if (code !== codes.lowercaseO)
|
|
100646
|
+
return nok(code);
|
|
100647
|
+
effects.consume(code);
|
|
100648
|
+
return expectC;
|
|
100649
|
+
};
|
|
100650
|
+
const expectC = (code) => {
|
|
100651
|
+
if (code !== codes.lowercaseC)
|
|
100652
|
+
return nok(code);
|
|
100653
|
+
effects.consume(code);
|
|
100654
|
+
return expectK;
|
|
100655
|
+
};
|
|
100656
|
+
const expectK = (code) => {
|
|
100657
|
+
if (code !== codes.lowercaseK)
|
|
100658
|
+
return nok(code);
|
|
100659
|
+
effects.consume(code);
|
|
100660
|
+
return expectColon;
|
|
100661
|
+
};
|
|
100662
|
+
const expectColon = (code) => {
|
|
100663
|
+
if (code !== codes.colon)
|
|
100664
|
+
return nok(code);
|
|
100665
|
+
effects.consume(code);
|
|
100666
|
+
effects.exit('magicBlockMarkerStart');
|
|
100667
|
+
effects.enter('magicBlockType');
|
|
100668
|
+
return onComplete;
|
|
100669
|
+
};
|
|
100670
|
+
return expectB;
|
|
100671
|
+
}
|
|
100672
|
+
/**
|
|
100673
|
+
* Creates the type capture state machine.
|
|
100674
|
+
* Captures type characters until ] and validates against known types.
|
|
100675
|
+
*/
|
|
100676
|
+
function createTypeCaptureParser(effects, nok, onComplete, blockTypeRef) {
|
|
100677
|
+
const captureTypeFirst = (code) => {
|
|
100678
|
+
// Reject empty type name [block:]
|
|
100679
|
+
if (code === codes.rightSquareBracket) {
|
|
100680
|
+
return nok(code);
|
|
100681
|
+
}
|
|
100682
|
+
if (isTypeChar(code)) {
|
|
100683
|
+
blockTypeRef.value += String.fromCharCode(code);
|
|
100684
|
+
effects.consume(code);
|
|
100685
|
+
return captureType;
|
|
100686
|
+
}
|
|
100687
|
+
return nok(code);
|
|
100688
|
+
};
|
|
100689
|
+
const captureType = (code) => {
|
|
100690
|
+
if (code === codes.rightSquareBracket) {
|
|
100691
|
+
if (!KNOWN_BLOCK_TYPES.has(blockTypeRef.value)) {
|
|
100692
|
+
return nok(code);
|
|
100693
|
+
}
|
|
100694
|
+
effects.exit('magicBlockType');
|
|
100695
|
+
effects.enter('magicBlockMarkerTypeEnd');
|
|
100696
|
+
effects.consume(code);
|
|
100697
|
+
effects.exit('magicBlockMarkerTypeEnd');
|
|
100698
|
+
return onComplete;
|
|
100699
|
+
}
|
|
100700
|
+
if (isTypeChar(code)) {
|
|
100701
|
+
blockTypeRef.value += String.fromCharCode(code);
|
|
100702
|
+
effects.consume(code);
|
|
100703
|
+
return captureType;
|
|
100704
|
+
}
|
|
100705
|
+
return nok(code);
|
|
100706
|
+
};
|
|
100707
|
+
return { first: captureTypeFirst, remaining: captureType };
|
|
100708
|
+
}
|
|
100709
|
+
/**
|
|
100710
|
+
* Creates the closing marker state machine: /block]
|
|
100711
|
+
* Handles partial matches by calling onMismatch to fall back to data capture.
|
|
100712
|
+
*/
|
|
100713
|
+
function createClosingMarkerParser(effects, onSuccess, onMismatch, onEof, jsonState) {
|
|
100714
|
+
const handleMismatch = (code) => {
|
|
100715
|
+
if (jsonState && code === codes.quotationMark) {
|
|
100716
|
+
jsonState.inString = true;
|
|
100717
|
+
}
|
|
100718
|
+
return onMismatch(code);
|
|
100719
|
+
};
|
|
100720
|
+
const expectSlash = (code) => {
|
|
100721
|
+
if (code === null)
|
|
100722
|
+
return onEof(code);
|
|
100723
|
+
if (code !== codes.slash)
|
|
100724
|
+
return handleMismatch(code);
|
|
100725
|
+
effects.consume(code);
|
|
100726
|
+
return expectB;
|
|
100727
|
+
};
|
|
100728
|
+
const expectB = (code) => {
|
|
100729
|
+
if (code === null)
|
|
100730
|
+
return onEof(code);
|
|
100731
|
+
if (code !== codes.lowercaseB)
|
|
100732
|
+
return handleMismatch(code);
|
|
100733
|
+
effects.consume(code);
|
|
100734
|
+
return expectL;
|
|
100735
|
+
};
|
|
100736
|
+
const expectL = (code) => {
|
|
100737
|
+
if (code === null)
|
|
100738
|
+
return onEof(code);
|
|
100739
|
+
if (code !== codes.lowercaseL)
|
|
100740
|
+
return handleMismatch(code);
|
|
100741
|
+
effects.consume(code);
|
|
100742
|
+
return expectO;
|
|
100743
|
+
};
|
|
100744
|
+
const expectO = (code) => {
|
|
100745
|
+
if (code === null)
|
|
100746
|
+
return onEof(code);
|
|
100747
|
+
if (code !== codes.lowercaseO)
|
|
100748
|
+
return handleMismatch(code);
|
|
100749
|
+
effects.consume(code);
|
|
100750
|
+
return expectC;
|
|
100751
|
+
};
|
|
100752
|
+
const expectC = (code) => {
|
|
100753
|
+
if (code === null)
|
|
100754
|
+
return onEof(code);
|
|
100755
|
+
if (code !== codes.lowercaseC)
|
|
100756
|
+
return handleMismatch(code);
|
|
100757
|
+
effects.consume(code);
|
|
100758
|
+
return expectK;
|
|
100759
|
+
};
|
|
100760
|
+
const expectK = (code) => {
|
|
100761
|
+
if (code === null)
|
|
100762
|
+
return onEof(code);
|
|
100763
|
+
if (code !== codes.lowercaseK)
|
|
100764
|
+
return handleMismatch(code);
|
|
100765
|
+
effects.consume(code);
|
|
100766
|
+
return expectBracket;
|
|
100767
|
+
};
|
|
100768
|
+
const expectBracket = (code) => {
|
|
100769
|
+
if (code === null)
|
|
100770
|
+
return onEof(code);
|
|
100771
|
+
if (code !== codes.rightSquareBracket)
|
|
100772
|
+
return handleMismatch(code);
|
|
100773
|
+
effects.consume(code);
|
|
100774
|
+
return onSuccess;
|
|
100775
|
+
};
|
|
100776
|
+
return { expectSlash };
|
|
100777
|
+
}
|
|
100778
|
+
/**
|
|
100779
|
+
* Partial construct for checking non-lazy continuation.
|
|
100780
|
+
* This is used by the flow tokenizer to check if we can continue
|
|
100781
|
+
* parsing on the next line.
|
|
100782
|
+
*/
|
|
100783
|
+
const syntax_nonLazyContinuation = {
|
|
100784
|
+
partial: true,
|
|
100785
|
+
tokenize: syntax_tokenizeNonLazyContinuation,
|
|
100786
|
+
};
|
|
100787
|
+
/**
|
|
100788
|
+
* Tokenizer for non-lazy continuation checking.
|
|
100789
|
+
* Returns ok if the next line is non-lazy (can continue), nok if lazy.
|
|
100790
|
+
*/
|
|
100791
|
+
function syntax_tokenizeNonLazyContinuation(effects, ok, nok) {
|
|
100792
|
+
const lineStart = (code) => {
|
|
100793
|
+
// `this` here refers to the micromark parser
|
|
100794
|
+
// since we are just passing functions as references and not actually calling them
|
|
100795
|
+
// micromarks's internal parser will call this automatically with appropriate arguments
|
|
100796
|
+
return this.parser.lazy[this.now().line] ? nok(code) : ok(code);
|
|
100797
|
+
};
|
|
100798
|
+
const start = (code) => {
|
|
100799
|
+
if (code === null) {
|
|
100800
|
+
return nok(code);
|
|
100801
|
+
}
|
|
100802
|
+
if (!markdownLineEnding(code)) {
|
|
100803
|
+
return nok(code);
|
|
100804
|
+
}
|
|
100805
|
+
effects.enter('magicBlockLineEnding');
|
|
100806
|
+
effects.consume(code);
|
|
100807
|
+
effects.exit('magicBlockLineEnding');
|
|
100808
|
+
return lineStart;
|
|
100809
|
+
};
|
|
100810
|
+
return start;
|
|
100811
|
+
}
|
|
100812
|
+
/**
|
|
100813
|
+
* Create a micromark extension for magic block syntax.
|
|
100814
|
+
*
|
|
100815
|
+
* This extension handles both single-line and multiline magic blocks:
|
|
100816
|
+
* - Flow construct (concrete): Handles block-level multiline magic blocks at document level
|
|
100817
|
+
* - Text construct: Handles inline magic blocks in lists, paragraphs, etc.
|
|
100818
|
+
*
|
|
100819
|
+
* The flow construct is marked as "concrete" which prevents it from being
|
|
100820
|
+
* interrupted by container markers (like `>` for blockquotes or `-` for lists).
|
|
100821
|
+
*/
|
|
100822
|
+
function magicBlock() {
|
|
100823
|
+
return {
|
|
100824
|
+
// Flow construct - handles block-level magic blocks at document root
|
|
100825
|
+
// Marked as concrete to prevent interruption by containers
|
|
100826
|
+
flow: {
|
|
100827
|
+
[codes.leftSquareBracket]: {
|
|
100828
|
+
name: 'magicBlock',
|
|
100829
|
+
concrete: true,
|
|
100830
|
+
tokenize: tokenizeMagicBlockFlow,
|
|
100831
|
+
},
|
|
100832
|
+
},
|
|
100833
|
+
// Text construct - handles magic blocks in inline contexts (lists, paragraphs)
|
|
100834
|
+
text: {
|
|
100835
|
+
[codes.leftSquareBracket]: {
|
|
100836
|
+
name: 'magicBlock',
|
|
100837
|
+
tokenize: tokenizeMagicBlockText,
|
|
100838
|
+
},
|
|
100839
|
+
},
|
|
100840
|
+
};
|
|
100841
|
+
}
|
|
100842
|
+
/**
|
|
100843
|
+
* Flow tokenizer for block-level magic blocks (multiline).
|
|
100844
|
+
* Uses the continuation checking pattern from code fences.
|
|
100845
|
+
*/
|
|
100846
|
+
function tokenizeMagicBlockFlow(effects, ok, nok) {
|
|
100847
|
+
// State for tracking JSON content
|
|
100848
|
+
const jsonState = { escapeNext: false, inString: false };
|
|
100849
|
+
const blockTypeRef = { value: '' };
|
|
100850
|
+
let seenOpenBrace = false;
|
|
100851
|
+
// Create shared parsers for opening marker and type capture
|
|
100852
|
+
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
100853
|
+
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
100854
|
+
return start;
|
|
100855
|
+
function start(code) {
|
|
100856
|
+
if (code !== codes.leftSquareBracket)
|
|
100857
|
+
return nok(code);
|
|
100858
|
+
effects.enter('magicBlock');
|
|
100859
|
+
effects.enter('magicBlockMarkerStart');
|
|
100860
|
+
effects.consume(code);
|
|
100861
|
+
return openingMarkerParser;
|
|
100862
|
+
}
|
|
100863
|
+
/**
|
|
100864
|
+
* State before data content - handles line endings or starts data capture.
|
|
100865
|
+
*/
|
|
100866
|
+
function beforeData(code) {
|
|
100867
|
+
// EOF - magic block must be closed
|
|
100868
|
+
if (code === null) {
|
|
100869
|
+
effects.exit('magicBlock');
|
|
100870
|
+
return nok(code);
|
|
100871
|
+
}
|
|
100872
|
+
// Line ending before any data - check continuation
|
|
100873
|
+
if (markdownLineEnding(code)) {
|
|
100874
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100875
|
+
}
|
|
100876
|
+
// Check for closing marker directly (without entering data)
|
|
100877
|
+
// This handles cases like [block:type]\n{}\n\n[/block] where there are
|
|
100878
|
+
// newlines after the data object
|
|
100879
|
+
if (code === codes.leftSquareBracket) {
|
|
100880
|
+
effects.enter('magicBlockMarkerEnd');
|
|
100881
|
+
effects.consume(code);
|
|
100882
|
+
return expectSlashFromContinuation;
|
|
100883
|
+
}
|
|
100884
|
+
// If we've already seen the opening brace, just continue capturing data
|
|
100885
|
+
if (seenOpenBrace) {
|
|
100886
|
+
effects.enter('magicBlockData');
|
|
100887
|
+
return captureData(code);
|
|
100888
|
+
}
|
|
100889
|
+
// Skip whitespace (spaces/tabs) before the data - stay in beforeData
|
|
100890
|
+
// Don't enter magicBlockData token yet until we confirm there's a '{'
|
|
100891
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
100892
|
+
return beforeDataWhitespace(code);
|
|
100893
|
+
}
|
|
100894
|
+
// Data must start with '{' for valid JSON
|
|
100895
|
+
if (code !== codes.leftCurlyBrace) {
|
|
100896
|
+
effects.exit('magicBlock');
|
|
100897
|
+
return nok(code);
|
|
100898
|
+
}
|
|
100899
|
+
// We have '{' - enter data token and start capturing
|
|
100900
|
+
seenOpenBrace = true;
|
|
100901
|
+
effects.enter('magicBlockData');
|
|
100902
|
+
return captureData(code);
|
|
100903
|
+
}
|
|
100904
|
+
/**
|
|
100905
|
+
* Consume whitespace before the data without creating a token.
|
|
100906
|
+
* Uses a temporary token to satisfy micromark's requirement.
|
|
100907
|
+
*/
|
|
100908
|
+
function beforeDataWhitespace(code) {
|
|
100909
|
+
if (code === null) {
|
|
100910
|
+
effects.exit('magicBlock');
|
|
100911
|
+
return nok(code);
|
|
100912
|
+
}
|
|
100913
|
+
if (markdownLineEnding(code)) {
|
|
100914
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100915
|
+
}
|
|
100916
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
100917
|
+
// We need to consume this but can't without a token - use magicBlockData
|
|
100918
|
+
// and track that we haven't seen '{' yet
|
|
100919
|
+
effects.enter('magicBlockData');
|
|
100920
|
+
effects.consume(code);
|
|
100921
|
+
return beforeDataWhitespaceContinue;
|
|
100922
|
+
}
|
|
100923
|
+
if (code === codes.leftCurlyBrace) {
|
|
100924
|
+
seenOpenBrace = true;
|
|
100925
|
+
effects.enter('magicBlockData');
|
|
100926
|
+
return captureData(code);
|
|
100927
|
+
}
|
|
100928
|
+
effects.exit('magicBlock');
|
|
100929
|
+
return nok(code);
|
|
100930
|
+
}
|
|
100931
|
+
/**
|
|
100932
|
+
* Continue consuming whitespace or validate the opening brace.
|
|
100933
|
+
*/
|
|
100934
|
+
function beforeDataWhitespaceContinue(code) {
|
|
100935
|
+
if (code === null) {
|
|
100936
|
+
effects.exit('magicBlockData');
|
|
100937
|
+
effects.exit('magicBlock');
|
|
100938
|
+
return nok(code);
|
|
100939
|
+
}
|
|
100940
|
+
if (markdownLineEnding(code)) {
|
|
100941
|
+
effects.exit('magicBlockData');
|
|
100942
|
+
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100943
|
+
}
|
|
100944
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
100945
|
+
effects.consume(code);
|
|
100946
|
+
return beforeDataWhitespaceContinue;
|
|
100947
|
+
}
|
|
100948
|
+
if (code === codes.leftCurlyBrace) {
|
|
100949
|
+
seenOpenBrace = true;
|
|
100950
|
+
return captureData(code);
|
|
100951
|
+
}
|
|
100952
|
+
effects.exit('magicBlockData');
|
|
100953
|
+
effects.exit('magicBlock');
|
|
100954
|
+
return nok(code);
|
|
100955
|
+
}
|
|
100956
|
+
/**
|
|
100957
|
+
* Continuation OK before we've entered data token.
|
|
100958
|
+
*/
|
|
100959
|
+
function continuationOkBeforeData(code) {
|
|
100960
|
+
effects.enter('magicBlockLineEnding');
|
|
100961
|
+
effects.consume(code);
|
|
100962
|
+
effects.exit('magicBlockLineEnding');
|
|
100963
|
+
return beforeData; // Stay in beforeData state - don't enter magicBlockData yet
|
|
100964
|
+
}
|
|
100965
|
+
function captureData(code) {
|
|
100966
|
+
// EOF - magic block must be closed
|
|
100967
|
+
if (code === null) {
|
|
100968
|
+
effects.exit('magicBlockData');
|
|
100969
|
+
effects.exit('magicBlock');
|
|
100970
|
+
return nok(code);
|
|
100971
|
+
}
|
|
100972
|
+
// At line ending, check if we can continue on the next line
|
|
100973
|
+
if (markdownLineEnding(code)) {
|
|
100974
|
+
effects.exit('magicBlockData');
|
|
100975
|
+
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100976
|
+
}
|
|
100977
|
+
if (jsonState.escapeNext) {
|
|
100978
|
+
jsonState.escapeNext = false;
|
|
100979
|
+
effects.consume(code);
|
|
100980
|
+
return captureData;
|
|
100981
|
+
}
|
|
100982
|
+
if (jsonState.inString) {
|
|
100983
|
+
if (code === codes.backslash) {
|
|
100984
|
+
jsonState.escapeNext = true;
|
|
100985
|
+
effects.consume(code);
|
|
100986
|
+
return captureData;
|
|
100987
|
+
}
|
|
100988
|
+
if (code === codes.quotationMark) {
|
|
100989
|
+
jsonState.inString = false;
|
|
100990
|
+
}
|
|
100991
|
+
effects.consume(code);
|
|
100992
|
+
return captureData;
|
|
100993
|
+
}
|
|
100994
|
+
if (code === codes.quotationMark) {
|
|
100995
|
+
jsonState.inString = true;
|
|
100996
|
+
effects.consume(code);
|
|
100997
|
+
return captureData;
|
|
100998
|
+
}
|
|
100999
|
+
if (code === codes.leftSquareBracket) {
|
|
101000
|
+
effects.exit('magicBlockData');
|
|
101001
|
+
effects.enter('magicBlockMarkerEnd');
|
|
101002
|
+
effects.consume(code);
|
|
101003
|
+
return expectSlash;
|
|
101004
|
+
}
|
|
101005
|
+
effects.consume(code);
|
|
101006
|
+
return captureData;
|
|
101007
|
+
}
|
|
101008
|
+
/**
|
|
101009
|
+
* Called when non-lazy continuation check passes - we can continue parsing.
|
|
101010
|
+
*/
|
|
101011
|
+
function continuationOk(code) {
|
|
101012
|
+
// Consume the line ending
|
|
101013
|
+
effects.enter('magicBlockLineEnding');
|
|
101014
|
+
effects.consume(code);
|
|
101015
|
+
effects.exit('magicBlockLineEnding');
|
|
101016
|
+
return continuationStart;
|
|
101017
|
+
}
|
|
101018
|
+
/**
|
|
101019
|
+
* Start of continuation line - check for more line endings, closing marker, or start capturing data.
|
|
101020
|
+
*/
|
|
101021
|
+
function continuationStart(code) {
|
|
101022
|
+
// Handle consecutive line endings
|
|
101023
|
+
if (code === null) {
|
|
101024
|
+
effects.exit('magicBlock');
|
|
101025
|
+
return nok(code);
|
|
101026
|
+
}
|
|
101027
|
+
if (markdownLineEnding(code)) {
|
|
101028
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
101029
|
+
}
|
|
101030
|
+
// Check if this is the start of the closing marker [/block]
|
|
101031
|
+
// If so, handle it directly without entering magicBlockData
|
|
101032
|
+
if (code === codes.leftSquareBracket) {
|
|
101033
|
+
effects.enter('magicBlockMarkerEnd');
|
|
101034
|
+
effects.consume(code);
|
|
101035
|
+
return expectSlashFromContinuation;
|
|
101036
|
+
}
|
|
101037
|
+
effects.enter('magicBlockData');
|
|
101038
|
+
return captureData(code);
|
|
101039
|
+
}
|
|
101040
|
+
/**
|
|
101041
|
+
* Check for closing marker slash when coming from continuation.
|
|
101042
|
+
* If not a closing marker, create an empty data token and continue.
|
|
101043
|
+
*/
|
|
101044
|
+
function expectSlashFromContinuation(code) {
|
|
101045
|
+
if (code === null) {
|
|
101046
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101047
|
+
effects.exit('magicBlock');
|
|
101048
|
+
return nok(code);
|
|
101049
|
+
}
|
|
101050
|
+
if (markdownLineEnding(code)) {
|
|
101051
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101052
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
101053
|
+
}
|
|
101054
|
+
if (code === codes.slash) {
|
|
101055
|
+
effects.consume(code);
|
|
101056
|
+
return expectClosingB;
|
|
101057
|
+
}
|
|
101058
|
+
// Not a closing marker - this is data content
|
|
101059
|
+
// Exit marker and enter data
|
|
101060
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101061
|
+
effects.enter('magicBlockData');
|
|
101062
|
+
// The [ was consumed by the marker, so we need to conceptually "have it" in our data
|
|
101063
|
+
// But since we already consumed it into the marker, we need a different approach
|
|
101064
|
+
// Re-classify: consume this character as data and continue
|
|
101065
|
+
if (code === codes.quotationMark)
|
|
101066
|
+
jsonState.inString = true;
|
|
101067
|
+
effects.consume(code);
|
|
101068
|
+
return captureData;
|
|
101069
|
+
}
|
|
101070
|
+
function expectSlash(code) {
|
|
101071
|
+
if (code === null) {
|
|
101072
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101073
|
+
effects.exit('magicBlock');
|
|
101074
|
+
return nok(code);
|
|
101075
|
+
}
|
|
101076
|
+
// At line ending during marker parsing
|
|
101077
|
+
if (markdownLineEnding(code)) {
|
|
101078
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101079
|
+
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
101080
|
+
}
|
|
101081
|
+
if (code !== codes.slash) {
|
|
101082
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101083
|
+
effects.enter('magicBlockData');
|
|
101084
|
+
if (code === codes.quotationMark)
|
|
101085
|
+
jsonState.inString = true;
|
|
101086
|
+
effects.consume(code);
|
|
101087
|
+
return captureData;
|
|
101088
|
+
}
|
|
101089
|
+
effects.consume(code);
|
|
101090
|
+
return expectClosingB;
|
|
101091
|
+
}
|
|
101092
|
+
function expectClosingB(code) {
|
|
101093
|
+
if (code === null) {
|
|
101094
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101095
|
+
effects.exit('magicBlock');
|
|
101096
|
+
return nok(code);
|
|
101097
|
+
}
|
|
101098
|
+
if (code !== codes.lowercaseB) {
|
|
101099
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101100
|
+
effects.enter('magicBlockData');
|
|
101101
|
+
if (code === codes.quotationMark)
|
|
101102
|
+
jsonState.inString = true;
|
|
101103
|
+
effects.consume(code);
|
|
101104
|
+
return captureData;
|
|
101105
|
+
}
|
|
101106
|
+
effects.consume(code);
|
|
101107
|
+
return expectClosingL;
|
|
101108
|
+
}
|
|
101109
|
+
function expectClosingL(code) {
|
|
101110
|
+
if (code === null) {
|
|
101111
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101112
|
+
effects.exit('magicBlock');
|
|
101113
|
+
return nok(code);
|
|
101114
|
+
}
|
|
101115
|
+
if (code !== codes.lowercaseL) {
|
|
101116
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101117
|
+
effects.enter('magicBlockData');
|
|
101118
|
+
if (code === codes.quotationMark)
|
|
101119
|
+
jsonState.inString = true;
|
|
101120
|
+
effects.consume(code);
|
|
101121
|
+
return captureData;
|
|
101122
|
+
}
|
|
101123
|
+
effects.consume(code);
|
|
101124
|
+
return expectClosingO;
|
|
101125
|
+
}
|
|
101126
|
+
function expectClosingO(code) {
|
|
101127
|
+
if (code === null) {
|
|
101128
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101129
|
+
effects.exit('magicBlock');
|
|
101130
|
+
return nok(code);
|
|
101131
|
+
}
|
|
101132
|
+
if (code !== codes.lowercaseO) {
|
|
101133
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101134
|
+
effects.enter('magicBlockData');
|
|
101135
|
+
if (code === codes.quotationMark)
|
|
101136
|
+
jsonState.inString = true;
|
|
101137
|
+
effects.consume(code);
|
|
101138
|
+
return captureData;
|
|
101139
|
+
}
|
|
101140
|
+
effects.consume(code);
|
|
101141
|
+
return expectClosingC;
|
|
101142
|
+
}
|
|
101143
|
+
function expectClosingC(code) {
|
|
101144
|
+
if (code === null) {
|
|
101145
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101146
|
+
effects.exit('magicBlock');
|
|
101147
|
+
return nok(code);
|
|
101148
|
+
}
|
|
101149
|
+
if (code !== codes.lowercaseC) {
|
|
101150
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101151
|
+
effects.enter('magicBlockData');
|
|
101152
|
+
if (code === codes.quotationMark)
|
|
101153
|
+
jsonState.inString = true;
|
|
101154
|
+
effects.consume(code);
|
|
101155
|
+
return captureData;
|
|
101156
|
+
}
|
|
101157
|
+
effects.consume(code);
|
|
101158
|
+
return expectClosingK;
|
|
101159
|
+
}
|
|
101160
|
+
function expectClosingK(code) {
|
|
101161
|
+
if (code === null) {
|
|
101162
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101163
|
+
effects.exit('magicBlock');
|
|
101164
|
+
return nok(code);
|
|
101165
|
+
}
|
|
101166
|
+
if (code !== codes.lowercaseK) {
|
|
101167
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101168
|
+
effects.enter('magicBlockData');
|
|
101169
|
+
if (code === codes.quotationMark)
|
|
101170
|
+
jsonState.inString = true;
|
|
101171
|
+
effects.consume(code);
|
|
101172
|
+
return captureData;
|
|
101173
|
+
}
|
|
101174
|
+
effects.consume(code);
|
|
101175
|
+
return expectClosingBracket;
|
|
101176
|
+
}
|
|
101177
|
+
function expectClosingBracket(code) {
|
|
101178
|
+
if (code === null) {
|
|
101179
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101180
|
+
effects.exit('magicBlock');
|
|
101181
|
+
return nok(code);
|
|
101182
|
+
}
|
|
101183
|
+
if (code !== codes.rightSquareBracket) {
|
|
101184
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101185
|
+
effects.enter('magicBlockData');
|
|
101186
|
+
if (code === codes.quotationMark)
|
|
101187
|
+
jsonState.inString = true;
|
|
101188
|
+
effects.consume(code);
|
|
101189
|
+
return captureData;
|
|
101190
|
+
}
|
|
101191
|
+
effects.consume(code);
|
|
101192
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101193
|
+
// Check for trailing whitespace on the same line
|
|
101194
|
+
return consumeTrailing;
|
|
101195
|
+
}
|
|
101196
|
+
/**
|
|
101197
|
+
* Consume trailing whitespace (spaces/tabs) on the same line after [/block].
|
|
101198
|
+
* For concrete flow constructs, we must end at eol/eof or fail.
|
|
101199
|
+
* Trailing whitespace is consumed; other content causes nok (text tokenizer handles it).
|
|
101200
|
+
*/
|
|
101201
|
+
function consumeTrailing(code) {
|
|
101202
|
+
// End of file - done
|
|
101203
|
+
if (code === null) {
|
|
101204
|
+
effects.exit('magicBlock');
|
|
101205
|
+
return ok(code);
|
|
101206
|
+
}
|
|
101207
|
+
// Line ending - done
|
|
101208
|
+
if (markdownLineEnding(code)) {
|
|
101209
|
+
effects.exit('magicBlock');
|
|
101210
|
+
return ok(code);
|
|
101211
|
+
}
|
|
101212
|
+
// Space or tab - consume as trailing whitespace
|
|
101213
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101214
|
+
effects.enter('magicBlockTrailing');
|
|
101215
|
+
effects.consume(code);
|
|
101216
|
+
return consumeTrailingContinue;
|
|
101217
|
+
}
|
|
101218
|
+
// Any other character - fail flow tokenizer, let text tokenizer handle it
|
|
101219
|
+
effects.exit('magicBlock');
|
|
101220
|
+
return nok(code);
|
|
101221
|
+
}
|
|
101222
|
+
/**
|
|
101223
|
+
* Continue consuming trailing whitespace.
|
|
101224
|
+
*/
|
|
101225
|
+
function consumeTrailingContinue(code) {
|
|
101226
|
+
// End of file - done
|
|
101227
|
+
if (code === null) {
|
|
101228
|
+
effects.exit('magicBlockTrailing');
|
|
101229
|
+
effects.exit('magicBlock');
|
|
101230
|
+
return ok(code);
|
|
101231
|
+
}
|
|
101232
|
+
// Line ending - done
|
|
101233
|
+
if (markdownLineEnding(code)) {
|
|
101234
|
+
effects.exit('magicBlockTrailing');
|
|
101235
|
+
effects.exit('magicBlock');
|
|
101236
|
+
return ok(code);
|
|
101237
|
+
}
|
|
101238
|
+
// More space or tab - keep consuming
|
|
101239
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101240
|
+
effects.consume(code);
|
|
101241
|
+
return consumeTrailingContinue;
|
|
101242
|
+
}
|
|
101243
|
+
// Non-whitespace after whitespace - fail flow tokenizer
|
|
101244
|
+
effects.exit('magicBlockTrailing');
|
|
101245
|
+
effects.exit('magicBlock');
|
|
101246
|
+
return nok(code);
|
|
101247
|
+
}
|
|
101248
|
+
/**
|
|
101249
|
+
* Called when we can't continue (lazy line or EOF) - exit the construct.
|
|
101250
|
+
*/
|
|
101251
|
+
function after(code) {
|
|
101252
|
+
effects.exit('magicBlock');
|
|
101253
|
+
return nok(code);
|
|
101254
|
+
}
|
|
101255
|
+
}
|
|
101256
|
+
/**
|
|
101257
|
+
* Text tokenizer for single-line magic blocks only.
|
|
101258
|
+
* Used in inline contexts like list items and paragraphs.
|
|
101259
|
+
* Multiline blocks are handled by the flow tokenizer.
|
|
101260
|
+
*/
|
|
101261
|
+
function tokenizeMagicBlockText(effects, ok, nok) {
|
|
101262
|
+
// State for tracking JSON content
|
|
101263
|
+
const jsonState = { escapeNext: false, inString: false };
|
|
101264
|
+
const blockTypeRef = { value: '' };
|
|
101265
|
+
let seenOpenBrace = false;
|
|
101266
|
+
// Create shared parsers for opening marker and type capture
|
|
101267
|
+
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
101268
|
+
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
101269
|
+
// Success handler for closing marker - exits tokens and returns ok
|
|
101270
|
+
const closingSuccess = (code) => {
|
|
101271
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101272
|
+
effects.exit('magicBlock');
|
|
101273
|
+
return ok(code);
|
|
101274
|
+
};
|
|
101275
|
+
// Mismatch handler - falls back to data capture
|
|
101276
|
+
const closingMismatch = (code) => {
|
|
101277
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101278
|
+
effects.enter('magicBlockData');
|
|
101279
|
+
if (code === codes.quotationMark)
|
|
101280
|
+
jsonState.inString = true;
|
|
101281
|
+
effects.consume(code);
|
|
101282
|
+
return captureData;
|
|
101283
|
+
};
|
|
101284
|
+
// EOF handler
|
|
101285
|
+
const closingEof = (_code) => nok(_code);
|
|
101286
|
+
// Create closing marker parsers
|
|
101287
|
+
const closingFromBeforeData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
101288
|
+
const closingFromData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
101289
|
+
return start;
|
|
101290
|
+
function start(code) {
|
|
101291
|
+
if (code !== codes.leftSquareBracket)
|
|
101292
|
+
return nok(code);
|
|
101293
|
+
effects.enter('magicBlock');
|
|
101294
|
+
effects.enter('magicBlockMarkerStart');
|
|
101295
|
+
effects.consume(code);
|
|
101296
|
+
return openingMarkerParser;
|
|
101297
|
+
}
|
|
101298
|
+
/**
|
|
101299
|
+
* State before data content - handles line endings before entering data token.
|
|
101300
|
+
* Whitespace before '{' is allowed.
|
|
101301
|
+
*/
|
|
101302
|
+
function beforeData(code) {
|
|
101303
|
+
// Fail on EOF - magic block must be closed
|
|
101304
|
+
if (code === null) {
|
|
101305
|
+
return nok(code);
|
|
101306
|
+
}
|
|
101307
|
+
// Handle line endings before any data - consume them without entering data token
|
|
101308
|
+
if (markdownLineEnding(code)) {
|
|
101309
|
+
effects.enter('magicBlockLineEnding');
|
|
101310
|
+
effects.consume(code);
|
|
101311
|
+
effects.exit('magicBlockLineEnding');
|
|
101312
|
+
return beforeData;
|
|
101313
|
+
}
|
|
101314
|
+
// Check for closing marker directly (without entering data)
|
|
101315
|
+
if (code === codes.leftSquareBracket) {
|
|
101316
|
+
effects.enter('magicBlockMarkerEnd');
|
|
101317
|
+
effects.consume(code);
|
|
101318
|
+
return closingFromBeforeData.expectSlash;
|
|
101319
|
+
}
|
|
101320
|
+
// If we've already seen the opening brace, just continue capturing data
|
|
101321
|
+
if (seenOpenBrace) {
|
|
101322
|
+
effects.enter('magicBlockData');
|
|
101323
|
+
return captureData(code);
|
|
101324
|
+
}
|
|
101325
|
+
// Skip whitespace (spaces/tabs) before the data
|
|
101326
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101327
|
+
return beforeDataWhitespace(code);
|
|
101328
|
+
}
|
|
101329
|
+
// Data must start with '{' for valid JSON
|
|
101330
|
+
if (code !== codes.leftCurlyBrace) {
|
|
101331
|
+
return nok(code);
|
|
101332
|
+
}
|
|
101333
|
+
// We have '{' - enter data token and start capturing
|
|
101334
|
+
seenOpenBrace = true;
|
|
101335
|
+
effects.enter('magicBlockData');
|
|
101336
|
+
return captureData(code);
|
|
101337
|
+
}
|
|
101338
|
+
/**
|
|
101339
|
+
* Consume whitespace before the data.
|
|
101340
|
+
*/
|
|
101341
|
+
function beforeDataWhitespace(code) {
|
|
101342
|
+
if (code === null) {
|
|
101343
|
+
return nok(code);
|
|
101344
|
+
}
|
|
101345
|
+
if (markdownLineEnding(code)) {
|
|
101346
|
+
effects.enter('magicBlockLineEnding');
|
|
101347
|
+
effects.consume(code);
|
|
101348
|
+
effects.exit('magicBlockLineEnding');
|
|
101349
|
+
return beforeData;
|
|
101350
|
+
}
|
|
101351
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101352
|
+
effects.enter('magicBlockData');
|
|
101353
|
+
effects.consume(code);
|
|
101354
|
+
return beforeDataWhitespaceContinue;
|
|
101355
|
+
}
|
|
101356
|
+
if (code === codes.leftCurlyBrace) {
|
|
101357
|
+
seenOpenBrace = true;
|
|
101358
|
+
effects.enter('magicBlockData');
|
|
101359
|
+
return captureData(code);
|
|
101360
|
+
}
|
|
101361
|
+
return nok(code);
|
|
101362
|
+
}
|
|
101363
|
+
/**
|
|
101364
|
+
* Continue consuming whitespace or validate the opening brace.
|
|
101365
|
+
*/
|
|
101366
|
+
function beforeDataWhitespaceContinue(code) {
|
|
101367
|
+
if (code === null) {
|
|
101368
|
+
effects.exit('magicBlockData');
|
|
101369
|
+
return nok(code);
|
|
101370
|
+
}
|
|
101371
|
+
if (markdownLineEnding(code)) {
|
|
101372
|
+
effects.exit('magicBlockData');
|
|
101373
|
+
effects.enter('magicBlockLineEnding');
|
|
101374
|
+
effects.consume(code);
|
|
101375
|
+
effects.exit('magicBlockLineEnding');
|
|
101376
|
+
return beforeData;
|
|
101377
|
+
}
|
|
101378
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101379
|
+
effects.consume(code);
|
|
101380
|
+
return beforeDataWhitespaceContinue;
|
|
101381
|
+
}
|
|
101382
|
+
if (code === codes.leftCurlyBrace) {
|
|
101383
|
+
seenOpenBrace = true;
|
|
101384
|
+
return captureData(code);
|
|
101385
|
+
}
|
|
101386
|
+
effects.exit('magicBlockData');
|
|
101387
|
+
return nok(code);
|
|
101388
|
+
}
|
|
101389
|
+
function captureData(code) {
|
|
101390
|
+
// Fail on EOF - magic block must be closed
|
|
101391
|
+
if (code === null) {
|
|
101392
|
+
effects.exit('magicBlockData');
|
|
101393
|
+
return nok(code);
|
|
101394
|
+
}
|
|
101395
|
+
// Handle multiline magic blocks within text/paragraphs
|
|
101396
|
+
// Exit data, consume line ending with proper token, then re-enter data
|
|
101397
|
+
if (markdownLineEnding(code)) {
|
|
101398
|
+
effects.exit('magicBlockData');
|
|
101399
|
+
effects.enter('magicBlockLineEnding');
|
|
101400
|
+
effects.consume(code);
|
|
101401
|
+
effects.exit('magicBlockLineEnding');
|
|
101402
|
+
return beforeData; // Go back to beforeData to handle potential empty lines
|
|
101403
|
+
}
|
|
101404
|
+
if (jsonState.escapeNext) {
|
|
101405
|
+
jsonState.escapeNext = false;
|
|
101406
|
+
effects.consume(code);
|
|
101407
|
+
return captureData;
|
|
101408
|
+
}
|
|
101409
|
+
if (jsonState.inString) {
|
|
101410
|
+
if (code === codes.backslash) {
|
|
101411
|
+
jsonState.escapeNext = true;
|
|
101412
|
+
effects.consume(code);
|
|
101413
|
+
return captureData;
|
|
101414
|
+
}
|
|
101415
|
+
if (code === codes.quotationMark) {
|
|
101416
|
+
jsonState.inString = false;
|
|
101417
|
+
}
|
|
101418
|
+
effects.consume(code);
|
|
101419
|
+
return captureData;
|
|
101420
|
+
}
|
|
101421
|
+
if (code === codes.quotationMark) {
|
|
101422
|
+
jsonState.inString = true;
|
|
101423
|
+
effects.consume(code);
|
|
101424
|
+
return captureData;
|
|
101425
|
+
}
|
|
101426
|
+
if (code === codes.leftSquareBracket) {
|
|
101427
|
+
effects.exit('magicBlockData');
|
|
101428
|
+
effects.enter('magicBlockMarkerEnd');
|
|
101429
|
+
effects.consume(code);
|
|
101430
|
+
return closingFromData.expectSlash;
|
|
101431
|
+
}
|
|
101432
|
+
effects.consume(code);
|
|
101433
|
+
return captureData;
|
|
101434
|
+
}
|
|
101435
|
+
}
|
|
101436
|
+
/* harmony default export */ const syntax = ((/* unused pure expression or super */ null && (magicBlock)));
|
|
101437
|
+
|
|
101438
|
+
;// ./lib/micromark/magic-block/index.ts
|
|
101439
|
+
/**
|
|
101440
|
+
* Micromark extension for magic block syntax.
|
|
101441
|
+
*
|
|
101442
|
+
* Usage:
|
|
101443
|
+
* ```ts
|
|
101444
|
+
* import { magicBlock } from './lib/micromark/magic-block';
|
|
101445
|
+
*
|
|
101446
|
+
* const processor = unified()
|
|
101447
|
+
* .data('micromarkExtensions', [magicBlock()])
|
|
101448
|
+
* ```
|
|
101449
|
+
*/
|
|
101450
|
+
|
|
101451
|
+
|
|
101452
|
+
;// ./lib/micromark/mdx-component/syntax.ts
|
|
101453
|
+
|
|
101454
|
+
|
|
101455
|
+
|
|
101456
|
+
|
|
101457
|
+
|
|
101458
|
+
// Raw tags (type-1: pre/script/style/textarea) and block tags (type-6: div,
|
|
101459
|
+
// section, …) always start a block, so they stay flow even with trailing
|
|
101460
|
+
// content. Other lowercase tags (i, span, …) follow the type-7 rule and only
|
|
101461
|
+
// stay flow when nothing trails the close tag.
|
|
101462
|
+
const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
|
|
101463
|
+
// Lowercase type-6 block tags claimable in flow even without a `{…}` attribute, so
|
|
101464
|
+
// blank lines between nested JSX siblings don't fragment the block. Excludes table
|
|
101465
|
+
// tags (mdxishTables owns their blank lines) and voids (never close).
|
|
101466
|
+
const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
|
|
101467
|
+
const mdx_component_syntax_nonLazyContinuationStart = {
|
|
101468
|
+
tokenize: mdx_component_syntax_tokenizeNonLazyContinuationStart,
|
|
101469
|
+
partial: true,
|
|
101470
|
+
};
|
|
101471
|
+
// Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
|
|
101472
|
+
// that merely starts with a tag? Run via `effects.check` so it never consumes.
|
|
101473
|
+
const markupOnlyContinuation = {
|
|
101474
|
+
tokenize: tokenizeMarkupOnlyContinuation,
|
|
101475
|
+
partial: true,
|
|
101476
|
+
};
|
|
101477
|
+
function resolveToMdxComponent(events) {
|
|
101478
|
+
let index = events.length;
|
|
101479
|
+
while (index > 0) {
|
|
101480
|
+
index -= 1;
|
|
101481
|
+
if (events[index][0] === 'enter' && events[index][1].type === 'mdxComponent') {
|
|
101482
|
+
break;
|
|
101483
|
+
}
|
|
101484
|
+
}
|
|
101485
|
+
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
101486
|
+
events[index][1].start = events[index - 2][1].start;
|
|
101487
|
+
events[index + 1][1].start = events[index - 2][1].start;
|
|
101488
|
+
events.splice(index - 2, 2);
|
|
101489
|
+
}
|
|
101490
|
+
return events;
|
|
101491
|
+
}
|
|
101492
|
+
const mdxComponentFlowConstruct = {
|
|
101493
|
+
name: 'mdxComponent',
|
|
101494
|
+
tokenize: createTokenize('flow'),
|
|
101495
|
+
resolveTo: resolveToMdxComponent,
|
|
101496
|
+
concrete: true,
|
|
101497
|
+
};
|
|
101498
|
+
const mdxComponentTextConstruct = {
|
|
101499
|
+
name: 'mdxComponentText',
|
|
101500
|
+
tokenize: createTokenize('text'),
|
|
101501
|
+
};
|
|
101502
|
+
/**
|
|
101503
|
+
* Factory for both flow (block) and text (inline) variants.
|
|
101504
|
+
*
|
|
101505
|
+
* **Flow** — the original behavior: claims PascalCase components (always) and
|
|
101506
|
+
* lowercase HTML tags that carry at least one `{…}` attribute expression.
|
|
101507
|
+
* Multi-line, concrete, `afterClose` consumes the rest of the line.
|
|
101508
|
+
*
|
|
101509
|
+
* **Text** — runs inside paragraphs / inline context. Claims lowercase tags and
|
|
101510
|
+
* inline PascalCase components (`INLINE_COMPONENT_TAGS` — Anchor, Glossary), both
|
|
101511
|
+
* gated on at least one `{…}` brace attribute. All other PascalCase stays
|
|
101512
|
+
* flow-only, matching how ReadMe's custom components are authored. Aborts on line
|
|
101513
|
+
* endings (inline constructs don't span lines) and exits immediately after
|
|
101514
|
+
* `</tag>` so the paragraph's inline parser picks up the trailing text.
|
|
101515
|
+
*/
|
|
101516
|
+
function createTokenize(mode) {
|
|
101517
|
+
const isFlow = mode === 'flow';
|
|
101518
|
+
return function tokenize(effects, ok, nok) {
|
|
101519
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
101520
|
+
const self = this;
|
|
101521
|
+
let tagName = '';
|
|
101522
|
+
let depth = 0;
|
|
101523
|
+
let closingTagName = '';
|
|
101524
|
+
// For lowercase tags we only want to claim the block if it uses JSX
|
|
101525
|
+
// attribute expression syntax (`attr={...}`). Plain HTML should fall
|
|
101526
|
+
// through to CommonMark html-flow. Flow mode claims any PascalCase block
|
|
101527
|
+
// component; text mode claims only inline PascalCase components
|
|
101528
|
+
// (INLINE_COMPONENT_TAGS — Anchor, Glossary), also brace-gated.
|
|
101529
|
+
let isLowercaseTag = false;
|
|
101530
|
+
let sawBraceAttr = false;
|
|
101531
|
+
// A plain lowercase block tag claimed without a `{…}` attribute, gated by
|
|
101532
|
+
// `plainClaimLineStart`: after a blank line it may only continue on a tag line.
|
|
101533
|
+
let isPlainBlockClaim = false;
|
|
101534
|
+
let pendingBlankLine = false;
|
|
101214
101535
|
// Code span tracking
|
|
101215
101536
|
let codeSpanOpenSize = 0;
|
|
101216
101537
|
let codeSpanCloseSize = 0;
|
|
@@ -101510,7 +101831,7 @@ function createTokenize(mode) {
|
|
|
101510
101831
|
}
|
|
101511
101832
|
// Continuation for multi-line opening tags
|
|
101512
101833
|
function openTagContinuationStart(code) {
|
|
101513
|
-
return effects.check(
|
|
101834
|
+
return effects.check(mdx_component_syntax_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
|
|
101514
101835
|
}
|
|
101515
101836
|
function openTagContinuationNonLazy(code) {
|
|
101516
101837
|
sawLineEnding = true;
|
|
@@ -101635,7 +101956,7 @@ function createTokenize(mode) {
|
|
|
101635
101956
|
return inFencedCode;
|
|
101636
101957
|
}
|
|
101637
101958
|
function fencedCodeContinuationStart(code) {
|
|
101638
|
-
return effects.check(
|
|
101959
|
+
return effects.check(mdx_component_syntax_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
|
|
101639
101960
|
}
|
|
101640
101961
|
function fencedCodeContinuationNonLazy(code) {
|
|
101641
101962
|
sawLineEnding = true;
|
|
@@ -101650,6 +101971,16 @@ function createTokenize(mode) {
|
|
|
101650
101971
|
}
|
|
101651
101972
|
effects.enter('mdxComponentData');
|
|
101652
101973
|
fenceCloseLength = 0;
|
|
101974
|
+
return fencedCodeMaybeClose(code);
|
|
101975
|
+
}
|
|
101976
|
+
// Skip leading indentation before the closing-fence check: an indented fence
|
|
101977
|
+
// (the norm in a component body) closes on an equally-indented line, else the
|
|
101978
|
+
// closer is never matched and scanning runs to EOF (CX-3704).
|
|
101979
|
+
function fencedCodeMaybeClose(code) {
|
|
101980
|
+
if (markdownSpace(code)) {
|
|
101981
|
+
effects.consume(code);
|
|
101982
|
+
return fencedCodeMaybeClose;
|
|
101983
|
+
}
|
|
101653
101984
|
// Check for closing fence
|
|
101654
101985
|
if (code === fenceChar) {
|
|
101655
101986
|
fenceCloseLength = 1;
|
|
@@ -101833,7 +102164,7 @@ function createTokenize(mode) {
|
|
|
101833
102164
|
}
|
|
101834
102165
|
// ── Body continuation (line endings) ───────────────────────────────────
|
|
101835
102166
|
function bodyContinuationStart(code) {
|
|
101836
|
-
return effects.check(
|
|
102167
|
+
return effects.check(mdx_component_syntax_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
|
|
101837
102168
|
}
|
|
101838
102169
|
function bodyContinuationNonLazy(code) {
|
|
101839
102170
|
sawLineEnding = true;
|
|
@@ -101865,6 +102196,13 @@ function createTokenize(mode) {
|
|
|
101865
102196
|
}
|
|
101866
102197
|
// Dispatch a non-blank continuation line: fenced code at line start, else body.
|
|
101867
102198
|
function bodyLineStart(code) {
|
|
102199
|
+
// Skip leading indentation while staying "at line start" so an indented
|
|
102200
|
+
// fence is still recognized. Otherwise the first space clears `atLineStart`
|
|
102201
|
+
// and its content — including any unbalanced `{` — stays live text (CX-3704).
|
|
102202
|
+
if (atLineStart && markdownSpace(code)) {
|
|
102203
|
+
effects.consume(code);
|
|
102204
|
+
return bodyLineStart;
|
|
102205
|
+
}
|
|
101868
102206
|
if (atLineStart && code === codes.tilde)
|
|
101869
102207
|
return bodyAfterLineStart(code);
|
|
101870
102208
|
if (atLineStart && code === codes.graveAccent) {
|
|
@@ -101915,7 +102253,7 @@ function createTokenize(mode) {
|
|
|
101915
102253
|
}
|
|
101916
102254
|
};
|
|
101917
102255
|
}
|
|
101918
|
-
function
|
|
102256
|
+
function mdx_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
101919
102257
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
101920
102258
|
const self = this;
|
|
101921
102259
|
return start;
|
|
@@ -102023,9 +102361,20 @@ function mdxComponent() {
|
|
|
102023
102361
|
|
|
102024
102362
|
|
|
102025
102363
|
|
|
102364
|
+
|
|
102365
|
+
|
|
102366
|
+
|
|
102367
|
+
|
|
102368
|
+
|
|
102369
|
+
|
|
102026
102370
|
const buildInlineMdProcessor = (safeMode) => {
|
|
102027
|
-
|
|
102371
|
+
// `jsxTable` must be present so a `<Table>`/`<table>` nested in a component
|
|
102372
|
+
// body (e.g. a `<Callout>`) is captured as one html node. Without it, blank
|
|
102373
|
+
// lines between rows let CommonMark HTML block type 6 fragment the table and
|
|
102374
|
+
// its rows spill out as text / indented code blocks (CX-3705).
|
|
102375
|
+
const micromarkExts = [jsxTable(), mdxComponent(), syntax_gemoji(), legacyVariable(), magicBlock()];
|
|
102028
102376
|
const fromMarkdownExts = [
|
|
102377
|
+
jsxTableFromMarkdown(),
|
|
102029
102378
|
mdxComponentFromMarkdown(),
|
|
102030
102379
|
gemojiFromMarkdown(),
|
|
102031
102380
|
legacyVariableFromMarkdown(),
|
|
@@ -102085,6 +102434,65 @@ const toMdxJsxTextElement = (name, attributes, children, position) => ({
|
|
|
102085
102434
|
children,
|
|
102086
102435
|
...(position ? { position } : {}),
|
|
102087
102436
|
});
|
|
102437
|
+
// Raw-body tags (pre/script/style/textarea) must stay byte-exact; table
|
|
102438
|
+
// structure (`table` + `tableTags`) is owned by `mdxishTables` and figures by
|
|
102439
|
+
// `mdxishJsxToMdast`, both of which run later on raw html nodes.
|
|
102440
|
+
const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table', 'figure', 'figcaption']);
|
|
102441
|
+
const NESTED_TABLE_RE = /<table[\s>]/i;
|
|
102442
|
+
const isMarkdownPromotableHtmlTag = (tag) => !NON_PROMOTABLE_PLAIN_TAGS.has(tag);
|
|
102443
|
+
// Expression nodes count as plain so `<div>{1+1}</div>` keeps its current
|
|
102444
|
+
// literal-brace behavior; variables/glossary already resolve inside raw html.
|
|
102445
|
+
const PLAIN_CONTENT_TYPES = new Set([
|
|
102446
|
+
'paragraph',
|
|
102447
|
+
'text',
|
|
102448
|
+
'html',
|
|
102449
|
+
'mdxTextExpression',
|
|
102450
|
+
'mdxFlowExpression',
|
|
102451
|
+
NodeTypes.variable,
|
|
102452
|
+
NodeTypes.glossary,
|
|
102453
|
+
]);
|
|
102454
|
+
// Promoting plain HTML is only worth bypassing rehype-raw's parse5 pass when
|
|
102455
|
+
// the body parses into an actual markdown construct.
|
|
102456
|
+
const containsMarkdownConstruct = (nodes) => nodes.some(node => !PLAIN_CONTENT_TYPES.has(node.type) ||
|
|
102457
|
+
('children' in node && Array.isArray(node.children) && containsMarkdownConstruct(node.children)));
|
|
102458
|
+
/**
|
|
102459
|
+
* Index of the `</tag>` that balances the already-consumed opening tag (the
|
|
102460
|
+
* caller starts us one level deep). `lastIndexOf` mis-slices sibling same-tag
|
|
102461
|
+
* pairs like `<div>**a**</div><div>**b**</div>`, so we depth-match instead —
|
|
102462
|
+
* delegating to `walkTags` (htmlparser2) so quoted attributes (`title="</div>"`),
|
|
102463
|
+
* code spans, and legacy `<<VARIABLE>>` are handled for free. Returns -1 when
|
|
102464
|
+
* the wrapper is left open.
|
|
102465
|
+
*/
|
|
102466
|
+
function findBalancedClosingTagIndex(content, tag) {
|
|
102467
|
+
const target = tag.toLowerCase();
|
|
102468
|
+
const canonicalCloserLength = tag.length + 3; // `</tag>`
|
|
102469
|
+
// The caller already stripped the opening tag, so re-attach one: htmlparser2
|
|
102470
|
+
// drops an unmatched closer, and we want it balanced. Offsets shift by the
|
|
102471
|
+
// prefix length.
|
|
102472
|
+
const prefix = `<${tag}>`;
|
|
102473
|
+
let depth = 0;
|
|
102474
|
+
let closeIndex = -1;
|
|
102475
|
+
walkTags(prefix + content, {
|
|
102476
|
+
onOpen: ({ name, isSelfClosing, isStrayCloser }) => {
|
|
102477
|
+
if (closeIndex >= 0 || isSelfClosing || isStrayCloser)
|
|
102478
|
+
return;
|
|
102479
|
+
if (name.toLowerCase() === target)
|
|
102480
|
+
depth += 1;
|
|
102481
|
+
},
|
|
102482
|
+
onClose: ({ name, start, end, implicit }) => {
|
|
102483
|
+
if (closeIndex >= 0 || implicit || name.toLowerCase() !== target)
|
|
102484
|
+
return;
|
|
102485
|
+
// Only canonical `</tag>` closers — the caller slices by that length, so a
|
|
102486
|
+
// whitespaced `</tag >` would misalign; leaving it unmatched keeps it raw.
|
|
102487
|
+
if (end - start !== canonicalCloserLength)
|
|
102488
|
+
return;
|
|
102489
|
+
depth -= 1;
|
|
102490
|
+
if (depth === 0)
|
|
102491
|
+
closeIndex = start - prefix.length;
|
|
102492
|
+
},
|
|
102493
|
+
});
|
|
102494
|
+
return closeIndex;
|
|
102495
|
+
}
|
|
102088
102496
|
|
|
102089
102497
|
;// ./processor/transform/mdxish/components/inline-html.ts
|
|
102090
102498
|
|
|
@@ -102216,70 +102624,168 @@ const mdxishInlineMdxComponents = () => tree => {
|
|
|
102216
102624
|
};
|
|
102217
102625
|
/* harmony default export */ const inline_mdx_blocks = (mdxishInlineMdxComponents);
|
|
102218
102626
|
|
|
102627
|
+
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
102628
|
+
|
|
102629
|
+
|
|
102630
|
+
|
|
102631
|
+
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
102632
|
+
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
102633
|
+
// A line that is exactly one lowercase opening (or self-closing) tag — the shape
|
|
102634
|
+
// that opens a CommonMark type-6/7 HTML block and swallows the lines below it.
|
|
102635
|
+
const SINGLE_OPENING_TAG_REGEX = /^<[a-z][^<>]*>$/;
|
|
102636
|
+
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
102637
|
+
// opener corrupts the payload.
|
|
102638
|
+
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
102639
|
+
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
102640
|
+
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
102641
|
+
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
102642
|
+
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
102643
|
+
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
102644
|
+
}));
|
|
102645
|
+
function isLineHtml(line) {
|
|
102646
|
+
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
102647
|
+
}
|
|
102648
|
+
// Per-tag {opens, closes} counts of RAW_CONTENT_TAGS on one line — feeds both the
|
|
102649
|
+
// per-line net-open check and the cumulative still-open depth tracking.
|
|
102650
|
+
function countRawContentTags(line) {
|
|
102651
|
+
return RAW_CONTENT_TAG_MATCHERS.map(({ open, close }) => ({
|
|
102652
|
+
opens: (line.match(open) ?? []).length,
|
|
102653
|
+
closes: (line.match(close) ?? []).length,
|
|
102654
|
+
}));
|
|
102655
|
+
}
|
|
102656
|
+
// Indentation width in columns, counting a tab as 4 per CommonMark.
|
|
102657
|
+
function indentWidth(line) {
|
|
102658
|
+
const leading = line.match(/^[ \t]*/)?.[0] ?? '';
|
|
102659
|
+
return leading.replace(/\t/g, ' ').length;
|
|
102660
|
+
}
|
|
102661
|
+
/**
|
|
102662
|
+
* Decides whether a blank line belongs between `line` and `next` so the HTML
|
|
102663
|
+
* flow block opened on `line` terminates and `next` parses as markdown.
|
|
102664
|
+
*/
|
|
102665
|
+
function shouldTerminateBetween(line, next, { insideRawContent, lineLeavesRawOpen }) {
|
|
102666
|
+
if (next.trim().length === 0)
|
|
102667
|
+
return false;
|
|
102668
|
+
const currentIndent = indentWidth(line);
|
|
102669
|
+
const nextIndent = indentWidth(next);
|
|
102670
|
+
// 4+ columns is CommonMark indented-code territory: an inserted blank line
|
|
102671
|
+
// would turn the next line into a code block instead of freeing it (#1344).
|
|
102672
|
+
if (currentIndent > 3 || nextIndent > 3)
|
|
102673
|
+
return false;
|
|
102674
|
+
const currentTrimmed = line.trim();
|
|
102675
|
+
const nextTrimmed = next.trim();
|
|
102676
|
+
if (!isLineHtml(currentTrimmed) || isLineHtml(nextTrimmed) || lineLeavesRawOpen) {
|
|
102677
|
+
return false;
|
|
102678
|
+
}
|
|
102679
|
+
// Column-0 pairs keep the original (pre-relaxation) rule, deliberately ignoring
|
|
102680
|
+
// `insideRawContent`: one unclosed <pre>/<table> typo would otherwise suppress
|
|
102681
|
+
// termination for the whole rest of the document.
|
|
102682
|
+
if (currentIndent === 0 && nextIndent === 0)
|
|
102683
|
+
return true;
|
|
102684
|
+
// Indented shapes (either line at 1–3 columns) are stricter: only a lone opening
|
|
102685
|
+
// tag followed by markdown. A next line opening a tag or expression must stay
|
|
102686
|
+
// glued for the mdxComponent tokenizer; raw-content payloads stay byte-exact.
|
|
102687
|
+
return (!insideRawContent &&
|
|
102688
|
+
SINGLE_OPENING_TAG_REGEX.test(currentTrimmed) &&
|
|
102689
|
+
!nextTrimmed.startsWith('<') &&
|
|
102690
|
+
!nextTrimmed.startsWith('{'));
|
|
102691
|
+
}
|
|
102692
|
+
/**
|
|
102693
|
+
* CommonMark HTML blocks (types 6/7) end only at a blank line, so markdown on the
|
|
102694
|
+
* next line is swallowed as HTML (`## heading` after `<div>` renders as literal text).
|
|
102695
|
+
* Inserts the missing blank line; the gating rules live in `shouldTerminateBetween`.
|
|
102696
|
+
*
|
|
102697
|
+
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
102698
|
+
*/
|
|
102699
|
+
function terminateHtmlFlowBlocks(content) {
|
|
102700
|
+
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
102701
|
+
const lines = protectedContent.split('\n');
|
|
102702
|
+
const result = [];
|
|
102703
|
+
// Per-tag count of still-open raw-content elements at the current boundary.
|
|
102704
|
+
const rawContentDepths = RAW_CONTENT_TAG_MATCHERS.map(() => 0);
|
|
102705
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
102706
|
+
const line = lines[i];
|
|
102707
|
+
result.push(line);
|
|
102708
|
+
const tagCounts = countRawContentTags(line);
|
|
102709
|
+
tagCounts.forEach(({ opens, closes }, tagIndex) => {
|
|
102710
|
+
rawContentDepths[tagIndex] = Math.max(0, rawContentDepths[tagIndex] + opens - closes);
|
|
102711
|
+
});
|
|
102712
|
+
const next = lines[i + 1];
|
|
102713
|
+
const rawContentFacts = {
|
|
102714
|
+
insideRawContent: rawContentDepths.some(depth => depth > 0),
|
|
102715
|
+
lineLeavesRawOpen: tagCounts.some(({ opens, closes }) => opens > closes),
|
|
102716
|
+
};
|
|
102717
|
+
if (next !== undefined && shouldTerminateBetween(line, next, rawContentFacts)) {
|
|
102718
|
+
result.push('');
|
|
102719
|
+
}
|
|
102720
|
+
}
|
|
102721
|
+
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
102722
|
+
}
|
|
102723
|
+
|
|
102219
102724
|
;// ./processor/transform/mdxish/components/mdx-blocks.ts
|
|
102220
102725
|
|
|
102221
102726
|
|
|
102222
102727
|
|
|
102223
102728
|
|
|
102224
102729
|
|
|
102225
|
-
|
|
102730
|
+
|
|
102731
|
+
|
|
102732
|
+
// Matches a JSX attribute expression (e.g. `key={i}`) anywhere in a string. */
|
|
102226
102733
|
const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
|
|
102227
|
-
|
|
102228
|
-
|
|
102229
|
-
|
|
102230
|
-
|
|
102231
|
-
|
|
102734
|
+
// Name shape mirrors `componentTagPattern`; the lookbehind skips the inner tag
|
|
102735
|
+
// of a legacy `<<VARIABLE>>`.
|
|
102736
|
+
const NESTED_COMPONENT_TAG_RE = /(?<!<)<([A-Z][A-Za-z0-9_]*)[\s/>]/g;
|
|
102737
|
+
// Excludes tags with dedicated transformers (`Table`, `HTMLBlock`, inline
|
|
102738
|
+
// components), which expect their wrapper to stay raw.
|
|
102739
|
+
const hasNestedGenericComponentTag = (content) => [...content.matchAll(NESTED_COMPONENT_TAG_RE)].some(match => !GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(match[1]));
|
|
102740
|
+
/**
|
|
102741
|
+
* Strip the shared leading indentation from a component body so readability indentation
|
|
102742
|
+
* isn't parsed as indented code (4+ spaces), e.g. ` <p>` / ` text` -> `<p>` / ` text`.
|
|
102743
|
+
* Relative indentation is kept, so content genuinely 4+ columns deeper stays code. We
|
|
102744
|
+
* only strip when a line actually reaches 4 columns; otherwise the body is left as-is so
|
|
102745
|
+
* its leading whitespace survives as text nodes (mixed component + HTML content needs it).
|
|
102232
102746
|
*/
|
|
102233
102747
|
function safeDeindent(text) {
|
|
102234
102748
|
const lines = text.split('\n');
|
|
102235
102749
|
const nonEmptyLines = lines.filter(line => line.trim().length > 0);
|
|
102236
102750
|
if (nonEmptyLines.length === 0)
|
|
102237
102751
|
return text;
|
|
102238
|
-
|
|
102239
|
-
|
|
102240
|
-
|
|
102241
|
-
|
|
102242
|
-
|
|
102243
|
-
const stripAmount =
|
|
102752
|
+
// Indent counts characters (tab = 1), unlike indentWidth's CommonMark columns
|
|
102753
|
+
// (tab = 4) in terminate-html-flow-blocks.
|
|
102754
|
+
const indents = nonEmptyLines.map(line => line.match(/^(\s*)/)?.[1].length ?? 0);
|
|
102755
|
+
const minIndent = Math.min(...indents);
|
|
102756
|
+
const maxIndent = Math.max(...indents);
|
|
102757
|
+
const stripAmount = maxIndent > 3 ? minIndent : 0;
|
|
102244
102758
|
if (stripAmount === 0)
|
|
102245
102759
|
return text;
|
|
102246
102760
|
return lines.map(line => line.slice(stripAmount)).join('\n');
|
|
102247
102761
|
}
|
|
102248
102762
|
/**
|
|
102249
|
-
* Parse markdown
|
|
102250
|
-
*
|
|
102251
|
-
*
|
|
102763
|
+
* Parse component-body markdown into mdast children. Dedenting shifts columns and
|
|
102764
|
+
* stales the top-level `terminateHtmlFlowBlocks` decisions, so that one preprocessor
|
|
102765
|
+
* re-runs here; other column-anchored fixups (compact headings, tables) do not.
|
|
102252
102766
|
*/
|
|
102253
102767
|
const parseMdChildren = (value, safeMode) => {
|
|
102254
|
-
const parsed = getInlineMdProcessor({ safeMode }).parse(safeDeindent(value).trim());
|
|
102768
|
+
const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
|
|
102255
102769
|
return parsed.children || [];
|
|
102256
102770
|
};
|
|
102257
|
-
|
|
102258
|
-
|
|
102259
|
-
*/
|
|
102771
|
+
// Parses trailing content into sibling nodes and re-queues the parent so any
|
|
102772
|
+
// components among them get processed.
|
|
102260
102773
|
const parseSibling = (stack, parent, index, sibling, safeMode) => {
|
|
102261
102774
|
const siblingNodes = parseMdChildren(sibling, safeMode);
|
|
102262
|
-
// The new sibling nodes might contain new components to be processed
|
|
102263
102775
|
if (siblingNodes.length > 0) {
|
|
102264
102776
|
parent.children.splice(index + 1, 0, ...siblingNodes);
|
|
102265
102777
|
stack.push(parent);
|
|
102266
102778
|
}
|
|
102267
102779
|
};
|
|
102268
|
-
|
|
102269
|
-
|
|
102270
|
-
* component doesn't claim trailing content the tokenizer swallowed into one node.
|
|
102271
|
-
*/
|
|
102780
|
+
// Ends the position at `consumedLength` so the component doesn't claim trailing
|
|
102781
|
+
// content the tokenizer swallowed into the same html node.
|
|
102272
102782
|
const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
|
|
102273
102783
|
if (!nodePosition?.start)
|
|
102274
102784
|
return nodePosition;
|
|
102275
102785
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
|
|
102276
102786
|
};
|
|
102277
|
-
|
|
102278
|
-
|
|
102279
|
-
* this node's span in the original source. Used in the trailing-content path so
|
|
102280
|
-
* the offset is computed against the real source bytes (including blockquote/list
|
|
102281
|
-
* prefixes that were stripped from the html node's value).
|
|
102282
|
-
*/
|
|
102787
|
+
// Like `positionEndingAtConsumed`, but measures against the original source so
|
|
102788
|
+
// blockquote/list prefixes stripped from the html node's value are counted.
|
|
102283
102789
|
const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) => {
|
|
102284
102790
|
if (!nodePosition?.start || !nodePosition.end)
|
|
102285
102791
|
return nodePosition;
|
|
@@ -102290,9 +102796,6 @@ const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) =>
|
|
|
102290
102796
|
const consumed = nodeSource.slice(0, closingTagOffset + closingTag.length);
|
|
102291
102797
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumed) };
|
|
102292
102798
|
};
|
|
102293
|
-
/**
|
|
102294
|
-
* Create an MdxJsxFlowElement node from component data.
|
|
102295
|
-
*/
|
|
102296
102799
|
const createComponentNode = ({ tag, attributes, children, startPosition, endPosition }) => ({
|
|
102297
102800
|
type: 'mdxJsxFlowElement',
|
|
102298
102801
|
name: tag,
|
|
@@ -102314,6 +102817,10 @@ const substituteNodeWithMdxNode = (parent, index, mdxNode) => {
|
|
|
102314
102817
|
* This transformer identifies these patterns and converts them to proper MDX JSX elements so they
|
|
102315
102818
|
* can be accurately recognized and rendered later with their component definition code.
|
|
102316
102819
|
*
|
|
102820
|
+
* Note: The main goal is to promote PascalCase tags to MDX elements, but we want to promote
|
|
102821
|
+
* normal HTML to MDX elements in some cases so they get the full custom parsing behavior.
|
|
102822
|
+
* E.g. tags with JSX expressions, nested components, etc.
|
|
102823
|
+
*
|
|
102317
102824
|
* The mdx-component micromark tokenizer ensures that multi-line components are captured
|
|
102318
102825
|
* as single HTML nodes, so this transformer only needs to handle two cases:
|
|
102319
102826
|
*
|
|
@@ -102345,8 +102852,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102345
102852
|
if ('children' in node && Array.isArray(node.children)) {
|
|
102346
102853
|
stack.push(node);
|
|
102347
102854
|
}
|
|
102348
|
-
// Only
|
|
102349
|
-
// which means a potential unparsed MDX component
|
|
102855
|
+
// Only html nodes can be an unparsed MDX component.
|
|
102350
102856
|
const value = node.value;
|
|
102351
102857
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
102352
102858
|
return;
|
|
@@ -102355,32 +102861,34 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102355
102861
|
if (!parsed)
|
|
102356
102862
|
return;
|
|
102357
102863
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
102358
|
-
//
|
|
102359
|
-
// so consumed-length math maps back onto the node's real source offsets.
|
|
102864
|
+
// Offsets so consumed-length math maps back onto the node's real source.
|
|
102360
102865
|
const leadingWhitespace = value.length - value.trimStart().length;
|
|
102361
|
-
// Index right after the opening tag's `>` within `trimmed`.
|
|
102362
102866
|
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
102363
|
-
// Skip tags that have dedicated transformers
|
|
102364
102867
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
102365
|
-
return;
|
|
102868
|
+
return; // owned by dedicated transformers
|
|
102366
102869
|
const isPascal = isPascalCase(tag);
|
|
102367
|
-
//
|
|
102368
|
-
//
|
|
102369
|
-
//
|
|
102370
|
-
//
|
|
102371
|
-
// inline, which is how ReadMe's custom components are modeled).
|
|
102870
|
+
// ==== SPECIAL CASES TO PROMOTE NORMAL HTML TO MDX ELEMENTS ====
|
|
102871
|
+
// Lowercase inline tags with `{…}` attributes belong to
|
|
102872
|
+
// mdxishInlineComponentBlocks; leave them as html for that pass. PascalCase
|
|
102873
|
+
// components stay flow-level even when inline (ReadMe's component model).
|
|
102372
102874
|
if (!isPascal && parent.type === 'paragraph')
|
|
102373
102875
|
return;
|
|
102374
|
-
//
|
|
102375
|
-
//
|
|
102376
|
-
// JSX
|
|
102377
|
-
//
|
|
102378
|
-
// `
|
|
102379
|
-
//
|
|
102380
|
-
|
|
102381
|
-
|
|
102382
|
-
const
|
|
102383
|
-
|
|
102876
|
+
// A lowercase wrapper is only promoted when it (or a descendant) carries a
|
|
102877
|
+
// JSX expression or nests a component; otherwise it would swallow that inner
|
|
102878
|
+
// JSX/component as literal text that rehype-raw's parse5 pass can't handle.
|
|
102879
|
+
// Table-structural wrappers are excluded from both — `mdxishTables` re-parses
|
|
102880
|
+
// those, so a `{…}` in a cell (e.g. `<code>--depth={n}</code>`) must not
|
|
102881
|
+
// accidentally promote the table to an MDX element prematurely.
|
|
102882
|
+
const isTableStructuralTag = tag === 'table' || tableTags.has(tag);
|
|
102883
|
+
const hasNestedExpressionAttr = !selfClosing && !isTableStructuralTag && NESTED_ATTR_EXPRESSION_RE.test(contentAfterTag);
|
|
102884
|
+
const hasNestedComponentTag = !selfClosing && !isTableStructuralTag && hasNestedGenericComponentTag(contentAfterTag);
|
|
102885
|
+
// Promotion: By default commonmark doesn't parse markdown in single line HTML tags (e.g. <div>**bold**</div>)
|
|
102886
|
+
// To support that, we try to promote them to MDX elements so the markdown gets parsed
|
|
102887
|
+
const isPlainLowercaseHtml = !isPascal && !hasExpressionAttr(attributes) && !hasNestedExpressionAttr && !hasNestedComponentTag;
|
|
102888
|
+
const plainClosingTagIndex = isPlainLowercaseHtml && !selfClosing && isMarkdownPromotableHtmlTag(tag) && !NESTED_TABLE_RE.test(contentAfterTag)
|
|
102889
|
+
? findBalancedClosingTagIndex(contentAfterTag, tag)
|
|
102890
|
+
: -1;
|
|
102891
|
+
if (isPlainLowercaseHtml && plainClosingTagIndex < 0)
|
|
102384
102892
|
return;
|
|
102385
102893
|
const closingTagStr = `</${tag}>`;
|
|
102386
102894
|
// Case 1: Self-closing tag
|
|
@@ -102394,7 +102902,6 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102394
102902
|
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
102395
102903
|
});
|
|
102396
102904
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
102397
|
-
// Check and parse if there's relevant content after the current closing tag
|
|
102398
102905
|
const remainingContent = contentAfterTag.trim();
|
|
102399
102906
|
if (remainingContent) {
|
|
102400
102907
|
parseSibling(stack, parent, index, remainingContent, safeMode);
|
|
@@ -102402,18 +102909,27 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102402
102909
|
return;
|
|
102403
102910
|
}
|
|
102404
102911
|
// Case 2: Self-contained block (closing tag in content)
|
|
102405
|
-
|
|
102406
|
-
|
|
102407
|
-
|
|
102408
|
-
// Pass raw (untrimmed) content so dedent in parseMdChildren can
|
|
102409
|
-
// normalize indentation before trimming
|
|
102912
|
+
const closingTagIndex = isPlainLowercaseHtml ? plainClosingTagIndex : contentAfterTag.lastIndexOf(closingTagStr);
|
|
102913
|
+
if (closingTagIndex >= 0) {
|
|
102914
|
+
// Untrimmed so parseMdChildren can dedent before trimming.
|
|
102410
102915
|
const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
|
|
102411
102916
|
const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
|
|
102412
|
-
let parsedChildren =
|
|
102413
|
-
|
|
102414
|
-
|
|
102415
|
-
|
|
102416
|
-
|
|
102917
|
+
let parsedChildren = [];
|
|
102918
|
+
if (componentInnerContent.trim()) {
|
|
102919
|
+
try {
|
|
102920
|
+
parsedChildren = parseMdChildren(componentInnerContent, safeMode);
|
|
102921
|
+
}
|
|
102922
|
+
catch (error) {
|
|
102923
|
+
// Plain HTML bodies can hold anything (e.g. stray braces the strict
|
|
102924
|
+
// expression parser rejects) — keep the node raw instead of throwing.
|
|
102925
|
+
if (isPlainLowercaseHtml)
|
|
102926
|
+
return;
|
|
102927
|
+
throw error;
|
|
102928
|
+
}
|
|
102929
|
+
}
|
|
102930
|
+
if (isPlainLowercaseHtml && !containsMarkdownConstruct(parsedChildren))
|
|
102931
|
+
return;
|
|
102932
|
+
// Lowercase tags are usually inline; unwrap a sole paragraph so their
|
|
102417
102933
|
// phrasing content isn't spuriously block-wrapped.
|
|
102418
102934
|
if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
|
|
102419
102935
|
parsedChildren = parsedChildren[0].children;
|
|
@@ -102423,12 +102939,9 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102423
102939
|
attributes,
|
|
102424
102940
|
children: parsedChildren,
|
|
102425
102941
|
startPosition: node.position,
|
|
102426
|
-
//
|
|
102427
|
-
//
|
|
102428
|
-
//
|
|
102429
|
-
// node's value has '> '/space prefixes stripped for blockquotes/list items, so
|
|
102430
|
-
// positionEndingAtConsumed would undercount source offsets. When the entire node
|
|
102431
|
-
// is consumed, use the original node position directly.
|
|
102942
|
+
// With trailing content, end precisely at the closing tag. Prefer source
|
|
102943
|
+
// offsets when available (the node's value strips blockquote/list
|
|
102944
|
+
// prefixes); otherwise fall back to the whole node position.
|
|
102432
102945
|
endPosition: contentAfterClose
|
|
102433
102946
|
? source
|
|
102434
102947
|
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
@@ -102436,17 +102949,16 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102436
102949
|
: node.position,
|
|
102437
102950
|
});
|
|
102438
102951
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
102439
|
-
//
|
|
102952
|
+
// Re-queue whichever side may hold further components.
|
|
102440
102953
|
if (contentAfterClose) {
|
|
102441
102954
|
parseSibling(stack, parent, index, contentAfterClose, safeMode);
|
|
102442
102955
|
}
|
|
102443
102956
|
else if (componentNode.children.length > 0) {
|
|
102444
|
-
// The content inside the component block might contain new components to be processed
|
|
102445
102957
|
stack.push(componentNode);
|
|
102446
102958
|
}
|
|
102447
102959
|
}
|
|
102448
102960
|
};
|
|
102449
|
-
//
|
|
102961
|
+
// Depth-first so nodes keep their source order.
|
|
102450
102962
|
while (stack.length) {
|
|
102451
102963
|
const parent = stack.pop();
|
|
102452
102964
|
if (parent?.children) {
|
|
@@ -103981,9 +104493,6 @@ const magicBlockTransformer = (options = {}) => tree => {
|
|
|
103981
104493
|
// single-line `<div>…</div>`). CommonMark slurps the whole div as one `html`
|
|
103982
104494
|
// node, so the tokenizer never sees the HTMLBlock — we recover it here.
|
|
103983
104495
|
const RAW_HTML_BLOCK_RE = /<HTMLBlock\b([^>]*)>\s*\{\s*`((?:[^`\\]|\\.)*)`\s*\}\s*<\/HTMLBlock>/g;
|
|
103984
|
-
// Opening `<HTMLBlock …>` as its own `html` node — produced inside a paragraph
|
|
103985
|
-
// when an HTMLBlock appears inline alongside text.
|
|
103986
|
-
const HTML_BLOCK_OPEN_RE = /^<HTMLBlock\b([^>]*)>$/;
|
|
103987
104496
|
/**
|
|
103988
104497
|
* Builds the canonical `html-block` MDAST node the renderer expects.
|
|
103989
104498
|
*/
|
|
@@ -104064,13 +104573,14 @@ const splitRawHtmlBlocks = (node) => {
|
|
|
104064
104573
|
/**
|
|
104065
104574
|
* Converts every `<HTMLBlock>` shape that survives parsing into the canonical
|
|
104066
104575
|
* `html-block` MDAST node, reading the body from the tokenizer's template-literal
|
|
104067
|
-
* expression.
|
|
104576
|
+
* expression. Two shapes occur:
|
|
104068
104577
|
*
|
|
104069
|
-
* 1. JSX element (`mdxJsxFlowElement`/`mdxJsxTextElement`) —
|
|
104070
|
-
*
|
|
104071
|
-
*
|
|
104072
|
-
*
|
|
104073
|
-
*
|
|
104578
|
+
* 1. JSX element (`mdxJsxFlowElement`/`mdxJsxTextElement`) — table cells, after
|
|
104579
|
+
* their remarkMdx re-parse (that re-parse runs without the htmlBlockComponent
|
|
104580
|
+
* tokenizer, so `<HTMLBlock>` arrives as JSX rather than an opaque `html` node).
|
|
104581
|
+
* 2. Raw `html` blob (`splitRawHtmlBlocks`) — the htmlBlockComponent tokenizer's
|
|
104582
|
+
* opaque output (top-level and inline), or an `<HTMLBlock>` embedded in a
|
|
104583
|
+
* larger raw-HTML node like an inline `<div>` that the tokenizer never saw.
|
|
104074
104584
|
*
|
|
104075
104585
|
* Runs *after* `mdxishTables` so table cells are re-parsed first;
|
|
104076
104586
|
* `mdxishTables` recognizes the still-JSX `<HTMLBlock>` element when deciding to
|
|
@@ -104095,36 +104605,6 @@ const mdxishHtmlBlocks = () => tree => {
|
|
|
104095
104605
|
if (replacement)
|
|
104096
104606
|
parent.children.splice(index, 1, ...replacement);
|
|
104097
104607
|
});
|
|
104098
|
-
// Shape 3: inline within a paragraph — `<HTMLBlock>` open/close arrive as
|
|
104099
|
-
// separate `html` siblings with the template-literal expression between them.
|
|
104100
|
-
visit(tree, 'paragraph', (paragraph) => {
|
|
104101
|
-
// An html-block is block content, so it isn't a valid PhrasingContent child;
|
|
104102
|
-
// widen to RootContent (which HTMLBlock belongs to) for the in-place splice.
|
|
104103
|
-
const children = paragraph.children;
|
|
104104
|
-
for (let i = 0; i < children.length; i += 1) {
|
|
104105
|
-
const open = children[i];
|
|
104106
|
-
const openMatch = open.type === 'html' ? open.value.match(HTML_BLOCK_OPEN_RE) : null;
|
|
104107
|
-
if (!openMatch)
|
|
104108
|
-
continue; // eslint-disable-line no-continue
|
|
104109
|
-
const closeIdx = children.findIndex((child, j) => j > i && child.type === 'html' && child.value === '</HTMLBlock>');
|
|
104110
|
-
if (closeIdx === -1)
|
|
104111
|
-
continue; // eslint-disable-line no-continue
|
|
104112
|
-
const body = children
|
|
104113
|
-
.slice(i + 1, closeIdx)
|
|
104114
|
-
.map(child => {
|
|
104115
|
-
if (child.type === 'mdxTextExpression' || child.type === 'mdxFlowExpression') {
|
|
104116
|
-
return extractTemplateLiteral(child.value);
|
|
104117
|
-
}
|
|
104118
|
-
// Preserve raw text from any other phrasing sibling (e.g. stray
|
|
104119
|
-
// whitespace or content the tokenizer didn't claim) so it isn't
|
|
104120
|
-
// silently dropped from the html payload.
|
|
104121
|
-
return 'value' in child && typeof child.value === 'string' ? child.value : '';
|
|
104122
|
-
})
|
|
104123
|
-
.join('');
|
|
104124
|
-
const openingTagIndent = (open.position?.start.column ?? 1) - 1;
|
|
104125
|
-
children.splice(i, closeIdx - i + 1, htmlBlockFromRaw(openMatch[1], body, open.position, openingTagIndent));
|
|
104126
|
-
}
|
|
104127
|
-
});
|
|
104128
104608
|
};
|
|
104129
104609
|
/* harmony default export */ const mdxish_html_blocks = (mdxishHtmlBlocks);
|
|
104130
104610
|
|
|
@@ -104824,6 +105304,29 @@ const mdxishMermaidTransformer = () => (tree) => {
|
|
|
104824
105304
|
};
|
|
104825
105305
|
/* harmony default export */ const mdxish_mermaid = (mdxishMermaidTransformer);
|
|
104826
105306
|
|
|
105307
|
+
;// ./processor/transform/mdxish/normalize-closing-tag-whitespace.ts
|
|
105308
|
+
|
|
105309
|
+
|
|
105310
|
+
// Spaces/tabs only — newlines would let prose `<` / `>` across lines look like one tag.
|
|
105311
|
+
const SPACED_CLOSING_TAG_RE = /<\/[ \t]*([a-zA-Z][a-zA-Z0-9-]*)[ \t]*>/g;
|
|
105312
|
+
/**
|
|
105313
|
+
* Canonicalize spaced closing tags (`</ td >` → `</td>`) for known HTML names.
|
|
105314
|
+
*
|
|
105315
|
+
* In HTML, `</` + whitespace is a bogus comment, so `</ table >` never closes the
|
|
105316
|
+
* table (jsxTable misses it → empty table + pre; CX-3706). Only standard HTML tags;
|
|
105317
|
+
* custom components, prose (`a </ b`), and code blocks are left alone.
|
|
105318
|
+
*
|
|
105319
|
+
* @example
|
|
105320
|
+
* normalizeClosingTagWhitespace('</ td >') // '</td>'
|
|
105321
|
+
* normalizeClosingTagWhitespace('</table >') // '</table>'
|
|
105322
|
+
* normalizeClosingTagWhitespace('a </ b >') // unchanged
|
|
105323
|
+
*/
|
|
105324
|
+
function normalizeClosingTagWhitespace(content) {
|
|
105325
|
+
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
105326
|
+
const result = protectedContent.replace(SPACED_CLOSING_TAG_RE, (match, tagName) => STANDARD_HTML_TAGS.has(tagName.toLowerCase()) ? `</${tagName}>` : match);
|
|
105327
|
+
return restoreCodeBlocks(result, protectedCode);
|
|
105328
|
+
}
|
|
105329
|
+
|
|
104827
105330
|
;// ./processor/transform/mdxish/normalize-compact-headings.ts
|
|
104828
105331
|
|
|
104829
105332
|
/**
|
|
@@ -105279,278 +105782,488 @@ function normalizeTableSeparator(content) {
|
|
|
105279
105782
|
}
|
|
105280
105783
|
/* harmony default export */ const normalize_table_separator = ((/* unused pure expression or super */ null && (normalizeTableSeparator)));
|
|
105281
105784
|
|
|
105282
|
-
;// ./processor/transform/mdxish/
|
|
105283
|
-
|
|
105785
|
+
;// ./processor/transform/mdxish/variables-code.ts
|
|
105284
105786
|
|
|
105285
105787
|
|
|
105286
|
-
|
|
105287
|
-
const
|
|
105288
|
-
//
|
|
105289
|
-
|
|
105290
|
-
|
|
105291
|
-
|
|
105292
|
-
|
|
105293
|
-
|
|
105294
|
-
|
|
105295
|
-
|
|
105296
|
-
}));
|
|
105297
|
-
function isLineHtml(line) {
|
|
105298
|
-
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
105788
|
+
// Single combined regex so that resolved values from one pattern are never re-scanned by the other.
|
|
105789
|
+
const COMBINED_VARIABLE_REGEX = new RegExp(`${variable_.VARIABLE_REGEXP}|${variable_.MDX_VARIABLE_REGEXP}`, 'giu');
|
|
105790
|
+
// Flatten variables into a single object for easy lookup
|
|
105791
|
+
function variables_code_flattenVariables(variables) {
|
|
105792
|
+
if (!variables)
|
|
105793
|
+
return {};
|
|
105794
|
+
return {
|
|
105795
|
+
...Object.fromEntries((variables.defaults || []).map(d => [d.name, d.default])),
|
|
105796
|
+
...variables.user,
|
|
105797
|
+
};
|
|
105299
105798
|
}
|
|
105300
|
-
|
|
105301
|
-
|
|
105302
|
-
|
|
105303
|
-
|
|
105304
|
-
|
|
105305
|
-
|
|
105799
|
+
function resolveCodeVariables(value, resolvedVariables) {
|
|
105800
|
+
return value.replace(COMBINED_VARIABLE_REGEX, (match, legacyName, mdxEscapePrefix, mdxVarName, mdxEscapeSuffix) => {
|
|
105801
|
+
// Legacy variable: <<...>>
|
|
105802
|
+
if (legacyName !== undefined) {
|
|
105803
|
+
if (match.startsWith('\\<<') || match.endsWith('\\>>'))
|
|
105804
|
+
return match;
|
|
105805
|
+
const name = legacyName.trim();
|
|
105806
|
+
if (name.startsWith('glossary:'))
|
|
105807
|
+
return name.toUpperCase();
|
|
105808
|
+
return name in resolvedVariables ? resolvedVariables[name] : name.toUpperCase();
|
|
105809
|
+
}
|
|
105810
|
+
// MDX variable: {user.*}
|
|
105811
|
+
if (mdxEscapePrefix || mdxEscapeSuffix)
|
|
105812
|
+
return match;
|
|
105813
|
+
if (mdxVarName in resolvedVariables)
|
|
105814
|
+
return resolvedVariables[mdxVarName];
|
|
105815
|
+
const fullPath = match.slice(1, -1);
|
|
105816
|
+
return fullPath.toUpperCase();
|
|
105306
105817
|
});
|
|
105307
105818
|
}
|
|
105308
105819
|
/**
|
|
105309
|
-
*
|
|
105820
|
+
* A remark mdast plugin that resolves legacy variables <<...>> and MDX variables {user.*} inside code and inline code nodes
|
|
105821
|
+
* to their values. Uses regexes from the readme variable to search for variables in the code string.
|
|
105310
105822
|
*
|
|
105311
|
-
*
|
|
105312
|
-
*
|
|
105313
|
-
|
|
105314
|
-
|
|
105823
|
+
* This is needed because variables in code blocks and inline cannot be tokenized, and also we need to maintain the code string
|
|
105824
|
+
* in the code nodes. This enables engine side variable resolution in codes which improves UX
|
|
105825
|
+
*/
|
|
105826
|
+
const variablesCodeResolver = ({ variables } = {}) => tree => {
|
|
105827
|
+
const resolvedVariables = variables_code_flattenVariables(variables);
|
|
105828
|
+
visit(tree, 'inlineCode', (node) => {
|
|
105829
|
+
if (!node.value)
|
|
105830
|
+
return;
|
|
105831
|
+
node.value = resolveCodeVariables(node.value, resolvedVariables);
|
|
105832
|
+
});
|
|
105833
|
+
visit(tree, 'code', (node) => {
|
|
105834
|
+
if (!node.value)
|
|
105835
|
+
return;
|
|
105836
|
+
if (node.lang === 'mermaid')
|
|
105837
|
+
return;
|
|
105838
|
+
const nextValue = resolveCodeVariables(node.value, resolvedVariables);
|
|
105839
|
+
node.value = nextValue;
|
|
105840
|
+
// Keep code-tabs/readme-components hProperties in sync with node.value
|
|
105841
|
+
// because renderers read `value` from hProperties.
|
|
105842
|
+
if (node.data?.hProperties && typeof node.data.hProperties === 'object') {
|
|
105843
|
+
node.data.hProperties.value = nextValue;
|
|
105844
|
+
}
|
|
105845
|
+
});
|
|
105846
|
+
return tree;
|
|
105847
|
+
};
|
|
105848
|
+
/* harmony default export */ const variables_code = (variablesCodeResolver);
|
|
105849
|
+
|
|
105850
|
+
;// ./processor/transform/mdxish/variables-text.ts
|
|
105851
|
+
|
|
105852
|
+
|
|
105853
|
+
/**
|
|
105854
|
+
* Matches {user.<field>} patterns:
|
|
105855
|
+
* - {user.name}
|
|
105856
|
+
* - {user.email}
|
|
105857
|
+
* - {user['field']}
|
|
105858
|
+
* - {user["field"]}
|
|
105315
105859
|
*
|
|
105316
|
-
*
|
|
105860
|
+
* Captures the field name in group 1 (dot notation) or group 2 (bracket notation)
|
|
105861
|
+
*/
|
|
105862
|
+
const USER_VAR_REGEX = /\{user\.(\w+)\}|\{user\[['"](\w+)['"]\]\}/g;
|
|
105863
|
+
function makeVariableNode(varName, rawValue) {
|
|
105864
|
+
return {
|
|
105865
|
+
type: NodeTypes.variable,
|
|
105866
|
+
data: {
|
|
105867
|
+
hName: 'Variable',
|
|
105868
|
+
hProperties: { name: varName },
|
|
105869
|
+
},
|
|
105870
|
+
value: rawValue,
|
|
105871
|
+
};
|
|
105872
|
+
}
|
|
105873
|
+
/**
|
|
105874
|
+
* A remark plugin that parses {user.<field>} patterns from text nodes and
|
|
105875
|
+
* mdx expression nodes, creating Variable nodes for runtime resolution.
|
|
105317
105876
|
*
|
|
105318
|
-
*
|
|
105319
|
-
*
|
|
105320
|
-
*
|
|
105877
|
+
* Handles:
|
|
105878
|
+
* - `text` nodes: when safeMode is true or after expression evaluation
|
|
105879
|
+
* - `mdxTextExpression` nodes: when mdxExpression has parsed {user.*} before evaluation
|
|
105880
|
+
* - `mdxFlowExpression` nodes: when {user.*} appears on its own line (e.g. inside JSX table cells)
|
|
105321
105881
|
*
|
|
105322
|
-
*
|
|
105323
|
-
* 1. Only non-indented lines with lowercase tag names are considered. Uppercase tags
|
|
105324
|
-
* (e.g. `<Table>`, `<MyComponent>`) are JSX custom components and don't trigger
|
|
105325
|
-
* CommonMark HTML blocks.
|
|
105326
|
-
* 2. Lines inside protected blocks (e.g. fenced code) are left untouched.
|
|
105327
|
-
* 3. Lines with an unclosed RAW_CONTENT_TAGS opener are exempted.
|
|
105882
|
+
* Supports any user field: name, email, email_verified, exp, iat, etc.
|
|
105328
105883
|
*/
|
|
105329
|
-
function
|
|
105330
|
-
|
|
105331
|
-
|
|
105332
|
-
const
|
|
105333
|
-
|
|
105334
|
-
|
|
105335
|
-
|
|
105336
|
-
|
|
105337
|
-
|
|
105338
|
-
|
|
105884
|
+
function visitExpressionNode(node, index, parent) {
|
|
105885
|
+
if (index === undefined || !parent)
|
|
105886
|
+
return;
|
|
105887
|
+
const wrapped = `{${(node.value ?? '').trim()}}`;
|
|
105888
|
+
const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
|
|
105889
|
+
if (matches.length !== 1)
|
|
105890
|
+
return;
|
|
105891
|
+
const varName = matches[0][1] || matches[0][2];
|
|
105892
|
+
parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
|
|
105893
|
+
}
|
|
105894
|
+
const variablesTextTransformer = () => tree => {
|
|
105895
|
+
visit(tree, 'mdxTextExpression', (node, index, parent) => {
|
|
105896
|
+
visitExpressionNode(node, index, parent);
|
|
105897
|
+
});
|
|
105898
|
+
visit(tree, 'mdxFlowExpression', (node, index, parent) => {
|
|
105899
|
+
visitExpressionNode(node, index, parent);
|
|
105900
|
+
});
|
|
105901
|
+
visit(tree, 'text', (node, index, parent) => {
|
|
105902
|
+
if (index === undefined || !parent)
|
|
105903
|
+
return;
|
|
105904
|
+
// Skip if inside inline code
|
|
105905
|
+
if (parent.type === 'inlineCode')
|
|
105906
|
+
return;
|
|
105907
|
+
const text = node.value;
|
|
105908
|
+
if (typeof text !== 'string' || !text.trim())
|
|
105909
|
+
return;
|
|
105910
|
+
if (!text.includes('{user.') && !text.includes('{user['))
|
|
105911
|
+
return;
|
|
105912
|
+
const matches = [...text.matchAll(USER_VAR_REGEX)];
|
|
105913
|
+
if (matches.length === 0)
|
|
105914
|
+
return;
|
|
105915
|
+
const parts = [];
|
|
105916
|
+
let lastIndex = 0;
|
|
105917
|
+
matches.forEach(match => {
|
|
105918
|
+
const matchIndex = match.index ?? 0;
|
|
105919
|
+
// Add text before the match
|
|
105920
|
+
if (matchIndex > lastIndex) {
|
|
105921
|
+
parts.push({ type: 'text', value: text.slice(lastIndex, matchIndex) });
|
|
105922
|
+
}
|
|
105923
|
+
// Extract variable name from either capture group (dot or bracket notation)
|
|
105924
|
+
const varName = match[1] || match[2];
|
|
105925
|
+
parts.push(makeVariableNode(varName, match[0]));
|
|
105926
|
+
lastIndex = matchIndex + match[0].length;
|
|
105927
|
+
});
|
|
105928
|
+
// Add remaining text after last match
|
|
105929
|
+
if (lastIndex < text.length) {
|
|
105930
|
+
parts.push({ type: 'text', value: text.slice(lastIndex) });
|
|
105339
105931
|
}
|
|
105340
|
-
|
|
105341
|
-
|
|
105342
|
-
|
|
105343
|
-
|
|
105932
|
+
// Replace node with parts
|
|
105933
|
+
if (parts.length > 1 || (parts.length === 1 && parts[0].type !== 'text')) {
|
|
105934
|
+
parent.children.splice(index, 1, ...parts);
|
|
105935
|
+
}
|
|
105936
|
+
});
|
|
105937
|
+
return tree;
|
|
105938
|
+
};
|
|
105939
|
+
/* harmony default export */ const variables_text = (variablesTextTransformer);
|
|
105940
|
+
|
|
105941
|
+
;// ./lib/mdast-util/html-block-component/index.ts
|
|
105942
|
+
const html_block_component_contextMap = new WeakMap();
|
|
105943
|
+
function findHtmlBlockComponentToken() {
|
|
105944
|
+
const events = this.tokenStack;
|
|
105945
|
+
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
105946
|
+
if (events[i][0].type === 'htmlBlockComponent')
|
|
105947
|
+
return events[i][0];
|
|
105948
|
+
}
|
|
105949
|
+
return undefined;
|
|
105950
|
+
}
|
|
105951
|
+
function enterHtmlBlockComponent(token) {
|
|
105952
|
+
html_block_component_contextMap.set(token, { chunks: [], lastEndLine: token.start.line });
|
|
105953
|
+
this.enter({ type: 'html', value: '' }, token);
|
|
105954
|
+
}
|
|
105955
|
+
function exitHtmlBlockComponentData(token) {
|
|
105956
|
+
const componentToken = findHtmlBlockComponentToken.call(this);
|
|
105957
|
+
if (!componentToken)
|
|
105958
|
+
return;
|
|
105959
|
+
const ctx = html_block_component_contextMap.get(componentToken);
|
|
105960
|
+
if (ctx) {
|
|
105961
|
+
const gap = token.start.line - ctx.lastEndLine;
|
|
105962
|
+
if (ctx.chunks.length > 0 && gap > 0) {
|
|
105963
|
+
ctx.chunks.push('\n'.repeat(gap));
|
|
105964
|
+
}
|
|
105965
|
+
ctx.chunks.push(this.sliceSerialize(token));
|
|
105966
|
+
ctx.lastEndLine = token.end.line;
|
|
105967
|
+
}
|
|
105968
|
+
}
|
|
105969
|
+
function exitHtmlBlockComponent(token) {
|
|
105970
|
+
const ctx = html_block_component_contextMap.get(token);
|
|
105971
|
+
const node = this.stack[this.stack.length - 1];
|
|
105972
|
+
if (ctx) {
|
|
105973
|
+
node.value = ctx.chunks.join('');
|
|
105974
|
+
html_block_component_contextMap.delete(token);
|
|
105975
|
+
}
|
|
105976
|
+
this.exit(token);
|
|
105977
|
+
}
|
|
105978
|
+
function htmlBlockComponentFromMarkdown() {
|
|
105979
|
+
return {
|
|
105980
|
+
enter: {
|
|
105981
|
+
htmlBlockComponent: enterHtmlBlockComponent,
|
|
105982
|
+
},
|
|
105983
|
+
exit: {
|
|
105984
|
+
htmlBlockComponentData: exitHtmlBlockComponentData,
|
|
105985
|
+
htmlBlockComponent: exitHtmlBlockComponent,
|
|
105986
|
+
},
|
|
105987
|
+
};
|
|
105988
|
+
}
|
|
105989
|
+
|
|
105990
|
+
;// ./lib/micromark/html-block-component/syntax.ts
|
|
105991
|
+
|
|
105992
|
+
|
|
105993
|
+
const TAG_SUFFIX = [
|
|
105994
|
+
codes.uppercaseT,
|
|
105995
|
+
codes.uppercaseM,
|
|
105996
|
+
codes.uppercaseL,
|
|
105997
|
+
codes.uppercaseB,
|
|
105998
|
+
codes.lowercaseL,
|
|
105999
|
+
codes.lowercaseO,
|
|
106000
|
+
codes.lowercaseC,
|
|
106001
|
+
codes.lowercaseK,
|
|
106002
|
+
];
|
|
106003
|
+
// ---------------------------------------------------------------------------
|
|
106004
|
+
// Shared tokenizer factory
|
|
106005
|
+
// ---------------------------------------------------------------------------
|
|
106006
|
+
/**
|
|
106007
|
+
* Creates a tokenize function for `<HTMLBlock>...</HTMLBlock>`.
|
|
106008
|
+
*
|
|
106009
|
+
* - **flow** (block-level): supports multiline content via line continuations,
|
|
106010
|
+
* consumes trailing whitespace after the closing tag.
|
|
106011
|
+
* - **text** (inline): single-line only, exits immediately after the closing tag.
|
|
106012
|
+
*/
|
|
106013
|
+
function syntax_createTokenize(mode) {
|
|
106014
|
+
return function tokenize(effects, ok, nok) {
|
|
106015
|
+
let depth = 1;
|
|
106016
|
+
function matchChars(chars, onMatch, onFail) {
|
|
106017
|
+
if (chars.length === 0)
|
|
106018
|
+
return onMatch;
|
|
106019
|
+
const next = (code) => {
|
|
106020
|
+
if (code === chars[0]) {
|
|
106021
|
+
effects.consume(code);
|
|
106022
|
+
return matchChars(chars.slice(1), onMatch, onFail);
|
|
106023
|
+
}
|
|
106024
|
+
return onFail(code);
|
|
106025
|
+
};
|
|
106026
|
+
return next;
|
|
106027
|
+
}
|
|
106028
|
+
function matchTagName(onMatch, onFail) {
|
|
106029
|
+
const next = (code) => {
|
|
106030
|
+
if (code === codes.uppercaseH) {
|
|
106031
|
+
effects.consume(code);
|
|
106032
|
+
return matchChars(TAG_SUFFIX, onMatch, onFail);
|
|
106033
|
+
}
|
|
106034
|
+
return onFail(code);
|
|
106035
|
+
};
|
|
106036
|
+
return next;
|
|
106037
|
+
}
|
|
106038
|
+
return start;
|
|
106039
|
+
function start(code) {
|
|
106040
|
+
if (code !== codes.lessThan)
|
|
106041
|
+
return nok(code);
|
|
106042
|
+
effects.enter('htmlBlockComponent');
|
|
106043
|
+
effects.enter('htmlBlockComponentData');
|
|
106044
|
+
effects.consume(code);
|
|
106045
|
+
return matchTagName(afterTagName, nok);
|
|
106046
|
+
}
|
|
106047
|
+
function afterTagName(code) {
|
|
106048
|
+
if (code === codes.greaterThan) {
|
|
106049
|
+
effects.consume(code);
|
|
106050
|
+
return body;
|
|
106051
|
+
}
|
|
106052
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
106053
|
+
effects.consume(code);
|
|
106054
|
+
return inAttributes;
|
|
106055
|
+
}
|
|
106056
|
+
if (mode === 'flow' && markdownLineEnding(code)) {
|
|
106057
|
+
effects.exit('htmlBlockComponentData');
|
|
106058
|
+
return attributeContinuationStart(code);
|
|
106059
|
+
}
|
|
106060
|
+
if (code === codes.slash) {
|
|
106061
|
+
effects.consume(code);
|
|
106062
|
+
return selfClose;
|
|
106063
|
+
}
|
|
106064
|
+
return nok(code);
|
|
106065
|
+
}
|
|
106066
|
+
function inAttributes(code) {
|
|
106067
|
+
if (code === codes.greaterThan) {
|
|
106068
|
+
effects.consume(code);
|
|
106069
|
+
return body;
|
|
106070
|
+
}
|
|
106071
|
+
if (code === null) {
|
|
106072
|
+
return nok(code);
|
|
106073
|
+
}
|
|
106074
|
+
if (markdownLineEnding(code)) {
|
|
106075
|
+
if (mode === 'text')
|
|
106076
|
+
return nok(code);
|
|
106077
|
+
effects.exit('htmlBlockComponentData');
|
|
106078
|
+
return attributeContinuationStart(code);
|
|
106079
|
+
}
|
|
106080
|
+
effects.consume(code);
|
|
106081
|
+
return inAttributes;
|
|
106082
|
+
}
|
|
106083
|
+
function attributeContinuationStart(code) {
|
|
106084
|
+
return effects.check(html_block_component_syntax_nonLazyContinuationStart, attributeContinuationNonLazy, continuationAfter)(code);
|
|
106085
|
+
}
|
|
106086
|
+
function attributeContinuationNonLazy(code) {
|
|
106087
|
+
effects.enter(types_types.lineEnding);
|
|
106088
|
+
effects.consume(code);
|
|
106089
|
+
effects.exit(types_types.lineEnding);
|
|
106090
|
+
return attributeContinuationBefore;
|
|
106091
|
+
}
|
|
106092
|
+
function attributeContinuationBefore(code) {
|
|
106093
|
+
if (code === null || markdownLineEnding(code)) {
|
|
106094
|
+
return attributeContinuationStart(code);
|
|
106095
|
+
}
|
|
106096
|
+
effects.enter('htmlBlockComponentData');
|
|
106097
|
+
return inAttributes(code);
|
|
106098
|
+
}
|
|
106099
|
+
function selfClose(code) {
|
|
106100
|
+
if (code === codes.greaterThan) {
|
|
106101
|
+
effects.consume(code);
|
|
106102
|
+
return mode === 'flow' ? afterClose : done(code);
|
|
106103
|
+
}
|
|
106104
|
+
return nok(code);
|
|
106105
|
+
}
|
|
106106
|
+
function body(code) {
|
|
106107
|
+
if (code === null)
|
|
106108
|
+
return nok(code);
|
|
106109
|
+
if (markdownLineEnding(code)) {
|
|
106110
|
+
if (mode === 'text') {
|
|
106111
|
+
// Text constructs operate on paragraph content which spans lines
|
|
106112
|
+
effects.consume(code);
|
|
106113
|
+
return body;
|
|
106114
|
+
}
|
|
106115
|
+
effects.exit('htmlBlockComponentData');
|
|
106116
|
+
return continuationStart(code);
|
|
106117
|
+
}
|
|
106118
|
+
if (code === codes.lessThan) {
|
|
106119
|
+
effects.consume(code);
|
|
106120
|
+
return closeSlash;
|
|
106121
|
+
}
|
|
106122
|
+
effects.consume(code);
|
|
106123
|
+
return body;
|
|
106124
|
+
}
|
|
106125
|
+
function closeSlash(code) {
|
|
106126
|
+
if (code === codes.slash) {
|
|
106127
|
+
effects.consume(code);
|
|
106128
|
+
return matchTagName(closeGt, body);
|
|
106129
|
+
}
|
|
106130
|
+
return matchTagName(openAfterTagName, body)(code);
|
|
106131
|
+
}
|
|
106132
|
+
function openAfterTagName(code) {
|
|
106133
|
+
if (code === codes.greaterThan || code === codes.space || code === codes.horizontalTab) {
|
|
106134
|
+
depth += 1;
|
|
106135
|
+
effects.consume(code);
|
|
106136
|
+
return body;
|
|
106137
|
+
}
|
|
106138
|
+
return body(code);
|
|
106139
|
+
}
|
|
106140
|
+
function closeGt(code) {
|
|
106141
|
+
if (code === codes.greaterThan) {
|
|
106142
|
+
depth -= 1;
|
|
106143
|
+
effects.consume(code);
|
|
106144
|
+
if (depth === 0) {
|
|
106145
|
+
return mode === 'flow' ? afterClose : done(code);
|
|
106146
|
+
}
|
|
106147
|
+
return body;
|
|
106148
|
+
}
|
|
106149
|
+
return body(code);
|
|
106150
|
+
}
|
|
106151
|
+
// -- flow-only states ---------------------------------------------------
|
|
106152
|
+
function afterClose(code) {
|
|
106153
|
+
if (code === null || markdownLineEnding(code)) {
|
|
106154
|
+
return done(code);
|
|
106155
|
+
}
|
|
106156
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
106157
|
+
effects.consume(code);
|
|
106158
|
+
return afterClose;
|
|
106159
|
+
}
|
|
106160
|
+
// Reject so the block re-parses as a paragraph, deferring to the
|
|
106161
|
+
// text tokenizer which preserves trailing content in the same line.
|
|
106162
|
+
return nok(code);
|
|
105344
106163
|
}
|
|
105345
|
-
|
|
105346
|
-
|
|
105347
|
-
|
|
105348
|
-
|
|
105349
|
-
;// ./processor/transform/mdxish/variables-code.ts
|
|
105350
|
-
|
|
105351
|
-
|
|
105352
|
-
// Single combined regex so that resolved values from one pattern are never re-scanned by the other.
|
|
105353
|
-
const COMBINED_VARIABLE_REGEX = new RegExp(`${variable_.VARIABLE_REGEXP}|${variable_.MDX_VARIABLE_REGEXP}`, 'giu');
|
|
105354
|
-
// Flatten variables into a single object for easy lookup
|
|
105355
|
-
function variables_code_flattenVariables(variables) {
|
|
105356
|
-
if (!variables)
|
|
105357
|
-
return {};
|
|
105358
|
-
return {
|
|
105359
|
-
...Object.fromEntries((variables.defaults || []).map(d => [d.name, d.default])),
|
|
105360
|
-
...variables.user,
|
|
105361
|
-
};
|
|
105362
|
-
}
|
|
105363
|
-
function resolveCodeVariables(value, resolvedVariables) {
|
|
105364
|
-
return value.replace(COMBINED_VARIABLE_REGEX, (match, legacyName, mdxEscapePrefix, mdxVarName, mdxEscapeSuffix) => {
|
|
105365
|
-
// Legacy variable: <<...>>
|
|
105366
|
-
if (legacyName !== undefined) {
|
|
105367
|
-
if (match.startsWith('\\<<') || match.endsWith('\\>>'))
|
|
105368
|
-
return match;
|
|
105369
|
-
const name = legacyName.trim();
|
|
105370
|
-
if (name.startsWith('glossary:'))
|
|
105371
|
-
return name.toUpperCase();
|
|
105372
|
-
return name in resolvedVariables ? resolvedVariables[name] : name.toUpperCase();
|
|
106164
|
+
// -- flow-only: line continuation ---------------------------------------
|
|
106165
|
+
function continuationStart(code) {
|
|
106166
|
+
return effects.check(html_block_component_syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
105373
106167
|
}
|
|
105374
|
-
|
|
105375
|
-
|
|
105376
|
-
|
|
105377
|
-
|
|
105378
|
-
return
|
|
105379
|
-
const fullPath = match.slice(1, -1);
|
|
105380
|
-
return fullPath.toUpperCase();
|
|
105381
|
-
});
|
|
105382
|
-
}
|
|
105383
|
-
/**
|
|
105384
|
-
* A remark mdast plugin that resolves legacy variables <<...>> and MDX variables {user.*} inside code and inline code nodes
|
|
105385
|
-
* to their values. Uses regexes from the readme variable to search for variables in the code string.
|
|
105386
|
-
*
|
|
105387
|
-
* This is needed because variables in code blocks and inline cannot be tokenized, and also we need to maintain the code string
|
|
105388
|
-
* in the code nodes. This enables engine side variable resolution in codes which improves UX
|
|
105389
|
-
*/
|
|
105390
|
-
const variablesCodeResolver = ({ variables } = {}) => tree => {
|
|
105391
|
-
const resolvedVariables = variables_code_flattenVariables(variables);
|
|
105392
|
-
visit(tree, 'inlineCode', (node) => {
|
|
105393
|
-
if (!node.value)
|
|
105394
|
-
return;
|
|
105395
|
-
node.value = resolveCodeVariables(node.value, resolvedVariables);
|
|
105396
|
-
});
|
|
105397
|
-
visit(tree, 'code', (node) => {
|
|
105398
|
-
if (!node.value)
|
|
105399
|
-
return;
|
|
105400
|
-
if (node.lang === 'mermaid')
|
|
105401
|
-
return;
|
|
105402
|
-
const nextValue = resolveCodeVariables(node.value, resolvedVariables);
|
|
105403
|
-
node.value = nextValue;
|
|
105404
|
-
// Keep code-tabs/readme-components hProperties in sync with node.value
|
|
105405
|
-
// because renderers read `value` from hProperties.
|
|
105406
|
-
if (node.data?.hProperties && typeof node.data.hProperties === 'object') {
|
|
105407
|
-
node.data.hProperties.value = nextValue;
|
|
106168
|
+
function continuationStartNonLazy(code) {
|
|
106169
|
+
effects.enter(types_types.lineEnding);
|
|
106170
|
+
effects.consume(code);
|
|
106171
|
+
effects.exit(types_types.lineEnding);
|
|
106172
|
+
return continuationBefore;
|
|
105408
106173
|
}
|
|
105409
|
-
|
|
105410
|
-
|
|
105411
|
-
|
|
105412
|
-
/* harmony default export */ const variables_code = (variablesCodeResolver);
|
|
105413
|
-
|
|
105414
|
-
;// ./processor/transform/mdxish/variables-text.ts
|
|
105415
|
-
|
|
105416
|
-
|
|
105417
|
-
/**
|
|
105418
|
-
* Matches {user.<field>} patterns:
|
|
105419
|
-
* - {user.name}
|
|
105420
|
-
* - {user.email}
|
|
105421
|
-
* - {user['field']}
|
|
105422
|
-
* - {user["field"]}
|
|
105423
|
-
*
|
|
105424
|
-
* Captures the field name in group 1 (dot notation) or group 2 (bracket notation)
|
|
105425
|
-
*/
|
|
105426
|
-
const USER_VAR_REGEX = /\{user\.(\w+)\}|\{user\[['"](\w+)['"]\]\}/g;
|
|
105427
|
-
function makeVariableNode(varName, rawValue) {
|
|
105428
|
-
return {
|
|
105429
|
-
type: NodeTypes.variable,
|
|
105430
|
-
data: {
|
|
105431
|
-
hName: 'Variable',
|
|
105432
|
-
hProperties: { name: varName },
|
|
105433
|
-
},
|
|
105434
|
-
value: rawValue,
|
|
105435
|
-
};
|
|
105436
|
-
}
|
|
105437
|
-
/**
|
|
105438
|
-
* A remark plugin that parses {user.<field>} patterns from text nodes and
|
|
105439
|
-
* mdx expression nodes, creating Variable nodes for runtime resolution.
|
|
105440
|
-
*
|
|
105441
|
-
* Handles:
|
|
105442
|
-
* - `text` nodes: when safeMode is true or after expression evaluation
|
|
105443
|
-
* - `mdxTextExpression` nodes: when mdxExpression has parsed {user.*} before evaluation
|
|
105444
|
-
* - `mdxFlowExpression` nodes: when {user.*} appears on its own line (e.g. inside JSX table cells)
|
|
105445
|
-
*
|
|
105446
|
-
* Supports any user field: name, email, email_verified, exp, iat, etc.
|
|
105447
|
-
*/
|
|
105448
|
-
function visitExpressionNode(node, index, parent) {
|
|
105449
|
-
if (index === undefined || !parent)
|
|
105450
|
-
return;
|
|
105451
|
-
const wrapped = `{${(node.value ?? '').trim()}}`;
|
|
105452
|
-
const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
|
|
105453
|
-
if (matches.length !== 1)
|
|
105454
|
-
return;
|
|
105455
|
-
const varName = matches[0][1] || matches[0][2];
|
|
105456
|
-
parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
|
|
105457
|
-
}
|
|
105458
|
-
const variablesTextTransformer = () => tree => {
|
|
105459
|
-
visit(tree, 'mdxTextExpression', (node, index, parent) => {
|
|
105460
|
-
visitExpressionNode(node, index, parent);
|
|
105461
|
-
});
|
|
105462
|
-
visit(tree, 'mdxFlowExpression', (node, index, parent) => {
|
|
105463
|
-
visitExpressionNode(node, index, parent);
|
|
105464
|
-
});
|
|
105465
|
-
visit(tree, 'text', (node, index, parent) => {
|
|
105466
|
-
if (index === undefined || !parent)
|
|
105467
|
-
return;
|
|
105468
|
-
// Skip if inside inline code
|
|
105469
|
-
if (parent.type === 'inlineCode')
|
|
105470
|
-
return;
|
|
105471
|
-
const text = node.value;
|
|
105472
|
-
if (typeof text !== 'string' || !text.trim())
|
|
105473
|
-
return;
|
|
105474
|
-
if (!text.includes('{user.') && !text.includes('{user['))
|
|
105475
|
-
return;
|
|
105476
|
-
const matches = [...text.matchAll(USER_VAR_REGEX)];
|
|
105477
|
-
if (matches.length === 0)
|
|
105478
|
-
return;
|
|
105479
|
-
const parts = [];
|
|
105480
|
-
let lastIndex = 0;
|
|
105481
|
-
matches.forEach(match => {
|
|
105482
|
-
const matchIndex = match.index ?? 0;
|
|
105483
|
-
// Add text before the match
|
|
105484
|
-
if (matchIndex > lastIndex) {
|
|
105485
|
-
parts.push({ type: 'text', value: text.slice(lastIndex, matchIndex) });
|
|
106174
|
+
function continuationBefore(code) {
|
|
106175
|
+
if (code === null || markdownLineEnding(code)) {
|
|
106176
|
+
return continuationStart(code);
|
|
105486
106177
|
}
|
|
105487
|
-
|
|
105488
|
-
|
|
105489
|
-
parts.push(makeVariableNode(varName, match[0]));
|
|
105490
|
-
lastIndex = matchIndex + match[0].length;
|
|
105491
|
-
});
|
|
105492
|
-
// Add remaining text after last match
|
|
105493
|
-
if (lastIndex < text.length) {
|
|
105494
|
-
parts.push({ type: 'text', value: text.slice(lastIndex) });
|
|
106178
|
+
effects.enter('htmlBlockComponentData');
|
|
106179
|
+
return body(code);
|
|
105495
106180
|
}
|
|
105496
|
-
|
|
105497
|
-
|
|
105498
|
-
|
|
106181
|
+
function continuationAfter(code) {
|
|
106182
|
+
if (code === null)
|
|
106183
|
+
return nok(code);
|
|
106184
|
+
effects.exit('htmlBlockComponent');
|
|
106185
|
+
return ok(code);
|
|
105499
106186
|
}
|
|
105500
|
-
|
|
105501
|
-
|
|
106187
|
+
// -- shared exit --------------------------------------------------------
|
|
106188
|
+
function done(_code) {
|
|
106189
|
+
effects.exit('htmlBlockComponentData');
|
|
106190
|
+
effects.exit('htmlBlockComponent');
|
|
106191
|
+
return ok(_code);
|
|
106192
|
+
}
|
|
106193
|
+
};
|
|
106194
|
+
}
|
|
106195
|
+
// ---------------------------------------------------------------------------
|
|
106196
|
+
// Flow construct (block-level)
|
|
106197
|
+
// ---------------------------------------------------------------------------
|
|
106198
|
+
const html_block_component_syntax_nonLazyContinuationStart = {
|
|
106199
|
+
tokenize: html_block_component_syntax_tokenizeNonLazyContinuationStart,
|
|
106200
|
+
partial: true,
|
|
105502
106201
|
};
|
|
105503
|
-
|
|
105504
|
-
|
|
105505
|
-
|
|
105506
|
-
|
|
105507
|
-
|
|
105508
|
-
|
|
105509
|
-
|
|
105510
|
-
if (events[i][0].type === 'jsxTable')
|
|
105511
|
-
return events[i][0];
|
|
106202
|
+
function resolveToHtmlBlockComponent(events) {
|
|
106203
|
+
let index = events.length;
|
|
106204
|
+
while (index > 0) {
|
|
106205
|
+
index -= 1;
|
|
106206
|
+
if (events[index][0] === 'enter' && events[index][1].type === 'htmlBlockComponent') {
|
|
106207
|
+
break;
|
|
106208
|
+
}
|
|
105512
106209
|
}
|
|
105513
|
-
|
|
105514
|
-
|
|
105515
|
-
|
|
105516
|
-
|
|
105517
|
-
|
|
106210
|
+
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
106211
|
+
events[index][1].start = events[index - 2][1].start;
|
|
106212
|
+
events[index + 1][1].start = events[index - 2][1].start;
|
|
106213
|
+
events.splice(index - 2, 2);
|
|
106214
|
+
}
|
|
106215
|
+
return events;
|
|
105518
106216
|
}
|
|
105519
|
-
|
|
105520
|
-
|
|
105521
|
-
|
|
105522
|
-
|
|
105523
|
-
|
|
105524
|
-
|
|
105525
|
-
|
|
105526
|
-
|
|
105527
|
-
|
|
106217
|
+
const htmlBlockComponentFlowConstruct = {
|
|
106218
|
+
name: 'htmlBlockComponent',
|
|
106219
|
+
tokenize: syntax_createTokenize('flow'),
|
|
106220
|
+
resolveTo: resolveToHtmlBlockComponent,
|
|
106221
|
+
concrete: true,
|
|
106222
|
+
};
|
|
106223
|
+
function html_block_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
106224
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
106225
|
+
const self = this;
|
|
106226
|
+
return start;
|
|
106227
|
+
function start(code) {
|
|
106228
|
+
if (markdownLineEnding(code)) {
|
|
106229
|
+
effects.enter(types_types.lineEnding);
|
|
106230
|
+
effects.consume(code);
|
|
106231
|
+
effects.exit(types_types.lineEnding);
|
|
106232
|
+
return after;
|
|
105528
106233
|
}
|
|
105529
|
-
|
|
105530
|
-
ctx.lastEndLine = token.end.line;
|
|
106234
|
+
return nok(code);
|
|
105531
106235
|
}
|
|
105532
|
-
|
|
105533
|
-
|
|
105534
|
-
|
|
105535
|
-
|
|
105536
|
-
|
|
105537
|
-
node.value = ctx.chunks.join('');
|
|
105538
|
-
jsx_table_contextMap.delete(token);
|
|
106236
|
+
function after(code) {
|
|
106237
|
+
if (self.parser.lazy[self.now().line]) {
|
|
106238
|
+
return nok(code);
|
|
106239
|
+
}
|
|
106240
|
+
return ok(code);
|
|
105539
106241
|
}
|
|
105540
|
-
this.exit(token);
|
|
105541
106242
|
}
|
|
105542
|
-
|
|
106243
|
+
// ---------------------------------------------------------------------------
|
|
106244
|
+
// Text construct (inline)
|
|
106245
|
+
// ---------------------------------------------------------------------------
|
|
106246
|
+
const htmlBlockComponentTextConstruct = {
|
|
106247
|
+
name: 'htmlBlockComponent',
|
|
106248
|
+
tokenize: syntax_createTokenize('text'),
|
|
106249
|
+
};
|
|
106250
|
+
// ---------------------------------------------------------------------------
|
|
106251
|
+
// Extension
|
|
106252
|
+
// ---------------------------------------------------------------------------
|
|
106253
|
+
function htmlBlockComponent() {
|
|
105543
106254
|
return {
|
|
105544
|
-
|
|
105545
|
-
|
|
106255
|
+
flow: {
|
|
106256
|
+
[codes.lessThan]: [htmlBlockComponentFlowConstruct],
|
|
105546
106257
|
},
|
|
105547
|
-
|
|
105548
|
-
|
|
105549
|
-
jsxTable: exitJsxTable,
|
|
106258
|
+
text: {
|
|
106259
|
+
[codes.lessThan]: [htmlBlockComponentTextConstruct],
|
|
105550
106260
|
},
|
|
105551
106261
|
};
|
|
105552
106262
|
}
|
|
105553
106263
|
|
|
106264
|
+
;// ./lib/micromark/html-block-component/index.ts
|
|
106265
|
+
|
|
106266
|
+
|
|
105554
106267
|
;// ./lib/micromark/jsx-comment/syntax.ts
|
|
105555
106268
|
|
|
105556
106269
|
|
|
@@ -105673,243 +106386,6 @@ function jsxComment() {
|
|
|
105673
106386
|
};
|
|
105674
106387
|
}
|
|
105675
106388
|
|
|
105676
|
-
;// ./lib/micromark/jsx-table/syntax.ts
|
|
105677
|
-
|
|
105678
|
-
|
|
105679
|
-
const jsx_table_syntax_nonLazyContinuationStart = {
|
|
105680
|
-
tokenize: jsx_table_syntax_tokenizeNonLazyContinuationStart,
|
|
105681
|
-
partial: true,
|
|
105682
|
-
};
|
|
105683
|
-
function resolveToJsxTable(events) {
|
|
105684
|
-
let index = events.length;
|
|
105685
|
-
while (index > 0) {
|
|
105686
|
-
index -= 1;
|
|
105687
|
-
if (events[index][0] === 'enter' && events[index][1].type === 'jsxTable') {
|
|
105688
|
-
break;
|
|
105689
|
-
}
|
|
105690
|
-
}
|
|
105691
|
-
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
105692
|
-
events[index][1].start = events[index - 2][1].start;
|
|
105693
|
-
events[index + 1][1].start = events[index - 2][1].start;
|
|
105694
|
-
events.splice(index - 2, 2);
|
|
105695
|
-
}
|
|
105696
|
-
return events;
|
|
105697
|
-
}
|
|
105698
|
-
const jsxTableConstruct = {
|
|
105699
|
-
name: 'jsxTable',
|
|
105700
|
-
tokenize: tokenizeJsxTable,
|
|
105701
|
-
resolveTo: resolveToJsxTable,
|
|
105702
|
-
concrete: true,
|
|
105703
|
-
};
|
|
105704
|
-
function tokenizeJsxTable(effects, ok, nok) {
|
|
105705
|
-
let codeSpanOpenSize = 0;
|
|
105706
|
-
let codeSpanCloseSize = 0;
|
|
105707
|
-
let depth = 1;
|
|
105708
|
-
const ABLE_SUFFIX = [codes.lowercaseA, codes.lowercaseB, codes.lowercaseL, codes.lowercaseE];
|
|
105709
|
-
/** Build a state chain that matches a sequence of character codes. */
|
|
105710
|
-
function matchChars(chars, onMatch, onFail) {
|
|
105711
|
-
if (chars.length === 0)
|
|
105712
|
-
return onMatch;
|
|
105713
|
-
return ((code) => {
|
|
105714
|
-
if (code === chars[0]) {
|
|
105715
|
-
effects.consume(code);
|
|
105716
|
-
return matchChars(chars.slice(1), onMatch, onFail);
|
|
105717
|
-
}
|
|
105718
|
-
return onFail(code);
|
|
105719
|
-
});
|
|
105720
|
-
}
|
|
105721
|
-
return start;
|
|
105722
|
-
function start(code) {
|
|
105723
|
-
if (code !== codes.lessThan)
|
|
105724
|
-
return nok(code);
|
|
105725
|
-
effects.enter('jsxTable');
|
|
105726
|
-
effects.enter('jsxTableData');
|
|
105727
|
-
effects.consume(code);
|
|
105728
|
-
return afterLessThan;
|
|
105729
|
-
}
|
|
105730
|
-
function afterLessThan(code) {
|
|
105731
|
-
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
105732
|
-
effects.consume(code);
|
|
105733
|
-
return matchChars(ABLE_SUFFIX, afterTagName, nok);
|
|
105734
|
-
}
|
|
105735
|
-
return nok(code);
|
|
105736
|
-
}
|
|
105737
|
-
function afterTagName(code) {
|
|
105738
|
-
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
105739
|
-
effects.consume(code);
|
|
105740
|
-
return body;
|
|
105741
|
-
}
|
|
105742
|
-
return nok(code);
|
|
105743
|
-
}
|
|
105744
|
-
function body(code) {
|
|
105745
|
-
// Reject unclosed <Table> so it falls back to normal HTML block parsing
|
|
105746
|
-
// instead of swallowing all subsequent content to EOF
|
|
105747
|
-
if (code === null) {
|
|
105748
|
-
return nok(code);
|
|
105749
|
-
}
|
|
105750
|
-
if (markdownLineEnding(code)) {
|
|
105751
|
-
effects.exit('jsxTableData');
|
|
105752
|
-
return continuationStart(code);
|
|
105753
|
-
}
|
|
105754
|
-
if (code === codes.backslash) {
|
|
105755
|
-
effects.consume(code);
|
|
105756
|
-
return escapedChar;
|
|
105757
|
-
}
|
|
105758
|
-
if (code === codes.lessThan) {
|
|
105759
|
-
effects.consume(code);
|
|
105760
|
-
return closeSlash;
|
|
105761
|
-
}
|
|
105762
|
-
// Skip over backtick code spans so `</Table>` in inline code isn't
|
|
105763
|
-
// treated as the closing tag
|
|
105764
|
-
if (code === codes.graveAccent) {
|
|
105765
|
-
codeSpanOpenSize = 0;
|
|
105766
|
-
return countOpenTicks(code);
|
|
105767
|
-
}
|
|
105768
|
-
effects.consume(code);
|
|
105769
|
-
return body;
|
|
105770
|
-
}
|
|
105771
|
-
function countOpenTicks(code) {
|
|
105772
|
-
if (code === codes.graveAccent) {
|
|
105773
|
-
codeSpanOpenSize += 1;
|
|
105774
|
-
effects.consume(code);
|
|
105775
|
-
return countOpenTicks;
|
|
105776
|
-
}
|
|
105777
|
-
return inCodeSpan(code);
|
|
105778
|
-
}
|
|
105779
|
-
function inCodeSpan(code) {
|
|
105780
|
-
if (code === null || markdownLineEnding(code))
|
|
105781
|
-
return body(code);
|
|
105782
|
-
if (code === codes.graveAccent) {
|
|
105783
|
-
codeSpanCloseSize = 0;
|
|
105784
|
-
return countCloseTicks(code);
|
|
105785
|
-
}
|
|
105786
|
-
effects.consume(code);
|
|
105787
|
-
return inCodeSpan;
|
|
105788
|
-
}
|
|
105789
|
-
function countCloseTicks(code) {
|
|
105790
|
-
if (code === codes.graveAccent) {
|
|
105791
|
-
codeSpanCloseSize += 1;
|
|
105792
|
-
effects.consume(code);
|
|
105793
|
-
return countCloseTicks;
|
|
105794
|
-
}
|
|
105795
|
-
return codeSpanCloseSize === codeSpanOpenSize ? body(code) : inCodeSpan(code);
|
|
105796
|
-
}
|
|
105797
|
-
function escapedChar(code) {
|
|
105798
|
-
if (code === null || markdownLineEnding(code)) {
|
|
105799
|
-
return body(code);
|
|
105800
|
-
}
|
|
105801
|
-
effects.consume(code);
|
|
105802
|
-
return body;
|
|
105803
|
-
}
|
|
105804
|
-
function closeSlash(code) {
|
|
105805
|
-
if (code === codes.slash) {
|
|
105806
|
-
effects.consume(code);
|
|
105807
|
-
return closeTagFirstChar;
|
|
105808
|
-
}
|
|
105809
|
-
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
105810
|
-
effects.consume(code);
|
|
105811
|
-
return matchChars(ABLE_SUFFIX, openAfterTagName, body);
|
|
105812
|
-
}
|
|
105813
|
-
return body(code);
|
|
105814
|
-
}
|
|
105815
|
-
function closeTagFirstChar(code) {
|
|
105816
|
-
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
105817
|
-
effects.consume(code);
|
|
105818
|
-
return matchChars(ABLE_SUFFIX, closeGt, body);
|
|
105819
|
-
}
|
|
105820
|
-
return body(code);
|
|
105821
|
-
}
|
|
105822
|
-
function openAfterTagName(code) {
|
|
105823
|
-
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
105824
|
-
depth += 1;
|
|
105825
|
-
effects.consume(code);
|
|
105826
|
-
return body;
|
|
105827
|
-
}
|
|
105828
|
-
return body(code);
|
|
105829
|
-
}
|
|
105830
|
-
function closeGt(code) {
|
|
105831
|
-
if (code === codes.greaterThan) {
|
|
105832
|
-
depth -= 1;
|
|
105833
|
-
effects.consume(code);
|
|
105834
|
-
if (depth === 0) {
|
|
105835
|
-
return afterClose;
|
|
105836
|
-
}
|
|
105837
|
-
return body;
|
|
105838
|
-
}
|
|
105839
|
-
return body(code);
|
|
105840
|
-
}
|
|
105841
|
-
function afterClose(code) {
|
|
105842
|
-
if (code === null || markdownLineEnding(code)) {
|
|
105843
|
-
effects.exit('jsxTableData');
|
|
105844
|
-
effects.exit('jsxTable');
|
|
105845
|
-
return ok(code);
|
|
105846
|
-
}
|
|
105847
|
-
effects.consume(code);
|
|
105848
|
-
return afterClose;
|
|
105849
|
-
}
|
|
105850
|
-
// Line ending handling — follows the htmlFlow pattern
|
|
105851
|
-
function continuationStart(code) {
|
|
105852
|
-
return effects.check(jsx_table_syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
105853
|
-
}
|
|
105854
|
-
function continuationStartNonLazy(code) {
|
|
105855
|
-
effects.enter(types_types.lineEnding);
|
|
105856
|
-
effects.consume(code);
|
|
105857
|
-
effects.exit(types_types.lineEnding);
|
|
105858
|
-
return continuationBefore;
|
|
105859
|
-
}
|
|
105860
|
-
function continuationBefore(code) {
|
|
105861
|
-
if (code === null || markdownLineEnding(code)) {
|
|
105862
|
-
return continuationStart(code);
|
|
105863
|
-
}
|
|
105864
|
-
effects.enter('jsxTableData');
|
|
105865
|
-
return body(code);
|
|
105866
|
-
}
|
|
105867
|
-
function continuationAfter(code) {
|
|
105868
|
-
// At EOF without </Table>, reject so content isn't swallowed
|
|
105869
|
-
if (code === null) {
|
|
105870
|
-
return nok(code);
|
|
105871
|
-
}
|
|
105872
|
-
effects.exit('jsxTable');
|
|
105873
|
-
return ok(code);
|
|
105874
|
-
}
|
|
105875
|
-
}
|
|
105876
|
-
function jsx_table_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
105877
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
105878
|
-
const self = this;
|
|
105879
|
-
return start;
|
|
105880
|
-
function start(code) {
|
|
105881
|
-
if (markdownLineEnding(code)) {
|
|
105882
|
-
effects.enter(types_types.lineEnding);
|
|
105883
|
-
effects.consume(code);
|
|
105884
|
-
effects.exit(types_types.lineEnding);
|
|
105885
|
-
return after;
|
|
105886
|
-
}
|
|
105887
|
-
return nok(code);
|
|
105888
|
-
}
|
|
105889
|
-
function after(code) {
|
|
105890
|
-
if (self.parser.lazy[self.now().line]) {
|
|
105891
|
-
return nok(code);
|
|
105892
|
-
}
|
|
105893
|
-
return ok(code);
|
|
105894
|
-
}
|
|
105895
|
-
}
|
|
105896
|
-
/**
|
|
105897
|
-
* Micromark extension that tokenizes `<Table>...</Table>` and `<table>...</table>`
|
|
105898
|
-
* as a single flow block.
|
|
105899
|
-
*
|
|
105900
|
-
* Prevents CommonMark HTML block type 6 from fragmenting table blocks at blank lines.
|
|
105901
|
-
*/
|
|
105902
|
-
function jsxTable() {
|
|
105903
|
-
return {
|
|
105904
|
-
flow: {
|
|
105905
|
-
[codes.lessThan]: [jsxTableConstruct],
|
|
105906
|
-
},
|
|
105907
|
-
};
|
|
105908
|
-
}
|
|
105909
|
-
|
|
105910
|
-
;// ./lib/micromark/jsx-table/index.ts
|
|
105911
|
-
|
|
105912
|
-
|
|
105913
106389
|
;// ./lib/micromark/mdx-expression-lenient/syntax.ts
|
|
105914
106390
|
|
|
105915
106391
|
|
|
@@ -106085,6 +106561,9 @@ function loadComponents() {
|
|
|
106085
106561
|
|
|
106086
106562
|
|
|
106087
106563
|
|
|
106564
|
+
|
|
106565
|
+
|
|
106566
|
+
|
|
106088
106567
|
|
|
106089
106568
|
|
|
106090
106569
|
|
|
@@ -106099,15 +106578,19 @@ const defaultTransformers = [
|
|
|
106099
106578
|
* CommonMark/remark limitations and reach parity with legacy (rdmd) rendering.
|
|
106100
106579
|
*
|
|
106101
106580
|
* Runs a series of string-level transformations before micromark/remark parsing:
|
|
106102
|
-
* 1.
|
|
106103
|
-
* 2.
|
|
106104
|
-
* 3.
|
|
106105
|
-
* 4.
|
|
106106
|
-
* 5.
|
|
106581
|
+
* 1. Canonicalize closing tags with stray whitespace (e.g., `</ td >` → `</td>`)
|
|
106582
|
+
* 2. Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
|
|
106583
|
+
* 3. Terminate HTML flow blocks so subsequent content isn't swallowed
|
|
106584
|
+
* 4. Close invalid "self-closing" HTML tags (e.g., `<i />` → `<i></i>`)
|
|
106585
|
+
* 5. Normalize compact ATX headings (e.g., `#Heading` → `# Heading`)
|
|
106586
|
+
* 6. Replace snake_case component names with parser-safe placeholders
|
|
106107
106587
|
*/
|
|
106108
106588
|
function preprocessContent(content, opts) {
|
|
106109
106589
|
const { knownComponents } = opts;
|
|
106110
|
-
|
|
106590
|
+
// Runs first so `jsxTable` sees a literal `</table>` (and the HTML-line
|
|
106591
|
+
// classification in `terminateHtmlFlowBlocks` is accurate)
|
|
106592
|
+
let result = normalizeClosingTagWhitespace(content);
|
|
106593
|
+
result = normalizeTableSeparator(result);
|
|
106111
106594
|
result = terminateHtmlFlowBlocks(result);
|
|
106112
106595
|
result = closeSelfClosingHtmlTags(result);
|
|
106113
106596
|
result = normalizeCompactHeadings(result);
|
|
@@ -106136,6 +106619,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
106136
106619
|
syntax_gemoji(),
|
|
106137
106620
|
legacyVariable(),
|
|
106138
106621
|
looseHtmlEntity(),
|
|
106622
|
+
htmlBlockComponent(),
|
|
106139
106623
|
];
|
|
106140
106624
|
const fromMarkdownExts = [
|
|
106141
106625
|
jsxTableFromMarkdown(),
|
|
@@ -106145,6 +106629,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
106145
106629
|
legacyVariableFromMarkdown(),
|
|
106146
106630
|
emptyTaskListItemFromMarkdown(),
|
|
106147
106631
|
looseHtmlEntityFromMarkdown(),
|
|
106632
|
+
htmlBlockComponentFromMarkdown(),
|
|
106148
106633
|
];
|
|
106149
106634
|
if (!safeMode) {
|
|
106150
106635
|
// Insert mdx expression (text-only, no flow) after gemoji at index 3
|
|
@@ -106158,6 +106643,10 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
106158
106643
|
// JSX comment tokenizer must come before magicBlock so it claims `{/* ... */}` first
|
|
106159
106644
|
micromarkExts.unshift(jsxComment());
|
|
106160
106645
|
}
|
|
106646
|
+
// Claim `<HTMLBlock>` as one opaque token so broad tokenizers can't fragment its body
|
|
106647
|
+
// We put this last as micromark tries the last-registered extension first, so push (not unshift) to win the `<` race.
|
|
106648
|
+
// micromarkExts.push(htmlBlockComponent());
|
|
106649
|
+
// fromMarkdownExts.push(htmlBlockComponentFromMarkdown());
|
|
106161
106650
|
const processor = unified()
|
|
106162
106651
|
.data('micromarkExtensions', micromarkExts)
|
|
106163
106652
|
.data('fromMarkdownExtensions', fromMarkdownExts)
|
|
@@ -106213,6 +106702,12 @@ function mdxishMdastToMd(mdast) {
|
|
|
106213
106702
|
.use(remarkStringify, {
|
|
106214
106703
|
bullet: '-',
|
|
106215
106704
|
emphasis: '_',
|
|
106705
|
+
// Escape literal braces in text so they don't parse as (often
|
|
106706
|
+
// unterminated) MDX expressions on the next round trip.
|
|
106707
|
+
unsafe: [
|
|
106708
|
+
{ character: '{', inConstruct: 'phrasing' },
|
|
106709
|
+
{ character: '}', inConstruct: 'phrasing' },
|
|
106710
|
+
],
|
|
106216
106711
|
});
|
|
106217
106712
|
return processor.stringify(processor.runSync(mdast));
|
|
106218
106713
|
}
|
|
@@ -106751,332 +107246,6 @@ const mdxishTags_tags = (doc) => {
|
|
|
106751
107246
|
};
|
|
106752
107247
|
/* harmony default export */ const mdxishTags = (mdxishTags_tags);
|
|
106753
107248
|
|
|
106754
|
-
;// ./lib/mdast-util/html-block-component/index.ts
|
|
106755
|
-
const html_block_component_contextMap = new WeakMap();
|
|
106756
|
-
function findHtmlBlockComponentToken() {
|
|
106757
|
-
const events = this.tokenStack;
|
|
106758
|
-
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
106759
|
-
if (events[i][0].type === 'htmlBlockComponent')
|
|
106760
|
-
return events[i][0];
|
|
106761
|
-
}
|
|
106762
|
-
return undefined;
|
|
106763
|
-
}
|
|
106764
|
-
function enterHtmlBlockComponent(token) {
|
|
106765
|
-
html_block_component_contextMap.set(token, { chunks: [], lastEndLine: token.start.line });
|
|
106766
|
-
this.enter({ type: 'html', value: '' }, token);
|
|
106767
|
-
}
|
|
106768
|
-
function exitHtmlBlockComponentData(token) {
|
|
106769
|
-
const componentToken = findHtmlBlockComponentToken.call(this);
|
|
106770
|
-
if (!componentToken)
|
|
106771
|
-
return;
|
|
106772
|
-
const ctx = html_block_component_contextMap.get(componentToken);
|
|
106773
|
-
if (ctx) {
|
|
106774
|
-
const gap = token.start.line - ctx.lastEndLine;
|
|
106775
|
-
if (ctx.chunks.length > 0 && gap > 0) {
|
|
106776
|
-
ctx.chunks.push('\n'.repeat(gap));
|
|
106777
|
-
}
|
|
106778
|
-
ctx.chunks.push(this.sliceSerialize(token));
|
|
106779
|
-
ctx.lastEndLine = token.end.line;
|
|
106780
|
-
}
|
|
106781
|
-
}
|
|
106782
|
-
function exitHtmlBlockComponent(token) {
|
|
106783
|
-
const ctx = html_block_component_contextMap.get(token);
|
|
106784
|
-
const node = this.stack[this.stack.length - 1];
|
|
106785
|
-
if (ctx) {
|
|
106786
|
-
node.value = ctx.chunks.join('');
|
|
106787
|
-
html_block_component_contextMap.delete(token);
|
|
106788
|
-
}
|
|
106789
|
-
this.exit(token);
|
|
106790
|
-
}
|
|
106791
|
-
function htmlBlockComponentFromMarkdown() {
|
|
106792
|
-
return {
|
|
106793
|
-
enter: {
|
|
106794
|
-
htmlBlockComponent: enterHtmlBlockComponent,
|
|
106795
|
-
},
|
|
106796
|
-
exit: {
|
|
106797
|
-
htmlBlockComponentData: exitHtmlBlockComponentData,
|
|
106798
|
-
htmlBlockComponent: exitHtmlBlockComponent,
|
|
106799
|
-
},
|
|
106800
|
-
};
|
|
106801
|
-
}
|
|
106802
|
-
|
|
106803
|
-
;// ./lib/micromark/html-block-component/syntax.ts
|
|
106804
|
-
|
|
106805
|
-
|
|
106806
|
-
const TAG_SUFFIX = [
|
|
106807
|
-
codes.uppercaseT,
|
|
106808
|
-
codes.uppercaseM,
|
|
106809
|
-
codes.uppercaseL,
|
|
106810
|
-
codes.uppercaseB,
|
|
106811
|
-
codes.lowercaseL,
|
|
106812
|
-
codes.lowercaseO,
|
|
106813
|
-
codes.lowercaseC,
|
|
106814
|
-
codes.lowercaseK,
|
|
106815
|
-
];
|
|
106816
|
-
// ---------------------------------------------------------------------------
|
|
106817
|
-
// Shared tokenizer factory
|
|
106818
|
-
// ---------------------------------------------------------------------------
|
|
106819
|
-
/**
|
|
106820
|
-
* Creates a tokenize function for `<HTMLBlock>...</HTMLBlock>`.
|
|
106821
|
-
*
|
|
106822
|
-
* - **flow** (block-level): supports multiline content via line continuations,
|
|
106823
|
-
* consumes trailing whitespace after the closing tag.
|
|
106824
|
-
* - **text** (inline): single-line only, exits immediately after the closing tag.
|
|
106825
|
-
*/
|
|
106826
|
-
function syntax_createTokenize(mode) {
|
|
106827
|
-
return function tokenize(effects, ok, nok) {
|
|
106828
|
-
let depth = 1;
|
|
106829
|
-
function matchChars(chars, onMatch, onFail) {
|
|
106830
|
-
if (chars.length === 0)
|
|
106831
|
-
return onMatch;
|
|
106832
|
-
const next = (code) => {
|
|
106833
|
-
if (code === chars[0]) {
|
|
106834
|
-
effects.consume(code);
|
|
106835
|
-
return matchChars(chars.slice(1), onMatch, onFail);
|
|
106836
|
-
}
|
|
106837
|
-
return onFail(code);
|
|
106838
|
-
};
|
|
106839
|
-
return next;
|
|
106840
|
-
}
|
|
106841
|
-
function matchTagName(onMatch, onFail) {
|
|
106842
|
-
const next = (code) => {
|
|
106843
|
-
if (code === codes.uppercaseH) {
|
|
106844
|
-
effects.consume(code);
|
|
106845
|
-
return matchChars(TAG_SUFFIX, onMatch, onFail);
|
|
106846
|
-
}
|
|
106847
|
-
return onFail(code);
|
|
106848
|
-
};
|
|
106849
|
-
return next;
|
|
106850
|
-
}
|
|
106851
|
-
return start;
|
|
106852
|
-
function start(code) {
|
|
106853
|
-
if (code !== codes.lessThan)
|
|
106854
|
-
return nok(code);
|
|
106855
|
-
effects.enter('htmlBlockComponent');
|
|
106856
|
-
effects.enter('htmlBlockComponentData');
|
|
106857
|
-
effects.consume(code);
|
|
106858
|
-
return matchTagName(afterTagName, nok);
|
|
106859
|
-
}
|
|
106860
|
-
function afterTagName(code) {
|
|
106861
|
-
if (code === codes.greaterThan) {
|
|
106862
|
-
effects.consume(code);
|
|
106863
|
-
return body;
|
|
106864
|
-
}
|
|
106865
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
106866
|
-
effects.consume(code);
|
|
106867
|
-
return inAttributes;
|
|
106868
|
-
}
|
|
106869
|
-
if (mode === 'flow' && markdownLineEnding(code)) {
|
|
106870
|
-
effects.exit('htmlBlockComponentData');
|
|
106871
|
-
return attributeContinuationStart(code);
|
|
106872
|
-
}
|
|
106873
|
-
if (code === codes.slash) {
|
|
106874
|
-
effects.consume(code);
|
|
106875
|
-
return selfClose;
|
|
106876
|
-
}
|
|
106877
|
-
return nok(code);
|
|
106878
|
-
}
|
|
106879
|
-
function inAttributes(code) {
|
|
106880
|
-
if (code === codes.greaterThan) {
|
|
106881
|
-
effects.consume(code);
|
|
106882
|
-
return body;
|
|
106883
|
-
}
|
|
106884
|
-
if (code === null) {
|
|
106885
|
-
return nok(code);
|
|
106886
|
-
}
|
|
106887
|
-
if (markdownLineEnding(code)) {
|
|
106888
|
-
if (mode === 'text')
|
|
106889
|
-
return nok(code);
|
|
106890
|
-
effects.exit('htmlBlockComponentData');
|
|
106891
|
-
return attributeContinuationStart(code);
|
|
106892
|
-
}
|
|
106893
|
-
effects.consume(code);
|
|
106894
|
-
return inAttributes;
|
|
106895
|
-
}
|
|
106896
|
-
function attributeContinuationStart(code) {
|
|
106897
|
-
return effects.check(html_block_component_syntax_nonLazyContinuationStart, attributeContinuationNonLazy, continuationAfter)(code);
|
|
106898
|
-
}
|
|
106899
|
-
function attributeContinuationNonLazy(code) {
|
|
106900
|
-
effects.enter(types_types.lineEnding);
|
|
106901
|
-
effects.consume(code);
|
|
106902
|
-
effects.exit(types_types.lineEnding);
|
|
106903
|
-
return attributeContinuationBefore;
|
|
106904
|
-
}
|
|
106905
|
-
function attributeContinuationBefore(code) {
|
|
106906
|
-
if (code === null || markdownLineEnding(code)) {
|
|
106907
|
-
return attributeContinuationStart(code);
|
|
106908
|
-
}
|
|
106909
|
-
effects.enter('htmlBlockComponentData');
|
|
106910
|
-
return inAttributes(code);
|
|
106911
|
-
}
|
|
106912
|
-
function selfClose(code) {
|
|
106913
|
-
if (code === codes.greaterThan) {
|
|
106914
|
-
effects.consume(code);
|
|
106915
|
-
return mode === 'flow' ? afterClose : done(code);
|
|
106916
|
-
}
|
|
106917
|
-
return nok(code);
|
|
106918
|
-
}
|
|
106919
|
-
function body(code) {
|
|
106920
|
-
if (code === null)
|
|
106921
|
-
return nok(code);
|
|
106922
|
-
if (markdownLineEnding(code)) {
|
|
106923
|
-
if (mode === 'text') {
|
|
106924
|
-
// Text constructs operate on paragraph content which spans lines
|
|
106925
|
-
effects.consume(code);
|
|
106926
|
-
return body;
|
|
106927
|
-
}
|
|
106928
|
-
effects.exit('htmlBlockComponentData');
|
|
106929
|
-
return continuationStart(code);
|
|
106930
|
-
}
|
|
106931
|
-
if (code === codes.lessThan) {
|
|
106932
|
-
effects.consume(code);
|
|
106933
|
-
return closeSlash;
|
|
106934
|
-
}
|
|
106935
|
-
effects.consume(code);
|
|
106936
|
-
return body;
|
|
106937
|
-
}
|
|
106938
|
-
function closeSlash(code) {
|
|
106939
|
-
if (code === codes.slash) {
|
|
106940
|
-
effects.consume(code);
|
|
106941
|
-
return matchTagName(closeGt, body);
|
|
106942
|
-
}
|
|
106943
|
-
return matchTagName(openAfterTagName, body)(code);
|
|
106944
|
-
}
|
|
106945
|
-
function openAfterTagName(code) {
|
|
106946
|
-
if (code === codes.greaterThan || code === codes.space || code === codes.horizontalTab) {
|
|
106947
|
-
depth += 1;
|
|
106948
|
-
effects.consume(code);
|
|
106949
|
-
return body;
|
|
106950
|
-
}
|
|
106951
|
-
return body(code);
|
|
106952
|
-
}
|
|
106953
|
-
function closeGt(code) {
|
|
106954
|
-
if (code === codes.greaterThan) {
|
|
106955
|
-
depth -= 1;
|
|
106956
|
-
effects.consume(code);
|
|
106957
|
-
if (depth === 0) {
|
|
106958
|
-
return mode === 'flow' ? afterClose : done(code);
|
|
106959
|
-
}
|
|
106960
|
-
return body;
|
|
106961
|
-
}
|
|
106962
|
-
return body(code);
|
|
106963
|
-
}
|
|
106964
|
-
// -- flow-only states ---------------------------------------------------
|
|
106965
|
-
function afterClose(code) {
|
|
106966
|
-
if (code === null || markdownLineEnding(code)) {
|
|
106967
|
-
return done(code);
|
|
106968
|
-
}
|
|
106969
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
106970
|
-
effects.consume(code);
|
|
106971
|
-
return afterClose;
|
|
106972
|
-
}
|
|
106973
|
-
// Reject so the block re-parses as a paragraph, deferring to the
|
|
106974
|
-
// text tokenizer which preserves trailing content in the same line.
|
|
106975
|
-
return nok(code);
|
|
106976
|
-
}
|
|
106977
|
-
// -- flow-only: line continuation ---------------------------------------
|
|
106978
|
-
function continuationStart(code) {
|
|
106979
|
-
return effects.check(html_block_component_syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
106980
|
-
}
|
|
106981
|
-
function continuationStartNonLazy(code) {
|
|
106982
|
-
effects.enter(types_types.lineEnding);
|
|
106983
|
-
effects.consume(code);
|
|
106984
|
-
effects.exit(types_types.lineEnding);
|
|
106985
|
-
return continuationBefore;
|
|
106986
|
-
}
|
|
106987
|
-
function continuationBefore(code) {
|
|
106988
|
-
if (code === null || markdownLineEnding(code)) {
|
|
106989
|
-
return continuationStart(code);
|
|
106990
|
-
}
|
|
106991
|
-
effects.enter('htmlBlockComponentData');
|
|
106992
|
-
return body(code);
|
|
106993
|
-
}
|
|
106994
|
-
function continuationAfter(code) {
|
|
106995
|
-
if (code === null)
|
|
106996
|
-
return nok(code);
|
|
106997
|
-
effects.exit('htmlBlockComponent');
|
|
106998
|
-
return ok(code);
|
|
106999
|
-
}
|
|
107000
|
-
// -- shared exit --------------------------------------------------------
|
|
107001
|
-
function done(_code) {
|
|
107002
|
-
effects.exit('htmlBlockComponentData');
|
|
107003
|
-
effects.exit('htmlBlockComponent');
|
|
107004
|
-
return ok(_code);
|
|
107005
|
-
}
|
|
107006
|
-
};
|
|
107007
|
-
}
|
|
107008
|
-
// ---------------------------------------------------------------------------
|
|
107009
|
-
// Flow construct (block-level)
|
|
107010
|
-
// ---------------------------------------------------------------------------
|
|
107011
|
-
const html_block_component_syntax_nonLazyContinuationStart = {
|
|
107012
|
-
tokenize: html_block_component_syntax_tokenizeNonLazyContinuationStart,
|
|
107013
|
-
partial: true,
|
|
107014
|
-
};
|
|
107015
|
-
function resolveToHtmlBlockComponent(events) {
|
|
107016
|
-
let index = events.length;
|
|
107017
|
-
while (index > 0) {
|
|
107018
|
-
index -= 1;
|
|
107019
|
-
if (events[index][0] === 'enter' && events[index][1].type === 'htmlBlockComponent') {
|
|
107020
|
-
break;
|
|
107021
|
-
}
|
|
107022
|
-
}
|
|
107023
|
-
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
107024
|
-
events[index][1].start = events[index - 2][1].start;
|
|
107025
|
-
events[index + 1][1].start = events[index - 2][1].start;
|
|
107026
|
-
events.splice(index - 2, 2);
|
|
107027
|
-
}
|
|
107028
|
-
return events;
|
|
107029
|
-
}
|
|
107030
|
-
const htmlBlockComponentFlowConstruct = {
|
|
107031
|
-
name: 'htmlBlockComponent',
|
|
107032
|
-
tokenize: syntax_createTokenize('flow'),
|
|
107033
|
-
resolveTo: resolveToHtmlBlockComponent,
|
|
107034
|
-
concrete: true,
|
|
107035
|
-
};
|
|
107036
|
-
function html_block_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
107037
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
107038
|
-
const self = this;
|
|
107039
|
-
return start;
|
|
107040
|
-
function start(code) {
|
|
107041
|
-
if (markdownLineEnding(code)) {
|
|
107042
|
-
effects.enter(types_types.lineEnding);
|
|
107043
|
-
effects.consume(code);
|
|
107044
|
-
effects.exit(types_types.lineEnding);
|
|
107045
|
-
return after;
|
|
107046
|
-
}
|
|
107047
|
-
return nok(code);
|
|
107048
|
-
}
|
|
107049
|
-
function after(code) {
|
|
107050
|
-
if (self.parser.lazy[self.now().line]) {
|
|
107051
|
-
return nok(code);
|
|
107052
|
-
}
|
|
107053
|
-
return ok(code);
|
|
107054
|
-
}
|
|
107055
|
-
}
|
|
107056
|
-
// ---------------------------------------------------------------------------
|
|
107057
|
-
// Text construct (inline)
|
|
107058
|
-
// ---------------------------------------------------------------------------
|
|
107059
|
-
const htmlBlockComponentTextConstruct = {
|
|
107060
|
-
name: 'htmlBlockComponent',
|
|
107061
|
-
tokenize: syntax_createTokenize('text'),
|
|
107062
|
-
};
|
|
107063
|
-
// ---------------------------------------------------------------------------
|
|
107064
|
-
// Extension
|
|
107065
|
-
// ---------------------------------------------------------------------------
|
|
107066
|
-
function htmlBlockComponent() {
|
|
107067
|
-
return {
|
|
107068
|
-
flow: {
|
|
107069
|
-
[codes.lessThan]: [htmlBlockComponentFlowConstruct],
|
|
107070
|
-
},
|
|
107071
|
-
text: {
|
|
107072
|
-
[codes.lessThan]: [htmlBlockComponentTextConstruct],
|
|
107073
|
-
},
|
|
107074
|
-
};
|
|
107075
|
-
}
|
|
107076
|
-
|
|
107077
|
-
;// ./lib/micromark/html-block-component/index.ts
|
|
107078
|
-
|
|
107079
|
-
|
|
107080
107249
|
;// ./lib/utils/extractMagicBlocks.ts
|
|
107081
107250
|
/**
|
|
107082
107251
|
* The content matching in this regex captures everything between `[block:TYPE]`
|