@readme/markdown 14.4.0 → 14.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Callout/style.scss +7 -4
- package/components/Image/index.tsx +7 -2
- package/components/Image/style.scss +38 -3
- package/dist/index.d.ts +1 -1
- package/dist/lib/constants.d.ts +19 -0
- package/dist/lib/index.d.ts +1 -1
- package/dist/main.css +1 -1
- package/dist/main.css.map +1 -1
- package/dist/main.js +153 -39
- package/dist/main.node.js +153 -39
- package/dist/main.node.js.map +1 -1
- package/dist/processor/transform/mdxish/tables/repair-expression-escapes.d.ts +14 -0
- package/dist/processor/transform/mdxish/tables/tag-walker.d.ts +11 -1
- package/package.json +1 -1
- package/styles/gfm.scss +47 -21
package/dist/main.js
CHANGED
|
@@ -11594,6 +11594,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
11594
11594
|
__webpack_require__.d(__webpack_exports__, {
|
|
11595
11595
|
Components: () => (/* reexport */ components_namespaceObject),
|
|
11596
11596
|
FLOW_TYPES: () => (/* reexport */ FLOW_TYPES),
|
|
11597
|
+
INLINE_ONLY_PARENT_TYPES: () => (/* reexport */ INLINE_ONLY_PARENT_TYPES),
|
|
11597
11598
|
NodeTypes: () => (/* reexport */ NodeTypes),
|
|
11598
11599
|
Owlmoji: () => (/* reexport */ Owlmoji),
|
|
11599
11600
|
compile: () => (/* reexport */ lib_compile),
|
|
@@ -12254,13 +12255,17 @@ const Image = (Props) => {
|
|
|
12254
12255
|
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("i", { "aria-hidden": "true", className: "fa-solid fa-xmark" }))))) : null;
|
|
12255
12256
|
if (framed) {
|
|
12256
12257
|
const frameClass = `img-frame img-frame-${align || 'center'}`;
|
|
12258
|
+
// Left/right frames shrink to fit, so percentage widths can't resolve
|
|
12259
|
+
// against the parent, hoist onto the wrapper. Center frames are full-width.
|
|
12260
|
+
const isClamped = align === 'left' || align === 'right';
|
|
12261
|
+
const frameStyle = isClamped && typeof width === 'string' && width.endsWith('%') ? { width } : undefined;
|
|
12257
12262
|
if (children || caption) {
|
|
12258
|
-
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("figure", { className: frameClass },
|
|
12263
|
+
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("figure", { className: frameClass, style: frameStyle },
|
|
12259
12264
|
closedLightbox(alt || 'Expand image', imgElement),
|
|
12260
12265
|
lightboxOverlay,
|
|
12261
12266
|
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("figcaption", null, children || caption)));
|
|
12262
12267
|
}
|
|
12263
|
-
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("div", { className: frameClass },
|
|
12268
|
+
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("div", { className: frameClass, style: frameStyle },
|
|
12264
12269
|
closedLightbox(alt || 'Expand image', imgElement),
|
|
12265
12270
|
lightboxOverlay));
|
|
12266
12271
|
}
|
|
@@ -13061,6 +13066,34 @@ const FLOW_TYPES = new Set([
|
|
|
13061
13066
|
'table',
|
|
13062
13067
|
'thematicBreak',
|
|
13063
13068
|
]);
|
|
13069
|
+
/**
|
|
13070
|
+
* MDAST parent types whose children are restricted to inline content. A block-level
|
|
13071
|
+
* node placed inside any of these violates the parent's content model and breaks
|
|
13072
|
+
* downstream consumers
|
|
13073
|
+
*
|
|
13074
|
+
* Derived from the mdast spec. Seven of these are direct "phrasing content" parents:
|
|
13075
|
+
* - paragraph, heading, link, linkReference, emphasis, strong
|
|
13076
|
+
* - tableCell (phrasing minus Break)
|
|
13077
|
+
*
|
|
13078
|
+
* @link {https://github.com/syntax-tree/mdast}
|
|
13079
|
+
*
|
|
13080
|
+
* `delete` is GFM and has *transparent* content, see:
|
|
13081
|
+
* @link {https://github.com/syntax-tree/mdast-util-gfm-strikethrough}
|
|
13082
|
+
*
|
|
13083
|
+
* its children must also be phrasing, so it belongs here too.
|
|
13084
|
+
*
|
|
13085
|
+
* NOTE: exported so downstream consumers can reuse and not drift away
|
|
13086
|
+
*/
|
|
13087
|
+
const INLINE_ONLY_PARENT_TYPES = new Set([
|
|
13088
|
+
'paragraph',
|
|
13089
|
+
'heading',
|
|
13090
|
+
'tableCell',
|
|
13091
|
+
'link',
|
|
13092
|
+
'linkReference',
|
|
13093
|
+
'emphasis',
|
|
13094
|
+
'strong',
|
|
13095
|
+
'delete',
|
|
13096
|
+
]);
|
|
13064
13097
|
// HELPER CONSTANTS FOR MDXISH RENDERING
|
|
13065
13098
|
/**
|
|
13066
13099
|
* Inline-only custom components that appear as phrasing content within
|
|
@@ -75543,7 +75576,15 @@ const walkTags = (html, handlers) => {
|
|
|
75543
75576
|
const tagEnd = (parser) => (parser.endIndex ?? parser.startIndex) + 1;
|
|
75544
75577
|
const parser = new Parser_Parser({
|
|
75545
75578
|
onopentag(name) {
|
|
75546
|
-
|
|
75579
|
+
const start = parser.startIndex;
|
|
75580
|
+
const end = tagEnd(parser);
|
|
75581
|
+
handlers.onOpen?.({
|
|
75582
|
+
name,
|
|
75583
|
+
start,
|
|
75584
|
+
end,
|
|
75585
|
+
isSelfClosing: html[end - 2] === '/',
|
|
75586
|
+
isStrayCloser: html[start + 1] === '/',
|
|
75587
|
+
});
|
|
75547
75588
|
},
|
|
75548
75589
|
onclosetag(name, implicit) {
|
|
75549
75590
|
handlers.onClose?.({ name, start: parser.startIndex, end: tagEnd(parser), implicit });
|
|
@@ -75786,6 +75827,57 @@ const remapPositionsToOriginal = (tree, originalSource, inserts) => {
|
|
|
75786
75827
|
});
|
|
75787
75828
|
};
|
|
75788
75829
|
|
|
75830
|
+
;// ./processor/transform/mdxish/tables/repair-expression-escapes.ts
|
|
75831
|
+
|
|
75832
|
+
/**
|
|
75833
|
+
* mdxjs hands the contents of every `{…}` to acorn as a JavaScript expression.
|
|
75834
|
+
* A bare backslash is only legal inside a string/template literal in JS, so a
|
|
75835
|
+
* markdown-style escape such as `{customer\_id}` — common when authors escape an
|
|
75836
|
+
* underscore out of habit — makes acorn throw "Could not parse expression with
|
|
75837
|
+
* acorn", which drops parsing for the whole surrounding `<Table>`.
|
|
75838
|
+
*
|
|
75839
|
+
* This pass deletes backslashes that sit in JS *code* position inside a `{…}`
|
|
75840
|
+
* expression. Backslashes within a '…', "…" or `…` literal are valid escapes
|
|
75841
|
+
* and are left untouched. Scoped to the malformed-retry path; the happy path
|
|
75842
|
+
* never runs it.
|
|
75843
|
+
*/
|
|
75844
|
+
const repairExpressionEscapes = (html) => {
|
|
75845
|
+
const inserts = [];
|
|
75846
|
+
let braceDepth = 0;
|
|
75847
|
+
// Active string/template delimiter while scanning inside an expression, or null.
|
|
75848
|
+
let stringChar = null;
|
|
75849
|
+
for (let i = 0; i < html.length; i += 1) {
|
|
75850
|
+
const ch = html[i];
|
|
75851
|
+
if (stringChar) {
|
|
75852
|
+
// Inside a JS string/template literal a backslash escapes the next char
|
|
75853
|
+
// and is valid, so skip the pair untouched (this also prevents an escaped
|
|
75854
|
+
// quote from prematurely closing the literal).
|
|
75855
|
+
if (ch === '\\') {
|
|
75856
|
+
i += 1;
|
|
75857
|
+
}
|
|
75858
|
+
else if (ch === stringChar) {
|
|
75859
|
+
stringChar = null;
|
|
75860
|
+
}
|
|
75861
|
+
}
|
|
75862
|
+
else if (braceDepth > 0 && (ch === '"' || ch === "'" || ch === '`')) {
|
|
75863
|
+
stringChar = ch;
|
|
75864
|
+
}
|
|
75865
|
+
else if (ch === '{') {
|
|
75866
|
+
braceDepth += 1;
|
|
75867
|
+
}
|
|
75868
|
+
else if (ch === '}') {
|
|
75869
|
+
if (braceDepth > 0)
|
|
75870
|
+
braceDepth -= 1;
|
|
75871
|
+
}
|
|
75872
|
+
else if (braceDepth > 0 && ch === '\\') {
|
|
75873
|
+
// A backslash in code position inside an expression is always a syntax
|
|
75874
|
+
// error; delete it so acorn can parse the remaining expression.
|
|
75875
|
+
inserts.push({ offset: i, text: '', consumes: 1 });
|
|
75876
|
+
}
|
|
75877
|
+
}
|
|
75878
|
+
return applyInserts(html, inserts);
|
|
75879
|
+
};
|
|
75880
|
+
|
|
75789
75881
|
;// ./node_modules/html-tags/html-tags.json
|
|
75790
75882
|
const html_tags_namespaceObject = /*#__PURE__*/JSON.parse('["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","label","legend","li","link","main","map","mark","math","menu","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","script","search","section","select","selectedcontent","slot","small","source","span","strong","style","sub","summary","sup","svg","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"]');
|
|
75791
75883
|
// EXTERNAL MODULE: ./node_modules/react-html-attributes/dist/index.js
|
|
@@ -75912,13 +76004,6 @@ const isStandardHtmlTag = (name) => STANDARD_HTML_TAGS.has(name.toLowerCase());
|
|
|
75912
76004
|
// (htmlparser2) handles attribute parsing; this scan only needs to locate
|
|
75913
76005
|
// orphan closers, which can't appear inside an attribute value anyway.
|
|
75914
76006
|
const HTML_TAG_TOKEN_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9-]*)\b[^>]*>/g;
|
|
75915
|
-
/**
|
|
75916
|
-
* htmlparser2 silently drops closing tags that have no matching opener
|
|
75917
|
-
* (e.g. the trailing `</li>` in `<ul><li>x</ul></li>`), leaving them in the
|
|
75918
|
-
* source makes mdxjs choke on the dangling closer. Scan the masked
|
|
75919
|
-
* source for `</name>` tokens that don't pair with any prior unmatched
|
|
75920
|
-
* `<name>` and return their spans so the caller can drop them.
|
|
75921
|
-
*/
|
|
75922
76007
|
const findOrphanClosers = (html) => {
|
|
75923
76008
|
const masked = maskNonTagRegions(html);
|
|
75924
76009
|
const stack = [];
|
|
@@ -75927,18 +76012,30 @@ const findOrphanClosers = (html) => {
|
|
|
75927
76012
|
let match;
|
|
75928
76013
|
while ((match = HTML_TAG_TOKEN_RE.exec(masked)) !== null) {
|
|
75929
76014
|
const name = match[2].toLowerCase();
|
|
75930
|
-
// Non-HTML names and void elements are handled by the main walker.
|
|
75931
76015
|
// eslint-disable-next-line no-continue
|
|
75932
|
-
if (!isStandardHtmlTag(name)
|
|
76016
|
+
if (!isStandardHtmlTag(name))
|
|
76017
|
+
continue;
|
|
76018
|
+
// Special case for <br>: htmlparser2 will normalize orphan </br> to <br>
|
|
76019
|
+
// so we don't need to handle it here.
|
|
76020
|
+
// eslint-disable-next-line no-continue
|
|
76021
|
+
if (name === 'br' && match[1] === '/')
|
|
75933
76022
|
continue;
|
|
76023
|
+
const isVoid = HTML_VOID_ELEMENTS.has(name);
|
|
75934
76024
|
if (match[1] === '/') {
|
|
76025
|
+
// Other void closers (`</hr>`, `</img>`, ...) have no HTML5 rewrite rule
|
|
76026
|
+
// and must be stripped before the strict mdxjs parse runs.
|
|
76027
|
+
if (isVoid) {
|
|
76028
|
+
orphans.push({ offset: match.index, length: match[0].length });
|
|
76029
|
+
// eslint-disable-next-line no-continue
|
|
76030
|
+
continue;
|
|
76031
|
+
}
|
|
75935
76032
|
const idx = stack.lastIndexOf(name);
|
|
75936
76033
|
if (idx === -1)
|
|
75937
76034
|
orphans.push({ offset: match.index, length: match[0].length });
|
|
75938
76035
|
else
|
|
75939
76036
|
stack.length = idx;
|
|
75940
76037
|
}
|
|
75941
|
-
else if (!match[0].endsWith('/>')) {
|
|
76038
|
+
else if (!isVoid && !match[0].endsWith('/>')) {
|
|
75942
76039
|
stack.push(name);
|
|
75943
76040
|
}
|
|
75944
76041
|
}
|
|
@@ -75971,7 +76068,7 @@ const repairUnclosedTags = (html) => {
|
|
|
75971
76068
|
const inserts = [];
|
|
75972
76069
|
const openTags = [];
|
|
75973
76070
|
walkTags(html, {
|
|
75974
|
-
onOpen({ name, start, end }) {
|
|
76071
|
+
onOpen({ name, start, end, isSelfClosing, isStrayCloser }) {
|
|
75975
76072
|
// Escape non-HTML names (custom components, typos, `<arbitrary-tag>`)
|
|
75976
76073
|
// so MDX treats them as literal text instead of expecting a closer
|
|
75977
76074
|
if (!isStandardHtmlTag(name)) {
|
|
@@ -75979,12 +76076,19 @@ const repairUnclosedTags = (html) => {
|
|
|
75979
76076
|
return;
|
|
75980
76077
|
}
|
|
75981
76078
|
if (HTML_VOID_ELEMENTS.has(name.toLowerCase())) {
|
|
75982
|
-
// MDX requires void elements to be self-closing (`<br/>`, not `<br>`)
|
|
75983
|
-
//
|
|
75984
|
-
|
|
75985
|
-
|
|
75986
|
-
|
|
76079
|
+
// MDX requires void elements to be self-closing (`<br/>`, not `<br>`)
|
|
76080
|
+
// so we need to rewrite them to self closing tags.
|
|
76081
|
+
if (isStrayCloser) {
|
|
76082
|
+
// htmlparser2 may normalize some stray closers like `</br>` into opener
|
|
76083
|
+
// events <br> per the HTML5 spec. In this case remove the closing /
|
|
76084
|
+
// and fully rewrite the tag to self closing.
|
|
76085
|
+
inserts.push({ offset: start, text: `<${name}/>`, consumes: end - start });
|
|
76086
|
+
return;
|
|
76087
|
+
}
|
|
76088
|
+
else if (!isSelfClosing) {
|
|
76089
|
+
// Slots in the / right before the closing >
|
|
75987
76090
|
inserts.push({ offset: end - 1, text: '/' });
|
|
76091
|
+
}
|
|
75988
76092
|
return;
|
|
75989
76093
|
}
|
|
75990
76094
|
openTags.push({ name, start, end });
|
|
@@ -76024,6 +76128,7 @@ const repairUnclosedTags = (html) => {
|
|
|
76024
76128
|
|
|
76025
76129
|
|
|
76026
76130
|
|
|
76131
|
+
|
|
76027
76132
|
|
|
76028
76133
|
const isTableCell = (node) => isMDXElement(node) && ['th', 'td'].includes(node.name);
|
|
76029
76134
|
const tableTypes = {
|
|
@@ -76035,6 +76140,9 @@ const tableTypes = {
|
|
|
76035
76140
|
// register them manually so we control ordering against our other tokenizers.
|
|
76036
76141
|
// The fallback omits these so blank-line-separated markdown inside cells still
|
|
76037
76142
|
// parses when mdxjs throws on malformed JSX.
|
|
76143
|
+
//
|
|
76144
|
+
// mdx parsing is used because it heavily simplifies the parsing of the table structure;
|
|
76145
|
+
// it can identify the rows and cells. The heavy lifting is done by it
|
|
76038
76146
|
const buildTableNodeProcessor = (withMdx) => unified()
|
|
76039
76147
|
.data('micromarkExtensions', [...(withMdx ? [mdxjs()] : []), syntax_gemoji(), legacyVariable()])
|
|
76040
76148
|
.data('fromMarkdownExtensions', [
|
|
@@ -76269,22 +76377,29 @@ const mdxishTables = () => tree => {
|
|
|
76269
76377
|
// Main logic to transform table node to its parts
|
|
76270
76378
|
// Because the processor uses remarkMdx, it is stricter in what it accepts
|
|
76271
76379
|
// and only accepts valid MDX syntax. in the table node.
|
|
76272
|
-
// To get around that, we have some fallback logics after trying to repair the table content
|
|
76380
|
+
// To get around that, we have some fallback logics after trying to repair the table content.
|
|
76273
76381
|
let parsed = parseTableNode(tableNodeProcessor, node);
|
|
76274
76382
|
if (!parsed) {
|
|
76275
|
-
//
|
|
76276
|
-
|
|
76277
|
-
|
|
76278
|
-
|
|
76279
|
-
|
|
76280
|
-
|
|
76281
|
-
|
|
76282
|
-
|
|
76283
|
-
|
|
76284
|
-
|
|
76285
|
-
|
|
76383
|
+
// Try a sequence of targeted repairs and re-parse
|
|
76384
|
+
// after each, stopping at the first that yields a parseable tree:
|
|
76385
|
+
// - repairUnclosedTags: unclosed/orphan HTML tags
|
|
76386
|
+
// - normalizeTagSpacing: a line mixing text and an opening tag
|
|
76387
|
+
// (e.g. `text <div> \n <div> text`)
|
|
76388
|
+
// - repairExpressionEscapes: backslash escapes inside a `{…}` expression
|
|
76389
|
+
// These repairs are created after seeing real customer content that has failed to parse
|
|
76390
|
+
const repairs = [
|
|
76391
|
+
repairUnclosedTags,
|
|
76392
|
+
normalizeTagSpacing,
|
|
76393
|
+
repairExpressionEscapes,
|
|
76394
|
+
];
|
|
76395
|
+
// Stops at the first repair that yields a parseable tree
|
|
76396
|
+
repairs.some(repair => {
|
|
76397
|
+
const { value, inserts } = repair(node.value);
|
|
76398
|
+
if (value !== node.value) {
|
|
76399
|
+
parsed = parseTableNode(tableNodeProcessor, { ...node, value }, { inserts, originalSource: node.value });
|
|
76286
76400
|
}
|
|
76287
|
-
|
|
76401
|
+
return Boolean(parsed);
|
|
76402
|
+
});
|
|
76288
76403
|
}
|
|
76289
76404
|
if (parsed) {
|
|
76290
76405
|
// If the table is parsed successfully, we can now process it further
|
|
@@ -76305,6 +76420,8 @@ const mdxishTables = () => tree => {
|
|
|
76305
76420
|
return;
|
|
76306
76421
|
parent.children.splice(index, 1, ...fallback.children);
|
|
76307
76422
|
}
|
|
76423
|
+
// Otherwise, there's no point in trying to parse the table content further
|
|
76424
|
+
// More repairs are needed in that case
|
|
76308
76425
|
});
|
|
76309
76426
|
return tree;
|
|
76310
76427
|
};
|
|
@@ -103402,6 +103519,7 @@ const mdxishHtmlBlocks = () => tree => {
|
|
|
103402
103519
|
|
|
103403
103520
|
|
|
103404
103521
|
|
|
103522
|
+
|
|
103405
103523
|
function toImageAlign(value) {
|
|
103406
103524
|
if (value === 'left' || value === 'center' || value === 'right') {
|
|
103407
103525
|
return value;
|
|
@@ -103954,16 +104072,12 @@ const mdxishJsxToMdast = () => tree => {
|
|
|
103954
104072
|
parent.children[index] = newNode;
|
|
103955
104073
|
}
|
|
103956
104074
|
});
|
|
103957
|
-
//
|
|
103958
|
-
//
|
|
104075
|
+
// Promote magic-block images (type: 'image') to image-block, except inside inline-only
|
|
104076
|
+
// parents where the image must stay inline (authors use `<Image caption="…" />` instead).
|
|
103959
104077
|
visit(tree, 'image', (node, index, parent) => {
|
|
103960
104078
|
if (!parent || index === undefined)
|
|
103961
104079
|
return SKIP;
|
|
103962
|
-
if (parent.type
|
|
103963
|
-
return SKIP;
|
|
103964
|
-
// `` in any tableCell stays inline. Authors who want a captioned figure use
|
|
103965
|
-
// `<Image caption="…" />` JSX, which becomes `image-block` via `COMPONENT_MAP` above.
|
|
103966
|
-
if (parent.type === 'tableCell')
|
|
104080
|
+
if (INLINE_ONLY_PARENT_TYPES.has(parent.type))
|
|
103967
104081
|
return SKIP;
|
|
103968
104082
|
const newNode = transformMagicBlockImage(node);
|
|
103969
104083
|
parent.children[index] = newNode;
|
package/dist/main.node.js
CHANGED
|
@@ -19278,6 +19278,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
19278
19278
|
__webpack_require__.d(__webpack_exports__, {
|
|
19279
19279
|
Components: () => (/* reexport */ components_namespaceObject),
|
|
19280
19280
|
FLOW_TYPES: () => (/* reexport */ FLOW_TYPES),
|
|
19281
|
+
INLINE_ONLY_PARENT_TYPES: () => (/* reexport */ INLINE_ONLY_PARENT_TYPES),
|
|
19281
19282
|
NodeTypes: () => (/* reexport */ NodeTypes),
|
|
19282
19283
|
Owlmoji: () => (/* reexport */ Owlmoji),
|
|
19283
19284
|
compile: () => (/* reexport */ lib_compile),
|
|
@@ -24880,13 +24881,17 @@ const Image = (Props) => {
|
|
|
24880
24881
|
external_react_.createElement("i", { "aria-hidden": "true", className: "fa-solid fa-xmark" }))))) : null;
|
|
24881
24882
|
if (framed) {
|
|
24882
24883
|
const frameClass = `img-frame img-frame-${align || 'center'}`;
|
|
24884
|
+
// Left/right frames shrink to fit, so percentage widths can't resolve
|
|
24885
|
+
// against the parent, hoist onto the wrapper. Center frames are full-width.
|
|
24886
|
+
const isClamped = align === 'left' || align === 'right';
|
|
24887
|
+
const frameStyle = isClamped && typeof width === 'string' && width.endsWith('%') ? { width } : undefined;
|
|
24883
24888
|
if (children || caption) {
|
|
24884
|
-
return (external_react_.createElement("figure", { className: frameClass },
|
|
24889
|
+
return (external_react_.createElement("figure", { className: frameClass, style: frameStyle },
|
|
24885
24890
|
closedLightbox(alt || 'Expand image', imgElement),
|
|
24886
24891
|
lightboxOverlay,
|
|
24887
24892
|
external_react_.createElement("figcaption", null, children || caption)));
|
|
24888
24893
|
}
|
|
24889
|
-
return (external_react_.createElement("div", { className: frameClass },
|
|
24894
|
+
return (external_react_.createElement("div", { className: frameClass, style: frameStyle },
|
|
24890
24895
|
closedLightbox(alt || 'Expand image', imgElement),
|
|
24891
24896
|
lightboxOverlay));
|
|
24892
24897
|
}
|
|
@@ -25634,6 +25639,34 @@ const FLOW_TYPES = new Set([
|
|
|
25634
25639
|
'table',
|
|
25635
25640
|
'thematicBreak',
|
|
25636
25641
|
]);
|
|
25642
|
+
/**
|
|
25643
|
+
* MDAST parent types whose children are restricted to inline content. A block-level
|
|
25644
|
+
* node placed inside any of these violates the parent's content model and breaks
|
|
25645
|
+
* downstream consumers
|
|
25646
|
+
*
|
|
25647
|
+
* Derived from the mdast spec. Seven of these are direct "phrasing content" parents:
|
|
25648
|
+
* - paragraph, heading, link, linkReference, emphasis, strong
|
|
25649
|
+
* - tableCell (phrasing minus Break)
|
|
25650
|
+
*
|
|
25651
|
+
* @link {https://github.com/syntax-tree/mdast}
|
|
25652
|
+
*
|
|
25653
|
+
* `delete` is GFM and has *transparent* content, see:
|
|
25654
|
+
* @link {https://github.com/syntax-tree/mdast-util-gfm-strikethrough}
|
|
25655
|
+
*
|
|
25656
|
+
* its children must also be phrasing, so it belongs here too.
|
|
25657
|
+
*
|
|
25658
|
+
* NOTE: exported so downstream consumers can reuse and not drift away
|
|
25659
|
+
*/
|
|
25660
|
+
const INLINE_ONLY_PARENT_TYPES = new Set([
|
|
25661
|
+
'paragraph',
|
|
25662
|
+
'heading',
|
|
25663
|
+
'tableCell',
|
|
25664
|
+
'link',
|
|
25665
|
+
'linkReference',
|
|
25666
|
+
'emphasis',
|
|
25667
|
+
'strong',
|
|
25668
|
+
'delete',
|
|
25669
|
+
]);
|
|
25637
25670
|
// HELPER CONSTANTS FOR MDXISH RENDERING
|
|
25638
25671
|
/**
|
|
25639
25672
|
* Inline-only custom components that appear as phrasing content within
|
|
@@ -95767,7 +95800,15 @@ const walkTags = (html, handlers) => {
|
|
|
95767
95800
|
const tagEnd = (parser) => (parser.endIndex ?? parser.startIndex) + 1;
|
|
95768
95801
|
const parser = new Parser_Parser({
|
|
95769
95802
|
onopentag(name) {
|
|
95770
|
-
|
|
95803
|
+
const start = parser.startIndex;
|
|
95804
|
+
const end = tagEnd(parser);
|
|
95805
|
+
handlers.onOpen?.({
|
|
95806
|
+
name,
|
|
95807
|
+
start,
|
|
95808
|
+
end,
|
|
95809
|
+
isSelfClosing: html[end - 2] === '/',
|
|
95810
|
+
isStrayCloser: html[start + 1] === '/',
|
|
95811
|
+
});
|
|
95771
95812
|
},
|
|
95772
95813
|
onclosetag(name, implicit) {
|
|
95773
95814
|
handlers.onClose?.({ name, start: parser.startIndex, end: tagEnd(parser), implicit });
|
|
@@ -96010,6 +96051,57 @@ const remapPositionsToOriginal = (tree, originalSource, inserts) => {
|
|
|
96010
96051
|
});
|
|
96011
96052
|
};
|
|
96012
96053
|
|
|
96054
|
+
;// ./processor/transform/mdxish/tables/repair-expression-escapes.ts
|
|
96055
|
+
|
|
96056
|
+
/**
|
|
96057
|
+
* mdxjs hands the contents of every `{…}` to acorn as a JavaScript expression.
|
|
96058
|
+
* A bare backslash is only legal inside a string/template literal in JS, so a
|
|
96059
|
+
* markdown-style escape such as `{customer\_id}` — common when authors escape an
|
|
96060
|
+
* underscore out of habit — makes acorn throw "Could not parse expression with
|
|
96061
|
+
* acorn", which drops parsing for the whole surrounding `<Table>`.
|
|
96062
|
+
*
|
|
96063
|
+
* This pass deletes backslashes that sit in JS *code* position inside a `{…}`
|
|
96064
|
+
* expression. Backslashes within a '…', "…" or `…` literal are valid escapes
|
|
96065
|
+
* and are left untouched. Scoped to the malformed-retry path; the happy path
|
|
96066
|
+
* never runs it.
|
|
96067
|
+
*/
|
|
96068
|
+
const repairExpressionEscapes = (html) => {
|
|
96069
|
+
const inserts = [];
|
|
96070
|
+
let braceDepth = 0;
|
|
96071
|
+
// Active string/template delimiter while scanning inside an expression, or null.
|
|
96072
|
+
let stringChar = null;
|
|
96073
|
+
for (let i = 0; i < html.length; i += 1) {
|
|
96074
|
+
const ch = html[i];
|
|
96075
|
+
if (stringChar) {
|
|
96076
|
+
// Inside a JS string/template literal a backslash escapes the next char
|
|
96077
|
+
// and is valid, so skip the pair untouched (this also prevents an escaped
|
|
96078
|
+
// quote from prematurely closing the literal).
|
|
96079
|
+
if (ch === '\\') {
|
|
96080
|
+
i += 1;
|
|
96081
|
+
}
|
|
96082
|
+
else if (ch === stringChar) {
|
|
96083
|
+
stringChar = null;
|
|
96084
|
+
}
|
|
96085
|
+
}
|
|
96086
|
+
else if (braceDepth > 0 && (ch === '"' || ch === "'" || ch === '`')) {
|
|
96087
|
+
stringChar = ch;
|
|
96088
|
+
}
|
|
96089
|
+
else if (ch === '{') {
|
|
96090
|
+
braceDepth += 1;
|
|
96091
|
+
}
|
|
96092
|
+
else if (ch === '}') {
|
|
96093
|
+
if (braceDepth > 0)
|
|
96094
|
+
braceDepth -= 1;
|
|
96095
|
+
}
|
|
96096
|
+
else if (braceDepth > 0 && ch === '\\') {
|
|
96097
|
+
// A backslash in code position inside an expression is always a syntax
|
|
96098
|
+
// error; delete it so acorn can parse the remaining expression.
|
|
96099
|
+
inserts.push({ offset: i, text: '', consumes: 1 });
|
|
96100
|
+
}
|
|
96101
|
+
}
|
|
96102
|
+
return applyInserts(html, inserts);
|
|
96103
|
+
};
|
|
96104
|
+
|
|
96013
96105
|
;// ./node_modules/html-tags/html-tags.json
|
|
96014
96106
|
const html_tags_namespaceObject = /*#__PURE__*/JSON.parse('["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","label","legend","li","link","main","map","mark","math","menu","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","script","search","section","select","selectedcontent","slot","small","source","span","strong","style","sub","summary","sup","svg","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"]');
|
|
96015
96107
|
// EXTERNAL MODULE: ./node_modules/react-html-attributes/dist/index.js
|
|
@@ -96136,13 +96228,6 @@ const isStandardHtmlTag = (name) => STANDARD_HTML_TAGS.has(name.toLowerCase());
|
|
|
96136
96228
|
// (htmlparser2) handles attribute parsing; this scan only needs to locate
|
|
96137
96229
|
// orphan closers, which can't appear inside an attribute value anyway.
|
|
96138
96230
|
const HTML_TAG_TOKEN_RE = /<(\/)?([a-zA-Z][a-zA-Z0-9-]*)\b[^>]*>/g;
|
|
96139
|
-
/**
|
|
96140
|
-
* htmlparser2 silently drops closing tags that have no matching opener
|
|
96141
|
-
* (e.g. the trailing `</li>` in `<ul><li>x</ul></li>`), leaving them in the
|
|
96142
|
-
* source makes mdxjs choke on the dangling closer. Scan the masked
|
|
96143
|
-
* source for `</name>` tokens that don't pair with any prior unmatched
|
|
96144
|
-
* `<name>` and return their spans so the caller can drop them.
|
|
96145
|
-
*/
|
|
96146
96231
|
const findOrphanClosers = (html) => {
|
|
96147
96232
|
const masked = maskNonTagRegions(html);
|
|
96148
96233
|
const stack = [];
|
|
@@ -96151,18 +96236,30 @@ const findOrphanClosers = (html) => {
|
|
|
96151
96236
|
let match;
|
|
96152
96237
|
while ((match = HTML_TAG_TOKEN_RE.exec(masked)) !== null) {
|
|
96153
96238
|
const name = match[2].toLowerCase();
|
|
96154
|
-
// Non-HTML names and void elements are handled by the main walker.
|
|
96155
96239
|
// eslint-disable-next-line no-continue
|
|
96156
|
-
if (!isStandardHtmlTag(name)
|
|
96240
|
+
if (!isStandardHtmlTag(name))
|
|
96241
|
+
continue;
|
|
96242
|
+
// Special case for <br>: htmlparser2 will normalize orphan </br> to <br>
|
|
96243
|
+
// so we don't need to handle it here.
|
|
96244
|
+
// eslint-disable-next-line no-continue
|
|
96245
|
+
if (name === 'br' && match[1] === '/')
|
|
96157
96246
|
continue;
|
|
96247
|
+
const isVoid = HTML_VOID_ELEMENTS.has(name);
|
|
96158
96248
|
if (match[1] === '/') {
|
|
96249
|
+
// Other void closers (`</hr>`, `</img>`, ...) have no HTML5 rewrite rule
|
|
96250
|
+
// and must be stripped before the strict mdxjs parse runs.
|
|
96251
|
+
if (isVoid) {
|
|
96252
|
+
orphans.push({ offset: match.index, length: match[0].length });
|
|
96253
|
+
// eslint-disable-next-line no-continue
|
|
96254
|
+
continue;
|
|
96255
|
+
}
|
|
96159
96256
|
const idx = stack.lastIndexOf(name);
|
|
96160
96257
|
if (idx === -1)
|
|
96161
96258
|
orphans.push({ offset: match.index, length: match[0].length });
|
|
96162
96259
|
else
|
|
96163
96260
|
stack.length = idx;
|
|
96164
96261
|
}
|
|
96165
|
-
else if (!match[0].endsWith('/>')) {
|
|
96262
|
+
else if (!isVoid && !match[0].endsWith('/>')) {
|
|
96166
96263
|
stack.push(name);
|
|
96167
96264
|
}
|
|
96168
96265
|
}
|
|
@@ -96195,7 +96292,7 @@ const repairUnclosedTags = (html) => {
|
|
|
96195
96292
|
const inserts = [];
|
|
96196
96293
|
const openTags = [];
|
|
96197
96294
|
walkTags(html, {
|
|
96198
|
-
onOpen({ name, start, end }) {
|
|
96295
|
+
onOpen({ name, start, end, isSelfClosing, isStrayCloser }) {
|
|
96199
96296
|
// Escape non-HTML names (custom components, typos, `<arbitrary-tag>`)
|
|
96200
96297
|
// so MDX treats them as literal text instead of expecting a closer
|
|
96201
96298
|
if (!isStandardHtmlTag(name)) {
|
|
@@ -96203,12 +96300,19 @@ const repairUnclosedTags = (html) => {
|
|
|
96203
96300
|
return;
|
|
96204
96301
|
}
|
|
96205
96302
|
if (HTML_VOID_ELEMENTS.has(name.toLowerCase())) {
|
|
96206
|
-
// MDX requires void elements to be self-closing (`<br/>`, not `<br>`)
|
|
96207
|
-
//
|
|
96208
|
-
|
|
96209
|
-
|
|
96210
|
-
|
|
96303
|
+
// MDX requires void elements to be self-closing (`<br/>`, not `<br>`)
|
|
96304
|
+
// so we need to rewrite them to self closing tags.
|
|
96305
|
+
if (isStrayCloser) {
|
|
96306
|
+
// htmlparser2 may normalize some stray closers like `</br>` into opener
|
|
96307
|
+
// events <br> per the HTML5 spec. In this case remove the closing /
|
|
96308
|
+
// and fully rewrite the tag to self closing.
|
|
96309
|
+
inserts.push({ offset: start, text: `<${name}/>`, consumes: end - start });
|
|
96310
|
+
return;
|
|
96311
|
+
}
|
|
96312
|
+
else if (!isSelfClosing) {
|
|
96313
|
+
// Slots in the / right before the closing >
|
|
96211
96314
|
inserts.push({ offset: end - 1, text: '/' });
|
|
96315
|
+
}
|
|
96212
96316
|
return;
|
|
96213
96317
|
}
|
|
96214
96318
|
openTags.push({ name, start, end });
|
|
@@ -96248,6 +96352,7 @@ const repairUnclosedTags = (html) => {
|
|
|
96248
96352
|
|
|
96249
96353
|
|
|
96250
96354
|
|
|
96355
|
+
|
|
96251
96356
|
|
|
96252
96357
|
const isTableCell = (node) => isMDXElement(node) && ['th', 'td'].includes(node.name);
|
|
96253
96358
|
const tableTypes = {
|
|
@@ -96259,6 +96364,9 @@ const tableTypes = {
|
|
|
96259
96364
|
// register them manually so we control ordering against our other tokenizers.
|
|
96260
96365
|
// The fallback omits these so blank-line-separated markdown inside cells still
|
|
96261
96366
|
// parses when mdxjs throws on malformed JSX.
|
|
96367
|
+
//
|
|
96368
|
+
// mdx parsing is used because it heavily simplifies the parsing of the table structure;
|
|
96369
|
+
// it can identify the rows and cells. The heavy lifting is done by it
|
|
96262
96370
|
const buildTableNodeProcessor = (withMdx) => unified()
|
|
96263
96371
|
.data('micromarkExtensions', [...(withMdx ? [mdxjs()] : []), syntax_gemoji(), legacyVariable()])
|
|
96264
96372
|
.data('fromMarkdownExtensions', [
|
|
@@ -96493,22 +96601,29 @@ const mdxishTables = () => tree => {
|
|
|
96493
96601
|
// Main logic to transform table node to its parts
|
|
96494
96602
|
// Because the processor uses remarkMdx, it is stricter in what it accepts
|
|
96495
96603
|
// and only accepts valid MDX syntax. in the table node.
|
|
96496
|
-
// To get around that, we have some fallback logics after trying to repair the table content
|
|
96604
|
+
// To get around that, we have some fallback logics after trying to repair the table content.
|
|
96497
96605
|
let parsed = parseTableNode(tableNodeProcessor, node);
|
|
96498
96606
|
if (!parsed) {
|
|
96499
|
-
//
|
|
96500
|
-
|
|
96501
|
-
|
|
96502
|
-
|
|
96503
|
-
|
|
96504
|
-
|
|
96505
|
-
|
|
96506
|
-
|
|
96507
|
-
|
|
96508
|
-
|
|
96509
|
-
|
|
96607
|
+
// Try a sequence of targeted repairs and re-parse
|
|
96608
|
+
// after each, stopping at the first that yields a parseable tree:
|
|
96609
|
+
// - repairUnclosedTags: unclosed/orphan HTML tags
|
|
96610
|
+
// - normalizeTagSpacing: a line mixing text and an opening tag
|
|
96611
|
+
// (e.g. `text <div> \n <div> text`)
|
|
96612
|
+
// - repairExpressionEscapes: backslash escapes inside a `{…}` expression
|
|
96613
|
+
// These repairs are created after seeing real customer content that has failed to parse
|
|
96614
|
+
const repairs = [
|
|
96615
|
+
repairUnclosedTags,
|
|
96616
|
+
normalizeTagSpacing,
|
|
96617
|
+
repairExpressionEscapes,
|
|
96618
|
+
];
|
|
96619
|
+
// Stops at the first repair that yields a parseable tree
|
|
96620
|
+
repairs.some(repair => {
|
|
96621
|
+
const { value, inserts } = repair(node.value);
|
|
96622
|
+
if (value !== node.value) {
|
|
96623
|
+
parsed = parseTableNode(tableNodeProcessor, { ...node, value }, { inserts, originalSource: node.value });
|
|
96510
96624
|
}
|
|
96511
|
-
|
|
96625
|
+
return Boolean(parsed);
|
|
96626
|
+
});
|
|
96512
96627
|
}
|
|
96513
96628
|
if (parsed) {
|
|
96514
96629
|
// If the table is parsed successfully, we can now process it further
|
|
@@ -96529,6 +96644,8 @@ const mdxishTables = () => tree => {
|
|
|
96529
96644
|
return;
|
|
96530
96645
|
parent.children.splice(index, 1, ...fallback.children);
|
|
96531
96646
|
}
|
|
96647
|
+
// Otherwise, there's no point in trying to parse the table content further
|
|
96648
|
+
// More repairs are needed in that case
|
|
96532
96649
|
});
|
|
96533
96650
|
return tree;
|
|
96534
96651
|
};
|
|
@@ -123626,6 +123743,7 @@ const mdxishHtmlBlocks = () => tree => {
|
|
|
123626
123743
|
|
|
123627
123744
|
|
|
123628
123745
|
|
|
123746
|
+
|
|
123629
123747
|
function toImageAlign(value) {
|
|
123630
123748
|
if (value === 'left' || value === 'center' || value === 'right') {
|
|
123631
123749
|
return value;
|
|
@@ -124178,16 +124296,12 @@ const mdxishJsxToMdast = () => tree => {
|
|
|
124178
124296
|
parent.children[index] = newNode;
|
|
124179
124297
|
}
|
|
124180
124298
|
});
|
|
124181
|
-
//
|
|
124182
|
-
//
|
|
124299
|
+
// Promote magic-block images (type: 'image') to image-block, except inside inline-only
|
|
124300
|
+
// parents where the image must stay inline (authors use `<Image caption="…" />` instead).
|
|
124183
124301
|
visit(tree, 'image', (node, index, parent) => {
|
|
124184
124302
|
if (!parent || index === undefined)
|
|
124185
124303
|
return SKIP;
|
|
124186
|
-
if (parent.type
|
|
124187
|
-
return SKIP;
|
|
124188
|
-
// `` in any tableCell stays inline. Authors who want a captioned figure use
|
|
124189
|
-
// `<Image caption="…" />` JSX, which becomes `image-block` via `COMPONENT_MAP` above.
|
|
124190
|
-
if (parent.type === 'tableCell')
|
|
124304
|
+
if (INLINE_ONLY_PARENT_TYPES.has(parent.type))
|
|
124191
124305
|
return SKIP;
|
|
124192
124306
|
const newNode = transformMagicBlockImage(node);
|
|
124193
124307
|
parent.children[index] = newNode;
|