Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit 718ae50

Browse files
Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link (#711)
1 parent 39cfdfc commit 718ae50

File tree

13 files changed

+207
-68
lines changed

13 files changed

+207
-68
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## [Unreleased]
66
### Added
7+
- [#711](https://github.com/plotly/dash-core-components/pull/711) Added support for `dcc.Link` (dccLink) and nested `dcc.Markdown` (dccMarkdown) react components inside of `dcc.Markdown`
78
- [#706](https://github.com/plotly/dash-core-components/pull/706)
89
- Added new `responsive` property that overrides the underlying Plotly.js graph responsiveness from Dash-land
910
- Added responsiveness on graph parent element resize (previously only worked on window.resize)

MANIFEST.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
include dash_core_components/dash_core_components.min.js
22
include dash_core_components/dash_core_components.min.js.map
3+
include dash_core_components/dash_core_components-shared.js
4+
include dash_core_components/dash_core_components-shared.js.map
35
include dash_core_components/async~*.js
46
include dash_core_components/async~*.js.map
5-
include dash_core_components/highlight.pack.js
67
include dash_core_components/metadata.json
78
include dash_core_components/package-info.json
89
include dash_core_components/plotly.min.js

babel.config.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ const presets = [
44
];
55

66
const plugins = [
7-
'@babel/plugin-syntax-dynamic-import',
8-
'@babel/plugin-transform-async-to-generator',
9-
'@babel/plugin-transform-runtime'
7+
'@babel/plugin-syntax-dynamic-import'
108
];
119

1210
// eslint-disable-next-line no-process-env

dash_core_components_base/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@
8888
'namespace': 'dash_core_components',
8989
'dynamic': True
9090
},
91+
{
92+
'relative_package_path': '{}-shared.js'.format(__name__),
93+
'external_url': (
94+
'https://unpkg.com/dash-core-components@{}'
95+
'/dash_core_components/dash_core_components-shared.js'
96+
).format(__version__),
97+
'namespace': 'dash_core_components'
98+
},
99+
{
100+
'relative_package_path': '{}-shared.js.map'.format(__name__),
101+
'external_url': (
102+
'https://unpkg.com/dash-core-components@{}'
103+
'/dash_core_components/dash_core_components-shared.js.map'
104+
).format(__version__),
105+
'namespace': 'dash_core_components',
106+
'dynamic': True
107+
},
91108
{
92109
'relative_package_path': 'plotly.min.js',
93110
'external_url': (

package-lock.json

Lines changed: 27 additions & 55 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@
5858
"@babel/core": "^7.4.0",
5959
"@babel/plugin-proposal-object-rest-spread": "^7.4.0",
6060
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
61-
"@babel/plugin-transform-async-to-generator": "^7.7.4",
62-
"@babel/plugin-transform-runtime": "^7.7.6",
6361
"@babel/preset-env": "^7.4.1",
6462
"@babel/preset-react": "^7.0.0",
6563
"@plotly/dash-component-plugins": "^1.0.2",
@@ -85,6 +83,8 @@
8583
"prettier": "^1.14.2",
8684
"react": "^16.8.6",
8785
"react-dom": "^16.8.6",
86+
"react-jsx-parser": "^1.21.0",
87+
"react-resize-detector": "^4.2.1",
8888
"style-loader": "^0.23.1",
8989
"styled-jsx": "^3.1.1",
9090
"terser-webpack-plugin": "^2.3.0",

src/fragments/Graph.react.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class PlotlyGraph extends Component {
270270
);
271271
}
272272

273-
async graphResize(force = false) {
273+
graphResize(force = false) {
274274
if (!force && !this.isResponsive(this.props)) {
275275
return;
276276
}

src/fragments/Markdown.react.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import React, {Component} from 'react';
2-
import {type} from 'ramda';
2+
import {mergeDeepRight, pick, type} from 'ramda';
3+
import JsxParser from 'react-jsx-parser';
34
import Markdown from 'react-markdown';
45

56
import MarkdownHighlighter from '../utils/MarkdownHighlighter';
67
import {propTypes, defaultProps} from '../components/Markdown.react';
78

9+
import DccLink from './../components/Link.react';
10+
811
export default class DashMarkdown extends Component {
912
constructor(props) {
1013
super(props);
@@ -91,6 +94,18 @@ export default class DashMarkdown extends Component {
9194
const displayText =
9295
dedent && textProp ? this.dedent(textProp) : textProp;
9396

97+
const componentTransforms = {
98+
dccLink: props => <DccLink {...props} />,
99+
dccMarkdown: props => (
100+
<Markdown
101+
{...mergeDeepRight(
102+
pick(['dangerously_allow_html', 'dedent'], this.props),
103+
pick(['children'], props)
104+
)}
105+
/>
106+
),
107+
};
108+
94109
return (
95110
<div
96111
id={id}
@@ -116,6 +131,18 @@ export default class DashMarkdown extends Component {
116131
<Markdown
117132
source={displayText}
118133
escapeHtml={!dangerously_allow_html}
134+
renderers={{
135+
html: props =>
136+
props.escapeHtml ? (
137+
props.value
138+
) : (
139+
<JsxParser
140+
jsx={props.value}
141+
components={componentTransforms}
142+
renderInWrapper={false}
143+
/>
144+
),
145+
}}
119146
/>
120147
</div>
121148
);

src/utils/MarkdownHighlighter.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import lazyhljs from './LazyLoader/hljs';
22

33
const MarkdownHighlighter = {
4-
loadhljs: async function() {
5-
this.hljs = await lazyhljs();
6-
this.hljsResolve();
7-
this.isReady = true;
4+
loadhljs: function() {
5+
return lazyhljs().then(hljs => {
6+
this.hljs = hljs;
7+
this.hljsResolve();
8+
this.isReady = true;
9+
});
810
},
911
};
1012

tests/assets/image.png

118 KB
Loading
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import os
2+
import pytest
3+
from selenium.common.exceptions import WebDriverException
4+
5+
import dash
6+
from dash.dependencies import Input, Output
7+
import dash_core_components as dcc
8+
import dash_html_components as html
9+
10+
11+
def test_mkdw001_img(dash_dcc):
12+
app = dash.Dash(__name__, eager_loading=True)
13+
14+
app.layout = html.Div(
15+
[
16+
html.Div('Markdown img'),
17+
dcc.Markdown(
18+
['<img src="assets/image.png" />'], dangerously_allow_html=True
19+
),
20+
html.Div('Markdown img - requires dangerously_allow_html'),
21+
dcc.Markdown(['<img src="assets/image.png" />']),
22+
]
23+
)
24+
25+
dash_dcc.start_server(app)
26+
dash_dcc.percy_snapshot("mkdw001 - image display")
27+
28+
29+
def test_mkdw002_dcclink(dash_dcc):
30+
app = dash.Dash(__name__, eager_loading=True)
31+
32+
app.layout = html.Div(
33+
[
34+
html.Div(['Markdown link']),
35+
dcc.Markdown(['[Title](title_crumb)']),
36+
html.Div(['Markdown dccLink']),
37+
dcc.Markdown(
38+
['<dccLink href="title_crumb" children="Title" />'],
39+
dangerously_allow_html=True,
40+
),
41+
html.Div(['Markdown dccLink - explicit children']),
42+
dcc.Markdown(
43+
[
44+
'''
45+
<dccLink href="title_crumb">
46+
Title
47+
</dccLink>
48+
'''
49+
],
50+
dangerously_allow_html=True,
51+
),
52+
html.Div('Markdown dccLink = inlined'),
53+
dcc.Markdown(
54+
[
55+
'This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'
56+
],
57+
dangerously_allow_html=True,
58+
),
59+
html.Div('Markdown dccLink - nested image'),
60+
dcc.Markdown(
61+
[
62+
'''
63+
<dccLink href="title_crumb">
64+
<img src="assets/image.png" />
65+
</dccLink>
66+
'''
67+
],
68+
dangerously_allow_html=True,
69+
),
70+
html.Div('Markdown dccLink - nested markdown'),
71+
dcc.Markdown(
72+
[
73+
'''
74+
<dccLink href="title_crumb">
75+
<dccMarkdown children="## Title" />
76+
</dccLink>
77+
'''
78+
],
79+
dangerously_allow_html=True,
80+
),
81+
html.Div('Markdown dccLink - nested markdown image'),
82+
dcc.Markdown(
83+
[
84+
'''
85+
<dccLink href="title_crumb">
86+
<dccMarkdown children="![Image](assets/image.png)" />
87+
</dccLink>
88+
'''
89+
],
90+
dangerously_allow_html=True,
91+
),
92+
html.Div('Markdown dccLink - requires dangerously_allow_html'),
93+
dcc.Markdown(['<dccLink href="title_crumb" children="Title" />']),
94+
]
95+
)
96+
97+
dash_dcc.start_server(app)
98+
dash_dcc.percy_snapshot("mkdw002 - markdowns display")

tests/integration/misc/test_markdown_highlight.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ def test_msmh001_no_window_variable(dash_dcc):
1717
app.layout = html.Div(dcc.Markdown(md_text))
1818
dash_dcc.start_server(app)
1919

20+
dash_dcc.wait_for_element('code')
21+
2022
window_hljs = dash_dcc.driver.execute_script('return window.hljs')
2123
assert window_hljs is None
2224

0 commit comments

Comments
 (0)