@readme/markdown 14.11.5 → 14.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/HTMLBlock/index.tsx +12 -10
- package/dist/main.js +1901 -1777
- package/dist/main.node.js +1894 -1770
- package/dist/main.node.js.map +1 -1
- package/dist/processor/plugin/hard-breaks.d.ts +13 -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/indentation.d.ts +19 -0
- 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/render-fixture.node.js +1829 -1705
- package/dist/render-fixture.node.js.map +1 -1
- package/package.json +2 -3
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
|
|
|
@@ -1893,7 +1893,7 @@ module.exports = function (exec) {
|
|
|
1893
1893
|
|
|
1894
1894
|
/***/ }),
|
|
1895
1895
|
|
|
1896
|
-
/***/
|
|
1896
|
+
/***/ 1842:
|
|
1897
1897
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
1898
1898
|
|
|
1899
1899
|
module.exports = __webpack_require__(4556)('native-function-to-string', Function.toString);
|
|
@@ -2493,7 +2493,7 @@ var global = __webpack_require__(7526);
|
|
|
2493
2493
|
var hide = __webpack_require__(3341);
|
|
2494
2494
|
var has = __webpack_require__(7917);
|
|
2495
2495
|
var SRC = __webpack_require__(4415)('src');
|
|
2496
|
-
var $toString = __webpack_require__(
|
|
2496
|
+
var $toString = __webpack_require__(1842);
|
|
2497
2497
|
var TO_STRING = 'toString';
|
|
2498
2498
|
var TPL = ('' + $toString).split(TO_STRING);
|
|
2499
2499
|
|
|
@@ -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);
|
|
@@ -89639,63 +89658,6 @@ function rehypeSanitize(options) {
|
|
|
89639
89658
|
}
|
|
89640
89659
|
}
|
|
89641
89660
|
|
|
89642
|
-
;// ./node_modules/mdast-util-newline-to-break/lib/index.js
|
|
89643
|
-
/**
|
|
89644
|
-
* @typedef {import('mdast').Nodes} Nodes
|
|
89645
|
-
* @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction
|
|
89646
|
-
*/
|
|
89647
|
-
|
|
89648
|
-
|
|
89649
|
-
|
|
89650
|
-
/**
|
|
89651
|
-
* Turn normal line endings into hard breaks.
|
|
89652
|
-
*
|
|
89653
|
-
* @param {Nodes} tree
|
|
89654
|
-
* Tree to change.
|
|
89655
|
-
* @returns {undefined}
|
|
89656
|
-
* Nothing.
|
|
89657
|
-
*/
|
|
89658
|
-
function newlineToBreak(tree) {
|
|
89659
|
-
findAndReplace(tree, [/\r?\n|\r/g, lib_replace])
|
|
89660
|
-
}
|
|
89661
|
-
|
|
89662
|
-
/**
|
|
89663
|
-
* Replace line endings.
|
|
89664
|
-
*
|
|
89665
|
-
* @type {ReplaceFunction}
|
|
89666
|
-
*/
|
|
89667
|
-
function lib_replace() {
|
|
89668
|
-
return {type: 'break'}
|
|
89669
|
-
}
|
|
89670
|
-
|
|
89671
|
-
;// ./node_modules/remark-breaks/lib/index.js
|
|
89672
|
-
/**
|
|
89673
|
-
* @typedef {import('mdast').Root} Root
|
|
89674
|
-
*/
|
|
89675
|
-
|
|
89676
|
-
|
|
89677
|
-
|
|
89678
|
-
/**
|
|
89679
|
-
* Support hard breaks without needing spaces or escapes (turns enters into
|
|
89680
|
-
* `<br>`s).
|
|
89681
|
-
*
|
|
89682
|
-
* @returns
|
|
89683
|
-
* Transform.
|
|
89684
|
-
*/
|
|
89685
|
-
function remarkBreaks() {
|
|
89686
|
-
/**
|
|
89687
|
-
* Transform.
|
|
89688
|
-
*
|
|
89689
|
-
* @param {Root} tree
|
|
89690
|
-
* Tree.
|
|
89691
|
-
* @returns {undefined}
|
|
89692
|
-
* Nothing.
|
|
89693
|
-
*/
|
|
89694
|
-
return function (tree) {
|
|
89695
|
-
newlineToBreak(tree)
|
|
89696
|
-
}
|
|
89697
|
-
}
|
|
89698
|
-
|
|
89699
89661
|
;// ./errors/mdx-syntax-error.ts
|
|
89700
89662
|
class MdxSyntaxError extends SyntaxError {
|
|
89701
89663
|
original = null;
|
|
@@ -89717,6 +89679,22 @@ class MdxSyntaxError extends SyntaxError {
|
|
|
89717
89679
|
}
|
|
89718
89680
|
}
|
|
89719
89681
|
|
|
89682
|
+
;// ./processor/plugin/hard-breaks.ts
|
|
89683
|
+
|
|
89684
|
+
/**
|
|
89685
|
+
* Converts LF and CRLF line endings into hard breaks while leaving standalone
|
|
89686
|
+
* carriage returns as soft whitespace.
|
|
89687
|
+
*
|
|
89688
|
+
* Unlike `remark-breaks`, this does not promote a lone `\r` into a `<br>`.
|
|
89689
|
+
* Standalone carriage returns can be left behind by generators that replace
|
|
89690
|
+
* the LF in Windows line endings with an explicit `<br>`, producing input such
|
|
89691
|
+
* as `\r<br>`. Treating both characters as hard breaks doubles the spacing.
|
|
89692
|
+
*/
|
|
89693
|
+
const hardBreaks = () => tree => {
|
|
89694
|
+
findAndReplace(tree, [/\r?\n/g, () => ({ type: 'break' })]);
|
|
89695
|
+
};
|
|
89696
|
+
/* harmony default export */ const hard_breaks = (hardBreaks);
|
|
89697
|
+
|
|
89720
89698
|
;// ./node_modules/estree-util-value-to-estree/dist/estree-util-value-to-estree.js
|
|
89721
89699
|
/**
|
|
89722
89700
|
* Create an ESTree identifier node for a given name.
|
|
@@ -92421,7 +92399,7 @@ const compile_compile = (text, { components = {}, missingComponents, copyButtons
|
|
|
92421
92399
|
const remarkPlugins = [
|
|
92422
92400
|
remarkFrontmatter,
|
|
92423
92401
|
remarkGfm,
|
|
92424
|
-
...(hardBreaks ? [
|
|
92402
|
+
...(hardBreaks ? [hard_breaks] : []),
|
|
92425
92403
|
...Object.values(transforms),
|
|
92426
92404
|
[codeTabsTransformer, { copyButtons }],
|
|
92427
92405
|
[
|
|
@@ -99649,6 +99627,55 @@ function emptyTaskListItemFromMarkdown() {
|
|
|
99649
99627
|
};
|
|
99650
99628
|
}
|
|
99651
99629
|
|
|
99630
|
+
;// ./lib/mdast-util/jsx-table/index.ts
|
|
99631
|
+
const jsx_table_contextMap = new WeakMap();
|
|
99632
|
+
function findJsxTableToken() {
|
|
99633
|
+
const events = this.tokenStack;
|
|
99634
|
+
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
99635
|
+
if (events[i][0].type === 'jsxTable')
|
|
99636
|
+
return events[i][0];
|
|
99637
|
+
}
|
|
99638
|
+
return undefined;
|
|
99639
|
+
}
|
|
99640
|
+
function enterJsxTable(token) {
|
|
99641
|
+
jsx_table_contextMap.set(token, { chunks: [], lastEndLine: token.start.line });
|
|
99642
|
+
this.enter({ type: 'html', value: '' }, token);
|
|
99643
|
+
}
|
|
99644
|
+
function exitJsxTableData(token) {
|
|
99645
|
+
const tableToken = findJsxTableToken.call(this);
|
|
99646
|
+
if (!tableToken)
|
|
99647
|
+
return;
|
|
99648
|
+
const ctx = jsx_table_contextMap.get(tableToken);
|
|
99649
|
+
if (ctx) {
|
|
99650
|
+
const gap = token.start.line - ctx.lastEndLine;
|
|
99651
|
+
if (ctx.chunks.length > 0 && gap > 0) {
|
|
99652
|
+
ctx.chunks.push('\n'.repeat(gap));
|
|
99653
|
+
}
|
|
99654
|
+
ctx.chunks.push(this.sliceSerialize(token));
|
|
99655
|
+
ctx.lastEndLine = token.end.line;
|
|
99656
|
+
}
|
|
99657
|
+
}
|
|
99658
|
+
function exitJsxTable(token) {
|
|
99659
|
+
const ctx = jsx_table_contextMap.get(token);
|
|
99660
|
+
const node = this.stack[this.stack.length - 1];
|
|
99661
|
+
if (ctx) {
|
|
99662
|
+
node.value = ctx.chunks.join('');
|
|
99663
|
+
jsx_table_contextMap.delete(token);
|
|
99664
|
+
}
|
|
99665
|
+
this.exit(token);
|
|
99666
|
+
}
|
|
99667
|
+
function jsxTableFromMarkdown() {
|
|
99668
|
+
return {
|
|
99669
|
+
enter: {
|
|
99670
|
+
jsxTable: enterJsxTable,
|
|
99671
|
+
},
|
|
99672
|
+
exit: {
|
|
99673
|
+
jsxTableData: exitJsxTableData,
|
|
99674
|
+
jsxTable: exitJsxTable,
|
|
99675
|
+
},
|
|
99676
|
+
};
|
|
99677
|
+
}
|
|
99678
|
+
|
|
99652
99679
|
;// ./lib/mdast-util/magic-block/index.ts
|
|
99653
99680
|
const magic_block_contextMap = new WeakMap();
|
|
99654
99681
|
/**
|
|
@@ -99838,867 +99865,16 @@ function mdxComponentFromMarkdown() {
|
|
|
99838
99865
|
};
|
|
99839
99866
|
}
|
|
99840
99867
|
|
|
99841
|
-
;// ./
|
|
99842
|
-
|
|
99843
|
-
|
|
99844
|
-
/**
|
|
99845
|
-
* Known magic block types that the tokenizer will recognize.
|
|
99846
|
-
* Unknown types will not be tokenized as magic blocks.
|
|
99847
|
-
*/
|
|
99848
|
-
const KNOWN_BLOCK_TYPES = new Set([
|
|
99849
|
-
'code',
|
|
99850
|
-
'api-header',
|
|
99851
|
-
'image',
|
|
99852
|
-
'callout',
|
|
99853
|
-
'parameters',
|
|
99854
|
-
'table',
|
|
99855
|
-
'embed',
|
|
99856
|
-
'html',
|
|
99857
|
-
'recipe',
|
|
99858
|
-
'tutorial-tile',
|
|
99859
|
-
]);
|
|
99860
|
-
/**
|
|
99861
|
-
* Check if a character is valid for a magic block type identifier.
|
|
99862
|
-
* Types can contain alphanumeric characters and hyphens (e.g., "api-header", "tutorial-tile")
|
|
99863
|
-
*/
|
|
99864
|
-
function isTypeChar(code) {
|
|
99865
|
-
return asciiAlphanumeric(code) || code === codes.dash;
|
|
99866
|
-
}
|
|
99867
|
-
/**
|
|
99868
|
-
* Creates the opening marker state machine: [block:
|
|
99869
|
-
* Returns the first state function to start parsing.
|
|
99870
|
-
*/
|
|
99871
|
-
function createOpeningMarkerParser(effects, nok, onComplete) {
|
|
99872
|
-
const expectB = (code) => {
|
|
99873
|
-
if (code !== codes.lowercaseB)
|
|
99874
|
-
return nok(code);
|
|
99875
|
-
effects.consume(code);
|
|
99876
|
-
return expectL;
|
|
99877
|
-
};
|
|
99878
|
-
const expectL = (code) => {
|
|
99879
|
-
if (code !== codes.lowercaseL)
|
|
99880
|
-
return nok(code);
|
|
99881
|
-
effects.consume(code);
|
|
99882
|
-
return expectO;
|
|
99883
|
-
};
|
|
99884
|
-
const expectO = (code) => {
|
|
99885
|
-
if (code !== codes.lowercaseO)
|
|
99886
|
-
return nok(code);
|
|
99887
|
-
effects.consume(code);
|
|
99888
|
-
return expectC;
|
|
99889
|
-
};
|
|
99890
|
-
const expectC = (code) => {
|
|
99891
|
-
if (code !== codes.lowercaseC)
|
|
99892
|
-
return nok(code);
|
|
99893
|
-
effects.consume(code);
|
|
99894
|
-
return expectK;
|
|
99895
|
-
};
|
|
99896
|
-
const expectK = (code) => {
|
|
99897
|
-
if (code !== codes.lowercaseK)
|
|
99898
|
-
return nok(code);
|
|
99899
|
-
effects.consume(code);
|
|
99900
|
-
return expectColon;
|
|
99901
|
-
};
|
|
99902
|
-
const expectColon = (code) => {
|
|
99903
|
-
if (code !== codes.colon)
|
|
99904
|
-
return nok(code);
|
|
99905
|
-
effects.consume(code);
|
|
99906
|
-
effects.exit('magicBlockMarkerStart');
|
|
99907
|
-
effects.enter('magicBlockType');
|
|
99908
|
-
return onComplete;
|
|
99909
|
-
};
|
|
99910
|
-
return expectB;
|
|
99911
|
-
}
|
|
99912
|
-
/**
|
|
99913
|
-
* Creates the type capture state machine.
|
|
99914
|
-
* Captures type characters until ] and validates against known types.
|
|
99915
|
-
*/
|
|
99916
|
-
function createTypeCaptureParser(effects, nok, onComplete, blockTypeRef) {
|
|
99917
|
-
const captureTypeFirst = (code) => {
|
|
99918
|
-
// Reject empty type name [block:]
|
|
99919
|
-
if (code === codes.rightSquareBracket) {
|
|
99920
|
-
return nok(code);
|
|
99921
|
-
}
|
|
99922
|
-
if (isTypeChar(code)) {
|
|
99923
|
-
blockTypeRef.value += String.fromCharCode(code);
|
|
99924
|
-
effects.consume(code);
|
|
99925
|
-
return captureType;
|
|
99926
|
-
}
|
|
99927
|
-
return nok(code);
|
|
99928
|
-
};
|
|
99929
|
-
const captureType = (code) => {
|
|
99930
|
-
if (code === codes.rightSquareBracket) {
|
|
99931
|
-
if (!KNOWN_BLOCK_TYPES.has(blockTypeRef.value)) {
|
|
99932
|
-
return nok(code);
|
|
99933
|
-
}
|
|
99934
|
-
effects.exit('magicBlockType');
|
|
99935
|
-
effects.enter('magicBlockMarkerTypeEnd');
|
|
99936
|
-
effects.consume(code);
|
|
99937
|
-
effects.exit('magicBlockMarkerTypeEnd');
|
|
99938
|
-
return onComplete;
|
|
99939
|
-
}
|
|
99940
|
-
if (isTypeChar(code)) {
|
|
99941
|
-
blockTypeRef.value += String.fromCharCode(code);
|
|
99942
|
-
effects.consume(code);
|
|
99943
|
-
return captureType;
|
|
99944
|
-
}
|
|
99945
|
-
return nok(code);
|
|
99946
|
-
};
|
|
99947
|
-
return { first: captureTypeFirst, remaining: captureType };
|
|
99948
|
-
}
|
|
99949
|
-
/**
|
|
99950
|
-
* Creates the closing marker state machine: /block]
|
|
99951
|
-
* Handles partial matches by calling onMismatch to fall back to data capture.
|
|
99952
|
-
*/
|
|
99953
|
-
function createClosingMarkerParser(effects, onSuccess, onMismatch, onEof, jsonState) {
|
|
99954
|
-
const handleMismatch = (code) => {
|
|
99955
|
-
if (jsonState && code === codes.quotationMark) {
|
|
99956
|
-
jsonState.inString = true;
|
|
99957
|
-
}
|
|
99958
|
-
return onMismatch(code);
|
|
99959
|
-
};
|
|
99960
|
-
const expectSlash = (code) => {
|
|
99961
|
-
if (code === null)
|
|
99962
|
-
return onEof(code);
|
|
99963
|
-
if (code !== codes.slash)
|
|
99964
|
-
return handleMismatch(code);
|
|
99965
|
-
effects.consume(code);
|
|
99966
|
-
return expectB;
|
|
99967
|
-
};
|
|
99968
|
-
const expectB = (code) => {
|
|
99969
|
-
if (code === null)
|
|
99970
|
-
return onEof(code);
|
|
99971
|
-
if (code !== codes.lowercaseB)
|
|
99972
|
-
return handleMismatch(code);
|
|
99973
|
-
effects.consume(code);
|
|
99974
|
-
return expectL;
|
|
99975
|
-
};
|
|
99976
|
-
const expectL = (code) => {
|
|
99977
|
-
if (code === null)
|
|
99978
|
-
return onEof(code);
|
|
99979
|
-
if (code !== codes.lowercaseL)
|
|
99980
|
-
return handleMismatch(code);
|
|
99981
|
-
effects.consume(code);
|
|
99982
|
-
return expectO;
|
|
99983
|
-
};
|
|
99984
|
-
const expectO = (code) => {
|
|
99985
|
-
if (code === null)
|
|
99986
|
-
return onEof(code);
|
|
99987
|
-
if (code !== codes.lowercaseO)
|
|
99988
|
-
return handleMismatch(code);
|
|
99989
|
-
effects.consume(code);
|
|
99990
|
-
return expectC;
|
|
99991
|
-
};
|
|
99992
|
-
const expectC = (code) => {
|
|
99993
|
-
if (code === null)
|
|
99994
|
-
return onEof(code);
|
|
99995
|
-
if (code !== codes.lowercaseC)
|
|
99996
|
-
return handleMismatch(code);
|
|
99997
|
-
effects.consume(code);
|
|
99998
|
-
return expectK;
|
|
99999
|
-
};
|
|
100000
|
-
const expectK = (code) => {
|
|
100001
|
-
if (code === null)
|
|
100002
|
-
return onEof(code);
|
|
100003
|
-
if (code !== codes.lowercaseK)
|
|
100004
|
-
return handleMismatch(code);
|
|
100005
|
-
effects.consume(code);
|
|
100006
|
-
return expectBracket;
|
|
100007
|
-
};
|
|
100008
|
-
const expectBracket = (code) => {
|
|
100009
|
-
if (code === null)
|
|
100010
|
-
return onEof(code);
|
|
100011
|
-
if (code !== codes.rightSquareBracket)
|
|
100012
|
-
return handleMismatch(code);
|
|
100013
|
-
effects.consume(code);
|
|
100014
|
-
return onSuccess;
|
|
100015
|
-
};
|
|
100016
|
-
return { expectSlash };
|
|
100017
|
-
}
|
|
100018
|
-
/**
|
|
100019
|
-
* Partial construct for checking non-lazy continuation.
|
|
100020
|
-
* This is used by the flow tokenizer to check if we can continue
|
|
100021
|
-
* parsing on the next line.
|
|
100022
|
-
*/
|
|
100023
|
-
const syntax_nonLazyContinuation = {
|
|
100024
|
-
partial: true,
|
|
100025
|
-
tokenize: syntax_tokenizeNonLazyContinuation,
|
|
100026
|
-
};
|
|
100027
|
-
/**
|
|
100028
|
-
* Tokenizer for non-lazy continuation checking.
|
|
100029
|
-
* Returns ok if the next line is non-lazy (can continue), nok if lazy.
|
|
100030
|
-
*/
|
|
100031
|
-
function syntax_tokenizeNonLazyContinuation(effects, ok, nok) {
|
|
100032
|
-
const lineStart = (code) => {
|
|
100033
|
-
// `this` here refers to the micromark parser
|
|
100034
|
-
// since we are just passing functions as references and not actually calling them
|
|
100035
|
-
// micromarks's internal parser will call this automatically with appropriate arguments
|
|
100036
|
-
return this.parser.lazy[this.now().line] ? nok(code) : ok(code);
|
|
100037
|
-
};
|
|
100038
|
-
const start = (code) => {
|
|
100039
|
-
if (code === null) {
|
|
100040
|
-
return nok(code);
|
|
100041
|
-
}
|
|
100042
|
-
if (!markdownLineEnding(code)) {
|
|
100043
|
-
return nok(code);
|
|
100044
|
-
}
|
|
100045
|
-
effects.enter('magicBlockLineEnding');
|
|
100046
|
-
effects.consume(code);
|
|
100047
|
-
effects.exit('magicBlockLineEnding');
|
|
100048
|
-
return lineStart;
|
|
100049
|
-
};
|
|
100050
|
-
return start;
|
|
100051
|
-
}
|
|
99868
|
+
;// ./node_modules/micromark-util-symbol/lib/types.js
|
|
100052
99869
|
/**
|
|
100053
|
-
*
|
|
100054
|
-
*
|
|
100055
|
-
* This extension handles both single-line and multiline magic blocks:
|
|
100056
|
-
* - Flow construct (concrete): Handles block-level multiline magic blocks at document level
|
|
100057
|
-
* - Text construct: Handles inline magic blocks in lists, paragraphs, etc.
|
|
99870
|
+
* This module is compiled away!
|
|
100058
99871
|
*
|
|
100059
|
-
*
|
|
100060
|
-
*
|
|
100061
|
-
|
|
100062
|
-
|
|
100063
|
-
|
|
100064
|
-
|
|
100065
|
-
// Marked as concrete to prevent interruption by containers
|
|
100066
|
-
flow: {
|
|
100067
|
-
[codes.leftSquareBracket]: {
|
|
100068
|
-
name: 'magicBlock',
|
|
100069
|
-
concrete: true,
|
|
100070
|
-
tokenize: tokenizeMagicBlockFlow,
|
|
100071
|
-
},
|
|
100072
|
-
},
|
|
100073
|
-
// Text construct - handles magic blocks in inline contexts (lists, paragraphs)
|
|
100074
|
-
text: {
|
|
100075
|
-
[codes.leftSquareBracket]: {
|
|
100076
|
-
name: 'magicBlock',
|
|
100077
|
-
tokenize: tokenizeMagicBlockText,
|
|
100078
|
-
},
|
|
100079
|
-
},
|
|
100080
|
-
};
|
|
100081
|
-
}
|
|
100082
|
-
/**
|
|
100083
|
-
* Flow tokenizer for block-level magic blocks (multiline).
|
|
100084
|
-
* Uses the continuation checking pattern from code fences.
|
|
100085
|
-
*/
|
|
100086
|
-
function tokenizeMagicBlockFlow(effects, ok, nok) {
|
|
100087
|
-
// State for tracking JSON content
|
|
100088
|
-
const jsonState = { escapeNext: false, inString: false };
|
|
100089
|
-
const blockTypeRef = { value: '' };
|
|
100090
|
-
let seenOpenBrace = false;
|
|
100091
|
-
// Create shared parsers for opening marker and type capture
|
|
100092
|
-
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
100093
|
-
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
100094
|
-
return start;
|
|
100095
|
-
function start(code) {
|
|
100096
|
-
if (code !== codes.leftSquareBracket)
|
|
100097
|
-
return nok(code);
|
|
100098
|
-
effects.enter('magicBlock');
|
|
100099
|
-
effects.enter('magicBlockMarkerStart');
|
|
100100
|
-
effects.consume(code);
|
|
100101
|
-
return openingMarkerParser;
|
|
100102
|
-
}
|
|
100103
|
-
/**
|
|
100104
|
-
* State before data content - handles line endings or starts data capture.
|
|
100105
|
-
*/
|
|
100106
|
-
function beforeData(code) {
|
|
100107
|
-
// EOF - magic block must be closed
|
|
100108
|
-
if (code === null) {
|
|
100109
|
-
effects.exit('magicBlock');
|
|
100110
|
-
return nok(code);
|
|
100111
|
-
}
|
|
100112
|
-
// Line ending before any data - check continuation
|
|
100113
|
-
if (markdownLineEnding(code)) {
|
|
100114
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100115
|
-
}
|
|
100116
|
-
// Check for closing marker directly (without entering data)
|
|
100117
|
-
// This handles cases like [block:type]\n{}\n\n[/block] where there are
|
|
100118
|
-
// newlines after the data object
|
|
100119
|
-
if (code === codes.leftSquareBracket) {
|
|
100120
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100121
|
-
effects.consume(code);
|
|
100122
|
-
return expectSlashFromContinuation;
|
|
100123
|
-
}
|
|
100124
|
-
// If we've already seen the opening brace, just continue capturing data
|
|
100125
|
-
if (seenOpenBrace) {
|
|
100126
|
-
effects.enter('magicBlockData');
|
|
100127
|
-
return captureData(code);
|
|
100128
|
-
}
|
|
100129
|
-
// Skip whitespace (spaces/tabs) before the data - stay in beforeData
|
|
100130
|
-
// Don't enter magicBlockData token yet until we confirm there's a '{'
|
|
100131
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100132
|
-
return beforeDataWhitespace(code);
|
|
100133
|
-
}
|
|
100134
|
-
// Data must start with '{' for valid JSON
|
|
100135
|
-
if (code !== codes.leftCurlyBrace) {
|
|
100136
|
-
effects.exit('magicBlock');
|
|
100137
|
-
return nok(code);
|
|
100138
|
-
}
|
|
100139
|
-
// We have '{' - enter data token and start capturing
|
|
100140
|
-
seenOpenBrace = true;
|
|
100141
|
-
effects.enter('magicBlockData');
|
|
100142
|
-
return captureData(code);
|
|
100143
|
-
}
|
|
100144
|
-
/**
|
|
100145
|
-
* Consume whitespace before the data without creating a token.
|
|
100146
|
-
* Uses a temporary token to satisfy micromark's requirement.
|
|
100147
|
-
*/
|
|
100148
|
-
function beforeDataWhitespace(code) {
|
|
100149
|
-
if (code === null) {
|
|
100150
|
-
effects.exit('magicBlock');
|
|
100151
|
-
return nok(code);
|
|
100152
|
-
}
|
|
100153
|
-
if (markdownLineEnding(code)) {
|
|
100154
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100155
|
-
}
|
|
100156
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100157
|
-
// We need to consume this but can't without a token - use magicBlockData
|
|
100158
|
-
// and track that we haven't seen '{' yet
|
|
100159
|
-
effects.enter('magicBlockData');
|
|
100160
|
-
effects.consume(code);
|
|
100161
|
-
return beforeDataWhitespaceContinue;
|
|
100162
|
-
}
|
|
100163
|
-
if (code === codes.leftCurlyBrace) {
|
|
100164
|
-
seenOpenBrace = true;
|
|
100165
|
-
effects.enter('magicBlockData');
|
|
100166
|
-
return captureData(code);
|
|
100167
|
-
}
|
|
100168
|
-
effects.exit('magicBlock');
|
|
100169
|
-
return nok(code);
|
|
100170
|
-
}
|
|
100171
|
-
/**
|
|
100172
|
-
* Continue consuming whitespace or validate the opening brace.
|
|
100173
|
-
*/
|
|
100174
|
-
function beforeDataWhitespaceContinue(code) {
|
|
100175
|
-
if (code === null) {
|
|
100176
|
-
effects.exit('magicBlockData');
|
|
100177
|
-
effects.exit('magicBlock');
|
|
100178
|
-
return nok(code);
|
|
100179
|
-
}
|
|
100180
|
-
if (markdownLineEnding(code)) {
|
|
100181
|
-
effects.exit('magicBlockData');
|
|
100182
|
-
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100183
|
-
}
|
|
100184
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100185
|
-
effects.consume(code);
|
|
100186
|
-
return beforeDataWhitespaceContinue;
|
|
100187
|
-
}
|
|
100188
|
-
if (code === codes.leftCurlyBrace) {
|
|
100189
|
-
seenOpenBrace = true;
|
|
100190
|
-
return captureData(code);
|
|
100191
|
-
}
|
|
100192
|
-
effects.exit('magicBlockData');
|
|
100193
|
-
effects.exit('magicBlock');
|
|
100194
|
-
return nok(code);
|
|
100195
|
-
}
|
|
100196
|
-
/**
|
|
100197
|
-
* Continuation OK before we've entered data token.
|
|
100198
|
-
*/
|
|
100199
|
-
function continuationOkBeforeData(code) {
|
|
100200
|
-
effects.enter('magicBlockLineEnding');
|
|
100201
|
-
effects.consume(code);
|
|
100202
|
-
effects.exit('magicBlockLineEnding');
|
|
100203
|
-
return beforeData; // Stay in beforeData state - don't enter magicBlockData yet
|
|
100204
|
-
}
|
|
100205
|
-
function captureData(code) {
|
|
100206
|
-
// EOF - magic block must be closed
|
|
100207
|
-
if (code === null) {
|
|
100208
|
-
effects.exit('magicBlockData');
|
|
100209
|
-
effects.exit('magicBlock');
|
|
100210
|
-
return nok(code);
|
|
100211
|
-
}
|
|
100212
|
-
// At line ending, check if we can continue on the next line
|
|
100213
|
-
if (markdownLineEnding(code)) {
|
|
100214
|
-
effects.exit('magicBlockData');
|
|
100215
|
-
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100216
|
-
}
|
|
100217
|
-
if (jsonState.escapeNext) {
|
|
100218
|
-
jsonState.escapeNext = false;
|
|
100219
|
-
effects.consume(code);
|
|
100220
|
-
return captureData;
|
|
100221
|
-
}
|
|
100222
|
-
if (jsonState.inString) {
|
|
100223
|
-
if (code === codes.backslash) {
|
|
100224
|
-
jsonState.escapeNext = true;
|
|
100225
|
-
effects.consume(code);
|
|
100226
|
-
return captureData;
|
|
100227
|
-
}
|
|
100228
|
-
if (code === codes.quotationMark) {
|
|
100229
|
-
jsonState.inString = false;
|
|
100230
|
-
}
|
|
100231
|
-
effects.consume(code);
|
|
100232
|
-
return captureData;
|
|
100233
|
-
}
|
|
100234
|
-
if (code === codes.quotationMark) {
|
|
100235
|
-
jsonState.inString = true;
|
|
100236
|
-
effects.consume(code);
|
|
100237
|
-
return captureData;
|
|
100238
|
-
}
|
|
100239
|
-
if (code === codes.leftSquareBracket) {
|
|
100240
|
-
effects.exit('magicBlockData');
|
|
100241
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100242
|
-
effects.consume(code);
|
|
100243
|
-
return expectSlash;
|
|
100244
|
-
}
|
|
100245
|
-
effects.consume(code);
|
|
100246
|
-
return captureData;
|
|
100247
|
-
}
|
|
100248
|
-
/**
|
|
100249
|
-
* Called when non-lazy continuation check passes - we can continue parsing.
|
|
100250
|
-
*/
|
|
100251
|
-
function continuationOk(code) {
|
|
100252
|
-
// Consume the line ending
|
|
100253
|
-
effects.enter('magicBlockLineEnding');
|
|
100254
|
-
effects.consume(code);
|
|
100255
|
-
effects.exit('magicBlockLineEnding');
|
|
100256
|
-
return continuationStart;
|
|
100257
|
-
}
|
|
100258
|
-
/**
|
|
100259
|
-
* Start of continuation line - check for more line endings, closing marker, or start capturing data.
|
|
100260
|
-
*/
|
|
100261
|
-
function continuationStart(code) {
|
|
100262
|
-
// Handle consecutive line endings
|
|
100263
|
-
if (code === null) {
|
|
100264
|
-
effects.exit('magicBlock');
|
|
100265
|
-
return nok(code);
|
|
100266
|
-
}
|
|
100267
|
-
if (markdownLineEnding(code)) {
|
|
100268
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100269
|
-
}
|
|
100270
|
-
// Check if this is the start of the closing marker [/block]
|
|
100271
|
-
// If so, handle it directly without entering magicBlockData
|
|
100272
|
-
if (code === codes.leftSquareBracket) {
|
|
100273
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100274
|
-
effects.consume(code);
|
|
100275
|
-
return expectSlashFromContinuation;
|
|
100276
|
-
}
|
|
100277
|
-
effects.enter('magicBlockData');
|
|
100278
|
-
return captureData(code);
|
|
100279
|
-
}
|
|
100280
|
-
/**
|
|
100281
|
-
* Check for closing marker slash when coming from continuation.
|
|
100282
|
-
* If not a closing marker, create an empty data token and continue.
|
|
100283
|
-
*/
|
|
100284
|
-
function expectSlashFromContinuation(code) {
|
|
100285
|
-
if (code === null) {
|
|
100286
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100287
|
-
effects.exit('magicBlock');
|
|
100288
|
-
return nok(code);
|
|
100289
|
-
}
|
|
100290
|
-
if (markdownLineEnding(code)) {
|
|
100291
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100292
|
-
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100293
|
-
}
|
|
100294
|
-
if (code === codes.slash) {
|
|
100295
|
-
effects.consume(code);
|
|
100296
|
-
return expectClosingB;
|
|
100297
|
-
}
|
|
100298
|
-
// Not a closing marker - this is data content
|
|
100299
|
-
// Exit marker and enter data
|
|
100300
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100301
|
-
effects.enter('magicBlockData');
|
|
100302
|
-
// The [ was consumed by the marker, so we need to conceptually "have it" in our data
|
|
100303
|
-
// But since we already consumed it into the marker, we need a different approach
|
|
100304
|
-
// Re-classify: consume this character as data and continue
|
|
100305
|
-
if (code === codes.quotationMark)
|
|
100306
|
-
jsonState.inString = true;
|
|
100307
|
-
effects.consume(code);
|
|
100308
|
-
return captureData;
|
|
100309
|
-
}
|
|
100310
|
-
function expectSlash(code) {
|
|
100311
|
-
if (code === null) {
|
|
100312
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100313
|
-
effects.exit('magicBlock');
|
|
100314
|
-
return nok(code);
|
|
100315
|
-
}
|
|
100316
|
-
// At line ending during marker parsing
|
|
100317
|
-
if (markdownLineEnding(code)) {
|
|
100318
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100319
|
-
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100320
|
-
}
|
|
100321
|
-
if (code !== codes.slash) {
|
|
100322
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100323
|
-
effects.enter('magicBlockData');
|
|
100324
|
-
if (code === codes.quotationMark)
|
|
100325
|
-
jsonState.inString = true;
|
|
100326
|
-
effects.consume(code);
|
|
100327
|
-
return captureData;
|
|
100328
|
-
}
|
|
100329
|
-
effects.consume(code);
|
|
100330
|
-
return expectClosingB;
|
|
100331
|
-
}
|
|
100332
|
-
function expectClosingB(code) {
|
|
100333
|
-
if (code === null) {
|
|
100334
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100335
|
-
effects.exit('magicBlock');
|
|
100336
|
-
return nok(code);
|
|
100337
|
-
}
|
|
100338
|
-
if (code !== codes.lowercaseB) {
|
|
100339
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100340
|
-
effects.enter('magicBlockData');
|
|
100341
|
-
if (code === codes.quotationMark)
|
|
100342
|
-
jsonState.inString = true;
|
|
100343
|
-
effects.consume(code);
|
|
100344
|
-
return captureData;
|
|
100345
|
-
}
|
|
100346
|
-
effects.consume(code);
|
|
100347
|
-
return expectClosingL;
|
|
100348
|
-
}
|
|
100349
|
-
function expectClosingL(code) {
|
|
100350
|
-
if (code === null) {
|
|
100351
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100352
|
-
effects.exit('magicBlock');
|
|
100353
|
-
return nok(code);
|
|
100354
|
-
}
|
|
100355
|
-
if (code !== codes.lowercaseL) {
|
|
100356
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100357
|
-
effects.enter('magicBlockData');
|
|
100358
|
-
if (code === codes.quotationMark)
|
|
100359
|
-
jsonState.inString = true;
|
|
100360
|
-
effects.consume(code);
|
|
100361
|
-
return captureData;
|
|
100362
|
-
}
|
|
100363
|
-
effects.consume(code);
|
|
100364
|
-
return expectClosingO;
|
|
100365
|
-
}
|
|
100366
|
-
function expectClosingO(code) {
|
|
100367
|
-
if (code === null) {
|
|
100368
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100369
|
-
effects.exit('magicBlock');
|
|
100370
|
-
return nok(code);
|
|
100371
|
-
}
|
|
100372
|
-
if (code !== codes.lowercaseO) {
|
|
100373
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100374
|
-
effects.enter('magicBlockData');
|
|
100375
|
-
if (code === codes.quotationMark)
|
|
100376
|
-
jsonState.inString = true;
|
|
100377
|
-
effects.consume(code);
|
|
100378
|
-
return captureData;
|
|
100379
|
-
}
|
|
100380
|
-
effects.consume(code);
|
|
100381
|
-
return expectClosingC;
|
|
100382
|
-
}
|
|
100383
|
-
function expectClosingC(code) {
|
|
100384
|
-
if (code === null) {
|
|
100385
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100386
|
-
effects.exit('magicBlock');
|
|
100387
|
-
return nok(code);
|
|
100388
|
-
}
|
|
100389
|
-
if (code !== codes.lowercaseC) {
|
|
100390
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100391
|
-
effects.enter('magicBlockData');
|
|
100392
|
-
if (code === codes.quotationMark)
|
|
100393
|
-
jsonState.inString = true;
|
|
100394
|
-
effects.consume(code);
|
|
100395
|
-
return captureData;
|
|
100396
|
-
}
|
|
100397
|
-
effects.consume(code);
|
|
100398
|
-
return expectClosingK;
|
|
100399
|
-
}
|
|
100400
|
-
function expectClosingK(code) {
|
|
100401
|
-
if (code === null) {
|
|
100402
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100403
|
-
effects.exit('magicBlock');
|
|
100404
|
-
return nok(code);
|
|
100405
|
-
}
|
|
100406
|
-
if (code !== codes.lowercaseK) {
|
|
100407
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100408
|
-
effects.enter('magicBlockData');
|
|
100409
|
-
if (code === codes.quotationMark)
|
|
100410
|
-
jsonState.inString = true;
|
|
100411
|
-
effects.consume(code);
|
|
100412
|
-
return captureData;
|
|
100413
|
-
}
|
|
100414
|
-
effects.consume(code);
|
|
100415
|
-
return expectClosingBracket;
|
|
100416
|
-
}
|
|
100417
|
-
function expectClosingBracket(code) {
|
|
100418
|
-
if (code === null) {
|
|
100419
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100420
|
-
effects.exit('magicBlock');
|
|
100421
|
-
return nok(code);
|
|
100422
|
-
}
|
|
100423
|
-
if (code !== codes.rightSquareBracket) {
|
|
100424
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100425
|
-
effects.enter('magicBlockData');
|
|
100426
|
-
if (code === codes.quotationMark)
|
|
100427
|
-
jsonState.inString = true;
|
|
100428
|
-
effects.consume(code);
|
|
100429
|
-
return captureData;
|
|
100430
|
-
}
|
|
100431
|
-
effects.consume(code);
|
|
100432
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100433
|
-
// Check for trailing whitespace on the same line
|
|
100434
|
-
return consumeTrailing;
|
|
100435
|
-
}
|
|
100436
|
-
/**
|
|
100437
|
-
* Consume trailing whitespace (spaces/tabs) on the same line after [/block].
|
|
100438
|
-
* For concrete flow constructs, we must end at eol/eof or fail.
|
|
100439
|
-
* Trailing whitespace is consumed; other content causes nok (text tokenizer handles it).
|
|
100440
|
-
*/
|
|
100441
|
-
function consumeTrailing(code) {
|
|
100442
|
-
// End of file - done
|
|
100443
|
-
if (code === null) {
|
|
100444
|
-
effects.exit('magicBlock');
|
|
100445
|
-
return ok(code);
|
|
100446
|
-
}
|
|
100447
|
-
// Line ending - done
|
|
100448
|
-
if (markdownLineEnding(code)) {
|
|
100449
|
-
effects.exit('magicBlock');
|
|
100450
|
-
return ok(code);
|
|
100451
|
-
}
|
|
100452
|
-
// Space or tab - consume as trailing whitespace
|
|
100453
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100454
|
-
effects.enter('magicBlockTrailing');
|
|
100455
|
-
effects.consume(code);
|
|
100456
|
-
return consumeTrailingContinue;
|
|
100457
|
-
}
|
|
100458
|
-
// Any other character - fail flow tokenizer, let text tokenizer handle it
|
|
100459
|
-
effects.exit('magicBlock');
|
|
100460
|
-
return nok(code);
|
|
100461
|
-
}
|
|
100462
|
-
/**
|
|
100463
|
-
* Continue consuming trailing whitespace.
|
|
100464
|
-
*/
|
|
100465
|
-
function consumeTrailingContinue(code) {
|
|
100466
|
-
// End of file - done
|
|
100467
|
-
if (code === null) {
|
|
100468
|
-
effects.exit('magicBlockTrailing');
|
|
100469
|
-
effects.exit('magicBlock');
|
|
100470
|
-
return ok(code);
|
|
100471
|
-
}
|
|
100472
|
-
// Line ending - done
|
|
100473
|
-
if (markdownLineEnding(code)) {
|
|
100474
|
-
effects.exit('magicBlockTrailing');
|
|
100475
|
-
effects.exit('magicBlock');
|
|
100476
|
-
return ok(code);
|
|
100477
|
-
}
|
|
100478
|
-
// More space or tab - keep consuming
|
|
100479
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100480
|
-
effects.consume(code);
|
|
100481
|
-
return consumeTrailingContinue;
|
|
100482
|
-
}
|
|
100483
|
-
// Non-whitespace after whitespace - fail flow tokenizer
|
|
100484
|
-
effects.exit('magicBlockTrailing');
|
|
100485
|
-
effects.exit('magicBlock');
|
|
100486
|
-
return nok(code);
|
|
100487
|
-
}
|
|
100488
|
-
/**
|
|
100489
|
-
* Called when we can't continue (lazy line or EOF) - exit the construct.
|
|
100490
|
-
*/
|
|
100491
|
-
function after(code) {
|
|
100492
|
-
effects.exit('magicBlock');
|
|
100493
|
-
return nok(code);
|
|
100494
|
-
}
|
|
100495
|
-
}
|
|
100496
|
-
/**
|
|
100497
|
-
* Text tokenizer for single-line magic blocks only.
|
|
100498
|
-
* Used in inline contexts like list items and paragraphs.
|
|
100499
|
-
* Multiline blocks are handled by the flow tokenizer.
|
|
100500
|
-
*/
|
|
100501
|
-
function tokenizeMagicBlockText(effects, ok, nok) {
|
|
100502
|
-
// State for tracking JSON content
|
|
100503
|
-
const jsonState = { escapeNext: false, inString: false };
|
|
100504
|
-
const blockTypeRef = { value: '' };
|
|
100505
|
-
let seenOpenBrace = false;
|
|
100506
|
-
// Create shared parsers for opening marker and type capture
|
|
100507
|
-
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
100508
|
-
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
100509
|
-
// Success handler for closing marker - exits tokens and returns ok
|
|
100510
|
-
const closingSuccess = (code) => {
|
|
100511
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100512
|
-
effects.exit('magicBlock');
|
|
100513
|
-
return ok(code);
|
|
100514
|
-
};
|
|
100515
|
-
// Mismatch handler - falls back to data capture
|
|
100516
|
-
const closingMismatch = (code) => {
|
|
100517
|
-
effects.exit('magicBlockMarkerEnd');
|
|
100518
|
-
effects.enter('magicBlockData');
|
|
100519
|
-
if (code === codes.quotationMark)
|
|
100520
|
-
jsonState.inString = true;
|
|
100521
|
-
effects.consume(code);
|
|
100522
|
-
return captureData;
|
|
100523
|
-
};
|
|
100524
|
-
// EOF handler
|
|
100525
|
-
const closingEof = (_code) => nok(_code);
|
|
100526
|
-
// Create closing marker parsers
|
|
100527
|
-
const closingFromBeforeData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
100528
|
-
const closingFromData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
100529
|
-
return start;
|
|
100530
|
-
function start(code) {
|
|
100531
|
-
if (code !== codes.leftSquareBracket)
|
|
100532
|
-
return nok(code);
|
|
100533
|
-
effects.enter('magicBlock');
|
|
100534
|
-
effects.enter('magicBlockMarkerStart');
|
|
100535
|
-
effects.consume(code);
|
|
100536
|
-
return openingMarkerParser;
|
|
100537
|
-
}
|
|
100538
|
-
/**
|
|
100539
|
-
* State before data content - handles line endings before entering data token.
|
|
100540
|
-
* Whitespace before '{' is allowed.
|
|
100541
|
-
*/
|
|
100542
|
-
function beforeData(code) {
|
|
100543
|
-
// Fail on EOF - magic block must be closed
|
|
100544
|
-
if (code === null) {
|
|
100545
|
-
return nok(code);
|
|
100546
|
-
}
|
|
100547
|
-
// Handle line endings before any data - consume them without entering data token
|
|
100548
|
-
if (markdownLineEnding(code)) {
|
|
100549
|
-
effects.enter('magicBlockLineEnding');
|
|
100550
|
-
effects.consume(code);
|
|
100551
|
-
effects.exit('magicBlockLineEnding');
|
|
100552
|
-
return beforeData;
|
|
100553
|
-
}
|
|
100554
|
-
// Check for closing marker directly (without entering data)
|
|
100555
|
-
if (code === codes.leftSquareBracket) {
|
|
100556
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100557
|
-
effects.consume(code);
|
|
100558
|
-
return closingFromBeforeData.expectSlash;
|
|
100559
|
-
}
|
|
100560
|
-
// If we've already seen the opening brace, just continue capturing data
|
|
100561
|
-
if (seenOpenBrace) {
|
|
100562
|
-
effects.enter('magicBlockData');
|
|
100563
|
-
return captureData(code);
|
|
100564
|
-
}
|
|
100565
|
-
// Skip whitespace (spaces/tabs) before the data
|
|
100566
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100567
|
-
return beforeDataWhitespace(code);
|
|
100568
|
-
}
|
|
100569
|
-
// Data must start with '{' for valid JSON
|
|
100570
|
-
if (code !== codes.leftCurlyBrace) {
|
|
100571
|
-
return nok(code);
|
|
100572
|
-
}
|
|
100573
|
-
// We have '{' - enter data token and start capturing
|
|
100574
|
-
seenOpenBrace = true;
|
|
100575
|
-
effects.enter('magicBlockData');
|
|
100576
|
-
return captureData(code);
|
|
100577
|
-
}
|
|
100578
|
-
/**
|
|
100579
|
-
* Consume whitespace before the data.
|
|
100580
|
-
*/
|
|
100581
|
-
function beforeDataWhitespace(code) {
|
|
100582
|
-
if (code === null) {
|
|
100583
|
-
return nok(code);
|
|
100584
|
-
}
|
|
100585
|
-
if (markdownLineEnding(code)) {
|
|
100586
|
-
effects.enter('magicBlockLineEnding');
|
|
100587
|
-
effects.consume(code);
|
|
100588
|
-
effects.exit('magicBlockLineEnding');
|
|
100589
|
-
return beforeData;
|
|
100590
|
-
}
|
|
100591
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100592
|
-
effects.enter('magicBlockData');
|
|
100593
|
-
effects.consume(code);
|
|
100594
|
-
return beforeDataWhitespaceContinue;
|
|
100595
|
-
}
|
|
100596
|
-
if (code === codes.leftCurlyBrace) {
|
|
100597
|
-
seenOpenBrace = true;
|
|
100598
|
-
effects.enter('magicBlockData');
|
|
100599
|
-
return captureData(code);
|
|
100600
|
-
}
|
|
100601
|
-
return nok(code);
|
|
100602
|
-
}
|
|
100603
|
-
/**
|
|
100604
|
-
* Continue consuming whitespace or validate the opening brace.
|
|
100605
|
-
*/
|
|
100606
|
-
function beforeDataWhitespaceContinue(code) {
|
|
100607
|
-
if (code === null) {
|
|
100608
|
-
effects.exit('magicBlockData');
|
|
100609
|
-
return nok(code);
|
|
100610
|
-
}
|
|
100611
|
-
if (markdownLineEnding(code)) {
|
|
100612
|
-
effects.exit('magicBlockData');
|
|
100613
|
-
effects.enter('magicBlockLineEnding');
|
|
100614
|
-
effects.consume(code);
|
|
100615
|
-
effects.exit('magicBlockLineEnding');
|
|
100616
|
-
return beforeData;
|
|
100617
|
-
}
|
|
100618
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
100619
|
-
effects.consume(code);
|
|
100620
|
-
return beforeDataWhitespaceContinue;
|
|
100621
|
-
}
|
|
100622
|
-
if (code === codes.leftCurlyBrace) {
|
|
100623
|
-
seenOpenBrace = true;
|
|
100624
|
-
return captureData(code);
|
|
100625
|
-
}
|
|
100626
|
-
effects.exit('magicBlockData');
|
|
100627
|
-
return nok(code);
|
|
100628
|
-
}
|
|
100629
|
-
function captureData(code) {
|
|
100630
|
-
// Fail on EOF - magic block must be closed
|
|
100631
|
-
if (code === null) {
|
|
100632
|
-
effects.exit('magicBlockData');
|
|
100633
|
-
return nok(code);
|
|
100634
|
-
}
|
|
100635
|
-
// Handle multiline magic blocks within text/paragraphs
|
|
100636
|
-
// Exit data, consume line ending with proper token, then re-enter data
|
|
100637
|
-
if (markdownLineEnding(code)) {
|
|
100638
|
-
effects.exit('magicBlockData');
|
|
100639
|
-
effects.enter('magicBlockLineEnding');
|
|
100640
|
-
effects.consume(code);
|
|
100641
|
-
effects.exit('magicBlockLineEnding');
|
|
100642
|
-
return beforeData; // Go back to beforeData to handle potential empty lines
|
|
100643
|
-
}
|
|
100644
|
-
if (jsonState.escapeNext) {
|
|
100645
|
-
jsonState.escapeNext = false;
|
|
100646
|
-
effects.consume(code);
|
|
100647
|
-
return captureData;
|
|
100648
|
-
}
|
|
100649
|
-
if (jsonState.inString) {
|
|
100650
|
-
if (code === codes.backslash) {
|
|
100651
|
-
jsonState.escapeNext = true;
|
|
100652
|
-
effects.consume(code);
|
|
100653
|
-
return captureData;
|
|
100654
|
-
}
|
|
100655
|
-
if (code === codes.quotationMark) {
|
|
100656
|
-
jsonState.inString = false;
|
|
100657
|
-
}
|
|
100658
|
-
effects.consume(code);
|
|
100659
|
-
return captureData;
|
|
100660
|
-
}
|
|
100661
|
-
if (code === codes.quotationMark) {
|
|
100662
|
-
jsonState.inString = true;
|
|
100663
|
-
effects.consume(code);
|
|
100664
|
-
return captureData;
|
|
100665
|
-
}
|
|
100666
|
-
if (code === codes.leftSquareBracket) {
|
|
100667
|
-
effects.exit('magicBlockData');
|
|
100668
|
-
effects.enter('magicBlockMarkerEnd');
|
|
100669
|
-
effects.consume(code);
|
|
100670
|
-
return closingFromData.expectSlash;
|
|
100671
|
-
}
|
|
100672
|
-
effects.consume(code);
|
|
100673
|
-
return captureData;
|
|
100674
|
-
}
|
|
100675
|
-
}
|
|
100676
|
-
/* harmony default export */ const syntax = ((/* unused pure expression or super */ null && (magicBlock)));
|
|
100677
|
-
|
|
100678
|
-
;// ./lib/micromark/magic-block/index.ts
|
|
100679
|
-
/**
|
|
100680
|
-
* Micromark extension for magic block syntax.
|
|
100681
|
-
*
|
|
100682
|
-
* Usage:
|
|
100683
|
-
* ```ts
|
|
100684
|
-
* import { magicBlock } from './lib/micromark/magic-block';
|
|
100685
|
-
*
|
|
100686
|
-
* const processor = unified()
|
|
100687
|
-
* .data('micromarkExtensions', [magicBlock()])
|
|
100688
|
-
* ```
|
|
100689
|
-
*/
|
|
100690
|
-
|
|
100691
|
-
|
|
100692
|
-
;// ./node_modules/micromark-util-symbol/lib/types.js
|
|
100693
|
-
/**
|
|
100694
|
-
* This module is compiled away!
|
|
100695
|
-
*
|
|
100696
|
-
* Here is the list of all types of tokens exposed by micromark, with a short
|
|
100697
|
-
* explanation of what they include and where they are found.
|
|
100698
|
-
* In picking names, generally, the rule is to be as explicit as possible
|
|
100699
|
-
* instead of reusing names.
|
|
100700
|
-
* For example, there is a `definitionDestination` and a `resourceDestination`,
|
|
100701
|
-
* instead of one shared name.
|
|
99872
|
+
* Here is the list of all types of tokens exposed by micromark, with a short
|
|
99873
|
+
* explanation of what they include and where they are found.
|
|
99874
|
+
* In picking names, generally, the rule is to be as explicit as possible
|
|
99875
|
+
* instead of reusing names.
|
|
99876
|
+
* For example, there is a `definitionDestination` and a `resourceDestination`,
|
|
99877
|
+
* instead of one shared name.
|
|
100702
99878
|
*/
|
|
100703
99879
|
|
|
100704
99880
|
// Note: when changing the next record, you must also change `TokenTypeMap`
|
|
@@ -101144,36 +100320,18 @@ const types_types = /** @type {const} */ ({
|
|
|
101144
100320
|
chunkString: 'chunkString'
|
|
101145
100321
|
})
|
|
101146
100322
|
|
|
101147
|
-
;// ./lib/micromark/
|
|
101148
|
-
|
|
101149
|
-
|
|
101150
|
-
|
|
100323
|
+
;// ./lib/micromark/jsx-table/syntax.ts
|
|
101151
100324
|
|
|
101152
100325
|
|
|
101153
|
-
// Raw tags (type-1: pre/script/style/textarea) and block tags (type-6: div,
|
|
101154
|
-
// section, …) always start a block, so they stay flow even with trailing
|
|
101155
|
-
// content. Other lowercase tags (i, span, …) follow the type-7 rule and only
|
|
101156
|
-
// stay flow when nothing trails the close tag.
|
|
101157
|
-
const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
|
|
101158
|
-
// Lowercase type-6 block tags claimable in flow even without a `{…}` attribute, so
|
|
101159
|
-
// blank lines between nested JSX siblings don't fragment the block. Excludes table
|
|
101160
|
-
// tags (mdxishTables owns their blank lines) and voids (never close).
|
|
101161
|
-
const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
|
|
101162
100326
|
const syntax_nonLazyContinuationStart = {
|
|
101163
100327
|
tokenize: syntax_tokenizeNonLazyContinuationStart,
|
|
101164
100328
|
partial: true,
|
|
101165
100329
|
};
|
|
101166
|
-
|
|
101167
|
-
// that merely starts with a tag? Run via `effects.check` so it never consumes.
|
|
101168
|
-
const markupOnlyContinuation = {
|
|
101169
|
-
tokenize: tokenizeMarkupOnlyContinuation,
|
|
101170
|
-
partial: true,
|
|
101171
|
-
};
|
|
101172
|
-
function resolveToMdxComponent(events) {
|
|
100330
|
+
function resolveToJsxTable(events) {
|
|
101173
100331
|
let index = events.length;
|
|
101174
100332
|
while (index > 0) {
|
|
101175
100333
|
index -= 1;
|
|
101176
|
-
if (events[index][0] === 'enter' && events[index][1].type === '
|
|
100334
|
+
if (events[index][0] === 'enter' && events[index][1].type === 'jsxTable') {
|
|
101177
100335
|
break;
|
|
101178
100336
|
}
|
|
101179
100337
|
}
|
|
@@ -101184,11 +100342,1117 @@ function resolveToMdxComponent(events) {
|
|
|
101184
100342
|
}
|
|
101185
100343
|
return events;
|
|
101186
100344
|
}
|
|
101187
|
-
const
|
|
101188
|
-
name: '
|
|
101189
|
-
tokenize:
|
|
101190
|
-
resolveTo:
|
|
101191
|
-
concrete: true,
|
|
100345
|
+
const jsxTableConstruct = {
|
|
100346
|
+
name: 'jsxTable',
|
|
100347
|
+
tokenize: tokenizeJsxTable,
|
|
100348
|
+
resolveTo: resolveToJsxTable,
|
|
100349
|
+
concrete: true,
|
|
100350
|
+
};
|
|
100351
|
+
function tokenizeJsxTable(effects, ok, nok) {
|
|
100352
|
+
let codeSpanOpenSize = 0;
|
|
100353
|
+
let codeSpanCloseSize = 0;
|
|
100354
|
+
let depth = 1;
|
|
100355
|
+
const ABLE_SUFFIX = [codes.lowercaseA, codes.lowercaseB, codes.lowercaseL, codes.lowercaseE];
|
|
100356
|
+
/** Build a state chain that matches a sequence of character codes. */
|
|
100357
|
+
function matchChars(chars, onMatch, onFail) {
|
|
100358
|
+
if (chars.length === 0)
|
|
100359
|
+
return onMatch;
|
|
100360
|
+
return ((code) => {
|
|
100361
|
+
if (code === chars[0]) {
|
|
100362
|
+
effects.consume(code);
|
|
100363
|
+
return matchChars(chars.slice(1), onMatch, onFail);
|
|
100364
|
+
}
|
|
100365
|
+
return onFail(code);
|
|
100366
|
+
});
|
|
100367
|
+
}
|
|
100368
|
+
return start;
|
|
100369
|
+
function start(code) {
|
|
100370
|
+
if (code !== codes.lessThan)
|
|
100371
|
+
return nok(code);
|
|
100372
|
+
effects.enter('jsxTable');
|
|
100373
|
+
effects.enter('jsxTableData');
|
|
100374
|
+
effects.consume(code);
|
|
100375
|
+
return afterLessThan;
|
|
100376
|
+
}
|
|
100377
|
+
function afterLessThan(code) {
|
|
100378
|
+
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
100379
|
+
effects.consume(code);
|
|
100380
|
+
return matchChars(ABLE_SUFFIX, afterTagName, nok);
|
|
100381
|
+
}
|
|
100382
|
+
return nok(code);
|
|
100383
|
+
}
|
|
100384
|
+
function afterTagName(code) {
|
|
100385
|
+
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
100386
|
+
effects.consume(code);
|
|
100387
|
+
return body;
|
|
100388
|
+
}
|
|
100389
|
+
return nok(code);
|
|
100390
|
+
}
|
|
100391
|
+
function body(code) {
|
|
100392
|
+
// Reject unclosed <Table> so it falls back to normal HTML block parsing
|
|
100393
|
+
// instead of swallowing all subsequent content to EOF
|
|
100394
|
+
if (code === null) {
|
|
100395
|
+
return nok(code);
|
|
100396
|
+
}
|
|
100397
|
+
if (markdownLineEnding(code)) {
|
|
100398
|
+
effects.exit('jsxTableData');
|
|
100399
|
+
return continuationStart(code);
|
|
100400
|
+
}
|
|
100401
|
+
if (code === codes.backslash) {
|
|
100402
|
+
effects.consume(code);
|
|
100403
|
+
return escapedChar;
|
|
100404
|
+
}
|
|
100405
|
+
if (code === codes.lessThan) {
|
|
100406
|
+
effects.consume(code);
|
|
100407
|
+
return closeSlash;
|
|
100408
|
+
}
|
|
100409
|
+
// Skip over backtick code spans so `</Table>` in inline code isn't
|
|
100410
|
+
// treated as the closing tag
|
|
100411
|
+
if (code === codes.graveAccent) {
|
|
100412
|
+
codeSpanOpenSize = 0;
|
|
100413
|
+
return countOpenTicks(code);
|
|
100414
|
+
}
|
|
100415
|
+
effects.consume(code);
|
|
100416
|
+
return body;
|
|
100417
|
+
}
|
|
100418
|
+
function countOpenTicks(code) {
|
|
100419
|
+
if (code === codes.graveAccent) {
|
|
100420
|
+
codeSpanOpenSize += 1;
|
|
100421
|
+
effects.consume(code);
|
|
100422
|
+
return countOpenTicks;
|
|
100423
|
+
}
|
|
100424
|
+
return inCodeSpan(code);
|
|
100425
|
+
}
|
|
100426
|
+
function inCodeSpan(code) {
|
|
100427
|
+
if (code === null || markdownLineEnding(code))
|
|
100428
|
+
return body(code);
|
|
100429
|
+
if (code === codes.graveAccent) {
|
|
100430
|
+
codeSpanCloseSize = 0;
|
|
100431
|
+
return countCloseTicks(code);
|
|
100432
|
+
}
|
|
100433
|
+
effects.consume(code);
|
|
100434
|
+
return inCodeSpan;
|
|
100435
|
+
}
|
|
100436
|
+
function countCloseTicks(code) {
|
|
100437
|
+
if (code === codes.graveAccent) {
|
|
100438
|
+
codeSpanCloseSize += 1;
|
|
100439
|
+
effects.consume(code);
|
|
100440
|
+
return countCloseTicks;
|
|
100441
|
+
}
|
|
100442
|
+
return codeSpanCloseSize === codeSpanOpenSize ? body(code) : inCodeSpan(code);
|
|
100443
|
+
}
|
|
100444
|
+
function escapedChar(code) {
|
|
100445
|
+
if (code === null || markdownLineEnding(code)) {
|
|
100446
|
+
return body(code);
|
|
100447
|
+
}
|
|
100448
|
+
effects.consume(code);
|
|
100449
|
+
return body;
|
|
100450
|
+
}
|
|
100451
|
+
function closeSlash(code) {
|
|
100452
|
+
if (code === codes.slash) {
|
|
100453
|
+
effects.consume(code);
|
|
100454
|
+
return closeTagFirstChar;
|
|
100455
|
+
}
|
|
100456
|
+
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
100457
|
+
effects.consume(code);
|
|
100458
|
+
return matchChars(ABLE_SUFFIX, openAfterTagName, body);
|
|
100459
|
+
}
|
|
100460
|
+
return body(code);
|
|
100461
|
+
}
|
|
100462
|
+
function closeTagFirstChar(code) {
|
|
100463
|
+
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
100464
|
+
effects.consume(code);
|
|
100465
|
+
return matchChars(ABLE_SUFFIX, closeGt, body);
|
|
100466
|
+
}
|
|
100467
|
+
return body(code);
|
|
100468
|
+
}
|
|
100469
|
+
function openAfterTagName(code) {
|
|
100470
|
+
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
100471
|
+
depth += 1;
|
|
100472
|
+
effects.consume(code);
|
|
100473
|
+
return body;
|
|
100474
|
+
}
|
|
100475
|
+
return body(code);
|
|
100476
|
+
}
|
|
100477
|
+
function closeGt(code) {
|
|
100478
|
+
if (code === codes.greaterThan) {
|
|
100479
|
+
depth -= 1;
|
|
100480
|
+
effects.consume(code);
|
|
100481
|
+
if (depth === 0) {
|
|
100482
|
+
return afterClose;
|
|
100483
|
+
}
|
|
100484
|
+
return body;
|
|
100485
|
+
}
|
|
100486
|
+
return body(code);
|
|
100487
|
+
}
|
|
100488
|
+
function afterClose(code) {
|
|
100489
|
+
if (code === null || markdownLineEnding(code)) {
|
|
100490
|
+
effects.exit('jsxTableData');
|
|
100491
|
+
effects.exit('jsxTable');
|
|
100492
|
+
return ok(code);
|
|
100493
|
+
}
|
|
100494
|
+
effects.consume(code);
|
|
100495
|
+
return afterClose;
|
|
100496
|
+
}
|
|
100497
|
+
// Line ending handling — follows the htmlFlow pattern
|
|
100498
|
+
function continuationStart(code) {
|
|
100499
|
+
return effects.check(syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
100500
|
+
}
|
|
100501
|
+
function continuationStartNonLazy(code) {
|
|
100502
|
+
effects.enter(types_types.lineEnding);
|
|
100503
|
+
effects.consume(code);
|
|
100504
|
+
effects.exit(types_types.lineEnding);
|
|
100505
|
+
return continuationBefore;
|
|
100506
|
+
}
|
|
100507
|
+
function continuationBefore(code) {
|
|
100508
|
+
if (code === null || markdownLineEnding(code)) {
|
|
100509
|
+
return continuationStart(code);
|
|
100510
|
+
}
|
|
100511
|
+
effects.enter('jsxTableData');
|
|
100512
|
+
return body(code);
|
|
100513
|
+
}
|
|
100514
|
+
function continuationAfter(code) {
|
|
100515
|
+
// At EOF without </Table>, reject so content isn't swallowed
|
|
100516
|
+
if (code === null) {
|
|
100517
|
+
return nok(code);
|
|
100518
|
+
}
|
|
100519
|
+
effects.exit('jsxTable');
|
|
100520
|
+
return ok(code);
|
|
100521
|
+
}
|
|
100522
|
+
}
|
|
100523
|
+
function syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
100524
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
100525
|
+
const self = this;
|
|
100526
|
+
return start;
|
|
100527
|
+
function start(code) {
|
|
100528
|
+
if (markdownLineEnding(code)) {
|
|
100529
|
+
effects.enter(types_types.lineEnding);
|
|
100530
|
+
effects.consume(code);
|
|
100531
|
+
effects.exit(types_types.lineEnding);
|
|
100532
|
+
return after;
|
|
100533
|
+
}
|
|
100534
|
+
return nok(code);
|
|
100535
|
+
}
|
|
100536
|
+
function after(code) {
|
|
100537
|
+
if (self.parser.lazy[self.now().line]) {
|
|
100538
|
+
return nok(code);
|
|
100539
|
+
}
|
|
100540
|
+
return ok(code);
|
|
100541
|
+
}
|
|
100542
|
+
}
|
|
100543
|
+
/**
|
|
100544
|
+
* Micromark extension that tokenizes `<Table>...</Table>` and `<table>...</table>`
|
|
100545
|
+
* as a single flow block.
|
|
100546
|
+
*
|
|
100547
|
+
* Prevents CommonMark HTML block type 6 from fragmenting table blocks at blank lines.
|
|
100548
|
+
*/
|
|
100549
|
+
function jsxTable() {
|
|
100550
|
+
return {
|
|
100551
|
+
flow: {
|
|
100552
|
+
[codes.lessThan]: [jsxTableConstruct],
|
|
100553
|
+
},
|
|
100554
|
+
};
|
|
100555
|
+
}
|
|
100556
|
+
|
|
100557
|
+
;// ./lib/micromark/jsx-table/index.ts
|
|
100558
|
+
|
|
100559
|
+
|
|
100560
|
+
;// ./lib/micromark/magic-block/syntax.ts
|
|
100561
|
+
|
|
100562
|
+
|
|
100563
|
+
/**
|
|
100564
|
+
* Known magic block types that the tokenizer will recognize.
|
|
100565
|
+
* Unknown types will not be tokenized as magic blocks.
|
|
100566
|
+
*/
|
|
100567
|
+
const KNOWN_BLOCK_TYPES = new Set([
|
|
100568
|
+
'code',
|
|
100569
|
+
'api-header',
|
|
100570
|
+
'image',
|
|
100571
|
+
'callout',
|
|
100572
|
+
'parameters',
|
|
100573
|
+
'table',
|
|
100574
|
+
'embed',
|
|
100575
|
+
'html',
|
|
100576
|
+
'recipe',
|
|
100577
|
+
'tutorial-tile',
|
|
100578
|
+
]);
|
|
100579
|
+
/**
|
|
100580
|
+
* Check if a character is valid for a magic block type identifier.
|
|
100581
|
+
* Types can contain alphanumeric characters and hyphens (e.g., "api-header", "tutorial-tile")
|
|
100582
|
+
*/
|
|
100583
|
+
function isTypeChar(code) {
|
|
100584
|
+
return asciiAlphanumeric(code) || code === codes.dash;
|
|
100585
|
+
}
|
|
100586
|
+
/**
|
|
100587
|
+
* Creates the opening marker state machine: [block:
|
|
100588
|
+
* Returns the first state function to start parsing.
|
|
100589
|
+
*/
|
|
100590
|
+
function createOpeningMarkerParser(effects, nok, onComplete) {
|
|
100591
|
+
const expectB = (code) => {
|
|
100592
|
+
if (code !== codes.lowercaseB)
|
|
100593
|
+
return nok(code);
|
|
100594
|
+
effects.consume(code);
|
|
100595
|
+
return expectL;
|
|
100596
|
+
};
|
|
100597
|
+
const expectL = (code) => {
|
|
100598
|
+
if (code !== codes.lowercaseL)
|
|
100599
|
+
return nok(code);
|
|
100600
|
+
effects.consume(code);
|
|
100601
|
+
return expectO;
|
|
100602
|
+
};
|
|
100603
|
+
const expectO = (code) => {
|
|
100604
|
+
if (code !== codes.lowercaseO)
|
|
100605
|
+
return nok(code);
|
|
100606
|
+
effects.consume(code);
|
|
100607
|
+
return expectC;
|
|
100608
|
+
};
|
|
100609
|
+
const expectC = (code) => {
|
|
100610
|
+
if (code !== codes.lowercaseC)
|
|
100611
|
+
return nok(code);
|
|
100612
|
+
effects.consume(code);
|
|
100613
|
+
return expectK;
|
|
100614
|
+
};
|
|
100615
|
+
const expectK = (code) => {
|
|
100616
|
+
if (code !== codes.lowercaseK)
|
|
100617
|
+
return nok(code);
|
|
100618
|
+
effects.consume(code);
|
|
100619
|
+
return expectColon;
|
|
100620
|
+
};
|
|
100621
|
+
const expectColon = (code) => {
|
|
100622
|
+
if (code !== codes.colon)
|
|
100623
|
+
return nok(code);
|
|
100624
|
+
effects.consume(code);
|
|
100625
|
+
effects.exit('magicBlockMarkerStart');
|
|
100626
|
+
effects.enter('magicBlockType');
|
|
100627
|
+
return onComplete;
|
|
100628
|
+
};
|
|
100629
|
+
return expectB;
|
|
100630
|
+
}
|
|
100631
|
+
/**
|
|
100632
|
+
* Creates the type capture state machine.
|
|
100633
|
+
* Captures type characters until ] and validates against known types.
|
|
100634
|
+
*/
|
|
100635
|
+
function createTypeCaptureParser(effects, nok, onComplete, blockTypeRef) {
|
|
100636
|
+
const captureTypeFirst = (code) => {
|
|
100637
|
+
// Reject empty type name [block:]
|
|
100638
|
+
if (code === codes.rightSquareBracket) {
|
|
100639
|
+
return nok(code);
|
|
100640
|
+
}
|
|
100641
|
+
if (isTypeChar(code)) {
|
|
100642
|
+
blockTypeRef.value += String.fromCharCode(code);
|
|
100643
|
+
effects.consume(code);
|
|
100644
|
+
return captureType;
|
|
100645
|
+
}
|
|
100646
|
+
return nok(code);
|
|
100647
|
+
};
|
|
100648
|
+
const captureType = (code) => {
|
|
100649
|
+
if (code === codes.rightSquareBracket) {
|
|
100650
|
+
if (!KNOWN_BLOCK_TYPES.has(blockTypeRef.value)) {
|
|
100651
|
+
return nok(code);
|
|
100652
|
+
}
|
|
100653
|
+
effects.exit('magicBlockType');
|
|
100654
|
+
effects.enter('magicBlockMarkerTypeEnd');
|
|
100655
|
+
effects.consume(code);
|
|
100656
|
+
effects.exit('magicBlockMarkerTypeEnd');
|
|
100657
|
+
return onComplete;
|
|
100658
|
+
}
|
|
100659
|
+
if (isTypeChar(code)) {
|
|
100660
|
+
blockTypeRef.value += String.fromCharCode(code);
|
|
100661
|
+
effects.consume(code);
|
|
100662
|
+
return captureType;
|
|
100663
|
+
}
|
|
100664
|
+
return nok(code);
|
|
100665
|
+
};
|
|
100666
|
+
return { first: captureTypeFirst, remaining: captureType };
|
|
100667
|
+
}
|
|
100668
|
+
/**
|
|
100669
|
+
* Creates the closing marker state machine: /block]
|
|
100670
|
+
* Handles partial matches by calling onMismatch to fall back to data capture.
|
|
100671
|
+
*/
|
|
100672
|
+
function createClosingMarkerParser(effects, onSuccess, onMismatch, onEof, jsonState) {
|
|
100673
|
+
const handleMismatch = (code) => {
|
|
100674
|
+
if (jsonState && code === codes.quotationMark) {
|
|
100675
|
+
jsonState.inString = true;
|
|
100676
|
+
}
|
|
100677
|
+
return onMismatch(code);
|
|
100678
|
+
};
|
|
100679
|
+
const expectSlash = (code) => {
|
|
100680
|
+
if (code === null)
|
|
100681
|
+
return onEof(code);
|
|
100682
|
+
if (code !== codes.slash)
|
|
100683
|
+
return handleMismatch(code);
|
|
100684
|
+
effects.consume(code);
|
|
100685
|
+
return expectB;
|
|
100686
|
+
};
|
|
100687
|
+
const expectB = (code) => {
|
|
100688
|
+
if (code === null)
|
|
100689
|
+
return onEof(code);
|
|
100690
|
+
if (code !== codes.lowercaseB)
|
|
100691
|
+
return handleMismatch(code);
|
|
100692
|
+
effects.consume(code);
|
|
100693
|
+
return expectL;
|
|
100694
|
+
};
|
|
100695
|
+
const expectL = (code) => {
|
|
100696
|
+
if (code === null)
|
|
100697
|
+
return onEof(code);
|
|
100698
|
+
if (code !== codes.lowercaseL)
|
|
100699
|
+
return handleMismatch(code);
|
|
100700
|
+
effects.consume(code);
|
|
100701
|
+
return expectO;
|
|
100702
|
+
};
|
|
100703
|
+
const expectO = (code) => {
|
|
100704
|
+
if (code === null)
|
|
100705
|
+
return onEof(code);
|
|
100706
|
+
if (code !== codes.lowercaseO)
|
|
100707
|
+
return handleMismatch(code);
|
|
100708
|
+
effects.consume(code);
|
|
100709
|
+
return expectC;
|
|
100710
|
+
};
|
|
100711
|
+
const expectC = (code) => {
|
|
100712
|
+
if (code === null)
|
|
100713
|
+
return onEof(code);
|
|
100714
|
+
if (code !== codes.lowercaseC)
|
|
100715
|
+
return handleMismatch(code);
|
|
100716
|
+
effects.consume(code);
|
|
100717
|
+
return expectK;
|
|
100718
|
+
};
|
|
100719
|
+
const expectK = (code) => {
|
|
100720
|
+
if (code === null)
|
|
100721
|
+
return onEof(code);
|
|
100722
|
+
if (code !== codes.lowercaseK)
|
|
100723
|
+
return handleMismatch(code);
|
|
100724
|
+
effects.consume(code);
|
|
100725
|
+
return expectBracket;
|
|
100726
|
+
};
|
|
100727
|
+
const expectBracket = (code) => {
|
|
100728
|
+
if (code === null)
|
|
100729
|
+
return onEof(code);
|
|
100730
|
+
if (code !== codes.rightSquareBracket)
|
|
100731
|
+
return handleMismatch(code);
|
|
100732
|
+
effects.consume(code);
|
|
100733
|
+
return onSuccess;
|
|
100734
|
+
};
|
|
100735
|
+
return { expectSlash };
|
|
100736
|
+
}
|
|
100737
|
+
/**
|
|
100738
|
+
* Partial construct for checking non-lazy continuation.
|
|
100739
|
+
* This is used by the flow tokenizer to check if we can continue
|
|
100740
|
+
* parsing on the next line.
|
|
100741
|
+
*/
|
|
100742
|
+
const syntax_nonLazyContinuation = {
|
|
100743
|
+
partial: true,
|
|
100744
|
+
tokenize: syntax_tokenizeNonLazyContinuation,
|
|
100745
|
+
};
|
|
100746
|
+
/**
|
|
100747
|
+
* Tokenizer for non-lazy continuation checking.
|
|
100748
|
+
* Returns ok if the next line is non-lazy (can continue), nok if lazy.
|
|
100749
|
+
*/
|
|
100750
|
+
function syntax_tokenizeNonLazyContinuation(effects, ok, nok) {
|
|
100751
|
+
const lineStart = (code) => {
|
|
100752
|
+
// `this` here refers to the micromark parser
|
|
100753
|
+
// since we are just passing functions as references and not actually calling them
|
|
100754
|
+
// micromarks's internal parser will call this automatically with appropriate arguments
|
|
100755
|
+
return this.parser.lazy[this.now().line] ? nok(code) : ok(code);
|
|
100756
|
+
};
|
|
100757
|
+
const start = (code) => {
|
|
100758
|
+
if (code === null) {
|
|
100759
|
+
return nok(code);
|
|
100760
|
+
}
|
|
100761
|
+
if (!markdownLineEnding(code)) {
|
|
100762
|
+
return nok(code);
|
|
100763
|
+
}
|
|
100764
|
+
effects.enter('magicBlockLineEnding');
|
|
100765
|
+
effects.consume(code);
|
|
100766
|
+
effects.exit('magicBlockLineEnding');
|
|
100767
|
+
return lineStart;
|
|
100768
|
+
};
|
|
100769
|
+
return start;
|
|
100770
|
+
}
|
|
100771
|
+
/**
|
|
100772
|
+
* Create a micromark extension for magic block syntax.
|
|
100773
|
+
*
|
|
100774
|
+
* This extension handles both single-line and multiline magic blocks:
|
|
100775
|
+
* - Flow construct (concrete): Handles block-level multiline magic blocks at document level
|
|
100776
|
+
* - Text construct: Handles inline magic blocks in lists, paragraphs, etc.
|
|
100777
|
+
*
|
|
100778
|
+
* The flow construct is marked as "concrete" which prevents it from being
|
|
100779
|
+
* interrupted by container markers (like `>` for blockquotes or `-` for lists).
|
|
100780
|
+
*/
|
|
100781
|
+
function magicBlock() {
|
|
100782
|
+
return {
|
|
100783
|
+
// Flow construct - handles block-level magic blocks at document root
|
|
100784
|
+
// Marked as concrete to prevent interruption by containers
|
|
100785
|
+
flow: {
|
|
100786
|
+
[codes.leftSquareBracket]: {
|
|
100787
|
+
name: 'magicBlock',
|
|
100788
|
+
concrete: true,
|
|
100789
|
+
tokenize: tokenizeMagicBlockFlow,
|
|
100790
|
+
},
|
|
100791
|
+
},
|
|
100792
|
+
// Text construct - handles magic blocks in inline contexts (lists, paragraphs)
|
|
100793
|
+
text: {
|
|
100794
|
+
[codes.leftSquareBracket]: {
|
|
100795
|
+
name: 'magicBlock',
|
|
100796
|
+
tokenize: tokenizeMagicBlockText,
|
|
100797
|
+
},
|
|
100798
|
+
},
|
|
100799
|
+
};
|
|
100800
|
+
}
|
|
100801
|
+
/**
|
|
100802
|
+
* Flow tokenizer for block-level magic blocks (multiline).
|
|
100803
|
+
* Uses the continuation checking pattern from code fences.
|
|
100804
|
+
*/
|
|
100805
|
+
function tokenizeMagicBlockFlow(effects, ok, nok) {
|
|
100806
|
+
// State for tracking JSON content
|
|
100807
|
+
const jsonState = { escapeNext: false, inString: false };
|
|
100808
|
+
const blockTypeRef = { value: '' };
|
|
100809
|
+
let seenOpenBrace = false;
|
|
100810
|
+
// Create shared parsers for opening marker and type capture
|
|
100811
|
+
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
100812
|
+
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
100813
|
+
return start;
|
|
100814
|
+
function start(code) {
|
|
100815
|
+
if (code !== codes.leftSquareBracket)
|
|
100816
|
+
return nok(code);
|
|
100817
|
+
effects.enter('magicBlock');
|
|
100818
|
+
effects.enter('magicBlockMarkerStart');
|
|
100819
|
+
effects.consume(code);
|
|
100820
|
+
return openingMarkerParser;
|
|
100821
|
+
}
|
|
100822
|
+
/**
|
|
100823
|
+
* State before data content - handles line endings or starts data capture.
|
|
100824
|
+
*/
|
|
100825
|
+
function beforeData(code) {
|
|
100826
|
+
// EOF - magic block must be closed
|
|
100827
|
+
if (code === null) {
|
|
100828
|
+
effects.exit('magicBlock');
|
|
100829
|
+
return nok(code);
|
|
100830
|
+
}
|
|
100831
|
+
// Line ending before any data - check continuation
|
|
100832
|
+
if (markdownLineEnding(code)) {
|
|
100833
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100834
|
+
}
|
|
100835
|
+
// Check for closing marker directly (without entering data)
|
|
100836
|
+
// This handles cases like [block:type]\n{}\n\n[/block] where there are
|
|
100837
|
+
// newlines after the data object
|
|
100838
|
+
if (code === codes.leftSquareBracket) {
|
|
100839
|
+
effects.enter('magicBlockMarkerEnd');
|
|
100840
|
+
effects.consume(code);
|
|
100841
|
+
return expectSlashFromContinuation;
|
|
100842
|
+
}
|
|
100843
|
+
// If we've already seen the opening brace, just continue capturing data
|
|
100844
|
+
if (seenOpenBrace) {
|
|
100845
|
+
effects.enter('magicBlockData');
|
|
100846
|
+
return captureData(code);
|
|
100847
|
+
}
|
|
100848
|
+
// Skip whitespace (spaces/tabs) before the data - stay in beforeData
|
|
100849
|
+
// Don't enter magicBlockData token yet until we confirm there's a '{'
|
|
100850
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
100851
|
+
return beforeDataWhitespace(code);
|
|
100852
|
+
}
|
|
100853
|
+
// Data must start with '{' for valid JSON
|
|
100854
|
+
if (code !== codes.leftCurlyBrace) {
|
|
100855
|
+
effects.exit('magicBlock');
|
|
100856
|
+
return nok(code);
|
|
100857
|
+
}
|
|
100858
|
+
// We have '{' - enter data token and start capturing
|
|
100859
|
+
seenOpenBrace = true;
|
|
100860
|
+
effects.enter('magicBlockData');
|
|
100861
|
+
return captureData(code);
|
|
100862
|
+
}
|
|
100863
|
+
/**
|
|
100864
|
+
* Consume whitespace before the data without creating a token.
|
|
100865
|
+
* Uses a temporary token to satisfy micromark's requirement.
|
|
100866
|
+
*/
|
|
100867
|
+
function beforeDataWhitespace(code) {
|
|
100868
|
+
if (code === null) {
|
|
100869
|
+
effects.exit('magicBlock');
|
|
100870
|
+
return nok(code);
|
|
100871
|
+
}
|
|
100872
|
+
if (markdownLineEnding(code)) {
|
|
100873
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100874
|
+
}
|
|
100875
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
100876
|
+
// We need to consume this but can't without a token - use magicBlockData
|
|
100877
|
+
// and track that we haven't seen '{' yet
|
|
100878
|
+
effects.enter('magicBlockData');
|
|
100879
|
+
effects.consume(code);
|
|
100880
|
+
return beforeDataWhitespaceContinue;
|
|
100881
|
+
}
|
|
100882
|
+
if (code === codes.leftCurlyBrace) {
|
|
100883
|
+
seenOpenBrace = true;
|
|
100884
|
+
effects.enter('magicBlockData');
|
|
100885
|
+
return captureData(code);
|
|
100886
|
+
}
|
|
100887
|
+
effects.exit('magicBlock');
|
|
100888
|
+
return nok(code);
|
|
100889
|
+
}
|
|
100890
|
+
/**
|
|
100891
|
+
* Continue consuming whitespace or validate the opening brace.
|
|
100892
|
+
*/
|
|
100893
|
+
function beforeDataWhitespaceContinue(code) {
|
|
100894
|
+
if (code === null) {
|
|
100895
|
+
effects.exit('magicBlockData');
|
|
100896
|
+
effects.exit('magicBlock');
|
|
100897
|
+
return nok(code);
|
|
100898
|
+
}
|
|
100899
|
+
if (markdownLineEnding(code)) {
|
|
100900
|
+
effects.exit('magicBlockData');
|
|
100901
|
+
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100902
|
+
}
|
|
100903
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
100904
|
+
effects.consume(code);
|
|
100905
|
+
return beforeDataWhitespaceContinue;
|
|
100906
|
+
}
|
|
100907
|
+
if (code === codes.leftCurlyBrace) {
|
|
100908
|
+
seenOpenBrace = true;
|
|
100909
|
+
return captureData(code);
|
|
100910
|
+
}
|
|
100911
|
+
effects.exit('magicBlockData');
|
|
100912
|
+
effects.exit('magicBlock');
|
|
100913
|
+
return nok(code);
|
|
100914
|
+
}
|
|
100915
|
+
/**
|
|
100916
|
+
* Continuation OK before we've entered data token.
|
|
100917
|
+
*/
|
|
100918
|
+
function continuationOkBeforeData(code) {
|
|
100919
|
+
effects.enter('magicBlockLineEnding');
|
|
100920
|
+
effects.consume(code);
|
|
100921
|
+
effects.exit('magicBlockLineEnding');
|
|
100922
|
+
return beforeData; // Stay in beforeData state - don't enter magicBlockData yet
|
|
100923
|
+
}
|
|
100924
|
+
function captureData(code) {
|
|
100925
|
+
// EOF - magic block must be closed
|
|
100926
|
+
if (code === null) {
|
|
100927
|
+
effects.exit('magicBlockData');
|
|
100928
|
+
effects.exit('magicBlock');
|
|
100929
|
+
return nok(code);
|
|
100930
|
+
}
|
|
100931
|
+
// At line ending, check if we can continue on the next line
|
|
100932
|
+
if (markdownLineEnding(code)) {
|
|
100933
|
+
effects.exit('magicBlockData');
|
|
100934
|
+
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
100935
|
+
}
|
|
100936
|
+
if (jsonState.escapeNext) {
|
|
100937
|
+
jsonState.escapeNext = false;
|
|
100938
|
+
effects.consume(code);
|
|
100939
|
+
return captureData;
|
|
100940
|
+
}
|
|
100941
|
+
if (jsonState.inString) {
|
|
100942
|
+
if (code === codes.backslash) {
|
|
100943
|
+
jsonState.escapeNext = true;
|
|
100944
|
+
effects.consume(code);
|
|
100945
|
+
return captureData;
|
|
100946
|
+
}
|
|
100947
|
+
if (code === codes.quotationMark) {
|
|
100948
|
+
jsonState.inString = false;
|
|
100949
|
+
}
|
|
100950
|
+
effects.consume(code);
|
|
100951
|
+
return captureData;
|
|
100952
|
+
}
|
|
100953
|
+
if (code === codes.quotationMark) {
|
|
100954
|
+
jsonState.inString = true;
|
|
100955
|
+
effects.consume(code);
|
|
100956
|
+
return captureData;
|
|
100957
|
+
}
|
|
100958
|
+
if (code === codes.leftSquareBracket) {
|
|
100959
|
+
effects.exit('magicBlockData');
|
|
100960
|
+
effects.enter('magicBlockMarkerEnd');
|
|
100961
|
+
effects.consume(code);
|
|
100962
|
+
return expectSlash;
|
|
100963
|
+
}
|
|
100964
|
+
effects.consume(code);
|
|
100965
|
+
return captureData;
|
|
100966
|
+
}
|
|
100967
|
+
/**
|
|
100968
|
+
* Called when non-lazy continuation check passes - we can continue parsing.
|
|
100969
|
+
*/
|
|
100970
|
+
function continuationOk(code) {
|
|
100971
|
+
// Consume the line ending
|
|
100972
|
+
effects.enter('magicBlockLineEnding');
|
|
100973
|
+
effects.consume(code);
|
|
100974
|
+
effects.exit('magicBlockLineEnding');
|
|
100975
|
+
return continuationStart;
|
|
100976
|
+
}
|
|
100977
|
+
/**
|
|
100978
|
+
* Start of continuation line - check for more line endings, closing marker, or start capturing data.
|
|
100979
|
+
*/
|
|
100980
|
+
function continuationStart(code) {
|
|
100981
|
+
// Handle consecutive line endings
|
|
100982
|
+
if (code === null) {
|
|
100983
|
+
effects.exit('magicBlock');
|
|
100984
|
+
return nok(code);
|
|
100985
|
+
}
|
|
100986
|
+
if (markdownLineEnding(code)) {
|
|
100987
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
100988
|
+
}
|
|
100989
|
+
// Check if this is the start of the closing marker [/block]
|
|
100990
|
+
// If so, handle it directly without entering magicBlockData
|
|
100991
|
+
if (code === codes.leftSquareBracket) {
|
|
100992
|
+
effects.enter('magicBlockMarkerEnd');
|
|
100993
|
+
effects.consume(code);
|
|
100994
|
+
return expectSlashFromContinuation;
|
|
100995
|
+
}
|
|
100996
|
+
effects.enter('magicBlockData');
|
|
100997
|
+
return captureData(code);
|
|
100998
|
+
}
|
|
100999
|
+
/**
|
|
101000
|
+
* Check for closing marker slash when coming from continuation.
|
|
101001
|
+
* If not a closing marker, create an empty data token and continue.
|
|
101002
|
+
*/
|
|
101003
|
+
function expectSlashFromContinuation(code) {
|
|
101004
|
+
if (code === null) {
|
|
101005
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101006
|
+
effects.exit('magicBlock');
|
|
101007
|
+
return nok(code);
|
|
101008
|
+
}
|
|
101009
|
+
if (markdownLineEnding(code)) {
|
|
101010
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101011
|
+
return effects.check(syntax_nonLazyContinuation, continuationOkBeforeData, after)(code);
|
|
101012
|
+
}
|
|
101013
|
+
if (code === codes.slash) {
|
|
101014
|
+
effects.consume(code);
|
|
101015
|
+
return expectClosingB;
|
|
101016
|
+
}
|
|
101017
|
+
// Not a closing marker - this is data content
|
|
101018
|
+
// Exit marker and enter data
|
|
101019
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101020
|
+
effects.enter('magicBlockData');
|
|
101021
|
+
// The [ was consumed by the marker, so we need to conceptually "have it" in our data
|
|
101022
|
+
// But since we already consumed it into the marker, we need a different approach
|
|
101023
|
+
// Re-classify: consume this character as data and continue
|
|
101024
|
+
if (code === codes.quotationMark)
|
|
101025
|
+
jsonState.inString = true;
|
|
101026
|
+
effects.consume(code);
|
|
101027
|
+
return captureData;
|
|
101028
|
+
}
|
|
101029
|
+
function expectSlash(code) {
|
|
101030
|
+
if (code === null) {
|
|
101031
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101032
|
+
effects.exit('magicBlock');
|
|
101033
|
+
return nok(code);
|
|
101034
|
+
}
|
|
101035
|
+
// At line ending during marker parsing
|
|
101036
|
+
if (markdownLineEnding(code)) {
|
|
101037
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101038
|
+
return effects.check(syntax_nonLazyContinuation, continuationOk, after)(code);
|
|
101039
|
+
}
|
|
101040
|
+
if (code !== codes.slash) {
|
|
101041
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101042
|
+
effects.enter('magicBlockData');
|
|
101043
|
+
if (code === codes.quotationMark)
|
|
101044
|
+
jsonState.inString = true;
|
|
101045
|
+
effects.consume(code);
|
|
101046
|
+
return captureData;
|
|
101047
|
+
}
|
|
101048
|
+
effects.consume(code);
|
|
101049
|
+
return expectClosingB;
|
|
101050
|
+
}
|
|
101051
|
+
function expectClosingB(code) {
|
|
101052
|
+
if (code === null) {
|
|
101053
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101054
|
+
effects.exit('magicBlock');
|
|
101055
|
+
return nok(code);
|
|
101056
|
+
}
|
|
101057
|
+
if (code !== codes.lowercaseB) {
|
|
101058
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101059
|
+
effects.enter('magicBlockData');
|
|
101060
|
+
if (code === codes.quotationMark)
|
|
101061
|
+
jsonState.inString = true;
|
|
101062
|
+
effects.consume(code);
|
|
101063
|
+
return captureData;
|
|
101064
|
+
}
|
|
101065
|
+
effects.consume(code);
|
|
101066
|
+
return expectClosingL;
|
|
101067
|
+
}
|
|
101068
|
+
function expectClosingL(code) {
|
|
101069
|
+
if (code === null) {
|
|
101070
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101071
|
+
effects.exit('magicBlock');
|
|
101072
|
+
return nok(code);
|
|
101073
|
+
}
|
|
101074
|
+
if (code !== codes.lowercaseL) {
|
|
101075
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101076
|
+
effects.enter('magicBlockData');
|
|
101077
|
+
if (code === codes.quotationMark)
|
|
101078
|
+
jsonState.inString = true;
|
|
101079
|
+
effects.consume(code);
|
|
101080
|
+
return captureData;
|
|
101081
|
+
}
|
|
101082
|
+
effects.consume(code);
|
|
101083
|
+
return expectClosingO;
|
|
101084
|
+
}
|
|
101085
|
+
function expectClosingO(code) {
|
|
101086
|
+
if (code === null) {
|
|
101087
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101088
|
+
effects.exit('magicBlock');
|
|
101089
|
+
return nok(code);
|
|
101090
|
+
}
|
|
101091
|
+
if (code !== codes.lowercaseO) {
|
|
101092
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101093
|
+
effects.enter('magicBlockData');
|
|
101094
|
+
if (code === codes.quotationMark)
|
|
101095
|
+
jsonState.inString = true;
|
|
101096
|
+
effects.consume(code);
|
|
101097
|
+
return captureData;
|
|
101098
|
+
}
|
|
101099
|
+
effects.consume(code);
|
|
101100
|
+
return expectClosingC;
|
|
101101
|
+
}
|
|
101102
|
+
function expectClosingC(code) {
|
|
101103
|
+
if (code === null) {
|
|
101104
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101105
|
+
effects.exit('magicBlock');
|
|
101106
|
+
return nok(code);
|
|
101107
|
+
}
|
|
101108
|
+
if (code !== codes.lowercaseC) {
|
|
101109
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101110
|
+
effects.enter('magicBlockData');
|
|
101111
|
+
if (code === codes.quotationMark)
|
|
101112
|
+
jsonState.inString = true;
|
|
101113
|
+
effects.consume(code);
|
|
101114
|
+
return captureData;
|
|
101115
|
+
}
|
|
101116
|
+
effects.consume(code);
|
|
101117
|
+
return expectClosingK;
|
|
101118
|
+
}
|
|
101119
|
+
function expectClosingK(code) {
|
|
101120
|
+
if (code === null) {
|
|
101121
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101122
|
+
effects.exit('magicBlock');
|
|
101123
|
+
return nok(code);
|
|
101124
|
+
}
|
|
101125
|
+
if (code !== codes.lowercaseK) {
|
|
101126
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101127
|
+
effects.enter('magicBlockData');
|
|
101128
|
+
if (code === codes.quotationMark)
|
|
101129
|
+
jsonState.inString = true;
|
|
101130
|
+
effects.consume(code);
|
|
101131
|
+
return captureData;
|
|
101132
|
+
}
|
|
101133
|
+
effects.consume(code);
|
|
101134
|
+
return expectClosingBracket;
|
|
101135
|
+
}
|
|
101136
|
+
function expectClosingBracket(code) {
|
|
101137
|
+
if (code === null) {
|
|
101138
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101139
|
+
effects.exit('magicBlock');
|
|
101140
|
+
return nok(code);
|
|
101141
|
+
}
|
|
101142
|
+
if (code !== codes.rightSquareBracket) {
|
|
101143
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101144
|
+
effects.enter('magicBlockData');
|
|
101145
|
+
if (code === codes.quotationMark)
|
|
101146
|
+
jsonState.inString = true;
|
|
101147
|
+
effects.consume(code);
|
|
101148
|
+
return captureData;
|
|
101149
|
+
}
|
|
101150
|
+
effects.consume(code);
|
|
101151
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101152
|
+
// Check for trailing whitespace on the same line
|
|
101153
|
+
return consumeTrailing;
|
|
101154
|
+
}
|
|
101155
|
+
/**
|
|
101156
|
+
* Consume trailing whitespace (spaces/tabs) on the same line after [/block].
|
|
101157
|
+
* For concrete flow constructs, we must end at eol/eof or fail.
|
|
101158
|
+
* Trailing whitespace is consumed; other content causes nok (text tokenizer handles it).
|
|
101159
|
+
*/
|
|
101160
|
+
function consumeTrailing(code) {
|
|
101161
|
+
// End of file - done
|
|
101162
|
+
if (code === null) {
|
|
101163
|
+
effects.exit('magicBlock');
|
|
101164
|
+
return ok(code);
|
|
101165
|
+
}
|
|
101166
|
+
// Line ending - done
|
|
101167
|
+
if (markdownLineEnding(code)) {
|
|
101168
|
+
effects.exit('magicBlock');
|
|
101169
|
+
return ok(code);
|
|
101170
|
+
}
|
|
101171
|
+
// Space or tab - consume as trailing whitespace
|
|
101172
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101173
|
+
effects.enter('magicBlockTrailing');
|
|
101174
|
+
effects.consume(code);
|
|
101175
|
+
return consumeTrailingContinue;
|
|
101176
|
+
}
|
|
101177
|
+
// Any other character - fail flow tokenizer, let text tokenizer handle it
|
|
101178
|
+
effects.exit('magicBlock');
|
|
101179
|
+
return nok(code);
|
|
101180
|
+
}
|
|
101181
|
+
/**
|
|
101182
|
+
* Continue consuming trailing whitespace.
|
|
101183
|
+
*/
|
|
101184
|
+
function consumeTrailingContinue(code) {
|
|
101185
|
+
// End of file - done
|
|
101186
|
+
if (code === null) {
|
|
101187
|
+
effects.exit('magicBlockTrailing');
|
|
101188
|
+
effects.exit('magicBlock');
|
|
101189
|
+
return ok(code);
|
|
101190
|
+
}
|
|
101191
|
+
// Line ending - done
|
|
101192
|
+
if (markdownLineEnding(code)) {
|
|
101193
|
+
effects.exit('magicBlockTrailing');
|
|
101194
|
+
effects.exit('magicBlock');
|
|
101195
|
+
return ok(code);
|
|
101196
|
+
}
|
|
101197
|
+
// More space or tab - keep consuming
|
|
101198
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101199
|
+
effects.consume(code);
|
|
101200
|
+
return consumeTrailingContinue;
|
|
101201
|
+
}
|
|
101202
|
+
// Non-whitespace after whitespace - fail flow tokenizer
|
|
101203
|
+
effects.exit('magicBlockTrailing');
|
|
101204
|
+
effects.exit('magicBlock');
|
|
101205
|
+
return nok(code);
|
|
101206
|
+
}
|
|
101207
|
+
/**
|
|
101208
|
+
* Called when we can't continue (lazy line or EOF) - exit the construct.
|
|
101209
|
+
*/
|
|
101210
|
+
function after(code) {
|
|
101211
|
+
effects.exit('magicBlock');
|
|
101212
|
+
return nok(code);
|
|
101213
|
+
}
|
|
101214
|
+
}
|
|
101215
|
+
/**
|
|
101216
|
+
* Text tokenizer for single-line magic blocks only.
|
|
101217
|
+
* Used in inline contexts like list items and paragraphs.
|
|
101218
|
+
* Multiline blocks are handled by the flow tokenizer.
|
|
101219
|
+
*/
|
|
101220
|
+
function tokenizeMagicBlockText(effects, ok, nok) {
|
|
101221
|
+
// State for tracking JSON content
|
|
101222
|
+
const jsonState = { escapeNext: false, inString: false };
|
|
101223
|
+
const blockTypeRef = { value: '' };
|
|
101224
|
+
let seenOpenBrace = false;
|
|
101225
|
+
// Create shared parsers for opening marker and type capture
|
|
101226
|
+
const typeParser = createTypeCaptureParser(effects, nok, beforeData, blockTypeRef);
|
|
101227
|
+
const openingMarkerParser = createOpeningMarkerParser(effects, nok, typeParser.first);
|
|
101228
|
+
// Success handler for closing marker - exits tokens and returns ok
|
|
101229
|
+
const closingSuccess = (code) => {
|
|
101230
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101231
|
+
effects.exit('magicBlock');
|
|
101232
|
+
return ok(code);
|
|
101233
|
+
};
|
|
101234
|
+
// Mismatch handler - falls back to data capture
|
|
101235
|
+
const closingMismatch = (code) => {
|
|
101236
|
+
effects.exit('magicBlockMarkerEnd');
|
|
101237
|
+
effects.enter('magicBlockData');
|
|
101238
|
+
if (code === codes.quotationMark)
|
|
101239
|
+
jsonState.inString = true;
|
|
101240
|
+
effects.consume(code);
|
|
101241
|
+
return captureData;
|
|
101242
|
+
};
|
|
101243
|
+
// EOF handler
|
|
101244
|
+
const closingEof = (_code) => nok(_code);
|
|
101245
|
+
// Create closing marker parsers
|
|
101246
|
+
const closingFromBeforeData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
101247
|
+
const closingFromData = createClosingMarkerParser(effects, closingSuccess, closingMismatch, closingEof, jsonState);
|
|
101248
|
+
return start;
|
|
101249
|
+
function start(code) {
|
|
101250
|
+
if (code !== codes.leftSquareBracket)
|
|
101251
|
+
return nok(code);
|
|
101252
|
+
effects.enter('magicBlock');
|
|
101253
|
+
effects.enter('magicBlockMarkerStart');
|
|
101254
|
+
effects.consume(code);
|
|
101255
|
+
return openingMarkerParser;
|
|
101256
|
+
}
|
|
101257
|
+
/**
|
|
101258
|
+
* State before data content - handles line endings before entering data token.
|
|
101259
|
+
* Whitespace before '{' is allowed.
|
|
101260
|
+
*/
|
|
101261
|
+
function beforeData(code) {
|
|
101262
|
+
// Fail on EOF - magic block must be closed
|
|
101263
|
+
if (code === null) {
|
|
101264
|
+
return nok(code);
|
|
101265
|
+
}
|
|
101266
|
+
// Handle line endings before any data - consume them without entering data token
|
|
101267
|
+
if (markdownLineEnding(code)) {
|
|
101268
|
+
effects.enter('magicBlockLineEnding');
|
|
101269
|
+
effects.consume(code);
|
|
101270
|
+
effects.exit('magicBlockLineEnding');
|
|
101271
|
+
return beforeData;
|
|
101272
|
+
}
|
|
101273
|
+
// Check for closing marker directly (without entering data)
|
|
101274
|
+
if (code === codes.leftSquareBracket) {
|
|
101275
|
+
effects.enter('magicBlockMarkerEnd');
|
|
101276
|
+
effects.consume(code);
|
|
101277
|
+
return closingFromBeforeData.expectSlash;
|
|
101278
|
+
}
|
|
101279
|
+
// If we've already seen the opening brace, just continue capturing data
|
|
101280
|
+
if (seenOpenBrace) {
|
|
101281
|
+
effects.enter('magicBlockData');
|
|
101282
|
+
return captureData(code);
|
|
101283
|
+
}
|
|
101284
|
+
// Skip whitespace (spaces/tabs) before the data
|
|
101285
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101286
|
+
return beforeDataWhitespace(code);
|
|
101287
|
+
}
|
|
101288
|
+
// Data must start with '{' for valid JSON
|
|
101289
|
+
if (code !== codes.leftCurlyBrace) {
|
|
101290
|
+
return nok(code);
|
|
101291
|
+
}
|
|
101292
|
+
// We have '{' - enter data token and start capturing
|
|
101293
|
+
seenOpenBrace = true;
|
|
101294
|
+
effects.enter('magicBlockData');
|
|
101295
|
+
return captureData(code);
|
|
101296
|
+
}
|
|
101297
|
+
/**
|
|
101298
|
+
* Consume whitespace before the data.
|
|
101299
|
+
*/
|
|
101300
|
+
function beforeDataWhitespace(code) {
|
|
101301
|
+
if (code === null) {
|
|
101302
|
+
return nok(code);
|
|
101303
|
+
}
|
|
101304
|
+
if (markdownLineEnding(code)) {
|
|
101305
|
+
effects.enter('magicBlockLineEnding');
|
|
101306
|
+
effects.consume(code);
|
|
101307
|
+
effects.exit('magicBlockLineEnding');
|
|
101308
|
+
return beforeData;
|
|
101309
|
+
}
|
|
101310
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101311
|
+
effects.enter('magicBlockData');
|
|
101312
|
+
effects.consume(code);
|
|
101313
|
+
return beforeDataWhitespaceContinue;
|
|
101314
|
+
}
|
|
101315
|
+
if (code === codes.leftCurlyBrace) {
|
|
101316
|
+
seenOpenBrace = true;
|
|
101317
|
+
effects.enter('magicBlockData');
|
|
101318
|
+
return captureData(code);
|
|
101319
|
+
}
|
|
101320
|
+
return nok(code);
|
|
101321
|
+
}
|
|
101322
|
+
/**
|
|
101323
|
+
* Continue consuming whitespace or validate the opening brace.
|
|
101324
|
+
*/
|
|
101325
|
+
function beforeDataWhitespaceContinue(code) {
|
|
101326
|
+
if (code === null) {
|
|
101327
|
+
effects.exit('magicBlockData');
|
|
101328
|
+
return nok(code);
|
|
101329
|
+
}
|
|
101330
|
+
if (markdownLineEnding(code)) {
|
|
101331
|
+
effects.exit('magicBlockData');
|
|
101332
|
+
effects.enter('magicBlockLineEnding');
|
|
101333
|
+
effects.consume(code);
|
|
101334
|
+
effects.exit('magicBlockLineEnding');
|
|
101335
|
+
return beforeData;
|
|
101336
|
+
}
|
|
101337
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
101338
|
+
effects.consume(code);
|
|
101339
|
+
return beforeDataWhitespaceContinue;
|
|
101340
|
+
}
|
|
101341
|
+
if (code === codes.leftCurlyBrace) {
|
|
101342
|
+
seenOpenBrace = true;
|
|
101343
|
+
return captureData(code);
|
|
101344
|
+
}
|
|
101345
|
+
effects.exit('magicBlockData');
|
|
101346
|
+
return nok(code);
|
|
101347
|
+
}
|
|
101348
|
+
function captureData(code) {
|
|
101349
|
+
// Fail on EOF - magic block must be closed
|
|
101350
|
+
if (code === null) {
|
|
101351
|
+
effects.exit('magicBlockData');
|
|
101352
|
+
return nok(code);
|
|
101353
|
+
}
|
|
101354
|
+
// Handle multiline magic blocks within text/paragraphs
|
|
101355
|
+
// Exit data, consume line ending with proper token, then re-enter data
|
|
101356
|
+
if (markdownLineEnding(code)) {
|
|
101357
|
+
effects.exit('magicBlockData');
|
|
101358
|
+
effects.enter('magicBlockLineEnding');
|
|
101359
|
+
effects.consume(code);
|
|
101360
|
+
effects.exit('magicBlockLineEnding');
|
|
101361
|
+
return beforeData; // Go back to beforeData to handle potential empty lines
|
|
101362
|
+
}
|
|
101363
|
+
if (jsonState.escapeNext) {
|
|
101364
|
+
jsonState.escapeNext = false;
|
|
101365
|
+
effects.consume(code);
|
|
101366
|
+
return captureData;
|
|
101367
|
+
}
|
|
101368
|
+
if (jsonState.inString) {
|
|
101369
|
+
if (code === codes.backslash) {
|
|
101370
|
+
jsonState.escapeNext = true;
|
|
101371
|
+
effects.consume(code);
|
|
101372
|
+
return captureData;
|
|
101373
|
+
}
|
|
101374
|
+
if (code === codes.quotationMark) {
|
|
101375
|
+
jsonState.inString = false;
|
|
101376
|
+
}
|
|
101377
|
+
effects.consume(code);
|
|
101378
|
+
return captureData;
|
|
101379
|
+
}
|
|
101380
|
+
if (code === codes.quotationMark) {
|
|
101381
|
+
jsonState.inString = true;
|
|
101382
|
+
effects.consume(code);
|
|
101383
|
+
return captureData;
|
|
101384
|
+
}
|
|
101385
|
+
if (code === codes.leftSquareBracket) {
|
|
101386
|
+
effects.exit('magicBlockData');
|
|
101387
|
+
effects.enter('magicBlockMarkerEnd');
|
|
101388
|
+
effects.consume(code);
|
|
101389
|
+
return closingFromData.expectSlash;
|
|
101390
|
+
}
|
|
101391
|
+
effects.consume(code);
|
|
101392
|
+
return captureData;
|
|
101393
|
+
}
|
|
101394
|
+
}
|
|
101395
|
+
/* harmony default export */ const syntax = ((/* unused pure expression or super */ null && (magicBlock)));
|
|
101396
|
+
|
|
101397
|
+
;// ./lib/micromark/magic-block/index.ts
|
|
101398
|
+
/**
|
|
101399
|
+
* Micromark extension for magic block syntax.
|
|
101400
|
+
*
|
|
101401
|
+
* Usage:
|
|
101402
|
+
* ```ts
|
|
101403
|
+
* import { magicBlock } from './lib/micromark/magic-block';
|
|
101404
|
+
*
|
|
101405
|
+
* const processor = unified()
|
|
101406
|
+
* .data('micromarkExtensions', [magicBlock()])
|
|
101407
|
+
* ```
|
|
101408
|
+
*/
|
|
101409
|
+
|
|
101410
|
+
|
|
101411
|
+
;// ./lib/micromark/mdx-component/syntax.ts
|
|
101412
|
+
|
|
101413
|
+
|
|
101414
|
+
|
|
101415
|
+
|
|
101416
|
+
|
|
101417
|
+
// Raw tags (type-1: pre/script/style/textarea) and block tags (type-6: div,
|
|
101418
|
+
// section, …) always start a block, so they stay flow even with trailing
|
|
101419
|
+
// content. Other lowercase tags (i, span, …) follow the type-7 rule and only
|
|
101420
|
+
// stay flow when nothing trails the close tag.
|
|
101421
|
+
const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
|
|
101422
|
+
// Lowercase type-6 block tags claimable in flow even without a `{…}` attribute, so
|
|
101423
|
+
// blank lines between nested JSX siblings don't fragment the block. Excludes table
|
|
101424
|
+
// tags (mdxishTables owns their blank lines) and voids (never close).
|
|
101425
|
+
const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
|
|
101426
|
+
const mdx_component_syntax_nonLazyContinuationStart = {
|
|
101427
|
+
tokenize: mdx_component_syntax_tokenizeNonLazyContinuationStart,
|
|
101428
|
+
partial: true,
|
|
101429
|
+
};
|
|
101430
|
+
// Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
|
|
101431
|
+
// that merely starts with a tag? Run via `effects.check` so it never consumes.
|
|
101432
|
+
const markupOnlyContinuation = {
|
|
101433
|
+
tokenize: tokenizeMarkupOnlyContinuation,
|
|
101434
|
+
partial: true,
|
|
101435
|
+
};
|
|
101436
|
+
function resolveToMdxComponent(events) {
|
|
101437
|
+
let index = events.length;
|
|
101438
|
+
while (index > 0) {
|
|
101439
|
+
index -= 1;
|
|
101440
|
+
if (events[index][0] === 'enter' && events[index][1].type === 'mdxComponent') {
|
|
101441
|
+
break;
|
|
101442
|
+
}
|
|
101443
|
+
}
|
|
101444
|
+
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
101445
|
+
events[index][1].start = events[index - 2][1].start;
|
|
101446
|
+
events[index + 1][1].start = events[index - 2][1].start;
|
|
101447
|
+
events.splice(index - 2, 2);
|
|
101448
|
+
}
|
|
101449
|
+
return events;
|
|
101450
|
+
}
|
|
101451
|
+
const mdxComponentFlowConstruct = {
|
|
101452
|
+
name: 'mdxComponent',
|
|
101453
|
+
tokenize: createTokenize('flow'),
|
|
101454
|
+
resolveTo: resolveToMdxComponent,
|
|
101455
|
+
concrete: true,
|
|
101192
101456
|
};
|
|
101193
101457
|
const mdxComponentTextConstruct = {
|
|
101194
101458
|
name: 'mdxComponentText',
|
|
@@ -101526,7 +101790,7 @@ function createTokenize(mode) {
|
|
|
101526
101790
|
}
|
|
101527
101791
|
// Continuation for multi-line opening tags
|
|
101528
101792
|
function openTagContinuationStart(code) {
|
|
101529
|
-
return effects.check(
|
|
101793
|
+
return effects.check(mdx_component_syntax_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
|
|
101530
101794
|
}
|
|
101531
101795
|
function openTagContinuationNonLazy(code) {
|
|
101532
101796
|
sawLineEnding = true;
|
|
@@ -101651,7 +101915,7 @@ function createTokenize(mode) {
|
|
|
101651
101915
|
return inFencedCode;
|
|
101652
101916
|
}
|
|
101653
101917
|
function fencedCodeContinuationStart(code) {
|
|
101654
|
-
return effects.check(
|
|
101918
|
+
return effects.check(mdx_component_syntax_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
|
|
101655
101919
|
}
|
|
101656
101920
|
function fencedCodeContinuationNonLazy(code) {
|
|
101657
101921
|
sawLineEnding = true;
|
|
@@ -101666,6 +101930,16 @@ function createTokenize(mode) {
|
|
|
101666
101930
|
}
|
|
101667
101931
|
effects.enter('mdxComponentData');
|
|
101668
101932
|
fenceCloseLength = 0;
|
|
101933
|
+
return fencedCodeMaybeClose(code);
|
|
101934
|
+
}
|
|
101935
|
+
// Skip leading indentation before the closing-fence check: an indented fence
|
|
101936
|
+
// (the norm in a component body) closes on an equally-indented line, else the
|
|
101937
|
+
// closer is never matched and scanning runs to EOF (CX-3704).
|
|
101938
|
+
function fencedCodeMaybeClose(code) {
|
|
101939
|
+
if (markdownSpace(code)) {
|
|
101940
|
+
effects.consume(code);
|
|
101941
|
+
return fencedCodeMaybeClose;
|
|
101942
|
+
}
|
|
101669
101943
|
// Check for closing fence
|
|
101670
101944
|
if (code === fenceChar) {
|
|
101671
101945
|
fenceCloseLength = 1;
|
|
@@ -101849,7 +102123,7 @@ function createTokenize(mode) {
|
|
|
101849
102123
|
}
|
|
101850
102124
|
// ── Body continuation (line endings) ───────────────────────────────────
|
|
101851
102125
|
function bodyContinuationStart(code) {
|
|
101852
|
-
return effects.check(
|
|
102126
|
+
return effects.check(mdx_component_syntax_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
|
|
101853
102127
|
}
|
|
101854
102128
|
function bodyContinuationNonLazy(code) {
|
|
101855
102129
|
sawLineEnding = true;
|
|
@@ -101881,6 +102155,13 @@ function createTokenize(mode) {
|
|
|
101881
102155
|
}
|
|
101882
102156
|
// Dispatch a non-blank continuation line: fenced code at line start, else body.
|
|
101883
102157
|
function bodyLineStart(code) {
|
|
102158
|
+
// Skip leading indentation while staying "at line start" so an indented
|
|
102159
|
+
// fence is still recognized. Otherwise the first space clears `atLineStart`
|
|
102160
|
+
// and its content — including any unbalanced `{` — stays live text (CX-3704).
|
|
102161
|
+
if (atLineStart && markdownSpace(code)) {
|
|
102162
|
+
effects.consume(code);
|
|
102163
|
+
return bodyLineStart;
|
|
102164
|
+
}
|
|
101884
102165
|
if (atLineStart && code === codes.tilde)
|
|
101885
102166
|
return bodyAfterLineStart(code);
|
|
101886
102167
|
if (atLineStart && code === codes.graveAccent) {
|
|
@@ -101931,7 +102212,7 @@ function createTokenize(mode) {
|
|
|
101931
102212
|
}
|
|
101932
102213
|
};
|
|
101933
102214
|
}
|
|
101934
|
-
function
|
|
102215
|
+
function mdx_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
101935
102216
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
101936
102217
|
const self = this;
|
|
101937
102218
|
return start;
|
|
@@ -102039,9 +102320,20 @@ function mdxComponent() {
|
|
|
102039
102320
|
|
|
102040
102321
|
|
|
102041
102322
|
|
|
102323
|
+
|
|
102324
|
+
|
|
102325
|
+
|
|
102326
|
+
|
|
102327
|
+
|
|
102328
|
+
|
|
102042
102329
|
const buildInlineMdProcessor = (safeMode) => {
|
|
102043
|
-
|
|
102330
|
+
// `jsxTable` must be present so a `<Table>`/`<table>` nested in a component
|
|
102331
|
+
// body (e.g. a `<Callout>`) is captured as one html node. Without it, blank
|
|
102332
|
+
// lines between rows let CommonMark HTML block type 6 fragment the table and
|
|
102333
|
+
// its rows spill out as text / indented code blocks (CX-3705).
|
|
102334
|
+
const micromarkExts = [jsxTable(), mdxComponent(), syntax_gemoji(), legacyVariable(), magicBlock()];
|
|
102044
102335
|
const fromMarkdownExts = [
|
|
102336
|
+
jsxTableFromMarkdown(),
|
|
102045
102337
|
mdxComponentFromMarkdown(),
|
|
102046
102338
|
gemojiFromMarkdown(),
|
|
102047
102339
|
legacyVariableFromMarkdown(),
|
|
@@ -102101,6 +102393,65 @@ const toMdxJsxTextElement = (name, attributes, children, position) => ({
|
|
|
102101
102393
|
children,
|
|
102102
102394
|
...(position ? { position } : {}),
|
|
102103
102395
|
});
|
|
102396
|
+
// Raw-body tags (pre/script/style/textarea) must stay byte-exact; table
|
|
102397
|
+
// structure (`table` + `tableTags`) is owned by `mdxishTables` and figures by
|
|
102398
|
+
// `mdxishJsxToMdast`, both of which run later on raw html nodes.
|
|
102399
|
+
const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table', 'figure', 'figcaption']);
|
|
102400
|
+
const NESTED_TABLE_RE = /<table[\s>]/i;
|
|
102401
|
+
const isMarkdownPromotableHtmlTag = (tag) => !NON_PROMOTABLE_PLAIN_TAGS.has(tag);
|
|
102402
|
+
// Expression nodes count as plain so `<div>{1+1}</div>` keeps its current
|
|
102403
|
+
// literal-brace behavior; variables/glossary already resolve inside raw html.
|
|
102404
|
+
const PLAIN_CONTENT_TYPES = new Set([
|
|
102405
|
+
'paragraph',
|
|
102406
|
+
'text',
|
|
102407
|
+
'html',
|
|
102408
|
+
'mdxTextExpression',
|
|
102409
|
+
'mdxFlowExpression',
|
|
102410
|
+
NodeTypes.variable,
|
|
102411
|
+
NodeTypes.glossary,
|
|
102412
|
+
]);
|
|
102413
|
+
// Promoting plain HTML is only worth bypassing rehype-raw's parse5 pass when
|
|
102414
|
+
// the body parses into an actual markdown construct.
|
|
102415
|
+
const containsMarkdownConstruct = (nodes) => nodes.some(node => !PLAIN_CONTENT_TYPES.has(node.type) ||
|
|
102416
|
+
('children' in node && Array.isArray(node.children) && containsMarkdownConstruct(node.children)));
|
|
102417
|
+
/**
|
|
102418
|
+
* Index of the `</tag>` that balances the already-consumed opening tag (the
|
|
102419
|
+
* caller starts us one level deep). `lastIndexOf` mis-slices sibling same-tag
|
|
102420
|
+
* pairs like `<div>**a**</div><div>**b**</div>`, so we depth-match instead —
|
|
102421
|
+
* delegating to `walkTags` (htmlparser2) so quoted attributes (`title="</div>"`),
|
|
102422
|
+
* code spans, and legacy `<<VARIABLE>>` are handled for free. Returns -1 when
|
|
102423
|
+
* the wrapper is left open.
|
|
102424
|
+
*/
|
|
102425
|
+
function findBalancedClosingTagIndex(content, tag) {
|
|
102426
|
+
const target = tag.toLowerCase();
|
|
102427
|
+
const canonicalCloserLength = tag.length + 3; // `</tag>`
|
|
102428
|
+
// The caller already stripped the opening tag, so re-attach one: htmlparser2
|
|
102429
|
+
// drops an unmatched closer, and we want it balanced. Offsets shift by the
|
|
102430
|
+
// prefix length.
|
|
102431
|
+
const prefix = `<${tag}>`;
|
|
102432
|
+
let depth = 0;
|
|
102433
|
+
let closeIndex = -1;
|
|
102434
|
+
walkTags(prefix + content, {
|
|
102435
|
+
onOpen: ({ name, isSelfClosing, isStrayCloser }) => {
|
|
102436
|
+
if (closeIndex >= 0 || isSelfClosing || isStrayCloser)
|
|
102437
|
+
return;
|
|
102438
|
+
if (name.toLowerCase() === target)
|
|
102439
|
+
depth += 1;
|
|
102440
|
+
},
|
|
102441
|
+
onClose: ({ name, start, end, implicit }) => {
|
|
102442
|
+
if (closeIndex >= 0 || implicit || name.toLowerCase() !== target)
|
|
102443
|
+
return;
|
|
102444
|
+
// Only canonical `</tag>` closers — the caller slices by that length, so a
|
|
102445
|
+
// whitespaced `</tag >` would misalign; leaving it unmatched keeps it raw.
|
|
102446
|
+
if (end - start !== canonicalCloserLength)
|
|
102447
|
+
return;
|
|
102448
|
+
depth -= 1;
|
|
102449
|
+
if (depth === 0)
|
|
102450
|
+
closeIndex = start - prefix.length;
|
|
102451
|
+
},
|
|
102452
|
+
});
|
|
102453
|
+
return closeIndex;
|
|
102454
|
+
}
|
|
102104
102455
|
|
|
102105
102456
|
;// ./processor/transform/mdxish/components/inline-html.ts
|
|
102106
102457
|
|
|
@@ -102232,10 +102583,36 @@ const mdxishInlineMdxComponents = () => tree => {
|
|
|
102232
102583
|
};
|
|
102233
102584
|
/* harmony default export */ const inline_mdx_blocks = (mdxishInlineMdxComponents);
|
|
102234
102585
|
|
|
102586
|
+
;// ./processor/transform/mdxish/indentation.ts
|
|
102587
|
+
/**
|
|
102588
|
+
* CommonMark indentation helpers, shared by the mdxish preprocessors so tab- and
|
|
102589
|
+
* space-indented content is measured (and sliced) on one scale.
|
|
102590
|
+
*
|
|
102591
|
+
* CommonMark's indented-code threshold is 4 *columns*, and a tab is a 4-column tab
|
|
102592
|
+
* stop — not a fixed 4 characters. Counting characters (tab = 1) under-measures
|
|
102593
|
+
* tab-indented lines, letting them slip past the 4-column gate so their content
|
|
102594
|
+
* fragments into code blocks. Keeping one implementation here stops the two callers
|
|
102595
|
+
* from drifting on what "4 columns" means.
|
|
102596
|
+
*/
|
|
102597
|
+
/** The run of leading spaces/tabs on a line. */
|
|
102598
|
+
const leadingIndent = (line) => line.match(/^[ \t]*/)?.[0] ?? '';
|
|
102599
|
+
/**
|
|
102600
|
+
* Expand a leading-whitespace run to spaces using CommonMark's 4-column tab stops,
|
|
102601
|
+
* so a run of mixed tabs/spaces can be measured by length and sliced by column.
|
|
102602
|
+
*/
|
|
102603
|
+
function expandIndentToColumns(indent) {
|
|
102604
|
+
return indent
|
|
102605
|
+
.split('')
|
|
102606
|
+
.reduce((columns, char) => columns + (char === '\t' ? ' '.repeat(4 - (columns.length % 4)) : ' '), '');
|
|
102607
|
+
}
|
|
102608
|
+
/** Indentation width of a line in CommonMark columns (a tab advances to the next 4-column stop). */
|
|
102609
|
+
const indentWidth = (line) => expandIndentToColumns(leadingIndent(line)).length;
|
|
102610
|
+
|
|
102235
102611
|
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
102236
102612
|
|
|
102237
102613
|
|
|
102238
102614
|
|
|
102615
|
+
|
|
102239
102616
|
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
102240
102617
|
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
102241
102618
|
// A line that is exactly one lowercase opening (or self-closing) tag — the shape
|
|
@@ -102261,11 +102638,6 @@ function countRawContentTags(line) {
|
|
|
102261
102638
|
closes: (line.match(close) ?? []).length,
|
|
102262
102639
|
}));
|
|
102263
102640
|
}
|
|
102264
|
-
// Indentation width in columns, counting a tab as 4 per CommonMark.
|
|
102265
|
-
function indentWidth(line) {
|
|
102266
|
-
const leading = line.match(/^[ \t]*/)?.[0] ?? '';
|
|
102267
|
-
return leading.replace(/\t/g, ' ').length;
|
|
102268
|
-
}
|
|
102269
102641
|
/**
|
|
102270
102642
|
* Decides whether a blank line belongs between `line` and `next` so the HTML
|
|
102271
102643
|
* flow block opened on `line` terminates and `next` parses as markdown.
|
|
@@ -102337,6 +102709,7 @@ function terminateHtmlFlowBlocks(content) {
|
|
|
102337
102709
|
|
|
102338
102710
|
|
|
102339
102711
|
|
|
102712
|
+
|
|
102340
102713
|
// Matches a JSX attribute expression (e.g. `key={i}`) anywhere in a string. */
|
|
102341
102714
|
const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
|
|
102342
102715
|
// Name shape mirrors `componentTagPattern`; the lookbehind skips the inner tag
|
|
@@ -102347,25 +102720,33 @@ const NESTED_COMPONENT_TAG_RE = /(?<!<)<([A-Z][A-Za-z0-9_]*)[\s/>]/g;
|
|
|
102347
102720
|
const hasNestedGenericComponentTag = (content) => [...content.matchAll(NESTED_COMPONENT_TAG_RE)].some(match => !GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(match[1]));
|
|
102348
102721
|
/**
|
|
102349
102722
|
* Strip the shared leading indentation from a component body so readability indentation
|
|
102350
|
-
* isn't parsed as indented code (4+
|
|
102723
|
+
* isn't parsed as indented code (4+ columns), e.g. ` <p>` / ` text` -> `<p>` / ` text`.
|
|
102351
102724
|
* Relative indentation is kept, so content genuinely 4+ columns deeper stays code. We
|
|
102352
102725
|
* only strip when a line actually reaches 4 columns; otherwise the body is left as-is so
|
|
102353
102726
|
* its leading whitespace survives as text nodes (mixed component + HTML content needs it).
|
|
102727
|
+
*
|
|
102728
|
+
* Indentation is measured in CommonMark columns (tab = up to 4), matching how the parser
|
|
102729
|
+
* decides indented code. A char count (tab = 1) under-measures tab-indented bodies, so
|
|
102730
|
+
* they slip past the 4-column gate and their nested content fragments into code blocks.
|
|
102354
102731
|
*/
|
|
102355
102732
|
function safeDeindent(text) {
|
|
102356
102733
|
const lines = text.split('\n');
|
|
102357
102734
|
const nonEmptyLines = lines.filter(line => line.trim().length > 0);
|
|
102358
102735
|
if (nonEmptyLines.length === 0)
|
|
102359
102736
|
return text;
|
|
102360
|
-
|
|
102361
|
-
// (tab = 4) in terminate-html-flow-blocks.
|
|
102362
|
-
const indents = nonEmptyLines.map(line => line.match(/^(\s*)/)?.[1].length ?? 0);
|
|
102737
|
+
const indents = nonEmptyLines.map(line => expandIndentToColumns(leadingIndent(line)).length);
|
|
102363
102738
|
const minIndent = Math.min(...indents);
|
|
102364
102739
|
const maxIndent = Math.max(...indents);
|
|
102365
|
-
|
|
102366
|
-
if (stripAmount === 0)
|
|
102740
|
+
if (maxIndent < 4 || minIndent === 0)
|
|
102367
102741
|
return text;
|
|
102368
|
-
|
|
102742
|
+
// Expand each line's leading run to spaces before slicing so a shared indent of mixed
|
|
102743
|
+
// tabs/spaces (and partial-tab remainders) strips cleanly while relative depth survives.
|
|
102744
|
+
return lines
|
|
102745
|
+
.map(line => {
|
|
102746
|
+
const indent = leadingIndent(line);
|
|
102747
|
+
return expandIndentToColumns(indent).slice(minIndent) + line.slice(indent.length);
|
|
102748
|
+
})
|
|
102749
|
+
.join('\n');
|
|
102369
102750
|
}
|
|
102370
102751
|
/**
|
|
102371
102752
|
* Parse component-body markdown into mdast children. Dedenting shifts columns and
|
|
@@ -102425,6 +102806,10 @@ const substituteNodeWithMdxNode = (parent, index, mdxNode) => {
|
|
|
102425
102806
|
* This transformer identifies these patterns and converts them to proper MDX JSX elements so they
|
|
102426
102807
|
* can be accurately recognized and rendered later with their component definition code.
|
|
102427
102808
|
*
|
|
102809
|
+
* Note: The main goal is to promote PascalCase tags to MDX elements, but we want to promote
|
|
102810
|
+
* normal HTML to MDX elements in some cases so they get the full custom parsing behavior.
|
|
102811
|
+
* E.g. tags with JSX expressions, nested components, etc.
|
|
102812
|
+
*
|
|
102428
102813
|
* The mdx-component micromark tokenizer ensures that multi-line components are captured
|
|
102429
102814
|
* as single HTML nodes, so this transformer only needs to handle two cases:
|
|
102430
102815
|
*
|
|
@@ -102471,6 +102856,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102471
102856
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
102472
102857
|
return; // owned by dedicated transformers
|
|
102473
102858
|
const isPascal = isPascalCase(tag);
|
|
102859
|
+
// ==== SPECIAL CASES TO PROMOTE NORMAL HTML TO MDX ELEMENTS ====
|
|
102474
102860
|
// Lowercase inline tags with `{…}` attributes belong to
|
|
102475
102861
|
// mdxishInlineComponentBlocks; leave them as html for that pass. PascalCase
|
|
102476
102862
|
// components stay flow-level even when inline (ReadMe's component model).
|
|
@@ -102479,11 +102865,19 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102479
102865
|
// A lowercase wrapper is only promoted when it (or a descendant) carries a
|
|
102480
102866
|
// JSX expression or nests a component; otherwise it would swallow that inner
|
|
102481
102867
|
// JSX/component as literal text that rehype-raw's parse5 pass can't handle.
|
|
102482
|
-
// Table-structural wrappers are excluded — `mdxishTables` re-parses
|
|
102483
|
-
|
|
102868
|
+
// Table-structural wrappers are excluded from both — `mdxishTables` re-parses
|
|
102869
|
+
// those, so a `{…}` in a cell (e.g. `<code>--depth={n}</code>`) must not
|
|
102870
|
+
// accidentally promote the table to an MDX element prematurely.
|
|
102484
102871
|
const isTableStructuralTag = tag === 'table' || tableTags.has(tag);
|
|
102872
|
+
const hasNestedExpressionAttr = !selfClosing && !isTableStructuralTag && NESTED_ATTR_EXPRESSION_RE.test(contentAfterTag);
|
|
102485
102873
|
const hasNestedComponentTag = !selfClosing && !isTableStructuralTag && hasNestedGenericComponentTag(contentAfterTag);
|
|
102486
|
-
|
|
102874
|
+
// Promotion: By default commonmark doesn't parse markdown in single line HTML tags (e.g. <div>**bold**</div>)
|
|
102875
|
+
// To support that, we try to promote them to MDX elements so the markdown gets parsed
|
|
102876
|
+
const isPlainLowercaseHtml = !isPascal && !hasExpressionAttr(attributes) && !hasNestedExpressionAttr && !hasNestedComponentTag;
|
|
102877
|
+
const plainClosingTagIndex = isPlainLowercaseHtml && !selfClosing && isMarkdownPromotableHtmlTag(tag) && !NESTED_TABLE_RE.test(contentAfterTag)
|
|
102878
|
+
? findBalancedClosingTagIndex(contentAfterTag, tag)
|
|
102879
|
+
: -1;
|
|
102880
|
+
if (isPlainLowercaseHtml && plainClosingTagIndex < 0)
|
|
102487
102881
|
return;
|
|
102488
102882
|
const closingTagStr = `</${tag}>`;
|
|
102489
102883
|
// Case 1: Self-closing tag
|
|
@@ -102504,14 +102898,26 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102504
102898
|
return;
|
|
102505
102899
|
}
|
|
102506
102900
|
// Case 2: Self-contained block (closing tag in content)
|
|
102507
|
-
|
|
102508
|
-
|
|
102901
|
+
const closingTagIndex = isPlainLowercaseHtml ? plainClosingTagIndex : contentAfterTag.lastIndexOf(closingTagStr);
|
|
102902
|
+
if (closingTagIndex >= 0) {
|
|
102509
102903
|
// Untrimmed so parseMdChildren can dedent before trimming.
|
|
102510
102904
|
const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
|
|
102511
102905
|
const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
|
|
102512
|
-
let parsedChildren =
|
|
102513
|
-
|
|
102514
|
-
|
|
102906
|
+
let parsedChildren = [];
|
|
102907
|
+
if (componentInnerContent.trim()) {
|
|
102908
|
+
try {
|
|
102909
|
+
parsedChildren = parseMdChildren(componentInnerContent, safeMode);
|
|
102910
|
+
}
|
|
102911
|
+
catch (error) {
|
|
102912
|
+
// Plain HTML bodies can hold anything (e.g. stray braces the strict
|
|
102913
|
+
// expression parser rejects) — keep the node raw instead of throwing.
|
|
102914
|
+
if (isPlainLowercaseHtml)
|
|
102915
|
+
return;
|
|
102916
|
+
throw error;
|
|
102917
|
+
}
|
|
102918
|
+
}
|
|
102919
|
+
if (isPlainLowercaseHtml && !containsMarkdownConstruct(parsedChildren))
|
|
102920
|
+
return;
|
|
102515
102921
|
// Lowercase tags are usually inline; unwrap a sole paragraph so their
|
|
102516
102922
|
// phrasing content isn't spuriously block-wrapped.
|
|
102517
102923
|
if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
|
|
@@ -103517,7 +103923,7 @@ const textToBlock = (text) => [{ children: textToInline(text), type: 'paragraph'
|
|
|
103517
103923
|
/**
|
|
103518
103924
|
* Converts leading newlines in magic block content to `<br>` tags.
|
|
103519
103925
|
* Leading newlines are stripped by remark-parse before they become soft break nodes,
|
|
103520
|
-
* so
|
|
103926
|
+
* so the hard-breaks plugin cannot handle them. We convert them to HTML `<br>` tags instead.
|
|
103521
103927
|
*/
|
|
103522
103928
|
const ensureLeadingBreaks = (text) => text.replace(/^\n+/, match => '<br>'.repeat(match.length));
|
|
103523
103929
|
/** Preprocesses magic block body content before parsing. */
|
|
@@ -103529,7 +103935,7 @@ const contentParser = unified()
|
|
|
103529
103935
|
.data('micromarkExtensions', [syntax_gemoji(), legacyVariable(), looseHtmlEntity()])
|
|
103530
103936
|
.data('fromMarkdownExtensions', [gemojiFromMarkdown(), legacyVariableFromMarkdown(), emptyTaskListItemFromMarkdown(), looseHtmlEntityFromMarkdown()])
|
|
103531
103937
|
.use(remarkParse)
|
|
103532
|
-
.use(
|
|
103938
|
+
.use(hard_breaks)
|
|
103533
103939
|
.use(remarkGfm)
|
|
103534
103940
|
.use(normalize_malformed_md_syntax);
|
|
103535
103941
|
/**
|
|
@@ -104076,9 +104482,6 @@ const magicBlockTransformer = (options = {}) => tree => {
|
|
|
104076
104482
|
// single-line `<div>…</div>`). CommonMark slurps the whole div as one `html`
|
|
104077
104483
|
// node, so the tokenizer never sees the HTMLBlock — we recover it here.
|
|
104078
104484
|
const RAW_HTML_BLOCK_RE = /<HTMLBlock\b([^>]*)>\s*\{\s*`((?:[^`\\]|\\.)*)`\s*\}\s*<\/HTMLBlock>/g;
|
|
104079
|
-
// Opening `<HTMLBlock …>` as its own `html` node — produced inside a paragraph
|
|
104080
|
-
// when an HTMLBlock appears inline alongside text.
|
|
104081
|
-
const HTML_BLOCK_OPEN_RE = /^<HTMLBlock\b([^>]*)>$/;
|
|
104082
104485
|
/**
|
|
104083
104486
|
* Builds the canonical `html-block` MDAST node the renderer expects.
|
|
104084
104487
|
*/
|
|
@@ -104159,13 +104562,14 @@ const splitRawHtmlBlocks = (node) => {
|
|
|
104159
104562
|
/**
|
|
104160
104563
|
* Converts every `<HTMLBlock>` shape that survives parsing into the canonical
|
|
104161
104564
|
* `html-block` MDAST node, reading the body from the tokenizer's template-literal
|
|
104162
|
-
* expression.
|
|
104565
|
+
* expression. Two shapes occur:
|
|
104163
104566
|
*
|
|
104164
|
-
* 1. JSX element (`mdxJsxFlowElement`/`mdxJsxTextElement`) —
|
|
104165
|
-
*
|
|
104166
|
-
*
|
|
104167
|
-
*
|
|
104168
|
-
*
|
|
104567
|
+
* 1. JSX element (`mdxJsxFlowElement`/`mdxJsxTextElement`) — table cells, after
|
|
104568
|
+
* their remarkMdx re-parse (that re-parse runs without the htmlBlockComponent
|
|
104569
|
+
* tokenizer, so `<HTMLBlock>` arrives as JSX rather than an opaque `html` node).
|
|
104570
|
+
* 2. Raw `html` blob (`splitRawHtmlBlocks`) — the htmlBlockComponent tokenizer's
|
|
104571
|
+
* opaque output (top-level and inline), or an `<HTMLBlock>` embedded in a
|
|
104572
|
+
* larger raw-HTML node like an inline `<div>` that the tokenizer never saw.
|
|
104169
104573
|
*
|
|
104170
104574
|
* Runs *after* `mdxishTables` so table cells are re-parsed first;
|
|
104171
104575
|
* `mdxishTables` recognizes the still-JSX `<HTMLBlock>` element when deciding to
|
|
@@ -104190,36 +104594,6 @@ const mdxishHtmlBlocks = () => tree => {
|
|
|
104190
104594
|
if (replacement)
|
|
104191
104595
|
parent.children.splice(index, 1, ...replacement);
|
|
104192
104596
|
});
|
|
104193
|
-
// Shape 3: inline within a paragraph — `<HTMLBlock>` open/close arrive as
|
|
104194
|
-
// separate `html` siblings with the template-literal expression between them.
|
|
104195
|
-
visit(tree, 'paragraph', (paragraph) => {
|
|
104196
|
-
// An html-block is block content, so it isn't a valid PhrasingContent child;
|
|
104197
|
-
// widen to RootContent (which HTMLBlock belongs to) for the in-place splice.
|
|
104198
|
-
const children = paragraph.children;
|
|
104199
|
-
for (let i = 0; i < children.length; i += 1) {
|
|
104200
|
-
const open = children[i];
|
|
104201
|
-
const openMatch = open.type === 'html' ? open.value.match(HTML_BLOCK_OPEN_RE) : null;
|
|
104202
|
-
if (!openMatch)
|
|
104203
|
-
continue; // eslint-disable-line no-continue
|
|
104204
|
-
const closeIdx = children.findIndex((child, j) => j > i && child.type === 'html' && child.value === '</HTMLBlock>');
|
|
104205
|
-
if (closeIdx === -1)
|
|
104206
|
-
continue; // eslint-disable-line no-continue
|
|
104207
|
-
const body = children
|
|
104208
|
-
.slice(i + 1, closeIdx)
|
|
104209
|
-
.map(child => {
|
|
104210
|
-
if (child.type === 'mdxTextExpression' || child.type === 'mdxFlowExpression') {
|
|
104211
|
-
return extractTemplateLiteral(child.value);
|
|
104212
|
-
}
|
|
104213
|
-
// Preserve raw text from any other phrasing sibling (e.g. stray
|
|
104214
|
-
// whitespace or content the tokenizer didn't claim) so it isn't
|
|
104215
|
-
// silently dropped from the html payload.
|
|
104216
|
-
return 'value' in child && typeof child.value === 'string' ? child.value : '';
|
|
104217
|
-
})
|
|
104218
|
-
.join('');
|
|
104219
|
-
const openingTagIndent = (open.position?.start.column ?? 1) - 1;
|
|
104220
|
-
children.splice(i, closeIdx - i + 1, htmlBlockFromRaw(openMatch[1], body, open.position, openingTagIndent));
|
|
104221
|
-
}
|
|
104222
|
-
});
|
|
104223
104597
|
};
|
|
104224
104598
|
/* harmony default export */ const mdxish_html_blocks = (mdxishHtmlBlocks);
|
|
104225
104599
|
|
|
@@ -104919,6 +105293,29 @@ const mdxishMermaidTransformer = () => (tree) => {
|
|
|
104919
105293
|
};
|
|
104920
105294
|
/* harmony default export */ const mdxish_mermaid = (mdxishMermaidTransformer);
|
|
104921
105295
|
|
|
105296
|
+
;// ./processor/transform/mdxish/normalize-closing-tag-whitespace.ts
|
|
105297
|
+
|
|
105298
|
+
|
|
105299
|
+
// Spaces/tabs only — newlines would let prose `<` / `>` across lines look like one tag.
|
|
105300
|
+
const SPACED_CLOSING_TAG_RE = /<\/[ \t]*([a-zA-Z][a-zA-Z0-9-]*)[ \t]*>/g;
|
|
105301
|
+
/**
|
|
105302
|
+
* Canonicalize spaced closing tags (`</ td >` → `</td>`) for known HTML names.
|
|
105303
|
+
*
|
|
105304
|
+
* In HTML, `</` + whitespace is a bogus comment, so `</ table >` never closes the
|
|
105305
|
+
* table (jsxTable misses it → empty table + pre; CX-3706). Only standard HTML tags;
|
|
105306
|
+
* custom components, prose (`a </ b`), and code blocks are left alone.
|
|
105307
|
+
*
|
|
105308
|
+
* @example
|
|
105309
|
+
* normalizeClosingTagWhitespace('</ td >') // '</td>'
|
|
105310
|
+
* normalizeClosingTagWhitespace('</table >') // '</table>'
|
|
105311
|
+
* normalizeClosingTagWhitespace('a </ b >') // unchanged
|
|
105312
|
+
*/
|
|
105313
|
+
function normalizeClosingTagWhitespace(content) {
|
|
105314
|
+
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
105315
|
+
const result = protectedContent.replace(SPACED_CLOSING_TAG_RE, (match, tagName) => STANDARD_HTML_TAGS.has(tagName.toLowerCase()) ? `</${tagName}>` : match);
|
|
105316
|
+
return restoreCodeBlocks(result, protectedCode);
|
|
105317
|
+
}
|
|
105318
|
+
|
|
104922
105319
|
;// ./processor/transform/mdxish/normalize-compact-headings.ts
|
|
104923
105320
|
|
|
104924
105321
|
/**
|
|
@@ -105399,186 +105796,463 @@ function resolveCodeVariables(value, resolvedVariables) {
|
|
|
105399
105796
|
return name.toUpperCase();
|
|
105400
105797
|
return name in resolvedVariables ? resolvedVariables[name] : name.toUpperCase();
|
|
105401
105798
|
}
|
|
105402
|
-
// MDX variable: {user.*}
|
|
105403
|
-
if (mdxEscapePrefix || mdxEscapeSuffix)
|
|
105404
|
-
return match;
|
|
105405
|
-
if (mdxVarName in resolvedVariables)
|
|
105406
|
-
return resolvedVariables[mdxVarName];
|
|
105407
|
-
const fullPath = match.slice(1, -1);
|
|
105408
|
-
return fullPath.toUpperCase();
|
|
105409
|
-
});
|
|
105410
|
-
}
|
|
105411
|
-
/**
|
|
105412
|
-
* A remark mdast plugin that resolves legacy variables <<...>> and MDX variables {user.*} inside code and inline code nodes
|
|
105413
|
-
* to their values. Uses regexes from the readme variable to search for variables in the code string.
|
|
105414
|
-
*
|
|
105415
|
-
* This is needed because variables in code blocks and inline cannot be tokenized, and also we need to maintain the code string
|
|
105416
|
-
* in the code nodes. This enables engine side variable resolution in codes which improves UX
|
|
105417
|
-
*/
|
|
105418
|
-
const variablesCodeResolver = ({ variables } = {}) => tree => {
|
|
105419
|
-
const resolvedVariables = variables_code_flattenVariables(variables);
|
|
105420
|
-
visit(tree, 'inlineCode', (node) => {
|
|
105421
|
-
if (!node.value)
|
|
105422
|
-
return;
|
|
105423
|
-
node.value = resolveCodeVariables(node.value, resolvedVariables);
|
|
105424
|
-
});
|
|
105425
|
-
visit(tree, 'code', (node) => {
|
|
105426
|
-
if (!node.value)
|
|
105427
|
-
return;
|
|
105428
|
-
if (node.lang === 'mermaid')
|
|
105429
|
-
return;
|
|
105430
|
-
const nextValue = resolveCodeVariables(node.value, resolvedVariables);
|
|
105431
|
-
node.value = nextValue;
|
|
105432
|
-
// Keep code-tabs/readme-components hProperties in sync with node.value
|
|
105433
|
-
// because renderers read `value` from hProperties.
|
|
105434
|
-
if (node.data?.hProperties && typeof node.data.hProperties === 'object') {
|
|
105435
|
-
node.data.hProperties.value = nextValue;
|
|
105799
|
+
// MDX variable: {user.*}
|
|
105800
|
+
if (mdxEscapePrefix || mdxEscapeSuffix)
|
|
105801
|
+
return match;
|
|
105802
|
+
if (mdxVarName in resolvedVariables)
|
|
105803
|
+
return resolvedVariables[mdxVarName];
|
|
105804
|
+
const fullPath = match.slice(1, -1);
|
|
105805
|
+
return fullPath.toUpperCase();
|
|
105806
|
+
});
|
|
105807
|
+
}
|
|
105808
|
+
/**
|
|
105809
|
+
* A remark mdast plugin that resolves legacy variables <<...>> and MDX variables {user.*} inside code and inline code nodes
|
|
105810
|
+
* to their values. Uses regexes from the readme variable to search for variables in the code string.
|
|
105811
|
+
*
|
|
105812
|
+
* This is needed because variables in code blocks and inline cannot be tokenized, and also we need to maintain the code string
|
|
105813
|
+
* in the code nodes. This enables engine side variable resolution in codes which improves UX
|
|
105814
|
+
*/
|
|
105815
|
+
const variablesCodeResolver = ({ variables } = {}) => tree => {
|
|
105816
|
+
const resolvedVariables = variables_code_flattenVariables(variables);
|
|
105817
|
+
visit(tree, 'inlineCode', (node) => {
|
|
105818
|
+
if (!node.value)
|
|
105819
|
+
return;
|
|
105820
|
+
node.value = resolveCodeVariables(node.value, resolvedVariables);
|
|
105821
|
+
});
|
|
105822
|
+
visit(tree, 'code', (node) => {
|
|
105823
|
+
if (!node.value)
|
|
105824
|
+
return;
|
|
105825
|
+
if (node.lang === 'mermaid')
|
|
105826
|
+
return;
|
|
105827
|
+
const nextValue = resolveCodeVariables(node.value, resolvedVariables);
|
|
105828
|
+
node.value = nextValue;
|
|
105829
|
+
// Keep code-tabs/readme-components hProperties in sync with node.value
|
|
105830
|
+
// because renderers read `value` from hProperties.
|
|
105831
|
+
if (node.data?.hProperties && typeof node.data.hProperties === 'object') {
|
|
105832
|
+
node.data.hProperties.value = nextValue;
|
|
105833
|
+
}
|
|
105834
|
+
});
|
|
105835
|
+
return tree;
|
|
105836
|
+
};
|
|
105837
|
+
/* harmony default export */ const variables_code = (variablesCodeResolver);
|
|
105838
|
+
|
|
105839
|
+
;// ./processor/transform/mdxish/variables-text.ts
|
|
105840
|
+
|
|
105841
|
+
|
|
105842
|
+
/**
|
|
105843
|
+
* Matches {user.<field>} patterns:
|
|
105844
|
+
* - {user.name}
|
|
105845
|
+
* - {user.email}
|
|
105846
|
+
* - {user['field']}
|
|
105847
|
+
* - {user["field"]}
|
|
105848
|
+
*
|
|
105849
|
+
* Captures the field name in group 1 (dot notation) or group 2 (bracket notation)
|
|
105850
|
+
*/
|
|
105851
|
+
const USER_VAR_REGEX = /\{user\.(\w+)\}|\{user\[['"](\w+)['"]\]\}/g;
|
|
105852
|
+
function makeVariableNode(varName, rawValue) {
|
|
105853
|
+
return {
|
|
105854
|
+
type: NodeTypes.variable,
|
|
105855
|
+
data: {
|
|
105856
|
+
hName: 'Variable',
|
|
105857
|
+
hProperties: { name: varName },
|
|
105858
|
+
},
|
|
105859
|
+
value: rawValue,
|
|
105860
|
+
};
|
|
105861
|
+
}
|
|
105862
|
+
/**
|
|
105863
|
+
* A remark plugin that parses {user.<field>} patterns from text nodes and
|
|
105864
|
+
* mdx expression nodes, creating Variable nodes for runtime resolution.
|
|
105865
|
+
*
|
|
105866
|
+
* Handles:
|
|
105867
|
+
* - `text` nodes: when safeMode is true or after expression evaluation
|
|
105868
|
+
* - `mdxTextExpression` nodes: when mdxExpression has parsed {user.*} before evaluation
|
|
105869
|
+
* - `mdxFlowExpression` nodes: when {user.*} appears on its own line (e.g. inside JSX table cells)
|
|
105870
|
+
*
|
|
105871
|
+
* Supports any user field: name, email, email_verified, exp, iat, etc.
|
|
105872
|
+
*/
|
|
105873
|
+
function visitExpressionNode(node, index, parent) {
|
|
105874
|
+
if (index === undefined || !parent)
|
|
105875
|
+
return;
|
|
105876
|
+
const wrapped = `{${(node.value ?? '').trim()}}`;
|
|
105877
|
+
const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
|
|
105878
|
+
if (matches.length !== 1)
|
|
105879
|
+
return;
|
|
105880
|
+
const varName = matches[0][1] || matches[0][2];
|
|
105881
|
+
parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
|
|
105882
|
+
}
|
|
105883
|
+
const variablesTextTransformer = () => tree => {
|
|
105884
|
+
visit(tree, 'mdxTextExpression', (node, index, parent) => {
|
|
105885
|
+
visitExpressionNode(node, index, parent);
|
|
105886
|
+
});
|
|
105887
|
+
visit(tree, 'mdxFlowExpression', (node, index, parent) => {
|
|
105888
|
+
visitExpressionNode(node, index, parent);
|
|
105889
|
+
});
|
|
105890
|
+
visit(tree, 'text', (node, index, parent) => {
|
|
105891
|
+
if (index === undefined || !parent)
|
|
105892
|
+
return;
|
|
105893
|
+
// Skip if inside inline code
|
|
105894
|
+
if (parent.type === 'inlineCode')
|
|
105895
|
+
return;
|
|
105896
|
+
const text = node.value;
|
|
105897
|
+
if (typeof text !== 'string' || !text.trim())
|
|
105898
|
+
return;
|
|
105899
|
+
if (!text.includes('{user.') && !text.includes('{user['))
|
|
105900
|
+
return;
|
|
105901
|
+
const matches = [...text.matchAll(USER_VAR_REGEX)];
|
|
105902
|
+
if (matches.length === 0)
|
|
105903
|
+
return;
|
|
105904
|
+
const parts = [];
|
|
105905
|
+
let lastIndex = 0;
|
|
105906
|
+
matches.forEach(match => {
|
|
105907
|
+
const matchIndex = match.index ?? 0;
|
|
105908
|
+
// Add text before the match
|
|
105909
|
+
if (matchIndex > lastIndex) {
|
|
105910
|
+
parts.push({ type: 'text', value: text.slice(lastIndex, matchIndex) });
|
|
105911
|
+
}
|
|
105912
|
+
// Extract variable name from either capture group (dot or bracket notation)
|
|
105913
|
+
const varName = match[1] || match[2];
|
|
105914
|
+
parts.push(makeVariableNode(varName, match[0]));
|
|
105915
|
+
lastIndex = matchIndex + match[0].length;
|
|
105916
|
+
});
|
|
105917
|
+
// Add remaining text after last match
|
|
105918
|
+
if (lastIndex < text.length) {
|
|
105919
|
+
parts.push({ type: 'text', value: text.slice(lastIndex) });
|
|
105920
|
+
}
|
|
105921
|
+
// Replace node with parts
|
|
105922
|
+
if (parts.length > 1 || (parts.length === 1 && parts[0].type !== 'text')) {
|
|
105923
|
+
parent.children.splice(index, 1, ...parts);
|
|
105924
|
+
}
|
|
105925
|
+
});
|
|
105926
|
+
return tree;
|
|
105927
|
+
};
|
|
105928
|
+
/* harmony default export */ const variables_text = (variablesTextTransformer);
|
|
105929
|
+
|
|
105930
|
+
;// ./lib/mdast-util/html-block-component/index.ts
|
|
105931
|
+
const html_block_component_contextMap = new WeakMap();
|
|
105932
|
+
function findHtmlBlockComponentToken() {
|
|
105933
|
+
const events = this.tokenStack;
|
|
105934
|
+
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
105935
|
+
if (events[i][0].type === 'htmlBlockComponent')
|
|
105936
|
+
return events[i][0];
|
|
105937
|
+
}
|
|
105938
|
+
return undefined;
|
|
105939
|
+
}
|
|
105940
|
+
function enterHtmlBlockComponent(token) {
|
|
105941
|
+
html_block_component_contextMap.set(token, { chunks: [], lastEndLine: token.start.line });
|
|
105942
|
+
this.enter({ type: 'html', value: '' }, token);
|
|
105943
|
+
}
|
|
105944
|
+
function exitHtmlBlockComponentData(token) {
|
|
105945
|
+
const componentToken = findHtmlBlockComponentToken.call(this);
|
|
105946
|
+
if (!componentToken)
|
|
105947
|
+
return;
|
|
105948
|
+
const ctx = html_block_component_contextMap.get(componentToken);
|
|
105949
|
+
if (ctx) {
|
|
105950
|
+
const gap = token.start.line - ctx.lastEndLine;
|
|
105951
|
+
if (ctx.chunks.length > 0 && gap > 0) {
|
|
105952
|
+
ctx.chunks.push('\n'.repeat(gap));
|
|
105953
|
+
}
|
|
105954
|
+
ctx.chunks.push(this.sliceSerialize(token));
|
|
105955
|
+
ctx.lastEndLine = token.end.line;
|
|
105956
|
+
}
|
|
105957
|
+
}
|
|
105958
|
+
function exitHtmlBlockComponent(token) {
|
|
105959
|
+
const ctx = html_block_component_contextMap.get(token);
|
|
105960
|
+
const node = this.stack[this.stack.length - 1];
|
|
105961
|
+
if (ctx) {
|
|
105962
|
+
node.value = ctx.chunks.join('');
|
|
105963
|
+
html_block_component_contextMap.delete(token);
|
|
105964
|
+
}
|
|
105965
|
+
this.exit(token);
|
|
105966
|
+
}
|
|
105967
|
+
function htmlBlockComponentFromMarkdown() {
|
|
105968
|
+
return {
|
|
105969
|
+
enter: {
|
|
105970
|
+
htmlBlockComponent: enterHtmlBlockComponent,
|
|
105971
|
+
},
|
|
105972
|
+
exit: {
|
|
105973
|
+
htmlBlockComponentData: exitHtmlBlockComponentData,
|
|
105974
|
+
htmlBlockComponent: exitHtmlBlockComponent,
|
|
105975
|
+
},
|
|
105976
|
+
};
|
|
105977
|
+
}
|
|
105978
|
+
|
|
105979
|
+
;// ./lib/micromark/html-block-component/syntax.ts
|
|
105980
|
+
|
|
105981
|
+
|
|
105982
|
+
const TAG_SUFFIX = [
|
|
105983
|
+
codes.uppercaseT,
|
|
105984
|
+
codes.uppercaseM,
|
|
105985
|
+
codes.uppercaseL,
|
|
105986
|
+
codes.uppercaseB,
|
|
105987
|
+
codes.lowercaseL,
|
|
105988
|
+
codes.lowercaseO,
|
|
105989
|
+
codes.lowercaseC,
|
|
105990
|
+
codes.lowercaseK,
|
|
105991
|
+
];
|
|
105992
|
+
// ---------------------------------------------------------------------------
|
|
105993
|
+
// Shared tokenizer factory
|
|
105994
|
+
// ---------------------------------------------------------------------------
|
|
105995
|
+
/**
|
|
105996
|
+
* Creates a tokenize function for `<HTMLBlock>...</HTMLBlock>`.
|
|
105997
|
+
*
|
|
105998
|
+
* - **flow** (block-level): supports multiline content via line continuations,
|
|
105999
|
+
* consumes trailing whitespace after the closing tag.
|
|
106000
|
+
* - **text** (inline): single-line only, exits immediately after the closing tag.
|
|
106001
|
+
*/
|
|
106002
|
+
function syntax_createTokenize(mode) {
|
|
106003
|
+
return function tokenize(effects, ok, nok) {
|
|
106004
|
+
let depth = 1;
|
|
106005
|
+
function matchChars(chars, onMatch, onFail) {
|
|
106006
|
+
if (chars.length === 0)
|
|
106007
|
+
return onMatch;
|
|
106008
|
+
const next = (code) => {
|
|
106009
|
+
if (code === chars[0]) {
|
|
106010
|
+
effects.consume(code);
|
|
106011
|
+
return matchChars(chars.slice(1), onMatch, onFail);
|
|
106012
|
+
}
|
|
106013
|
+
return onFail(code);
|
|
106014
|
+
};
|
|
106015
|
+
return next;
|
|
106016
|
+
}
|
|
106017
|
+
function matchTagName(onMatch, onFail) {
|
|
106018
|
+
const next = (code) => {
|
|
106019
|
+
if (code === codes.uppercaseH) {
|
|
106020
|
+
effects.consume(code);
|
|
106021
|
+
return matchChars(TAG_SUFFIX, onMatch, onFail);
|
|
106022
|
+
}
|
|
106023
|
+
return onFail(code);
|
|
106024
|
+
};
|
|
106025
|
+
return next;
|
|
106026
|
+
}
|
|
106027
|
+
return start;
|
|
106028
|
+
function start(code) {
|
|
106029
|
+
if (code !== codes.lessThan)
|
|
106030
|
+
return nok(code);
|
|
106031
|
+
effects.enter('htmlBlockComponent');
|
|
106032
|
+
effects.enter('htmlBlockComponentData');
|
|
106033
|
+
effects.consume(code);
|
|
106034
|
+
return matchTagName(afterTagName, nok);
|
|
106035
|
+
}
|
|
106036
|
+
function afterTagName(code) {
|
|
106037
|
+
if (code === codes.greaterThan) {
|
|
106038
|
+
effects.consume(code);
|
|
106039
|
+
return body;
|
|
106040
|
+
}
|
|
106041
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
106042
|
+
effects.consume(code);
|
|
106043
|
+
return inAttributes;
|
|
106044
|
+
}
|
|
106045
|
+
if (mode === 'flow' && markdownLineEnding(code)) {
|
|
106046
|
+
effects.exit('htmlBlockComponentData');
|
|
106047
|
+
return attributeContinuationStart(code);
|
|
106048
|
+
}
|
|
106049
|
+
if (code === codes.slash) {
|
|
106050
|
+
effects.consume(code);
|
|
106051
|
+
return selfClose;
|
|
106052
|
+
}
|
|
106053
|
+
return nok(code);
|
|
106054
|
+
}
|
|
106055
|
+
function inAttributes(code) {
|
|
106056
|
+
if (code === codes.greaterThan) {
|
|
106057
|
+
effects.consume(code);
|
|
106058
|
+
return body;
|
|
106059
|
+
}
|
|
106060
|
+
if (code === null) {
|
|
106061
|
+
return nok(code);
|
|
106062
|
+
}
|
|
106063
|
+
if (markdownLineEnding(code)) {
|
|
106064
|
+
if (mode === 'text')
|
|
106065
|
+
return nok(code);
|
|
106066
|
+
effects.exit('htmlBlockComponentData');
|
|
106067
|
+
return attributeContinuationStart(code);
|
|
106068
|
+
}
|
|
106069
|
+
effects.consume(code);
|
|
106070
|
+
return inAttributes;
|
|
106071
|
+
}
|
|
106072
|
+
function attributeContinuationStart(code) {
|
|
106073
|
+
return effects.check(html_block_component_syntax_nonLazyContinuationStart, attributeContinuationNonLazy, continuationAfter)(code);
|
|
106074
|
+
}
|
|
106075
|
+
function attributeContinuationNonLazy(code) {
|
|
106076
|
+
effects.enter(types_types.lineEnding);
|
|
106077
|
+
effects.consume(code);
|
|
106078
|
+
effects.exit(types_types.lineEnding);
|
|
106079
|
+
return attributeContinuationBefore;
|
|
106080
|
+
}
|
|
106081
|
+
function attributeContinuationBefore(code) {
|
|
106082
|
+
if (code === null || markdownLineEnding(code)) {
|
|
106083
|
+
return attributeContinuationStart(code);
|
|
106084
|
+
}
|
|
106085
|
+
effects.enter('htmlBlockComponentData');
|
|
106086
|
+
return inAttributes(code);
|
|
106087
|
+
}
|
|
106088
|
+
function selfClose(code) {
|
|
106089
|
+
if (code === codes.greaterThan) {
|
|
106090
|
+
effects.consume(code);
|
|
106091
|
+
return mode === 'flow' ? afterClose : done(code);
|
|
106092
|
+
}
|
|
106093
|
+
return nok(code);
|
|
106094
|
+
}
|
|
106095
|
+
function body(code) {
|
|
106096
|
+
if (code === null)
|
|
106097
|
+
return nok(code);
|
|
106098
|
+
if (markdownLineEnding(code)) {
|
|
106099
|
+
if (mode === 'text') {
|
|
106100
|
+
// Text constructs operate on paragraph content which spans lines
|
|
106101
|
+
effects.consume(code);
|
|
106102
|
+
return body;
|
|
106103
|
+
}
|
|
106104
|
+
effects.exit('htmlBlockComponentData');
|
|
106105
|
+
return continuationStart(code);
|
|
106106
|
+
}
|
|
106107
|
+
if (code === codes.lessThan) {
|
|
106108
|
+
effects.consume(code);
|
|
106109
|
+
return closeSlash;
|
|
106110
|
+
}
|
|
106111
|
+
effects.consume(code);
|
|
106112
|
+
return body;
|
|
106113
|
+
}
|
|
106114
|
+
function closeSlash(code) {
|
|
106115
|
+
if (code === codes.slash) {
|
|
106116
|
+
effects.consume(code);
|
|
106117
|
+
return matchTagName(closeGt, body);
|
|
106118
|
+
}
|
|
106119
|
+
return matchTagName(openAfterTagName, body)(code);
|
|
106120
|
+
}
|
|
106121
|
+
function openAfterTagName(code) {
|
|
106122
|
+
if (code === codes.greaterThan || code === codes.space || code === codes.horizontalTab) {
|
|
106123
|
+
depth += 1;
|
|
106124
|
+
effects.consume(code);
|
|
106125
|
+
return body;
|
|
106126
|
+
}
|
|
106127
|
+
return body(code);
|
|
106128
|
+
}
|
|
106129
|
+
function closeGt(code) {
|
|
106130
|
+
if (code === codes.greaterThan) {
|
|
106131
|
+
depth -= 1;
|
|
106132
|
+
effects.consume(code);
|
|
106133
|
+
if (depth === 0) {
|
|
106134
|
+
return mode === 'flow' ? afterClose : done(code);
|
|
106135
|
+
}
|
|
106136
|
+
return body;
|
|
106137
|
+
}
|
|
106138
|
+
return body(code);
|
|
105436
106139
|
}
|
|
105437
|
-
|
|
105438
|
-
|
|
105439
|
-
|
|
105440
|
-
|
|
105441
|
-
|
|
105442
|
-
;// ./processor/transform/mdxish/variables-text.ts
|
|
105443
|
-
|
|
105444
|
-
|
|
105445
|
-
/**
|
|
105446
|
-
* Matches {user.<field>} patterns:
|
|
105447
|
-
* - {user.name}
|
|
105448
|
-
* - {user.email}
|
|
105449
|
-
* - {user['field']}
|
|
105450
|
-
* - {user["field"]}
|
|
105451
|
-
*
|
|
105452
|
-
* Captures the field name in group 1 (dot notation) or group 2 (bracket notation)
|
|
105453
|
-
*/
|
|
105454
|
-
const USER_VAR_REGEX = /\{user\.(\w+)\}|\{user\[['"](\w+)['"]\]\}/g;
|
|
105455
|
-
function makeVariableNode(varName, rawValue) {
|
|
105456
|
-
return {
|
|
105457
|
-
type: NodeTypes.variable,
|
|
105458
|
-
data: {
|
|
105459
|
-
hName: 'Variable',
|
|
105460
|
-
hProperties: { name: varName },
|
|
105461
|
-
},
|
|
105462
|
-
value: rawValue,
|
|
105463
|
-
};
|
|
105464
|
-
}
|
|
105465
|
-
/**
|
|
105466
|
-
* A remark plugin that parses {user.<field>} patterns from text nodes and
|
|
105467
|
-
* mdx expression nodes, creating Variable nodes for runtime resolution.
|
|
105468
|
-
*
|
|
105469
|
-
* Handles:
|
|
105470
|
-
* - `text` nodes: when safeMode is true or after expression evaluation
|
|
105471
|
-
* - `mdxTextExpression` nodes: when mdxExpression has parsed {user.*} before evaluation
|
|
105472
|
-
* - `mdxFlowExpression` nodes: when {user.*} appears on its own line (e.g. inside JSX table cells)
|
|
105473
|
-
*
|
|
105474
|
-
* Supports any user field: name, email, email_verified, exp, iat, etc.
|
|
105475
|
-
*/
|
|
105476
|
-
function visitExpressionNode(node, index, parent) {
|
|
105477
|
-
if (index === undefined || !parent)
|
|
105478
|
-
return;
|
|
105479
|
-
const wrapped = `{${(node.value ?? '').trim()}}`;
|
|
105480
|
-
const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
|
|
105481
|
-
if (matches.length !== 1)
|
|
105482
|
-
return;
|
|
105483
|
-
const varName = matches[0][1] || matches[0][2];
|
|
105484
|
-
parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
|
|
105485
|
-
}
|
|
105486
|
-
const variablesTextTransformer = () => tree => {
|
|
105487
|
-
visit(tree, 'mdxTextExpression', (node, index, parent) => {
|
|
105488
|
-
visitExpressionNode(node, index, parent);
|
|
105489
|
-
});
|
|
105490
|
-
visit(tree, 'mdxFlowExpression', (node, index, parent) => {
|
|
105491
|
-
visitExpressionNode(node, index, parent);
|
|
105492
|
-
});
|
|
105493
|
-
visit(tree, 'text', (node, index, parent) => {
|
|
105494
|
-
if (index === undefined || !parent)
|
|
105495
|
-
return;
|
|
105496
|
-
// Skip if inside inline code
|
|
105497
|
-
if (parent.type === 'inlineCode')
|
|
105498
|
-
return;
|
|
105499
|
-
const text = node.value;
|
|
105500
|
-
if (typeof text !== 'string' || !text.trim())
|
|
105501
|
-
return;
|
|
105502
|
-
if (!text.includes('{user.') && !text.includes('{user['))
|
|
105503
|
-
return;
|
|
105504
|
-
const matches = [...text.matchAll(USER_VAR_REGEX)];
|
|
105505
|
-
if (matches.length === 0)
|
|
105506
|
-
return;
|
|
105507
|
-
const parts = [];
|
|
105508
|
-
let lastIndex = 0;
|
|
105509
|
-
matches.forEach(match => {
|
|
105510
|
-
const matchIndex = match.index ?? 0;
|
|
105511
|
-
// Add text before the match
|
|
105512
|
-
if (matchIndex > lastIndex) {
|
|
105513
|
-
parts.push({ type: 'text', value: text.slice(lastIndex, matchIndex) });
|
|
106140
|
+
// -- flow-only states ---------------------------------------------------
|
|
106141
|
+
function afterClose(code) {
|
|
106142
|
+
if (code === null || markdownLineEnding(code)) {
|
|
106143
|
+
return done(code);
|
|
105514
106144
|
}
|
|
105515
|
-
|
|
105516
|
-
|
|
105517
|
-
|
|
105518
|
-
|
|
105519
|
-
|
|
105520
|
-
|
|
105521
|
-
|
|
105522
|
-
parts.push({ type: 'text', value: text.slice(lastIndex) });
|
|
106145
|
+
if (code === codes.space || code === codes.horizontalTab) {
|
|
106146
|
+
effects.consume(code);
|
|
106147
|
+
return afterClose;
|
|
106148
|
+
}
|
|
106149
|
+
// Reject so the block re-parses as a paragraph, deferring to the
|
|
106150
|
+
// text tokenizer which preserves trailing content in the same line.
|
|
106151
|
+
return nok(code);
|
|
105523
106152
|
}
|
|
105524
|
-
//
|
|
105525
|
-
|
|
105526
|
-
|
|
106153
|
+
// -- flow-only: line continuation ---------------------------------------
|
|
106154
|
+
function continuationStart(code) {
|
|
106155
|
+
return effects.check(html_block_component_syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
105527
106156
|
}
|
|
105528
|
-
|
|
105529
|
-
|
|
106157
|
+
function continuationStartNonLazy(code) {
|
|
106158
|
+
effects.enter(types_types.lineEnding);
|
|
106159
|
+
effects.consume(code);
|
|
106160
|
+
effects.exit(types_types.lineEnding);
|
|
106161
|
+
return continuationBefore;
|
|
106162
|
+
}
|
|
106163
|
+
function continuationBefore(code) {
|
|
106164
|
+
if (code === null || markdownLineEnding(code)) {
|
|
106165
|
+
return continuationStart(code);
|
|
106166
|
+
}
|
|
106167
|
+
effects.enter('htmlBlockComponentData');
|
|
106168
|
+
return body(code);
|
|
106169
|
+
}
|
|
106170
|
+
function continuationAfter(code) {
|
|
106171
|
+
if (code === null)
|
|
106172
|
+
return nok(code);
|
|
106173
|
+
effects.exit('htmlBlockComponent');
|
|
106174
|
+
return ok(code);
|
|
106175
|
+
}
|
|
106176
|
+
// -- shared exit --------------------------------------------------------
|
|
106177
|
+
function done(_code) {
|
|
106178
|
+
effects.exit('htmlBlockComponentData');
|
|
106179
|
+
effects.exit('htmlBlockComponent');
|
|
106180
|
+
return ok(_code);
|
|
106181
|
+
}
|
|
106182
|
+
};
|
|
106183
|
+
}
|
|
106184
|
+
// ---------------------------------------------------------------------------
|
|
106185
|
+
// Flow construct (block-level)
|
|
106186
|
+
// ---------------------------------------------------------------------------
|
|
106187
|
+
const html_block_component_syntax_nonLazyContinuationStart = {
|
|
106188
|
+
tokenize: html_block_component_syntax_tokenizeNonLazyContinuationStart,
|
|
106189
|
+
partial: true,
|
|
105530
106190
|
};
|
|
105531
|
-
|
|
105532
|
-
|
|
105533
|
-
|
|
105534
|
-
|
|
105535
|
-
|
|
105536
|
-
|
|
105537
|
-
|
|
105538
|
-
if (events[i][0].type === 'jsxTable')
|
|
105539
|
-
return events[i][0];
|
|
106191
|
+
function resolveToHtmlBlockComponent(events) {
|
|
106192
|
+
let index = events.length;
|
|
106193
|
+
while (index > 0) {
|
|
106194
|
+
index -= 1;
|
|
106195
|
+
if (events[index][0] === 'enter' && events[index][1].type === 'htmlBlockComponent') {
|
|
106196
|
+
break;
|
|
106197
|
+
}
|
|
105540
106198
|
}
|
|
105541
|
-
|
|
105542
|
-
|
|
105543
|
-
|
|
105544
|
-
|
|
105545
|
-
|
|
106199
|
+
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
106200
|
+
events[index][1].start = events[index - 2][1].start;
|
|
106201
|
+
events[index + 1][1].start = events[index - 2][1].start;
|
|
106202
|
+
events.splice(index - 2, 2);
|
|
106203
|
+
}
|
|
106204
|
+
return events;
|
|
105546
106205
|
}
|
|
105547
|
-
|
|
105548
|
-
|
|
105549
|
-
|
|
105550
|
-
|
|
105551
|
-
|
|
105552
|
-
|
|
105553
|
-
|
|
105554
|
-
|
|
105555
|
-
|
|
106206
|
+
const htmlBlockComponentFlowConstruct = {
|
|
106207
|
+
name: 'htmlBlockComponent',
|
|
106208
|
+
tokenize: syntax_createTokenize('flow'),
|
|
106209
|
+
resolveTo: resolveToHtmlBlockComponent,
|
|
106210
|
+
concrete: true,
|
|
106211
|
+
};
|
|
106212
|
+
function html_block_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
106213
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
106214
|
+
const self = this;
|
|
106215
|
+
return start;
|
|
106216
|
+
function start(code) {
|
|
106217
|
+
if (markdownLineEnding(code)) {
|
|
106218
|
+
effects.enter(types_types.lineEnding);
|
|
106219
|
+
effects.consume(code);
|
|
106220
|
+
effects.exit(types_types.lineEnding);
|
|
106221
|
+
return after;
|
|
105556
106222
|
}
|
|
105557
|
-
|
|
105558
|
-
ctx.lastEndLine = token.end.line;
|
|
106223
|
+
return nok(code);
|
|
105559
106224
|
}
|
|
105560
|
-
|
|
105561
|
-
|
|
105562
|
-
|
|
105563
|
-
|
|
105564
|
-
|
|
105565
|
-
node.value = ctx.chunks.join('');
|
|
105566
|
-
jsx_table_contextMap.delete(token);
|
|
106225
|
+
function after(code) {
|
|
106226
|
+
if (self.parser.lazy[self.now().line]) {
|
|
106227
|
+
return nok(code);
|
|
106228
|
+
}
|
|
106229
|
+
return ok(code);
|
|
105567
106230
|
}
|
|
105568
|
-
this.exit(token);
|
|
105569
106231
|
}
|
|
105570
|
-
|
|
106232
|
+
// ---------------------------------------------------------------------------
|
|
106233
|
+
// Text construct (inline)
|
|
106234
|
+
// ---------------------------------------------------------------------------
|
|
106235
|
+
const htmlBlockComponentTextConstruct = {
|
|
106236
|
+
name: 'htmlBlockComponent',
|
|
106237
|
+
tokenize: syntax_createTokenize('text'),
|
|
106238
|
+
};
|
|
106239
|
+
// ---------------------------------------------------------------------------
|
|
106240
|
+
// Extension
|
|
106241
|
+
// ---------------------------------------------------------------------------
|
|
106242
|
+
function htmlBlockComponent() {
|
|
105571
106243
|
return {
|
|
105572
|
-
|
|
105573
|
-
|
|
106244
|
+
flow: {
|
|
106245
|
+
[codes.lessThan]: [htmlBlockComponentFlowConstruct],
|
|
105574
106246
|
},
|
|
105575
|
-
|
|
105576
|
-
|
|
105577
|
-
jsxTable: exitJsxTable,
|
|
106247
|
+
text: {
|
|
106248
|
+
[codes.lessThan]: [htmlBlockComponentTextConstruct],
|
|
105578
106249
|
},
|
|
105579
106250
|
};
|
|
105580
106251
|
}
|
|
105581
106252
|
|
|
106253
|
+
;// ./lib/micromark/html-block-component/index.ts
|
|
106254
|
+
|
|
106255
|
+
|
|
105582
106256
|
;// ./lib/micromark/jsx-comment/syntax.ts
|
|
105583
106257
|
|
|
105584
106258
|
|
|
@@ -105701,243 +106375,6 @@ function jsxComment() {
|
|
|
105701
106375
|
};
|
|
105702
106376
|
}
|
|
105703
106377
|
|
|
105704
|
-
;// ./lib/micromark/jsx-table/syntax.ts
|
|
105705
|
-
|
|
105706
|
-
|
|
105707
|
-
const jsx_table_syntax_nonLazyContinuationStart = {
|
|
105708
|
-
tokenize: jsx_table_syntax_tokenizeNonLazyContinuationStart,
|
|
105709
|
-
partial: true,
|
|
105710
|
-
};
|
|
105711
|
-
function resolveToJsxTable(events) {
|
|
105712
|
-
let index = events.length;
|
|
105713
|
-
while (index > 0) {
|
|
105714
|
-
index -= 1;
|
|
105715
|
-
if (events[index][0] === 'enter' && events[index][1].type === 'jsxTable') {
|
|
105716
|
-
break;
|
|
105717
|
-
}
|
|
105718
|
-
}
|
|
105719
|
-
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
105720
|
-
events[index][1].start = events[index - 2][1].start;
|
|
105721
|
-
events[index + 1][1].start = events[index - 2][1].start;
|
|
105722
|
-
events.splice(index - 2, 2);
|
|
105723
|
-
}
|
|
105724
|
-
return events;
|
|
105725
|
-
}
|
|
105726
|
-
const jsxTableConstruct = {
|
|
105727
|
-
name: 'jsxTable',
|
|
105728
|
-
tokenize: tokenizeJsxTable,
|
|
105729
|
-
resolveTo: resolveToJsxTable,
|
|
105730
|
-
concrete: true,
|
|
105731
|
-
};
|
|
105732
|
-
function tokenizeJsxTable(effects, ok, nok) {
|
|
105733
|
-
let codeSpanOpenSize = 0;
|
|
105734
|
-
let codeSpanCloseSize = 0;
|
|
105735
|
-
let depth = 1;
|
|
105736
|
-
const ABLE_SUFFIX = [codes.lowercaseA, codes.lowercaseB, codes.lowercaseL, codes.lowercaseE];
|
|
105737
|
-
/** Build a state chain that matches a sequence of character codes. */
|
|
105738
|
-
function matchChars(chars, onMatch, onFail) {
|
|
105739
|
-
if (chars.length === 0)
|
|
105740
|
-
return onMatch;
|
|
105741
|
-
return ((code) => {
|
|
105742
|
-
if (code === chars[0]) {
|
|
105743
|
-
effects.consume(code);
|
|
105744
|
-
return matchChars(chars.slice(1), onMatch, onFail);
|
|
105745
|
-
}
|
|
105746
|
-
return onFail(code);
|
|
105747
|
-
});
|
|
105748
|
-
}
|
|
105749
|
-
return start;
|
|
105750
|
-
function start(code) {
|
|
105751
|
-
if (code !== codes.lessThan)
|
|
105752
|
-
return nok(code);
|
|
105753
|
-
effects.enter('jsxTable');
|
|
105754
|
-
effects.enter('jsxTableData');
|
|
105755
|
-
effects.consume(code);
|
|
105756
|
-
return afterLessThan;
|
|
105757
|
-
}
|
|
105758
|
-
function afterLessThan(code) {
|
|
105759
|
-
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
105760
|
-
effects.consume(code);
|
|
105761
|
-
return matchChars(ABLE_SUFFIX, afterTagName, nok);
|
|
105762
|
-
}
|
|
105763
|
-
return nok(code);
|
|
105764
|
-
}
|
|
105765
|
-
function afterTagName(code) {
|
|
105766
|
-
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
105767
|
-
effects.consume(code);
|
|
105768
|
-
return body;
|
|
105769
|
-
}
|
|
105770
|
-
return nok(code);
|
|
105771
|
-
}
|
|
105772
|
-
function body(code) {
|
|
105773
|
-
// Reject unclosed <Table> so it falls back to normal HTML block parsing
|
|
105774
|
-
// instead of swallowing all subsequent content to EOF
|
|
105775
|
-
if (code === null) {
|
|
105776
|
-
return nok(code);
|
|
105777
|
-
}
|
|
105778
|
-
if (markdownLineEnding(code)) {
|
|
105779
|
-
effects.exit('jsxTableData');
|
|
105780
|
-
return continuationStart(code);
|
|
105781
|
-
}
|
|
105782
|
-
if (code === codes.backslash) {
|
|
105783
|
-
effects.consume(code);
|
|
105784
|
-
return escapedChar;
|
|
105785
|
-
}
|
|
105786
|
-
if (code === codes.lessThan) {
|
|
105787
|
-
effects.consume(code);
|
|
105788
|
-
return closeSlash;
|
|
105789
|
-
}
|
|
105790
|
-
// Skip over backtick code spans so `</Table>` in inline code isn't
|
|
105791
|
-
// treated as the closing tag
|
|
105792
|
-
if (code === codes.graveAccent) {
|
|
105793
|
-
codeSpanOpenSize = 0;
|
|
105794
|
-
return countOpenTicks(code);
|
|
105795
|
-
}
|
|
105796
|
-
effects.consume(code);
|
|
105797
|
-
return body;
|
|
105798
|
-
}
|
|
105799
|
-
function countOpenTicks(code) {
|
|
105800
|
-
if (code === codes.graveAccent) {
|
|
105801
|
-
codeSpanOpenSize += 1;
|
|
105802
|
-
effects.consume(code);
|
|
105803
|
-
return countOpenTicks;
|
|
105804
|
-
}
|
|
105805
|
-
return inCodeSpan(code);
|
|
105806
|
-
}
|
|
105807
|
-
function inCodeSpan(code) {
|
|
105808
|
-
if (code === null || markdownLineEnding(code))
|
|
105809
|
-
return body(code);
|
|
105810
|
-
if (code === codes.graveAccent) {
|
|
105811
|
-
codeSpanCloseSize = 0;
|
|
105812
|
-
return countCloseTicks(code);
|
|
105813
|
-
}
|
|
105814
|
-
effects.consume(code);
|
|
105815
|
-
return inCodeSpan;
|
|
105816
|
-
}
|
|
105817
|
-
function countCloseTicks(code) {
|
|
105818
|
-
if (code === codes.graveAccent) {
|
|
105819
|
-
codeSpanCloseSize += 1;
|
|
105820
|
-
effects.consume(code);
|
|
105821
|
-
return countCloseTicks;
|
|
105822
|
-
}
|
|
105823
|
-
return codeSpanCloseSize === codeSpanOpenSize ? body(code) : inCodeSpan(code);
|
|
105824
|
-
}
|
|
105825
|
-
function escapedChar(code) {
|
|
105826
|
-
if (code === null || markdownLineEnding(code)) {
|
|
105827
|
-
return body(code);
|
|
105828
|
-
}
|
|
105829
|
-
effects.consume(code);
|
|
105830
|
-
return body;
|
|
105831
|
-
}
|
|
105832
|
-
function closeSlash(code) {
|
|
105833
|
-
if (code === codes.slash) {
|
|
105834
|
-
effects.consume(code);
|
|
105835
|
-
return closeTagFirstChar;
|
|
105836
|
-
}
|
|
105837
|
-
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
105838
|
-
effects.consume(code);
|
|
105839
|
-
return matchChars(ABLE_SUFFIX, openAfterTagName, body);
|
|
105840
|
-
}
|
|
105841
|
-
return body(code);
|
|
105842
|
-
}
|
|
105843
|
-
function closeTagFirstChar(code) {
|
|
105844
|
-
if (code === codes.uppercaseT || code === codes.lowercaseT) {
|
|
105845
|
-
effects.consume(code);
|
|
105846
|
-
return matchChars(ABLE_SUFFIX, closeGt, body);
|
|
105847
|
-
}
|
|
105848
|
-
return body(code);
|
|
105849
|
-
}
|
|
105850
|
-
function openAfterTagName(code) {
|
|
105851
|
-
if (code === codes.greaterThan || code === codes.slash || code === codes.space || code === codes.horizontalTab) {
|
|
105852
|
-
depth += 1;
|
|
105853
|
-
effects.consume(code);
|
|
105854
|
-
return body;
|
|
105855
|
-
}
|
|
105856
|
-
return body(code);
|
|
105857
|
-
}
|
|
105858
|
-
function closeGt(code) {
|
|
105859
|
-
if (code === codes.greaterThan) {
|
|
105860
|
-
depth -= 1;
|
|
105861
|
-
effects.consume(code);
|
|
105862
|
-
if (depth === 0) {
|
|
105863
|
-
return afterClose;
|
|
105864
|
-
}
|
|
105865
|
-
return body;
|
|
105866
|
-
}
|
|
105867
|
-
return body(code);
|
|
105868
|
-
}
|
|
105869
|
-
function afterClose(code) {
|
|
105870
|
-
if (code === null || markdownLineEnding(code)) {
|
|
105871
|
-
effects.exit('jsxTableData');
|
|
105872
|
-
effects.exit('jsxTable');
|
|
105873
|
-
return ok(code);
|
|
105874
|
-
}
|
|
105875
|
-
effects.consume(code);
|
|
105876
|
-
return afterClose;
|
|
105877
|
-
}
|
|
105878
|
-
// Line ending handling — follows the htmlFlow pattern
|
|
105879
|
-
function continuationStart(code) {
|
|
105880
|
-
return effects.check(jsx_table_syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
105881
|
-
}
|
|
105882
|
-
function continuationStartNonLazy(code) {
|
|
105883
|
-
effects.enter(types_types.lineEnding);
|
|
105884
|
-
effects.consume(code);
|
|
105885
|
-
effects.exit(types_types.lineEnding);
|
|
105886
|
-
return continuationBefore;
|
|
105887
|
-
}
|
|
105888
|
-
function continuationBefore(code) {
|
|
105889
|
-
if (code === null || markdownLineEnding(code)) {
|
|
105890
|
-
return continuationStart(code);
|
|
105891
|
-
}
|
|
105892
|
-
effects.enter('jsxTableData');
|
|
105893
|
-
return body(code);
|
|
105894
|
-
}
|
|
105895
|
-
function continuationAfter(code) {
|
|
105896
|
-
// At EOF without </Table>, reject so content isn't swallowed
|
|
105897
|
-
if (code === null) {
|
|
105898
|
-
return nok(code);
|
|
105899
|
-
}
|
|
105900
|
-
effects.exit('jsxTable');
|
|
105901
|
-
return ok(code);
|
|
105902
|
-
}
|
|
105903
|
-
}
|
|
105904
|
-
function jsx_table_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
105905
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
105906
|
-
const self = this;
|
|
105907
|
-
return start;
|
|
105908
|
-
function start(code) {
|
|
105909
|
-
if (markdownLineEnding(code)) {
|
|
105910
|
-
effects.enter(types_types.lineEnding);
|
|
105911
|
-
effects.consume(code);
|
|
105912
|
-
effects.exit(types_types.lineEnding);
|
|
105913
|
-
return after;
|
|
105914
|
-
}
|
|
105915
|
-
return nok(code);
|
|
105916
|
-
}
|
|
105917
|
-
function after(code) {
|
|
105918
|
-
if (self.parser.lazy[self.now().line]) {
|
|
105919
|
-
return nok(code);
|
|
105920
|
-
}
|
|
105921
|
-
return ok(code);
|
|
105922
|
-
}
|
|
105923
|
-
}
|
|
105924
|
-
/**
|
|
105925
|
-
* Micromark extension that tokenizes `<Table>...</Table>` and `<table>...</table>`
|
|
105926
|
-
* as a single flow block.
|
|
105927
|
-
*
|
|
105928
|
-
* Prevents CommonMark HTML block type 6 from fragmenting table blocks at blank lines.
|
|
105929
|
-
*/
|
|
105930
|
-
function jsxTable() {
|
|
105931
|
-
return {
|
|
105932
|
-
flow: {
|
|
105933
|
-
[codes.lessThan]: [jsxTableConstruct],
|
|
105934
|
-
},
|
|
105935
|
-
};
|
|
105936
|
-
}
|
|
105937
|
-
|
|
105938
|
-
;// ./lib/micromark/jsx-table/index.ts
|
|
105939
|
-
|
|
105940
|
-
|
|
105941
106378
|
;// ./lib/micromark/mdx-expression-lenient/syntax.ts
|
|
105942
106379
|
|
|
105943
106380
|
|
|
@@ -106113,6 +106550,9 @@ function loadComponents() {
|
|
|
106113
106550
|
|
|
106114
106551
|
|
|
106115
106552
|
|
|
106553
|
+
|
|
106554
|
+
|
|
106555
|
+
|
|
106116
106556
|
|
|
106117
106557
|
|
|
106118
106558
|
|
|
@@ -106127,15 +106567,19 @@ const defaultTransformers = [
|
|
|
106127
106567
|
* CommonMark/remark limitations and reach parity with legacy (rdmd) rendering.
|
|
106128
106568
|
*
|
|
106129
106569
|
* Runs a series of string-level transformations before micromark/remark parsing:
|
|
106130
|
-
* 1.
|
|
106131
|
-
* 2.
|
|
106132
|
-
* 3.
|
|
106133
|
-
* 4.
|
|
106134
|
-
* 5.
|
|
106570
|
+
* 1. Canonicalize closing tags with stray whitespace (e.g., `</ td >` → `</td>`)
|
|
106571
|
+
* 2. Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
|
|
106572
|
+
* 3. Terminate HTML flow blocks so subsequent content isn't swallowed
|
|
106573
|
+
* 4. Close invalid "self-closing" HTML tags (e.g., `<i />` → `<i></i>`)
|
|
106574
|
+
* 5. Normalize compact ATX headings (e.g., `#Heading` → `# Heading`)
|
|
106575
|
+
* 6. Replace snake_case component names with parser-safe placeholders
|
|
106135
106576
|
*/
|
|
106136
106577
|
function preprocessContent(content, opts) {
|
|
106137
106578
|
const { knownComponents } = opts;
|
|
106138
|
-
|
|
106579
|
+
// Runs first so `jsxTable` sees a literal `</table>` (and the HTML-line
|
|
106580
|
+
// classification in `terminateHtmlFlowBlocks` is accurate)
|
|
106581
|
+
let result = normalizeClosingTagWhitespace(content);
|
|
106582
|
+
result = normalizeTableSeparator(result);
|
|
106139
106583
|
result = terminateHtmlFlowBlocks(result);
|
|
106140
106584
|
result = closeSelfClosingHtmlTags(result);
|
|
106141
106585
|
result = normalizeCompactHeadings(result);
|
|
@@ -106164,6 +106608,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
106164
106608
|
syntax_gemoji(),
|
|
106165
106609
|
legacyVariable(),
|
|
106166
106610
|
looseHtmlEntity(),
|
|
106611
|
+
htmlBlockComponent(),
|
|
106167
106612
|
];
|
|
106168
106613
|
const fromMarkdownExts = [
|
|
106169
106614
|
jsxTableFromMarkdown(),
|
|
@@ -106173,6 +106618,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
106173
106618
|
legacyVariableFromMarkdown(),
|
|
106174
106619
|
emptyTaskListItemFromMarkdown(),
|
|
106175
106620
|
looseHtmlEntityFromMarkdown(),
|
|
106621
|
+
htmlBlockComponentFromMarkdown(),
|
|
106176
106622
|
];
|
|
106177
106623
|
if (!safeMode) {
|
|
106178
106624
|
// Insert mdx expression (text-only, no flow) after gemoji at index 3
|
|
@@ -106186,6 +106632,10 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
106186
106632
|
// JSX comment tokenizer must come before magicBlock so it claims `{/* ... */}` first
|
|
106187
106633
|
micromarkExts.unshift(jsxComment());
|
|
106188
106634
|
}
|
|
106635
|
+
// Claim `<HTMLBlock>` as one opaque token so broad tokenizers can't fragment its body
|
|
106636
|
+
// We put this last as micromark tries the last-registered extension first, so push (not unshift) to win the `<` race.
|
|
106637
|
+
// micromarkExts.push(htmlBlockComponent());
|
|
106638
|
+
// fromMarkdownExts.push(htmlBlockComponentFromMarkdown());
|
|
106189
106639
|
const processor = unified()
|
|
106190
106640
|
.data('micromarkExtensions', micromarkExts)
|
|
106191
106641
|
.data('fromMarkdownExtensions', fromMarkdownExts)
|
|
@@ -106269,7 +106719,7 @@ function mdxish(mdContent, opts = {}) {
|
|
|
106269
106719
|
const { processor, parserReadyContent } = mdxishAstProcessor(contentWithoutComments, opts);
|
|
106270
106720
|
processor
|
|
106271
106721
|
.use(safeMode ? undefined : evaluate_exports) // Evaluate `export const/function` and stash scope on file.data.mdxishScope
|
|
106272
|
-
.use(
|
|
106722
|
+
.use(hard_breaks) // Must precede evaluateExpressions to avoid splitting the \n in an evaluated template literal into a <br> node
|
|
106273
106723
|
.use(safeMode ? undefined : evaluate_expressions) // Evaluate self-contained MDX expressions (e.g. `{1+1}`)
|
|
106274
106724
|
.use(safeMode ? undefined : evaluate_style_block_expressions) // Evaluate `<style>{`...`}</style>` template literals into plain CSS
|
|
106275
106725
|
.use(variables_code, { variables }) // Resolve <<...>> and {user.*} inside code and inline code nodes
|
|
@@ -106785,332 +107235,6 @@ const mdxishTags_tags = (doc) => {
|
|
|
106785
107235
|
};
|
|
106786
107236
|
/* harmony default export */ const mdxishTags = (mdxishTags_tags);
|
|
106787
107237
|
|
|
106788
|
-
;// ./lib/mdast-util/html-block-component/index.ts
|
|
106789
|
-
const html_block_component_contextMap = new WeakMap();
|
|
106790
|
-
function findHtmlBlockComponentToken() {
|
|
106791
|
-
const events = this.tokenStack;
|
|
106792
|
-
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
106793
|
-
if (events[i][0].type === 'htmlBlockComponent')
|
|
106794
|
-
return events[i][0];
|
|
106795
|
-
}
|
|
106796
|
-
return undefined;
|
|
106797
|
-
}
|
|
106798
|
-
function enterHtmlBlockComponent(token) {
|
|
106799
|
-
html_block_component_contextMap.set(token, { chunks: [], lastEndLine: token.start.line });
|
|
106800
|
-
this.enter({ type: 'html', value: '' }, token);
|
|
106801
|
-
}
|
|
106802
|
-
function exitHtmlBlockComponentData(token) {
|
|
106803
|
-
const componentToken = findHtmlBlockComponentToken.call(this);
|
|
106804
|
-
if (!componentToken)
|
|
106805
|
-
return;
|
|
106806
|
-
const ctx = html_block_component_contextMap.get(componentToken);
|
|
106807
|
-
if (ctx) {
|
|
106808
|
-
const gap = token.start.line - ctx.lastEndLine;
|
|
106809
|
-
if (ctx.chunks.length > 0 && gap > 0) {
|
|
106810
|
-
ctx.chunks.push('\n'.repeat(gap));
|
|
106811
|
-
}
|
|
106812
|
-
ctx.chunks.push(this.sliceSerialize(token));
|
|
106813
|
-
ctx.lastEndLine = token.end.line;
|
|
106814
|
-
}
|
|
106815
|
-
}
|
|
106816
|
-
function exitHtmlBlockComponent(token) {
|
|
106817
|
-
const ctx = html_block_component_contextMap.get(token);
|
|
106818
|
-
const node = this.stack[this.stack.length - 1];
|
|
106819
|
-
if (ctx) {
|
|
106820
|
-
node.value = ctx.chunks.join('');
|
|
106821
|
-
html_block_component_contextMap.delete(token);
|
|
106822
|
-
}
|
|
106823
|
-
this.exit(token);
|
|
106824
|
-
}
|
|
106825
|
-
function htmlBlockComponentFromMarkdown() {
|
|
106826
|
-
return {
|
|
106827
|
-
enter: {
|
|
106828
|
-
htmlBlockComponent: enterHtmlBlockComponent,
|
|
106829
|
-
},
|
|
106830
|
-
exit: {
|
|
106831
|
-
htmlBlockComponentData: exitHtmlBlockComponentData,
|
|
106832
|
-
htmlBlockComponent: exitHtmlBlockComponent,
|
|
106833
|
-
},
|
|
106834
|
-
};
|
|
106835
|
-
}
|
|
106836
|
-
|
|
106837
|
-
;// ./lib/micromark/html-block-component/syntax.ts
|
|
106838
|
-
|
|
106839
|
-
|
|
106840
|
-
const TAG_SUFFIX = [
|
|
106841
|
-
codes.uppercaseT,
|
|
106842
|
-
codes.uppercaseM,
|
|
106843
|
-
codes.uppercaseL,
|
|
106844
|
-
codes.uppercaseB,
|
|
106845
|
-
codes.lowercaseL,
|
|
106846
|
-
codes.lowercaseO,
|
|
106847
|
-
codes.lowercaseC,
|
|
106848
|
-
codes.lowercaseK,
|
|
106849
|
-
];
|
|
106850
|
-
// ---------------------------------------------------------------------------
|
|
106851
|
-
// Shared tokenizer factory
|
|
106852
|
-
// ---------------------------------------------------------------------------
|
|
106853
|
-
/**
|
|
106854
|
-
* Creates a tokenize function for `<HTMLBlock>...</HTMLBlock>`.
|
|
106855
|
-
*
|
|
106856
|
-
* - **flow** (block-level): supports multiline content via line continuations,
|
|
106857
|
-
* consumes trailing whitespace after the closing tag.
|
|
106858
|
-
* - **text** (inline): single-line only, exits immediately after the closing tag.
|
|
106859
|
-
*/
|
|
106860
|
-
function syntax_createTokenize(mode) {
|
|
106861
|
-
return function tokenize(effects, ok, nok) {
|
|
106862
|
-
let depth = 1;
|
|
106863
|
-
function matchChars(chars, onMatch, onFail) {
|
|
106864
|
-
if (chars.length === 0)
|
|
106865
|
-
return onMatch;
|
|
106866
|
-
const next = (code) => {
|
|
106867
|
-
if (code === chars[0]) {
|
|
106868
|
-
effects.consume(code);
|
|
106869
|
-
return matchChars(chars.slice(1), onMatch, onFail);
|
|
106870
|
-
}
|
|
106871
|
-
return onFail(code);
|
|
106872
|
-
};
|
|
106873
|
-
return next;
|
|
106874
|
-
}
|
|
106875
|
-
function matchTagName(onMatch, onFail) {
|
|
106876
|
-
const next = (code) => {
|
|
106877
|
-
if (code === codes.uppercaseH) {
|
|
106878
|
-
effects.consume(code);
|
|
106879
|
-
return matchChars(TAG_SUFFIX, onMatch, onFail);
|
|
106880
|
-
}
|
|
106881
|
-
return onFail(code);
|
|
106882
|
-
};
|
|
106883
|
-
return next;
|
|
106884
|
-
}
|
|
106885
|
-
return start;
|
|
106886
|
-
function start(code) {
|
|
106887
|
-
if (code !== codes.lessThan)
|
|
106888
|
-
return nok(code);
|
|
106889
|
-
effects.enter('htmlBlockComponent');
|
|
106890
|
-
effects.enter('htmlBlockComponentData');
|
|
106891
|
-
effects.consume(code);
|
|
106892
|
-
return matchTagName(afterTagName, nok);
|
|
106893
|
-
}
|
|
106894
|
-
function afterTagName(code) {
|
|
106895
|
-
if (code === codes.greaterThan) {
|
|
106896
|
-
effects.consume(code);
|
|
106897
|
-
return body;
|
|
106898
|
-
}
|
|
106899
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
106900
|
-
effects.consume(code);
|
|
106901
|
-
return inAttributes;
|
|
106902
|
-
}
|
|
106903
|
-
if (mode === 'flow' && markdownLineEnding(code)) {
|
|
106904
|
-
effects.exit('htmlBlockComponentData');
|
|
106905
|
-
return attributeContinuationStart(code);
|
|
106906
|
-
}
|
|
106907
|
-
if (code === codes.slash) {
|
|
106908
|
-
effects.consume(code);
|
|
106909
|
-
return selfClose;
|
|
106910
|
-
}
|
|
106911
|
-
return nok(code);
|
|
106912
|
-
}
|
|
106913
|
-
function inAttributes(code) {
|
|
106914
|
-
if (code === codes.greaterThan) {
|
|
106915
|
-
effects.consume(code);
|
|
106916
|
-
return body;
|
|
106917
|
-
}
|
|
106918
|
-
if (code === null) {
|
|
106919
|
-
return nok(code);
|
|
106920
|
-
}
|
|
106921
|
-
if (markdownLineEnding(code)) {
|
|
106922
|
-
if (mode === 'text')
|
|
106923
|
-
return nok(code);
|
|
106924
|
-
effects.exit('htmlBlockComponentData');
|
|
106925
|
-
return attributeContinuationStart(code);
|
|
106926
|
-
}
|
|
106927
|
-
effects.consume(code);
|
|
106928
|
-
return inAttributes;
|
|
106929
|
-
}
|
|
106930
|
-
function attributeContinuationStart(code) {
|
|
106931
|
-
return effects.check(html_block_component_syntax_nonLazyContinuationStart, attributeContinuationNonLazy, continuationAfter)(code);
|
|
106932
|
-
}
|
|
106933
|
-
function attributeContinuationNonLazy(code) {
|
|
106934
|
-
effects.enter(types_types.lineEnding);
|
|
106935
|
-
effects.consume(code);
|
|
106936
|
-
effects.exit(types_types.lineEnding);
|
|
106937
|
-
return attributeContinuationBefore;
|
|
106938
|
-
}
|
|
106939
|
-
function attributeContinuationBefore(code) {
|
|
106940
|
-
if (code === null || markdownLineEnding(code)) {
|
|
106941
|
-
return attributeContinuationStart(code);
|
|
106942
|
-
}
|
|
106943
|
-
effects.enter('htmlBlockComponentData');
|
|
106944
|
-
return inAttributes(code);
|
|
106945
|
-
}
|
|
106946
|
-
function selfClose(code) {
|
|
106947
|
-
if (code === codes.greaterThan) {
|
|
106948
|
-
effects.consume(code);
|
|
106949
|
-
return mode === 'flow' ? afterClose : done(code);
|
|
106950
|
-
}
|
|
106951
|
-
return nok(code);
|
|
106952
|
-
}
|
|
106953
|
-
function body(code) {
|
|
106954
|
-
if (code === null)
|
|
106955
|
-
return nok(code);
|
|
106956
|
-
if (markdownLineEnding(code)) {
|
|
106957
|
-
if (mode === 'text') {
|
|
106958
|
-
// Text constructs operate on paragraph content which spans lines
|
|
106959
|
-
effects.consume(code);
|
|
106960
|
-
return body;
|
|
106961
|
-
}
|
|
106962
|
-
effects.exit('htmlBlockComponentData');
|
|
106963
|
-
return continuationStart(code);
|
|
106964
|
-
}
|
|
106965
|
-
if (code === codes.lessThan) {
|
|
106966
|
-
effects.consume(code);
|
|
106967
|
-
return closeSlash;
|
|
106968
|
-
}
|
|
106969
|
-
effects.consume(code);
|
|
106970
|
-
return body;
|
|
106971
|
-
}
|
|
106972
|
-
function closeSlash(code) {
|
|
106973
|
-
if (code === codes.slash) {
|
|
106974
|
-
effects.consume(code);
|
|
106975
|
-
return matchTagName(closeGt, body);
|
|
106976
|
-
}
|
|
106977
|
-
return matchTagName(openAfterTagName, body)(code);
|
|
106978
|
-
}
|
|
106979
|
-
function openAfterTagName(code) {
|
|
106980
|
-
if (code === codes.greaterThan || code === codes.space || code === codes.horizontalTab) {
|
|
106981
|
-
depth += 1;
|
|
106982
|
-
effects.consume(code);
|
|
106983
|
-
return body;
|
|
106984
|
-
}
|
|
106985
|
-
return body(code);
|
|
106986
|
-
}
|
|
106987
|
-
function closeGt(code) {
|
|
106988
|
-
if (code === codes.greaterThan) {
|
|
106989
|
-
depth -= 1;
|
|
106990
|
-
effects.consume(code);
|
|
106991
|
-
if (depth === 0) {
|
|
106992
|
-
return mode === 'flow' ? afterClose : done(code);
|
|
106993
|
-
}
|
|
106994
|
-
return body;
|
|
106995
|
-
}
|
|
106996
|
-
return body(code);
|
|
106997
|
-
}
|
|
106998
|
-
// -- flow-only states ---------------------------------------------------
|
|
106999
|
-
function afterClose(code) {
|
|
107000
|
-
if (code === null || markdownLineEnding(code)) {
|
|
107001
|
-
return done(code);
|
|
107002
|
-
}
|
|
107003
|
-
if (code === codes.space || code === codes.horizontalTab) {
|
|
107004
|
-
effects.consume(code);
|
|
107005
|
-
return afterClose;
|
|
107006
|
-
}
|
|
107007
|
-
// Reject so the block re-parses as a paragraph, deferring to the
|
|
107008
|
-
// text tokenizer which preserves trailing content in the same line.
|
|
107009
|
-
return nok(code);
|
|
107010
|
-
}
|
|
107011
|
-
// -- flow-only: line continuation ---------------------------------------
|
|
107012
|
-
function continuationStart(code) {
|
|
107013
|
-
return effects.check(html_block_component_syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
|
|
107014
|
-
}
|
|
107015
|
-
function continuationStartNonLazy(code) {
|
|
107016
|
-
effects.enter(types_types.lineEnding);
|
|
107017
|
-
effects.consume(code);
|
|
107018
|
-
effects.exit(types_types.lineEnding);
|
|
107019
|
-
return continuationBefore;
|
|
107020
|
-
}
|
|
107021
|
-
function continuationBefore(code) {
|
|
107022
|
-
if (code === null || markdownLineEnding(code)) {
|
|
107023
|
-
return continuationStart(code);
|
|
107024
|
-
}
|
|
107025
|
-
effects.enter('htmlBlockComponentData');
|
|
107026
|
-
return body(code);
|
|
107027
|
-
}
|
|
107028
|
-
function continuationAfter(code) {
|
|
107029
|
-
if (code === null)
|
|
107030
|
-
return nok(code);
|
|
107031
|
-
effects.exit('htmlBlockComponent');
|
|
107032
|
-
return ok(code);
|
|
107033
|
-
}
|
|
107034
|
-
// -- shared exit --------------------------------------------------------
|
|
107035
|
-
function done(_code) {
|
|
107036
|
-
effects.exit('htmlBlockComponentData');
|
|
107037
|
-
effects.exit('htmlBlockComponent');
|
|
107038
|
-
return ok(_code);
|
|
107039
|
-
}
|
|
107040
|
-
};
|
|
107041
|
-
}
|
|
107042
|
-
// ---------------------------------------------------------------------------
|
|
107043
|
-
// Flow construct (block-level)
|
|
107044
|
-
// ---------------------------------------------------------------------------
|
|
107045
|
-
const html_block_component_syntax_nonLazyContinuationStart = {
|
|
107046
|
-
tokenize: html_block_component_syntax_tokenizeNonLazyContinuationStart,
|
|
107047
|
-
partial: true,
|
|
107048
|
-
};
|
|
107049
|
-
function resolveToHtmlBlockComponent(events) {
|
|
107050
|
-
let index = events.length;
|
|
107051
|
-
while (index > 0) {
|
|
107052
|
-
index -= 1;
|
|
107053
|
-
if (events[index][0] === 'enter' && events[index][1].type === 'htmlBlockComponent') {
|
|
107054
|
-
break;
|
|
107055
|
-
}
|
|
107056
|
-
}
|
|
107057
|
-
if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
|
|
107058
|
-
events[index][1].start = events[index - 2][1].start;
|
|
107059
|
-
events[index + 1][1].start = events[index - 2][1].start;
|
|
107060
|
-
events.splice(index - 2, 2);
|
|
107061
|
-
}
|
|
107062
|
-
return events;
|
|
107063
|
-
}
|
|
107064
|
-
const htmlBlockComponentFlowConstruct = {
|
|
107065
|
-
name: 'htmlBlockComponent',
|
|
107066
|
-
tokenize: syntax_createTokenize('flow'),
|
|
107067
|
-
resolveTo: resolveToHtmlBlockComponent,
|
|
107068
|
-
concrete: true,
|
|
107069
|
-
};
|
|
107070
|
-
function html_block_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
107071
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
107072
|
-
const self = this;
|
|
107073
|
-
return start;
|
|
107074
|
-
function start(code) {
|
|
107075
|
-
if (markdownLineEnding(code)) {
|
|
107076
|
-
effects.enter(types_types.lineEnding);
|
|
107077
|
-
effects.consume(code);
|
|
107078
|
-
effects.exit(types_types.lineEnding);
|
|
107079
|
-
return after;
|
|
107080
|
-
}
|
|
107081
|
-
return nok(code);
|
|
107082
|
-
}
|
|
107083
|
-
function after(code) {
|
|
107084
|
-
if (self.parser.lazy[self.now().line]) {
|
|
107085
|
-
return nok(code);
|
|
107086
|
-
}
|
|
107087
|
-
return ok(code);
|
|
107088
|
-
}
|
|
107089
|
-
}
|
|
107090
|
-
// ---------------------------------------------------------------------------
|
|
107091
|
-
// Text construct (inline)
|
|
107092
|
-
// ---------------------------------------------------------------------------
|
|
107093
|
-
const htmlBlockComponentTextConstruct = {
|
|
107094
|
-
name: 'htmlBlockComponent',
|
|
107095
|
-
tokenize: syntax_createTokenize('text'),
|
|
107096
|
-
};
|
|
107097
|
-
// ---------------------------------------------------------------------------
|
|
107098
|
-
// Extension
|
|
107099
|
-
// ---------------------------------------------------------------------------
|
|
107100
|
-
function htmlBlockComponent() {
|
|
107101
|
-
return {
|
|
107102
|
-
flow: {
|
|
107103
|
-
[codes.lessThan]: [htmlBlockComponentFlowConstruct],
|
|
107104
|
-
},
|
|
107105
|
-
text: {
|
|
107106
|
-
[codes.lessThan]: [htmlBlockComponentTextConstruct],
|
|
107107
|
-
},
|
|
107108
|
-
};
|
|
107109
|
-
}
|
|
107110
|
-
|
|
107111
|
-
;// ./lib/micromark/html-block-component/index.ts
|
|
107112
|
-
|
|
107113
|
-
|
|
107114
107238
|
;// ./lib/utils/extractMagicBlocks.ts
|
|
107115
107239
|
/**
|
|
107116
107240
|
* The content matching in this regex captures everything between `[block:TYPE]`
|