jvetrau-ds 0.2.31 → 0.2.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/index.d.ts +1 -1
- package/components/markdown/index.d.ts +1 -1
- package/components/markdown/markdown.cjs +89 -4
- package/components/markdown/markdown.cjs.map +1 -1
- package/components/markdown/markdown.d.ts +5 -0
- package/components/markdown/markdown.js +88 -4
- package/components/markdown/markdown.js.map +1 -1
- package/index.d.ts +1 -1
- package/package.json +1 -1
package/components/index.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export type { CardGroupProps } from './card-group/card-group';
|
|
|
50
50
|
export { default as Breadcrumbs } from './breadcrumbs/breadcrumbs';
|
|
51
51
|
export type { BreadcrumbsProps } from './breadcrumbs/breadcrumbs';
|
|
52
52
|
export { default as Markdown } from './markdown/markdown';
|
|
53
|
-
export type { MarkdownProps } from './markdown/markdown';
|
|
53
|
+
export type { MarkdownEmbed, MarkdownProps, } from './markdown/markdown';
|
|
54
54
|
export { default as Discussion } from './discussion/discussion';
|
|
55
55
|
export type { DiscussionItem, DiscussionProps, } from './discussion/discussion';
|
|
56
56
|
export { default as CourseOutline } from './course-outline/course-outline';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default } from './markdown';
|
|
2
|
-
export type { MarkdownProps } from './markdown';
|
|
2
|
+
export type { MarkdownEmbed, MarkdownProps, } from './markdown';
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var ReactMarkdown = require('react-markdown');
|
|
5
|
+
var remarkDirective = require('remark-directive');
|
|
5
6
|
var remarkGfm = require('remark-gfm');
|
|
6
7
|
require('./markdown.css');
|
|
7
8
|
var classnames = require('../helpers/classnames');
|
|
@@ -9,6 +10,7 @@ var classnames = require('../helpers/classnames');
|
|
|
9
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
11
|
|
|
11
12
|
var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
|
|
13
|
+
var remarkDirective__default = /*#__PURE__*/_interopDefault(remarkDirective);
|
|
12
14
|
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
13
15
|
|
|
14
16
|
function normalizeHeadingLevelOffset(value) {
|
|
@@ -35,6 +37,55 @@ function appendNodesWithSeparator(target, nodes) {
|
|
|
35
37
|
}
|
|
36
38
|
target.push(...nodes);
|
|
37
39
|
}
|
|
40
|
+
function getNodeText(node) {
|
|
41
|
+
if (typeof node.value === "string") {
|
|
42
|
+
return node.value;
|
|
43
|
+
}
|
|
44
|
+
return (node.children ?? []).map(getNodeText).join("");
|
|
45
|
+
}
|
|
46
|
+
function getEmbed(node) {
|
|
47
|
+
if (node.type !== "leafDirective" || node.name !== "embed") {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const src = node.attributes?.src ?? "";
|
|
51
|
+
const label = getNodeText(node);
|
|
52
|
+
if (!src.trim() || !label.trim()) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
src,
|
|
57
|
+
label
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function transformEmbedNodes(nodes) {
|
|
61
|
+
for (const node of nodes) {
|
|
62
|
+
if (node.type === "leafDirective" && node.name === "embed") {
|
|
63
|
+
const embed = getEmbed(node);
|
|
64
|
+
node.data = {
|
|
65
|
+
...node.data,
|
|
66
|
+
hName: "div",
|
|
67
|
+
hProperties: embed ? {
|
|
68
|
+
"data-markdown-embed": "true",
|
|
69
|
+
"data-markdown-embed-src": embed.src,
|
|
70
|
+
"data-markdown-embed-label": embed.label
|
|
71
|
+
} : {
|
|
72
|
+
"data-markdown-embed": "invalid"
|
|
73
|
+
},
|
|
74
|
+
hChildren: []
|
|
75
|
+
};
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (node.children) {
|
|
79
|
+
transformEmbedNodes(node.children);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const remarkEmbed = () => {
|
|
84
|
+
return (tree) => {
|
|
85
|
+
const root = tree;
|
|
86
|
+
transformEmbedNodes(root.children);
|
|
87
|
+
};
|
|
88
|
+
};
|
|
38
89
|
function flattenInlineNode(node) {
|
|
39
90
|
switch (node.type) {
|
|
40
91
|
case "html":
|
|
@@ -82,6 +133,12 @@ function flattenBlockNode(node) {
|
|
|
82
133
|
value: node.value
|
|
83
134
|
}
|
|
84
135
|
] : [];
|
|
136
|
+
case "leafDirective": {
|
|
137
|
+
const embed = getEmbed(node);
|
|
138
|
+
return embed ? [
|
|
139
|
+
createTextNode(embed.label)
|
|
140
|
+
] : [];
|
|
141
|
+
}
|
|
85
142
|
case "html":
|
|
86
143
|
case "definition":
|
|
87
144
|
case "footnoteDefinition":
|
|
@@ -142,7 +199,7 @@ const MarkdownHeading = ({
|
|
|
142
199
|
return /* @__PURE__ */ jsxRuntime.jsx("h6", { ...props, children });
|
|
143
200
|
}
|
|
144
201
|
};
|
|
145
|
-
function createDocumentComponents(headingLevelOffset) {
|
|
202
|
+
function createDocumentComponents(headingLevelOffset, renderEmbed) {
|
|
146
203
|
return {
|
|
147
204
|
h1: ({ node: _node, ...headingProps }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
148
205
|
MarkdownHeading,
|
|
@@ -191,13 +248,35 @@ function createDocumentComponents(headingLevelOffset) {
|
|
|
191
248
|
sourceLevel: 6,
|
|
192
249
|
offset: headingLevelOffset
|
|
193
250
|
}
|
|
194
|
-
)
|
|
251
|
+
),
|
|
252
|
+
div: ({
|
|
253
|
+
node: _node,
|
|
254
|
+
...divProps
|
|
255
|
+
}) => {
|
|
256
|
+
const {
|
|
257
|
+
"data-markdown-embed": embedMarker,
|
|
258
|
+
"data-markdown-embed-src": embedSrc,
|
|
259
|
+
"data-markdown-embed-label": embedLabel,
|
|
260
|
+
...props
|
|
261
|
+
} = divProps;
|
|
262
|
+
if (embedMarker !== void 0) {
|
|
263
|
+
if (embedMarker !== "true" || !embedSrc || !embedLabel || !renderEmbed) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
return renderEmbed({
|
|
267
|
+
src: embedSrc,
|
|
268
|
+
label: embedLabel
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props });
|
|
272
|
+
}
|
|
195
273
|
};
|
|
196
274
|
}
|
|
197
275
|
const Markdown = ({
|
|
198
276
|
content,
|
|
199
277
|
excerpt = false,
|
|
200
278
|
headingLevelOffset = 0,
|
|
279
|
+
renderEmbed,
|
|
201
280
|
className = "",
|
|
202
281
|
...props
|
|
203
282
|
}) => {
|
|
@@ -218,6 +297,7 @@ const Markdown = ({
|
|
|
218
297
|
{
|
|
219
298
|
remarkPlugins: [
|
|
220
299
|
remarkGfm__default.default,
|
|
300
|
+
remarkDirective__default.default,
|
|
221
301
|
remarkExcerpt
|
|
222
302
|
],
|
|
223
303
|
children: content
|
|
@@ -228,7 +308,8 @@ const Markdown = ({
|
|
|
228
308
|
}
|
|
229
309
|
const normalizedHeadingLevelOffset = normalizeHeadingLevelOffset(headingLevelOffset);
|
|
230
310
|
const documentComponents = createDocumentComponents(
|
|
231
|
-
normalizedHeadingLevelOffset
|
|
311
|
+
normalizedHeadingLevelOffset,
|
|
312
|
+
renderEmbed
|
|
232
313
|
);
|
|
233
314
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
234
315
|
"div",
|
|
@@ -238,7 +319,11 @@ const Markdown = ({
|
|
|
238
319
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
239
320
|
ReactMarkdown__default.default,
|
|
240
321
|
{
|
|
241
|
-
remarkPlugins: [
|
|
322
|
+
remarkPlugins: [
|
|
323
|
+
remarkGfm__default.default,
|
|
324
|
+
remarkDirective__default.default,
|
|
325
|
+
remarkEmbed
|
|
326
|
+
],
|
|
242
327
|
components: documentComponents,
|
|
243
328
|
children: content
|
|
244
329
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/markdown/markdown.tsx"],"names":["jsx","classnames","ReactMarkdown","remarkGfm"],"mappings":"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","file":"markdown.cjs","sourcesContent":["import React from 'react';\nimport ReactMarkdown, { type Components } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport type { Plugin } from 'unified';\n\nimport './markdown.css';\nimport { classnames } from '../helpers/classnames';\n\nexport interface MarkdownProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children' | 'dangerouslySetInnerHTML'\n > {\n content: string;\n excerpt?: boolean;\n headingLevelOffset?: number;\n}\n\ninterface MarkdownHeadingProps\n extends React.HTMLAttributes<HTMLHeadingElement> {\n sourceLevel: number;\n offset: number;\n}\n\ntype MarkdownNode = {\n type: string;\n value?: string;\n alt?: string | null;\n children?: MarkdownNode[];\n [key: string]: unknown;\n};\n\ntype MarkdownRoot = {\n type: 'root';\n children: MarkdownNode[];\n};\n\nfunction normalizeHeadingLevelOffset(value: number | undefined) {\n if (value === undefined || !Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n\nfunction getHeadingLevel(\n sourceLevel: number,\n offset: number,\n) {\n return Math.min(6, sourceLevel + offset);\n}\n\nfunction createTextNode(value: string): MarkdownNode {\n return {\n type: 'text',\n value,\n };\n}\n\nfunction appendNodesWithSeparator(\n target: MarkdownNode[],\n nodes: MarkdownNode[],\n) {\n if (nodes.length === 0) {\n return;\n }\n\n if (target.length > 0) {\n target.push(createTextNode(' '));\n }\n\n target.push(...nodes);\n}\n\nfunction flattenInlineNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'html':\n return [];\n\n case 'break':\n return [\n createTextNode(' '),\n ];\n\n case 'image':\n case 'imageReference':\n return node.alt\n ? [\n createTextNode(node.alt),\n ]\n : [];\n\n default:\n if (!node.children) {\n return [\n node,\n ];\n }\n\n return [\n {\n ...node,\n children: node.children.flatMap(\n flattenInlineNode,\n ),\n },\n ];\n }\n}\n\nfunction flattenBlockNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'paragraph':\n case 'heading':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'tableCell':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'code':\n return node.value\n ? [\n {\n type: 'inlineCode',\n value: node.value,\n },\n ]\n : [];\n\n case 'html':\n case 'definition':\n case 'footnoteDefinition':\n case 'thematicBreak':\n case 'yaml':\n return [];\n\n case 'blockquote':\n case 'list':\n case 'listItem':\n case 'table':\n case 'tableRow':\n return flattenBlockNodes(node.children ?? []);\n\n default:\n return node.children\n ? flattenBlockNodes(node.children)\n : [];\n }\n}\n\nfunction flattenBlockNodes(\n nodes: MarkdownNode[],\n): MarkdownNode[] {\n const result: MarkdownNode[] = [];\n\n for (const node of nodes) {\n appendNodesWithSeparator(\n result,\n flattenBlockNode(node),\n );\n }\n\n return result;\n}\n\nconst remarkExcerpt: Plugin = () => {\n return (tree) => {\n const root = tree as MarkdownRoot;\n const children = flattenBlockNodes(root.children);\n\n root.children = children.length > 0\n ? [\n {\n type: 'paragraph',\n children,\n },\n ]\n : [];\n };\n};\n\nconst MarkdownHeading: React.FC<MarkdownHeadingProps> = ({\n sourceLevel,\n offset,\n children,\n ...props\n}) => {\n const level = getHeadingLevel(sourceLevel, offset);\n\n switch (level) {\n case 1:\n return <h1 {...props}>{children}</h1>;\n\n case 2:\n return <h2 {...props}>{children}</h2>;\n\n case 3:\n return <h3 {...props}>{children}</h3>;\n\n case 4:\n return <h4 {...props}>{children}</h4>;\n\n case 5:\n return <h5 {...props}>{children}</h5>;\n\n default:\n return <h6 {...props}>{children}</h6>;\n }\n};\n\nfunction createDocumentComponents(\n headingLevelOffset: number,\n): Components {\n return {\n h1: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={1}\n offset={headingLevelOffset}\n />\n ),\n\n h2: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={2}\n offset={headingLevelOffset}\n />\n ),\n\n h3: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={3}\n offset={headingLevelOffset}\n />\n ),\n\n h4: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={4}\n offset={headingLevelOffset}\n />\n ),\n\n h5: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={5}\n offset={headingLevelOffset}\n />\n ),\n\n h6: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={6}\n offset={headingLevelOffset}\n />\n ),\n };\n}\n\nconst Markdown: React.FC<MarkdownProps> = ({\n content,\n excerpt = false,\n headingLevelOffset = 0,\n className = '',\n ...props\n}) => {\n if (!content.trim()) {\n return null;\n }\n\n const classes = classnames('markdown', className, {\n 'markdown--excerpt': excerpt,\n });\n\n if (excerpt) {\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[\n remarkGfm,\n remarkExcerpt,\n ]}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n }\n\n const normalizedHeadingLevelOffset =\n normalizeHeadingLevelOffset(headingLevelOffset);\n\n const documentComponents = createDocumentComponents(\n normalizedHeadingLevelOffset,\n );\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={documentComponents}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n};\n\nexport default Markdown;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/markdown/markdown.tsx"],"names":["jsx","classnames","ReactMarkdown","remarkGfm","remarkDirective"],"mappings":"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","file":"markdown.cjs","sourcesContent":["import React from 'react';\nimport ReactMarkdown, { type Components } from 'react-markdown';\nimport remarkDirective from 'remark-directive';\nimport remarkGfm from 'remark-gfm';\nimport type { Plugin } from 'unified';\n\nimport './markdown.css';\nimport { classnames } from '../helpers/classnames';\n\nexport interface MarkdownEmbed {\n src: string;\n label: string;\n}\n\nexport interface MarkdownProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children' | 'dangerouslySetInnerHTML'\n > {\n content: string;\n excerpt?: boolean;\n headingLevelOffset?: number;\n renderEmbed?: (\n embed: MarkdownEmbed,\n ) => React.ReactNode;\n}\n\ninterface MarkdownHeadingProps\n extends React.HTMLAttributes<HTMLHeadingElement> {\n sourceLevel: number;\n offset: number;\n}\n\ntype MarkdownNodeData = {\n hName?: string;\n hProperties?: Record<string, unknown>;\n hChildren?: MarkdownNode[];\n [key: string]: unknown;\n};\n\ntype MarkdownNode = {\n type: string;\n name?: string;\n value?: string;\n alt?: string | null;\n attributes?: Record<\n string,\n string | null | undefined\n >;\n data?: MarkdownNodeData;\n children?: MarkdownNode[];\n [key: string]: unknown;\n};\n\ntype MarkdownRoot = {\n type: 'root';\n children: MarkdownNode[];\n};\n\ntype MarkdownEmbedDivProps =\n React.HTMLAttributes<HTMLDivElement> & {\n 'data-markdown-embed'?: string;\n 'data-markdown-embed-src'?: string;\n 'data-markdown-embed-label'?: string;\n };\n\nfunction normalizeHeadingLevelOffset(value: number | undefined) {\n if (value === undefined || !Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n\nfunction getHeadingLevel(\n sourceLevel: number,\n offset: number,\n) {\n return Math.min(6, sourceLevel + offset);\n}\n\nfunction createTextNode(value: string): MarkdownNode {\n return {\n type: 'text',\n value,\n };\n}\n\nfunction appendNodesWithSeparator(\n target: MarkdownNode[],\n nodes: MarkdownNode[],\n) {\n if (nodes.length === 0) {\n return;\n }\n\n if (target.length > 0) {\n target.push(createTextNode(' '));\n }\n\n target.push(...nodes);\n}\n\nfunction getNodeText(node: MarkdownNode): string {\n if (typeof node.value === 'string') {\n return node.value;\n }\n\n return (node.children ?? [])\n .map(getNodeText)\n .join('');\n}\n\nfunction getEmbed(\n node: MarkdownNode,\n): MarkdownEmbed | null {\n if (\n node.type !== 'leafDirective' ||\n node.name !== 'embed'\n ) {\n return null;\n }\n\n const src = node.attributes?.src ?? '';\n const label = getNodeText(node);\n\n if (!src.trim() || !label.trim()) {\n return null;\n }\n\n return {\n src,\n label,\n };\n}\n\nfunction transformEmbedNodes(\n nodes: MarkdownNode[],\n) {\n for (const node of nodes) {\n if (\n node.type === 'leafDirective' &&\n node.name === 'embed'\n ) {\n const embed = getEmbed(node);\n\n node.data = {\n ...node.data,\n hName: 'div',\n hProperties: embed\n ? {\n 'data-markdown-embed': 'true',\n 'data-markdown-embed-src':\n embed.src,\n 'data-markdown-embed-label':\n embed.label,\n }\n : {\n 'data-markdown-embed':\n 'invalid',\n },\n hChildren: [],\n };\n\n continue;\n }\n\n if (node.children) {\n transformEmbedNodes(node.children);\n }\n }\n}\n\nconst remarkEmbed: Plugin = () => {\n return (tree) => {\n const root = tree as MarkdownRoot;\n\n transformEmbedNodes(root.children);\n };\n};\n\nfunction flattenInlineNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'html':\n return [];\n\n case 'break':\n return [\n createTextNode(' '),\n ];\n\n case 'image':\n case 'imageReference':\n return node.alt\n ? [\n createTextNode(node.alt),\n ]\n : [];\n\n default:\n if (!node.children) {\n return [\n node,\n ];\n }\n\n return [\n {\n ...node,\n children: node.children.flatMap(\n flattenInlineNode,\n ),\n },\n ];\n }\n}\n\nfunction flattenBlockNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'paragraph':\n case 'heading':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'tableCell':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'code':\n return node.value\n ? [\n {\n type: 'inlineCode',\n value: node.value,\n },\n ]\n : [];\n\n case 'leafDirective': {\n const embed = getEmbed(node);\n\n return embed\n ? [\n createTextNode(embed.label),\n ]\n : [];\n }\n\n case 'html':\n case 'definition':\n case 'footnoteDefinition':\n case 'thematicBreak':\n case 'yaml':\n return [];\n\n case 'blockquote':\n case 'list':\n case 'listItem':\n case 'table':\n case 'tableRow':\n return flattenBlockNodes(node.children ?? []);\n\n default:\n return node.children\n ? flattenBlockNodes(node.children)\n : [];\n }\n}\n\nfunction flattenBlockNodes(\n nodes: MarkdownNode[],\n): MarkdownNode[] {\n const result: MarkdownNode[] = [];\n\n for (const node of nodes) {\n appendNodesWithSeparator(\n result,\n flattenBlockNode(node),\n );\n }\n\n return result;\n}\n\nconst remarkExcerpt: Plugin = () => {\n return (tree) => {\n const root = tree as MarkdownRoot;\n const children = flattenBlockNodes(root.children);\n\n root.children = children.length > 0\n ? [\n {\n type: 'paragraph',\n children,\n },\n ]\n : [];\n };\n};\n\nconst MarkdownHeading: React.FC<MarkdownHeadingProps> = ({\n sourceLevel,\n offset,\n children,\n ...props\n}) => {\n const level = getHeadingLevel(sourceLevel, offset);\n\n switch (level) {\n case 1:\n return <h1 {...props}>{children}</h1>;\n\n case 2:\n return <h2 {...props}>{children}</h2>;\n\n case 3:\n return <h3 {...props}>{children}</h3>;\n\n case 4:\n return <h4 {...props}>{children}</h4>;\n\n case 5:\n return <h5 {...props}>{children}</h5>;\n\n default:\n return <h6 {...props}>{children}</h6>;\n }\n};\n\nfunction createDocumentComponents(\n headingLevelOffset: number,\n renderEmbed:\n | ((\n embed: MarkdownEmbed,\n ) => React.ReactNode)\n | undefined,\n): Components {\n return {\n h1: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={1}\n offset={headingLevelOffset}\n />\n ),\n\n h2: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={2}\n offset={headingLevelOffset}\n />\n ),\n\n h3: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={3}\n offset={headingLevelOffset}\n />\n ),\n\n h4: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={4}\n offset={headingLevelOffset}\n />\n ),\n\n h5: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={5}\n offset={headingLevelOffset}\n />\n ),\n\n h6: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={6}\n offset={headingLevelOffset}\n />\n ),\n\n div: ({\n node: _node,\n ...divProps\n }) => {\n const {\n 'data-markdown-embed':\n embedMarker,\n 'data-markdown-embed-src':\n embedSrc,\n 'data-markdown-embed-label':\n embedLabel,\n ...props\n } = divProps as MarkdownEmbedDivProps;\n\n if (embedMarker !== undefined) {\n if (\n embedMarker !== 'true' ||\n !embedSrc ||\n !embedLabel ||\n !renderEmbed\n ) {\n return null;\n }\n\n return renderEmbed({\n src: embedSrc,\n label: embedLabel,\n });\n }\n\n return <div {...props} />;\n },\n };\n}\n\nconst Markdown: React.FC<MarkdownProps> = ({\n content,\n excerpt = false,\n headingLevelOffset = 0,\n renderEmbed,\n className = '',\n ...props\n}) => {\n if (!content.trim()) {\n return null;\n }\n\n const classes = classnames('markdown', className, {\n 'markdown--excerpt': excerpt,\n });\n\n if (excerpt) {\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[\n remarkGfm,\n remarkDirective,\n remarkExcerpt,\n ]}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n }\n\n const normalizedHeadingLevelOffset =\n normalizeHeadingLevelOffset(headingLevelOffset);\n\n const documentComponents = createDocumentComponents(\n normalizedHeadingLevelOffset,\n renderEmbed,\n );\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[\n remarkGfm,\n remarkDirective,\n remarkEmbed,\n ]}\n components={documentComponents}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n};\n\nexport default Markdown;\n"]}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import './markdown.css';
|
|
3
|
+
export interface MarkdownEmbed {
|
|
4
|
+
src: string;
|
|
5
|
+
label: string;
|
|
6
|
+
}
|
|
3
7
|
export interface MarkdownProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'dangerouslySetInnerHTML'> {
|
|
4
8
|
content: string;
|
|
5
9
|
excerpt?: boolean;
|
|
6
10
|
headingLevelOffset?: number;
|
|
11
|
+
renderEmbed?: (embed: MarkdownEmbed) => React.ReactNode;
|
|
7
12
|
}
|
|
8
13
|
declare const Markdown: React.FC<MarkdownProps>;
|
|
9
14
|
export default Markdown;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import ReactMarkdown from 'react-markdown';
|
|
3
|
+
import remarkDirective from 'remark-directive';
|
|
3
4
|
import remarkGfm from 'remark-gfm';
|
|
4
5
|
import './markdown.css';
|
|
5
6
|
import { classnames } from '../helpers/classnames';
|
|
@@ -28,6 +29,55 @@ function appendNodesWithSeparator(target, nodes) {
|
|
|
28
29
|
}
|
|
29
30
|
target.push(...nodes);
|
|
30
31
|
}
|
|
32
|
+
function getNodeText(node) {
|
|
33
|
+
if (typeof node.value === "string") {
|
|
34
|
+
return node.value;
|
|
35
|
+
}
|
|
36
|
+
return (node.children ?? []).map(getNodeText).join("");
|
|
37
|
+
}
|
|
38
|
+
function getEmbed(node) {
|
|
39
|
+
if (node.type !== "leafDirective" || node.name !== "embed") {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const src = node.attributes?.src ?? "";
|
|
43
|
+
const label = getNodeText(node);
|
|
44
|
+
if (!src.trim() || !label.trim()) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
src,
|
|
49
|
+
label
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function transformEmbedNodes(nodes) {
|
|
53
|
+
for (const node of nodes) {
|
|
54
|
+
if (node.type === "leafDirective" && node.name === "embed") {
|
|
55
|
+
const embed = getEmbed(node);
|
|
56
|
+
node.data = {
|
|
57
|
+
...node.data,
|
|
58
|
+
hName: "div",
|
|
59
|
+
hProperties: embed ? {
|
|
60
|
+
"data-markdown-embed": "true",
|
|
61
|
+
"data-markdown-embed-src": embed.src,
|
|
62
|
+
"data-markdown-embed-label": embed.label
|
|
63
|
+
} : {
|
|
64
|
+
"data-markdown-embed": "invalid"
|
|
65
|
+
},
|
|
66
|
+
hChildren: []
|
|
67
|
+
};
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (node.children) {
|
|
71
|
+
transformEmbedNodes(node.children);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const remarkEmbed = () => {
|
|
76
|
+
return (tree) => {
|
|
77
|
+
const root = tree;
|
|
78
|
+
transformEmbedNodes(root.children);
|
|
79
|
+
};
|
|
80
|
+
};
|
|
31
81
|
function flattenInlineNode(node) {
|
|
32
82
|
switch (node.type) {
|
|
33
83
|
case "html":
|
|
@@ -75,6 +125,12 @@ function flattenBlockNode(node) {
|
|
|
75
125
|
value: node.value
|
|
76
126
|
}
|
|
77
127
|
] : [];
|
|
128
|
+
case "leafDirective": {
|
|
129
|
+
const embed = getEmbed(node);
|
|
130
|
+
return embed ? [
|
|
131
|
+
createTextNode(embed.label)
|
|
132
|
+
] : [];
|
|
133
|
+
}
|
|
78
134
|
case "html":
|
|
79
135
|
case "definition":
|
|
80
136
|
case "footnoteDefinition":
|
|
@@ -135,7 +191,7 @@ const MarkdownHeading = ({
|
|
|
135
191
|
return /* @__PURE__ */ jsx("h6", { ...props, children });
|
|
136
192
|
}
|
|
137
193
|
};
|
|
138
|
-
function createDocumentComponents(headingLevelOffset) {
|
|
194
|
+
function createDocumentComponents(headingLevelOffset, renderEmbed) {
|
|
139
195
|
return {
|
|
140
196
|
h1: ({ node: _node, ...headingProps }) => /* @__PURE__ */ jsx(
|
|
141
197
|
MarkdownHeading,
|
|
@@ -184,13 +240,35 @@ function createDocumentComponents(headingLevelOffset) {
|
|
|
184
240
|
sourceLevel: 6,
|
|
185
241
|
offset: headingLevelOffset
|
|
186
242
|
}
|
|
187
|
-
)
|
|
243
|
+
),
|
|
244
|
+
div: ({
|
|
245
|
+
node: _node,
|
|
246
|
+
...divProps
|
|
247
|
+
}) => {
|
|
248
|
+
const {
|
|
249
|
+
"data-markdown-embed": embedMarker,
|
|
250
|
+
"data-markdown-embed-src": embedSrc,
|
|
251
|
+
"data-markdown-embed-label": embedLabel,
|
|
252
|
+
...props
|
|
253
|
+
} = divProps;
|
|
254
|
+
if (embedMarker !== void 0) {
|
|
255
|
+
if (embedMarker !== "true" || !embedSrc || !embedLabel || !renderEmbed) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
return renderEmbed({
|
|
259
|
+
src: embedSrc,
|
|
260
|
+
label: embedLabel
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return /* @__PURE__ */ jsx("div", { ...props });
|
|
264
|
+
}
|
|
188
265
|
};
|
|
189
266
|
}
|
|
190
267
|
const Markdown = ({
|
|
191
268
|
content,
|
|
192
269
|
excerpt = false,
|
|
193
270
|
headingLevelOffset = 0,
|
|
271
|
+
renderEmbed,
|
|
194
272
|
className = "",
|
|
195
273
|
...props
|
|
196
274
|
}) => {
|
|
@@ -211,6 +289,7 @@ const Markdown = ({
|
|
|
211
289
|
{
|
|
212
290
|
remarkPlugins: [
|
|
213
291
|
remarkGfm,
|
|
292
|
+
remarkDirective,
|
|
214
293
|
remarkExcerpt
|
|
215
294
|
],
|
|
216
295
|
children: content
|
|
@@ -221,7 +300,8 @@ const Markdown = ({
|
|
|
221
300
|
}
|
|
222
301
|
const normalizedHeadingLevelOffset = normalizeHeadingLevelOffset(headingLevelOffset);
|
|
223
302
|
const documentComponents = createDocumentComponents(
|
|
224
|
-
normalizedHeadingLevelOffset
|
|
303
|
+
normalizedHeadingLevelOffset,
|
|
304
|
+
renderEmbed
|
|
225
305
|
);
|
|
226
306
|
return /* @__PURE__ */ jsx(
|
|
227
307
|
"div",
|
|
@@ -231,7 +311,11 @@ const Markdown = ({
|
|
|
231
311
|
children: /* @__PURE__ */ jsx(
|
|
232
312
|
ReactMarkdown,
|
|
233
313
|
{
|
|
234
|
-
remarkPlugins: [
|
|
314
|
+
remarkPlugins: [
|
|
315
|
+
remarkGfm,
|
|
316
|
+
remarkDirective,
|
|
317
|
+
remarkEmbed
|
|
318
|
+
],
|
|
235
319
|
components: documentComponents,
|
|
236
320
|
children: content
|
|
237
321
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/markdown/markdown.tsx"],"names":[],"mappings":"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","file":"markdown.js","sourcesContent":["import React from 'react';\nimport ReactMarkdown, { type Components } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport type { Plugin } from 'unified';\n\nimport './markdown.css';\nimport { classnames } from '../helpers/classnames';\n\nexport interface MarkdownProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children' | 'dangerouslySetInnerHTML'\n > {\n content: string;\n excerpt?: boolean;\n headingLevelOffset?: number;\n}\n\ninterface MarkdownHeadingProps\n extends React.HTMLAttributes<HTMLHeadingElement> {\n sourceLevel: number;\n offset: number;\n}\n\ntype MarkdownNode = {\n type: string;\n value?: string;\n alt?: string | null;\n children?: MarkdownNode[];\n [key: string]: unknown;\n};\n\ntype MarkdownRoot = {\n type: 'root';\n children: MarkdownNode[];\n};\n\nfunction normalizeHeadingLevelOffset(value: number | undefined) {\n if (value === undefined || !Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n\nfunction getHeadingLevel(\n sourceLevel: number,\n offset: number,\n) {\n return Math.min(6, sourceLevel + offset);\n}\n\nfunction createTextNode(value: string): MarkdownNode {\n return {\n type: 'text',\n value,\n };\n}\n\nfunction appendNodesWithSeparator(\n target: MarkdownNode[],\n nodes: MarkdownNode[],\n) {\n if (nodes.length === 0) {\n return;\n }\n\n if (target.length > 0) {\n target.push(createTextNode(' '));\n }\n\n target.push(...nodes);\n}\n\nfunction flattenInlineNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'html':\n return [];\n\n case 'break':\n return [\n createTextNode(' '),\n ];\n\n case 'image':\n case 'imageReference':\n return node.alt\n ? [\n createTextNode(node.alt),\n ]\n : [];\n\n default:\n if (!node.children) {\n return [\n node,\n ];\n }\n\n return [\n {\n ...node,\n children: node.children.flatMap(\n flattenInlineNode,\n ),\n },\n ];\n }\n}\n\nfunction flattenBlockNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'paragraph':\n case 'heading':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'tableCell':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'code':\n return node.value\n ? [\n {\n type: 'inlineCode',\n value: node.value,\n },\n ]\n : [];\n\n case 'html':\n case 'definition':\n case 'footnoteDefinition':\n case 'thematicBreak':\n case 'yaml':\n return [];\n\n case 'blockquote':\n case 'list':\n case 'listItem':\n case 'table':\n case 'tableRow':\n return flattenBlockNodes(node.children ?? []);\n\n default:\n return node.children\n ? flattenBlockNodes(node.children)\n : [];\n }\n}\n\nfunction flattenBlockNodes(\n nodes: MarkdownNode[],\n): MarkdownNode[] {\n const result: MarkdownNode[] = [];\n\n for (const node of nodes) {\n appendNodesWithSeparator(\n result,\n flattenBlockNode(node),\n );\n }\n\n return result;\n}\n\nconst remarkExcerpt: Plugin = () => {\n return (tree) => {\n const root = tree as MarkdownRoot;\n const children = flattenBlockNodes(root.children);\n\n root.children = children.length > 0\n ? [\n {\n type: 'paragraph',\n children,\n },\n ]\n : [];\n };\n};\n\nconst MarkdownHeading: React.FC<MarkdownHeadingProps> = ({\n sourceLevel,\n offset,\n children,\n ...props\n}) => {\n const level = getHeadingLevel(sourceLevel, offset);\n\n switch (level) {\n case 1:\n return <h1 {...props}>{children}</h1>;\n\n case 2:\n return <h2 {...props}>{children}</h2>;\n\n case 3:\n return <h3 {...props}>{children}</h3>;\n\n case 4:\n return <h4 {...props}>{children}</h4>;\n\n case 5:\n return <h5 {...props}>{children}</h5>;\n\n default:\n return <h6 {...props}>{children}</h6>;\n }\n};\n\nfunction createDocumentComponents(\n headingLevelOffset: number,\n): Components {\n return {\n h1: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={1}\n offset={headingLevelOffset}\n />\n ),\n\n h2: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={2}\n offset={headingLevelOffset}\n />\n ),\n\n h3: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={3}\n offset={headingLevelOffset}\n />\n ),\n\n h4: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={4}\n offset={headingLevelOffset}\n />\n ),\n\n h5: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={5}\n offset={headingLevelOffset}\n />\n ),\n\n h6: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={6}\n offset={headingLevelOffset}\n />\n ),\n };\n}\n\nconst Markdown: React.FC<MarkdownProps> = ({\n content,\n excerpt = false,\n headingLevelOffset = 0,\n className = '',\n ...props\n}) => {\n if (!content.trim()) {\n return null;\n }\n\n const classes = classnames('markdown', className, {\n 'markdown--excerpt': excerpt,\n });\n\n if (excerpt) {\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[\n remarkGfm,\n remarkExcerpt,\n ]}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n }\n\n const normalizedHeadingLevelOffset =\n normalizeHeadingLevelOffset(headingLevelOffset);\n\n const documentComponents = createDocumentComponents(\n normalizedHeadingLevelOffset,\n );\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={documentComponents}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n};\n\nexport default Markdown;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/markdown/markdown.tsx"],"names":[],"mappings":"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","file":"markdown.js","sourcesContent":["import React from 'react';\nimport ReactMarkdown, { type Components } from 'react-markdown';\nimport remarkDirective from 'remark-directive';\nimport remarkGfm from 'remark-gfm';\nimport type { Plugin } from 'unified';\n\nimport './markdown.css';\nimport { classnames } from '../helpers/classnames';\n\nexport interface MarkdownEmbed {\n src: string;\n label: string;\n}\n\nexport interface MarkdownProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children' | 'dangerouslySetInnerHTML'\n > {\n content: string;\n excerpt?: boolean;\n headingLevelOffset?: number;\n renderEmbed?: (\n embed: MarkdownEmbed,\n ) => React.ReactNode;\n}\n\ninterface MarkdownHeadingProps\n extends React.HTMLAttributes<HTMLHeadingElement> {\n sourceLevel: number;\n offset: number;\n}\n\ntype MarkdownNodeData = {\n hName?: string;\n hProperties?: Record<string, unknown>;\n hChildren?: MarkdownNode[];\n [key: string]: unknown;\n};\n\ntype MarkdownNode = {\n type: string;\n name?: string;\n value?: string;\n alt?: string | null;\n attributes?: Record<\n string,\n string | null | undefined\n >;\n data?: MarkdownNodeData;\n children?: MarkdownNode[];\n [key: string]: unknown;\n};\n\ntype MarkdownRoot = {\n type: 'root';\n children: MarkdownNode[];\n};\n\ntype MarkdownEmbedDivProps =\n React.HTMLAttributes<HTMLDivElement> & {\n 'data-markdown-embed'?: string;\n 'data-markdown-embed-src'?: string;\n 'data-markdown-embed-label'?: string;\n };\n\nfunction normalizeHeadingLevelOffset(value: number | undefined) {\n if (value === undefined || !Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n\nfunction getHeadingLevel(\n sourceLevel: number,\n offset: number,\n) {\n return Math.min(6, sourceLevel + offset);\n}\n\nfunction createTextNode(value: string): MarkdownNode {\n return {\n type: 'text',\n value,\n };\n}\n\nfunction appendNodesWithSeparator(\n target: MarkdownNode[],\n nodes: MarkdownNode[],\n) {\n if (nodes.length === 0) {\n return;\n }\n\n if (target.length > 0) {\n target.push(createTextNode(' '));\n }\n\n target.push(...nodes);\n}\n\nfunction getNodeText(node: MarkdownNode): string {\n if (typeof node.value === 'string') {\n return node.value;\n }\n\n return (node.children ?? [])\n .map(getNodeText)\n .join('');\n}\n\nfunction getEmbed(\n node: MarkdownNode,\n): MarkdownEmbed | null {\n if (\n node.type !== 'leafDirective' ||\n node.name !== 'embed'\n ) {\n return null;\n }\n\n const src = node.attributes?.src ?? '';\n const label = getNodeText(node);\n\n if (!src.trim() || !label.trim()) {\n return null;\n }\n\n return {\n src,\n label,\n };\n}\n\nfunction transformEmbedNodes(\n nodes: MarkdownNode[],\n) {\n for (const node of nodes) {\n if (\n node.type === 'leafDirective' &&\n node.name === 'embed'\n ) {\n const embed = getEmbed(node);\n\n node.data = {\n ...node.data,\n hName: 'div',\n hProperties: embed\n ? {\n 'data-markdown-embed': 'true',\n 'data-markdown-embed-src':\n embed.src,\n 'data-markdown-embed-label':\n embed.label,\n }\n : {\n 'data-markdown-embed':\n 'invalid',\n },\n hChildren: [],\n };\n\n continue;\n }\n\n if (node.children) {\n transformEmbedNodes(node.children);\n }\n }\n}\n\nconst remarkEmbed: Plugin = () => {\n return (tree) => {\n const root = tree as MarkdownRoot;\n\n transformEmbedNodes(root.children);\n };\n};\n\nfunction flattenInlineNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'html':\n return [];\n\n case 'break':\n return [\n createTextNode(' '),\n ];\n\n case 'image':\n case 'imageReference':\n return node.alt\n ? [\n createTextNode(node.alt),\n ]\n : [];\n\n default:\n if (!node.children) {\n return [\n node,\n ];\n }\n\n return [\n {\n ...node,\n children: node.children.flatMap(\n flattenInlineNode,\n ),\n },\n ];\n }\n}\n\nfunction flattenBlockNode(\n node: MarkdownNode,\n): MarkdownNode[] {\n switch (node.type) {\n case 'paragraph':\n case 'heading':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'tableCell':\n return (node.children ?? []).flatMap(\n flattenInlineNode,\n );\n\n case 'code':\n return node.value\n ? [\n {\n type: 'inlineCode',\n value: node.value,\n },\n ]\n : [];\n\n case 'leafDirective': {\n const embed = getEmbed(node);\n\n return embed\n ? [\n createTextNode(embed.label),\n ]\n : [];\n }\n\n case 'html':\n case 'definition':\n case 'footnoteDefinition':\n case 'thematicBreak':\n case 'yaml':\n return [];\n\n case 'blockquote':\n case 'list':\n case 'listItem':\n case 'table':\n case 'tableRow':\n return flattenBlockNodes(node.children ?? []);\n\n default:\n return node.children\n ? flattenBlockNodes(node.children)\n : [];\n }\n}\n\nfunction flattenBlockNodes(\n nodes: MarkdownNode[],\n): MarkdownNode[] {\n const result: MarkdownNode[] = [];\n\n for (const node of nodes) {\n appendNodesWithSeparator(\n result,\n flattenBlockNode(node),\n );\n }\n\n return result;\n}\n\nconst remarkExcerpt: Plugin = () => {\n return (tree) => {\n const root = tree as MarkdownRoot;\n const children = flattenBlockNodes(root.children);\n\n root.children = children.length > 0\n ? [\n {\n type: 'paragraph',\n children,\n },\n ]\n : [];\n };\n};\n\nconst MarkdownHeading: React.FC<MarkdownHeadingProps> = ({\n sourceLevel,\n offset,\n children,\n ...props\n}) => {\n const level = getHeadingLevel(sourceLevel, offset);\n\n switch (level) {\n case 1:\n return <h1 {...props}>{children}</h1>;\n\n case 2:\n return <h2 {...props}>{children}</h2>;\n\n case 3:\n return <h3 {...props}>{children}</h3>;\n\n case 4:\n return <h4 {...props}>{children}</h4>;\n\n case 5:\n return <h5 {...props}>{children}</h5>;\n\n default:\n return <h6 {...props}>{children}</h6>;\n }\n};\n\nfunction createDocumentComponents(\n headingLevelOffset: number,\n renderEmbed:\n | ((\n embed: MarkdownEmbed,\n ) => React.ReactNode)\n | undefined,\n): Components {\n return {\n h1: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={1}\n offset={headingLevelOffset}\n />\n ),\n\n h2: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={2}\n offset={headingLevelOffset}\n />\n ),\n\n h3: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={3}\n offset={headingLevelOffset}\n />\n ),\n\n h4: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={4}\n offset={headingLevelOffset}\n />\n ),\n\n h5: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={5}\n offset={headingLevelOffset}\n />\n ),\n\n h6: ({ node: _node, ...headingProps }) => (\n <MarkdownHeading\n {...headingProps}\n sourceLevel={6}\n offset={headingLevelOffset}\n />\n ),\n\n div: ({\n node: _node,\n ...divProps\n }) => {\n const {\n 'data-markdown-embed':\n embedMarker,\n 'data-markdown-embed-src':\n embedSrc,\n 'data-markdown-embed-label':\n embedLabel,\n ...props\n } = divProps as MarkdownEmbedDivProps;\n\n if (embedMarker !== undefined) {\n if (\n embedMarker !== 'true' ||\n !embedSrc ||\n !embedLabel ||\n !renderEmbed\n ) {\n return null;\n }\n\n return renderEmbed({\n src: embedSrc,\n label: embedLabel,\n });\n }\n\n return <div {...props} />;\n },\n };\n}\n\nconst Markdown: React.FC<MarkdownProps> = ({\n content,\n excerpt = false,\n headingLevelOffset = 0,\n renderEmbed,\n className = '',\n ...props\n}) => {\n if (!content.trim()) {\n return null;\n }\n\n const classes = classnames('markdown', className, {\n 'markdown--excerpt': excerpt,\n });\n\n if (excerpt) {\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[\n remarkGfm,\n remarkDirective,\n remarkExcerpt,\n ]}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n }\n\n const normalizedHeadingLevelOffset =\n normalizeHeadingLevelOffset(headingLevelOffset);\n\n const documentComponents = createDocumentComponents(\n normalizedHeadingLevelOffset,\n renderEmbed,\n );\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ReactMarkdown\n remarkPlugins={[\n remarkGfm,\n remarkDirective,\n remarkEmbed,\n ]}\n components={documentComponents}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n};\n\nexport default Markdown;\n"]}
|
package/index.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ export type { CardGroupProps } from './components/card-group';
|
|
|
58
58
|
export { default as Breadcrumbs } from './components/breadcrumbs';
|
|
59
59
|
export type { BreadcrumbsProps } from './components/breadcrumbs';
|
|
60
60
|
export { default as Markdown } from './components/markdown';
|
|
61
|
-
export type { MarkdownProps } from './components/markdown';
|
|
61
|
+
export type { MarkdownEmbed, MarkdownProps, } from './components/markdown';
|
|
62
62
|
export { default as Discussion } from './components/discussion';
|
|
63
63
|
export type { DiscussionItem, DiscussionProps, } from './components/discussion';
|
|
64
64
|
export { default as CourseOutline } from './components/course-outline';
|