@chartguard/quality-core 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +118 -2
- package/dist/access.d.ts +4 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +58 -0
- package/dist/access.js.map +1 -0
- package/dist/catalog.d.ts +146 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +91 -0
- package/dist/catalog.js.map +1 -0
- package/dist/chart.d.ts +138 -0
- package/dist/chart.d.ts.map +1 -0
- package/dist/chart.js +2 -0
- package/dist/chart.js.map +1 -0
- package/dist/color.d.ts +16 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +64 -0
- package/dist/color.js.map +1 -0
- package/dist/colors.d.ts +4 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +91 -0
- package/dist/colors.js.map +1 -0
- package/dist/context.d.ts +9 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +28 -0
- package/dist/context.js.map +1 -0
- package/dist/facts.d.ts +56 -0
- package/dist/facts.d.ts.map +1 -0
- package/dist/facts.js +15 -0
- package/dist/facts.js.map +1 -0
- package/dist/fit.d.ts +18 -0
- package/dist/fit.d.ts.map +1 -0
- package/dist/fit.js +58 -0
- package/dist/fit.js.map +1 -0
- package/dist/fixes.d.ts +51 -0
- package/dist/fixes.d.ts.map +1 -0
- package/dist/fixes.js +128 -0
- package/dist/fixes.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/labels.d.ts +5 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +123 -0
- package/dist/labels.js.map +1 -0
- package/dist/measure.d.ts +11 -0
- package/dist/measure.d.ts.map +1 -0
- package/dist/measure.js +18 -0
- package/dist/measure.js.map +1 -0
- package/dist/motion.d.ts +7 -0
- package/dist/motion.d.ts.map +1 -0
- package/dist/motion.js +43 -0
- package/dist/motion.js.map +1 -0
- package/dist/read.d.ts +72 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +166 -0
- package/dist/read.js.map +1 -0
- package/dist/review.d.ts +21 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +61 -0
- package/dist/review.js.map +1 -0
- package/dist/rules.d.ts +3 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +212 -0
- package/dist/rules.js.map +1 -0
- package/dist/settings.d.ts +77 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +191 -0
- package/dist/settings.js.map +1 -0
- package/dist/shades.d.ts +5 -0
- package/dist/shades.d.ts.map +1 -0
- package/dist/shades.js +7 -0
- package/dist/shades.js.map +1 -0
- package/dist/units.d.ts +2 -0
- package/dist/units.d.ts.map +1 -0
- package/dist/units.js +36 -0
- package/dist/units.js.map +1 -0
- package/package.json +38 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ChartGuard contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,119 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @chartguard/quality-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Library-neutral chart semantics and the advisory quality rules that read them. The adapters (`@chartguard/quality-chartjs`, `-echarts`, `-highcharts`) turn a config into `ChartSemantics`; `review(chart, options?)` returns a `QualityReport`: findings only, never a verdict, never an error.
|
|
4
|
+
|
|
5
|
+
**Status:** pre-release (0.x). Coverage is partial, and the API and settings may still change between minor versions.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @chartguard/quality-core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Facts
|
|
12
|
+
|
|
13
|
+
Every fact is one of:
|
|
14
|
+
|
|
15
|
+
- **known from the config**, with the path it was read from;
|
|
16
|
+
- **the runtime's default**, with a pointer to the line of the pinned package that applies it (`<package>@<version> <file>:<line> <text>`; a text that is not distinctive in that file names its context, ` [in TitleModel.defaultOption]` or ` [after …]`, and a test checks it names exactly one line);
|
|
17
|
+
- **declared by the caller** (`context`), for a fact the chart leaves to the page;
|
|
18
|
+
- **unknown**, with its reason: `unset`, `accessor`, `dynamic`, `shape`, `unmodelled`, `inapplicable`, `layout` (it depends on the size the chart is drawn at) or `page` (the chart leaves it to the page it is shown in).
|
|
19
|
+
|
|
20
|
+
Rules claim nothing on an unknown fact. Rules about an author's choice fire only on facts from the config.
|
|
21
|
+
|
|
22
|
+
## Rule catalog
|
|
23
|
+
|
|
24
|
+
`RULE_CATALOG` lists every rule with its rationale, its sources and its documented limits.
|
|
25
|
+
|
|
26
|
+
| Rule | Code | Severity | Reports |
|
|
27
|
+
| --- | --- | --- | --- |
|
|
28
|
+
| `bar-baseline` | `VIS_BAR_BASELINE` | warning | bars that do not grow from zero: a configured range that excludes it (a minimum above it, a maximum below it, or the data minimum), a range fitted to the data that leaves it out at every chart size (Chart.js `beginAtZero: false`, ECharts `scale: true`), or a base other than zero (Chart.js `base`, ECharts `startValue`, Highcharts `threshold`) |
|
|
29
|
+
| `bar-log-scale` | `VIS_BAR_LOG_SCALE` | warning | bars on a logarithmic value axis |
|
|
30
|
+
| `reversed-value-axis` | `VIS_REVERSED_VALUE_AXIS` | warning | a value axis the config reverses |
|
|
31
|
+
| `dual-axis` | `VIS_DUAL_AXIS` | info | series of one orientation measured on two value axes |
|
|
32
|
+
| `pie-negative` | `VIS_PIE_NEGATIVE` | warning | a negative value in a pie series (drawn as a positive slice or left out) |
|
|
33
|
+
| `same-color-series` | `VIS_SAME_COLOR_SERIES` | warning | two cartesian series drawn in the same colour (a repeated colour, Chart.js's default grey, a wrapped palette) |
|
|
34
|
+
| `low-contrast-series` | `VIS_LOW_CONTRAST_SERIES` | info | a cartesian series below 3:1 against a known background, in each colour scheme the chart can show |
|
|
35
|
+
| `placeholder-text` | `VIS_PLACEHOLDER_TEXT` | warning | a chart or value-axis title drawn with the library's placeholder text (Highcharts "Chart title", "Values") |
|
|
36
|
+
| `legend-placeholder` | `VIS_LEGEND_PLACEHOLDER` | warning | a series without a name whose legend entry is drawn with the library's placeholder (Highcharts "Series 1", Chart.js "undefined") |
|
|
37
|
+
| `value-axis-untitled` | `VIS_VALUE_AXIS_UNTITLED` | info | a value axis whose title, and the chart's, are known to show nothing |
|
|
38
|
+
| `data-not-described` | `VIS_DATA_NOT_DESCRIBED` | warning | assistive technology gets no description of the data (ECharts without `aria`, Highcharts with accessibility off) |
|
|
39
|
+
| `keyboard-disabled` | `VIS_KEYBOARD_DISABLED` | warning | the config turns keyboard navigation off |
|
|
40
|
+
| `long-motion` | `VIS_LONG_MOTION` | warning | motion that starts by itself and runs forever (a looping animation, a ripple effect) or longer than five seconds |
|
|
41
|
+
| `empty-title` | `VIS_EMPTY_TITLE` | info | a title the config sets to blank text, unless it is known to be hidden |
|
|
42
|
+
| `percent-without-unit` | `VIS_PERCENT_WITHOUT_UNIT` | info | a percent-stacked value axis whose tick labels and title show no `%` |
|
|
43
|
+
|
|
44
|
+
## Fixes
|
|
45
|
+
|
|
46
|
+
The adapters' `analyze` attaches a `set-option` fix to a finding only when the fix is trustworthy:
|
|
47
|
+
|
|
48
|
+
- **The config decides it:** the fix sets the option the finding names, to a value decided from what the option holds.
|
|
49
|
+
- **It is verified:** applied and reviewed again, the finding is gone and no new finding appears.
|
|
50
|
+
|
|
51
|
+
Each catalog entry's `fix` says which edit its rule offers, or why it offers none (the remedy needs the author's words, data or design choices).
|
|
52
|
+
|
|
53
|
+
| Rule | Fix |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| `bar-baseline` | the configured minimum, maximum or base to 0; `beginAtZero: true` (Chart.js), `scale: false` (ECharts) |
|
|
56
|
+
| `bar-log-scale` | the axis type to linear |
|
|
57
|
+
| `reversed-value-axis` | the reversal off |
|
|
58
|
+
| `percent-without-unit` | `labels.format: '{value}%'` where the axis has no format |
|
|
59
|
+
| `data-not-described` | ECharts `aria` on, Highcharts `accessibility.enabled` on (with the accessibility module) |
|
|
60
|
+
| `keyboard-disabled` | Highcharts keyboard navigation on |
|
|
61
|
+
| `long-motion` | a loop off, an ECharts ripple on hover only, a duration over five seconds to one second |
|
|
62
|
+
|
|
63
|
+
Before/after examples for every fixable rule are in `examples/quality-fixes`. Each is checked on the pinned runtimes: both versions render, `after` is the fix applied to `before`, and what the rule is about is drawn before and not after.
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"code": "VIS_BAR_BASELINE",
|
|
68
|
+
"path": "$.options.scales.y.min",
|
|
69
|
+
"fix": {
|
|
70
|
+
"kind": "set-option",
|
|
71
|
+
"path": "$.options.scales.y.min",
|
|
72
|
+
"from": 60,
|
|
73
|
+
"value": 0,
|
|
74
|
+
"effect": "The bars grow from zero again, so their lengths are proportional to their values."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`withFixes(report, config, remedies, analyze)` is the machinery: an adapter's `remedies` propose, its `analyze` verifies.
|
|
80
|
+
|
|
81
|
+
## Settings and context
|
|
82
|
+
|
|
83
|
+
`review(chart, options)` and every adapter's `analyze(config, options)` take the caller's options:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"rules": {
|
|
88
|
+
"value-axis-untitled": "off",
|
|
89
|
+
"dual-axis": "warning",
|
|
90
|
+
"bar-baseline": { "level": "info", "ignore": [{ "path": "$.options.scales.y", "reason": "A narrow band of stock prices." }] }
|
|
91
|
+
},
|
|
92
|
+
"context": { "background": { "light": "#ffffff", "dark": "#121212" }, "describesData": true, "pausesMotion": false }
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Each rule's setting works as follows:
|
|
97
|
+
|
|
98
|
+
- **A level:** `off` (the rule does not run, and is listed in `disabled`), `info` or `warning`. Never `error`: quality never decides validity.
|
|
99
|
+
- **An ignore:** a finding at the path, or inside it, is not reported. Paths are compared segment by segment, and a reason is required.
|
|
100
|
+
- **Suppressed findings are kept** in `suppressed`, with why (`by: 'setting'` or `'context'`), never dropped.
|
|
101
|
+
|
|
102
|
+
The context declares what the config cannot show about the page:
|
|
103
|
+
|
|
104
|
+
- **`background`:** the page behind a chart that draws none (a Chart.js canvas, ECharts without `backgroundColor`, a transparent Highcharts background), so its series can be measured for contrast.
|
|
105
|
+
- **`describesData`:** `true` meets `data-not-described` (the page has a table or a text alternative). `false` lets the rule decide for a canvas.
|
|
106
|
+
- **`pausesMotion`:** `true` meets `long-motion` (WCAG 2.2.2).
|
|
107
|
+
|
|
108
|
+
Each catalog entry lists the context facts that change it (`context`).
|
|
109
|
+
|
|
110
|
+
`ruleset` selects the rules that run, by rule id or impact (`misleads`, `excludes`, `omits`, `risks`): `{ "ruleset": ["misleads", "data-not-described"] }` runs the rules that mislead and `data-not-described`; every other rule is off and listed in `disabled`. `rules` shapes the selected ones (a level `off` still turns one off); a level for a rule outside the set does not make it run. An empty list, a hole or an entry that is neither an id nor an impact is a `QualityOptionsError`.
|
|
111
|
+
|
|
112
|
+
Invalid options throw `QualityOptionsError`, listing every problem with where it is; `assertQualityOptions` checks them alone.
|
|
113
|
+
|
|
114
|
+
A rule's default severity follows its `impact`:
|
|
115
|
+
|
|
116
|
+
- `misleads` (every reader is shown the data wrongly) and `excludes` (some readers cannot get the content) are warnings;
|
|
117
|
+
- `omits` and `risks` are information.
|
|
118
|
+
|
|
119
|
+
Findings are advisory. A chart's purpose is not in its config, so every finding asks the reader to verify; each rule's `limits` say where it can be wrong.
|
package/dist/access.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The accessibility rules (CG-05-04 part 5): what assistive technology gets from the chart. */
|
|
2
|
+
export declare const dataNotDescribed: import("./catalog.js").QualityRule;
|
|
3
|
+
export declare const keyboardDisabled: import("./catalog.js").QualityRule;
|
|
4
|
+
//# sourceMappingURL=access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAEA,gGAAgG;AAEhG,eAAO,MAAM,gBAAgB,oCAwC5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,oCA6B5B,CAAC"}
|
package/dist/access.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { rule, SOURCES } from './catalog.js';
|
|
2
|
+
/** The accessibility rules (CG-05-04 part 5): what assistive technology gets from the chart. */
|
|
3
|
+
export const dataNotDescribed = rule({
|
|
4
|
+
id: 'data-not-described',
|
|
5
|
+
code: 'VIS_DATA_NOT_DESCRIBED',
|
|
6
|
+
severity: 'warning',
|
|
7
|
+
impact: 'excludes',
|
|
8
|
+
context: [
|
|
9
|
+
{
|
|
10
|
+
fact: 'describesData',
|
|
11
|
+
effect: 'supplies',
|
|
12
|
+
note: '`false`: a chart that leaves its description to the page (a Chart.js canvas) gives assistive technology nothing.'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
fact: 'describesData',
|
|
16
|
+
effect: 'satisfies',
|
|
17
|
+
note: '`true`: the page describes the data (a data table, a text alternative next to the chart); the finding is suppressed.'
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
fix: {
|
|
21
|
+
offered: true,
|
|
22
|
+
edit: "Turns the library's description on (ECharts `aria.enabled` or `aria.label.enabled`; Highcharts `accessibility.enabled`, which needs the accessibility module loaded). A canvas is described by the page: no fix."
|
|
23
|
+
},
|
|
24
|
+
title: 'The data is not described to assistive technology',
|
|
25
|
+
rationale: 'A chart drawn as graphics gives a screen reader nothing to read unless the library labels its points or generates a description. ECharts does so only with `aria.enabled`; Highcharts only with its accessibility module enabled.',
|
|
26
|
+
evidence: [SOURCES.wcag22],
|
|
27
|
+
limits: [
|
|
28
|
+
'The page may describe the data outside the chart (a caption, a table, an `aria-label` on the container); the config does not show it. Declaring it (`context.describesData: true`) suppresses the finding.',
|
|
29
|
+
'Chart.js draws on a canvas whose text alternative is set in the page, not in the config: it is checked only when the caller declares what the page gives (`context.describesData`).'
|
|
30
|
+
]
|
|
31
|
+
}, ({ access: { dataDescribed } }, report) => dataDescribed.known && !dataDescribed.value
|
|
32
|
+
? [
|
|
33
|
+
report(dataDescribed.path, "Assistive technology gets no description of this chart's data: enable the library's accessibility support, or describe the data next to the chart.")
|
|
34
|
+
]
|
|
35
|
+
: []);
|
|
36
|
+
export const keyboardDisabled = rule({
|
|
37
|
+
id: 'keyboard-disabled',
|
|
38
|
+
code: 'VIS_KEYBOARD_DISABLED',
|
|
39
|
+
severity: 'warning',
|
|
40
|
+
impact: 'excludes',
|
|
41
|
+
context: [],
|
|
42
|
+
fix: {
|
|
43
|
+
offered: true,
|
|
44
|
+
edit: 'Turns keyboard navigation back on (Highcharts `accessibility.keyboardNavigation.enabled` or `accessibility.enabled`).'
|
|
45
|
+
},
|
|
46
|
+
title: 'Keyboard access turned off',
|
|
47
|
+
rationale: "Keyboard users reach a chart's points, legend and menus only through the library's keyboard navigation. A config that turns it off leaves them with what a mouse user hovers over.",
|
|
48
|
+
evidence: [SOURCES.wcag22Keyboard],
|
|
49
|
+
limits: [
|
|
50
|
+
'Only keyboard access the config turns off is reported; a library without keyboard navigation (ECharts, Chart.js) is not.',
|
|
51
|
+
'A chart that only shows a picture, with nothing to operate, may not need keyboard access.'
|
|
52
|
+
]
|
|
53
|
+
}, ({ access: { keyboard } }, report) => keyboard.known && keyboard.source === 'config' && !keyboard.value
|
|
54
|
+
? [
|
|
55
|
+
report(keyboard.path, "The config turns keyboard navigation off: keyboard users cannot reach the chart's points or legend.")
|
|
56
|
+
]
|
|
57
|
+
: []);
|
|
58
|
+
//# sourceMappingURL=access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7C,gGAAgG;AAEhG,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CACnC;IACC,EAAE,EAAE,oBAAoB;IACxB,IAAI,EAAE,wBAAwB;IAC9B,QAAQ,EAAE,SAAS;IACnB,MAAM,EAAE,UAAU;IAClB,OAAO,EAAE;QACR;YACC,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,UAAU;YAClB,IAAI,EAAE,kHAAkH;SACxH;QACD;YACC,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,WAAW;YACnB,IAAI,EAAE,sHAAsH;SAC5H;KACD;IACD,GAAG,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,kNAAkN;KACxN;IACD,KAAK,EAAE,mDAAmD;IAC1D,SAAS,EACR,mOAAmO;IACpO,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IAC1B,MAAM,EAAE;QACP,4MAA4M;QAC5M,qLAAqL;KACrL;CACD,EACD,CAAC,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CACzC,aAAa,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,KAAK;IAC1C,CAAC,CAAC;QACA,MAAM,CACL,aAAa,CAAC,IAAI,EAClB,oJAAoJ,CACpJ;KACD;IACF,CAAC,CAAC,EAAE,CACN,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CACnC;IACC,EAAE,EAAE,mBAAmB;IACvB,IAAI,EAAE,uBAAuB;IAC7B,QAAQ,EAAE,SAAS;IACnB,MAAM,EAAE,UAAU;IAClB,OAAO,EAAE,EAAE;IACX,GAAG,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,uHAAuH;KAC7H;IACD,KAAK,EAAE,4BAA4B;IACnC,SAAS,EACR,oLAAoL;IACrL,QAAQ,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC;IAClC,MAAM,EAAE;QACP,0HAA0H;QAC1H,2FAA2F;KAC3F;CACD,EACD,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CACpC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK;IAChE,CAAC,CAAC;QACA,MAAM,CACL,QAAQ,CAAC,IAAI,EACb,qGAAqG,CACrG;KACD;IACF,CAAC,CAAC,EAAE,CACN,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { Diagnostic } from '@chartguard/core';
|
|
2
|
+
import type { ChartSemantics } from './chart.js';
|
|
3
|
+
/** A published source a rule rests on. */
|
|
4
|
+
export interface Evidence {
|
|
5
|
+
readonly authors: string;
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly venue: string;
|
|
8
|
+
readonly year: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* What a finding means for readers, which decides its default severity (`SEVERITY_OF_IMPACT`):
|
|
12
|
+
* `misleads`: the chart as drawn shows the data wrongly to every reader; `excludes`: some readers
|
|
13
|
+
* cannot get the content at all; `omits`: something readers may need is missing, and the text around
|
|
14
|
+
* the chart may give it; `risks`: the reading depends on choices readers cannot see, or other cues
|
|
15
|
+
* may carry what is at risk.
|
|
16
|
+
*/
|
|
17
|
+
export type Impact = 'misleads' | 'excludes' | 'omits' | 'risks';
|
|
18
|
+
/** The default severity of each impact: a rule's `severity` is always this (tested). */
|
|
19
|
+
export declare const SEVERITY_OF_IMPACT: Readonly<Record<Impact, 'warning' | 'info'>>;
|
|
20
|
+
/** A fact about where the chart is shown, which the config cannot show and the caller declares (`QualityContext`). */
|
|
21
|
+
export type ContextFact = 'background' | 'describesData' | 'pausesMotion';
|
|
22
|
+
/**
|
|
23
|
+
* How a context fact the caller declares changes a rule (CG-05-05). `supplies`: it fills a fact the
|
|
24
|
+
* chart leaves to the page, so the rule can decide where it could not; `satisfies`: a `true` value meets
|
|
25
|
+
* the rule's concern, and its findings are suppressed (`by: 'context'`), never dropped.
|
|
26
|
+
*/
|
|
27
|
+
export interface ContextCondition {
|
|
28
|
+
readonly fact: ContextFact;
|
|
29
|
+
readonly effect: 'supplies' | 'satisfies';
|
|
30
|
+
readonly note: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A rule's fix (CG-05-06): `offered`, the edit the adapters propose where the config decides it and
|
|
34
|
+
* it is verified to resolve the finding; or why there is none (what a fix would need that only the
|
|
35
|
+
* author knows, or an edit that would silence the finding without removing the harm).
|
|
36
|
+
*/
|
|
37
|
+
export type FixPolicy = {
|
|
38
|
+
readonly offered: true;
|
|
39
|
+
readonly edit: string;
|
|
40
|
+
} | {
|
|
41
|
+
readonly offered: false;
|
|
42
|
+
readonly why: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* What a rule is and why (CG-05-04): its finding code and severity (advisory only: never an error),
|
|
46
|
+
* the reasoning, the sources it rests on, and the cases where it is knowingly wrong or silent.
|
|
47
|
+
*/
|
|
48
|
+
export interface RuleInfo {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly code: string;
|
|
51
|
+
readonly severity: 'warning' | 'info';
|
|
52
|
+
/** What the finding means for readers; it decides `severity`. */
|
|
53
|
+
readonly impact: Impact;
|
|
54
|
+
/** The context facts that change what the rule reports (CG-05-05). */
|
|
55
|
+
readonly context: readonly ContextCondition[];
|
|
56
|
+
/** Whether the adapters offer a fix for the rule's findings, and which edit, or why none (CG-05-06). */
|
|
57
|
+
readonly fix: FixPolicy;
|
|
58
|
+
readonly title: string;
|
|
59
|
+
readonly rationale: string;
|
|
60
|
+
readonly evidence: readonly Evidence[];
|
|
61
|
+
/** Where the rule can be wrong or says nothing: the documented false-positive and false-negative limits. */
|
|
62
|
+
readonly limits: readonly string[];
|
|
63
|
+
}
|
|
64
|
+
export interface QualityRule extends RuleInfo {
|
|
65
|
+
readonly check: (chart: ChartSemantics) => readonly Diagnostic[];
|
|
66
|
+
}
|
|
67
|
+
/** Reports a finding of the rule at `path`. */
|
|
68
|
+
export type Report = (path: string, message: string) => Diagnostic;
|
|
69
|
+
/** A rule from its catalog entry and its check, which reports through `report` (code, severity and id come from `info`). */
|
|
70
|
+
export declare function rule(info: RuleInfo, check: (chart: ChartSemantics, report: Report) => readonly Diagnostic[]): QualityRule;
|
|
71
|
+
/** Sources several rules share. */
|
|
72
|
+
export declare const SOURCES: {
|
|
73
|
+
readonly pandey2015: {
|
|
74
|
+
readonly authors: "Pandey, Rall, Satterthwaite, Nov, Bertini";
|
|
75
|
+
readonly title: "How Deceptive are Deceptive Visualizations? An Empirical Analysis of Common Distortion Techniques";
|
|
76
|
+
readonly venue: "Proceedings of CHI 2015";
|
|
77
|
+
readonly year: 2015;
|
|
78
|
+
};
|
|
79
|
+
readonly correll2020: {
|
|
80
|
+
readonly authors: "Correll, Bertini, Franconeri";
|
|
81
|
+
readonly title: "Truncating the Y-Axis: Threat or Menace?";
|
|
82
|
+
readonly venue: "Proceedings of CHI 2020";
|
|
83
|
+
readonly year: 2020;
|
|
84
|
+
};
|
|
85
|
+
readonly cleveland1984: {
|
|
86
|
+
readonly authors: "Cleveland, McGill";
|
|
87
|
+
readonly title: "Graphical Perception: Theory, Experimentation, and Application to the Development of Graphical Methods";
|
|
88
|
+
readonly venue: "Journal of the American Statistical Association 79(387)";
|
|
89
|
+
readonly year: 1984;
|
|
90
|
+
};
|
|
91
|
+
readonly isenberg2011: {
|
|
92
|
+
readonly authors: "Isenberg, Bezerianos, Dragicevic, Fekete";
|
|
93
|
+
readonly title: "A Study on Dual-Scale Data Charts";
|
|
94
|
+
readonly venue: "IEEE Transactions on Visualization and Computer Graphics 17(12)";
|
|
95
|
+
readonly year: 2011;
|
|
96
|
+
};
|
|
97
|
+
readonly spence1991: {
|
|
98
|
+
readonly authors: "Spence, Lewandowsky";
|
|
99
|
+
readonly title: "Displaying Proportions and Percentages";
|
|
100
|
+
readonly venue: "Applied Cognitive Psychology 5(1)";
|
|
101
|
+
readonly year: 1991;
|
|
102
|
+
};
|
|
103
|
+
readonly few2012: {
|
|
104
|
+
readonly authors: "Few";
|
|
105
|
+
readonly title: "Show Me the Numbers: Designing Tables and Graphs to Enlighten (2nd edition)";
|
|
106
|
+
readonly venue: "Analytics Press";
|
|
107
|
+
readonly year: 2012;
|
|
108
|
+
};
|
|
109
|
+
readonly ware2012: {
|
|
110
|
+
readonly authors: "Ware";
|
|
111
|
+
readonly title: "Information Visualization: Perception for Design (3rd edition)";
|
|
112
|
+
readonly venue: "Morgan Kaufmann";
|
|
113
|
+
readonly year: 2012;
|
|
114
|
+
};
|
|
115
|
+
readonly wcag22Labels: {
|
|
116
|
+
readonly authors: "W3C";
|
|
117
|
+
readonly title: "Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.4.6 Headings and Labels";
|
|
118
|
+
readonly venue: "W3C Recommendation";
|
|
119
|
+
readonly year: 2023;
|
|
120
|
+
};
|
|
121
|
+
readonly wcag22Keyboard: {
|
|
122
|
+
readonly authors: "W3C";
|
|
123
|
+
readonly title: "Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.1.1 Keyboard";
|
|
124
|
+
readonly venue: "W3C Recommendation";
|
|
125
|
+
readonly year: 2023;
|
|
126
|
+
};
|
|
127
|
+
readonly wcag22Contrast: {
|
|
128
|
+
readonly authors: "W3C";
|
|
129
|
+
readonly title: "Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 1.4.11 Non-text Contrast";
|
|
130
|
+
readonly venue: "W3C Recommendation";
|
|
131
|
+
readonly year: 2023;
|
|
132
|
+
};
|
|
133
|
+
readonly wcag22Pause: {
|
|
134
|
+
readonly authors: "W3C";
|
|
135
|
+
readonly title: "Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.2.2 Pause, Stop, Hide";
|
|
136
|
+
readonly venue: "W3C Recommendation";
|
|
137
|
+
readonly year: 2023;
|
|
138
|
+
};
|
|
139
|
+
readonly wcag22: {
|
|
140
|
+
readonly authors: "W3C";
|
|
141
|
+
readonly title: "Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 1.1.1 Non-text Content";
|
|
142
|
+
readonly venue: "W3C Recommendation";
|
|
143
|
+
readonly year: 2023;
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,0CAA0C;AAC1C,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjE,wFAAwF;AACxF,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,CAK3E,CAAC;AAEF,sHAAsH;AACtH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,eAAe,GAAG,cAAc,CAAC;AAE1E;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,MAAM,SAAS,GACpB;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvG;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;IACtC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,wGAAwG;IACxG,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,QAAQ,EAAE,CAAC;IACvC,4GAA4G;IAC5G,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC5C,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,SAAS,UAAU,EAAE,CAAC;CACjE;AAED,+CAA+C;AAC/C,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC;AAEnE,4HAA4H;AAC5H,wBAAgB,IAAI,CACnB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,UAAU,EAAE,GACrE,WAAW,CAEb;AAOD,mCAAmC;AACnC,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyEyB,CAAC"}
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** The default severity of each impact: a rule's `severity` is always this (tested). */
|
|
2
|
+
export const SEVERITY_OF_IMPACT = {
|
|
3
|
+
misleads: 'warning',
|
|
4
|
+
excludes: 'warning',
|
|
5
|
+
omits: 'info',
|
|
6
|
+
risks: 'info'
|
|
7
|
+
};
|
|
8
|
+
/** A rule from its catalog entry and its check, which reports through `report` (code, severity and id come from `info`). */
|
|
9
|
+
export function rule(info, check) {
|
|
10
|
+
return { ...info, check: (chart) => check(chart, (path, message) => finding(info, path, message)) };
|
|
11
|
+
}
|
|
12
|
+
/** A finding of a rule at `path`: inferred, as every quality finding (a chart's intent is not in its config). */
|
|
13
|
+
function finding({ id, code, severity }, path, message) {
|
|
14
|
+
return { code, severity, path, message, confidence: 'inferred', ruleId: id };
|
|
15
|
+
}
|
|
16
|
+
/** Sources several rules share. */
|
|
17
|
+
export const SOURCES = {
|
|
18
|
+
pandey2015: {
|
|
19
|
+
authors: 'Pandey, Rall, Satterthwaite, Nov, Bertini',
|
|
20
|
+
title: 'How Deceptive are Deceptive Visualizations? An Empirical Analysis of Common Distortion Techniques',
|
|
21
|
+
venue: 'Proceedings of CHI 2015',
|
|
22
|
+
year: 2015
|
|
23
|
+
},
|
|
24
|
+
correll2020: {
|
|
25
|
+
authors: 'Correll, Bertini, Franconeri',
|
|
26
|
+
title: 'Truncating the Y-Axis: Threat or Menace?',
|
|
27
|
+
venue: 'Proceedings of CHI 2020',
|
|
28
|
+
year: 2020
|
|
29
|
+
},
|
|
30
|
+
cleveland1984: {
|
|
31
|
+
authors: 'Cleveland, McGill',
|
|
32
|
+
title: 'Graphical Perception: Theory, Experimentation, and Application to the Development of Graphical Methods',
|
|
33
|
+
venue: 'Journal of the American Statistical Association 79(387)',
|
|
34
|
+
year: 1984
|
|
35
|
+
},
|
|
36
|
+
isenberg2011: {
|
|
37
|
+
authors: 'Isenberg, Bezerianos, Dragicevic, Fekete',
|
|
38
|
+
title: 'A Study on Dual-Scale Data Charts',
|
|
39
|
+
venue: 'IEEE Transactions on Visualization and Computer Graphics 17(12)',
|
|
40
|
+
year: 2011
|
|
41
|
+
},
|
|
42
|
+
spence1991: {
|
|
43
|
+
authors: 'Spence, Lewandowsky',
|
|
44
|
+
title: 'Displaying Proportions and Percentages',
|
|
45
|
+
venue: 'Applied Cognitive Psychology 5(1)',
|
|
46
|
+
year: 1991
|
|
47
|
+
},
|
|
48
|
+
few2012: {
|
|
49
|
+
authors: 'Few',
|
|
50
|
+
title: 'Show Me the Numbers: Designing Tables and Graphs to Enlighten (2nd edition)',
|
|
51
|
+
venue: 'Analytics Press',
|
|
52
|
+
year: 2012
|
|
53
|
+
},
|
|
54
|
+
ware2012: {
|
|
55
|
+
authors: 'Ware',
|
|
56
|
+
title: 'Information Visualization: Perception for Design (3rd edition)',
|
|
57
|
+
venue: 'Morgan Kaufmann',
|
|
58
|
+
year: 2012
|
|
59
|
+
},
|
|
60
|
+
wcag22Labels: {
|
|
61
|
+
authors: 'W3C',
|
|
62
|
+
title: 'Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.4.6 Headings and Labels',
|
|
63
|
+
venue: 'W3C Recommendation',
|
|
64
|
+
year: 2023
|
|
65
|
+
},
|
|
66
|
+
wcag22Keyboard: {
|
|
67
|
+
authors: 'W3C',
|
|
68
|
+
title: 'Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.1.1 Keyboard',
|
|
69
|
+
venue: 'W3C Recommendation',
|
|
70
|
+
year: 2023
|
|
71
|
+
},
|
|
72
|
+
wcag22Contrast: {
|
|
73
|
+
authors: 'W3C',
|
|
74
|
+
title: 'Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 1.4.11 Non-text Contrast',
|
|
75
|
+
venue: 'W3C Recommendation',
|
|
76
|
+
year: 2023
|
|
77
|
+
},
|
|
78
|
+
wcag22Pause: {
|
|
79
|
+
authors: 'W3C',
|
|
80
|
+
title: 'Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.2.2 Pause, Stop, Hide',
|
|
81
|
+
venue: 'W3C Recommendation',
|
|
82
|
+
year: 2023
|
|
83
|
+
},
|
|
84
|
+
wcag22: {
|
|
85
|
+
authors: 'W3C',
|
|
86
|
+
title: 'Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 1.1.1 Non-text Content',
|
|
87
|
+
venue: 'W3C Recommendation',
|
|
88
|
+
year: 2023
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAqBA,wFAAwF;AACxF,MAAM,CAAC,MAAM,kBAAkB,GAAiD;IAC/E,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;IACnB,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,MAAM;CACb,CAAC;AAoDF,4HAA4H;AAC5H,MAAM,UAAU,IAAI,CACnB,IAAc,EACd,KAAuE;IAEvE,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;AACrG,CAAC;AAED,iHAAiH;AACjH,SAAS,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAY,EAAE,IAAY,EAAE,OAAe;IAC/E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAC9E,CAAC;AAED,mCAAmC;AACnC,MAAM,CAAC,MAAM,OAAO,GAAG;IACtB,UAAU,EAAE;QACX,OAAO,EAAE,2CAA2C;QACpD,KAAK,EAAE,mGAAmG;QAC1G,KAAK,EAAE,yBAAyB;QAChC,IAAI,EAAE,IAAI;KACV;IACD,WAAW,EAAE;QACZ,OAAO,EAAE,8BAA8B;QACvC,KAAK,EAAE,0CAA0C;QACjD,KAAK,EAAE,yBAAyB;QAChC,IAAI,EAAE,IAAI;KACV;IACD,aAAa,EAAE;QACd,OAAO,EAAE,mBAAmB;QAC5B,KAAK,EAAE,wGAAwG;QAC/G,KAAK,EAAE,yDAAyD;QAChE,IAAI,EAAE,IAAI;KACV;IACD,YAAY,EAAE;QACb,OAAO,EAAE,0CAA0C;QACnD,KAAK,EAAE,mCAAmC;QAC1C,KAAK,EAAE,iEAAiE;QACxE,IAAI,EAAE,IAAI;KACV;IACD,UAAU,EAAE;QACX,OAAO,EAAE,qBAAqB;QAC9B,KAAK,EAAE,wCAAwC;QAC/C,KAAK,EAAE,mCAAmC;QAC1C,IAAI,EAAE,IAAI;KACV;IACD,OAAO,EAAE;QACR,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,6EAA6E;QACpF,KAAK,EAAE,iBAAiB;QACxB,IAAI,EAAE,IAAI;KACV;IACD,QAAQ,EAAE;QACT,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,gEAAgE;QACvE,KAAK,EAAE,iBAAiB;QACxB,IAAI,EAAE,IAAI;KACV;IACD,YAAY,EAAE;QACb,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,8FAA8F;QACrG,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,IAAI;KACV;IACD,cAAc,EAAE;QACf,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,mFAAmF;QAC1F,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,IAAI;KACV;IACD,cAAc,EAAE;QACf,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,6FAA6F;QACpG,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,IAAI;KACV;IACD,WAAW,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,4FAA4F;QACnG,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,IAAI;KACV;IACD,MAAM,EAAE;QACP,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,2FAA2F;QAClG,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,IAAI;KACV;CAC2C,CAAC"}
|
package/dist/chart.d.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { Fact, KnownFact, Listed } from './facts.js';
|
|
2
|
+
/** What a series draws, across libraries; `other` keeps the library type for rules that need it. */
|
|
3
|
+
export type SeriesKind = 'bar' | 'line' | 'area' | 'scatter' | 'pie' | 'other';
|
|
4
|
+
/** The direction a series' values grow in: up (`vertical`, the values on the y axis) or across (`horizontal`). */
|
|
5
|
+
export type Orientation = 'vertical' | 'horizontal';
|
|
6
|
+
/** Whether a series' values are stacked onto the series sharing its stack, as amounts or as shares (`percent`). */
|
|
7
|
+
export type Stacking = 'none' | 'stacked' | 'percent';
|
|
8
|
+
/** The coordinate system a series is drawn in. */
|
|
9
|
+
export type CoordinateSystem = 'cartesian' | 'polar';
|
|
10
|
+
/**
|
|
11
|
+
* A colour as it is shown in each colour scheme the chart can be shown in: `light`, `dark`, or both
|
|
12
|
+
* (the same colour in both when it does not depend on the scheme). The payload of a `Fact`; each shade
|
|
13
|
+
* carries where it was read from, or the runtime default it comes from.
|
|
14
|
+
*/
|
|
15
|
+
export interface Shades {
|
|
16
|
+
readonly light: KnownFact<string> | undefined;
|
|
17
|
+
readonly dark: KnownFact<string> | undefined;
|
|
18
|
+
}
|
|
19
|
+
/** A value of a series and where it is in the config. */
|
|
20
|
+
export interface ValueAt {
|
|
21
|
+
readonly value: number;
|
|
22
|
+
readonly path: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The numeric values a series draws: how many, the smallest and the largest. The payload of a
|
|
26
|
+
* `Fact`: known only when every element of the data could be read (gaps, `null`, are skipped).
|
|
27
|
+
*/
|
|
28
|
+
export interface ValueSummary {
|
|
29
|
+
readonly count: number;
|
|
30
|
+
readonly min: ValueAt | undefined;
|
|
31
|
+
readonly max: ValueAt | undefined;
|
|
32
|
+
}
|
|
33
|
+
/** One series (dataset): its library type, what it draws, its name and the axis its values are measured on. */
|
|
34
|
+
export interface SeriesSemantics {
|
|
35
|
+
/** Where the series is in the config. */
|
|
36
|
+
readonly path: string;
|
|
37
|
+
readonly type: Fact<string>;
|
|
38
|
+
readonly kind: Fact<SeriesKind>;
|
|
39
|
+
readonly name: Fact<string>;
|
|
40
|
+
/** The `key` of the axis in `ChartSemantics.axes` its values are plotted against. */
|
|
41
|
+
readonly valueAxis: Fact<string>;
|
|
42
|
+
readonly coordinateSystem: Fact<CoordinateSystem>;
|
|
43
|
+
/** Cartesian series only; `inapplicable` in polar and axis-less series. */
|
|
44
|
+
readonly orientation: Fact<Orientation>;
|
|
45
|
+
readonly stacking: Fact<Stacking>;
|
|
46
|
+
/**
|
|
47
|
+
* The value a bar grows from (Chart.js `base`, ECharts `startValue` of its value axis, Highcharts
|
|
48
|
+
* `threshold`); zero by default. `inapplicable` for series that are not bars.
|
|
49
|
+
*/
|
|
50
|
+
readonly base: Fact<number>;
|
|
51
|
+
/**
|
|
52
|
+
* The colour the series is drawn in, as the runtime sets it: a CSS colour (Highcharts palette colours
|
|
53
|
+
* are CSS variables). Per-point colours and gradients are `unmodelled`.
|
|
54
|
+
*/
|
|
55
|
+
readonly color: Fact<string>;
|
|
56
|
+
/** Its colour as shown in each colour scheme: CSS variables resolved, for contrast. */
|
|
57
|
+
readonly shades: Fact<Shades>;
|
|
58
|
+
/** Its values as the runtime reads them from `data`; `unmodelled` for shapes not read yet (datasets, parsing keys, ranges). */
|
|
59
|
+
readonly values: Fact<ValueSummary>;
|
|
60
|
+
/**
|
|
61
|
+
* Its entry in the legend (CG-05-04 part 9): the text drawn for it, its name or what the runtime
|
|
62
|
+
* makes up for a series without one (`source: 'default'`); and whether the legend draws an entry for
|
|
63
|
+
* the series itself (`inapplicable` where the legend lists its points instead).
|
|
64
|
+
*/
|
|
65
|
+
readonly legend: TitleSemantics;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Where a range the runtime fits to the data puts zero: `excluded` at every size the chart can be
|
|
69
|
+
* drawn at, or `included` at every size.
|
|
70
|
+
*/
|
|
71
|
+
export type ZeroFit = 'excluded' | 'included';
|
|
72
|
+
/** How an axis maps values to positions. */
|
|
73
|
+
export type ScaleType = 'linear' | 'log' | 'category' | 'time' | 'other';
|
|
74
|
+
/** One axis: the key series refer to it by, its scale, range, direction and title. */
|
|
75
|
+
export interface AxisSemantics {
|
|
76
|
+
/** Library-neutral and unique in the chart: `y`, `y-left` (Chart.js scale ids), `yAxis[0]`. */
|
|
77
|
+
readonly key: string;
|
|
78
|
+
/** Where the axis is configured, or would be. */
|
|
79
|
+
readonly path: string;
|
|
80
|
+
readonly scale: Fact<ScaleType>;
|
|
81
|
+
/** A number, or `data`: the axis starts at the smallest value shown (ECharts `min: 'dataMin'`). */
|
|
82
|
+
readonly min: Fact<number | 'data'>;
|
|
83
|
+
readonly max: Fact<number | 'data'>;
|
|
84
|
+
/**
|
|
85
|
+
* Whether the range the runtime fits to the data leaves zero out, when the config asks for a range
|
|
86
|
+
* fitted to the data (Chart.js `beginAtZero: false`, ECharts `scale: true`) and sets no bound: the
|
|
87
|
+
* path is that switch. `unset` when the config does not ask; `layout` when it depends on the size.
|
|
88
|
+
*/
|
|
89
|
+
readonly fit: Fact<ZeroFit>;
|
|
90
|
+
/**
|
|
91
|
+
* The unit the tick labels show around each value (`%` from a format `{value}%`); empty when they
|
|
92
|
+
* show bare numbers. A function that formats them is `dynamic`.
|
|
93
|
+
*/
|
|
94
|
+
readonly unit: Fact<string>;
|
|
95
|
+
/**
|
|
96
|
+
* The plot region the axis spans: axes whose known panels are equal are drawn over one another,
|
|
97
|
+
* in one plot; different panels are separate (a grid of their own, a stacked band, a pane), or
|
|
98
|
+
* not known to overlap.
|
|
99
|
+
*/
|
|
100
|
+
readonly panel: Fact<string>;
|
|
101
|
+
/** Values grow towards the origin of the screen direction (down, or left). */
|
|
102
|
+
readonly reversed: Fact<boolean>;
|
|
103
|
+
readonly title: TitleSemantics;
|
|
104
|
+
}
|
|
105
|
+
/** A title or label (of the chart, an axis, a series' legend entry): its text and whether it is shown. */
|
|
106
|
+
export interface TitleSemantics {
|
|
107
|
+
readonly text: Fact<string>;
|
|
108
|
+
readonly shown: Fact<boolean>;
|
|
109
|
+
}
|
|
110
|
+
/** What assistive technology gets from the chart (CG-05-04 part 5). */
|
|
111
|
+
export interface AccessSemantics {
|
|
112
|
+
/** Whether the data is described to assistive technology: point labels, or a generated description. */
|
|
113
|
+
readonly dataDescribed: Fact<boolean>;
|
|
114
|
+
/** Whether the chart can be operated with a keyboard. */
|
|
115
|
+
readonly keyboard: Fact<boolean>;
|
|
116
|
+
}
|
|
117
|
+
/** The motion a chart starts by itself when it is drawn (CG-05-04 part 7). */
|
|
118
|
+
export interface MotionSemantics {
|
|
119
|
+
/** Whether something keeps moving without end (a looping animation, a ripple effect). */
|
|
120
|
+
readonly endless: Fact<boolean>;
|
|
121
|
+
/** The longest animation that runs when the chart is drawn, in milliseconds (0 when none). */
|
|
122
|
+
readonly longest: Fact<number>;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Library-neutral chart semantics (CG-05-02). Every fact is known, with the path it was read from
|
|
126
|
+
* (or the runtime default and its pointer), or unknown with why: rules claim nothing on an unknown fact.
|
|
127
|
+
*/
|
|
128
|
+
export interface ChartSemantics {
|
|
129
|
+
readonly library: string;
|
|
130
|
+
readonly title: TitleSemantics;
|
|
131
|
+
readonly series: Listed<SeriesSemantics>;
|
|
132
|
+
readonly axes: readonly AxisSemantics[];
|
|
133
|
+
readonly access: AccessSemantics;
|
|
134
|
+
/** The background the series are drawn on, in each colour scheme; unknown when the page shows through. */
|
|
135
|
+
readonly background: Fact<Shades>;
|
|
136
|
+
readonly motion: MotionSemantics;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=chart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["../src/chart.ts"],"names":[],"mappings":"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"}
|
package/dist/chart.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart.js","sourceRoot":"","sources":["../src/chart.ts"],"names":[],"mappings":""}
|
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A key under which two CSS colours that are the same compare equal: `#f00`, `#ff0000` and
|
|
3
|
+
* `rgb(255, 0, 0)` share one. Other forms (names, `hsl()`, CSS variables) keep their own text, so two
|
|
4
|
+
* identical texts are the same colour; a text and an equivalent other form are not recognised as
|
|
5
|
+
* the same (a rule claims only sameness it can see, never distinctness).
|
|
6
|
+
*/
|
|
7
|
+
export declare function colorKey(color: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* The contrast ratio (WCAG 2.2, 1 to 21) of `foreground` drawn over `background`: a translucent
|
|
10
|
+
* foreground is composited over the background first. Undefined when either colour is not in a hex or
|
|
11
|
+
* `rgb()` form, or the background is not opaque (whatever is behind it shows through).
|
|
12
|
+
*/
|
|
13
|
+
export declare function contrastRatio(foreground: string, background: string): number | undefined;
|
|
14
|
+
/** Whether a colour draws nothing: `transparent`, or a hex or `rgb()` colour with zero alpha. */
|
|
15
|
+
export declare function isTransparent(color: string): boolean;
|
|
16
|
+
//# sourceMappingURL=color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO9C;AAkBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOxF;AAED,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGpD"}
|