@readme/markdown 15.0.1 → 15.0.2

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
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}
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,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,uCAIJ,iDACE,4C","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\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
@@ -101593,6 +101712,7 @@ const variables = ({ asMdx } = { asMdx: true }) => tree => {
101593
101712
 
101594
101713
 
101595
101714
 
101715
+
101596
101716
  const defaultTransforms = {
101597
101717
  calloutTransformer: callouts,
101598
101718
  codeTabsTransformer: code_tabs,
@@ -101620,6 +101740,9 @@ const ast_processor_astProcessor = (opts = {}) => {
101620
101740
  const components = opts.components || {};
101621
101741
  let processor = remark_remark()
101622
101742
  .use(lib_remarkMdx)
101743
+ // Must precede every other transformer: it strips evaluable attribute expressions so no
101744
+ // downstream `getAttrs()` call can reach `evaluate()`.
101745
+ .use(opts.safeMode ? flatten_attribute_expressions : undefined)
101623
101746
  .use(remarkPlugins)
101624
101747
  .use(opts.remarkPlugins)
101625
101748
  .use(transform_variables, { asMdx: false })
@@ -116199,12 +116322,59 @@ const lib_h = create_h_createH(node_modules_property_information_html, 'div')
116199
116322
  /** @type {ReturnType<createH>} */
116200
116323
  const lib_s = create_h_createH(node_modules_property_information_svg, 'g', svg_case_sensitive_tag_names_svgCaseSensitiveTagNames)
116201
116324
 
116325
+ ;// ./utils/user.ts
116326
+ /**
116327
+ * Coerce a user variable value to a string for substitution into markdown text.
116328
+ * Non-string values (arrays, objects, numbers) are stringified via JSON or `String()`
116329
+ * so that `<<var>>` syntax doesn't produce `[object Object]` for structured data like
116330
+ * JWT `keys`.
116331
+ */
116332
+ const stringifyVariableValue = (value) => {
116333
+ if (typeof value === 'string')
116334
+ return value;
116335
+ if (value == null)
116336
+ return '';
116337
+ if (typeof value === 'object') {
116338
+ try {
116339
+ return JSON.stringify(value) ?? '';
116340
+ }
116341
+ catch {
116342
+ console.warn('[WARNING] Could not stringify a structured user variable.');
116343
+ return '';
116344
+ }
116345
+ }
116346
+ return String(value);
116347
+ };
116348
+ /**
116349
+ * Flatten `variables.user` into a string-keyed string-valued record by coercing
116350
+ * each value. Used by markdown substitution paths that need a plain
116351
+ * `Record<string, string>` lookup.
116352
+ */
116353
+ const flattenUserVariables = (user) => Object.fromEntries(Object.entries(user).map(([name, value]) => [name, stringifyVariableValue(value)]));
116354
+ const User = (variables) => {
116355
+ const { user = {}, defaults = [] } = variables || {};
116356
+ return new Proxy(user, {
116357
+ get(target, attribute) {
116358
+ if (typeof attribute === 'symbol') {
116359
+ return '';
116360
+ }
116361
+ if (attribute in target) {
116362
+ return target[attribute];
116363
+ }
116364
+ const def = defaults.find((d) => d.name === attribute);
116365
+ return def ? def.default : attribute.toUpperCase();
116366
+ },
116367
+ });
116368
+ };
116369
+ /* harmony default export */ const user = (User);
116370
+
116202
116371
  ;// ./processor/plugin/toc.ts
116203
116372
 
116204
116373
 
116205
116374
 
116206
116375
 
116207
116376
 
116377
+
116208
116378
  const HEADING_TAGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
116209
116379
  const isHeadingTag = (tag) => (tag ? HEADING_TAGS.includes(tag) : false);
116210
116380
  const isStandardHtmlElement = (node) => STANDARD_HTML_TAGS.has(node.tagName.toLowerCase());
@@ -116316,7 +116486,7 @@ const flattenVariables = (variables) => {
116316
116486
  if (!variables)
116317
116487
  return {};
116318
116488
  return {
116319
- ...variables.user,
116489
+ ...flattenUserVariables(variables.user),
116320
116490
  ...Object.fromEntries((variables.defaults || []).filter(d => !(d.name in variables.user)).map(d => [d.name, d.default])),
116321
116491
  };
116322
116492
  };
@@ -116464,7 +116634,7 @@ const exports_exports = (doc) => {
116464
116634
 
116465
116635
  const hast = (text, opts = {}) => {
116466
116636
  const components = Object.entries(opts.components || {}).reduce((memo, [name, doc]) => {
116467
- memo[name] = mdast(doc);
116637
+ memo[name] = mdast(doc, { safeMode: opts.safeMode });
116468
116638
  return memo;
116469
116639
  }, {});
116470
116640
  const processor = astProcessor(opts)
@@ -127065,6 +127235,7 @@ function normalizeTableSeparator(content) {
127065
127235
  ;// ./processor/transform/mdxish/variables-code.ts
127066
127236
 
127067
127237
 
127238
+
127068
127239
  // Single combined regex so that resolved values from one pattern are never re-scanned by the other.
127069
127240
  const COMBINED_VARIABLE_REGEX = new RegExp(`${variable_dist.VARIABLE_REGEXP}|${variable_dist.MDX_VARIABLE_REGEXP}`, 'giu');
127070
127241
  // Flatten variables into a single object for easy lookup
@@ -127073,7 +127244,7 @@ function variables_code_flattenVariables(variables) {
127073
127244
  return {};
127074
127245
  return {
127075
127246
  ...Object.fromEntries((variables.defaults || []).map(d => [d.name, d.default])),
127076
- ...variables.user,
127247
+ ...flattenUserVariables(variables.user),
127077
127248
  };
127078
127249
  }
127079
127250
  function resolveCodeVariables(value, resolvedVariables) {
@@ -127561,24 +127732,6 @@ const Contexts = ({ children, terms = [], variables = { user: {}, defaults: [] }
127561
127732
  };
127562
127733
  /* harmony default export */ const contexts = (Contexts);
127563
127734
 
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
127735
  ;// ./lib/utils/makeUseMdxComponents.ts
127583
127736
 
127584
127737
 
@@ -127611,6 +127764,7 @@ const makeUseMDXComponents = (more = {}) => {
127611
127764
 
127612
127765
  ;// ./lib/utils/mdxish/mdxish-variables.ts
127613
127766
 
127767
+
127614
127768
  // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
127615
127769
  // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
127616
127770
  // which either evaluated already or is meant to stay literal.
@@ -127634,7 +127788,7 @@ function resolveAttributeVariables(value, user) {
127634
127788
  .replace(MDX_VARIABLE_REGEX, (source, escapePrefix, name, escapeSuffix) => {
127635
127789
  if (escapePrefix || escapeSuffix)
127636
127790
  return source;
127637
- return user[name];
127791
+ return stringifyVariableValue(user[name]);
127638
127792
  });
127639
127793
  }
127640
127794
 
@@ -127910,7 +128064,8 @@ const run_run = (string, _opts = {}) => {
127910
128064
 
127911
128065
  const tags = (doc) => {
127912
128066
  const set = new Set();
127913
- visit(mdast(doc), isMDXElement, (node) => {
128067
+ // Tag names never depend on evaluated attribute values, so always parse in safeMode.
128068
+ visit(mdast(doc, { safeMode: true }), isMDXElement, (node) => {
127914
128069
  if (node.name?.match(/^[A-Z]/)) {
127915
128070
  set.add(node.name);
127916
128071
  }
@@ -127926,13 +128081,14 @@ const tags = (doc) => {
127926
128081
 
127927
128082
 
127928
128083
 
127929
- const { micromarkExtensions, fromMarkdownExtensions } = mdxish_extensions_mdxishExtensions(mdxish_extensions_FEATURES.tags);
128084
+ const { micromarkExtensions, fromMarkdownExtensions } = mdxish_extensions_mdxishExtensions(mdxish_extensions_FEATURES.tags, { safeMode: true });
127930
128085
  const mdxishTags_tags = (doc) => {
127931
128086
  const set = new Set();
127932
128087
  const processor = remark()
127933
128088
  .data('micromarkExtensions', micromarkExtensions)
127934
128089
  .data('fromMarkdownExtensions', fromMarkdownExtensions)
127935
- .use(mdxishMdxComponentBlocks)
128090
+ // Tag names never depend on evaluated attribute values, so always parse in safeMode.
128091
+ .use(mdxishMdxComponentBlocks, { safeMode: true })
127936
128092
  .use(mdxishTables);
127937
128093
  const tree = processor.parse(doc);
127938
128094
  visit(processor.runSync(tree), isMDXElement, (node) => {