@gravity-ui/aikit 2.19.2-beta.f57139873deb58bb27de738cef3da72426a9be48.0 → 2.19.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.
- package/build/cjs/components/atoms/MarkdownRenderer/MarkdownRenderer.d.ts +1 -1
- package/build/cjs/components/atoms/MarkdownRenderer/MarkdownRenderer.js.map +1 -1
- package/build/cjs/components/atoms/MarkdownRenderer/MdxPortals.d.ts +1 -1
- package/build/cjs/components/atoms/MarkdownRenderer/MdxPortals.js +8 -7
- package/build/cjs/components/atoms/MarkdownRenderer/MdxPortals.js.map +1 -1
- package/build/cjs/components/atoms/MarkdownRenderer/asyncExecuteCode.d.ts +1 -0
- package/build/cjs/components/atoms/MarkdownRenderer/asyncExecuteCode.js +15 -2
- package/build/cjs/components/atoms/MarkdownRenderer/asyncExecuteCode.js.map +1 -1
- package/build/cjs/components/molecules/PromptInputFooter/PromptInputFooter.css +1 -1
- package/build/cjs/package.json +1 -1
- package/build/docs/components/atoms/MarkdownRenderer.md +7 -6
- package/build/esm/components/atoms/MarkdownRenderer/MarkdownRenderer.d.ts +1 -1
- package/build/esm/components/atoms/MarkdownRenderer/MarkdownRenderer.js.map +1 -1
- package/build/esm/components/atoms/MarkdownRenderer/MdxPortals.d.ts +1 -1
- package/build/esm/components/atoms/MarkdownRenderer/MdxPortals.js +9 -8
- package/build/esm/components/atoms/MarkdownRenderer/MdxPortals.js.map +1 -1
- package/build/esm/components/atoms/MarkdownRenderer/asyncExecuteCode.d.ts +1 -0
- package/build/esm/components/atoms/MarkdownRenderer/asyncExecuteCode.js +14 -2
- package/build/esm/components/atoms/MarkdownRenderer/asyncExecuteCode.js.map +1 -1
- package/build/esm/components/molecules/PromptInputFooter/PromptInputFooter.css +1 -1
- package/build/esm/package.json +1 -1
- package/package.json +1 -1
|
@@ -11,7 +11,7 @@ export interface MarkdownRendererMdxOptions {
|
|
|
11
11
|
components: MDXComponents;
|
|
12
12
|
/** Optional list of tag names to limit which components are processed as MDX. */
|
|
13
13
|
tagNames?: string[];
|
|
14
|
-
/** CSP nonce applied to scripts
|
|
14
|
+
/** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */
|
|
15
15
|
nonce?: string;
|
|
16
16
|
}
|
|
17
17
|
export interface MarkdownRendererProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownRenderer.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MarkdownRenderer.tsx"],"names":[],"mappings":";;;;AAAA,iCAA2E;AAE3E,2DAAkD;AAQlD,iFAAyE;AACzE,2DAAmD;AACnD,6CAAwC;AACxC,mEAA6D;AAE7D,gDAAwC;AAExC,kCAAiC;AAEjC,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,mBAAmB,CAAC,CAAC;AA4BrC,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEhD,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAE,EAAE;IAC1C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACnE,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEhD,OAAO,CACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YACjB,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM;YACrC,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC,QAAQ;YACzC,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,CACxC,CAAC;IACN,CAAC;IAAC,WAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAA8B,CAAC,CAAC,EAAc,EAAE,EAAE;IAC3E,MAAM,aAAa,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;IACxC,MAAM,aAAa,GACf,aAAa,CAAC,SAAS;QACvB,UAAU,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI;YACtC,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC,CAAC;IAEN,aAAa,CAAC,SAAS,GAAG,UAAU,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI;QAC/D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1D,CAAC,CAAC;AACN,CAAC,CAA8B,CAAC;AAEhC,SAAS,yBAAyB,CAAC,EAC/B,OAAO,EACP,SAAS,EACT,EAAE,EACF,gBAAgB,EAChB,6BAA6B,GAAG,KAAK,EACrC,iBAAiB,GAAG,KAAK,EACzB,UAAU,EACV,UAAU,EACV,UAAU,GACU;IACpB,MAAM,aAAa,GAAG,IAAA,qBAAS,EAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,UAAU,CAAC;IAC7C,MAAM,WAAW,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,QAAQ,CAAC;IACzC,MAAM,QAAQ,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,KAAK,CAAC;IACnC,MAAM,qBAAqB,GAAG,IAAA,eAAO,EAA0B,GAAG,EAAE;;QAChE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,MAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,OAAO,mCAAI,EAAE,CAAC,CAAC,CAAC;QAEvD,IAAI,iBAAiB,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CACR,IAAA,yBAAS,EACL,WAAW,CAAC,CAAC,CAAC,EAAC,QAAQ,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC,SAAS,CACZ,CAC5C,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,gBAAgB,CAAC;QAC5B,CAAC;QAED,uCACO,gBAAgB,KACnB,OAAO,IACT;IACN,CAAC,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAElE,MAAM,YAAY,GAAG,IAAA,cAAM,EAAwB,IAAI,CAAC,CAAC;IACzD,MAAM,EAAC,IAAI,EAAE,YAAY,EAAC,GAAG,IAAA,2CAAoB,EAC7C,aAAa,EACb,qBAAqB,EACrB,SAAS,CACZ,CAAC;IAEF,OAAO,CACH,wBAAC,gBAAQ,eACL,8CACI,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,aAC7B,EAAE,EACX,uBAAuB,EAAE,EAAC,MAAM,EAAE,IAAI,EAAC,IACnC,UAAU,EAChB,EACD,SAAS,CAAC,CAAC,CAAC,CACT,uBAAC,uBAAU,IACP,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,QAAQ,EACf,UAAU,EAAE,UAAU,GACxB,CACL,CAAC,CAAC,CAAC,IAAI,IACD,CACd,CAAC;AACN,CAAC;AAEY,QAAA,gBAAgB,GAAG,IAAA,YAAI,EAAC,yBAAyB,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE;;IACrF,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,CAAC,6BAA6B,KAAK,SAAS,CAAC,6BAA6B,EAAE,CAAC;QACtF,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,CAAC,iBAAiB,KAAK,SAAS,CAAC,iBAAiB,EAAE,CAAC;QAC9D,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,CAAC,SAAS,KAAK,SAAS,CAAC,SAAS,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,CAAC,EAAE,KAAK,SAAS,CAAC,EAAE,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,CAAA,MAAA,SAAS,CAAC,UAAU,0CAAE,UAAU,OAAK,MAAA,SAAS,CAAC,UAAU,0CAAE,UAAU,CAAA,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,CAAA,MAAA,SAAS,CAAC,UAAU,0CAAE,QAAQ,OAAK,MAAA,SAAS,CAAC,UAAU,0CAAE,QAAQ,CAAA,EAAE,CAAC;QACpE,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,CAAA,MAAA,SAAS,CAAC,UAAU,0CAAE,KAAK,OAAK,MAAA,SAAS,CAAC,UAAU,0CAAE,KAAK,CAAA,EAAE,CAAC;QAC9D,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,IAAA,+BAAe,EAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAC;AACnF,CAAC,CAAC,CAAC;AAEH,wBAAgB,CAAC,WAAW,GAAG,kBAAkB,CAAC","sourcesContent":["import {Fragment, type HTMLAttributes, memo, useMemo, useRef} from 'react';\n\nimport {mdxPlugin} from '@diplodoc/mdx-extension';\nimport type {\n ExtendedPluginWithCollect,\n MarkdownIt,\n OptionsType,\n} from '@diplodoc/transform/lib/typings';\nimport type {MDXComponents} from 'mdx/types';\n\nimport {useMarkdownTransform} from '../../../hooks/useMarkdownTransform';\nimport {useRemend} from '../../../hooks/useRemend';\nimport {block} from '../../../utils/cn';\nimport {areOptionsEqual} from '../../../utils/markdownUtils';\n\nimport {MdxPortals} from './MdxPortals';\n\nimport './MarkdownRenderer.scss';\n\nconst b = block('markdown-renderer');\n\n/**\n * Options for rendering embedded MDX/JSX in the markdown content via\n * `@diplodoc/mdx-extension`. Passing `mdxOptions` enables MDX processing.\n */\nexport interface MarkdownRendererMdxOptions {\n /** Map of components rendered from embedded MDX/JSX in the markdown content. */\n components: MDXComponents;\n /** Optional list of tag names to limit which components are processed as MDX. */\n tagNames?: string[];\n /** CSP nonce applied to scripts that execute compiled MDX artifacts. */\n nonce?: string;\n}\n\nexport interface MarkdownRendererProps {\n content: string;\n className?: string;\n qa?: string;\n transformOptions?: OptionsType;\n shouldParseIncompleteMarkdown?: boolean;\n openLinksInNewTab?: boolean;\n mdxOptions?: MarkdownRendererMdxOptions;\n mdxContext?: Record<string, unknown>;\n /** Extra props forwarded to the root container `div` element. */\n extraProps?: HTMLAttributes<HTMLDivElement>;\n}\n\nconst ABSOLUTE_HTTP_URL_RE = /^(https?:)?\\/\\//i;\n\nconst isSameDocumentAnchor = (href: string) => {\n if (href.startsWith('#')) {\n return true;\n }\n\n if (ABSOLUTE_HTTP_URL_RE.test(href) || typeof window === 'undefined') {\n return false;\n }\n\n try {\n const url = new URL(href, window.location.href);\n\n return (\n Boolean(url.hash) &&\n url.origin === window.location.origin &&\n url.pathname === window.location.pathname &&\n url.search === window.location.search\n );\n } catch {\n return false;\n }\n};\n\nconst openLinksInNewTabPlugin: ExtendedPluginWithCollect = ((md: MarkdownIt) => {\n const rendererRules = md.renderer.rules;\n const defaultRender =\n rendererRules.link_open ||\n function (tokens, idx, options, _env, self) {\n return self.renderToken(tokens, idx, options);\n };\n\n rendererRules.link_open = function (tokens, idx, options, env, self) {\n const href = tokens[idx].attrGet('href');\n if (!href || !isSameDocumentAnchor(href)) {\n tokens[idx].attrSet('target', '_blank');\n tokens[idx].attrSet('rel', 'noopener noreferrer');\n }\n\n return defaultRender(tokens, idx, options, env, self);\n };\n}) as ExtendedPluginWithCollect;\n\nfunction MarkdownRendererComponent({\n content,\n className,\n qa,\n transformOptions,\n shouldParseIncompleteMarkdown = false,\n openLinksInNewTab = false,\n mdxOptions,\n mdxContext,\n extraProps,\n}: MarkdownRendererProps) {\n const closedContent = useRemend(content, shouldParseIncompleteMarkdown);\n const enableMdx = Boolean(mdxOptions);\n const mdxComponents = mdxOptions?.components;\n const mdxTagNames = mdxOptions?.tagNames;\n const mdxNonce = mdxOptions?.nonce;\n const finalTransformOptions = useMemo<OptionsType | undefined>(() => {\n const plugins = [...(transformOptions?.plugins ?? [])];\n\n if (openLinksInNewTab) {\n plugins.push(openLinksInNewTabPlugin);\n }\n\n if (enableMdx) {\n plugins.push(\n mdxPlugin(\n mdxTagNames ? {tagNames: mdxTagNames} : undefined,\n ) as unknown as ExtendedPluginWithCollect,\n );\n }\n\n if (plugins.length === 0) {\n return transformOptions;\n }\n\n return {\n ...transformOptions,\n plugins,\n };\n }, [openLinksInNewTab, transformOptions, enableMdx, mdxTagNames]);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const {html, mdxArtifacts} = useMarkdownTransform(\n closedContent,\n finalTransformOptions,\n enableMdx,\n );\n\n return (\n <Fragment>\n <div\n ref={containerRef}\n className={b(null, [className, 'yfm'])}\n data-qa={qa}\n dangerouslySetInnerHTML={{__html: html}}\n {...extraProps}\n />\n {enableMdx ? (\n <MdxPortals\n refCtr={containerRef}\n html={html}\n components={mdxComponents}\n mdxArtifacts={mdxArtifacts}\n nonce={mdxNonce}\n mdxContext={mdxContext}\n />\n ) : null}\n </Fragment>\n );\n}\n\nexport const MarkdownRenderer = memo(MarkdownRendererComponent, (prevProps, nextProps) => {\n if (prevProps.content !== nextProps.content) {\n return false;\n }\n\n if (prevProps.shouldParseIncompleteMarkdown !== nextProps.shouldParseIncompleteMarkdown) {\n return false;\n }\n\n if (prevProps.openLinksInNewTab !== nextProps.openLinksInNewTab) {\n return false;\n }\n\n if (prevProps.className !== nextProps.className) {\n return false;\n }\n\n if (prevProps.qa !== nextProps.qa) {\n return false;\n }\n\n if (prevProps.mdxOptions?.components !== nextProps.mdxOptions?.components) {\n return false;\n }\n\n if (prevProps.mdxOptions?.tagNames !== nextProps.mdxOptions?.tagNames) {\n return false;\n }\n\n if (prevProps.mdxOptions?.nonce !== nextProps.mdxOptions?.nonce) {\n return false;\n }\n\n if (prevProps.mdxContext !== nextProps.mdxContext) {\n return false;\n }\n\n if (prevProps.extraProps !== nextProps.extraProps) {\n return false;\n }\n\n return areOptionsEqual(prevProps.transformOptions, nextProps.transformOptions);\n});\n\nMarkdownRenderer.displayName = 'MarkdownRenderer';\n"]}
|
|
1
|
+
{"version":3,"file":"MarkdownRenderer.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MarkdownRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Fragment, type HTMLAttributes, memo, useMemo, useRef} from 'react';\n\nimport {mdxPlugin} from '@diplodoc/mdx-extension';\nimport type {\n ExtendedPluginWithCollect,\n MarkdownIt,\n OptionsType,\n} from '@diplodoc/transform/lib/typings';\nimport type {MDXComponents} from 'mdx/types';\n\nimport {useMarkdownTransform} from '../../../hooks/useMarkdownTransform';\nimport {useRemend} from '../../../hooks/useRemend';\nimport {block} from '../../../utils/cn';\nimport {areOptionsEqual} from '../../../utils/markdownUtils';\n\nimport {MdxPortals} from './MdxPortals';\n\nimport './MarkdownRenderer.scss';\n\nconst b = block('markdown-renderer');\n\n/**\n * Options for rendering embedded MDX/JSX in the markdown content via\n * `@diplodoc/mdx-extension`. Passing `mdxOptions` enables MDX processing.\n */\nexport interface MarkdownRendererMdxOptions {\n /** Map of components rendered from embedded MDX/JSX in the markdown content. */\n components: MDXComponents;\n /** Optional list of tag names to limit which components are processed as MDX. */\n tagNames?: string[];\n /** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */\n nonce?: string;\n}\n\nexport interface MarkdownRendererProps {\n content: string;\n className?: string;\n qa?: string;\n transformOptions?: OptionsType;\n shouldParseIncompleteMarkdown?: boolean;\n openLinksInNewTab?: boolean;\n mdxOptions?: MarkdownRendererMdxOptions;\n mdxContext?: Record<string, unknown>;\n /** Extra props forwarded to the root container `div` element. */\n extraProps?: HTMLAttributes<HTMLDivElement>;\n}\n\nconst ABSOLUTE_HTTP_URL_RE = /^(https?:)?\\/\\//i;\n\nconst isSameDocumentAnchor = (href: string) => {\n if (href.startsWith('#')) {\n return true;\n }\n\n if (ABSOLUTE_HTTP_URL_RE.test(href) || typeof window === 'undefined') {\n return false;\n }\n\n try {\n const url = new URL(href, window.location.href);\n\n return (\n Boolean(url.hash) &&\n url.origin === window.location.origin &&\n url.pathname === window.location.pathname &&\n url.search === window.location.search\n );\n } catch {\n return false;\n }\n};\n\nconst openLinksInNewTabPlugin: ExtendedPluginWithCollect = ((md: MarkdownIt) => {\n const rendererRules = md.renderer.rules;\n const defaultRender =\n rendererRules.link_open ||\n function (tokens, idx, options, _env, self) {\n return self.renderToken(tokens, idx, options);\n };\n\n rendererRules.link_open = function (tokens, idx, options, env, self) {\n const href = tokens[idx].attrGet('href');\n if (!href || !isSameDocumentAnchor(href)) {\n tokens[idx].attrSet('target', '_blank');\n tokens[idx].attrSet('rel', 'noopener noreferrer');\n }\n\n return defaultRender(tokens, idx, options, env, self);\n };\n}) as ExtendedPluginWithCollect;\n\nfunction MarkdownRendererComponent({\n content,\n className,\n qa,\n transformOptions,\n shouldParseIncompleteMarkdown = false,\n openLinksInNewTab = false,\n mdxOptions,\n mdxContext,\n extraProps,\n}: MarkdownRendererProps) {\n const closedContent = useRemend(content, shouldParseIncompleteMarkdown);\n const enableMdx = Boolean(mdxOptions);\n const mdxComponents = mdxOptions?.components;\n const mdxTagNames = mdxOptions?.tagNames;\n const mdxNonce = mdxOptions?.nonce;\n const finalTransformOptions = useMemo<OptionsType | undefined>(() => {\n const plugins = [...(transformOptions?.plugins ?? [])];\n\n if (openLinksInNewTab) {\n plugins.push(openLinksInNewTabPlugin);\n }\n\n if (enableMdx) {\n plugins.push(\n mdxPlugin(\n mdxTagNames ? {tagNames: mdxTagNames} : undefined,\n ) as unknown as ExtendedPluginWithCollect,\n );\n }\n\n if (plugins.length === 0) {\n return transformOptions;\n }\n\n return {\n ...transformOptions,\n plugins,\n };\n }, [openLinksInNewTab, transformOptions, enableMdx, mdxTagNames]);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const {html, mdxArtifacts} = useMarkdownTransform(\n closedContent,\n finalTransformOptions,\n enableMdx,\n );\n\n return (\n <Fragment>\n <div\n ref={containerRef}\n className={b(null, [className, 'yfm'])}\n data-qa={qa}\n dangerouslySetInnerHTML={{__html: html}}\n {...extraProps}\n />\n {enableMdx ? (\n <MdxPortals\n refCtr={containerRef}\n html={html}\n components={mdxComponents}\n mdxArtifacts={mdxArtifacts}\n nonce={mdxNonce}\n mdxContext={mdxContext}\n />\n ) : null}\n </Fragment>\n );\n}\n\nexport const MarkdownRenderer = memo(MarkdownRendererComponent, (prevProps, nextProps) => {\n if (prevProps.content !== nextProps.content) {\n return false;\n }\n\n if (prevProps.shouldParseIncompleteMarkdown !== nextProps.shouldParseIncompleteMarkdown) {\n return false;\n }\n\n if (prevProps.openLinksInNewTab !== nextProps.openLinksInNewTab) {\n return false;\n }\n\n if (prevProps.className !== nextProps.className) {\n return false;\n }\n\n if (prevProps.qa !== nextProps.qa) {\n return false;\n }\n\n if (prevProps.mdxOptions?.components !== nextProps.mdxOptions?.components) {\n return false;\n }\n\n if (prevProps.mdxOptions?.tagNames !== nextProps.mdxOptions?.tagNames) {\n return false;\n }\n\n if (prevProps.mdxOptions?.nonce !== nextProps.mdxOptions?.nonce) {\n return false;\n }\n\n if (prevProps.mdxContext !== nextProps.mdxContext) {\n return false;\n }\n\n if (prevProps.extraProps !== nextProps.extraProps) {\n return false;\n }\n\n return areOptionsEqual(prevProps.transformOptions, nextProps.transformOptions);\n});\n\nMarkdownRenderer.displayName = 'MarkdownRenderer';\n"]}
|
|
@@ -11,7 +11,7 @@ export interface MdxPortalsProps {
|
|
|
11
11
|
components?: MDXComponents;
|
|
12
12
|
/** Artifacts collected by the MDX transform, required to hydrate the components. */
|
|
13
13
|
mdxArtifacts?: MdxArtifacts;
|
|
14
|
-
/** CSP nonce applied to scripts
|
|
14
|
+
/** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */
|
|
15
15
|
nonce?: string;
|
|
16
16
|
/** Arbitrary value exposed to the MDX components through {@link MdxDataContext}. */
|
|
17
17
|
mdxContext?: Record<string, unknown>;
|
|
@@ -10,9 +10,10 @@ const MdxContext_1 = require("./MdxContext.js");
|
|
|
10
10
|
const asyncExecuteCode_1 = require("./asyncExecuteCode.js");
|
|
11
11
|
function useMdxComponentLoader(mdxArtifacts, nonce) {
|
|
12
12
|
const idMdx = mdxArtifacts === null || mdxArtifacts === void 0 ? void 0 : mdxArtifacts.idMdx;
|
|
13
|
+
const resolvedNonce = (0, asyncExecuteCode_1.resolveCspNonce)(nonce);
|
|
13
14
|
const [state, setState] = (0, react_1.useState)({ isSuccess: false });
|
|
14
15
|
(0, react_1.useEffect)(() => {
|
|
15
|
-
if (!
|
|
16
|
+
if (!resolvedNonce) {
|
|
16
17
|
return () => undefined;
|
|
17
18
|
}
|
|
18
19
|
let isActive = true;
|
|
@@ -20,30 +21,30 @@ function useMdxComponentLoader(mdxArtifacts, nonce) {
|
|
|
20
21
|
try {
|
|
21
22
|
const data = {};
|
|
22
23
|
for (const [artifactId, code] of Object.entries(idMdx !== null && idMdx !== void 0 ? idMdx : {})) {
|
|
23
|
-
const fn = await (0, asyncExecuteCode_1.asyncExecuteCode)(code,
|
|
24
|
+
const fn = await (0, asyncExecuteCode_1.asyncExecuteCode)(code, resolvedNonce);
|
|
24
25
|
if (!isActive) {
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
27
28
|
data[artifactId] = fn(runtime).default;
|
|
28
29
|
}
|
|
29
30
|
if (isActive) {
|
|
30
|
-
setState({ idMdx, nonce, data, isSuccess: true });
|
|
31
|
+
setState({ idMdx, nonce: resolvedNonce, data, isSuccess: true });
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
catch (_a) {
|
|
34
35
|
if (isActive) {
|
|
35
|
-
setState({ idMdx, nonce, isSuccess: false });
|
|
36
|
+
setState({ idMdx, nonce: resolvedNonce, isSuccess: false });
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
})();
|
|
39
40
|
return () => {
|
|
40
41
|
isActive = false;
|
|
41
42
|
};
|
|
42
|
-
}, [idMdx,
|
|
43
|
-
if (!
|
|
43
|
+
}, [idMdx, resolvedNonce]);
|
|
44
|
+
if (!resolvedNonce) {
|
|
44
45
|
return undefined;
|
|
45
46
|
}
|
|
46
|
-
if (state.idMdx !== idMdx || state.nonce !==
|
|
47
|
+
if (state.idMdx !== idMdx || state.nonce !== resolvedNonce) {
|
|
47
48
|
return { isSuccess: false };
|
|
48
49
|
}
|
|
49
50
|
return state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MdxPortals.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MdxPortals.tsx"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"MdxPortals.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MdxPortals.tsx"],"names":[],"mappings":";;AAsFA,gCAmBC;;;AAzGD,iCAA0C;AAG1C,2DAA+C;AAG/C,mEAA6C;AAE7C,gDAA4C;AAC5C,4DAAqE;AAOrE,SAAS,qBAAqB,CAAC,YAAsC,EAAE,KAAc;IACjF,MAAM,KAAK,GAAG,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,KAAK,CAAC;IAClC,MAAM,aAAa,GAAG,IAAA,kCAAe,EAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAiB,EAAC,SAAS,EAAE,KAAK,EAAC,CAAC,CAAC;IAEvE,IAAA,iBAAS,EAAC,GAAG,EAAE;QACX,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;QAC3B,CAAC;QAED,IAAI,QAAQ,GAAG,IAAI,CAAC;QAEpB,CAAC,KAAK,IAAI,EAAE;YACR,IAAI,CAAC;gBACD,MAAM,IAAI,GAAkD,EAAE,CAAC;gBAE/D,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,EAAE,CAAC;oBAC3D,MAAM,EAAE,GAAG,MAAM,IAAA,mCAAgB,EAC7B,IAAI,EACJ,aAAa,CAChB,CAAC;oBAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACZ,OAAO;oBACX,CAAC;oBAED,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;gBAC3C,CAAC;gBAED,IAAI,QAAQ,EAAE,CAAC;oBACX,QAAQ,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;gBACnE,CAAC;YACL,CAAC;YAAC,WAAM,CAAC;gBACL,IAAI,QAAQ,EAAE,CAAC;oBACX,QAAQ,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAC,CAAC,CAAC;gBAC9D,CAAC;YACL,CAAC;QACL,CAAC,CAAC,EAAE,CAAC;QAEL,OAAO,GAAG,EAAE;YACR,QAAQ,GAAG,KAAK,CAAC;QACrB,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;IAE3B,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;QACzD,OAAO,EAAC,SAAS,EAAE,KAAK,EAAC,CAAC;IAC9B,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAiBD,SAAgB,UAAU,CAAC,EACvB,MAAM,EACN,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,KAAK,EACL,UAAU,GACI;IACd,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,IAAA,sBAAM,EAAC;QACnB,MAAM;QACN,IAAI;QACJ,UAAU;QACV,YAAY;QACZ,WAAW,EAAE,CAAC,2BAAc,CAAC;QAC7B,oBAAoB;KACvB,CAAC,CAAC;IAEH,OAAO,uBAAC,2BAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU,YAAG,OAAO,GAA2B,CAAC;AAC3F,CAAC;AAED,UAAU,CAAC,WAAW,GAAG,YAAY,CAAC","sourcesContent":["import {useEffect, useState} from 'react';\nimport type {RefObject} from 'react';\n\nimport {useMdx} from '@diplodoc/mdx-extension';\nimport type {IdMdxComponentLoader, MdxArtifacts} from '@diplodoc/mdx-extension';\nimport type {MDXComponents, MDXModule, MDXProps} from 'mdx/types';\nimport * as runtime from 'react/jsx-runtime';\n\nimport {MdxDataContext} from './MdxContext';\nimport {asyncExecuteCode, resolveCspNonce} from './asyncExecuteCode';\n\ninterface MdxLoaderState extends IdMdxComponentLoader {\n idMdx?: Record<string, string>;\n nonce?: string;\n}\n\nfunction useMdxComponentLoader(mdxArtifacts: MdxArtifacts | undefined, nonce?: string) {\n const idMdx = mdxArtifacts?.idMdx;\n const resolvedNonce = resolveCspNonce(nonce);\n const [state, setState] = useState<MdxLoaderState>({isSuccess: false});\n\n useEffect(() => {\n if (!resolvedNonce) {\n return () => undefined;\n }\n\n let isActive = true;\n\n (async () => {\n try {\n const data: Record<string, React.ComponentType<MDXProps>> = {};\n\n for (const [artifactId, code] of Object.entries(idMdx ?? {})) {\n const fn = await asyncExecuteCode<(jsxRuntime: typeof runtime) => MDXModule>(\n code,\n resolvedNonce,\n );\n\n if (!isActive) {\n return;\n }\n\n data[artifactId] = fn(runtime).default;\n }\n\n if (isActive) {\n setState({idMdx, nonce: resolvedNonce, data, isSuccess: true});\n }\n } catch {\n if (isActive) {\n setState({idMdx, nonce: resolvedNonce, isSuccess: false});\n }\n }\n })();\n\n return () => {\n isActive = false;\n };\n }, [idMdx, resolvedNonce]);\n\n if (!resolvedNonce) {\n return undefined;\n }\n\n if (state.idMdx !== idMdx || state.nonce !== resolvedNonce) {\n return {isSuccess: false};\n }\n\n return state;\n}\n\nexport interface MdxPortalsProps {\n /** Ref to the container element into which the rendered HTML is injected. */\n refCtr: RefObject<HTMLDivElement | null>;\n /** HTML produced by the markdown transform for the current content. */\n html: string;\n /** Map of components rendered from embedded MDX/JSX in the markdown content. */\n components?: MDXComponents;\n /** Artifacts collected by the MDX transform, required to hydrate the components. */\n mdxArtifacts?: MdxArtifacts;\n /** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */\n nonce?: string;\n /** Arbitrary value exposed to the MDX components through {@link MdxDataContext}. */\n mdxContext?: Record<string, unknown>;\n}\n\nexport function MdxPortals({\n refCtr,\n html,\n components,\n mdxArtifacts,\n nonce,\n mdxContext,\n}: MdxPortalsProps) {\n const idMdxComponentLoader = useMdxComponentLoader(mdxArtifacts, nonce);\n const portals = useMdx({\n refCtr,\n html,\n components,\n mdxArtifacts,\n contextList: [MdxDataContext],\n idMdxComponentLoader,\n });\n\n return <MdxDataContext.Provider value={mdxContext}>{portals}</MdxDataContext.Provider>;\n}\n\nMdxPortals.displayName = 'MdxPortals';\n"]}
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveCspNonce = resolveCspNonce;
|
|
3
4
|
exports.asyncExecuteCode = asyncExecuteCode;
|
|
4
5
|
const HANDLERS_KEY = '__gravityUiAikitMdxLoader__';
|
|
6
|
+
function resolveCspNonce(nonce) {
|
|
7
|
+
if (nonce || typeof document === 'undefined') {
|
|
8
|
+
return nonce;
|
|
9
|
+
}
|
|
10
|
+
for (const script of document.querySelectorAll('script[nonce]')) {
|
|
11
|
+
if (script.nonce) {
|
|
12
|
+
return script.nonce;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
5
17
|
/** Executes code through a nonce-aware script without using `eval` or `new Function`. */
|
|
6
18
|
async function asyncExecuteCode(code, nonce) {
|
|
7
19
|
var _a;
|
|
8
20
|
const globalScope = window;
|
|
9
21
|
const handlers = ((_a = globalScope[HANDLERS_KEY]) !== null && _a !== void 0 ? _a : (globalScope[HANDLERS_KEY] = {}));
|
|
22
|
+
const resolvedNonce = resolveCspNonce(nonce);
|
|
10
23
|
let id;
|
|
11
24
|
do {
|
|
12
25
|
id = Math.random().toString(36).substring(2);
|
|
13
26
|
} while (handlers[id]);
|
|
14
27
|
const script = document.createElement('script');
|
|
15
|
-
if (
|
|
16
|
-
script.setAttribute('nonce',
|
|
28
|
+
if (resolvedNonce) {
|
|
29
|
+
script.setAttribute('nonce', resolvedNonce);
|
|
17
30
|
}
|
|
18
31
|
const promise = new Promise((resolve, reject) => {
|
|
19
32
|
let wasHandled = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asyncExecuteCode.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/asyncExecuteCode.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"asyncExecuteCode.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/asyncExecuteCode.ts"],"names":[],"mappings":";;AASA,0CAYC;AAGD,4CA6DC;AArFD,MAAM,YAAY,GAAG,6BAA6B,CAAC;AASnD,SAAgB,eAAe,CAAC,KAAc;IAC1C,IAAI,KAAK,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,gBAAgB,CAAoB,eAAe,CAAC,EAAE,CAAC;QACjF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,KAAK,CAAC;QACxB,CAAC;IACL,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,yFAAyF;AAClF,KAAK,UAAU,gBAAgB,CAAI,IAAY,EAAE,KAAc;;IAClE,MAAM,WAAW,GAAG,MAA4C,CAAC;IACjE,MAAM,QAAQ,GAAG,OAAC,WAAW,CAAC,YAAY,qCAAxB,WAAW,CAAC,YAAY,IAAM,EAAE,EAAsB,CAAC;IACzE,MAAM,aAAa,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAE7C,IAAI,EAAU,CAAC;IACf,GAAG,CAAC;QACA,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,QAAQ,QAAQ,CAAC,EAAE,CAAC,EAAE;IAEvB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,aAAa,EAAE,CAAC;QAChB,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC/C,IAAI,UAAU,GAAG,KAAK,CAAC;QAEvB,QAAQ,CAAC,EAAE,CAAC,GAAG;YACX,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACf,UAAU,GAAG,IAAI,CAAC;gBAClB,OAAO,CAAC,KAAU,CAAC,CAAC;YACxB,CAAC;YACD,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;gBACf,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;SACJ,CAAC;QAEF,MAAM,CAAC,WAAW,GAAG;;oBAET,EAAE;cACR,IAAI;;;oBAGE,EAAE;;uBAEC,EAAE;YACb,YAAY,IAAI,CAAC;QAErB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAElC,iFAAiF;QACjF,uFAAuF;QACvF,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,MAAM,CACF,IAAI,KAAK,CACL,oFAAoF,CACvF,CACJ,CAAC;QACN,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;;QACxB,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC;QACpB,MAAA,MAAM,CAAC,UAAU,0CAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAEvC,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,OAAO,WAAW,CAAC,YAAY,CAAC,CAAC;QACrC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["const HANDLERS_KEY = '__gravityUiAikitMdxLoader__';\n\ninterface ExecutionHandler<T> {\n resolve: (value: T) => void;\n reject: (reason?: unknown) => void;\n}\n\ntype ExecutionHandlers = Record<string, ExecutionHandler<unknown>>;\n\nexport function resolveCspNonce(nonce?: string) {\n if (nonce || typeof document === 'undefined') {\n return nonce;\n }\n\n for (const script of document.querySelectorAll<HTMLScriptElement>('script[nonce]')) {\n if (script.nonce) {\n return script.nonce;\n }\n }\n\n return undefined;\n}\n\n/** Executes code through a nonce-aware script without using `eval` or `new Function`. */\nexport async function asyncExecuteCode<T>(code: string, nonce?: string): Promise<T> {\n const globalScope = window as unknown as Record<string, unknown>;\n const handlers = (globalScope[HANDLERS_KEY] ??= {}) as ExecutionHandlers;\n const resolvedNonce = resolveCspNonce(nonce);\n\n let id: string;\n do {\n id = Math.random().toString(36).substring(2);\n } while (handlers[id]);\n\n const script = document.createElement('script');\n if (resolvedNonce) {\n script.setAttribute('nonce', resolvedNonce);\n }\n\n const promise = new Promise<T>((resolve, reject) => {\n let wasHandled = false;\n\n handlers[id] = {\n resolve: (value) => {\n wasHandled = true;\n resolve(value as T);\n },\n reject: (reason) => {\n wasHandled = true;\n reject(reason);\n },\n };\n\n script.textContent = `(function(handlers) {\n try {\n handlers['${id}'].resolve(function() {\n ${code}\n });\n } catch (error) {\n handlers['${id}'].reject(error);\n }\n delete handlers['${id}'];\n})(window.${HANDLERS_KEY});`;\n\n document.head.appendChild(script);\n\n // Inline classic scripts execute synchronously when inserted. If neither handler\n // ran before appendChild returned, the browser most likely blocked the script via CSP.\n if (!wasHandled) {\n reject(\n new Error(\n 'Failed to execute MDX script. It may have been blocked by Content Security Policy.',\n ),\n );\n }\n });\n\n return promise.finally(() => {\n delete handlers[id];\n script.parentNode?.removeChild(script);\n\n if (Object.keys(handlers).length === 0) {\n delete globalScope[HANDLERS_KEY];\n }\n });\n}\n"]}
|
package/build/cjs/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"2.19.2
|
|
1
|
+
{"version":"2.19.2","type":"commonjs","sideEffects":["*.css","*.scss"]}
|
|
@@ -52,7 +52,7 @@ This block is rendered by a **React component**.
|
|
|
52
52
|
components: {Callout},
|
|
53
53
|
// Optional: only treat these tags as MDX components
|
|
54
54
|
tagNames: ['Callout'],
|
|
55
|
-
//
|
|
55
|
+
// Optional: pass the nonce explicitly instead of discovering it from the page
|
|
56
56
|
nonce: cspNonce,
|
|
57
57
|
}}
|
|
58
58
|
/>;
|
|
@@ -63,10 +63,11 @@ This block is rendered by a **React component**.
|
|
|
63
63
|
> blocks and its artifacts must be collected from the whole document.
|
|
64
64
|
|
|
65
65
|
Compiled MDX artifacts are executed through an inline `<script>` instead of `eval` or
|
|
66
|
-
`new Function`. Services with a nonce-based `script-src` Content Security Policy
|
|
67
|
-
nonce through `mdxOptions.nonce`; the renderer applies it to every temporary MDX script.
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
`new Function`. Services with a nonce-based `script-src` Content Security Policy can pass the
|
|
67
|
+
nonce through `mdxOptions.nonce`; the renderer applies it to every temporary MDX script. When the
|
|
68
|
+
option is omitted, the renderer reuses the first non-empty nonce from a
|
|
69
|
+
`<script nonce="...">` in the document. If no nonce is available, the renderer preserves the
|
|
70
|
+
extension's legacy `new Function` execution path for backward compatibility.
|
|
70
71
|
|
|
71
72
|
### Per-message context (`mdxContext` + `useMdxContext`)
|
|
72
73
|
|
|
@@ -128,7 +129,7 @@ instead of a static value. It is called with the concrete message and its return
|
|
|
128
129
|
| ------------ | --------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
129
130
|
| `components` | `MDXComponents` | Yes | - | Map of tag name → React component used to render embedded MDX/JSX in the content (e.g. `{Callout, StatusBadge}`). |
|
|
130
131
|
| `tagNames` | `string[]` | - | - | Restricts which tags are processed as MDX components. When omitted, the extension's default detection is used. |
|
|
131
|
-
| `nonce` | `string` | - | - | CSP nonce applied to temporary inline scripts. When omitted,
|
|
132
|
+
| `nonce` | `string` | - | - | CSP nonce applied to temporary inline scripts. When omitted, it is discovered from an existing script. |
|
|
132
133
|
|
|
133
134
|
## Styling
|
|
134
135
|
|
|
@@ -11,7 +11,7 @@ export interface MarkdownRendererMdxOptions {
|
|
|
11
11
|
components: MDXComponents;
|
|
12
12
|
/** Optional list of tag names to limit which components are processed as MDX. */
|
|
13
13
|
tagNames?: string[];
|
|
14
|
-
/** CSP nonce applied to scripts
|
|
14
|
+
/** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */
|
|
15
15
|
nonce?: string;
|
|
16
16
|
}
|
|
17
17
|
export interface MarkdownRendererProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownRenderer.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MarkdownRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Fragment, type HTMLAttributes, memo, useMemo, useRef} from 'react';\n\nimport {mdxPlugin} from '@diplodoc/mdx-extension';\nimport type {\n ExtendedPluginWithCollect,\n MarkdownIt,\n OptionsType,\n} from '@diplodoc/transform/lib/typings';\nimport type {MDXComponents} from 'mdx/types';\n\nimport {useMarkdownTransform} from '../../../hooks/useMarkdownTransform';\nimport {useRemend} from '../../../hooks/useRemend';\nimport {block} from '../../../utils/cn';\nimport {areOptionsEqual} from '../../../utils/markdownUtils';\n\nimport {MdxPortals} from './MdxPortals';\n\nimport './MarkdownRenderer.scss';\n\nconst b = block('markdown-renderer');\n\n/**\n * Options for rendering embedded MDX/JSX in the markdown content via\n * `@diplodoc/mdx-extension`. Passing `mdxOptions` enables MDX processing.\n */\nexport interface MarkdownRendererMdxOptions {\n /** Map of components rendered from embedded MDX/JSX in the markdown content. */\n components: MDXComponents;\n /** Optional list of tag names to limit which components are processed as MDX. */\n tagNames?: string[];\n /** CSP nonce applied to scripts that execute compiled MDX artifacts. */\n nonce?: string;\n}\n\nexport interface MarkdownRendererProps {\n content: string;\n className?: string;\n qa?: string;\n transformOptions?: OptionsType;\n shouldParseIncompleteMarkdown?: boolean;\n openLinksInNewTab?: boolean;\n mdxOptions?: MarkdownRendererMdxOptions;\n mdxContext?: Record<string, unknown>;\n /** Extra props forwarded to the root container `div` element. */\n extraProps?: HTMLAttributes<HTMLDivElement>;\n}\n\nconst ABSOLUTE_HTTP_URL_RE = /^(https?:)?\\/\\//i;\n\nconst isSameDocumentAnchor = (href: string) => {\n if (href.startsWith('#')) {\n return true;\n }\n\n if (ABSOLUTE_HTTP_URL_RE.test(href) || typeof window === 'undefined') {\n return false;\n }\n\n try {\n const url = new URL(href, window.location.href);\n\n return (\n Boolean(url.hash) &&\n url.origin === window.location.origin &&\n url.pathname === window.location.pathname &&\n url.search === window.location.search\n );\n } catch {\n return false;\n }\n};\n\nconst openLinksInNewTabPlugin: ExtendedPluginWithCollect = ((md: MarkdownIt) => {\n const rendererRules = md.renderer.rules;\n const defaultRender =\n rendererRules.link_open ||\n function (tokens, idx, options, _env, self) {\n return self.renderToken(tokens, idx, options);\n };\n\n rendererRules.link_open = function (tokens, idx, options, env, self) {\n const href = tokens[idx].attrGet('href');\n if (!href || !isSameDocumentAnchor(href)) {\n tokens[idx].attrSet('target', '_blank');\n tokens[idx].attrSet('rel', 'noopener noreferrer');\n }\n\n return defaultRender(tokens, idx, options, env, self);\n };\n}) as ExtendedPluginWithCollect;\n\nfunction MarkdownRendererComponent({\n content,\n className,\n qa,\n transformOptions,\n shouldParseIncompleteMarkdown = false,\n openLinksInNewTab = false,\n mdxOptions,\n mdxContext,\n extraProps,\n}: MarkdownRendererProps) {\n const closedContent = useRemend(content, shouldParseIncompleteMarkdown);\n const enableMdx = Boolean(mdxOptions);\n const mdxComponents = mdxOptions?.components;\n const mdxTagNames = mdxOptions?.tagNames;\n const mdxNonce = mdxOptions?.nonce;\n const finalTransformOptions = useMemo<OptionsType | undefined>(() => {\n const plugins = [...(transformOptions?.plugins ?? [])];\n\n if (openLinksInNewTab) {\n plugins.push(openLinksInNewTabPlugin);\n }\n\n if (enableMdx) {\n plugins.push(\n mdxPlugin(\n mdxTagNames ? {tagNames: mdxTagNames} : undefined,\n ) as unknown as ExtendedPluginWithCollect,\n );\n }\n\n if (plugins.length === 0) {\n return transformOptions;\n }\n\n return {\n ...transformOptions,\n plugins,\n };\n }, [openLinksInNewTab, transformOptions, enableMdx, mdxTagNames]);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const {html, mdxArtifacts} = useMarkdownTransform(\n closedContent,\n finalTransformOptions,\n enableMdx,\n );\n\n return (\n <Fragment>\n <div\n ref={containerRef}\n className={b(null, [className, 'yfm'])}\n data-qa={qa}\n dangerouslySetInnerHTML={{__html: html}}\n {...extraProps}\n />\n {enableMdx ? (\n <MdxPortals\n refCtr={containerRef}\n html={html}\n components={mdxComponents}\n mdxArtifacts={mdxArtifacts}\n nonce={mdxNonce}\n mdxContext={mdxContext}\n />\n ) : null}\n </Fragment>\n );\n}\n\nexport const MarkdownRenderer = memo(MarkdownRendererComponent, (prevProps, nextProps) => {\n if (prevProps.content !== nextProps.content) {\n return false;\n }\n\n if (prevProps.shouldParseIncompleteMarkdown !== nextProps.shouldParseIncompleteMarkdown) {\n return false;\n }\n\n if (prevProps.openLinksInNewTab !== nextProps.openLinksInNewTab) {\n return false;\n }\n\n if (prevProps.className !== nextProps.className) {\n return false;\n }\n\n if (prevProps.qa !== nextProps.qa) {\n return false;\n }\n\n if (prevProps.mdxOptions?.components !== nextProps.mdxOptions?.components) {\n return false;\n }\n\n if (prevProps.mdxOptions?.tagNames !== nextProps.mdxOptions?.tagNames) {\n return false;\n }\n\n if (prevProps.mdxOptions?.nonce !== nextProps.mdxOptions?.nonce) {\n return false;\n }\n\n if (prevProps.mdxContext !== nextProps.mdxContext) {\n return false;\n }\n\n if (prevProps.extraProps !== nextProps.extraProps) {\n return false;\n }\n\n return areOptionsEqual(prevProps.transformOptions, nextProps.transformOptions);\n});\n\nMarkdownRenderer.displayName = 'MarkdownRenderer';\n"]}
|
|
1
|
+
{"version":3,"file":"MarkdownRenderer.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MarkdownRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Fragment, type HTMLAttributes, memo, useMemo, useRef} from 'react';\n\nimport {mdxPlugin} from '@diplodoc/mdx-extension';\nimport type {\n ExtendedPluginWithCollect,\n MarkdownIt,\n OptionsType,\n} from '@diplodoc/transform/lib/typings';\nimport type {MDXComponents} from 'mdx/types';\n\nimport {useMarkdownTransform} from '../../../hooks/useMarkdownTransform';\nimport {useRemend} from '../../../hooks/useRemend';\nimport {block} from '../../../utils/cn';\nimport {areOptionsEqual} from '../../../utils/markdownUtils';\n\nimport {MdxPortals} from './MdxPortals';\n\nimport './MarkdownRenderer.scss';\n\nconst b = block('markdown-renderer');\n\n/**\n * Options for rendering embedded MDX/JSX in the markdown content via\n * `@diplodoc/mdx-extension`. Passing `mdxOptions` enables MDX processing.\n */\nexport interface MarkdownRendererMdxOptions {\n /** Map of components rendered from embedded MDX/JSX in the markdown content. */\n components: MDXComponents;\n /** Optional list of tag names to limit which components are processed as MDX. */\n tagNames?: string[];\n /** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */\n nonce?: string;\n}\n\nexport interface MarkdownRendererProps {\n content: string;\n className?: string;\n qa?: string;\n transformOptions?: OptionsType;\n shouldParseIncompleteMarkdown?: boolean;\n openLinksInNewTab?: boolean;\n mdxOptions?: MarkdownRendererMdxOptions;\n mdxContext?: Record<string, unknown>;\n /** Extra props forwarded to the root container `div` element. */\n extraProps?: HTMLAttributes<HTMLDivElement>;\n}\n\nconst ABSOLUTE_HTTP_URL_RE = /^(https?:)?\\/\\//i;\n\nconst isSameDocumentAnchor = (href: string) => {\n if (href.startsWith('#')) {\n return true;\n }\n\n if (ABSOLUTE_HTTP_URL_RE.test(href) || typeof window === 'undefined') {\n return false;\n }\n\n try {\n const url = new URL(href, window.location.href);\n\n return (\n Boolean(url.hash) &&\n url.origin === window.location.origin &&\n url.pathname === window.location.pathname &&\n url.search === window.location.search\n );\n } catch {\n return false;\n }\n};\n\nconst openLinksInNewTabPlugin: ExtendedPluginWithCollect = ((md: MarkdownIt) => {\n const rendererRules = md.renderer.rules;\n const defaultRender =\n rendererRules.link_open ||\n function (tokens, idx, options, _env, self) {\n return self.renderToken(tokens, idx, options);\n };\n\n rendererRules.link_open = function (tokens, idx, options, env, self) {\n const href = tokens[idx].attrGet('href');\n if (!href || !isSameDocumentAnchor(href)) {\n tokens[idx].attrSet('target', '_blank');\n tokens[idx].attrSet('rel', 'noopener noreferrer');\n }\n\n return defaultRender(tokens, idx, options, env, self);\n };\n}) as ExtendedPluginWithCollect;\n\nfunction MarkdownRendererComponent({\n content,\n className,\n qa,\n transformOptions,\n shouldParseIncompleteMarkdown = false,\n openLinksInNewTab = false,\n mdxOptions,\n mdxContext,\n extraProps,\n}: MarkdownRendererProps) {\n const closedContent = useRemend(content, shouldParseIncompleteMarkdown);\n const enableMdx = Boolean(mdxOptions);\n const mdxComponents = mdxOptions?.components;\n const mdxTagNames = mdxOptions?.tagNames;\n const mdxNonce = mdxOptions?.nonce;\n const finalTransformOptions = useMemo<OptionsType | undefined>(() => {\n const plugins = [...(transformOptions?.plugins ?? [])];\n\n if (openLinksInNewTab) {\n plugins.push(openLinksInNewTabPlugin);\n }\n\n if (enableMdx) {\n plugins.push(\n mdxPlugin(\n mdxTagNames ? {tagNames: mdxTagNames} : undefined,\n ) as unknown as ExtendedPluginWithCollect,\n );\n }\n\n if (plugins.length === 0) {\n return transformOptions;\n }\n\n return {\n ...transformOptions,\n plugins,\n };\n }, [openLinksInNewTab, transformOptions, enableMdx, mdxTagNames]);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const {html, mdxArtifacts} = useMarkdownTransform(\n closedContent,\n finalTransformOptions,\n enableMdx,\n );\n\n return (\n <Fragment>\n <div\n ref={containerRef}\n className={b(null, [className, 'yfm'])}\n data-qa={qa}\n dangerouslySetInnerHTML={{__html: html}}\n {...extraProps}\n />\n {enableMdx ? (\n <MdxPortals\n refCtr={containerRef}\n html={html}\n components={mdxComponents}\n mdxArtifacts={mdxArtifacts}\n nonce={mdxNonce}\n mdxContext={mdxContext}\n />\n ) : null}\n </Fragment>\n );\n}\n\nexport const MarkdownRenderer = memo(MarkdownRendererComponent, (prevProps, nextProps) => {\n if (prevProps.content !== nextProps.content) {\n return false;\n }\n\n if (prevProps.shouldParseIncompleteMarkdown !== nextProps.shouldParseIncompleteMarkdown) {\n return false;\n }\n\n if (prevProps.openLinksInNewTab !== nextProps.openLinksInNewTab) {\n return false;\n }\n\n if (prevProps.className !== nextProps.className) {\n return false;\n }\n\n if (prevProps.qa !== nextProps.qa) {\n return false;\n }\n\n if (prevProps.mdxOptions?.components !== nextProps.mdxOptions?.components) {\n return false;\n }\n\n if (prevProps.mdxOptions?.tagNames !== nextProps.mdxOptions?.tagNames) {\n return false;\n }\n\n if (prevProps.mdxOptions?.nonce !== nextProps.mdxOptions?.nonce) {\n return false;\n }\n\n if (prevProps.mdxContext !== nextProps.mdxContext) {\n return false;\n }\n\n if (prevProps.extraProps !== nextProps.extraProps) {\n return false;\n }\n\n return areOptionsEqual(prevProps.transformOptions, nextProps.transformOptions);\n});\n\nMarkdownRenderer.displayName = 'MarkdownRenderer';\n"]}
|
|
@@ -11,7 +11,7 @@ export interface MdxPortalsProps {
|
|
|
11
11
|
components?: MDXComponents;
|
|
12
12
|
/** Artifacts collected by the MDX transform, required to hydrate the components. */
|
|
13
13
|
mdxArtifacts?: MdxArtifacts;
|
|
14
|
-
/** CSP nonce applied to scripts
|
|
14
|
+
/** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */
|
|
15
15
|
nonce?: string;
|
|
16
16
|
/** Arbitrary value exposed to the MDX components through {@link MdxDataContext}. */
|
|
17
17
|
mdxContext?: Record<string, unknown>;
|
|
@@ -3,12 +3,13 @@ import { useEffect, useState } from 'react';
|
|
|
3
3
|
import { useMdx } from '@diplodoc/mdx-extension';
|
|
4
4
|
import * as runtime from 'react/jsx-runtime';
|
|
5
5
|
import { MdxDataContext } from "./MdxContext.js";
|
|
6
|
-
import { asyncExecuteCode } from "./asyncExecuteCode.js";
|
|
6
|
+
import { asyncExecuteCode, resolveCspNonce } from "./asyncExecuteCode.js";
|
|
7
7
|
function useMdxComponentLoader(mdxArtifacts, nonce) {
|
|
8
8
|
const idMdx = mdxArtifacts === null || mdxArtifacts === void 0 ? void 0 : mdxArtifacts.idMdx;
|
|
9
|
+
const resolvedNonce = resolveCspNonce(nonce);
|
|
9
10
|
const [state, setState] = useState({ isSuccess: false });
|
|
10
11
|
useEffect(() => {
|
|
11
|
-
if (!
|
|
12
|
+
if (!resolvedNonce) {
|
|
12
13
|
return () => undefined;
|
|
13
14
|
}
|
|
14
15
|
let isActive = true;
|
|
@@ -16,30 +17,30 @@ function useMdxComponentLoader(mdxArtifacts, nonce) {
|
|
|
16
17
|
try {
|
|
17
18
|
const data = {};
|
|
18
19
|
for (const [artifactId, code] of Object.entries(idMdx !== null && idMdx !== void 0 ? idMdx : {})) {
|
|
19
|
-
const fn = await asyncExecuteCode(code,
|
|
20
|
+
const fn = await asyncExecuteCode(code, resolvedNonce);
|
|
20
21
|
if (!isActive) {
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
24
|
data[artifactId] = fn(runtime).default;
|
|
24
25
|
}
|
|
25
26
|
if (isActive) {
|
|
26
|
-
setState({ idMdx, nonce, data, isSuccess: true });
|
|
27
|
+
setState({ idMdx, nonce: resolvedNonce, data, isSuccess: true });
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
catch (_a) {
|
|
30
31
|
if (isActive) {
|
|
31
|
-
setState({ idMdx, nonce, isSuccess: false });
|
|
32
|
+
setState({ idMdx, nonce: resolvedNonce, isSuccess: false });
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
})();
|
|
35
36
|
return () => {
|
|
36
37
|
isActive = false;
|
|
37
38
|
};
|
|
38
|
-
}, [idMdx,
|
|
39
|
-
if (!
|
|
39
|
+
}, [idMdx, resolvedNonce]);
|
|
40
|
+
if (!resolvedNonce) {
|
|
40
41
|
return undefined;
|
|
41
42
|
}
|
|
42
|
-
if (state.idMdx !== idMdx || state.nonce !==
|
|
43
|
+
if (state.idMdx !== idMdx || state.nonce !== resolvedNonce) {
|
|
43
44
|
return { isSuccess: false };
|
|
44
45
|
}
|
|
45
46
|
return state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MdxPortals.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MdxPortals.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAG1C,OAAO,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAG/C,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAC,cAAc,EAAC,wBAAqB;AAC5C,OAAO,EAAC,gBAAgB,EAAC,8BAA2B;
|
|
1
|
+
{"version":3,"file":"MdxPortals.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/MdxPortals.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useState} from 'react';\nimport type {RefObject} from 'react';\n\nimport {useMdx} from '@diplodoc/mdx-extension';\nimport type {IdMdxComponentLoader, MdxArtifacts} from '@diplodoc/mdx-extension';\nimport type {MDXComponents, MDXModule, MDXProps} from 'mdx/types';\nimport * as runtime from 'react/jsx-runtime';\n\nimport {MdxDataContext} from './MdxContext';\nimport {asyncExecuteCode, resolveCspNonce} from './asyncExecuteCode';\n\ninterface MdxLoaderState extends IdMdxComponentLoader {\n idMdx?: Record<string, string>;\n nonce?: string;\n}\n\nfunction useMdxComponentLoader(mdxArtifacts: MdxArtifacts | undefined, nonce?: string) {\n const idMdx = mdxArtifacts?.idMdx;\n const resolvedNonce = resolveCspNonce(nonce);\n const [state, setState] = useState<MdxLoaderState>({isSuccess: false});\n\n useEffect(() => {\n if (!resolvedNonce) {\n return () => undefined;\n }\n\n let isActive = true;\n\n (async () => {\n try {\n const data: Record<string, React.ComponentType<MDXProps>> = {};\n\n for (const [artifactId, code] of Object.entries(idMdx ?? {})) {\n const fn = await asyncExecuteCode<(jsxRuntime: typeof runtime) => MDXModule>(\n code,\n resolvedNonce,\n );\n\n if (!isActive) {\n return;\n }\n\n data[artifactId] = fn(runtime).default;\n }\n\n if (isActive) {\n setState({idMdx, nonce: resolvedNonce, data, isSuccess: true});\n }\n } catch {\n if (isActive) {\n setState({idMdx, nonce: resolvedNonce, isSuccess: false});\n }\n }\n })();\n\n return () => {\n isActive = false;\n };\n }, [idMdx, resolvedNonce]);\n\n if (!resolvedNonce) {\n return undefined;\n }\n\n if (state.idMdx !== idMdx || state.nonce !== resolvedNonce) {\n return {isSuccess: false};\n }\n\n return state;\n}\n\nexport interface MdxPortalsProps {\n /** Ref to the container element into which the rendered HTML is injected. */\n refCtr: RefObject<HTMLDivElement | null>;\n /** HTML produced by the markdown transform for the current content. */\n html: string;\n /** Map of components rendered from embedded MDX/JSX in the markdown content. */\n components?: MDXComponents;\n /** Artifacts collected by the MDX transform, required to hydrate the components. */\n mdxArtifacts?: MdxArtifacts;\n /** CSP nonce applied to compiled MDX scripts. Defaults to a nonce found in the document. */\n nonce?: string;\n /** Arbitrary value exposed to the MDX components through {@link MdxDataContext}. */\n mdxContext?: Record<string, unknown>;\n}\n\nexport function MdxPortals({\n refCtr,\n html,\n components,\n mdxArtifacts,\n nonce,\n mdxContext,\n}: MdxPortalsProps) {\n const idMdxComponentLoader = useMdxComponentLoader(mdxArtifacts, nonce);\n const portals = useMdx({\n refCtr,\n html,\n components,\n mdxArtifacts,\n contextList: [MdxDataContext],\n idMdxComponentLoader,\n });\n\n return <MdxDataContext.Provider value={mdxContext}>{portals}</MdxDataContext.Provider>;\n}\n\nMdxPortals.displayName = 'MdxPortals';\n"]}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
const HANDLERS_KEY = '__gravityUiAikitMdxLoader__';
|
|
2
|
+
export function resolveCspNonce(nonce) {
|
|
3
|
+
if (nonce || typeof document === 'undefined') {
|
|
4
|
+
return nonce;
|
|
5
|
+
}
|
|
6
|
+
for (const script of document.querySelectorAll('script[nonce]')) {
|
|
7
|
+
if (script.nonce) {
|
|
8
|
+
return script.nonce;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
2
13
|
/** Executes code through a nonce-aware script without using `eval` or `new Function`. */
|
|
3
14
|
export async function asyncExecuteCode(code, nonce) {
|
|
4
15
|
var _a;
|
|
5
16
|
const globalScope = window;
|
|
6
17
|
const handlers = ((_a = globalScope[HANDLERS_KEY]) !== null && _a !== void 0 ? _a : (globalScope[HANDLERS_KEY] = {}));
|
|
18
|
+
const resolvedNonce = resolveCspNonce(nonce);
|
|
7
19
|
let id;
|
|
8
20
|
do {
|
|
9
21
|
id = Math.random().toString(36).substring(2);
|
|
10
22
|
} while (handlers[id]);
|
|
11
23
|
const script = document.createElement('script');
|
|
12
|
-
if (
|
|
13
|
-
script.setAttribute('nonce',
|
|
24
|
+
if (resolvedNonce) {
|
|
25
|
+
script.setAttribute('nonce', resolvedNonce);
|
|
14
26
|
}
|
|
15
27
|
const promise = new Promise((resolve, reject) => {
|
|
16
28
|
let wasHandled = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asyncExecuteCode.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/asyncExecuteCode.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,6BAA6B,CAAC;AASnD,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAI,IAAY,EAAE,KAAc;;IAClE,MAAM,WAAW,GAAG,MAA4C,CAAC;IACjE,MAAM,QAAQ,GAAG,OAAC,WAAW,CAAC,YAAY,qCAAxB,WAAW,CAAC,YAAY,IAAM,EAAE,EAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"asyncExecuteCode.js","sourceRoot":"../../../../../src","sources":["components/atoms/MarkdownRenderer/asyncExecuteCode.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,6BAA6B,CAAC;AASnD,MAAM,UAAU,eAAe,CAAC,KAAc;IAC1C,IAAI,KAAK,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,gBAAgB,CAAoB,eAAe,CAAC,EAAE,CAAC;QACjF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,KAAK,CAAC;QACxB,CAAC;IACL,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAI,IAAY,EAAE,KAAc;;IAClE,MAAM,WAAW,GAAG,MAA4C,CAAC;IACjE,MAAM,QAAQ,GAAG,OAAC,WAAW,CAAC,YAAY,qCAAxB,WAAW,CAAC,YAAY,IAAM,EAAE,EAAsB,CAAC;IACzE,MAAM,aAAa,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAE7C,IAAI,EAAU,CAAC;IACf,GAAG,CAAC;QACA,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,QAAQ,QAAQ,CAAC,EAAE,CAAC,EAAE;IAEvB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,aAAa,EAAE,CAAC;QAChB,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC/C,IAAI,UAAU,GAAG,KAAK,CAAC;QAEvB,QAAQ,CAAC,EAAE,CAAC,GAAG;YACX,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACf,UAAU,GAAG,IAAI,CAAC;gBAClB,OAAO,CAAC,KAAU,CAAC,CAAC;YACxB,CAAC;YACD,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;gBACf,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;SACJ,CAAC;QAEF,MAAM,CAAC,WAAW,GAAG;;oBAET,EAAE;cACR,IAAI;;;oBAGE,EAAE;;uBAEC,EAAE;YACb,YAAY,IAAI,CAAC;QAErB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAElC,iFAAiF;QACjF,uFAAuF;QACvF,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,MAAM,CACF,IAAI,KAAK,CACL,oFAAoF,CACvF,CACJ,CAAC;QACN,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;;QACxB,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC;QACpB,MAAA,MAAM,CAAC,UAAU,0CAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAEvC,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,OAAO,WAAW,CAAC,YAAY,CAAC,CAAC;QACrC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["const HANDLERS_KEY = '__gravityUiAikitMdxLoader__';\n\ninterface ExecutionHandler<T> {\n resolve: (value: T) => void;\n reject: (reason?: unknown) => void;\n}\n\ntype ExecutionHandlers = Record<string, ExecutionHandler<unknown>>;\n\nexport function resolveCspNonce(nonce?: string) {\n if (nonce || typeof document === 'undefined') {\n return nonce;\n }\n\n for (const script of document.querySelectorAll<HTMLScriptElement>('script[nonce]')) {\n if (script.nonce) {\n return script.nonce;\n }\n }\n\n return undefined;\n}\n\n/** Executes code through a nonce-aware script without using `eval` or `new Function`. */\nexport async function asyncExecuteCode<T>(code: string, nonce?: string): Promise<T> {\n const globalScope = window as unknown as Record<string, unknown>;\n const handlers = (globalScope[HANDLERS_KEY] ??= {}) as ExecutionHandlers;\n const resolvedNonce = resolveCspNonce(nonce);\n\n let id: string;\n do {\n id = Math.random().toString(36).substring(2);\n } while (handlers[id]);\n\n const script = document.createElement('script');\n if (resolvedNonce) {\n script.setAttribute('nonce', resolvedNonce);\n }\n\n const promise = new Promise<T>((resolve, reject) => {\n let wasHandled = false;\n\n handlers[id] = {\n resolve: (value) => {\n wasHandled = true;\n resolve(value as T);\n },\n reject: (reason) => {\n wasHandled = true;\n reject(reason);\n },\n };\n\n script.textContent = `(function(handlers) {\n try {\n handlers['${id}'].resolve(function() {\n ${code}\n });\n } catch (error) {\n handlers['${id}'].reject(error);\n }\n delete handlers['${id}'];\n})(window.${HANDLERS_KEY});`;\n\n document.head.appendChild(script);\n\n // Inline classic scripts execute synchronously when inserted. If neither handler\n // ran before appendChild returned, the browser most likely blocked the script via CSP.\n if (!wasHandled) {\n reject(\n new Error(\n 'Failed to execute MDX script. It may have been blocked by Content Security Policy.',\n ),\n );\n }\n });\n\n return promise.finally(() => {\n delete handlers[id];\n script.parentNode?.removeChild(script);\n\n if (Object.keys(handlers).length === 0) {\n delete globalScope[HANDLERS_KEY];\n }\n });\n}\n"]}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"2.19.2
|
|
1
|
+
{"version":"2.19.2","type":"module","sideEffects":["*.css","*.scss"]}
|
package/package.json
CHANGED