Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Document discouraged elements, and fix ObjectEl data by alexcjohnson · Pull Request #178 · plotly/dash-html-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Document discouraged elements, and fix ObjectEl data by alexcjohnson · Pull Request #178 · plotly/dash-html-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Document discouraged elements, and fix ObjectEl data by alexcjohnson · Pull Request #178 · plotly/dash-html-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Document discouraged elements, and fix ObjectEl data by alexcjohnson · Pull Request #178 · plotly/dash-html-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Document discouraged elements, and fix ObjectEl data by alexcjohnson · Pull Request #178 · plotly/dash-html-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
version: 2

jobs:
percy-finalize:
docker:
- image: percyio/agent
auth:
username: dashautomation
password: $DASH_PAT_DOCKERHUB
steps:
- run: percy finalize --all

python-2.7: &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
Expand All@@ -9,7 +18,7 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py27
PERCY_ENABLE: 1
PERCY_ENABLE: 0

working_directory: ~/repo

Expand DownExpand Up@@ -76,7 +85,8 @@ jobs:
password: $DASH_PAT_DOCKERHUB
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
PERCY_ENABLE: 1
PERCY_PARALLEL_TOTAL: -1

workflows:
version: 2
Expand All@@ -85,3 +95,6 @@ workflows:
- python-2.7
- python-3.6
- python-3.7
- percy-finalize:
requires:
- python-3.7
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## UNRELEASED
### Fixed
- [#178](https://github.com/plotly/dash-html-components/pull/178) - Fix [#161](https://github.com/plotly/dash-html-components/issues/161) <object> `data` property, and fix [#129](https://github.com/plotly/dash-html-components/issues/129) obsolete, deprecated, and discouraged elements. No elements were removed, but comments were added to the documentation about these elements detailing their limitations.

## [1.1.2] - 2021-01-19
### Fixed
- [#169](https://github.com/plotly/dash-html-components/pull/169) - part of fixing dash import bug https://github.com/plotly/dash/issues/1143
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,7 +24,7 @@
"postbuild": "es-check es5 dash_html_components/*.js",
"build:watch": "watch 'npm run build' src",
"test:import": "python -m unittest tests.test_dash_import",
"test:py": "python -m unittest tests.test_dash_html_components tests.test_integration",
"test:py": "pytest --nopercyfinalize --headless tests/test_dash_html_components.py tests/test_integration.py",
"test": "run-s -c test:py test:import lint"
},
"author": "Chris Parmer <chris@plotly.com>",
Expand Down
7 changes: 3 additions & 4 deletions scripts/extract-attributes.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,13 @@ const dataPath = './data/attributes.json';
const htmlPath = './data/attributes.html';

// From https://facebook.github.io/react/docs/tags-and-attributes.html#supported-attributes
// less the `data` attribute,
// the special `className` and `htmlFor` props,
// less the special `className` and `htmlFor` props,
// and `httpEquiv` + `acceptCharset` which are already correctly camelCased.
const supportedAttributes = ['accept', 'accessKey', 'action',
'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete',
'autoFocus', 'autoPlay', 'capture', 'cellPadding', 'cellSpacing', 'challenge',
'charSet', 'checked', 'cite', 'classID', 'colSpan', 'cols', 'content',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin',
'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data',
'dateTime', 'default', 'defer', 'dir', 'disabled', 'download', 'draggable',
'encType', 'form', 'formAction', 'formEncType', 'formMethod', 'formNoValidate',
'formTarget', 'frameBorder', 'headers', 'height', 'hidden', 'high', 'href',
Expand DownExpand Up@@ -82,7 +81,7 @@ function extractAttributes($) {
.toString();

// Skip `data-*` attributes
if (htmlAttribute.indexOf('data') === 0) {
if (htmlAttribute.indexOf('data-') === 0) {
return;
}

Expand Down
10 changes: 9 additions & 1 deletion scripts/extract-elements.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,11 +20,18 @@ function extractElements($) {
'svg', 'math',
// obsolete, non-standard, or deprecated tags
'image', 'dir', 'tt', 'applet', 'noembed', 'bgsound', 'menu', 'menuitem',
'noframes'
'noframes',
// experimental, don't add yet
'portal'
];
// `<section>` is for some reason missing from the reference tables.
// `<command>` and `element` are obsolete and has been removed from the
// reference table, but we had them in the past so we should wait for a
// major to remove
const addElements = [
'base',
'command',
'element',
'section',
'h1',
'h2',
Expand DownExpand Up@@ -64,6 +71,7 @@ request(refUrl, (error, response, html) => {
if (elements.length !== expectedElCount) {
throw new Error(
'Unexpected number of elements extracted from ' + refUrl +
' - Found ' + elements.length + ' but expected ' + expectedElCount +
' Check the output and edit expectedElCount if this is intended.'
);
}
Expand Down
54 changes: 53 additions & 1 deletion scripts/generate-components.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,16 +198,68 @@ function generatePropTypes(element, attributes) {
'setProps': PropTypes.func`
}

const obsoleteDoc = element => `
* OBSOLETE: <${element}> is included for completeness, but should be avoided
* as it is not supported by any modern browsers.`;

const customDocs = {
basefont: `
* OBSOLETE: <basefont> is included for completeness, but should be avoided
* as it is only supported by Internet Explorer.`,
blink: obsoleteDoc('blink'),
command: obsoleteDoc('command'),
element: obsoleteDoc('element'),
isindex: obsoleteDoc('isindex'),
keygen: `
* DEPRECATED: <keygen> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
listing: obsoleteDoc('listing') + ' Use <pre> or <code> instead.',
marquee: `
* DEPRECATED: <marquee> is included for completeness, but should be avoided
* as browsers may remove it at any time.`,
meta: `
* CAUTION: <meta> is included for completeness, but generally will not behave
* as expected since <meta> tags should be static HTML content in the <head> of
* the document. Dash components are dynamic <body> content.`,
multicol: obsoleteDoc('multicol'),
nextid: obsoleteDoc('nextid'),
output: `
* CAUTION: <output> is included for completeness, but its typical usage
* requires the oninput attribute of the enclosing <form> element, which
* is not accessible to Dash.`,
script: `
* CAUTION: <script> is included for completeness, but you cannot execute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❤️

* JavaScript code by providing it to a <script> element. Use a clientside
* callback for this purpose instead.`,
plaintext: `
* OBSOLETE: <plaintext> is included for completeness, but should be avoided
* as browsers may remove it at any time, and its behavior when added
* dynamically by Dash is not what it would be statically on page load.
* Use <pre> or <code> instead.`,
shadow: `
* DEPRECATED: <shadow> is included for completeness, but should be avoided
* as it is not supported by all browsers and may be removed at any time from
* those that do support it.`,
spacer: obsoleteDoc('spacer'),
title: `
* CAUTION: <title> is included for completeness, but is not expected to
* do anything outside of <head>. Dash components are always created in the
* <body>.`
};

function generateComponent(Component, element, attributes) {
const propTypes = generatePropTypes(element, attributes);

const customDoc = customDocs[element] ? ('\n *' + customDocs[element] + '\n *') : '';

return `
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';

/**
* ${Component} is a wrapper for the <${element}> HTML5 element.
* ${Component} is a wrapper for the <${element}> HTML5 element.${customDoc}
* For detailed attribute info see:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${element}
*/
Expand Down
87 changes: 0 additions & 87 deletions tests/IntegrationTests.py

This file was deleted.

91 changes: 48 additions & 43 deletions tests/test_dash_html_components.py
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
import unittest
import dash_html_components


class TestDashHtmlComponents(unittest.TestCase):
def test_imports(self):
with open('./scripts/data/elements.txt') as f:
elements = [
s[0].upper() + s[1:] for s in
f.read().split('\n')
]
elements += ['MapEl', 'ObjectEl']
for s in ['Map', 'Object']:
elements.remove(s)

print(dir(dash_html_components))

self.assertEqual(
set([d for d in dir(dash_html_components) if d[0] != '_' and d[0] == d[0].capitalize()]),
set(elements)
)

def test_sample_items(self):
Div = dash_html_components.Div
Img = dash_html_components.Img

layout = Div(
Div(
Img(src='https://plotly.com/~chris/1638.png')
), style={'color': 'red'}
)

self.assertEqual(
repr(layout),
''.join([
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
])
)

self.assertEqual(
layout._namespace, 'dash_html_components'
)
import pytest
import dash_html_components as html


def test_imports():
with open("./scripts/data/elements.txt") as f:
elements = [s[0].upper() + s[1:] for s in f.read().split("\n")]
elements += ["MapEl", "ObjectEl"]
for s in ["Map", "Object"]:
elements.remove(s)

dir_set = set(
[
d
for d in dir(html)
if d[0] != "_" and d[0] == d[0].capitalize()
]
)
assert dir_set == set(elements)


def test_sample_items():
layout = html.Div(
html.Div(html.Img(src="https://plotly.com/~chris/1638.png")),
style={"color": "red"}
)

expected = (
"Div(children=Div(Img(src='https://plotly.com/~chris/1638.png')), "
"style={'color': 'red'})"
)
assert repr(layout) == expected

assert layout._namespace == "dash_html_components"


def test_objectEl():
layout = html.ObjectEl(data="something", **{"data-x": "else"})
assert repr(layout) == "ObjectEl(data='something', data-x='else')"

with pytest.raises(TypeError):
html.ObjectEl(datax="something")


def test_customDocs():
assert "CAUTION" in html.Script.__doc__[:100]
assert "OBSOLETE" in html.Blink.__doc__[:100]
assert "DEPRECATED" in html.Marquee.__doc__[:100]
8 changes: 4 additions & 4 deletions tests/test_dash_import.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,18 +5,18 @@
class TestDashImport(unittest.TestCase):
def setUp(self):
with open('dash.py', 'w') as f:
pass
pass

def tearDown(self):
try:
os.remove('dash.py')
os.remove('dash.pyc')
except OSError:
pass

def test_dash_import(self):
"""Test that program exits if the wrong dash module was imported"""

with self.assertRaises(SystemExit) as cm:
import dash_html_components

Expand Down
Loading