Skip to content
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
1 change: 0 additions & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,3 @@ jobs:
echo ::add-matcher::.github/eslint.json
yarn run eslint . --format=compact
- run: yarn test
- run: yarn readme:check
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.DS_Store
build/
dist/
types/
node_modules/
Expand Down
1,441 changes: 466 additions & 975 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bundle.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export {version} from "./package.json";
export * from "./src/index.js";
export * from "./dist/index.js";
10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@
"types/**/*.d.ts"
],
"scripts": {
"test": "yarn test:mocha && yarn test:typecheck && yarn test:lint && yarn readme:check",
"test": "yarn test:mocha && yarn test:typecheck && yarn test:lint",
"test:mocha": "mkdir -p test/output && mocha --conditions=mocha 'test/**/*-test.*' 'test/plot.js'",
"test:lint": "eslint src test",
"test:typecheck": "tsc --noEmit",
"readme:check": "tsx scripts/jsdoc-to-readme.ts --check",
"readme:update": "tsx scripts/jsdoc-to-readme.ts",
"prepublishOnly": "rm -rf dist && rollup -c && tsc",
"prepublishOnly": "rm -rf build dist && tsc && tsx scripts/readme-to-jsdoc.ts && rollup -c",
"postpublish": "git push && git push --tags",
"dev": "vite"
},
Expand All @@ -47,7 +45,6 @@
"@rollup/plugin-commonjs": "22",
"@rollup/plugin-json": "4",
"@rollup/plugin-node-resolve": "13",
"@rollup/plugin-typescript": "^8.3.2",
"@types/d3": "^7.4.0",
"@types/expect": "^24.3.0",
"@types/mocha": "^9.1.1",
Expand All @@ -62,13 +59,12 @@
"htl": "0.3",
"js-beautify": "1",
"jsdom": "19",
"mkdirp": "^1.0.4",
"mocha": "10",
"module-alias": "2",
"prettier": "^2.7.1",
"rollup": "2",
"rollup-plugin-terser": "7",
"ts-morph": "^15.1.0",
"tslib": "^2.4.0",
"tsx": "^3.8.0",
"typescript": "^4.6.4",
"typescript-module-alias": "^1.0.2",
Expand Down
3 changes: 1 addition & 2 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";
import node from "@rollup/plugin-node-resolve";
import * as meta from "./package.json";
import typescript from "@rollup/plugin-typescript";

const filename = meta.name.split("/").pop();

Expand All @@ -27,7 +26,7 @@ const config = {
indent: false,
banner: `// ${meta.name} v${meta.version} Copyright ${copyrights.join(", ")}`
},
plugins: [typescript(), commonjs(), json(), node()]
plugins: [commonjs(), json(), node()]
};

export default [
Expand Down
119 changes: 0 additions & 119 deletions scripts/jsdoc-to-readme.ts

This file was deleted.

78 changes: 78 additions & 0 deletions scripts/readme-to-jsdoc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {readFileSync, writeFileSync} from "fs";
import {dirname} from "path";
import glob from "glob";
import mkdirp from "mkdirp";

// Extract the documentation from the README.
const readme = readFileSync("./README.md", "utf-8");
const docmap = new Map<string, string[]>();
let doc: {name: string; lines: string[]} | null = null;
for (const [i, line] of readme.split("\n").entries()) {
if (/<!--\s*jsdoc/.test(line)) {
let match: RegExpExecArray | null;
if ((match = /^<!--\s+jsdoc\s+(\w+)\s+-->$/.exec(line))) {
const [, name] = match;
if (doc) {
throw new Error(`nested jsdoc directive on line ${i}: ${line}`);
}
if (docmap.has(name)) {
throw new Error(`duplicate jsdoc directive on line ${i}: ${line}`);
}
doc = {name, lines: []};
} else if ((match = /^<!--\s+jsdocEnd\s+(\w+)\s+-->$/.exec(line))) {
const [, name] = match;
if (!doc) {
throw new Error(`orphaned jsdocEnd directive on line ${i}: ${line}`);
}
if (doc.name !== name) {
throw new Error(`mismatched jsdocEnd ${doc.name} directive on line ${i}: ${line}`);
}
docmap.set(doc.name, doc.lines);
doc = null;
} else {
throw new Error(`malformed jsdoc directive on line ${i}: ${line}`);
}
} else if (doc) {
doc.lines.push(line);
}
}

// Make relative and anchor links absolute.
for (const lines of docmap.values()) {
for (let i = 0, n = lines.length; i < n; ++i) {
lines[i] = lines[i]
.replace(/\]\(#([^)]+)\)/g, "](./README.md#$1)")
.replace(/\]\(\.\/([^)]+)\)/g, "](https://github.com/observablehq/plot/blob/main/$1)");
}
}

// Copy files from build/ to dist/, replacing /** @jsdoc name */ directives.
const unused = new Set(docmap.keys());
for (const file of glob.sync("build/**/*.js")) {
process.stdout.write(`\x1b[2m${file}\x1b[0m`);
const lines = readFileSync(file, "utf-8").split("\n");
let count = 0;
for (let i = 0, n = lines.length; i < n; ++i) {
let match: RegExpExecArray | null;
if ((match = /^\/\*\*\s+@jsdoc\s+(\w+)\s+\*\/$/.exec(lines[i]))) {
const [, name] = match;
const docs = docmap.get(name);
if (!docs) throw new Error(`missing @jsdoc definition: ${name}`);
if (!unused.has(name)) throw new Error(`duplicate @jsdoc reference: ${name}`);
unused.delete(name);
++count;
lines[i] = docs
.map((line, i, lines) => (i === 0 ? `/** ${line}` : i === lines.length - 1 ? ` * ${line}\n */` : ` * ${line}`))
.join("\n");
}
}
const ofile = file.replace(/^build\//, "dist/");
process.stdout.write(` → \x1b[36m${ofile}\x1b[0m${count ? ` (${count} jsdoc${count === 1 ? "" : "s"})` : ""}\n`);
const odir = dirname(ofile);
mkdirp.sync(odir);
writeFileSync(ofile, lines.join("\n"), "utf-8");
}

for (const name of unused) {
console.warn(`\x1b[33m[warning] unused @jsdoc directive:\x1b[0m ${name}`);
}
36 changes: 3 additions & 33 deletions src/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,7 @@ export function formatNumber(locale = "en-US"): (value: any) => string | undefin
return (i: any) => (i != null && !isNaN(i) ? format.format(i) : undefined);
}

/**
* ```js
* Plot.formatMonth("es-MX", "long")(0) // "enero"
* ```
*
* Returns a function that formats a given month number (from 0 = January to 11
* = December) according to the specified *locale* and *format*. The *locale* is
* a [BCP 47 language tag](https://tools.ietf.org/html/bcp47) and defaults to
* U.S. English. The *format* is a [month
* format](https://tc39.es/ecma402/#datetimeformat-objects): either *2-digit*,
* *numeric*, *narrow*, *short*, *long*; if not specified, it defaults to
* *short*.
*/
/** @jsdoc formatMonth */
export function formatMonth(
locale = "en-US",
format: "numeric" | "2-digit" | "long" | "short" | "narrow" | undefined = "short"
Expand All @@ -42,32 +30,14 @@ export function formatMonth(
i != null && !isNaN((i = +new Date(Date.UTC(2000, +i)))) ? fmt.format(i) : undefined;
}

/**
* ```js
* Plot.formatWeekday("es-MX", "long")(0) // "domingo"
* ```
*
* Returns a function that formats a given week day number (from 0 = Sunday to 6
* = Saturday) according to the specified *locale* and *format*. The *locale* is
* a [BCP 47 language tag](https://tools.ietf.org/html/bcp47) and defaults to
* U.S. English. The *format* is a [weekday
* format](https://tc39.es/ecma402/#datetimeformat-objects): either *narrow*,
* *short*, or *long*; if not specified, it defaults to *short*.
*/
/** @jsdoc formatWeekday */
export function formatWeekday(locale = "en-US", format: "long" | "short" | "narrow" | undefined = "short") {
const fmt = weekdayFormat(locale, format);
return (i: Date | number | null | undefined) =>
i != null && !isNaN((i = +new Date(Date.UTC(2001, 0, +i)))) ? fmt.format(i) : undefined;
}

/**
* ```js
* Plot.formatIsoDate(new Date("2020-01-01T00:00.000Z")) // "2020-01-01"
* ```
*
* Given a *date*, returns the shortest equivalent ISO 8601 UTC string. If the
* given *date* is not valid, returns `"Invalid Date"`.
*/
/** @jsdoc formatIsoDate */
export function formatIsoDate(date: Date): string {
return isoFormat(date, "Invalid Date");
}
Expand Down
25 changes: 1 addition & 24 deletions src/legends.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,7 @@ const legendRegistry = new Map([
["opacity", legendOpacity]
]);

/**
* Returns a standalone legend for the scale defined by the given *options*
* object. The *options* object must define at least one scale; see [Scale
* options](https://github.com/observablehq/plot/blob/main/README.md#scale-options)
* for how to define a scale. For example, here is a ramp legend of a linear
* color scale with the default domain of [0, 1] and default scheme *turbo*:
*
* ```js
* Plot.legend({color: {type: "linear"}})
* ```
*
* The *options* object may also include any additional legend options described
* in the previous section. For example, to make the above legend slightly
* wider:
*
* ```js
* Plot.legend({
* width: 320,
* color: {
* type: "linear"
* }
* })
* ```
*/
/** @jsdoc legend */
export function legend(options = {}) {
for (const [key, value] of legendRegistry) {
const scale = options[key];
Expand Down
Loading