@openneuro/app 4.21.3 → 4.22.0-alpha.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/package.json +8 -6
- package/src/scripts/common/containers/header.tsx +10 -3
- package/src/scripts/dataset/__tests__/__snapshots__/snapshot-container.spec.tsx.snap +12 -0
- package/src/scripts/dataset/components/MetaDataBlock.tsx +1 -1
- package/src/scripts/dataset/components/MetaDataListBlock.tsx +10 -1
- package/src/scripts/dataset/draft-container.tsx +1 -1
- package/src/scripts/dataset/files/__tests__/__snapshots__/file-tree.spec.jsx.snap +1 -0
- package/src/scripts/dataset/fragments/edit-description-list.jsx +1 -1
- package/src/scripts/dataset/routes/dataset-default.tsx +1 -1
- package/src/scripts/dataset/routes/snapshot-default.tsx +1 -1
- package/src/scripts/dataset/snapshot-container.tsx +4 -3
- package/src/scripts/search/search-container.tsx +2 -0
- package/src/scripts/search/use-search-results.tsx +1 -1
- package/src/scripts/utils/__tests__/__snapshots__/markdown.spec.tsx.snap +57 -0
- package/src/scripts/utils/__tests__/markdown.spec.tsx +35 -0
- package/src/scripts/utils/markdown.tsx +167 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openneuro/app",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.22.0-alpha.0",
|
|
4
4
|
"description": "React JS web frontend for the OpenNeuro platform.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "public/client.js",
|
|
@@ -20,18 +20,19 @@
|
|
|
20
20
|
"@emotion/react": "11.11.1",
|
|
21
21
|
"@emotion/styled": "11.11.0",
|
|
22
22
|
"@niivue/niivue": "0.34.0",
|
|
23
|
-
"@openneuro/client": "^4.
|
|
24
|
-
"@openneuro/components": "^4.
|
|
23
|
+
"@openneuro/client": "^4.22.0-alpha.0",
|
|
24
|
+
"@openneuro/components": "^4.22.0-alpha.0",
|
|
25
25
|
"@tanstack/react-table": "^8.9.3",
|
|
26
26
|
"bids-validator": "1.13.0",
|
|
27
27
|
"bytes": "^3.0.0",
|
|
28
28
|
"comlink": "^4.0.5",
|
|
29
29
|
"date-fns": "^2.16.1",
|
|
30
|
+
"dompurify": "^3.0.8",
|
|
30
31
|
"draft-js": "^0.11.7",
|
|
31
32
|
"email-validator": "^2.0.4",
|
|
32
33
|
"graphql": "16.8.1",
|
|
33
34
|
"jwt-decode": "^2.2.0",
|
|
34
|
-
"markdown-to-jsx": "^7.
|
|
35
|
+
"markdown-to-jsx": "^7.4.0",
|
|
35
36
|
"pluralize": "8.0.0",
|
|
36
37
|
"prop-types": "^15.6.0",
|
|
37
38
|
"react": "^17.0.1",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@testing-library/jest-dom": "6.1.3",
|
|
51
52
|
"@testing-library/react": "^11.1.0",
|
|
53
|
+
"@types/dompurify": "^3",
|
|
52
54
|
"@types/jsdom": "^16",
|
|
53
55
|
"@types/node": "18.11.9",
|
|
54
56
|
"@types/react": "^17.0.8",
|
|
@@ -64,11 +66,11 @@
|
|
|
64
66
|
"sass": "^1.32.8",
|
|
65
67
|
"stream-browserify": "^3.0.0",
|
|
66
68
|
"typescript": "5.1.6",
|
|
67
|
-
"vite": "4.
|
|
69
|
+
"vite": "4.5.2",
|
|
68
70
|
"vitest": "0.34.4"
|
|
69
71
|
},
|
|
70
72
|
"publishConfig": {
|
|
71
73
|
"access": "public"
|
|
72
74
|
},
|
|
73
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "9931842bb7afcac659af2a7b5a5d045aae1f4776"
|
|
74
76
|
}
|
|
@@ -31,11 +31,18 @@ export const HeaderContainer: FC = () => {
|
|
|
31
31
|
const [newKeyword, setNewKeyword, newKeywordRef] = useState("")
|
|
32
32
|
|
|
33
33
|
const handleSubmit = () => {
|
|
34
|
-
const
|
|
34
|
+
const newQuery = {
|
|
35
35
|
keywords: newKeywordRef.current ? [newKeywordRef.current] : [],
|
|
36
|
-
}
|
|
36
|
+
}
|
|
37
|
+
const query = JSON.stringify(newQuery)
|
|
37
38
|
setNewKeyword("")
|
|
38
|
-
|
|
39
|
+
if (
|
|
40
|
+
newQuery?.keywords?.length && newQuery.keywords[0].match(/^ds[0-9]{6,6}$/)
|
|
41
|
+
) {
|
|
42
|
+
navigate(`/datasets/${newQuery.keywords[0]}`)
|
|
43
|
+
} else {
|
|
44
|
+
navigate(`/search?query=${query}`)
|
|
45
|
+
}
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
const toggleLoginModal = (): void => {
|
|
@@ -156,6 +156,7 @@ exports[`SnapshotContainer component > renders successfully 1`] = `
|
|
|
156
156
|
>
|
|
157
157
|
<div
|
|
158
158
|
class="accordion-title "
|
|
159
|
+
role="switch"
|
|
159
160
|
>
|
|
160
161
|
<div>
|
|
161
162
|
<h3
|
|
@@ -204,6 +205,7 @@ exports[`SnapshotContainer component > renders successfully 1`] = `
|
|
|
204
205
|
>
|
|
205
206
|
<div
|
|
206
207
|
class="accordion-title "
|
|
208
|
+
role="switch"
|
|
207
209
|
>
|
|
208
210
|
<span>
|
|
209
211
|
view 1 warning in 1 file
|
|
@@ -223,6 +225,7 @@ exports[`SnapshotContainer component > renders successfully 1`] = `
|
|
|
223
225
|
>
|
|
224
226
|
<div
|
|
225
227
|
class="accordion-title "
|
|
228
|
+
role="switch"
|
|
226
229
|
>
|
|
227
230
|
<span
|
|
228
231
|
class="file-header"
|
|
@@ -556,6 +559,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
556
559
|
>
|
|
557
560
|
<div
|
|
558
561
|
class="accordion-title "
|
|
562
|
+
role="switch"
|
|
559
563
|
>
|
|
560
564
|
<span
|
|
561
565
|
aria-label="DS003-downsampled (only T1)"
|
|
@@ -675,6 +679,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
675
679
|
>
|
|
676
680
|
<div
|
|
677
681
|
class="accordion-title "
|
|
682
|
+
role="switch"
|
|
678
683
|
>
|
|
679
684
|
<span
|
|
680
685
|
aria-label="sub-01"
|
|
@@ -708,6 +713,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
708
713
|
>
|
|
709
714
|
<div
|
|
710
715
|
class="accordion-title "
|
|
716
|
+
role="switch"
|
|
711
717
|
>
|
|
712
718
|
<span
|
|
713
719
|
aria-label="sub-02"
|
|
@@ -766,6 +772,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
766
772
|
>
|
|
767
773
|
<div
|
|
768
774
|
class="accordion-title open"
|
|
775
|
+
role="switch"
|
|
769
776
|
>
|
|
770
777
|
<span
|
|
771
778
|
aria-label="DS003-downsampled (only T1)"
|
|
@@ -885,6 +892,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
885
892
|
>
|
|
886
893
|
<div
|
|
887
894
|
class="accordion-title "
|
|
895
|
+
role="switch"
|
|
888
896
|
>
|
|
889
897
|
<span
|
|
890
898
|
aria-label="sub-01"
|
|
@@ -918,6 +926,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
918
926
|
>
|
|
919
927
|
<div
|
|
920
928
|
class="accordion-title "
|
|
929
|
+
role="switch"
|
|
921
930
|
>
|
|
922
931
|
<span
|
|
923
932
|
aria-label="sub-02"
|
|
@@ -1279,6 +1288,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
1279
1288
|
>
|
|
1280
1289
|
Funding
|
|
1281
1290
|
</h2>
|
|
1291
|
+
<ul />
|
|
1282
1292
|
</div>
|
|
1283
1293
|
<div
|
|
1284
1294
|
class="dataset-meta-block dmb-list"
|
|
@@ -1288,6 +1298,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
1288
1298
|
>
|
|
1289
1299
|
References and Links
|
|
1290
1300
|
</h2>
|
|
1301
|
+
<ul />
|
|
1291
1302
|
</div>
|
|
1292
1303
|
<div
|
|
1293
1304
|
class="dataset-meta-block dmb-list"
|
|
@@ -1297,6 +1308,7 @@ OCI-1131441 (R. Poldrack, PI) in any publications.
|
|
|
1297
1308
|
>
|
|
1298
1309
|
Ethics Approvals
|
|
1299
1310
|
</h2>
|
|
1311
|
+
<ul />
|
|
1300
1312
|
</div>
|
|
1301
1313
|
</div>
|
|
1302
1314
|
</div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react"
|
|
2
|
+
import { Markdown } from "../../utils/markdown"
|
|
2
3
|
|
|
3
4
|
export interface MetaDataListBlockProps {
|
|
4
5
|
heading: string
|
|
@@ -17,7 +18,15 @@ export const MetaDataListBlock = ({
|
|
|
17
18
|
return (
|
|
18
19
|
<div className={"dataset-meta-block " + className}>
|
|
19
20
|
<h2 className="dmb-heading">{heading}</h2>
|
|
20
|
-
|
|
21
|
+
<ul>
|
|
22
|
+
{Array.isArray(fieldContent)
|
|
23
|
+
? fieldContent.map((item, index) => (
|
|
24
|
+
<li key={index}>
|
|
25
|
+
<Markdown>{item}</Markdown>
|
|
26
|
+
</li>
|
|
27
|
+
))
|
|
28
|
+
: item}
|
|
29
|
+
</ul>
|
|
21
30
|
</div>
|
|
22
31
|
)
|
|
23
32
|
}
|
|
@@ -2,7 +2,7 @@ import React, { useState } from "react"
|
|
|
2
2
|
import UpdateDescription from "../mutations/description.jsx"
|
|
3
3
|
import { CancelButton } from "./cancel-button"
|
|
4
4
|
import { EditButton } from "./edit-button"
|
|
5
|
-
import Markdown from "markdown
|
|
5
|
+
import { Markdown } from "../../utils/markdown"
|
|
6
6
|
|
|
7
7
|
import EditList from "./edit-list.jsx"
|
|
8
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react"
|
|
2
|
-
import Markdown from "markdown
|
|
2
|
+
import { Markdown } from "../../utils/markdown"
|
|
3
3
|
import { ReadMore } from "@openneuro/components/read-more"
|
|
4
4
|
import { MetaDataBlock } from "../components/MetaDataBlock"
|
|
5
5
|
import Files from "../files/files"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react"
|
|
2
|
-
import Markdown from "markdown
|
|
2
|
+
import { Markdown } from "../../utils/markdown"
|
|
3
3
|
import { ReadMore } from "@openneuro/components/read-more"
|
|
4
4
|
import { MetaDataBlock } from "../components/MetaDataBlock"
|
|
5
5
|
import Files from "../files/files"
|
|
@@ -17,6 +17,7 @@ import { DatasetGitAccess } from "./components/DatasetGitAccess"
|
|
|
17
17
|
import { DatasetHeader } from "./components/DatasetHeader"
|
|
18
18
|
import { DatasetTools } from "./components/DatasetTools"
|
|
19
19
|
import { MetaDataBlock } from "./components/MetaDataBlock"
|
|
20
|
+
import { MetaDataListBlock } from "./components/MetaDataListBlock"
|
|
20
21
|
import { ModalitiesMetaDataBlock } from "./components/ModalitiesMetaDataBlock"
|
|
21
22
|
import { ValidationBlock } from "./components/ValidationBlock"
|
|
22
23
|
import { VersionList } from "./components/VersionList"
|
|
@@ -316,19 +317,19 @@ export const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
316
317
|
heading="How to Acknowledge"
|
|
317
318
|
item={description.HowToAcknowledge}
|
|
318
319
|
/>
|
|
319
|
-
<
|
|
320
|
+
<MetaDataListBlock
|
|
320
321
|
heading="Funding"
|
|
321
322
|
item={description.Funding}
|
|
322
323
|
className="dmb-list"
|
|
323
324
|
/>
|
|
324
325
|
|
|
325
|
-
<
|
|
326
|
+
<MetaDataListBlock
|
|
326
327
|
heading="References and Links"
|
|
327
328
|
item={description.ReferencesAndLinks}
|
|
328
329
|
className="dmb-list"
|
|
329
330
|
/>
|
|
330
331
|
|
|
331
|
-
<
|
|
332
|
+
<MetaDataListBlock
|
|
332
333
|
heading="Ethics Approvals"
|
|
333
334
|
item={description.EthicsApprovals}
|
|
334
335
|
className="dmb-list"
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "../authentication/profile"
|
|
11
11
|
import { Button } from "@openneuro/components/button"
|
|
12
12
|
import { Loading } from "@openneuro/components/loading"
|
|
13
|
+
import { NeurobagelSearch } from "@openneuro/components/search-page"
|
|
13
14
|
import {
|
|
14
15
|
AgeRangeInput,
|
|
15
16
|
AllDatasetsToggle,
|
|
@@ -156,6 +157,7 @@ const SearchContainer: FC<SearchContainerProps> = ({ portalContent }) => {
|
|
|
156
157
|
)}
|
|
157
158
|
renderSearchFacets={() => (
|
|
158
159
|
<>
|
|
160
|
+
<NeurobagelSearch />
|
|
159
161
|
<KeywordInput />
|
|
160
162
|
<AdminUser>
|
|
161
163
|
<AllDatasetsToggle />
|
|
@@ -157,7 +157,7 @@ export const useSearchResults = () => {
|
|
|
157
157
|
boolQuery.addClause(
|
|
158
158
|
"must",
|
|
159
159
|
simpleQueryString(sqsJoinWithAND(keywords), [
|
|
160
|
-
"id^
|
|
160
|
+
"id^20",
|
|
161
161
|
"latestSnapshot.readme",
|
|
162
162
|
"latestSnapshot.description.Name^6",
|
|
163
163
|
"latestSnapshot.description.Authors^3",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Test <Markdown> component > allows a href with certain protocols 1`] = `
|
|
4
|
+
<DocumentFragment>
|
|
5
|
+
<a
|
|
6
|
+
href="https://example.com"
|
|
7
|
+
>
|
|
8
|
+
Example link that should work.
|
|
9
|
+
</a>
|
|
10
|
+
</DocumentFragment>
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
exports[`Test <Markdown> component > does not allow href with unknown protocols 1`] = `
|
|
14
|
+
<DocumentFragment>
|
|
15
|
+
<a>
|
|
16
|
+
Example link that should not work.
|
|
17
|
+
</a>
|
|
18
|
+
</DocumentFragment>
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
exports[`Test <Markdown> component > filters close-break tags 1`] = `
|
|
22
|
+
<DocumentFragment>
|
|
23
|
+
<span>
|
|
24
|
+
<br />
|
|
25
|
+
sample text
|
|
26
|
+
<br />
|
|
27
|
+
</span>
|
|
28
|
+
</DocumentFragment>
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
exports[`Test <Markdown> component > filters out disallowed tags 1`] = `
|
|
32
|
+
<DocumentFragment>
|
|
33
|
+
<ul>
|
|
34
|
+
<li>
|
|
35
|
+
Markdown document
|
|
36
|
+
</li>
|
|
37
|
+
</ul>
|
|
38
|
+
</DocumentFragment>
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
exports[`Test <Markdown> component > safely handles broken HTML tags 1`] = `
|
|
42
|
+
<DocumentFragment>
|
|
43
|
+
<ul>
|
|
44
|
+
<li>
|
|
45
|
+
Markdown document
|
|
46
|
+
|
|
47
|
+
<br />
|
|
48
|
+
<br />
|
|
49
|
+
<ul>
|
|
50
|
+
<li>
|
|
51
|
+
test content
|
|
52
|
+
</li>
|
|
53
|
+
</ul>
|
|
54
|
+
</li>
|
|
55
|
+
</ul>
|
|
56
|
+
</DocumentFragment>
|
|
57
|
+
`;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { render } from "@testing-library/react"
|
|
3
|
+
import { Markdown } from "../markdown"
|
|
4
|
+
|
|
5
|
+
describe("Test <Markdown> component", () => {
|
|
6
|
+
it("safely handles broken HTML tags", () => {
|
|
7
|
+
const brokenTagInput = "* Markdown document\n<br><br>\n * test content"
|
|
8
|
+
const { asFragment } = render(<Markdown>{brokenTagInput}</Markdown>)
|
|
9
|
+
expect(asFragment()).toMatchSnapshot()
|
|
10
|
+
})
|
|
11
|
+
it("filters out disallowed tags", () => {
|
|
12
|
+
const badTags =
|
|
13
|
+
'* Markdown document\n<script type="text/javascript">alert("this should not happen")</script>\n'
|
|
14
|
+
const { asFragment } = render(<Markdown>{badTags}</Markdown>)
|
|
15
|
+
expect(asFragment()).toMatchSnapshot()
|
|
16
|
+
})
|
|
17
|
+
it("allows a href with certain protocols", () => {
|
|
18
|
+
const hrefExample =
|
|
19
|
+
'<a href="https://example.com">Example link that should work.</a>'
|
|
20
|
+
const { asFragment } = render(<Markdown>{hrefExample}</Markdown>)
|
|
21
|
+
expect(asFragment()).toMatchSnapshot()
|
|
22
|
+
})
|
|
23
|
+
it("does not allow href with unknown protocols", () => {
|
|
24
|
+
const hrefExample =
|
|
25
|
+
'<a href="about:memory">Example link that should not work.</a>'
|
|
26
|
+
const { asFragment } = render(<Markdown>{hrefExample}</Markdown>)
|
|
27
|
+
expect(asFragment()).toMatchSnapshot()
|
|
28
|
+
})
|
|
29
|
+
it("filters close-break tags", () => {
|
|
30
|
+
const hrefExample =
|
|
31
|
+
'<br>sample text</br>'
|
|
32
|
+
const { asFragment } = render(<Markdown>{hrefExample}</Markdown>)
|
|
33
|
+
expect(asFragment()).toMatchSnapshot()
|
|
34
|
+
})
|
|
35
|
+
})
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import MarkdownToJsx from "markdown-to-jsx"
|
|
3
|
+
import DOMPurify from "dompurify"
|
|
4
|
+
|
|
5
|
+
interface MarkdownProps {
|
|
6
|
+
children: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Closely aligned with GitHub Markdown
|
|
10
|
+
// See https://github.com/gjtorikian/html-pipeline/blob/7e562219f9814777b73b48f32aece874452c0c5e/lib/html_pipeline/sanitization_filter.rb
|
|
11
|
+
|
|
12
|
+
const ALLOWED_TAGS = [
|
|
13
|
+
"h1",
|
|
14
|
+
"h2",
|
|
15
|
+
"h3",
|
|
16
|
+
"h4",
|
|
17
|
+
"h5",
|
|
18
|
+
"h6",
|
|
19
|
+
"br",
|
|
20
|
+
"b",
|
|
21
|
+
"i",
|
|
22
|
+
"strong",
|
|
23
|
+
"em",
|
|
24
|
+
"a",
|
|
25
|
+
"pre",
|
|
26
|
+
"code",
|
|
27
|
+
"img",
|
|
28
|
+
"tt",
|
|
29
|
+
"div",
|
|
30
|
+
"ins",
|
|
31
|
+
"del",
|
|
32
|
+
"sup",
|
|
33
|
+
"sub",
|
|
34
|
+
"p",
|
|
35
|
+
"picture",
|
|
36
|
+
"ol",
|
|
37
|
+
"ul",
|
|
38
|
+
"table",
|
|
39
|
+
"thead",
|
|
40
|
+
"tbody",
|
|
41
|
+
"tfoot",
|
|
42
|
+
"blockquote",
|
|
43
|
+
"dl",
|
|
44
|
+
"dt",
|
|
45
|
+
"dd",
|
|
46
|
+
"kbd",
|
|
47
|
+
"q",
|
|
48
|
+
"samp",
|
|
49
|
+
"var",
|
|
50
|
+
"hr",
|
|
51
|
+
"ruby",
|
|
52
|
+
"rt",
|
|
53
|
+
"rp",
|
|
54
|
+
"li",
|
|
55
|
+
"tr",
|
|
56
|
+
"td",
|
|
57
|
+
"th",
|
|
58
|
+
"s",
|
|
59
|
+
"strike",
|
|
60
|
+
"summary",
|
|
61
|
+
"details",
|
|
62
|
+
"caption",
|
|
63
|
+
"figure",
|
|
64
|
+
"figcaption",
|
|
65
|
+
"abbr",
|
|
66
|
+
"bdo",
|
|
67
|
+
"cite",
|
|
68
|
+
"dfn",
|
|
69
|
+
"mark",
|
|
70
|
+
"small",
|
|
71
|
+
"source",
|
|
72
|
+
"span",
|
|
73
|
+
"time",
|
|
74
|
+
"wbr",
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
const ALLOWED_ATTR = [
|
|
78
|
+
"abbr",
|
|
79
|
+
"accept",
|
|
80
|
+
"accept-charset",
|
|
81
|
+
"accesskey",
|
|
82
|
+
"action",
|
|
83
|
+
"align",
|
|
84
|
+
"alt",
|
|
85
|
+
"aria-describedby",
|
|
86
|
+
"aria-hidden",
|
|
87
|
+
"aria-label",
|
|
88
|
+
"aria-labelledby",
|
|
89
|
+
"axis",
|
|
90
|
+
"border",
|
|
91
|
+
"char",
|
|
92
|
+
"charoff",
|
|
93
|
+
"charset",
|
|
94
|
+
"checked",
|
|
95
|
+
"clear",
|
|
96
|
+
"cols",
|
|
97
|
+
"colspan",
|
|
98
|
+
"compact",
|
|
99
|
+
"coords",
|
|
100
|
+
"datetime",
|
|
101
|
+
"dir",
|
|
102
|
+
"disabled",
|
|
103
|
+
"enctype",
|
|
104
|
+
"for",
|
|
105
|
+
"frame",
|
|
106
|
+
"headers",
|
|
107
|
+
"height",
|
|
108
|
+
"hreflang",
|
|
109
|
+
"hspace",
|
|
110
|
+
"id",
|
|
111
|
+
"ismap",
|
|
112
|
+
"label",
|
|
113
|
+
"lang",
|
|
114
|
+
"maxlength",
|
|
115
|
+
"media",
|
|
116
|
+
"method",
|
|
117
|
+
"multiple",
|
|
118
|
+
"name",
|
|
119
|
+
"nohref",
|
|
120
|
+
"noshade",
|
|
121
|
+
"nowrap",
|
|
122
|
+
"open",
|
|
123
|
+
"progress",
|
|
124
|
+
"prompt",
|
|
125
|
+
"readonly",
|
|
126
|
+
"rel",
|
|
127
|
+
"rev",
|
|
128
|
+
"role",
|
|
129
|
+
"rows",
|
|
130
|
+
"rowspan",
|
|
131
|
+
"rules",
|
|
132
|
+
"scope",
|
|
133
|
+
"selected",
|
|
134
|
+
"shape",
|
|
135
|
+
"size",
|
|
136
|
+
"span",
|
|
137
|
+
"start",
|
|
138
|
+
"summary",
|
|
139
|
+
"tabindex",
|
|
140
|
+
"title",
|
|
141
|
+
"type",
|
|
142
|
+
"usemap",
|
|
143
|
+
"valign",
|
|
144
|
+
"value",
|
|
145
|
+
"width",
|
|
146
|
+
"itemprop",
|
|
147
|
+
"href",
|
|
148
|
+
"cite",
|
|
149
|
+
"src",
|
|
150
|
+
"longdesc",
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Sanitize disallowed HTML tags and attributes and convert from Markdown to JSX
|
|
155
|
+
*/
|
|
156
|
+
export function Markdown({ children }: MarkdownProps) {
|
|
157
|
+
const sanitizedMarkdown = DOMPurify.sanitize(children, {
|
|
158
|
+
ALLOWED_TAGS,
|
|
159
|
+
ALLOWED_ATTR,
|
|
160
|
+
ALLOW_ARIA_ATTR: false,
|
|
161
|
+
})
|
|
162
|
+
return (
|
|
163
|
+
<>
|
|
164
|
+
<MarkdownToJsx>{sanitizedMarkdown}</MarkdownToJsx>
|
|
165
|
+
</>
|
|
166
|
+
)
|
|
167
|
+
}
|