Skip to content

Commit 1df1d85

Browse files
duaneatatFilmbostock
authored
Typescript (#880)
* convert some files to ts * typescript * undo test parallelism * eslint-disable-line @typescript-eslint/no-this-alias * for some reason moving to node@18 makes my local install insist on changing this… doesn't seem problematic * fix formatting * remove unnecessary yarn * remove unnecesary --files * make eslint disables global * fix regular expression * fix formatting * fix formatting * fix formatting * fix formatting Co-authored-by: Philippe Rivière <[email protected]> Co-authored-by: Mike Bostock <[email protected]>
1 parent 0c80c81 commit 1df1d85

21 files changed

+1023
-139
lines changed

.eslintrc.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
{
2-
"extends": "eslint:recommended",
3-
"parserOptions": {
4-
"sourceType": "module",
5-
"ecmaVersion": 2020
6-
},
2+
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
3+
"plugins": ["@typescript-eslint"],
4+
"parser": "@typescript-eslint/parser",
75
"env": {
86
"es6": true,
97
"node": true,
@@ -15,6 +13,9 @@
1513
"no-sparse-arrays": 0,
1614
"no-unexpected-multiline": 0,
1715
"comma-dangle": ["error", "never"],
18-
"semi": [2, "always"]
16+
"semi": [2, "always"],
17+
"@typescript-eslint/no-empty-function": 0,
18+
"@typescript-eslint/no-this-alias": 0,
19+
"@typescript-eslint/no-unused-vars": ["error", {"ignoreRestSiblings": true}]
1920
}
2021
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ dist/
33
node_modules/
44
test/output/*-changed.svg
55
test/output/*-changed.html
6+
tsconfig.tsbuildinfo
7+
yarn-error.log

.mocharc.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"require": ["module-alias/register.js", "ts-node/register"],
3+
"loader": "ts-node/esm",
4+
"extensions": ["js", "ts"],
5+
"spec": [
6+
"test/**/*-test.*",
7+
"test/plot.js"
8+
],
9+
"watch-files": [
10+
"bundle.js",
11+
"test",
12+
"src"
13+
]
14+
}

package.json

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
},
99
"license": "ISC",
1010
"type": "module",
11-
"main": "src/index.js",
12-
"module": "src/index.js",
11+
"main": "dist/index.js",
12+
"module": "dist/index.js",
1313
"jsdelivr": "dist/plot.umd.min.js",
1414
"unpkg": "dist/plot.umd.min.js",
1515
"exports": {
16+
"mocha": "./src/index.js",
1617
"umd": "./dist/plot.umd.min.js",
17-
"default": "./src/index.js"
18+
"default": "./dist/index.js"
1819
},
1920
"repository": {
2021
"type": "git",
@@ -25,8 +26,11 @@
2526
"src/**/*.js"
2627
],
2728
"scripts": {
28-
"test": "mkdir -p test/output && mocha -r module-alias/register 'test/**/*-test.js' test/plot.js && eslint src test",
29-
"prepublishOnly": "rm -rf dist && rollup -c",
29+
"test": "yarn test:typecheck && yarn test:lint && yarn test:mocha",
30+
"test:mocha": "mkdir -p test/output && mocha --conditions=mocha",
31+
"test:lint": "eslint src test",
32+
"test:typecheck": "tsc --noEmit",
33+
"prepublishOnly": "rm -rf dist && rollup -c && tsc",
3034
"postpublish": "git push && git push --tags",
3135
"dev": "vite"
3236
},
@@ -38,15 +42,27 @@
3842
"@rollup/plugin-commonjs": "22",
3943
"@rollup/plugin-json": "4",
4044
"@rollup/plugin-node-resolve": "13",
45+
"@rollup/plugin-typescript": "^8.3.2",
46+
"@types/d3": "^7.4.0",
47+
"@types/expect": "^24.3.0",
48+
"@types/mocha": "^9.1.1",
49+
"@types/node": "^17.0.35",
50+
"@typescript-eslint/eslint-plugin": "^5.25.0",
51+
"@typescript-eslint/parser": "^5.25.0",
4152
"canvas": "2",
42-
"eslint": "8",
53+
"eslint": "^8.16.0",
54+
"glob": "^8.0.3",
4355
"htl": "0.3",
4456
"js-beautify": "1",
4557
"jsdom": "19",
4658
"mocha": "10",
4759
"module-alias": "2",
4860
"rollup": "2",
4961
"rollup-plugin-terser": "7",
62+
"ts-node": "^10.8.0",
63+
"tslib": "^2.4.0",
64+
"typescript": "^4.6.4",
65+
"typescript-module-alias": "^1.0.2",
5066
"vite": "2"
5167
},
5268
"dependencies": {

rollup.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import commonjs from "@rollup/plugin-commonjs";
44
import json from "@rollup/plugin-json";
55
import node from "@rollup/plugin-node-resolve";
66
import * as meta from "./package.json";
7+
import typescript from "@rollup/plugin-typescript";
78

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

@@ -26,6 +27,7 @@ const config = {
2627
banner: `// ${meta.name} v${meta.version} Copyright ${copyrights.join(", ")}`
2728
},
2829
plugins: [
30+
typescript(),
2931
commonjs(),
3032
json(),
3133
node()

src/curve.js renamed to src/curve.ts

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,41 @@ import {
2020
curveStepAfter,
2121
curveStepBefore
2222
} from "d3";
23+
import type {
24+
CurveFactory,
25+
CurveBundleFactory,
26+
CurveCardinalFactory,
27+
CurveCatmullRomFactory
28+
} from "d3";
29+
30+
type CurveFunction =
31+
| CurveFactory
32+
| CurveBundleFactory
33+
| CurveCardinalFactory
34+
| CurveCatmullRomFactory;
35+
type CurveName =
36+
| "basis"
37+
| "basis-closed"
38+
| "basis-open"
39+
| "bundle"
40+
| "bump-x"
41+
| "bump-y"
42+
| "cardinal"
43+
| "cardinal-closed"
44+
| "cardinal-open"
45+
| "catmull-rom"
46+
| "catmull-rom-closed"
47+
| "catmull-rom-open"
48+
| "linear"
49+
| "linear-closed"
50+
| "monotone-x"
51+
| "monotone-y"
52+
| "natural"
53+
| "step"
54+
| "step-after"
55+
| "step-before";
2356

24-
const curves = new Map([
57+
const curves = new Map<CurveName, CurveFunction>([
2558
["basis", curveBasis],
2659
["basis-closed", curveBasisClosed],
2760
["basis-open", curveBasisOpen],
@@ -44,19 +77,20 @@ const curves = new Map([
4477
["step-before", curveStepBefore]
4578
]);
4679

47-
export function Curve(curve = curveLinear, tension) {
80+
export function Curve(
81+
curve: CurveName | CurveFunction = curveLinear,
82+
tension?: number
83+
): CurveFunction {
4884
if (typeof curve === "function") return curve; // custom curve
49-
const c = curves.get(`${curve}`.toLowerCase());
85+
const c = curves.get(`${curve}`.toLowerCase() as CurveName);
5086
if (!c) throw new Error(`unknown curve: ${curve}`);
5187
if (tension !== undefined) {
52-
switch (c) {
53-
case curveBundle: return c.beta(tension);
54-
case curveCardinalClosed:
55-
case curveCardinalOpen:
56-
case curveCardinal: return c.tension(tension);
57-
case curveCatmullRomClosed:
58-
case curveCatmullRomOpen:
59-
case curveCatmullRom: return c.alpha(tension);
88+
if ("beta" in c) {
89+
return c.beta(tension);
90+
} else if ("tension" in c) {
91+
return c.tension(tension);
92+
} else if ("alpha" in c) {
93+
return c.alpha(tension);
6094
}
6195
}
6296
return c;

src/defined.js

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

src/defined.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {ascending, descending, type Primitive} from "d3";
2+
3+
export function defined(x: Primitive | undefined): boolean {
4+
return x != null && !Number.isNaN(x);
5+
}
6+
7+
export function ascendingDefined(a: Primitive | undefined, b: Primitive | undefined): number {
8+
return +defined(b) - +defined(a) || ascending(a, b);
9+
}
10+
11+
export function descendingDefined(a: Primitive | undefined, b: Primitive | undefined): number {
12+
return +defined(b) - +defined(a) || descending(a, b);
13+
}
14+
15+
export function nonempty(x: unknown): boolean {
16+
return x != null && `${x}` !== "";
17+
}
18+
19+
export function finite(x: number): number {
20+
return isFinite(x) ? x : NaN;
21+
}
22+
23+
export function positive(x: number): number {
24+
return x > 0 && isFinite(x) ? x : NaN;
25+
}
26+
27+
export function negative(x: number): number {
28+
return x < 0 && isFinite(x) ? x : NaN;
29+
}

src/format.js

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

src/format.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import {format as isoFormat} from "isoformat";
3+
import {string} from "./options.js";
4+
import {memoize1} from "./memoize.js";
5+
6+
const numberFormat = memoize1<Intl.NumberFormat>((locale: string | string[] | undefined) => new Intl.NumberFormat(locale));
7+
const monthFormat = memoize1<Intl.DateTimeFormat>((locale: string | string[] | undefined, month: "numeric" | "2-digit" | "long" | "short" | "narrow" | undefined) => new Intl.DateTimeFormat(locale, {timeZone: "UTC", month}));
8+
const weekdayFormat = memoize1<Intl.DateTimeFormat>((locale: string | string[] | undefined, weekday: "long" | "short" | "narrow" | undefined) => new Intl.DateTimeFormat(locale, {timeZone: "UTC", weekday}));
9+
10+
export function formatNumber(locale = "en-US"): (value: any) => string | undefined {
11+
const format = numberFormat(locale);
12+
return (i: any) => i != null && !isNaN(i) ? format.format(i) : undefined;
13+
}
14+
15+
export function formatMonth(locale = "en-US", month: "numeric" | "2-digit" | "long" | "short" | "narrow" | undefined = "short") {
16+
const format = monthFormat(locale, month);
17+
return (i: Date | number | null | undefined) => i != null && !isNaN(i = +new Date(Date.UTC(2000, +i))) ? format.format(i) : undefined;
18+
}
19+
20+
export function formatWeekday(locale = "en-US", weekday: "long" | "short" | "narrow" | undefined = "short") {
21+
const format = weekdayFormat(locale, weekday);
22+
return (i: Date | number | null | undefined) => i != null && !isNaN(i = +new Date(Date.UTC(2001, 0, +i))) ? format.format(i) : undefined;
23+
}
24+
25+
export function formatIsoDate(date: Date): string {
26+
return isoFormat(date, "Invalid Date");
27+
}
28+
29+
export function formatAuto(locale = "en-US"): (value: any) => string | number | undefined {
30+
const number = formatNumber(locale);
31+
return (v: any) => (v instanceof Date ? formatIsoDate : typeof v === "number" ? number : string)(v);
32+
}
33+
34+
// TODO When Plot supports a top-level locale option, this should be removed
35+
// because it lacks context to know which locale to use; formatAuto should be
36+
// used instead whenever possible.
37+
export const formatDefault = formatAuto();

0 commit comments

Comments
 (0)