New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typescript #880
Typescript #880
Changes from 5 commits
2a19570
62815b5
1e056ea
08807d9
e1091a2
e5e63e1
c5e0bf6
69e13ea
f0fd0b7
5af1c28
0570342
34480ce
cadca94
66d01da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,5 @@ dist/ | |
node_modules/ | ||
test/output/*-changed.svg | ||
test/output/*-changed.html | ||
tsconfig.tsbuildinfo | ||
yarn-error.log |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"require": ["module-alias/register.js", "ts-node/register"], | ||
"loader": "ts-node/esm", | ||
"extensions": ["js", "ts"], | ||
"spec": [ | ||
"test/**/*-test.*", | ||
"test/plot.js" | ||
], | ||
"watch-files": [ | ||
"bundle.js", | ||
"test", | ||
"src" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,8 +20,32 @@ import { | |
curveStepAfter, | ||
curveStepBefore | ||
} from "d3"; | ||
import type { CurveFactory, CurveBundleFactory, CurveCardinalFactory, CurveCatmullRomFactory } from "d3"; | ||
|
||
const curves = new Map([ | ||
type CurveFunction = CurveFactory | CurveBundleFactory | CurveCardinalFactory | CurveCatmullRomFactory; | ||
type CurveName = | ||
| "basis" | ||
| "basis-closed" | ||
| "basis-open" | ||
| "bundle" | ||
| "bump-x" | ||
| "bump-y" | ||
| "cardinal" | ||
| "cardinal-closed" | ||
| "cardinal-open" | ||
| "catmull-rom" | ||
| "catmull-rom-closed" | ||
| "catmull-rom-open" | ||
| "linear" | ||
| "linear-closed" | ||
| "monotone-x" | ||
| "monotone-y" | ||
| "natural" | ||
| "step" | ||
| "step-after" | ||
| "step-before"; | ||
|
||
const curves = new Map<CurveName, CurveFunction>([ | ||
["basis", curveBasis], | ||
["basis-closed", curveBasisClosed], | ||
["basis-open", curveBasisOpen], | ||
|
@@ -44,19 +68,21 @@ const curves = new Map([ | |
["step-before", curveStepBefore] | ||
]); | ||
|
||
export function Curve(curve = curveLinear, tension) { | ||
export function Curve( | ||
curve: CurveName | CurveFunction = curveLinear, | ||
tension?: number | ||
): CurveFunction { | ||
if (typeof curve === "function") return curve; // custom curve | ||
const c = curves.get(`${curve}`.toLowerCase()); | ||
const c = curves.get(`${curve}`.toLowerCase() as CurveName); | ||
if (!c) throw new Error(`unknown curve: ${curve}`); | ||
Comment on lines
+85
to
86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It works, but the logic escapes me a little: if curve is not a curveName, the curves.get(…) must still be allowed to proceed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 makes sense! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. spoke to Fil about this, we can have the types be case-sensitive but still let the js be more permissive, so as it's written is good |
||
|
||
if (tension !== undefined) { | ||
switch (c) { | ||
case curveBundle: return c.beta(tension); | ||
case curveCardinalClosed: | ||
case curveCardinalOpen: | ||
case curveCardinal: return c.tension(tension); | ||
case curveCatmullRomClosed: | ||
case curveCatmullRomOpen: | ||
case curveCatmullRom: return c.alpha(tension); | ||
if ("beta" in c) { | ||
return c.beta(tension); | ||
} else if ("tension" in c) { | ||
return c.tension(tension); | ||
} else if ("alpha" in c) { | ||
return c.alpha(tension); | ||
} | ||
} | ||
return c; | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import {ascending, descending, type Primitive} from "d3"; | ||
|
||
export function defined(x: Primitive | undefined): boolean { | ||
return x != null && !Number.isNaN(x); | ||
} | ||
|
||
export function ascendingDefined(a: Primitive | undefined, b: Primitive | undefined): number { | ||
return +defined(b) - +defined(a) || ascending(a, b); | ||
} | ||
|
||
export function descendingDefined(a: Primitive | undefined, b: Primitive | undefined): number { | ||
return +defined(b) - +defined(a) || descending(a, b); | ||
} | ||
|
||
export function nonempty(x: unknown): boolean { | ||
return x != null && `${x}` !== ""; | ||
} | ||
|
||
export function finite(x: number): number { | ||
return isFinite(x) ? x : NaN; | ||
} | ||
|
||
export function positive(x: number): number { | ||
return x > 0 && isFinite(x) ? x : NaN; | ||
} | ||
|
||
export function negative(x: number): number { | ||
return x < 0 && isFinite(x) ? x : NaN; | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import {format as isoFormat} from "isoformat"; | ||
import {string} from "./options.js"; | ||
import {memoize1} from "./memoize.js"; | ||
|
||
|
||
const numberFormat = memoize1<Intl.NumberFormat>((locale: string | string[] | undefined) => new Intl.NumberFormat(locale)); | ||
const monthFormat = memoize1<Intl.DateTimeFormat>((locale: string | string[] | undefined, month: "numeric" | "2-digit" | "long" | "short" | "narrow" | undefined) => new Intl.DateTimeFormat(locale, {timeZone: "UTC", month})); | ||
const weekdayFormat = memoize1<Intl.DateTimeFormat>((locale: string | string[] | undefined, weekday: "long" | "short" | "narrow" | undefined) => new Intl.DateTimeFormat(locale, {timeZone: "UTC", weekday})); | ||
|
||
export function formatNumber(locale = "en-US"): (value: any) => string | undefined { | ||
const format = numberFormat(locale); | ||
return (i: any) => i != null && !isNaN(i) ? format.format(i) : undefined; | ||
} | ||
|
||
export function formatMonth(locale = "en-US", month: "numeric" | "2-digit" | "long" | "short" | "narrow" | undefined = "short") { | ||
const format = monthFormat(locale, month); | ||
return (i: Date | number | null | undefined) => i != null && !isNaN(i = +new Date(Date.UTC(2000, +i))) ? format.format(i) : undefined; | ||
} | ||
|
||
export function formatWeekday(locale = "en-US", weekday: "long" | "short" | "narrow" | undefined = "short") { | ||
const format = weekdayFormat(locale, weekday); | ||
return (i: Date | number | null | undefined) => i != null && !isNaN(i = +new Date(Date.UTC(2001, 0, +i))) ? format.format(i) : undefined; | ||
} | ||
|
||
export function formatIsoDate(date: Date): string { | ||
return isoFormat(date, "Invalid Date"); | ||
} | ||
|
||
export function formatAuto(locale = "en-US"): (value: any) => string | number | undefined { | ||
const number = formatNumber(locale); | ||
return (v: any) => (v instanceof Date ? formatIsoDate : typeof v === "number" ? number : string)(v); | ||
} | ||
|
||
// TODO When Plot supports a top-level locale option, this should be removed | ||
// because it lacks context to know which locale to use; formatAuto should be | ||
// used instead whenever possible. | ||
export const formatDefault = formatAuto(); |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const radians: number = Math.PI / 180; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
export function memoize1<T>(compute: (...rest: any[]) => T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sounds like very arcane knowledge, black belt! I'm still a yellow belt. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's a source that talks a bit about the difference: https://www.typescript-training.com/course/fundamentals-v3/11-top-and-bottom-types/ Some useful quotes:
|
||
let cacheValue: T, cacheKeys: any[] | undefined; | ||
return (...keys: any[]) => { | ||
if (cacheKeys?.length !== keys.length || cacheKeys.some((k, i) => k !== keys[i])) { | ||
cacheKeys = keys; | ||
cacheValue = compute(...keys); | ||
} | ||
return cacheValue; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
declare module 'isoformat' { | ||
export function format(value: any, fallback: string): string; | ||
export function format(value: any, fallback: any): any; | ||
export function parse(value: string): Date; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does
--conditions=mocha
and--files
do? I can’t find any documentation about these arguments.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I was able to answer this myself. It’s a Node flag, not a Mocha flag, document here:
https://nodejs.org/api/packages.html#resolving-user-conditions
And it means that Node will respect the
mocha
export in package.json here:plot/package.json
Line 16 in e1091a2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And as for
--files
it doesn’t seem to have any effect so should probably be removed?