diff --git a/src/plot.js b/src/plot.js
index 8350bb4347..abd4a28f63 100644
--- a/src/plot.js
+++ b/src/plot.js
@@ -6,7 +6,7 @@ import {Scales, autoScaleRange} from "./scales.js";
import {offset} from "./style.js";
export function plot(options = {}) {
- const {facet, style, caption} = options;
+ const {facet, style, caption, title, subtitle} = options;
// When faceting, wrap all marks in a faceting mark.
if (facet !== undefined) {
@@ -88,12 +88,28 @@ export function plot(options = {}) {
if (node != null) svg.appendChild(node);
}
- // Wrap the plot in a figure with a caption, if desired.
- if (caption == null) return svg;
+ // Wrap the plot in a figure with a caption, a title or a subtitle, if desired.
+ if (caption == null && title == null && subtitle == null) return svg;
+
const figure = document.createElement("figure");
+
+ if (title) {
+ const figtitle = figure.appendChild(document.createElement("h1"));
+ figtitle.appendChild(title instanceof Node ? title : document.createTextNode(title));
+ }
+
+ if (subtitle) {
+ const figsubtitle = figure.appendChild(document.createElement("h2"));
+ figsubtitle.appendChild(subtitle instanceof Node ? subtitle : document.createTextNode(subtitle));
+ }
+
figure.appendChild(svg);
- const figcaption = figure.appendChild(document.createElement("figcaption"));
- figcaption.appendChild(caption instanceof Node ? caption : document.createTextNode(caption));
+
+ if (caption) {
+ const figcaption = figure.appendChild(document.createElement("figcaption"));
+ figcaption.appendChild(caption instanceof Node ? caption : document.createTextNode(caption));
+ }
+
return figure;
}
diff --git a/test/output/subtitle.html b/test/output/subtitle.html
new file mode 100644
index 0000000000..4f3f1189f0
--- /dev/null
+++ b/test/output/subtitle.html
@@ -0,0 +1,169 @@
+
+
Relative frequency of letters in the English language
+
\ No newline at end of file
diff --git a/test/output/subtitleHtml.html b/test/output/subtitleHtml.html
new file mode 100644
index 0000000000..a3ae22ba42
--- /dev/null
+++ b/test/output/subtitleHtml.html
@@ -0,0 +1,169 @@
+
+
Relative frequency of letters in the English language
+
\ No newline at end of file
diff --git a/test/output/title.html b/test/output/title.html
new file mode 100644
index 0000000000..951272057b
--- /dev/null
+++ b/test/output/title.html
@@ -0,0 +1,169 @@
+
+
Relative frequency of letters in the English language
+
\ No newline at end of file
diff --git a/test/output/titleHtml.html b/test/output/titleHtml.html
new file mode 100644
index 0000000000..a21f83146a
--- /dev/null
+++ b/test/output/titleHtml.html
@@ -0,0 +1,169 @@
+
+
Relative frequency of letters in the English language
+
\ No newline at end of file
diff --git a/test/output/titleSubtitle.html b/test/output/titleSubtitle.html
new file mode 100644
index 0000000000..60e40afb26
--- /dev/null
+++ b/test/output/titleSubtitle.html
@@ -0,0 +1,170 @@
+
+
Relative frequency of letters in the English language
+
Data: Cryptographical Mathematics
+
\ No newline at end of file
diff --git a/test/output/titleSubtitleHtml.html b/test/output/titleSubtitleHtml.html
new file mode 100644
index 0000000000..568e2625e9
--- /dev/null
+++ b/test/output/titleSubtitleHtml.html
@@ -0,0 +1,170 @@
+
+
Relative frequency of letters in the English language
+
Data: Cryptographical Mathematics
+
\ No newline at end of file
diff --git a/test/plots/index.html b/test/plots/index.html
index 64297f265e..8249adf729 100644
--- a/test/plots/index.html
+++ b/test/plots/index.html
@@ -15,6 +15,15 @@
max-width: 640px;
}
+h1 {
+ margin: 0;
+}
+
+h2 {
+ margin: 0;
+ margin-bottom: 0.5rem;
+}
+
figcaption {
color: #838383;
}
diff --git a/test/plots/index.js b/test/plots/index.js
index 6ee155b7cd..c1883c6f47 100644
--- a/test/plots/index.js
+++ b/test/plots/index.js
@@ -29,6 +29,12 @@ export {default as empty} from "./empty.js";
export {default as emptyX} from "./empty-x.js";
export {default as figcaption} from "./figcaption.js";
export {default as figcaptionHtml} from "./figcaption-html.js";
+export {default as title} from "./title.js";
+export {default as titleHtml} from "./title-html.js";
+export {default as subtitle} from "./subtitle.js";
+export {default as subtitleHtml} from "./subtitle-html.js";
+export {default as titleSubtitle} from "./title-subtitle.js";
+export {default as titleSubtitleHtml} from "./title-subtitle-html.js";
export {default as fruitSales} from "./fruit-sales.js";
export {default as fruitSalesDate} from "./fruit-sales-date.js";
export {default as gistempAnomaly} from "./gistemp-anomaly.js";
diff --git a/test/plots/subtitle-html.js b/test/plots/subtitle-html.js
new file mode 100644
index 0000000000..35f38e067f
--- /dev/null
+++ b/test/plots/subtitle-html.js
@@ -0,0 +1,22 @@
+import * as Plot from "@observablehq/plot";
+import * as d3 from "d3";
+import { html } from "htl";
+
+export default async function() {
+ const alphabet = await d3.csv("data/alphabet.csv", d3.autoType);
+ return Plot.plot({
+ subtitle: html`Relative frequency of letters in the English language`,
+ x: {
+ label: null
+ },
+ y: {
+ label: "↑ Frequency (%)",
+ transform: y => y * 100,
+ grid: true
+ },
+ marks: [
+ Plot.barY(alphabet, {x: "letter", y: "frequency"}),
+ Plot.ruleY([0])
+ ]
+ });
+}
diff --git a/test/plots/subtitle.js b/test/plots/subtitle.js
new file mode 100644
index 0000000000..c8b0c9d0d8
--- /dev/null
+++ b/test/plots/subtitle.js
@@ -0,0 +1,21 @@
+import * as Plot from "@observablehq/plot";
+import * as d3 from "d3";
+
+export default async function() {
+ const alphabet = await d3.csv("data/alphabet.csv", d3.autoType);
+ return Plot.plot({
+ subtitle: "Relative frequency of letters in the English language",
+ x: {
+ label: null
+ },
+ y: {
+ label: "↑ Frequency (%)",
+ transform: y => y * 100,
+ grid: true
+ },
+ marks: [
+ Plot.barY(alphabet, {x: "letter", y: "frequency"}),
+ Plot.ruleY([0])
+ ]
+ });
+}
diff --git a/test/plots/title-html.js b/test/plots/title-html.js
new file mode 100644
index 0000000000..d720550757
--- /dev/null
+++ b/test/plots/title-html.js
@@ -0,0 +1,22 @@
+import * as Plot from "@observablehq/plot";
+import * as d3 from "d3";
+import { html } from "htl";
+
+export default async function() {
+ const alphabet = await d3.csv("data/alphabet.csv", d3.autoType);
+ return Plot.plot({
+ title: html`Relative frequency of letters in the English language`,
+ x: {
+ label: null
+ },
+ y: {
+ label: "↑ Frequency (%)",
+ transform: y => y * 100,
+ grid: true
+ },
+ marks: [
+ Plot.barY(alphabet, {x: "letter", y: "frequency"}),
+ Plot.ruleY([0])
+ ]
+ });
+}
diff --git a/test/plots/title-subtitle-html.js b/test/plots/title-subtitle-html.js
new file mode 100644
index 0000000000..b5b56123fe
--- /dev/null
+++ b/test/plots/title-subtitle-html.js
@@ -0,0 +1,23 @@
+import * as Plot from "@observablehq/plot";
+import * as d3 from "d3";
+import { html } from "htl";
+
+export default async function() {
+ const alphabet = await d3.csv("data/alphabet.csv", d3.autoType);
+ return Plot.plot({
+ title: "Relative frequency of letters in the English language",
+ subtitle: html`Data: Cryptographical Mathematics`,
+ x: {
+ label: null
+ },
+ y: {
+ label: "↑ Frequency (%)",
+ transform: y => y * 100,
+ grid: true
+ },
+ marks: [
+ Plot.barY(alphabet, {x: "letter", y: "frequency"}),
+ Plot.ruleY([0])
+ ]
+ });
+}
diff --git a/test/plots/title-subtitle.js b/test/plots/title-subtitle.js
new file mode 100644
index 0000000000..c3b6d26bab
--- /dev/null
+++ b/test/plots/title-subtitle.js
@@ -0,0 +1,22 @@
+import * as Plot from "@observablehq/plot";
+import * as d3 from "d3";
+
+export default async function() {
+ const alphabet = await d3.csv("data/alphabet.csv", d3.autoType);
+ return Plot.plot({
+ title: "Relative frequency of letters in the English language",
+ subtitle: "Data: Cryptographical Mathematics",
+ x: {
+ label: null
+ },
+ y: {
+ label: "↑ Frequency (%)",
+ transform: y => y * 100,
+ grid: true
+ },
+ marks: [
+ Plot.barY(alphabet, {x: "letter", y: "frequency"}),
+ Plot.ruleY([0])
+ ]
+ });
+}
diff --git a/test/plots/title.js b/test/plots/title.js
new file mode 100644
index 0000000000..cf4d117ca0
--- /dev/null
+++ b/test/plots/title.js
@@ -0,0 +1,21 @@
+import * as Plot from "@observablehq/plot";
+import * as d3 from "d3";
+
+export default async function() {
+ const alphabet = await d3.csv("data/alphabet.csv", d3.autoType);
+ return Plot.plot({
+ title: "Relative frequency of letters in the English language",
+ x: {
+ label: null
+ },
+ y: {
+ label: "↑ Frequency (%)",
+ transform: y => y * 100,
+ grid: true
+ },
+ marks: [
+ Plot.barY(alphabet, {x: "letter", y: "frequency"}),
+ Plot.ruleY([0])
+ ]
+ });
+}