Open karosc opened 3 years ago
(moved to the DCC repo)
That would be great! We'll have be careful to do it in a way that doesn't bloat the component unless they're used. Individually plugins generally seem pretty small but there are a lot of them we might include. I could imagine a number of ways this might be done, from requiring users to load plugins manually on the page, to one or many async chunks defined within this repo that get loaded on demand. Regardless, the dash prop would need to reference the plugins as strings, which then get associated with the correct code inside the component.
I'm not a react developer (or a js developer for that matter), but interested in seeing if I can clobber something together. On the react markdown readme, it seems strait forward to include a plugin:
const React = require('react')
const ReactMarkdown = require('react-markdown')
const render = require('react-dom').render
const gfm = require('remark-gfm')
const markdown = `Just a link: https://reactjs.com.`
render(<ReactMarkdown plugins={[gfm]} children={markdown} />, document.body)
could we add a method to the dash markdown class that looks something like this?
load_plugins(text_array){
let plugins = [];
if(text_array.includes('remark-attr')){
const attr_plugin = require('remark-attr');
plugins.push(attr_plugin);
}
return plugins
}
Then push the results of that function to the Markdown jsx in the render function like this
render() {
const {
id,
style,
className,
highlight_config,
loading_state,
dangerously_allow_html,
children,
dedent,
plugins, //new plugin prop
} = this.props;
const textProp =
type(children) === 'Array' ? children.join('\n') : children;
const displayText =
dedent && textProp ? this.dedent(textProp) : textProp;
const plugs = this.load_plugins(plugins) //load plugins given list of strings
const componentTransforms = {
dccLink: props => <DccLink {...props} />,
dccMarkdown: props => (
<Markdown
{...mergeDeepRight(
pick(['dangerously_allow_html', 'dedent','plugins'], this.props), // not sure what this line does, but the dedent is added, so wondering if plugings belongs here to?
pick(['children'], props)
)}
/>
),
};
return (
<div
id={id}
ref={node => {
this.mdContainer = node;
}}
style={style}
className={
((highlight_config && highlight_config.theme) ||
className) &&
`${className ? className : ''} ${
highlight_config &&
highlight_config.theme &&
highlight_config.theme === 'dark'
? 'hljs-dark'
: ''
}`
}
data-dash-is-loading={
(loading_state && loading_state.is_loading) || undefined
}
>
<Markdown
source={displayText}
escapeHtml={!dangerously_allow_html}
plugins = {plugs} // add in plugin list
renderers={{
html: props =>
props.escapeHtml ? (
props.value
) : (
<JsxParser
jsx={props.value}
components={componentTransforms}
renderInWrapper={false}
/>
),
}}
/>
</div>
);
}
You know, my main use case for these plugins would be solved by allowing html to rendered from the markdown document. However, I am hesitant to use dangerously_allow_html because I don't fully understand the risks and don't want to expose users to such a threat.
I found a different repository based on remarkjs (react-remark) that seems to allow for html sanitization using rehype plugins, which might improve the security of using dangerously_allow_html.
What are your thoughts of porting the dcc.Markdown component from react-markdown to react-remark. Doing so would increase the opportunity to use more plugins that operate both on markdown and html, and potentially increase security against XSS.
Is there any interest in supporting remarkjs plugins? I am currently using dcc.Markdown a bunch and would really benefit from some extended functionality, like being able to add ids and classes using the curly brace syntax to help me style content.