Skip to content

Commit 45b2148

Browse files
mbostockFil
andauthored
inline styles; tabular nums (#579)
* inline styles; tabular nums * inline styles test (#581) * keep inline stylesheet * inline stylesheets * top-level className (#582) * keep inline stylesheet * inline stylesheets * top-level className * coerce className to string Co-authored-by: Mike Bostock <mbostock@gmail.com> Co-authored-by: Philippe Rivière <fil@rezo.net>
1 parent ca57bbd commit 45b2148

File tree

139 files changed

+1843
-187
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+1843
-187
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ Plot.plot({
106106
})
107107
```
108108

109+
The generated SVG element has a random class name which applies a default stylesheet. Use the top-level **className** option to specify that class name.
110+
109111
### Scale options
110112

111113
Plot passes data through [scales](https://observablehq.com/@observablehq/plot-scales) as needed before rendering marks. A scale maps abstract values such as time or temperature to visual values such as position or color. Within a given plot, marks share scales. For example, if a plot has two Plot.line marks, both share the same *x* and *y* scales for a consistent representation of data. (Plot does not currently support dual-axis charts, which are [not advised](https://blog.datawrapper.de/dualaxis/).)

bundle.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
import "./src/style.css";
21
export {version} from "./package.json";
32
export * from "./src/index.js";

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
},
2323
"files": [
2424
"dist/**/*.js",
25-
"src/**/*.js",
26-
"src/**/*.css"
25+
"src/**/*.js"
2726
],
2827
"scripts": {
2928
"test": "mkdir -p test/output && mocha -r module-alias/register 'test/**/*-test.js' test/plot.js && eslint src test",
@@ -38,12 +37,10 @@
3837
"devDependencies": {
3938
"@rollup/plugin-json": "^4.1.0",
4039
"@rollup/plugin-node-resolve": "^13.0.4",
41-
"clean-css": "^5.1.1",
4240
"eslint": "^7.12.1",
4341
"htl": "^0.3.0",
4442
"js-beautify": "^1.13.0",
4543
"jsdom": "^17.0.0",
46-
"jsesc": "^3.0.2",
4744
"mocha": "^9.1.0",
4845
"module-alias": "^2.2.2",
4946
"rollup": "^2.32.1",

rollup.config.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import fs from "fs";
2-
import path from "path";
32
import {terser} from "rollup-plugin-terser";
43
import json from "@rollup/plugin-json";
54
import node from "@rollup/plugin-node-resolve";
6-
import jsesc from "jsesc";
7-
import CleanCSS from "clean-css";
85
import * as meta from "./package.json";
96

107
const filename = meta.name.split("/").pop();
@@ -20,27 +17,6 @@ const copyrights = fs.readFileSync("./LICENSE", "utf-8")
2017
.filter(line => /^copyright\s+/i.test(line))
2118
.map(line => line.replace(/^copyright\s+/i, ""));
2219

23-
// A lil’ Rollup plugin to allow importing of style.css.
24-
const cssPath = path.resolve("./src/style.css");
25-
const css = {
26-
load(id) {
27-
if (id !== cssPath) return;
28-
return fs.readFileSync(id, "utf8");
29-
},
30-
transform(input, id) {
31-
if (id !== cssPath) return;
32-
return {
33-
moduleSideEffects: true,
34-
code: `if (typeof document !== 'undefined') {
35-
const style = document.createElement('style');
36-
style.textContent = '${jsesc(new CleanCSS().minify(input).styles)}';
37-
document.head.appendChild(style);
38-
}
39-
`
40-
};
41-
}
42-
};
43-
4420
const config = {
4521
input: "bundle.js",
4622
external: ["d3"],
@@ -49,7 +25,6 @@ const config = {
4925
banner: `// ${meta.name} v${meta.version} Copyright ${copyrights.join(", ")}`
5026
},
5127
plugins: [
52-
css,
5328
json(),
5429
node()
5530
]

src/plot.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import {Axes, autoAxisTicks, autoScaleLabels} from "./axes.js";
33
import {facets} from "./facet.js";
44
import {markify} from "./mark.js";
55
import {Scales, autoScaleRange, applyScales, exposeScales, isOrdinalScale} from "./scales.js";
6-
import {filterStyles, offset} from "./style.js";
6+
import {filterStyles, maybeClassName, offset} from "./style.js";
77

88
export function plot(options = {}) {
99
const {facet, style, caption} = options;
1010

11+
// className for inline styles
12+
const className = maybeClassName(options.className);
13+
1114
// When faceting, wrap all marks in a faceting mark.
1215
if (facet !== undefined) {
1316
const {marks} = options;
@@ -69,12 +72,27 @@ export function plot(options = {}) {
6972
const {width, height} = dimensions;
7073

7174
const svg = create("svg")
72-
.attr("class", "plot")
75+
.attr("class", className)
7376
.attr("fill", "currentColor")
77+
.attr("font-family", "system-ui, sans-serif")
78+
.attr("font-size", 10)
79+
.attr("font-variant", "tabular-nums")
7480
.attr("text-anchor", "middle")
7581
.attr("width", width)
7682
.attr("height", height)
7783
.attr("viewBox", `0 0 ${width} ${height}`)
84+
.call(svg => svg.append("style").text(`
85+
.${className} {
86+
display: block;
87+
background: white;
88+
height: auto;
89+
height: intrinsic;
90+
max-width: 100%;
91+
}
92+
.${className} text {
93+
white-space: pre;
94+
}
95+
`))
7896
.each(function() {
7997
if (typeof style === "string") this.style = style;
8098
else Object.assign(this.style, style);

src/style.css

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/style.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,12 @@ export function filterStyles(index, {fill: F, fillOpacity: FO, stroke: S, stroke
153153
function none(color) {
154154
return color == null || color === "none";
155155
}
156+
157+
const validClassName = /^-?([_a-z]|[\240-\377]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])([_a-z0-9-]|[\240-\377]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*$/;
158+
159+
export function maybeClassName(name) {
160+
if (name === undefined) return `plot-${Math.random().toString(16).slice(2)}`;
161+
name = `${name}`;
162+
if (!validClassName.test(name)) throw new Error(`invalid class name: ${name}`);
163+
return name;
164+
}

test/output/aaplBollinger.svg

Lines changed: 14 additions & 1 deletion
Loading

test/output/aaplCandlestick.svg

Lines changed: 14 additions & 1 deletion
Loading

test/output/aaplChangeVolume.svg

Lines changed: 14 additions & 1 deletion
Loading

0 commit comments

Comments
 (0)