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

Markdown dedent, and remove containerProps #569

Merged
merged 9 commits into from
Jun 14, 2019
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- `Markdown` components support code highlighting - no need to switch to `SyntaxHighlighter`, which has been removed. Use triple backticks, with the opening backticks followed by the language name or abbreviation. [#562](https://github.com/plotly/dash-core-components/pull/562) Supported languages:
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add that Markdown will attempt to auto-detect the language (via highlight.js) without specifying the language name

Copy link
Contributor

Choose a reason for hiding this comment

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

Also maybe mention the theme prop, but this could be in the docs for dcc.Markdown as well/instead

- Bash
- CSS
- HTTP
- JavaScript
- Python
- JSON
- Markdown
- HTML, XML
- R
- Ruby
- SQL
- Shell Session
- YAML
- Added a `dedent` prop to `Markdown` components, and enabled it by default - removing all matching leading whitespace from every line that has any non-whitespace content. You can disable this with `dedent=False`. [#569](https://github.com/plotly/dash-core-components/pull/569)
- Ability to add tooltips to `Slider` and `RangeSlider`, which can be visible always or on hover. Tooltips also take a position argument. [#564](https://github.com/plotly/dash-core-components/pull/564)

### Fixed
Expand All @@ -14,6 +29,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Changed
- Changed `dcc.Checklist` prop `values` to `value`, to match all the other input components [#558](https://github.com/plotly/dash-core-components/pull/558). Also improved prop types for `Dropdown` and `RadioItems` `value` props to consistently accept both strings and numbers.

### Removed
- 💥 Removed the `SyntaxHighlighter` component. This is now built into `Markdown` [#562](https://github.com/plotly/dash-core-components/pull/562).
- Removed the `containerProps` prop in `Markdown` - after the refactor of [#562](https://github.com/plotly/dash-core-components/pull/562), its function is served by the `id`, `className`, and `style` props. [#569](https://github.com/plotly/dash-core-components/pull/569)

## [0.48.0] - 2019-05-15
### Added
- `figure` prop in `dcc.Graph` now accepts a `frames` key
Expand Down
75 changes: 61 additions & 14 deletions src/components/Markdown.react.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {omit, propOr, type} from 'ramda';
import {type} from 'ramda';
import Markdown from 'react-markdown';
import './css/highlight.css';

Expand All @@ -11,6 +11,12 @@ import './css/highlight.css';
* [react-markdown](https://rexxars.github.io/react-markdown/) under the hood.
*/
class DashMarkdown extends Component {
constructor(props) {
super(props);
this.highlightCode = this.highlightCode.bind(this);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

apparently not needed given our current usage, but makes me nervous to have it there unbound...

this.dedent = this.dedent.bind(this);
}

componentDidMount() {
this.highlightCode();
}
Expand All @@ -25,14 +31,48 @@ class DashMarkdown extends Component {
return;
}
if (this.mdContainer) {
const nodes = this.mdContainer.getElementsByTagName('code');
const nodes = this.mdContainer.querySelectorAll('pre code');

for (let i = 0; i < nodes.length; i++) {
window.hljs.highlightBlock(nodes[i]);
}
}
}

dedent(text) {
const lines = text.split(/\r\n|\r|\n/);
let commonPrefix = null;
for (const line of lines) {
const preMatch = line && line.match(/^\s*(?=\S)/);
if (preMatch) {
const prefix = preMatch[0];
if (commonPrefix !== null) {
for (let i = 0; i < commonPrefix.length; i++) {
// Like Python's textwrap.dedent, we'll remove both
// space and tab characters, but only if they match
if (prefix[i] !== commonPrefix[i]) {
commonPrefix = commonPrefix.substr(0, i);
break;
}
}
} else {
commonPrefix = prefix;
}

if (!commonPrefix) {
break;
}
}
}

const commonLen = commonPrefix ? commonPrefix.length : 0;
return lines
.map(line => {
return line.match(/\S/) ? line.substr(commonLen) : '';
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

})
.join('\n');
}

render() {
const {
id,
Expand All @@ -41,11 +81,14 @@ class DashMarkdown extends Component {
highlight_config,
loading_state,
dangerously_allow_html,
children,
dedent,
} = this.props;

if (type(this.props.children) === 'Array') {
this.props.children = this.props.children.join('\n');
}
const textProp =
type(children) === 'Array' ? children.join('\n') : children;
const displayText =
dedent && textProp ? this.dedent(textProp) : textProp;

return (
<div
Expand All @@ -68,12 +111,10 @@ class DashMarkdown extends Component {
data-dash-is-loading={
(loading_state && loading_state.is_loading) || undefined
}
{...propOr({}, 'containerProps', this.props)}
>
<Markdown
source={this.props.children}
source={displayText}
escapeHtml={!dangerously_allow_html}
{...omit(['containerProps'], this.props)}
/>
</div>
);
Expand All @@ -92,12 +133,6 @@ DashMarkdown.propTypes = {
*/
className: PropTypes.string,

/**
* An object containing custom element props to put on the container
* element such as id or style
*/
containerProps: PropTypes.object,

/**
* A boolean to control raw HTML escaping.
* Setting HTML from code is risky because it's easy to
Expand All @@ -114,10 +149,21 @@ DashMarkdown.propTypes = {
PropTypes.arrayOf(PropTypes.string),
]),

/**
* Remove matching leading whitespace from all lines.
* Lines that are empty, or contain *only* whitespace, are ignored.
* Both spaces and tab characters are removed, but only if they match;
* we will not convert tabs to spaces or vice versa.
*/
dedent: PropTypes.bool,

/**
* Config options for syntax highlighting.
*/
highlight_config: PropTypes.exact({
/**
* Color scheme; default 'light'
*/
theme: PropTypes.oneOf(['dark', 'light']),
}),

Expand Down Expand Up @@ -148,6 +194,7 @@ DashMarkdown.propTypes = {
DashMarkdown.defaultProps = {
dangerously_allow_html: false,
highlight_config: {},
dedent: true,
};

export default DashMarkdown;
Loading