@dataimago/css 0.1.0-alpha.16 → 0.1.0-alpha.19
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/README.md +22 -0
- package/dist/bin/dataimago-sync.mjs +342 -0
- package/dist/dataviz/dataimago-dataviz.css +42 -0
- package/dist/dataviz/dataimago-dataviz.json +42 -0
- package/dist/dataviz/dataimago-dataviz.tex +21 -0
- package/dist/dataviz/dataimago_dataviz.R +61 -0
- package/dist/latex/dataimago-tokens.sty +122 -0
- package/dist/latex/dataimago.sty +618 -0
- package/dist/outputs.json +26 -0
- package/dist/quarto/components.scss +230 -0
- package/dist/quarto/dataimago-dark.scss +321 -0
- package/dist/quarto/dataimago-light.scss +321 -0
- package/dist/templates/KNOWLEDGE-explorer.md +236 -0
- package/dist/templates/KNOWLEDGE-framework.md +233 -0
- package/dist/templates/KNOWLEDGE-research.md +201 -0
- package/dist/templates/quarto_website/README.md +48 -0
- package/dist/templates/quarto_website/_quarto.yml.template +141 -0
- package/dist/templates/quarto_website/about.qmd.template +36 -0
- package/dist/templates/quarto_website/assets/js/custom-anchors.js +6 -0
- package/dist/templates/quarto_website/assets/js/logo-switch.js +73 -0
- package/dist/templates/quarto_website/assets/js/scroll.js +67 -0
- package/dist/templates/quarto_website/ethics.qmd.template +49 -0
- package/dist/templates/quarto_website/index.qmd.template +71 -0
- package/dist/tokens.css +29 -0
- package/dist/tokens.scss +29 -0
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -9,6 +9,11 @@ Depends on [`@dataimago/tokens`](../tokens) for the canonical house identity.
|
|
|
9
9
|
- `dist/tokens.css` — CSS custom properties (theme-aware).
|
|
10
10
|
- `dist/dataimago.css` / `dist/dataimago.min.css` — full compiled design system.
|
|
11
11
|
- `dist/tailwind-preset.js` — Tailwind preset generated from token JSON, including `ink`, `stone`, `forest`, `paper`, `presentation-blue`, `accent`, `copper`, functional colors, typography, spacing, radius, shadow, and transition tokens.
|
|
12
|
+
- `dist/quarto/dataimago-{light,dark}.scss` + `components.scss` — the Quarto theme pair (self-contained; dark keyed to `body.quarto-dark`) and the `.di-*` components.
|
|
13
|
+
- `dist/latex/dataimago-tokens.sty` + `dataimago.sty` — the generated `di-*` colour layer and the LaTeX macro layer.
|
|
14
|
+
- `dist/dataviz/` — the Okabe-Ito data-viz palette as CSS, TeX (PSTricks/TikZ), JSON and R.
|
|
15
|
+
- `dist/templates/` — the project templates (`KNOWLEDGE-*.md`, the Quarto website scaffold) as stamped copies, synced into a project with `dataimago-sync` like the other outputs (house only).
|
|
16
|
+
- `dist/outputs.json` and the `dataimago-sync` bin — pinned sync for non-JS consumers (below).
|
|
12
17
|
|
|
13
18
|
Use [`@dataimago/css-neutral`](../css-neutral) instead when an externally-owned Level-3 app or future third-party hub needs the neutral identity.
|
|
14
19
|
|
|
@@ -41,6 +46,23 @@ module.exports = {
|
|
|
41
46
|
|
|
42
47
|
Serve the compiled CSS from `node_modules/@dataimago/css/dist/` through your R package's asset pipeline.
|
|
43
48
|
|
|
49
|
+
### Quarto, LaTeX, figures — `dataimago-sync`
|
|
50
|
+
|
|
51
|
+
A consumer that does not install from npm pins a version and syncs files. Commit
|
|
52
|
+
`.dataimago/design.json`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{ "package": "@dataimago/css", "version": "<exact version>",
|
|
56
|
+
"outputs": { "quarto/dataimago-light.scss": "styles/", "quarto/dataimago-dark.scss": "styles/",
|
|
57
|
+
"latex/dataimago-tokens.sty": "latex/", "dataviz/dataimago_dataviz.R": "R/palette.R" } }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
then run `npx -p @dataimago/css@<version> dataimago-sync` and commit the files (each carries a
|
|
61
|
+
provenance stamp; never edit them). Put `npx -p @dataimago/css@<version> dataimago-sync --check`
|
|
62
|
+
in CI: it fails on any drift. The shipped outputs are listed in `dist/outputs.json`
|
|
63
|
+
(e.g. `https://unpkg.com/@dataimago/css@<version>/dist/outputs.json`). See
|
|
64
|
+
[`wiki/patterns/new-consumer-checklist.md`](../../wiki/patterns/new-consumer-checklist.md).
|
|
65
|
+
|
|
44
66
|
## Building
|
|
45
67
|
|
|
46
68
|
```bash
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* dataimago-sync — pinned design-system sync for non-JS consumers (spec §4).
|
|
4
|
+
*
|
|
5
|
+
* npx -p @dataimago/css@<version> dataimago-sync write the files
|
|
6
|
+
* npx -p @dataimago/css@<version> dataimago-sync --check exit 1 on any drift
|
|
7
|
+
* dataimago-sync --from <dataimago-design checkout> try an unreleased build
|
|
8
|
+
* node tools/formats/dataimago-sync.mjs --self-test (repo only)
|
|
9
|
+
*
|
|
10
|
+
* Reads the consumer's .dataimago/design.json (or --config <path>):
|
|
11
|
+
* { "package": "@dataimago/css", "version": "<exact>",
|
|
12
|
+
* "outputs": { "<dist path>": "<destination dir/ or file>" } }
|
|
13
|
+
*
|
|
14
|
+
* Copies bytes from THIS package's own dist/ — no download, no transformation;
|
|
15
|
+
* every format decision lives in the dataimago-design build. Exit codes:
|
|
16
|
+
* 0 ok, 1 check failed, 2 configuration error (nothing written).
|
|
17
|
+
*
|
|
18
|
+
* Node built-ins only: this file ships in @dataimago/css and
|
|
19
|
+
* @dataimago/css-neutral dist/bin/. The stamp grammar it reads is defined in
|
|
20
|
+
* tools/formats/stamp.mjs — change both together.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { spawnSync } from 'node:child_process';
|
|
24
|
+
import fs from 'node:fs';
|
|
25
|
+
import os from 'node:os';
|
|
26
|
+
import path from 'node:path';
|
|
27
|
+
import { fileURLToPath } from 'node:url';
|
|
28
|
+
|
|
29
|
+
const LOCAL = 'local-unreleased';
|
|
30
|
+
|
|
31
|
+
class ConfigError extends Error {}
|
|
32
|
+
|
|
33
|
+
function readJson(file, what) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
36
|
+
} catch (e) {
|
|
37
|
+
throw new ConfigError(`cannot read ${what} at ${file}: ${e.message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const USAGE = `dataimago-sync — copy a pinned @dataimago release's design files into this repo
|
|
42
|
+
|
|
43
|
+
dataimago-sync write the files listed in .dataimago/design.json
|
|
44
|
+
dataimago-sync --check exit 1 if any listed file differs from the release
|
|
45
|
+
dataimago-sync --from <checkout> write a local, unreleased build (--check then fails)
|
|
46
|
+
dataimago-sync --config <file> read design.json from <file>
|
|
47
|
+
dataimago-sync --help this text
|
|
48
|
+
|
|
49
|
+
Run it from the pinned release: npx -p @dataimago/css@<version> dataimago-sync`;
|
|
50
|
+
|
|
51
|
+
const FLAGS = new Set(['--check', '--help', '--self-test']);
|
|
52
|
+
const VALUE_FLAGS = new Set(['--from', '--config']);
|
|
53
|
+
|
|
54
|
+
/** Refuse unknown flags before anything runs: a typo'd --check must not silently re-sync. */
|
|
55
|
+
function checkArgs(args) {
|
|
56
|
+
for (let i = 0; i < args.length; i++) {
|
|
57
|
+
if (VALUE_FLAGS.has(args[i])) { i += 1; continue; }
|
|
58
|
+
if (!FLAGS.has(args[i])) throw new ConfigError(`unknown argument ${args[i]} (see --help)`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function argValue(args, flag) {
|
|
63
|
+
const i = args.indexOf(flag);
|
|
64
|
+
if (i === -1) return null;
|
|
65
|
+
if (!args[i + 1] || args[i + 1].startsWith('--')) throw new ConfigError(`${flag} needs a path`);
|
|
66
|
+
return path.resolve(args[i + 1]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** The package this bin ships in: dist/bin/dataimago-sync.mjs → ../.. (symlinks resolved). */
|
|
70
|
+
function ownPackageRoot() {
|
|
71
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Rewrite only the stamp's version tokens to mark a copy as local and unreleased. */
|
|
75
|
+
function localize(text, distPath, pkg, version, sha) {
|
|
76
|
+
const marker = `${LOCAL}(${sha})`;
|
|
77
|
+
if (distPath.endsWith('.json')) {
|
|
78
|
+
const parsed = JSON.parse(text);
|
|
79
|
+
parsed._meta.version = marker;
|
|
80
|
+
parsed._meta.restore = String(parsed._meta.restore).replace(`${pkg}@${version}`, `${pkg}@${marker}`);
|
|
81
|
+
return JSON.stringify(parsed, null, 2) + '\n';
|
|
82
|
+
}
|
|
83
|
+
const nl = text.indexOf('\n');
|
|
84
|
+
return text.slice(0, nl).split(`${pkg}@${version}`).join(`${pkg}@${marker}`) + text.slice(nl);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function gitShortSha(dir) {
|
|
88
|
+
const r = spawnSync('git', ['-C', dir, 'rev-parse', '--short', 'HEAD'], { encoding: 'utf8' });
|
|
89
|
+
return r.status === 0 ? r.stdout.trim() : 'unknown';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Validate everything, return the plan of {key, src, dest}; throws ConfigError before any write. */
|
|
93
|
+
function plan(args) {
|
|
94
|
+
const configPath = argValue(args, '--config') ?? path.resolve('.dataimago', 'design.json');
|
|
95
|
+
// The consumer root holds .dataimago/; a --config file elsewhere is its own root.
|
|
96
|
+
const configDir = path.dirname(configPath);
|
|
97
|
+
const consumerRoot = path.basename(configDir) === '.dataimago' ? path.dirname(configDir) : configDir;
|
|
98
|
+
const design = readJson(configPath, 'design.json');
|
|
99
|
+
if (typeof design.package !== 'string' || typeof design.version !== 'string' || !design.outputs || typeof design.outputs !== 'object') {
|
|
100
|
+
throw new ConfigError('design.json needs "package", "version" and an "outputs" object');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const fromCheckout = argValue(args, '--from');
|
|
104
|
+
const own = readJson(path.join(ownPackageRoot(), 'package.json'), 'package.json of this bin');
|
|
105
|
+
if (design.package !== own.name) {
|
|
106
|
+
throw new ConfigError(`design.json asks for ${design.package}, but this is ${own.name}. Run: npx -p ${design.package}@${design.version} dataimago-sync`);
|
|
107
|
+
}
|
|
108
|
+
let pkgRoot = ownPackageRoot();
|
|
109
|
+
let local = null;
|
|
110
|
+
if (fromCheckout) {
|
|
111
|
+
pkgRoot = path.join(fromCheckout, 'packages', design.package.replace(/^@dataimago\//, ''));
|
|
112
|
+
const built = readJson(path.join(pkgRoot, 'package.json'), `${design.package} in the --from checkout`);
|
|
113
|
+
local = { version: built.version, sha: gitShortSha(fromCheckout) };
|
|
114
|
+
} else if (design.version !== own.version) {
|
|
115
|
+
throw new ConfigError(`design.json pins ${design.package}@${design.version}, but this is ${own.version}. Run: npx -p ${design.package}@${design.version} dataimago-sync`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const manifest = readJson(path.join(pkgRoot, 'dist', 'outputs.json'), 'outputs.json (is the package built?)');
|
|
119
|
+
const available = Object.keys(manifest.files ?? {});
|
|
120
|
+
const steps = [];
|
|
121
|
+
const problems = [];
|
|
122
|
+
for (const [key, destSpec] of Object.entries(design.outputs)) {
|
|
123
|
+
if (!available.includes(key)) {
|
|
124
|
+
problems.push(`${design.package} does not ship "${key}". Available outputs:\n ${available.join('\n ')}`);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (typeof destSpec !== 'string' || destSpec === '' || path.isAbsolute(destSpec)) {
|
|
128
|
+
problems.push(`destination for "${key}" must be a relative path inside the consumer, got ${JSON.stringify(destSpec)}`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const dest = path.resolve(consumerRoot, destSpec.endsWith('/') ? path.join(destSpec, path.basename(key)) : destSpec);
|
|
132
|
+
const rel = path.relative(consumerRoot, dest);
|
|
133
|
+
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
134
|
+
problems.push(`destination for "${key}" escapes the consumer root: ${destSpec}`);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (rel === '' || (fs.existsSync(dest) && fs.statSync(dest).isDirectory())) {
|
|
138
|
+
problems.push(`destination for "${key}" is a directory: write "${destSpec.replace(/\/?$/, '/')}" to put the file inside it`);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (steps.some((s) => s.dest === dest)) {
|
|
142
|
+
problems.push(`two outputs are mapped to the same destination: ${rel}`);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
steps.push({ key, src: path.join(pkgRoot, 'dist', key), dest, rel });
|
|
146
|
+
}
|
|
147
|
+
if (problems.length) throw new ConfigError(problems.join('\n '));
|
|
148
|
+
return { steps, design, local };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function sync(args) {
|
|
152
|
+
const { steps, design, local } = plan(args);
|
|
153
|
+
for (const { key, src, dest, rel } of steps) {
|
|
154
|
+
let bytes = fs.readFileSync(src);
|
|
155
|
+
if (local) bytes = Buffer.from(localize(bytes.toString('utf8'), key, design.package, local.version, local.sha));
|
|
156
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
157
|
+
fs.writeFileSync(dest, bytes);
|
|
158
|
+
console.log(` ✓ ${rel} ← ${design.package}@${local ? `${LOCAL}(${local.sha})` : design.version} dist/${key}`);
|
|
159
|
+
}
|
|
160
|
+
if (local) console.log(`\n⚠ local, unreleased design files: \`dataimago-sync --check\` fails until you re-sync from a release.`);
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function check(args) {
|
|
165
|
+
const { steps, design } = plan(args.filter((a) => a !== '--check'));
|
|
166
|
+
const failures = [];
|
|
167
|
+
for (const { src, dest, rel } of steps) {
|
|
168
|
+
if (!fs.existsSync(dest)) { failures.push(`${rel}: missing`); continue; }
|
|
169
|
+
const have = fs.readFileSync(dest);
|
|
170
|
+
// The marker lives in the stamp: line 1, or the leading _meta object of a JSON file.
|
|
171
|
+
if (have.subarray(0, 1024).includes(LOCAL)) { failures.push(`${rel}: written by --from (local, unreleased); re-sync from a release`); continue; }
|
|
172
|
+
if (!have.equals(fs.readFileSync(src))) failures.push(`${rel}: differs from ${design.package}@${design.version}`);
|
|
173
|
+
}
|
|
174
|
+
for (const f of failures) console.error(` ✗ ${f}`);
|
|
175
|
+
if (failures.length) {
|
|
176
|
+
console.error(`\n✗ dataimago-sync --check: ${failures.length} file(s) out of sync. Run: npx -p ${design.package}@${design.version} dataimago-sync`);
|
|
177
|
+
return 1;
|
|
178
|
+
}
|
|
179
|
+
console.log(`✓ dataimago-sync --check: ${steps.length} file(s) match ${design.package}@${design.version}`);
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function main(args) {
|
|
184
|
+
try {
|
|
185
|
+
checkArgs(args);
|
|
186
|
+
if (args.includes('--help')) {
|
|
187
|
+
console.log(USAGE);
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
if (args.includes('--check')) {
|
|
191
|
+
if (args.includes('--from')) throw new ConfigError('--check verifies a release; it cannot be combined with --from');
|
|
192
|
+
return check(args);
|
|
193
|
+
}
|
|
194
|
+
return sync(args);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
if (e instanceof ConfigError) {
|
|
197
|
+
console.error(`✗ dataimago-sync: ${e.message}`);
|
|
198
|
+
return 2;
|
|
199
|
+
}
|
|
200
|
+
throw e;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ─── Self-test ────────────────────────────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
async function selfTest() {
|
|
207
|
+
const stampUrl = new URL('./stamp.mjs', import.meta.url);
|
|
208
|
+
if (!fs.existsSync(fileURLToPath(stampUrl))) {
|
|
209
|
+
console.error('dataimago-sync --self-test runs from the dataimago-design repo (tools/formats/).');
|
|
210
|
+
process.exit(2);
|
|
211
|
+
}
|
|
212
|
+
const { stamp, stampJson } = await import(stampUrl);
|
|
213
|
+
const assert = (await import('node:assert/strict')).default;
|
|
214
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'di-sync-'));
|
|
215
|
+
|
|
216
|
+
// A fake published package: <tmp>/pkg with dist/{quarto/a.scss, dataviz/p.json, outputs.json, bin/}.
|
|
217
|
+
function makePackage(root, name, version) {
|
|
218
|
+
const files = {
|
|
219
|
+
'quarto/a.scss': stamp({ kind: 'scss', pkg: name, version, distPath: 'quarto/a.scss', body: '$x: 1 !default;\n' }),
|
|
220
|
+
'dataviz/p.json': stampJson({ pkg: name, version, distPath: 'dataviz/p.json', data: { a: '#E69F00' } }),
|
|
221
|
+
};
|
|
222
|
+
fs.mkdirSync(path.join(root, 'dist', 'bin'), { recursive: true });
|
|
223
|
+
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify({ name, version }));
|
|
224
|
+
for (const [p, text] of Object.entries(files)) {
|
|
225
|
+
fs.mkdirSync(path.dirname(path.join(root, 'dist', p)), { recursive: true });
|
|
226
|
+
fs.writeFileSync(path.join(root, 'dist', p), text);
|
|
227
|
+
}
|
|
228
|
+
fs.writeFileSync(path.join(root, 'dist', 'outputs.json'), JSON.stringify({ package: name, version, files: Object.fromEntries(Object.keys(files).sort().map((k) => [k, 'x'])) }, null, 2));
|
|
229
|
+
fs.copyFileSync(fileURLToPath(import.meta.url), path.join(root, 'dist', 'bin', 'dataimago-sync.mjs'));
|
|
230
|
+
return { files, bin: path.join(root, 'dist', 'bin', 'dataimago-sync.mjs') };
|
|
231
|
+
}
|
|
232
|
+
const pkg = makePackage(path.join(tmp, 'pkg'), '@dataimago/css', '9.9.9');
|
|
233
|
+
// A fake dataimago-design checkout for --from: packages/css/{package.json,dist/}.
|
|
234
|
+
makePackage(path.join(tmp, 'checkout', 'packages', 'css'), '@dataimago/css', '9.9.10');
|
|
235
|
+
|
|
236
|
+
const consumer = path.join(tmp, 'consumer');
|
|
237
|
+
const writeDesign = (design) => {
|
|
238
|
+
fs.mkdirSync(path.join(consumer, '.dataimago'), { recursive: true });
|
|
239
|
+
fs.writeFileSync(path.join(consumer, '.dataimago', 'design.json'), JSON.stringify(design));
|
|
240
|
+
};
|
|
241
|
+
const base = { package: '@dataimago/css', version: '9.9.9', outputs: { 'quarto/a.scss': 'styles/', 'dataviz/p.json': 'figs/palette.json' } };
|
|
242
|
+
const run = (...args) => spawnSync(process.execPath, [pkg.bin, ...args], { cwd: consumer, encoding: 'utf8' });
|
|
243
|
+
const exists = (rel) => fs.existsSync(path.join(consumer, rel));
|
|
244
|
+
|
|
245
|
+
// (a) sync writes exact bytes; --check passes.
|
|
246
|
+
writeDesign(base);
|
|
247
|
+
let r = run();
|
|
248
|
+
assert.equal(r.status, 0, r.stderr);
|
|
249
|
+
assert.equal(fs.readFileSync(path.join(consumer, 'styles/a.scss'), 'utf8'), pkg.files['quarto/a.scss']);
|
|
250
|
+
assert.equal(fs.readFileSync(path.join(consumer, 'figs/palette.json'), 'utf8'), pkg.files['dataviz/p.json']);
|
|
251
|
+
assert.equal(run('--check').status, 0);
|
|
252
|
+
|
|
253
|
+
// (b) one appended byte fails --check, naming the file.
|
|
254
|
+
fs.appendFileSync(path.join(consumer, 'styles/a.scss'), ' ');
|
|
255
|
+
r = run('--check');
|
|
256
|
+
assert.equal(r.status, 1);
|
|
257
|
+
assert.match(r.stdout + r.stderr, /styles\/a\.scss/);
|
|
258
|
+
run();
|
|
259
|
+
|
|
260
|
+
// (c) version mismatch: config error with the matching command.
|
|
261
|
+
writeDesign({ ...base, version: '9.9.8' });
|
|
262
|
+
r = run();
|
|
263
|
+
assert.equal(r.status, 2);
|
|
264
|
+
assert.match(r.stderr, /npx -p @dataimago\/css@9\.9\.8 dataimago-sync/);
|
|
265
|
+
|
|
266
|
+
// (d) an output the package does not ship: config error, lists outputs, writes nothing.
|
|
267
|
+
fs.rmSync(path.join(consumer, 'styles'), { recursive: true });
|
|
268
|
+
writeDesign({ ...base, outputs: { ...base.outputs, 'quarto/components.scss': 'styles/' } });
|
|
269
|
+
r = run();
|
|
270
|
+
assert.equal(r.status, 2);
|
|
271
|
+
assert.match(r.stderr, /quarto\/components\.scss/);
|
|
272
|
+
assert.match(r.stderr, /dataviz\/p\.json/);
|
|
273
|
+
assert.ok(!exists('styles/a.scss'), 'nothing written on a config error');
|
|
274
|
+
|
|
275
|
+
// (e) destinations escaping the consumer root are refused before writing.
|
|
276
|
+
for (const dest of ['../x/', '/abs/']) {
|
|
277
|
+
writeDesign({ ...base, outputs: { 'quarto/a.scss': 'styles/', 'dataviz/p.json': dest } });
|
|
278
|
+
r = run();
|
|
279
|
+
assert.equal(r.status, 2, `destination ${dest} must be refused`);
|
|
280
|
+
assert.ok(!exists('styles/a.scss'), `nothing written when ${dest} is refused`);
|
|
281
|
+
}
|
|
282
|
+
assert.ok(!fs.existsSync(path.join(tmp, 'x')));
|
|
283
|
+
|
|
284
|
+
// (f) --from writes local-unreleased stamps that --check always rejects.
|
|
285
|
+
writeDesign(base);
|
|
286
|
+
r = run('--from', path.join(tmp, 'checkout'));
|
|
287
|
+
assert.equal(r.status, 0, r.stderr);
|
|
288
|
+
assert.match(fs.readFileSync(path.join(consumer, 'styles/a.scss'), 'utf8').split('\n')[0], new RegExp(LOCAL));
|
|
289
|
+
assert.match(fs.readFileSync(path.join(consumer, 'figs/palette.json'), 'utf8'), new RegExp(LOCAL));
|
|
290
|
+
r = run('--check');
|
|
291
|
+
assert.equal(r.status, 1);
|
|
292
|
+
assert.match(r.stdout + r.stderr, /--from/);
|
|
293
|
+
|
|
294
|
+
// (g) a design.json for another package is a config error.
|
|
295
|
+
writeDesign({ ...base, package: '@dataimago/css-neutral' });
|
|
296
|
+
assert.equal(run().status, 2);
|
|
297
|
+
|
|
298
|
+
// (h) --config outside .dataimago/: the consumer root is the config's own directory.
|
|
299
|
+
fs.rmSync(path.join(consumer, 'styles'), { recursive: true, force: true });
|
|
300
|
+
fs.writeFileSync(path.join(consumer, 'design.json'), JSON.stringify(base));
|
|
301
|
+
r = run('--config', path.join(consumer, 'design.json'));
|
|
302
|
+
assert.equal(r.status, 0, r.stderr);
|
|
303
|
+
assert.ok(exists('styles/a.scss'), '--config ./design.json writes inside the consumer');
|
|
304
|
+
assert.ok(!fs.existsSync(path.join(tmp, 'styles')), 'nothing written above the consumer');
|
|
305
|
+
fs.rmSync(path.join(consumer, 'design.json'));
|
|
306
|
+
|
|
307
|
+
// (i) an unknown flag (a typo'd --check) is a config error and writes nothing; --help writes nothing.
|
|
308
|
+
writeDesign(base);
|
|
309
|
+
const before = fs.readFileSync(path.join(consumer, 'styles/a.scss'));
|
|
310
|
+
fs.appendFileSync(path.join(consumer, 'styles/a.scss'), 'x');
|
|
311
|
+
r = run('--chek');
|
|
312
|
+
assert.equal(r.status, 2);
|
|
313
|
+
assert.match(r.stderr, /--chek/);
|
|
314
|
+
r = run('--help');
|
|
315
|
+
assert.equal(r.status, 0);
|
|
316
|
+
assert.match(r.stdout, /--check/);
|
|
317
|
+
assert.notDeepEqual(fs.readFileSync(path.join(consumer, 'styles/a.scss')), before, 'neither run re-synced');
|
|
318
|
+
run();
|
|
319
|
+
|
|
320
|
+
// (j) a destination that is the root or an existing directory (no trailing /) is refused up front.
|
|
321
|
+
fs.rmSync(path.join(consumer, 'figs'), { recursive: true, force: true });
|
|
322
|
+
fs.mkdirSync(path.join(consumer, 'figs'));
|
|
323
|
+
for (const dest of ['.', 'figs']) {
|
|
324
|
+
fs.rmSync(path.join(consumer, 'styles'), { recursive: true, force: true });
|
|
325
|
+
writeDesign({ ...base, outputs: { 'quarto/a.scss': 'styles/', 'dataviz/p.json': dest } });
|
|
326
|
+
r = run();
|
|
327
|
+
assert.equal(r.status, 2, `destination ${dest} must be refused`);
|
|
328
|
+
assert.ok(!exists('styles/a.scss'), `nothing written when ${dest} is refused`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// (k) two outputs on one destination is a config error.
|
|
332
|
+
writeDesign({ ...base, outputs: { 'quarto/a.scss': 'same.txt', 'dataviz/p.json': 'same.txt' } });
|
|
333
|
+
r = run();
|
|
334
|
+
assert.equal(r.status, 2);
|
|
335
|
+
assert.ok(!exists('same.txt'));
|
|
336
|
+
|
|
337
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
338
|
+
console.log('dataimago-sync self-test: all checks passed');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (process.argv.includes('--self-test')) await selfTest();
|
|
342
|
+
else process.exitCode = main(process.argv.slice(2));
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* @dataimago/css@0.1.0-alpha.19 dist/dataviz/dataimago-dataviz.css · sha256:4fb36e2401c1cd21f57d50c017ac080377c3943362a5b6c5ce2cd658080e4499 · generated from tokens; do not edit · restore: npx -p @dataimago/css@0.1.0-alpha.19 dataimago-sync */
|
|
2
|
+
/* dataimago data-viz palette (Okabe-Ito). Categorical colour is never the only channel. */
|
|
3
|
+
:root, [data-bs-theme="light"], body.quarto-light {
|
|
4
|
+
--color-dataviz-okabe-ito-orange: #E69F00;
|
|
5
|
+
--color-dataviz-okabe-ito-sky-blue: #56B4E9;
|
|
6
|
+
--color-dataviz-okabe-ito-bluish-green: #009E73;
|
|
7
|
+
--color-dataviz-okabe-ito-yellow: #F0E442;
|
|
8
|
+
--color-dataviz-okabe-ito-blue: #0072B2;
|
|
9
|
+
--color-dataviz-okabe-ito-vermillion: #D55E00;
|
|
10
|
+
--color-dataviz-okabe-ito-reddish-purple: #CC79A7;
|
|
11
|
+
--color-dataviz-okabe-ito-black: #000000;
|
|
12
|
+
--color-dataviz-categorical-1: #E69F00;
|
|
13
|
+
--color-dataviz-categorical-2: #56B4E9;
|
|
14
|
+
--color-dataviz-categorical-3: #009E73;
|
|
15
|
+
--color-dataviz-categorical-4: #F0E442;
|
|
16
|
+
--color-dataviz-categorical-5: #0072B2;
|
|
17
|
+
--color-dataviz-categorical-6: #D55E00;
|
|
18
|
+
--color-dataviz-categorical-7: #CC79A7;
|
|
19
|
+
--color-dataviz-categorical-8: #000000;
|
|
20
|
+
--color-dataviz-uncertainty-outer: #D6D6D6;
|
|
21
|
+
--color-dataviz-uncertainty-union: #9E9E9E;
|
|
22
|
+
--color-dataviz-uncertainty-inner: #333333;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
[data-bs-theme="dark"],
|
|
26
|
+
body.quarto-dark {
|
|
27
|
+
--color-dataviz-okabe-ito-black: #FDF9F2;
|
|
28
|
+
--color-dataviz-categorical-8: #FDF9F2;
|
|
29
|
+
--color-dataviz-uncertainty-outer: #333333;
|
|
30
|
+
--color-dataviz-uncertainty-union: #6B6B6B;
|
|
31
|
+
--color-dataviz-uncertainty-inner: #D6D6D6;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@media (prefers-color-scheme: dark) {
|
|
35
|
+
:root:where(:not([data-bs-theme="light"])) {
|
|
36
|
+
--color-dataviz-okabe-ito-black: #FDF9F2;
|
|
37
|
+
--color-dataviz-categorical-8: #FDF9F2;
|
|
38
|
+
--color-dataviz-uncertainty-outer: #333333;
|
|
39
|
+
--color-dataviz-uncertainty-union: #6B6B6B;
|
|
40
|
+
--color-dataviz-uncertainty-inner: #D6D6D6;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta": {
|
|
3
|
+
"package": "@dataimago/css",
|
|
4
|
+
"version": "0.1.0-alpha.19",
|
|
5
|
+
"path": "dist/dataviz/dataimago-dataviz.json",
|
|
6
|
+
"sha256": "28160e151fca196be3e36790d6b67db232d8df060e8d9556b29dfee50f4b278b",
|
|
7
|
+
"note": "generated from tokens; do not edit",
|
|
8
|
+
"restore": "npx -p @dataimago/css@0.1.0-alpha.19 dataimago-sync"
|
|
9
|
+
},
|
|
10
|
+
"okabe-ito": {
|
|
11
|
+
"orange": "#E69F00",
|
|
12
|
+
"sky-blue": "#56B4E9",
|
|
13
|
+
"bluish-green": "#009E73",
|
|
14
|
+
"yellow": "#F0E442",
|
|
15
|
+
"blue": "#0072B2",
|
|
16
|
+
"vermillion": "#D55E00",
|
|
17
|
+
"reddish-purple": "#CC79A7",
|
|
18
|
+
"black": "#000000"
|
|
19
|
+
},
|
|
20
|
+
"categorical": [
|
|
21
|
+
"#E69F00",
|
|
22
|
+
"#56B4E9",
|
|
23
|
+
"#009E73",
|
|
24
|
+
"#F0E442",
|
|
25
|
+
"#0072B2",
|
|
26
|
+
"#D55E00",
|
|
27
|
+
"#CC79A7",
|
|
28
|
+
"#000000"
|
|
29
|
+
],
|
|
30
|
+
"uncertainty": {
|
|
31
|
+
"outer": "#D6D6D6",
|
|
32
|
+
"union": "#9E9E9E",
|
|
33
|
+
"inner": "#333333"
|
|
34
|
+
},
|
|
35
|
+
"dark": {
|
|
36
|
+
"okabe-ito.black": "#FDF9F2",
|
|
37
|
+
"categorical.8": "#FDF9F2",
|
|
38
|
+
"uncertainty.outer": "#333333",
|
|
39
|
+
"uncertainty.union": "#6B6B6B",
|
|
40
|
+
"uncertainty.inner": "#D6D6D6"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
% @dataimago/css@0.1.0-alpha.19 dist/dataviz/dataimago-dataviz.tex · sha256:d7be36cb429ce8a1f19c95a7da8f57a7fcfda85fd2b0113e086913d37e9fa645 · generated from tokens; do not edit · restore: npx -p @dataimago/css@0.1.0-alpha.19 dataimago-sync
|
|
2
|
+
% dataimago data-viz palette (Okabe-Ito), light mode, for PSTricks and TikZ. Requires xcolor.
|
|
3
|
+
\definecolor{di-dataviz-okabe-ito-orange}{HTML}{E69F00}
|
|
4
|
+
\definecolor{di-dataviz-okabe-ito-sky-blue}{HTML}{56B4E9}
|
|
5
|
+
\definecolor{di-dataviz-okabe-ito-bluish-green}{HTML}{009E73}
|
|
6
|
+
\definecolor{di-dataviz-okabe-ito-yellow}{HTML}{F0E442}
|
|
7
|
+
\definecolor{di-dataviz-okabe-ito-blue}{HTML}{0072B2}
|
|
8
|
+
\definecolor{di-dataviz-okabe-ito-vermillion}{HTML}{D55E00}
|
|
9
|
+
\definecolor{di-dataviz-okabe-ito-reddish-purple}{HTML}{CC79A7}
|
|
10
|
+
\definecolor{di-dataviz-okabe-ito-black}{HTML}{000000}
|
|
11
|
+
\colorlet{di-dataviz-categorical-1}{di-dataviz-okabe-ito-orange}
|
|
12
|
+
\colorlet{di-dataviz-categorical-2}{di-dataviz-okabe-ito-sky-blue}
|
|
13
|
+
\colorlet{di-dataviz-categorical-3}{di-dataviz-okabe-ito-bluish-green}
|
|
14
|
+
\colorlet{di-dataviz-categorical-4}{di-dataviz-okabe-ito-yellow}
|
|
15
|
+
\colorlet{di-dataviz-categorical-5}{di-dataviz-okabe-ito-blue}
|
|
16
|
+
\colorlet{di-dataviz-categorical-6}{di-dataviz-okabe-ito-vermillion}
|
|
17
|
+
\colorlet{di-dataviz-categorical-7}{di-dataviz-okabe-ito-reddish-purple}
|
|
18
|
+
\colorlet{di-dataviz-categorical-8}{di-dataviz-okabe-ito-black}
|
|
19
|
+
\definecolor{di-dataviz-uncertainty-outer}{HTML}{D6D6D6}
|
|
20
|
+
\definecolor{di-dataviz-uncertainty-union}{HTML}{9E9E9E}
|
|
21
|
+
\definecolor{di-dataviz-uncertainty-inner}{HTML}{333333}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @dataimago/css@0.1.0-alpha.19 dist/dataviz/dataimago_dataviz.R · sha256:6443982f105b0f5e4a9d90ac2d1f6ce9fce2db4e8e8148b47f71bfc438940055 · generated from tokens; do not edit · restore: npx -p @dataimago/css@0.1.0-alpha.19 dataimago-sync
|
|
2
|
+
# dataimago data-viz palette (Okabe-Ito). Categorical colour is never the only channel:
|
|
3
|
+
# pair it with marker shape, line type or a label.
|
|
4
|
+
|
|
5
|
+
dataimago_okabe_ito <- c(
|
|
6
|
+
orange = "#E69F00",
|
|
7
|
+
sky_blue = "#56B4E9",
|
|
8
|
+
bluish_green = "#009E73",
|
|
9
|
+
yellow = "#F0E442",
|
|
10
|
+
blue = "#0072B2",
|
|
11
|
+
vermillion = "#D55E00",
|
|
12
|
+
reddish_purple = "#CC79A7",
|
|
13
|
+
black = "#000000"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
dataimago_categorical <- c(
|
|
17
|
+
"#E69F00",
|
|
18
|
+
"#56B4E9",
|
|
19
|
+
"#009E73",
|
|
20
|
+
"#F0E442",
|
|
21
|
+
"#0072B2",
|
|
22
|
+
"#D55E00",
|
|
23
|
+
"#CC79A7",
|
|
24
|
+
"#000000"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
dataimago_uncertainty_bands <- c(
|
|
28
|
+
outer = "#D6D6D6",
|
|
29
|
+
union = "#9E9E9E",
|
|
30
|
+
inner = "#333333"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Dark-mode variants (approved overrides; identical elsewhere).
|
|
34
|
+
|
|
35
|
+
dataimago_okabe_ito_dark <- c(
|
|
36
|
+
orange = "#E69F00",
|
|
37
|
+
sky_blue = "#56B4E9",
|
|
38
|
+
bluish_green = "#009E73",
|
|
39
|
+
yellow = "#F0E442",
|
|
40
|
+
blue = "#0072B2",
|
|
41
|
+
vermillion = "#D55E00",
|
|
42
|
+
reddish_purple = "#CC79A7",
|
|
43
|
+
black = "#FDF9F2"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
dataimago_categorical_dark <- c(
|
|
47
|
+
"#E69F00",
|
|
48
|
+
"#56B4E9",
|
|
49
|
+
"#009E73",
|
|
50
|
+
"#F0E442",
|
|
51
|
+
"#0072B2",
|
|
52
|
+
"#D55E00",
|
|
53
|
+
"#CC79A7",
|
|
54
|
+
"#FDF9F2"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
dataimago_uncertainty_bands_dark <- c(
|
|
58
|
+
outer = "#333333",
|
|
59
|
+
union = "#6B6B6B",
|
|
60
|
+
inner = "#D6D6D6"
|
|
61
|
+
)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
% @dataimago/css@0.1.0-alpha.19 dist/latex/dataimago-tokens.sty · sha256:97596b5136434afc7d03b17916219cdccffd6c1cdc748b861f012e06fbbfc5df · generated from tokens; do not edit · restore: npx -p @dataimago/css@0.1.0-alpha.19 dataimago-sync
|
|
2
|
+
\NeedsTeXFormat{LaTeX2e}
|
|
3
|
+
\ProvidesPackage{dataimago-tokens}[dataimago design tokens, light mode]
|
|
4
|
+
\RequirePackage{xcolor}
|
|
5
|
+
|
|
6
|
+
% Colours: every color.* token, light mode, as opaque sRGB.
|
|
7
|
+
\definecolor{di-palette-ink-50}{HTML}{F5F5F4}
|
|
8
|
+
\definecolor{di-palette-ink-100}{HTML}{E7E5E4}
|
|
9
|
+
\definecolor{di-palette-ink-200}{HTML}{D6D3D1}
|
|
10
|
+
\definecolor{di-palette-ink-300}{HTML}{A8A29E}
|
|
11
|
+
\definecolor{di-palette-ink-400}{HTML}{78716C}
|
|
12
|
+
\definecolor{di-palette-ink-500}{HTML}{57534E}
|
|
13
|
+
\definecolor{di-palette-ink-600}{HTML}{44403C}
|
|
14
|
+
\definecolor{di-palette-ink-700}{HTML}{292524}
|
|
15
|
+
\definecolor{di-palette-ink-800}{HTML}{1C1917}
|
|
16
|
+
\definecolor{di-palette-ink-900}{HTML}{0C0A09}
|
|
17
|
+
\definecolor{di-palette-stone-50}{HTML}{F7F7F6}
|
|
18
|
+
\definecolor{di-palette-stone-100}{HTML}{EDEDEB}
|
|
19
|
+
\definecolor{di-palette-stone-200}{HTML}{DCDCDA}
|
|
20
|
+
\definecolor{di-palette-stone-300}{HTML}{C1C1BF}
|
|
21
|
+
\definecolor{di-palette-stone-400}{HTML}{A0A0A0}
|
|
22
|
+
\definecolor{di-palette-stone-500}{HTML}{7C7C7C}
|
|
23
|
+
\definecolor{di-palette-stone-600}{HTML}{5E5E5C}
|
|
24
|
+
\definecolor{di-palette-stone-700}{HTML}{424240}
|
|
25
|
+
\definecolor{di-palette-stone-800}{HTML}{292927}
|
|
26
|
+
\definecolor{di-palette-stone-900}{HTML}{14140F}
|
|
27
|
+
\definecolor{di-palette-forest-50}{HTML}{F0F1ED}
|
|
28
|
+
\definecolor{di-palette-forest-100}{HTML}{DDE0D4}
|
|
29
|
+
\definecolor{di-palette-forest-200}{HTML}{BDC4AD}
|
|
30
|
+
\definecolor{di-palette-forest-300}{HTML}{98A384}
|
|
31
|
+
\definecolor{di-palette-forest-400}{HTML}{7E8A6B}
|
|
32
|
+
\definecolor{di-palette-forest-500}{HTML}{5E6749}
|
|
33
|
+
\definecolor{di-palette-forest-600}{HTML}{4D5640}
|
|
34
|
+
\definecolor{di-palette-forest-700}{HTML}{434739}
|
|
35
|
+
\definecolor{di-palette-forest-800}{HTML}{363A2E}
|
|
36
|
+
\definecolor{di-palette-forest-900}{HTML}{1F2218}
|
|
37
|
+
\definecolor{di-palette-paper-50}{HTML}{FEFDFB}
|
|
38
|
+
\definecolor{di-palette-paper-100}{HTML}{FDF9F2}
|
|
39
|
+
\definecolor{di-palette-paper-200}{HTML}{FAF2E3}
|
|
40
|
+
\definecolor{di-palette-paper-300}{HTML}{F5E8CF}
|
|
41
|
+
\definecolor{di-palette-paper-400}{HTML}{EDD9B3}
|
|
42
|
+
\definecolor{di-palette-paper-500}{HTML}{E0C088}
|
|
43
|
+
\definecolor{di-palette-copper-50}{HTML}{FDF4EE}
|
|
44
|
+
\definecolor{di-palette-copper-100}{HTML}{FBE5D1}
|
|
45
|
+
\definecolor{di-palette-copper-200}{HTML}{F6C79C}
|
|
46
|
+
\definecolor{di-palette-copper-300}{HTML}{F0A467}
|
|
47
|
+
\definecolor{di-palette-copper-400}{HTML}{EA8441}
|
|
48
|
+
\definecolor{di-palette-copper-500}{HTML}{D46820}
|
|
49
|
+
\definecolor{di-palette-copper-600}{HTML}{B55017}
|
|
50
|
+
\definecolor{di-palette-copper-700}{HTML}{913D15}
|
|
51
|
+
\definecolor{di-palette-copper-800}{HTML}{753318}
|
|
52
|
+
\definecolor{di-palette-copper-900}{HTML}{612B16}
|
|
53
|
+
\definecolor{di-palette-accent-50}{HTML}{F0F8FC}
|
|
54
|
+
\definecolor{di-palette-accent-300}{HTML}{3498DB}
|
|
55
|
+
\definecolor{di-palette-accent-400}{HTML}{2980B9}
|
|
56
|
+
\definecolor{di-palette-accent-500}{HTML}{1F618D}
|
|
57
|
+
\definecolor{di-palette-accent-600}{HTML}{154D6F}
|
|
58
|
+
\definecolor{di-palette-accent-700}{HTML}{0F3A52}
|
|
59
|
+
\definecolor{di-palette-presentation-blue-50}{HTML}{F0F8FC}
|
|
60
|
+
\definecolor{di-palette-presentation-blue-500}{HTML}{3498DB}
|
|
61
|
+
\definecolor{di-palette-presentation-blue-600}{HTML}{2980B9}
|
|
62
|
+
\definecolor{di-palette-presentation-blue-700}{HTML}{1F618D}
|
|
63
|
+
\definecolor{di-functional-success}{HTML}{27AE60}
|
|
64
|
+
\definecolor{di-functional-warning}{HTML}{F39C12}
|
|
65
|
+
\definecolor{di-functional-error}{HTML}{E74C3C}
|
|
66
|
+
\definecolor{di-functional-info}{HTML}{3498DB}
|
|
67
|
+
\definecolor{di-surface-page}{HTML}{EDEDEB}
|
|
68
|
+
\definecolor{di-surface-page-scrolled}{HTML}{EDEDEB}
|
|
69
|
+
\definecolor{di-surface-elevated}{HTML}{F7F7F6}
|
|
70
|
+
\definecolor{di-surface-sunken}{HTML}{FAF2E3}
|
|
71
|
+
\definecolor{di-surface-navbar}{HTML}{EDEDEB}
|
|
72
|
+
\definecolor{di-surface-navbar-scrolled}{HTML}{EDEDEB}
|
|
73
|
+
\definecolor{di-surface-code}{HTML}{FAF2E3}
|
|
74
|
+
\definecolor{di-border-subtle}{HTML}{888785}
|
|
75
|
+
\definecolor{di-border-moderate}{HTML}{666563}
|
|
76
|
+
\definecolor{di-border-strong}{HTML}{444342}
|
|
77
|
+
\definecolor{di-border-card}{HTML}{666563}
|
|
78
|
+
\definecolor{di-border-code}{HTML}{D6D3D1}
|
|
79
|
+
\definecolor{di-content-primary}{HTML}{14140F}
|
|
80
|
+
\definecolor{di-content-secondary}{HTML}{6A6A6A}
|
|
81
|
+
\definecolor{di-content-muted}{HTML}{706964}
|
|
82
|
+
\definecolor{di-content-inverse}{HTML}{FDF9F2}
|
|
83
|
+
\definecolor{di-interactive-primary}{HTML}{434739}
|
|
84
|
+
\definecolor{di-interactive-hover}{HTML}{363A2E}
|
|
85
|
+
\definecolor{di-interactive-accent}{HTML}{1F618D}
|
|
86
|
+
\definecolor{di-interactive-focus}{HTML}{434739}
|
|
87
|
+
\definecolor{di-presentation-accent}{HTML}{3498DB}
|
|
88
|
+
\definecolor{di-presentation-accent-hover}{HTML}{2980B9}
|
|
89
|
+
\definecolor{di-vertical-accent-dissertation}{HTML}{B87333}
|
|
90
|
+
\definecolor{di-vertical-accent-rpkg}{HTML}{3B82F6}
|
|
91
|
+
\definecolor{di-vertical-accent-SGPc}{HTML}{5A6310}
|
|
92
|
+
\definecolor{di-brand-mark-red}{HTML}{CC0000}
|
|
93
|
+
\definecolor{di-dataviz-okabe-ito-orange}{HTML}{E69F00}
|
|
94
|
+
\definecolor{di-dataviz-okabe-ito-sky-blue}{HTML}{56B4E9}
|
|
95
|
+
\definecolor{di-dataviz-okabe-ito-bluish-green}{HTML}{009E73}
|
|
96
|
+
\definecolor{di-dataviz-okabe-ito-yellow}{HTML}{F0E442}
|
|
97
|
+
\definecolor{di-dataviz-okabe-ito-blue}{HTML}{0072B2}
|
|
98
|
+
\definecolor{di-dataviz-okabe-ito-vermillion}{HTML}{D55E00}
|
|
99
|
+
\definecolor{di-dataviz-okabe-ito-reddish-purple}{HTML}{CC79A7}
|
|
100
|
+
\definecolor{di-dataviz-okabe-ito-black}{HTML}{000000}
|
|
101
|
+
\definecolor{di-dataviz-categorical-1}{HTML}{E69F00}
|
|
102
|
+
\definecolor{di-dataviz-categorical-2}{HTML}{56B4E9}
|
|
103
|
+
\definecolor{di-dataviz-categorical-3}{HTML}{009E73}
|
|
104
|
+
\definecolor{di-dataviz-categorical-4}{HTML}{F0E442}
|
|
105
|
+
\definecolor{di-dataviz-categorical-5}{HTML}{0072B2}
|
|
106
|
+
\definecolor{di-dataviz-categorical-6}{HTML}{D55E00}
|
|
107
|
+
\definecolor{di-dataviz-categorical-7}{HTML}{CC79A7}
|
|
108
|
+
\definecolor{di-dataviz-categorical-8}{HTML}{000000}
|
|
109
|
+
\definecolor{di-dataviz-uncertainty-outer}{HTML}{D6D6D6}
|
|
110
|
+
\definecolor{di-dataviz-uncertainty-union}{HTML}{9E9E9E}
|
|
111
|
+
\definecolor{di-dataviz-uncertainty-inner}{HTML}{333333}
|
|
112
|
+
|
|
113
|
+
% Font families: the first family of each token stack.
|
|
114
|
+
\newcommand{\diFontFamilySans}{Noto Sans}
|
|
115
|
+
\newcommand{\diFontFamilyMono}{JetBrains Mono}
|
|
116
|
+
\newcommand{\diFontFamilyDisplay}{Josefin Sans}
|
|
117
|
+
\newcommand{\diFontFamilyDisplayEditorial}{Josefin Sans}
|
|
118
|
+
\newcommand{\diFontFamilyDisplayDocumentation}{Noto Sans}
|
|
119
|
+
\newcommand{\diFontFamilyBrand}{Futura}
|
|
120
|
+
\newcommand{\diFontFamilyMath}{Noto Sans Math}
|
|
121
|
+
|
|
122
|
+
\endinput
|