@readme/markdown 15.0.1 → 15.1.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.
@@ -0,0 +1,11 @@
1
+ import type { Transform } from 'mdast-util-from-markdown';
2
+ /**
3
+ * Rewrites JSX attribute expressions (`icon={String(1 + 3)}`) into plain string attributes
4
+ * holding their literal source, so nothing downstream can evaluate them.
5
+ *
6
+ * This is the RMDX counterpart to mdxish's `preserveExpressionsAsText` parse option: safeMode's
7
+ * contract is enforced once, at the head of the pipeline, rather than at every `getAttrs()` call
8
+ * site. Only registered when safeMode is on.
9
+ */
10
+ declare const flattenAttributeExpressions: () => Transform;
11
+ export default flattenAttributeExpressions;
@@ -1,5 +1,6 @@
1
1
  import compatabilityTransfomer from './compatability';
2
2
  import divTransformer from './div';
3
+ import flattenAttributeExpressions from './flatten-attribute-expressions';
3
4
  import handleMissingComponents from './handle-missing-components';
4
5
  import injectComponents from './inject-components';
5
6
  import mdxToHast from './mdx-to-hast';
@@ -11,7 +12,7 @@ import tablesToJsx from './tables-to-jsx';
11
12
  import tailwindTransformer from './tailwind';
12
13
  import validateMCPIntro from './validate-mcpintro';
13
14
  import variablesTransformer from './variables';
14
- export { compatabilityTransfomer, divTransformer, injectComponents, mdxToHast, mdxishTables, mermaidTransformer, readmeComponentsTransformer, readmeToMdx, tablesToJsx, tailwindTransformer, handleMissingComponents, validateMCPIntro, variablesTransformer, };
15
+ export { compatabilityTransfomer, divTransformer, flattenAttributeExpressions, injectComponents, mdxToHast, mdxishTables, mermaidTransformer, readmeComponentsTransformer, readmeToMdx, tablesToJsx, tailwindTransformer, handleMissingComponents, validateMCPIntro, variablesTransformer, };
15
16
  export declare const defaultTransforms: {
16
17
  calloutTransformer: ({ isMdxish }?: {
17
18
  isMdxish?: boolean;
@@ -1,6 +1,6 @@
1
1
  .Accordion{background:rgba(var(--color-bg-page-rgb, white), 1);border:1px solid var(--color-border-default, rgba(0, 0, 0, 0.1));border-radius:5px}.Accordion-title{align-items:center;background:rgba(var(--color-bg-page-rgb, white), 1);border:0;border-radius:5px;color:var(--color-text-default, #384248);cursor:pointer;display:flex;font-size:16px;font-weight:500;padding:10px;position:relative;text-align:left;width:100%}.Accordion-title:hover{background:var(--color-bg-hover, rgba(0, 0, 0, 0.05))}.Accordion[open] .Accordion-title{border-bottom-left-radius:0;border-bottom-right-radius:0}.Accordion-title::marker{content:""}.Accordion-title::-webkit-details-marker{display:none}.Accordion-toggleIcon,.Accordion-toggleIcon_opened{color:var(--color-text-minimum, #637288);font-size:14px;margin-left:5px;margin-right:10px;transition:transform .1s}.Accordion-toggleIcon_opened,.Accordion-toggleIcon_opened_opened{transform:rotate(90deg)}.Accordion-icon{color:var(--project-color-primary, inherit);margin-right:10px}.Accordion-content{color:var(--color-text-muted, #4f5a66);padding:5px 15px 0 15px}.Accordion-content>*{margin-bottom:var(--markdown-spacing, 15px)}
2
- .CardsGrid{--CardsGrid-gap: 1.5em;--CardsGrid-columns: auto-fit;--CardsGrid-cardWidth: auto;display:grid;gap:var(--CardsGrid-gap);grid-template-columns:repeat(var(--CardsGrid-columns), minmax(var(--CardsGrid-cardWidth), 1fr))}.Card{--Card-badge-bg-color: var(--yellow);--Card-badge-color: var(--yellow10);--Card-content-color: var(--color-text-minimum);--Card-gap: 0.25em;--Card-href-arrow-opacity: 0;--Card-href-arrow-transform: translateX(-5px);--Card-icon-color: var(--color-text-default);--Card-icon-opacity: 0.65;--Card-icon-opacity-hover: 0.75;--Card-line-height: 1.4;--Card-shadow: none;--Card-title-color: var(--color-text-default);background:var(--Card-bg-color);border:1px solid var(--Card-border-color);border-radius:var(--border-radius-lg);box-shadow:var(--Card-shadow);display:flex;flex-direction:var(--Card-layout);gap:var(--Card-gap);line-height:var(--Card-line-height);padding:var(--Card-padding);text-decoration:none}.Card_card{--Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0);--Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0);--Card-border-color: var(--color-border-default);--Card-layout: column;--Card-padding: 1.5em}[data-color-mode=dark] .Card_card{--Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0.05);--Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0.1)}@media(prefers-color-scheme: dark){[data-color-mode=auto] .Card_card,[data-color-mode=system] .Card_card{--Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0.05);--Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0.1)}}.Card_tile{--Card-gap: 1em;--Card-icon-opacity: 0.5;--Card-layout: row}.Card_tile .Card-content{--Card-gap: 0}.Card[href]:not([href=""]){color:inherit;text-decoration:none}.Card[href]:not([href=""]):hover,.Card[href]:not([href=""]):active,.Card[href]:not([href=""]):focus{--Card-icon-opacity: var(--Card-icon-opacity-hover);--Card-href-arrow-opacity: 0.75;--Card-href-arrow-transform: none;background:var(--Card-bg-color-hover)}.Card-icon{color:var(--Card-icon-color);font-size:1.4em;margin-bottom:.5em;opacity:var(--Card-icon-opacity);transition:opacity var(--transition-timing) var(--transition-fast)}.Card-title{align-items:flex-start;color:var(--Card-title-color);display:flex;gap:.5em;font-weight:var(--font-weight-bold)}.Card-badge{align-items:center;background:var(--Card-badge-bg-color);border-radius:1em;color:var(--Card-badge-color);font-size:.6em;padding:0 .5em;display:inline-flex;position:relative;top:.5em}.Card-arrow{font-size:.8em;opacity:var(--Card-href-arrow-opacity);position:relative;top:.375em;transition:opacity var(--transition-timing) var(--transition-fast),transform var(--transition-timing) var(--transition-fast);transform:var(--Card-href-arrow-transform)}.Card-content{color:var(--Card-content-color);display:flex;flex-direction:column;font-size:1em;gap:var(--Card-gap)}.Card-content p:last-child{margin-bottom:0}
2
+ .CardsGrid{--CardsGrid-gap: 1.5em;--CardsGrid-columns: auto-fit;--CardsGrid-cardWidth: auto;display:grid;gap:var(--CardsGrid-gap);grid-template-columns:repeat(var(--CardsGrid-columns), minmax(var(--CardsGrid-cardWidth), 1fr))}.Card{--Card-badge-bg-color: var(--yellow);--Card-badge-color: var(--yellow10);--Card-content-color: var(--color-text-minimum);--Card-gap: 0.25em;--Card-href-arrow-opacity: 0;--Card-href-arrow-transform: translateX(-5px);--Card-icon-color: var(--color-text-default);--Card-icon-opacity: 0.65;--Card-icon-opacity-hover: 0.75;--Card-line-height: 1.4;--Card-shadow: none;--Card-title-color: var(--color-text-default);background:var(--Card-bg-color);border:1px solid var(--Card-border-color);border-radius:var(--border-radius-lg);box-shadow:var(--Card-shadow);display:flex;flex-direction:var(--Card-layout);gap:var(--Card-gap);line-height:var(--Card-line-height);padding:var(--Card-padding);text-decoration:none}.Card_card{--Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0);--Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0);--Card-border-color: var(--color-border-default);--Card-layout: column;--Card-padding: 1.5em}.rm-ReadMe[data-color-mode=dark] .Card_card{--Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0.05);--Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0.1)}@media(prefers-color-scheme: dark){.rm-ReadMe[data-color-mode=system] .Card_card{--Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0.05);--Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0.1)}}.Card_tile{--Card-gap: 1em;--Card-icon-opacity: 0.5;--Card-layout: row}.Card_tile .Card-content{--Card-gap: 0}.Card[href]:not([href=""]){color:inherit;text-decoration:none}.Card[href]:not([href=""]):hover,.Card[href]:not([href=""]):active,.Card[href]:not([href=""]):focus{--Card-icon-opacity: var(--Card-icon-opacity-hover);--Card-href-arrow-opacity: 0.75;--Card-href-arrow-transform: none;background:var(--Card-bg-color-hover)}.Card-icon{color:var(--Card-icon-color);font-size:1.4em;margin-bottom:.5em;opacity:var(--Card-icon-opacity);transition:opacity var(--transition-timing) var(--transition-fast)}.Card-title{align-items:flex-start;color:var(--Card-title-color);display:flex;gap:.5em;font-weight:var(--font-weight-bold)}.Card-badge{align-items:center;background:var(--Card-badge-bg-color);border-radius:1em;color:var(--Card-badge-color);font-size:.6em;padding:0 .5em;display:inline-flex;position:relative;top:.5em}.Card-arrow{font-size:.8em;opacity:var(--Card-href-arrow-opacity);position:relative;top:.375em;transition:opacity var(--transition-timing) var(--transition-fast),transform var(--transition-timing) var(--transition-fast);transform:var(--Card-href-arrow-transform)}.Card-content{color:var(--Card-content-color);display:flex;flex-direction:column;font-size:1em;gap:var(--Card-gap)}.Card-content p:last-child{margin-bottom:0}
3
3
  .Columns{display:grid;gap:var(--md, 20px)}@media(max-width: 414px){.Columns{grid-template-columns:1fr !important}}
4
- .TabGroup-nav{border-bottom:solid var(--color-border-default, rgba(0, 0, 0, 0.1));margin-bottom:15px}.TabGroup-tab{background:none;border:0;color:var(--color-text-minimum, #637288);cursor:pointer;font-size:15px;font-weight:600;margin-right:15px;padding:0;padding-bottom:10px}.TabGroup-tab_active{background:none;border:0;border-bottom:solid var(--color-tab-active, currentcolor);color:var(--color-tab-active, currentcolor);font-size:15px;font-weight:600;margin-right:15px;margin-bottom:-2px;padding:0;padding-bottom:10px}.TabGroup-tab:hover{color:var(--color-text-muted, #4f5a66)}.TabGroup-icon{color:var(--project-color-primary, inherit);margin-right:10px}.TabGroup .TabContent{color:var(--color-text-muted, #4f5a66)}
4
+ .TabGroup-nav{border-bottom:solid var(--color-border-default, rgba(0, 0, 0, 0.1));margin-bottom:15px}.TabGroup-tab{background:none;border:0;color:var(--color-text-minimum, #637288);cursor:pointer;font-size:15px;font-weight:600;margin-right:15px;padding:0;padding-bottom:10px}.TabGroup-tab_active{background:none;border:0;border-bottom:solid var(--color-tab-active, currentcolor);color:var(--color-tab-active, currentcolor);font-size:15px;font-weight:600;margin-right:15px;margin-bottom:-2px;padding:0;padding-bottom:10px}.TabGroup-tab:hover{color:var(--color-text-muted, #4f5a66)}.TabGroup-icon{color:var(--project-color-primary, inherit);margin-right:10px}.TabGroup .TabContent{color:var(--color-text-muted, #4f5a66)}:where(.TabGroup .TabContent>*:not(:last-child)){margin-bottom:var(--markdown-spacing, 15px)}
5
5
 
6
6
  /*# sourceMappingURL=render-fixture.css.map*/
@@ -1 +1 @@
1
- {"version":3,"file":"render-fixture.css","mappings":"AAAA,WACE,oDACA,iEACA,kBAEA,iBACE,mBACA,oDACA,SACA,kBACA,yCACA,eACA,aACA,eACA,gBACA,aACA,kBACA,gBACA,WAEA,uBACE,sDAGF,kCACE,4BACA,6BAGF,yBACE,WAGF,yCACE,aAIJ,mDAEE,yCACA,eACA,gBACA,kBACA,yBAEA,iEACE,wBAIJ,gBACE,4CACA,kBAGF,mBACE,uCACA,wBAEA,qBACE,4C;ACzDN,WACE,uBACA,8BACA,4BAEA,aACA,yBACA,gGAGF,MAGE,qCACA,oCACA,gDACA,mBACA,6BACA,8CACA,6CACA,0BACA,gCACA,wBACA,oBACA,8CAEA,gCACA,0CACA,sCACA,8BACA,aACA,kCACA,oBACA,oCACA,4BACA,qBAEA,WACE,2DACA,iEACA,iDACA,sBACA,sBCXA,kCDcE,8DACA,mECTA,mCAFF,sEDUE,8DACA,oEAIJ,WACE,gBACA,yBACA,mBAEA,yBACE,cAKJ,2BACE,cACA,qBAEA,oGAGE,oDACA,gCACA,kCAEA,sCAIJ,WACE,6BACA,gBACA,mBACA,iCACA,mEAGF,YACE,uBACA,8BACA,aACA,SACA,oCAGF,YACE,mBACA,sCACA,kBACA,8BACA,eACA,eACA,oBACA,kBACA,SAGF,YACE,eACA,uCACA,kBACA,WACA,4HACE,CAEF,2CAGF,cACE,gCACA,aACA,sBACA,cACA,oBAEA,2BACE,gB;AE7HN,SACE,aACA,oBAEA,yBAJF,SAKI,sC;ACNF,cACE,oEACA,mBAGF,cACE,gBACA,SACA,yCACA,eACA,eACA,gBACA,kBACA,UACA,oBAEA,qBACE,gBACA,SACA,0DACA,4CACA,eACA,gBACA,kBACA,mBACA,UACA,oBAGF,oBACE,uCAIJ,eACE,4CACA,kBAGF,sBACE,uC","sources":["webpack://@readme/markdown/./components/Accordion/style.scss","webpack://@readme/markdown/./components/Cards/style.scss","webpack://@readme/markdown/./styles/mixins/dark-mode.scss","webpack://@readme/markdown/./components/Columns/style.scss","webpack://@readme/markdown/./components/Tabs/style.scss"],"sourcesContent":[".Accordion {\n background: rgba(var(--color-bg-page-rgb, white), 1);\n border: 1px solid var(--color-border-default, rgba(black, 0.1));\n border-radius: 5px;\n\n &-title {\n align-items: center;\n background: rgba(var(--color-bg-page-rgb, white), 1);\n border: 0;\n border-radius: 5px;\n color: var(--color-text-default, #384248);\n cursor: pointer;\n display: flex;\n font-size: 16px;\n font-weight: 500;\n padding: 10px;\n position: relative;\n text-align: left;\n width: 100%;\n\n &:hover {\n background: var(--color-bg-hover, rgba(black, 0.05));\n }\n\n .Accordion[open] & {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n }\n\n &::marker {\n content: \"\";\n }\n\n &::-webkit-details-marker {\n display: none;\n } \n }\n\n &-toggleIcon,\n &-toggleIcon_opened {\n color: var(--color-text-minimum, #637288);\n font-size: 14px;\n margin-left: 5px;\n margin-right: 10px;\n transition: transform 0.1s;\n\n &_opened {\n transform: rotate(90deg);\n }\n }\n\n &-icon {\n color: var(--project-color-primary, inherit);\n margin-right: 10px;\n }\n\n &-content {\n color: var(--color-text-muted, #4f5a66);\n padding: 5px 15px 0 15px;\n\n > * {\n margin-bottom: var(--markdown-spacing, 15px);\n }\n }\n}\n","@import '../../styles/mixins/dark-mode.scss';\n\n$iphone-plus: 414px;\n\n.CardsGrid {\n --CardsGrid-gap: 1.5em;\n --CardsGrid-columns: auto-fit;\n --CardsGrid-cardWidth: auto;\n\n display: grid;\n gap: var(--CardsGrid-gap);\n grid-template-columns: repeat(var(--CardsGrid-columns), minmax(var(--CardsGrid-cardWidth), 1fr));\n}\n\n.Card {\n $card: &;\n\n --Card-badge-bg-color: var(--yellow);\n --Card-badge-color: var(--yellow10);\n --Card-content-color: var(--color-text-minimum);\n --Card-gap: 0.25em;\n --Card-href-arrow-opacity: 0;\n --Card-href-arrow-transform: translateX(-5px);\n --Card-icon-color: var(--color-text-default);\n --Card-icon-opacity: 0.65;\n --Card-icon-opacity-hover: 0.75;\n --Card-line-height: 1.4;\n --Card-shadow: none;\n --Card-title-color: var(--color-text-default);\n\n background: var(--Card-bg-color);\n border: 1px solid var(--Card-border-color);\n border-radius: var(--border-radius-lg);\n box-shadow: var(--Card-shadow);\n display: flex;\n flex-direction: var(--Card-layout);\n gap: var(--Card-gap);\n line-height: var(--Card-line-height);\n padding: var(--Card-padding);\n text-decoration: none;\n\n &_card {\n --Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0);\n --Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0);\n --Card-border-color: var(--color-border-default);\n --Card-layout: column;\n --Card-padding: 1.5em;\n\n @include dark-mode {\n --Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0.05);\n --Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0.1);\n }\n }\n\n &_tile {\n --Card-gap: 1em;\n --Card-icon-opacity: 0.5;\n --Card-layout: row;\n\n #{$card}-content {\n --Card-gap: 0;\n }\n }\n\n // needs specificity to override the default link styles; while preserving logic for empty hrefs\n &[href]:not([href='']) {\n color: inherit;\n text-decoration: none;\n\n &:hover,\n &:active,\n &:focus {\n --Card-icon-opacity: var(--Card-icon-opacity-hover);\n --Card-href-arrow-opacity: 0.75;\n --Card-href-arrow-transform: none;\n\n background: var(--Card-bg-color-hover);\n }\n }\n\n &-icon {\n color: var(--Card-icon-color);\n font-size: 1.4em;\n margin-bottom: 0.5em;\n opacity: var(--Card-icon-opacity);\n transition: opacity var(--transition-timing) var(--transition-fast);\n }\n\n &-title {\n align-items: flex-start;\n color: var(--Card-title-color);\n display: flex;\n gap: 0.5em;\n font-weight: var(--font-weight-bold);\n }\n\n &-badge {\n align-items: center;\n background: var(--Card-badge-bg-color);\n border-radius: 1em;\n color: var(--Card-badge-color);\n font-size: 0.6em;\n padding: 0 0.5em;\n display: inline-flex;\n position: relative;\n top: 0.5em;\n }\n\n &-arrow {\n font-size: 0.8em;\n opacity: var(--Card-href-arrow-opacity);\n position: relative;\n top: 0.375em;\n transition:\n opacity var(--transition-timing) var(--transition-fast),\n transform var(--transition-timing) var(--transition-fast);\n transform: var(--Card-href-arrow-transform);\n }\n\n &-content {\n color: var(--Card-content-color);\n display: flex;\n flex-direction: column;\n font-size: 1em;\n gap: var(--Card-gap);\n\n p:last-child {\n margin-bottom: 0;\n }\n }\n}\n","/* We’re planning to move this in to the monorepo in which case\n we could share the dark mode mix in. Kelly is planning to take\n some time to make that move so can we add a comment here to\n circle back on this at that point?\n\n - Rafe\n April 2025\n*/\n\n@mixin dark-mode($global: false) {\n $root: &;\n\n @if not $root {\n [data-color-mode='dark'] {\n @content;\n }\n\n [data-color-mode='auto'],\n [data-color-mode='system'] {\n @media (prefers-color-scheme: dark) {\n @content;\n }\n }\n } @else if $global {\n :global([data-color-mode='dark']) & {\n @content;\n }\n\n :global([data-color-mode='auto']) &,\n :global([data-color-mode='system']) & {\n @media (prefers-color-scheme: dark) {\n @content;\n }\n }\n } @else {\n [data-color-mode='dark'] & {\n @content;\n }\n\n [data-color-mode='auto'] &,\n [data-color-mode='system'] & {\n @media (prefers-color-scheme: dark) {\n @content;\n }\n }\n }\n}\n","$iphone-plus: 414px;\n\n.Columns {\n display: grid;\n gap: var(--md, 20px);\n\n @media (max-width: $iphone-plus) {\n grid-template-columns: 1fr !important;\n }\n}\n",".TabGroup {\n &-nav {\n border-bottom: solid var(--color-border-default, #{rgba(black, 0.1)});\n margin-bottom: 15px;\n }\n\n &-tab {\n background: none;\n border: 0;\n color: var(--color-text-minimum, #637288);\n cursor: pointer;\n font-size: 15px;\n font-weight: 600;\n margin-right: 15px;\n padding: 0;\n padding-bottom: 10px;\n\n &_active {\n background: none;\n border: 0;\n border-bottom: solid var(--color-tab-active, currentcolor);\n color: var(--color-tab-active, currentcolor);\n font-size: 15px;\n font-weight: 600;\n margin-right: 15px;\n margin-bottom: -2px;\n padding: 0;\n padding-bottom: 10px;\n }\n\n &:hover {\n color: var(--color-text-muted, #4f5a66);\n }\n }\n\n &-icon {\n color: var(--project-color-primary, inherit);\n margin-right: 10px;\n }\n\n .TabContent {\n color: var(--color-text-muted, #4f5a66);\n }\n}\n"],"names":[],"sourceRoot":""}
1
+ {"version":3,"file":"render-fixture.css","mappings":"AAAA,WACE,oDACA,iEACA,kBAEA,iBACE,mBACA,oDACA,SACA,kBACA,yCACA,eACA,aACA,eACA,gBACA,aACA,kBACA,gBACA,WAEA,uBACE,sDAGF,kCACE,4BACA,6BAGF,yBACE,WAGF,yCACE,aAIJ,mDAEE,yCACA,eACA,gBACA,kBACA,yBAEA,iEACE,wBAIJ,gBACE,4CACA,kBAGF,mBACE,uCACA,wBAEA,qBACE,4C;ACzDN,WACE,uBACA,8BACA,4BAEA,aACA,yBACA,gGAGF,MAGE,qCACA,oCACA,gDACA,mBACA,6BACA,8CACA,6CACA,0BACA,gCACA,wBACA,oBACA,8CAEA,gCACA,0CACA,sCACA,8BACA,aACA,kCACA,oBACA,oCACA,4BACA,qBAEA,WACE,2DACA,iEACA,iDACA,sBACA,sBCTA,4CDYE,8DACA,mECRA,mCADF,8CDQE,8DACA,oEAIJ,WACE,gBACA,yBACA,mBAEA,yBACE,cAKJ,2BACE,cACA,qBAEA,oGAGE,oDACA,gCACA,kCAEA,sCAIJ,WACE,6BACA,gBACA,mBACA,iCACA,mEAGF,YACE,uBACA,8BACA,aACA,SACA,oCAGF,YACE,mBACA,sCACA,kBACA,8BACA,eACA,eACA,oBACA,kBACA,SAGF,YACE,eACA,uCACA,kBACA,WACA,4HACE,CAEF,2CAGF,cACE,gCACA,aACA,sBACA,cACA,oBAEA,2BACE,gB;AE7HN,SACE,aACA,oBAEA,yBAJF,SAKI,sC;ACNF,cACE,oEACA,mBAGF,cACE,gBACA,SACA,yCACA,eACA,eACA,gBACA,kBACA,UACA,oBAEA,qBACE,gBACA,SACA,0DACA,4CACA,eACA,gBACA,kBACA,mBACA,UACA,oBAGF,oBACE,uCAIJ,eACE,4CACA,kBAGF,sBACE,uCAIJ,iDACE,4C","sources":["webpack://@readme/markdown/./components/Accordion/style.scss","webpack://@readme/markdown/./components/Cards/style.scss","webpack://@readme/markdown/./styles/mixins/when-color-mode-dark.scss","webpack://@readme/markdown/./components/Columns/style.scss","webpack://@readme/markdown/./components/Tabs/style.scss"],"sourcesContent":[".Accordion {\n background: rgba(var(--color-bg-page-rgb, white), 1);\n border: 1px solid var(--color-border-default, rgba(black, 0.1));\n border-radius: 5px;\n\n &-title {\n align-items: center;\n background: rgba(var(--color-bg-page-rgb, white), 1);\n border: 0;\n border-radius: 5px;\n color: var(--color-text-default, #384248);\n cursor: pointer;\n display: flex;\n font-size: 16px;\n font-weight: 500;\n padding: 10px;\n position: relative;\n text-align: left;\n width: 100%;\n\n &:hover {\n background: var(--color-bg-hover, rgba(black, 0.05));\n }\n\n .Accordion[open] & {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n }\n\n &::marker {\n content: \"\";\n }\n\n &::-webkit-details-marker {\n display: none;\n } \n }\n\n &-toggleIcon,\n &-toggleIcon_opened {\n color: var(--color-text-minimum, #637288);\n font-size: 14px;\n margin-left: 5px;\n margin-right: 10px;\n transition: transform 0.1s;\n\n &_opened {\n transform: rotate(90deg);\n }\n }\n\n &-icon {\n color: var(--project-color-primary, inherit);\n margin-right: 10px;\n }\n\n &-content {\n color: var(--color-text-muted, #4f5a66);\n padding: 5px 15px 0 15px;\n\n > * {\n margin-bottom: var(--markdown-spacing, 15px);\n }\n }\n}\n","@import '../../styles/mixins/when-color-mode-dark.scss';\n\n$iphone-plus: 414px;\n\n.CardsGrid {\n --CardsGrid-gap: 1.5em;\n --CardsGrid-columns: auto-fit;\n --CardsGrid-cardWidth: auto;\n\n display: grid;\n gap: var(--CardsGrid-gap);\n grid-template-columns: repeat(var(--CardsGrid-columns), minmax(var(--CardsGrid-cardWidth), 1fr));\n}\n\n.Card {\n $card: &;\n\n --Card-badge-bg-color: var(--yellow);\n --Card-badge-color: var(--yellow10);\n --Card-content-color: var(--color-text-minimum);\n --Card-gap: 0.25em;\n --Card-href-arrow-opacity: 0;\n --Card-href-arrow-transform: translateX(-5px);\n --Card-icon-color: var(--color-text-default);\n --Card-icon-opacity: 0.65;\n --Card-icon-opacity-hover: 0.75;\n --Card-line-height: 1.4;\n --Card-shadow: none;\n --Card-title-color: var(--color-text-default);\n\n background: var(--Card-bg-color);\n border: 1px solid var(--Card-border-color);\n border-radius: var(--border-radius-lg);\n box-shadow: var(--Card-shadow);\n display: flex;\n flex-direction: var(--Card-layout);\n gap: var(--Card-gap);\n line-height: var(--Card-line-height);\n padding: var(--Card-padding);\n text-decoration: none;\n\n &_card {\n --Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0);\n --Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0);\n --Card-border-color: var(--color-border-default);\n --Card-layout: column;\n --Card-padding: 1.5em;\n\n @include when-color-mode-dark('.rm-ReadMe') {\n --Card-bg-color: rgba(var(--color-bg-page-inverse-rgb), 0.05);\n --Card-bg-color-hover: rgba(var(--color-bg-page-inverse-rgb), 0.1);\n }\n }\n\n &_tile {\n --Card-gap: 1em;\n --Card-icon-opacity: 0.5;\n --Card-layout: row;\n\n #{$card}-content {\n --Card-gap: 0;\n }\n }\n\n // needs specificity to override the default link styles; while preserving logic for empty hrefs\n &[href]:not([href='']) {\n color: inherit;\n text-decoration: none;\n\n &:hover,\n &:active,\n &:focus {\n --Card-icon-opacity: var(--Card-icon-opacity-hover);\n --Card-href-arrow-opacity: 0.75;\n --Card-href-arrow-transform: none;\n\n background: var(--Card-bg-color-hover);\n }\n }\n\n &-icon {\n color: var(--Card-icon-color);\n font-size: 1.4em;\n margin-bottom: 0.5em;\n opacity: var(--Card-icon-opacity);\n transition: opacity var(--transition-timing) var(--transition-fast);\n }\n\n &-title {\n align-items: flex-start;\n color: var(--Card-title-color);\n display: flex;\n gap: 0.5em;\n font-weight: var(--font-weight-bold);\n }\n\n &-badge {\n align-items: center;\n background: var(--Card-badge-bg-color);\n border-radius: 1em;\n color: var(--Card-badge-color);\n font-size: 0.6em;\n padding: 0 0.5em;\n display: inline-flex;\n position: relative;\n top: 0.5em;\n }\n\n &-arrow {\n font-size: 0.8em;\n opacity: var(--Card-href-arrow-opacity);\n position: relative;\n top: 0.375em;\n transition:\n opacity var(--transition-timing) var(--transition-fast),\n transform var(--transition-timing) var(--transition-fast);\n transform: var(--Card-href-arrow-transform);\n }\n\n &-content {\n color: var(--Card-content-color);\n display: flex;\n flex-direction: column;\n font-size: 1em;\n gap: var(--Card-gap);\n\n p:last-child {\n margin-bottom: 0;\n }\n }\n}\n","/**\n * Dark styles keyed off `$root`'s own `data-color-mode`, not any ancestor.\n * Unlike `dark-mode` (which matches ANY ancestor carrying the attribute —\n * see the warning on that mixin), this only fires when `$root` itself\n * declares the dark/system mode. None of this package's components carry\n * `data-color-mode` on their own root, so callers must pass the selector\n * for whichever wrapper actually carries it in their consuming app — there\n * is no default.\n *\n * IMPORTANT: this package ships one precompiled `dist/main.css` — there is\n * no build step where a consumer can supply their own value for `$root`.\n * Whatever gets passed at each `@include` call site below is permanent for\n * every installer of this package. Call sites currently hardcode\n * `'.rm-ReadMe'`, readme's hub color-mode wrapper, because readme is this\n * package's only real consumer today. If that ever changes, this becomes\n * silently wrong (not an error — dark mode just never activates) for any\n * consumer without that exact class in their DOM, and `$root` should be\n * dropped in favor of each component resolving its own nearest\n * `[data-color-mode]` ancestor at mount via `Element.closest()` and\n * stamping it onto its own root, so the CSS can self-anchor with no\n * hardcoded selector at all.\n *\n * $global: wrap the root-anchor selector in :global(), for use when this\n * file is imported into a CSS-module context (mirrors `dark-mode`'s param).\n */\n@mixin when-color-mode-dark($root, $global: false) {\n @if $global {\n :global(#{$root}[data-color-mode='dark']) & {\n @content;\n }\n\n :global(#{$root}[data-color-mode='system']) & {\n @media (prefers-color-scheme: dark) {\n @content;\n }\n }\n } @else {\n #{$root}[data-color-mode='dark'] & {\n @content;\n }\n\n #{$root}[data-color-mode='system'] & {\n @media (prefers-color-scheme: dark) {\n @content;\n }\n }\n }\n}\n","$iphone-plus: 414px;\n\n.Columns {\n display: grid;\n gap: var(--md, 20px);\n\n @media (max-width: $iphone-plus) {\n grid-template-columns: 1fr !important;\n }\n}\n",".TabGroup {\n &-nav {\n border-bottom: solid var(--color-border-default, #{rgba(black, 0.1)});\n margin-bottom: 15px;\n }\n\n &-tab {\n background: none;\n border: 0;\n color: var(--color-text-minimum, #637288);\n cursor: pointer;\n font-size: 15px;\n font-weight: 600;\n margin-right: 15px;\n padding: 0;\n padding-bottom: 10px;\n\n &_active {\n background: none;\n border: 0;\n border-bottom: solid var(--color-tab-active, currentcolor);\n color: var(--color-tab-active, currentcolor);\n font-size: 15px;\n font-weight: 600;\n margin-right: 15px;\n margin-bottom: -2px;\n padding: 0;\n padding-bottom: 10px;\n }\n\n &:hover {\n color: var(--color-text-muted, #4f5a66);\n }\n }\n\n &-icon {\n color: var(--project-color-primary, inherit);\n margin-right: 10px;\n }\n\n .TabContent {\n color: var(--color-text-muted, #4f5a66);\n }\n}\n\n:where(.TabGroup .TabContent > *:not(:last-child)) {\n margin-bottom: var(--markdown-spacing, 15px);\n}\n"],"names":[],"sourceRoot":""}
@@ -68723,12 +68723,104 @@ const mdast_mdast = (text, opts = {}) => {
68723
68723
  */
68724
68724
  const jsxAcornParser = Parser.extend(acorn_jsx_default()());
68725
68725
 
68726
+ ;// ./lib/utils/literal-expression.ts
68727
+
68728
+ const unsupported = (description) => new Error(`not a literal expression: ${description}`);
68729
+ /** Narrows a resolved value for arithmetic, so operands never coerce to `NaN` or `"[object Object]"`. */
68730
+ const asNumber = (value) => {
68731
+ if (typeof value !== 'number')
68732
+ throw unsupported('non-numeric operand');
68733
+ return value;
68734
+ };
68735
+ const asOperand = (value) => {
68736
+ if (typeof value !== 'number' && typeof value !== 'string')
68737
+ throw unsupported('non-primitive operand');
68738
+ return value;
68739
+ };
68740
+ const ARITHMETIC_OPERATORS = {
68741
+ // `+` doubles as string concatenation, so it accepts a string on either side.
68742
+ '+': (left, right) => (typeof left === 'number' && typeof right === 'number' ? left + right : `${left}${right}`),
68743
+ '-': (left, right) => asNumber(left) - asNumber(right),
68744
+ '*': (left, right) => asNumber(left) * asNumber(right),
68745
+ '/': (left, right) => asNumber(left) / asNumber(right),
68746
+ };
68747
+ /** Resolve one estree node, recursing into arrays and objects. Throws for anything not on the allowlist. */
68748
+ const resolveNode = (node) => {
68749
+ switch (node.type) {
68750
+ case 'Literal':
68751
+ // Regex and bigint `Literal`s hold values a tree consumer can't serialise;
68752
+ // a BigInt throws outright in `JSON.stringify`.
68753
+ if ('regex' in node || 'bigint' in node)
68754
+ throw unsupported('regex or bigint literal');
68755
+ return node.value;
68756
+ case 'Identifier':
68757
+ if (node.name !== 'undefined')
68758
+ throw unsupported(`identifier \`${node.name}\``);
68759
+ return undefined;
68760
+ case 'TemplateLiteral':
68761
+ if (node.expressions.length)
68762
+ throw unsupported('template substitution');
68763
+ return node.quasis.map(quasi => quasi.value.cooked).join('');
68764
+ case 'UnaryExpression':
68765
+ if (node.operator !== '-')
68766
+ throw unsupported(`operator \`${node.operator}\``);
68767
+ return -asNumber(resolveNode(node.argument));
68768
+ case 'BinaryExpression': {
68769
+ const applyOperator = ARITHMETIC_OPERATORS[node.operator];
68770
+ if (!applyOperator)
68771
+ throw unsupported(`operator \`${node.operator}\``);
68772
+ return applyOperator(asOperand(resolveNode(node.left)), asOperand(resolveNode(node.right)));
68773
+ }
68774
+ case 'ArrayExpression':
68775
+ return node.elements.map(element => (element === null ? null : resolveNode(element)));
68776
+ case 'ObjectExpression':
68777
+ return node.properties.reduce((memo, property) => {
68778
+ if (property.type !== 'Property' || property.computed)
68779
+ throw unsupported('computed or spread property');
68780
+ const { key } = property;
68781
+ if (key.type !== 'Identifier' && key.type !== 'Literal')
68782
+ throw unsupported('property key');
68783
+ const name = key.type === 'Identifier' ? key.name : String(key.value);
68784
+ // `__proto__` would replace the object's prototype rather than add a property.
68785
+ if (name === '__proto__')
68786
+ throw unsupported('`__proto__` key');
68787
+ memo[name] = resolveNode(property.value);
68788
+ return memo;
68789
+ }, {});
68790
+ default:
68791
+ throw unsupported(node.type);
68792
+ }
68793
+ };
68794
+ /**
68795
+ * Resolve a JSX attribute expression's source to its value without executing it.
68796
+ *
68797
+ * Supports the literal syntax attributes actually use — `true`, `"a"`, `` `a` ``,
68798
+ * `undefined`, `{ textAlign: "left" }`, `["left"]`, `1 + 1`, `'https://' + 'x.com'` —
68799
+ * and refuses everything else, so no identifier, member access, call, assignment or
68800
+ * function body can ever run. The trade-off is that expressions needing a scope or a
68801
+ * method call (`{item.url}`, `{"a".toUpperCase()}`) throw, and callers keep the raw
68802
+ * source instead — the same fallback they already used for an expression that threw.
68803
+ * mdxish rendering is unaffected, since it resolves those later with its scoped
68804
+ * evaluator; only consumers reading attributes straight off the tree see the source.
68805
+ *
68806
+ * @param source expression body, without the surrounding braces
68807
+ * @throws if `source` is unparseable or isn't a supported literal expression
68808
+ */
68809
+ const evaluateLiteralExpression = (source) => {
68810
+ const expression = jsxAcornParser.parseExpressionAt(source, 0, { ecmaVersion: 'latest' });
68811
+ // acorn stops at the first complete expression, so anything trailing means this isn't one.
68812
+ if (expression.end !== source.trimEnd().length)
68813
+ throw unsupported('trailing content');
68814
+ return resolveNode(expression);
68815
+ };
68816
+
68726
68817
  ;// ./processor/utils.ts
68727
68818
 
68728
68819
 
68729
68820
 
68730
68821
 
68731
68822
 
68823
+
68732
68824
  /**
68733
68825
  * Evaluate a JavaScript expression source and return its value.
68734
68826
  *
@@ -68826,8 +68918,10 @@ const utils_getAttrs = (jsx) => jsx.attributes.reduce((memo, attr) => {
68826
68918
  memo[attr.name] = decode_decodeHTMLStrict(attr.value);
68827
68919
  }
68828
68920
  else if (attr.value?.value !== undefined) {
68921
+ // Expression values only survive to here when safeMode is off; `flattenAttributeExpressions`
68922
+ // rewrites them to plain strings at the head of the pipeline otherwise.
68829
68923
  try {
68830
- memo[attr.name] = evaluate(attr.value.value);
68924
+ memo[attr.name] = evaluateLiteralExpression(attr.value.value);
68831
68925
  }
68832
68926
  catch {
68833
68927
  memo[attr.name] = attr.value.value;
@@ -69608,6 +69702,31 @@ const embedTransformer = () => {
69608
69702
  };
69609
69703
  /* harmony default export */ const transform_embeds = (embedTransformer);
69610
69704
 
69705
+ ;// ./processor/transform/flatten-attribute-expressions.ts
69706
+
69707
+
69708
+ /**
69709
+ * Rewrites JSX attribute expressions (`icon={String(1 + 3)}`) into plain string attributes
69710
+ * holding their literal source, so nothing downstream can evaluate them.
69711
+ *
69712
+ * This is the RMDX counterpart to mdxish's `preserveExpressionsAsText` parse option: safeMode's
69713
+ * contract is enforced once, at the head of the pipeline, rather than at every `getAttrs()` call
69714
+ * site. Only registered when safeMode is on.
69715
+ */
69716
+ const flattenAttributeExpressions = () => tree => {
69717
+ lib_visit(tree, utils_isMDXElement, (node) => {
69718
+ node.attributes.forEach(attr => {
69719
+ if (!('name' in attr))
69720
+ return;
69721
+ if (attr.value === null || typeof attr.value === 'string')
69722
+ return;
69723
+ attr.value = attr.value.value;
69724
+ });
69725
+ });
69726
+ return tree;
69727
+ };
69728
+ /* harmony default export */ const flatten_attribute_expressions = (flattenAttributeExpressions);
69729
+
69611
69730
  ;// ./node_modules/gemoji/index.js
69612
69731
  /**
69613
69732
  * @typedef Gemoji
@@ -91991,6 +92110,9 @@ const GlossaryContext = (0,external_react_.createContext)([]);
91991
92110
 
91992
92111
 
91993
92112
 
92113
+ /** Tippy portals to document.body by default, which would break the
92114
+ * `.rm-ReadMe[data-color-mode] …` descendant selectors in style.scss. */
92115
+ const appendToReadMeRoot = (ref) => ref.closest('.rm-ReadMe') ?? document.body;
91994
92116
  const Glossary = ({ children, term: termProp, terms }) => {
91995
92117
  const term = (Array.isArray(children) ? children[0] : children) || termProp;
91996
92118
  if (!term)
@@ -91998,7 +92120,7 @@ const Glossary = ({ children, term: termProp, terms }) => {
91998
92120
  const foundTerm = terms.find(i => term.toLowerCase() === i?.term?.toLowerCase());
91999
92121
  if (!foundTerm)
92000
92122
  return external_react_default().createElement("span", null, term);
92001
- return (external_react_default().createElement(tippy_react_esm, { content: external_react_default().createElement("div", { className: "GlossaryItem-tooltip-content" },
92123
+ return (external_react_default().createElement(tippy_react_esm, { appendTo: appendToReadMeRoot, content: external_react_default().createElement("div", { className: "GlossaryItem-tooltip-content" },
92002
92124
  external_react_default().createElement("strong", { className: "GlossaryItem-term" }, foundTerm.term),
92003
92125
  " - ",
92004
92126
  foundTerm.definition), offset: [-5, 5], placement: "bottom-start" },
@@ -97128,13 +97250,36 @@ const MARKER_PATTERNS = [
97128
97250
  // Pattern for ** bold **
97129
97251
  // Groups: 1=wordBefore, 2=marker, 3=contentWithSpaceAfter, 4=trailingSpace1, 5=contentWithSpaceBefore, 6=trailingSpace2, 7=afterChar
97130
97252
  // trailingSpace1 is for "** text **" pattern, trailingSpace2 is for "**text **" pattern
97131
- const asteriskBoldRegex = /([^*\s]+)?\s*(\*\*)(?:\s+((?:[^*\n]|\*(?!\*))+?)(\s*)\2|((?:[^*\n]|\*(?!\*))+?)(\s+)\2)(\S|$)?/g;
97253
+ //
97254
+ // The wordBefore and whitespace prefixes are deliberately bounded ({1,64} /
97255
+ // {0,8}) rather than unbounded (+ / *). An unbounded prefix makes matchAll
97256
+ // re-scan an arbitrarily long run from every character position, which turns
97257
+ // the pass O(n²) on text nodes containing huge unbroken tokens (pasted base64
97258
+ // payloads, minified code). Bounding the prefix caps the backtracking per
97259
+ // position; a prefix longer than the bound just starts the match later, and
97260
+ // the cut-off chars flow into the preceding text node instead — adjacent text
97261
+ // parts are merged before splicing, so the emitted AST is unchanged.
97262
+ //
97263
+ // The content quantifiers are bounded too ({1,500}). The underscore content
97264
+ // clauses can scan across `_` (needed for snake_case content), so without a
97265
+ // bound every `_` in a marker-dense token (base64url, snake_case identifiers)
97266
+ // re-scans to end-of-line looking for a closer — O(n²) again. Content already
97267
+ // can't cross a newline, and 500 chars covers any sentence-length emphasis
97268
+ // phrase; longer spans stay unnormalized rather than costing quadratic scans.
97269
+ const asteriskBoldRegex = /([^*\s]{1,64})?\s{0,8}(\*\*)(?:\s+((?:[^*\n]|\*(?!\*)){1,500}?)(\s*)\2|((?:[^*\n]|\*(?!\*)){1,500}?)(\s+)\2)(\S|$)?/g;
97132
97270
  // Pattern for __ bold __
97133
- const underscoreBoldRegex = /([^_\s]+)?\s*(__)(?:\s+((?:__(?! )|_(?!_)|[^_\n])+?)(\s*)\2|((?:__(?! )|_(?!_)|[^_\n])+?)(\s+)\2)(\S|$)?/g;
97271
+ const underscoreBoldRegex = /([^_\s]{1,64})?\s{0,8}(__)(?:\s+((?:__(?! )|_(?!_)|[^_\n]){1,500}?)(\s*)\2|((?:__(?! )|_(?!_)|[^_\n]){1,500}?)(\s+)\2)(\S|$)?/g;
97134
97272
  // Pattern for * italic *
97135
- const asteriskItalicRegex = /([^*\s]+)?\s*(\*)(?!\*)(?:\s+([^*\n]+?)(\s*)\2|([^*\n]+?)(\s+)\2)(\S|$)?/g;
97273
+ const asteriskItalicRegex = /([^*\s]{1,64})?\s{0,8}(\*)(?!\*)(?:\s+([^*\n]{1,500}?)(\s*)\2|([^*\n]{1,500}?)(\s+)\2)(\S|$)?/g;
97136
97274
  // Pattern for _ italic _
97137
- const underscoreItalicRegex = /([^_\s]+)?\s*(_)(?!_)(?:\s+((?:[^_\n]|_(?! ))+?)(\s*)\2|((?:[^_\n]|_(?! ))+?)(\s+)\2)(\S|$)?/g;
97275
+ const underscoreItalicRegex = /([^_\s]{1,64})?\s{0,8}(_)(?!_)(?:\s+((?:[^_\n]|_(?! )){1,500}?)(\s*)\2|((?:[^_\n]|_(?! )){1,500}?)(\s+)\2)(\S|$)?/g;
97276
+ // Every loose alternation requires whitespace beside a marker — after the
97277
+ // opening (`** text**`) or before the closing (`**text **`) — so
97278
+ // marker-beside-whitespace is an exact gate for the loose families. A single
97279
+ // linear probe skips them entirely on marker-dense tokens whose markers are
97280
+ // all intraword (base64url payloads, snake_case identifiers).
97281
+ const asteriskBesideWhitespaceRegex = /\*\s|\s\*/;
97282
+ const underscoreBesideWhitespaceRegex = /_\s|\s_/;
97138
97283
  // CommonMark ignores intraword underscores or asteriks, but we want to italicize/bold the inner part
97139
97284
  // Pattern for intraword _word_ in words like hello_world_
97140
97285
  const intrawordUnderscoreItalicRegex = /(\w)_(?!_)([a-zA-Z0-9]+)_(?![\w_])/g;
@@ -97144,6 +97289,23 @@ const intrawordUnderscoreBoldRegex = /(\w)__([a-zA-Z0-9]+)__(?![\w_])/g;
97144
97289
  const intrawordAsteriskItalicRegex = /(\w)\*(?!\*)([a-zA-Z0-9]+)\*(?![\w*])/g;
97145
97290
  // Pattern for intraword **word** in words like hello**world**
97146
97291
  const intrawordAsteriskBoldRegex = /(\w)\*\*([a-zA-Z0-9]+)\*\*(?![\w*])/g;
97292
+ // All regex families, in match-precedence order: collected matches are
97293
+ // stable-sorted by match.index, so at an equal index the earlier row wins the
97294
+ // overlap filter — keep this order. `gate` names the per-node precondition
97295
+ // (see the gate record in the visitor) checked before the family's regex
97296
+ // runs, so a node that can't possibly match never pays for a full scan: the
97297
+ // intraword families need their marker character present, and the loose
97298
+ // families additionally need that marker beside whitespace.
97299
+ const REGEX_FAMILIES = [
97300
+ { regex: asteriskBoldRegex, isBold: true, marker: '**', gate: 'asteriskLoose' },
97301
+ { regex: underscoreBoldRegex, isBold: true, marker: '__', gate: 'underscoreLoose' },
97302
+ { regex: asteriskItalicRegex, isBold: false, marker: '*', gate: 'asteriskLoose' },
97303
+ { regex: underscoreItalicRegex, isBold: false, marker: '_', gate: 'underscoreLoose' },
97304
+ { regex: intrawordUnderscoreItalicRegex, isBold: false, isIntraword: true, marker: '_', gate: 'underscore' },
97305
+ { regex: intrawordUnderscoreBoldRegex, isBold: true, isIntraword: true, marker: '__', gate: 'underscore' },
97306
+ { regex: intrawordAsteriskItalicRegex, isBold: false, isIntraword: true, marker: '*', gate: 'asterisk' },
97307
+ { regex: intrawordAsteriskBoldRegex, isBold: true, isIntraword: true, marker: '**', gate: 'asterisk' },
97308
+ ];
97147
97309
  /**
97148
97310
  * Finds opening emphasis marker in a text value.
97149
97311
  * Returns marker info if found, null otherwise.
@@ -97335,6 +97497,21 @@ function isInsideInlineHtmlCode(index, parent) {
97335
97497
  * malformed emphasis syntax. This plugin post-processes the AST to handle these cases.
97336
97498
  */
97337
97499
  const normalize_malformed_md_syntax_normalizeEmphasisAST = () => (tree) => {
97500
+ // Back-scanning siblings for <code>…</code> html pairs costs O(children)
97501
+ // per text node — O(children²) per parent, which bites on marker-dense
97502
+ // paragraphs where micromark emits thousands of inline children. Most
97503
+ // parents have no html children at all, so cache that check per parent and
97504
+ // skip the back-scan entirely. The cached flag survives our splices: they
97505
+ // only ever swap text nodes for text/strong/emphasis, never html.
97506
+ const hasHtmlChild = new WeakMap();
97507
+ const mayBeInsideInlineHtmlCode = (index, parent) => {
97508
+ let flag = hasHtmlChild.get(parent);
97509
+ if (flag === undefined) {
97510
+ flag = parent.children.some(child => child.type === 'html');
97511
+ hasHtmlChild.set(parent, flag);
97512
+ }
97513
+ return flag && isInsideInlineHtmlCode(index, parent);
97514
+ };
97338
97515
  lib_visit(tree, 'text', function visitor(node, index, parent) {
97339
97516
  if (index === undefined || !parent)
97340
97517
  return undefined;
@@ -97346,41 +97523,39 @@ const normalize_malformed_md_syntax_normalizeEmphasisAST = () => (tree) => {
97346
97523
  // raw HTML <code>...</code> inside table cells, which the table re-parser
97347
97524
  // parses as MDX JSX (not as an mdast `inlineCode` node).
97348
97525
  if ((parent.type === 'mdxJsxTextElement' || parent.type === 'mdxJsxFlowElement') &&
97349
- 'name' in parent && parent.name === 'code') {
97526
+ 'name' in parent &&
97527
+ parent.name === 'code') {
97350
97528
  return undefined;
97351
97529
  }
97530
+ const text = node.value;
97531
+ // The regexes below can't match without their marker character, but
97532
+ // running them anyway costs a scan of the whole node — ruinous on huge
97533
+ // pasted payloads (base64 attachments, minified code). Checked before the
97534
+ // html-sibling scan so marker-free text never pays for that either.
97535
+ const hasAsterisk = text.includes('*');
97536
+ const hasUnderscore = text.includes('_');
97537
+ if (!hasAsterisk && !hasUnderscore)
97538
+ return undefined;
97352
97539
  // In GFM tables, inline <code>...</code> is represented as sibling `html`
97353
97540
  // nodes rather than as an mdxJsxTextElement, so the check above doesn't
97354
97541
  // apply. Scan backwards through siblings to see if we are enclosed by a
97355
97542
  // <code>…</code> inline HTML pair.
97356
- if (isInsideInlineHtmlCode(index, parent)) {
97543
+ if (mayBeInsideInlineHtmlCode(index, parent)) {
97357
97544
  return undefined;
97358
97545
  }
97359
- const text = node.value;
97546
+ const gates = {
97547
+ asterisk: hasAsterisk,
97548
+ asteriskLoose: hasAsterisk && asteriskBesideWhitespaceRegex.test(text),
97549
+ underscore: hasUnderscore,
97550
+ underscoreLoose: hasUnderscore && underscoreBesideWhitespaceRegex.test(text),
97551
+ };
97360
97552
  const allMatches = [];
97361
- [...text.matchAll(asteriskBoldRegex)].forEach(match => {
97362
- allMatches.push({ isBold: true, marker: '**', match });
97363
- });
97364
- [...text.matchAll(underscoreBoldRegex)].forEach(match => {
97365
- allMatches.push({ isBold: true, marker: '__', match });
97366
- });
97367
- [...text.matchAll(asteriskItalicRegex)].forEach(match => {
97368
- allMatches.push({ isBold: false, marker: '*', match });
97369
- });
97370
- [...text.matchAll(underscoreItalicRegex)].forEach(match => {
97371
- allMatches.push({ isBold: false, marker: '_', match });
97372
- });
97373
- [...text.matchAll(intrawordUnderscoreItalicRegex)].forEach(match => {
97374
- allMatches.push({ isBold: false, isIntraword: true, marker: '_', match });
97375
- });
97376
- [...text.matchAll(intrawordUnderscoreBoldRegex)].forEach(match => {
97377
- allMatches.push({ isBold: true, isIntraword: true, marker: '__', match });
97378
- });
97379
- [...text.matchAll(intrawordAsteriskItalicRegex)].forEach(match => {
97380
- allMatches.push({ isBold: false, isIntraword: true, marker: '*', match });
97381
- });
97382
- [...text.matchAll(intrawordAsteriskBoldRegex)].forEach(match => {
97383
- allMatches.push({ isBold: true, isIntraword: true, marker: '**', match });
97553
+ REGEX_FAMILIES.forEach(({ regex, gate, ...info }) => {
97554
+ if (!gates[gate])
97555
+ return;
97556
+ [...text.matchAll(regex)].forEach(match => {
97557
+ allMatches.push({ ...info, match });
97558
+ });
97384
97559
  });
97385
97560
  if (allMatches.length === 0)
97386
97561
  return undefined;
@@ -97477,9 +97652,22 @@ const normalize_malformed_md_syntax_normalizeEmphasisAST = () => (tree) => {
97477
97652
  parts.push({ type: 'text', value: remainingText });
97478
97653
  }
97479
97654
  }
97480
- if (parts.length > 0) {
97481
- parent.children.splice(index, 1, ...parts);
97482
- return [lib_SKIP, index + parts.length];
97655
+ // Merge adjacent text parts so the emitted AST doesn't depend on where a
97656
+ // match happened to start (the bounded prefixes above can shift a match
97657
+ // start rightward, splitting what used to be a single text node).
97658
+ const mergedParts = parts.reduce((acc, part) => {
97659
+ const prev = acc[acc.length - 1];
97660
+ if (part.type === 'text' && prev?.type === 'text') {
97661
+ prev.value += part.value;
97662
+ }
97663
+ else {
97664
+ acc.push(part);
97665
+ }
97666
+ return acc;
97667
+ }, []);
97668
+ if (mergedParts.length > 0) {
97669
+ parent.children.splice(index, 1, ...mergedParts);
97670
+ return [lib_SKIP, index + mergedParts.length];
97483
97671
  }
97484
97672
  return undefined;
97485
97673
  });
@@ -101593,6 +101781,7 @@ const variables = ({ asMdx } = { asMdx: true }) => tree => {
101593
101781
 
101594
101782
 
101595
101783
 
101784
+
101596
101785
  const defaultTransforms = {
101597
101786
  calloutTransformer: callouts,
101598
101787
  codeTabsTransformer: code_tabs,
@@ -101620,6 +101809,9 @@ const ast_processor_astProcessor = (opts = {}) => {
101620
101809
  const components = opts.components || {};
101621
101810
  let processor = remark_remark()
101622
101811
  .use(lib_remarkMdx)
101812
+ // Must precede every other transformer: it strips evaluable attribute expressions so no
101813
+ // downstream `getAttrs()` call can reach `evaluate()`.
101814
+ .use(opts.safeMode ? flatten_attribute_expressions : undefined)
101623
101815
  .use(remarkPlugins)
101624
101816
  .use(opts.remarkPlugins)
101625
101817
  .use(transform_variables, { asMdx: false })
@@ -116199,12 +116391,59 @@ const lib_h = create_h_createH(node_modules_property_information_html, 'div')
116199
116391
  /** @type {ReturnType<createH>} */
116200
116392
  const lib_s = create_h_createH(node_modules_property_information_svg, 'g', svg_case_sensitive_tag_names_svgCaseSensitiveTagNames)
116201
116393
 
116394
+ ;// ./utils/user.ts
116395
+ /**
116396
+ * Coerce a user variable value to a string for substitution into markdown text.
116397
+ * Non-string values (arrays, objects, numbers) are stringified via JSON or `String()`
116398
+ * so that `<<var>>` syntax doesn't produce `[object Object]` for structured data like
116399
+ * JWT `keys`.
116400
+ */
116401
+ const stringifyVariableValue = (value) => {
116402
+ if (typeof value === 'string')
116403
+ return value;
116404
+ if (value == null)
116405
+ return '';
116406
+ if (typeof value === 'object') {
116407
+ try {
116408
+ return JSON.stringify(value) ?? '';
116409
+ }
116410
+ catch {
116411
+ console.warn('[WARNING] Could not stringify a structured user variable.');
116412
+ return '';
116413
+ }
116414
+ }
116415
+ return String(value);
116416
+ };
116417
+ /**
116418
+ * Flatten `variables.user` into a string-keyed string-valued record by coercing
116419
+ * each value. Used by markdown substitution paths that need a plain
116420
+ * `Record<string, string>` lookup.
116421
+ */
116422
+ const flattenUserVariables = (user) => Object.fromEntries(Object.entries(user).map(([name, value]) => [name, stringifyVariableValue(value)]));
116423
+ const User = (variables) => {
116424
+ const { user = {}, defaults = [] } = variables || {};
116425
+ return new Proxy(user, {
116426
+ get(target, attribute) {
116427
+ if (typeof attribute === 'symbol') {
116428
+ return '';
116429
+ }
116430
+ if (attribute in target) {
116431
+ return target[attribute];
116432
+ }
116433
+ const def = defaults.find((d) => d.name === attribute);
116434
+ return def ? def.default : attribute.toUpperCase();
116435
+ },
116436
+ });
116437
+ };
116438
+ /* harmony default export */ const user = (User);
116439
+
116202
116440
  ;// ./processor/plugin/toc.ts
116203
116441
 
116204
116442
 
116205
116443
 
116206
116444
 
116207
116445
 
116446
+
116208
116447
  const HEADING_TAGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
116209
116448
  const isHeadingTag = (tag) => (tag ? HEADING_TAGS.includes(tag) : false);
116210
116449
  const isStandardHtmlElement = (node) => STANDARD_HTML_TAGS.has(node.tagName.toLowerCase());
@@ -116316,7 +116555,7 @@ const flattenVariables = (variables) => {
116316
116555
  if (!variables)
116317
116556
  return {};
116318
116557
  return {
116319
- ...variables.user,
116558
+ ...flattenUserVariables(variables.user),
116320
116559
  ...Object.fromEntries((variables.defaults || []).filter(d => !(d.name in variables.user)).map(d => [d.name, d.default])),
116321
116560
  };
116322
116561
  };
@@ -116464,7 +116703,7 @@ const exports_exports = (doc) => {
116464
116703
 
116465
116704
  const hast = (text, opts = {}) => {
116466
116705
  const components = Object.entries(opts.components || {}).reduce((memo, [name, doc]) => {
116467
- memo[name] = mdast(doc);
116706
+ memo[name] = mdast(doc, { safeMode: opts.safeMode });
116468
116707
  return memo;
116469
116708
  }, {});
116470
116709
  const processor = astProcessor(opts)
@@ -127065,6 +127304,7 @@ function normalizeTableSeparator(content) {
127065
127304
  ;// ./processor/transform/mdxish/variables-code.ts
127066
127305
 
127067
127306
 
127307
+
127068
127308
  // Single combined regex so that resolved values from one pattern are never re-scanned by the other.
127069
127309
  const COMBINED_VARIABLE_REGEX = new RegExp(`${variable_dist.VARIABLE_REGEXP}|${variable_dist.MDX_VARIABLE_REGEXP}`, 'giu');
127070
127310
  // Flatten variables into a single object for easy lookup
@@ -127073,7 +127313,7 @@ function variables_code_flattenVariables(variables) {
127073
127313
  return {};
127074
127314
  return {
127075
127315
  ...Object.fromEntries((variables.defaults || []).map(d => [d.name, d.default])),
127076
- ...variables.user,
127316
+ ...flattenUserVariables(variables.user),
127077
127317
  };
127078
127318
  }
127079
127319
  function resolveCodeVariables(value, resolvedVariables) {
@@ -127561,24 +127801,6 @@ const Contexts = ({ children, terms = [], variables = { user: {}, defaults: [] }
127561
127801
  };
127562
127802
  /* harmony default export */ const contexts = (Contexts);
127563
127803
 
127564
- ;// ./utils/user.ts
127565
- const User = (variables) => {
127566
- const { user = {}, defaults = [] } = variables || {};
127567
- return new Proxy(user, {
127568
- get(target, attribute) {
127569
- if (typeof attribute === 'symbol') {
127570
- return '';
127571
- }
127572
- if (attribute in target) {
127573
- return target[attribute];
127574
- }
127575
- const def = defaults.find((d) => d.name === attribute);
127576
- return def ? def.default : attribute.toUpperCase();
127577
- },
127578
- });
127579
- };
127580
- /* harmony default export */ const user = (User);
127581
-
127582
127804
  ;// ./lib/utils/makeUseMdxComponents.ts
127583
127805
 
127584
127806
 
@@ -127611,6 +127833,7 @@ const makeUseMDXComponents = (more = {}) => {
127611
127833
 
127612
127834
  ;// ./lib/utils/mdxish/mdxish-variables.ts
127613
127835
 
127836
+
127614
127837
  // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
127615
127838
  // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
127616
127839
  // which either evaluated already or is meant to stay literal.
@@ -127634,7 +127857,7 @@ function resolveAttributeVariables(value, user) {
127634
127857
  .replace(MDX_VARIABLE_REGEX, (source, escapePrefix, name, escapeSuffix) => {
127635
127858
  if (escapePrefix || escapeSuffix)
127636
127859
  return source;
127637
- return user[name];
127860
+ return stringifyVariableValue(user[name]);
127638
127861
  });
127639
127862
  }
127640
127863
 
@@ -127910,7 +128133,8 @@ const run_run = (string, _opts = {}) => {
127910
128133
 
127911
128134
  const tags = (doc) => {
127912
128135
  const set = new Set();
127913
- visit(mdast(doc), isMDXElement, (node) => {
128136
+ // Tag names never depend on evaluated attribute values, so always parse in safeMode.
128137
+ visit(mdast(doc, { safeMode: true }), isMDXElement, (node) => {
127914
128138
  if (node.name?.match(/^[A-Z]/)) {
127915
128139
  set.add(node.name);
127916
128140
  }
@@ -127926,13 +128150,14 @@ const tags = (doc) => {
127926
128150
 
127927
128151
 
127928
128152
 
127929
- const { micromarkExtensions, fromMarkdownExtensions } = mdxish_extensions_mdxishExtensions(mdxish_extensions_FEATURES.tags);
128153
+ const { micromarkExtensions, fromMarkdownExtensions } = mdxish_extensions_mdxishExtensions(mdxish_extensions_FEATURES.tags, { safeMode: true });
127930
128154
  const mdxishTags_tags = (doc) => {
127931
128155
  const set = new Set();
127932
128156
  const processor = remark()
127933
128157
  .data('micromarkExtensions', micromarkExtensions)
127934
128158
  .data('fromMarkdownExtensions', fromMarkdownExtensions)
127935
- .use(mdxishMdxComponentBlocks)
128159
+ // Tag names never depend on evaluated attribute values, so always parse in safeMode.
128160
+ .use(mdxishMdxComponentBlocks, { safeMode: true })
127936
128161
  .use(mdxishTables);
127937
128162
  const tree = processor.parse(doc);
127938
128163
  visit(processor.runSync(tree), isMDXElement, (node) => {