diff --git a/CHANGELOG.md b/CHANGELOG.md index 628299e9f..daa95ba03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- [#916](https://github.com/plotly/dash-table/pull/916) + - Added `html` option to `markdown_options` prop. This enables the use of html tags in markdown text. + - [#545](https://github.com/plotly/dash-table/issues/545) - Case insensitive filtering - New props: `filter_options` - to control case of all filters, `columns.filter_options` - to control filter case for each column diff --git a/src/dash-table/components/Table/props.ts b/src/dash-table/components/Table/props.ts index aa7249bd7..71aef1894 100644 --- a/src/dash-table/components/Table/props.ts +++ b/src/dash-table/components/Table/props.ts @@ -163,6 +163,7 @@ export interface INumberLocale { export interface IMarkdownOptions { link_target: '_blank' | '_parent' | '_self' | '_top' | string; + html?: boolean; } export type NumberFormat = diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 53ca225e3..0132fb62b 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -67,7 +67,8 @@ export const defaultProps = { }, markdown_options: { - link_target: '_blank' + link_target: '_blank', + html: false }, tooltip: {}, @@ -483,7 +484,13 @@ export const propTypes = { link_target: PropTypes.oneOfType([ PropTypes.string, PropTypes.oneOf(['_blank', '_parent', '_self', '_top']) - ]).isRequired + ]), + /** + * (default: False) If True, html may be used in markdown cells + * Be careful enabling html if the content being rendered can come + * from an untrusted user, as this may create an XSS vulnerability. + */ + html: PropTypes.bool }), /** diff --git a/tests/selenium/test_markdown_html.py b/tests/selenium/test_markdown_html.py new file mode 100644 index 000000000..b9a316302 --- /dev/null +++ b/tests/selenium/test_markdown_html.py @@ -0,0 +1,38 @@ +import dash +from dash_table import DataTable + + +def get_app(markdown_options): + + app = dash.Dash(__name__) + + props = dict( + id="table", + columns=[dict(name="a", id="a", type="text", presentation="markdown")], + data=[dict(a="

html h1 heading

")], + ) + + if markdown_options is not None: + props["markdown_options"] = markdown_options + + app.layout = DataTable(**props) + + return app + + +def test_tmdh001_html_not_allowed(test): + test.start_server(get_app(None)) + + h1_elements = test.find_elements("h1") + + assert len(h1_elements) == 0 + assert test.get_log_errors() == [] + + +def test_tmdh002_html_allowed(test): + test.start_server(get_app(dict(html=True))) + + h1_elements = test.find_elements("h1") + + assert len(h1_elements) == 1 + assert test.get_log_errors() == []