@apify/ui-library 0.58.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/src/components/simple_markdown/simple_markdown.d.ts +1 -1
- package/dist/src/components/simple_markdown/simple_markdown.d.ts.map +1 -1
- package/dist/src/components/simple_markdown/simple_markdown.js +29 -4
- package/dist/src/components/simple_markdown/simple_markdown.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -3
- package/src/components/simple_markdown/simple_markdown.tsx +38 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apify/ui-library",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.0",
|
|
4
4
|
"description": "React UI library used by apify.com",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
"rehype-sanitize": "^6.0.0",
|
|
42
42
|
"remark-gfm": "^3.0.1",
|
|
43
43
|
"remark-toc": "8.0.1",
|
|
44
|
-
"slugify": "^1.6.6"
|
|
44
|
+
"slugify": "^1.6.6",
|
|
45
|
+
"unified": "^10.0.0",
|
|
46
|
+
"unist-util-visit": "^5.0.0"
|
|
45
47
|
},
|
|
46
48
|
"peerDependencies": {
|
|
47
49
|
"react": "17.x || 18.x",
|
|
@@ -65,5 +67,5 @@
|
|
|
65
67
|
"recast": "^0.23.9",
|
|
66
68
|
"typescript": "^5.1.6"
|
|
67
69
|
},
|
|
68
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "aff5f2f1a3db4fa021ade9588f4d923e59527e8b"
|
|
69
71
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Root, Element, Text as TextNode } from 'hast';
|
|
1
2
|
import React, { useCallback, useMemo, useRef } from 'react';
|
|
2
3
|
import type { Components } from 'react-markdown';
|
|
3
4
|
import ReactMarkdown, { uriTransformer } from 'react-markdown';
|
|
@@ -6,6 +7,8 @@ import rehypeRaw from 'rehype-raw';
|
|
|
6
7
|
import rehypeSanitize from 'rehype-sanitize';
|
|
7
8
|
import remarkGfm from 'remark-gfm';
|
|
8
9
|
import styled from 'styled-components';
|
|
10
|
+
import type { Pluggable, PluggableList } from 'unified';
|
|
11
|
+
import { visit } from 'unist-util-visit';
|
|
9
12
|
|
|
10
13
|
import { theme } from '../../design_system/theme.js';
|
|
11
14
|
import { useSharedUiDependencies } from '../../ui_dependency_provider.js';
|
|
@@ -43,8 +46,33 @@ const StyledMarkdown = styled(ReactMarkdown)`
|
|
|
43
46
|
}
|
|
44
47
|
`;
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
// Function to recursively process unsupported elements
|
|
50
|
+
const unwrapUnsupportedElement = (node: Element): (Element | TextNode)[] => {
|
|
51
|
+
return node.children.flatMap((child) => {
|
|
52
|
+
if (child.type === 'text') {
|
|
53
|
+
return child; // Keep text as is
|
|
54
|
+
}
|
|
55
|
+
if (child.type === 'element') {
|
|
56
|
+
if (defaultAllowedElements.includes(child.tagName)) {
|
|
57
|
+
return child; // Keep supported elements
|
|
58
|
+
}
|
|
59
|
+
return unwrapUnsupportedElement(child as Element);
|
|
60
|
+
}
|
|
61
|
+
return []; // Ignore other node types
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getUnsupportedRehypeTagsSanitationPlugIn = (
|
|
66
|
+
allowedElements: string[],
|
|
67
|
+
): Pluggable<any[]> => () => (tree: Root) => {
|
|
68
|
+
visit(tree, 'element', (node, index, parent) => {
|
|
69
|
+
if (!allowedElements.includes(node.tagName) && parent && typeof index === 'number') {
|
|
70
|
+
// Replace unsupported element with its valid children
|
|
71
|
+
parent.children.splice(index, 1, ...unwrapUnsupportedElement(node));
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
48
76
|
export const defaultAllowedElements = [
|
|
49
77
|
'a',
|
|
50
78
|
'b',
|
|
@@ -79,6 +107,9 @@ export const defaultAllowedElements = [
|
|
|
79
107
|
'ul',
|
|
80
108
|
];
|
|
81
109
|
|
|
110
|
+
export const defaultRehypePlugins = [rehypeRaw];
|
|
111
|
+
export const defaultRemarkPlugins = [remarkGfm];
|
|
112
|
+
|
|
82
113
|
// TODO: Add Image component
|
|
83
114
|
const regularMarkdownSizeComponents: Components = {
|
|
84
115
|
h1: ({ children }) => <HeadingContent mt='space32' mb='space16' type='heading1'>{children}</HeadingContent>,
|
|
@@ -151,13 +182,15 @@ export const SimpleMarkdown: React.FC<SimpleMarkdownProps> = ({
|
|
|
151
182
|
}) => {
|
|
152
183
|
const cleanedMarkdown = useMemo(() => cleanMarkdown(markdown), [markdown]);
|
|
153
184
|
|
|
185
|
+
const effectiveAllowedElements = useRef(allowedElements || defaultAllowedElements);
|
|
186
|
+
|
|
154
187
|
const effectiveComponents = useRef({
|
|
155
188
|
...(size === 'regular' ? regularMarkdownSizeComponents : smallMarkdownSizeComponents),
|
|
156
189
|
...components,
|
|
157
190
|
});
|
|
158
191
|
|
|
159
|
-
const rehypePluginsRef = useRef([
|
|
160
|
-
...(rehypePlugins || defaultRehypePlugins),
|
|
192
|
+
const rehypePluginsRef = useRef<PluggableList>([
|
|
193
|
+
...(rehypePlugins || [...defaultRehypePlugins, getUnsupportedRehypeTagsSanitationPlugIn(effectiveAllowedElements.current)]),
|
|
161
194
|
rehypeSanitize, // lets always sanitize the output
|
|
162
195
|
]);
|
|
163
196
|
|
|
@@ -168,7 +201,7 @@ export const SimpleMarkdown: React.FC<SimpleMarkdownProps> = ({
|
|
|
168
201
|
components={effectiveComponents.current}
|
|
169
202
|
rehypePlugins={rehypePluginsRef.current}
|
|
170
203
|
remarkPlugins={remarkPlugins || defaultRemarkPlugins}
|
|
171
|
-
allowedElements={
|
|
204
|
+
allowedElements={effectiveAllowedElements.current}
|
|
172
205
|
transformLinkUri={(href, children, title) => {
|
|
173
206
|
const transformed = transformLinkUri ? transformLinkUri(href, children, title) : defaultUrlTransform(href);
|
|
174
207
|
return uriTransformer(transformed);
|