Skip to content

Commit 2a7105f

Browse files
mariusconjeaudMarius Conjeaud
andauthored
Markdown tables not rendered #836 (#893)
Co-authored-by: Marius Conjeaud <[email protected]>
1 parent f880666 commit 2a7105f

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
"tailwindcss": "^3.3.2",
103103
"three": "^0.159.0",
104104
"three-spritetext": "^1.8.1",
105+
"urijs": "^1.19.11",
105106
"use-neo4j": "^0.3.13",
106107
"yaml": "^2.2.1"
107108
},

src/chart/markdown/MarkdownChart.tsx

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
import React from 'react';
22
import { ChartProps } from '../Chart';
33
import ReactMarkdown from 'react-markdown';
4-
import gfm from 'remark-gfm';
4+
import remarkGfm from 'remark-gfm';
5+
import URI from 'urijs';
56
import { replaceDashboardParameters } from '../ChartUtils';
67

8+
// Sanitizes URIs
9+
const transformUri = (uri: string): string | undefined => {
10+
const parsedUri = URI(uri);
11+
if (parsedUri.protocol() === 'http' || parsedUri.protocol() === 'https') {
12+
return parsedUri.toString(); // Convert URI object back to string
13+
}
14+
return undefined; // Return undefined to skip rendering of potentially unsafe URLs
15+
};
16+
17+
// Define custom components for Markdown elements
18+
const CustomTable = ({ _, ...props }) => <table {...props} className='markdown-table' />;
19+
const CustomTh = ({ _, ...props }) => <th {...props} className='markdown-th' />;
20+
const CustomTd = ({ _, ...props }) => <td {...props} className='markdown-td' />;
21+
const CustomATag = ({ _, href, ...props }) => (
22+
// Apply URI transformation right in the anchor element for additional security
23+
<a href={href ? transformUri(href) : undefined} {...props} rel='noopener noreferrer' target='_blank' />
24+
);
25+
726
/**
827
* Renders Markdown text provided by the user.
928
*/
1029
const NeoMarkdownChart = (props: ChartProps) => {
30+
// Define custom components for Markdown elements
31+
const components = {
32+
table: CustomTable,
33+
th: CustomTh,
34+
td: CustomTd,
35+
a: CustomATag,
36+
};
37+
1138
// Records are overridden to be a single element array with a field called 'input'.
1239
const { records } = props;
1340
const parameters = props.parameters ? props.parameters : {};
@@ -17,13 +44,18 @@ const NeoMarkdownChart = (props: ChartProps) => {
1744
: true;
1845
const markdown = records[0].input;
1946
const modifiedMarkdown = replaceGlobalParameters ? replaceDashboardParameters(markdown, parameters) : markdown;
20-
// TODO: we should check if the gfm plugin has an impact on the standard security provided by ReactMarkdown
2147
return (
2248
<div
2349
className='markdown-widget'
2450
style={{ marginTop: '0px', marginLeft: '15px', marginRight: '15px', marginBottom: '0px' }}
2551
>
26-
<base target='_blank' /> <ReactMarkdown remarkPLugins={[gfm]} children={modifiedMarkdown} />
52+
<base target='_blank' />
53+
<ReactMarkdown
54+
children={modifiedMarkdown}
55+
remarkPlugins={[remarkGfm]}
56+
components={components}
57+
transformLinkUri={transformUri}
58+
/>
2759
</div>
2860
);
2961
};

src/index.pcss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,22 @@
9090
.n-bg-dark-neutral-text-weak {
9191
background-color: rgb(196 200 205 / var(--tw-bg-opacity)) !important;
9292
}
93+
94+
/* Markdown table styles */
95+
.markdown-table {
96+
width: 100%;
97+
border-collapse: collapse;
98+
}
99+
100+
.markdown-table th,
101+
.markdown-table td {
102+
border: 1px solid #ddd; /* Light gray border */
103+
padding: 8px; /* Padding around text */
104+
text-align: left; /* Align text to the left */
105+
}
106+
107+
.markdown-table th {
108+
background-color: #f4f4f4; /* Light gray background for header */
109+
color: #333; /* Dark text color for contrast */
110+
}
93111
}

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13504,6 +13504,11 @@ uri-js@^4.2.2:
1350413504
dependencies:
1350513505
punycode "^2.1.0"
1350613506

13507+
urijs@^1.19.11:
13508+
version "1.19.11"
13509+
resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc"
13510+
integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==
13511+
1350713512
url-parse@^1.5.3:
1350813513
version "1.5.10"
1350913514
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"

0 commit comments

Comments
 (0)