This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link - #711

Merged
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link
Jan 9, 2020
Merged

Issue 250 - Support for rendering links inside dcc.Markdown as dcc.Link#711
Marc-Andre-Rivet merged 24 commits into
devfrom
250-markdown-link

Conversation

@Marc-Andre-Rivet

@Marc-Andre-RivetMarc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
Contributor

Fixes#250

Adds additional node type for dcc.Link (vs. link) and the general mechanism to extend markdown syntax with any React Component of our choosing. Leaves the existing link syntax untouched.

Works as-is, no need to set dangerously_allow_html=True -- which I'm not sure makes sense? Need to investigate / make sure we're not doing something wrong..

Requires dangerously_allow_html=True to work correctly.

Todo

import dash
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = dcc.Markdown("""
# Link
[Outside Link](https://www.google.com)
# DCC Link!
<dccLink href="potato" children="potato" />
<dccLink href="with_gravy" children="with gravy" />
""")
app.run_server(debug=True)

image

Comment threadwebpack.config.js Outdated
{
test: /\.jsx?$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!react-jsx-parser\/)/,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not transpiled to ES5 so needs to be re-transpiled.


const componentTransforms = {
DccLink: props => <DccLink {...props} />,
};

@Marc-Andre-RivetMarc-Andre-RivetDec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we define the list of components we want to support are their name in markdown + props customization as needed.

@Marc-Andre-Rivet
Marc-Andre-Rivet marked this pull request as ready for review December 3, 2019 01:27
@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Very cool syntax. Should we do <DccLink or <dccLink? The latter is similar to the Python and R (cc @sudburyrob@rpkyle ) syntax but maybe less semantic in terms of XML

Comment threadsrc/fragments/Markdown.react.js Outdated
source={displayText}
escapeHtml={!dangerously_allow_html}
renderers={{
html: props => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we toss in a danderous HTML / XSS test for future sanity?

@chriddyp

Copy link
Copy Markdown
Member

I like it. Nice general solution. 💃

@chriddyp

chriddyp commented Dec 3, 2019

Copy link
Copy Markdown
Member

Does this work?

<DccLink href="/lahlah">
Test
</DccLink>

Also, does this work?

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly~chris/1638.png)
</DccLink>

What about this?

<DccLink href="/lahlah" children="![Alt text for an image](https://plot.ly~chris/1638.png)">
</DccLink>

@chriddyp

Copy link
Copy Markdown
Member

Also could we do a image test that our CSS is OK? That is, that inline dcc.Link is rendered the same way as an inline markdown link?

This is a [regular html link](/test) within a line of text.
This is a <DccLink href="/test">special dcc link</DccLink> within a line of text.
You can't tell them apart!

@chriddyp

Copy link
Copy Markdown
Member

Sorry @sudburyrob I meant to tag @rpkyle

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

@chriddyp We're in html land now so this does not work:

<DccLink href="/lahlah">
![Alt text for an image](https://plot.ly/~chris/1638.png)
</DccLink>

But this works:

<dccLink href="lots_of_cheese">
<img src="https://plot.ly/~chris/1638.png"/>
</dccLink>

And this works too

<DccLink href="/lahlah">
Test
</DccLink>

That said, nothing would prevent us from going all in and allowing nested markdowns inside the markdown:

<dccLink href="really_lots_of_cheese">
<dccMarkdown source="![Alt text for an image](https://plot.ly/~chris/1638.png)" />
</dccLink>

Not advocating this, but... it works... who am I to say nested markdowns shouldn't be a thing? 🤷‍♂️

@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

Should we do DccLink or dccLink? The latter is similar to the Python and R

dccLink does make more sense, and it works (does not suffer React's capitalization limitations). Updating.

Marc-Andre-Rivetand others added 5 commits December 2, 2019 20:43
@Marc-Andre-Rivet

Copy link
Copy Markdown
ContributorAuthor

One difference between using dccLink through the html renderer and link (e.g. [Link](/link-path)) gets wrapped in a <p>...</p> along with everything else in the line.

@Marc-Andre-RivetMarc-Andre-Rivet added this to the Dash v1.8 milestone Dec 3, 2019
@chriddyp

Copy link
Copy Markdown
Member

Another nice enhancement (down the line) would be to enable end users to specify the properties of their html.A like target="blank", so:

dcc.Markdown('''
Long string of text with a <a href="https://plot.ly" target="blank">absolute link</a> in it.
''')

@chriddyp

Copy link
Copy Markdown
Member

One difference between using dccLink through the html renderer and link (e.g. Link) gets wrapped in a

...

along with everything else in the line.

Does this mean that using <dccLink/> in markdown will bring the content into a new line rather than keeping it with the text? If so, then that would reduce the ease of use of this enhancement.

@Marc-Andre-Rivet

Marc-Andre-Rivet commented Dec 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Does this mean that using in markdown will bring the content into a new line rather than keeping it with the text?

Testing it...

dcc.Markdown(['This is an inlined <dccLink href="title_crumb" children="Title" /> with text on both sides'], dangerously_allow_html=True,),

Currently renders as:
image

Checking if something can be done about it.


With some tweaking (https://github.com/TroyAlford/react-jsx-parserrenderInWrapper=False) now renders html without a wrapper, so the above is now:

image

Added a test for the inline case.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For dash-docs this will work fine - we can update reusable_components.Markdown to automatically convert [title](url) to <dccLink children="title" href="url" /> or whatever, and add dangerously_allow_html=True. Given that this implementation is pretty easy (and done), let's put it in 💃(once tests pass again)

If anyone else besides dash-docs is interested in this, we still may want to explore a syntax like [title](%url) that should work without dangerously_allow_html and should allow markdown within the link text without re-wrapping it.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for rendering links inside dcc.Markdown as dcc.Link for single page dash apps

3 participants

@Marc-Andre-Rivet@chriddyp@alexcjohnson