@trishchuk/coolors-mcp 1.0.1 → 1.1.0
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/.github/workflows/ci.yml +23 -20
- package/.github/workflows/deploy-docs.yml +6 -3
- package/.github/workflows/release.yml +11 -9
- package/README.md +123 -14
- package/dist/bin/server.js +997 -256
- package/dist/bin/server.js.map +1 -1
- package/dist/{chunk-P3ARRKLS.js → chunk-HOMDMKUY.js} +3 -1
- package/dist/{chunk-P3ARRKLS.js.map → chunk-HOMDMKUY.js.map} +1 -1
- package/dist/{chunk-IQ7NN26V.js → chunk-LHW2ZTOU.js} +14 -2
- package/dist/chunk-LHW2ZTOU.js.map +1 -0
- package/dist/color/index.js +1 -1
- package/dist/coolors-mcp.d.ts +4 -4
- package/dist/coolors-mcp.js +1 -1
- package/eslint.config.ts +13 -0
- package/jsr.json +1 -1
- package/package.json +16 -12
- package/src/bin/server.ts +13 -1
- package/src/color/__tests__/extract-colors.test.ts +20 -30
- package/src/color/apca.ts +105 -0
- package/src/color/color-blindness.ts +109 -0
- package/src/coolors-mcp.ts +1 -1
- package/src/session.ts +10 -2
- package/src/theme/matcher.ts +1 -1
- package/src/theme/refactor.ts +1 -1
- package/src/theme/types.ts +3 -0
- package/src/tools/__tests__/cohesion.test.ts +97 -0
- package/src/tools/__tests__/color-blindness.test.ts +45 -0
- package/src/tools/__tests__/color-conversion.test.ts +38 -0
- package/src/tools/__tests__/contrast-checker.test.ts +56 -0
- package/src/tools/__tests__/palette-export.test.ts +54 -0
- package/src/tools/adjust-color.tool.ts +80 -0
- package/src/tools/cohesion.tools.ts +380 -0
- package/src/tools/color-blindness.tool.ts +168 -0
- package/src/tools/color-conversion.tool.ts +1 -1
- package/src/tools/contrast-checker.tool.ts +53 -14
- package/src/tools/dislike-analyzer.tool.ts +41 -54
- package/src/tools/image-extraction.tools.ts +62 -115
- package/src/tools/index.ts +15 -2
- package/src/tools/palette-export.tool.ts +174 -0
- package/src/tools/palette-with-locks.tool.ts +8 -6
- package/src/types.ts +2 -3
- package/tsconfig.json +12 -2
- package/vitest.config.js +1 -3
- package/.claude/settings.local.json +0 -35
- package/.env +0 -2
- package/.mcp.json +0 -12
- package/CLAUDE.md +0 -201
- package/DOCUMENTATION.md +0 -274
- package/GEMINI.md +0 -54
- package/TOOLS_UK.md +0 -233
- package/demo/content_based_color.png +0 -0
- package/demo/music-player.html +0 -621
- package/demo/podcast-player.html +0 -903
- package/dist/chunk-IQ7NN26V.js.map +0 -1
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js +0 -111
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js.map +0 -7
- package/docs/.vitepress/cache/deps/_metadata.json +0 -127
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js +0 -12
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +0 -7
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js +0 -13614
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js.map +0 -7
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js +0 -10698
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js.map +0 -7
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js +0 -5609
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +0 -7
- package/docs/.vitepress/cache/deps/cytoscape.js +0 -36234
- package/docs/.vitepress/cache/deps/cytoscape.js.map +0 -7
- package/docs/.vitepress/cache/deps/dayjs.js +0 -507
- package/docs/.vitepress/cache/deps/dayjs.js.map +0 -7
- package/docs/.vitepress/cache/deps/debug.js +0 -512
- package/docs/.vitepress/cache/deps/debug.js.map +0 -7
- package/docs/.vitepress/cache/deps/package.json +0 -3
- package/docs/.vitepress/cache/deps/prismjs.js +0 -1638
- package/docs/.vitepress/cache/deps/prismjs.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js +0 -235
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js +0 -173
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js +0 -27
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js +0 -72
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js +0 -56
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js +0 -107
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -5074
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -584
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +0 -1483
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +0 -1779
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js +0 -2023
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js.map +0 -7
- package/docs/.vitepress/cache/deps/vue.js +0 -344
- package/docs/.vitepress/cache/deps/vue.js.map +0 -7
- package/examples/theme-matching.md +0 -113
- package/mcp-config.json +0 -8
- package/note.md +0 -34
- package/research_results.md +0 -53
- package/src/tools/colors.ts +0 -31
- package/src/tools/registry.ts +0 -142
- package/src/tools/simple-tools.ts +0 -37
package/.github/workflows/ci.yml
CHANGED
|
@@ -14,35 +14,32 @@ jobs:
|
|
|
14
14
|
strategy:
|
|
15
15
|
matrix:
|
|
16
16
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
17
|
-
node-version: [
|
|
18
|
-
exclude:
|
|
19
|
-
# Skip some combinations to save CI time
|
|
20
|
-
- os: windows-latest
|
|
21
|
-
node-version: 18.x
|
|
22
|
-
- os: macos-latest
|
|
23
|
-
node-version: 18.x
|
|
17
|
+
node-version: [20.x, 22.x]
|
|
24
18
|
|
|
25
19
|
steps:
|
|
26
20
|
- name: Checkout code
|
|
27
21
|
uses: actions/checkout@v4
|
|
28
22
|
|
|
23
|
+
- name: Setup pnpm
|
|
24
|
+
uses: pnpm/action-setup@v4
|
|
25
|
+
|
|
29
26
|
- name: Setup Node.js ${{ matrix.node-version }}
|
|
30
27
|
uses: actions/setup-node@v4
|
|
31
28
|
with:
|
|
32
29
|
node-version: ${{ matrix.node-version }}
|
|
33
|
-
cache: "
|
|
30
|
+
cache: "pnpm"
|
|
34
31
|
|
|
35
32
|
- name: Install dependencies
|
|
36
|
-
run:
|
|
33
|
+
run: pnpm install --frozen-lockfile
|
|
37
34
|
|
|
38
35
|
- name: Lint TypeScript
|
|
39
|
-
run:
|
|
36
|
+
run: pnpm run lint
|
|
40
37
|
|
|
41
38
|
- name: Build project
|
|
42
|
-
run:
|
|
39
|
+
run: pnpm run build
|
|
43
40
|
|
|
44
41
|
- name: Run tests
|
|
45
|
-
run:
|
|
42
|
+
run: pnpm test
|
|
46
43
|
continue-on-error: true
|
|
47
44
|
|
|
48
45
|
- name: Verify build output
|
|
@@ -71,21 +68,24 @@ jobs:
|
|
|
71
68
|
- name: Checkout code
|
|
72
69
|
uses: actions/checkout@v4
|
|
73
70
|
|
|
71
|
+
- name: Setup pnpm
|
|
72
|
+
uses: pnpm/action-setup@v4
|
|
73
|
+
|
|
74
74
|
- name: Setup Node.js
|
|
75
75
|
uses: actions/setup-node@v4
|
|
76
76
|
with:
|
|
77
77
|
node-version: "20.x"
|
|
78
|
-
cache: "
|
|
78
|
+
cache: "pnpm"
|
|
79
79
|
|
|
80
80
|
- name: Install dependencies
|
|
81
|
-
run:
|
|
81
|
+
run: pnpm install --frozen-lockfile
|
|
82
82
|
|
|
83
83
|
- name: Build
|
|
84
|
-
run:
|
|
84
|
+
run: pnpm run build
|
|
85
85
|
|
|
86
|
-
- name: Test
|
|
86
|
+
- name: Test pnpm pack
|
|
87
87
|
run: |
|
|
88
|
-
|
|
88
|
+
pnpm pack
|
|
89
89
|
ls -la *.tgz
|
|
90
90
|
|
|
91
91
|
- name: Validate package contents
|
|
@@ -107,17 +107,20 @@ jobs:
|
|
|
107
107
|
- name: Checkout code
|
|
108
108
|
uses: actions/checkout@v4
|
|
109
109
|
|
|
110
|
+
- name: Setup pnpm
|
|
111
|
+
uses: pnpm/action-setup@v4
|
|
112
|
+
|
|
110
113
|
- name: Setup Node.js
|
|
111
114
|
uses: actions/setup-node@v4
|
|
112
115
|
with:
|
|
113
116
|
node-version: "20.x"
|
|
114
|
-
cache: "
|
|
117
|
+
cache: "pnpm"
|
|
115
118
|
|
|
116
119
|
- name: Install dependencies
|
|
117
|
-
run:
|
|
120
|
+
run: pnpm install --frozen-lockfile
|
|
118
121
|
|
|
119
122
|
- name: Build documentation
|
|
120
|
-
run:
|
|
123
|
+
run: pnpm run docs:build
|
|
121
124
|
|
|
122
125
|
- name: Verify docs build
|
|
123
126
|
run: |
|
|
@@ -24,17 +24,20 @@ jobs:
|
|
|
24
24
|
with:
|
|
25
25
|
fetch-depth: 0 # For lastUpdated feature
|
|
26
26
|
|
|
27
|
+
- name: Setup pnpm
|
|
28
|
+
uses: pnpm/action-setup@v4
|
|
29
|
+
|
|
27
30
|
- name: Setup Node.js
|
|
28
31
|
uses: actions/setup-node@v4
|
|
29
32
|
with:
|
|
30
33
|
node-version: "20"
|
|
31
|
-
cache: "
|
|
34
|
+
cache: "pnpm"
|
|
32
35
|
|
|
33
36
|
- name: Install dependencies
|
|
34
|
-
run:
|
|
37
|
+
run: pnpm install --frozen-lockfile
|
|
35
38
|
|
|
36
39
|
- name: Build VitePress site
|
|
37
|
-
run:
|
|
40
|
+
run: pnpm run docs:build
|
|
38
41
|
env:
|
|
39
42
|
NODE_ENV: production
|
|
40
43
|
|
|
@@ -25,12 +25,15 @@ jobs:
|
|
|
25
25
|
with:
|
|
26
26
|
fetch-depth: 0
|
|
27
27
|
|
|
28
|
+
- name: Setup pnpm
|
|
29
|
+
uses: pnpm/action-setup@v4
|
|
30
|
+
|
|
28
31
|
- name: Setup Node.js
|
|
29
32
|
uses: actions/setup-node@v4
|
|
30
33
|
with:
|
|
31
34
|
node-version: "20"
|
|
32
35
|
registry-url: "https://registry.npmjs.org"
|
|
33
|
-
cache: "
|
|
36
|
+
cache: "pnpm"
|
|
34
37
|
|
|
35
38
|
- name: Verify package name
|
|
36
39
|
run: |
|
|
@@ -41,13 +44,13 @@ jobs:
|
|
|
41
44
|
fi
|
|
42
45
|
|
|
43
46
|
- name: Install dependencies
|
|
44
|
-
run:
|
|
47
|
+
run: pnpm install --frozen-lockfile
|
|
45
48
|
|
|
46
49
|
- name: Run tests and build
|
|
47
50
|
run: |
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
pnpm run lint
|
|
52
|
+
pnpm run build
|
|
53
|
+
pnpm test || true
|
|
51
54
|
|
|
52
55
|
- name: Verify build output
|
|
53
56
|
run: |
|
|
@@ -59,16 +62,15 @@ jobs:
|
|
|
59
62
|
|
|
60
63
|
- name: Create tarball and check size
|
|
61
64
|
run: |
|
|
62
|
-
|
|
63
|
-
SIZE=$(
|
|
65
|
+
pnpm pack
|
|
66
|
+
SIZE=$(stat -c%s *.tgz)
|
|
64
67
|
echo "📦 Package size: $SIZE bytes"
|
|
65
68
|
if [ $SIZE -gt 10485760 ]; then
|
|
66
69
|
echo "⚠️ Warning: Package size exceeds 10MB"
|
|
67
70
|
fi
|
|
68
71
|
|
|
69
72
|
- name: Publish to npm
|
|
70
|
-
run:
|
|
71
|
-
npm publish --access public
|
|
73
|
+
run: pnpm publish --access public --no-git-checks
|
|
72
74
|
env:
|
|
73
75
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
74
76
|
|
package/README.md
CHANGED
|
@@ -15,6 +15,12 @@ Advanced color operations MCP server with Material Design 3 support, CSS theme m
|
|
|
15
15
|
- 🌈 **Advanced Palette Generation** - Create palettes with locked colors
|
|
16
16
|
- 🎨 **Gradient Generation** - Smooth gradients with multiple interpolation methods
|
|
17
17
|
- 🚫 **Dislike Analysis** - Detect and fix universally disliked colors
|
|
18
|
+
- 👁️ **Color-Blindness Simulation** - Brettel/Machado matrices for protan/deutan/tritan + accessibility audit
|
|
19
|
+
- 🆎 **APCA Contrast** - WCAG 3 draft contrast (Lc) alongside classic WCAG 2.x ratio
|
|
20
|
+
- 🎚️ **Tonal Scales & State Colors** - Tailwind-style 50–950 scales and hover/active/focus/disabled variants in HCT
|
|
21
|
+
- 🧬 **Palette Cohesion Score** - Quantify visual unity (tone / chroma / hue harmony) with targeted fix suggestions
|
|
22
|
+
- 🪪 **Semantic Palettes** - One brand color → primary/secondary/tertiary + success/warning/error/info in a unified family
|
|
23
|
+
- 📦 **Palette Export** - CSS custom properties, SCSS, Tailwind config, W3C design tokens, JSON
|
|
18
24
|
|
|
19
25
|
## Installation
|
|
20
26
|
|
|
@@ -52,8 +58,8 @@ npm install @trishchuk/coolors-mcp
|
|
|
52
58
|
```bash
|
|
53
59
|
git clone https://github.com/x51xxx/coolors-mcp
|
|
54
60
|
cd coolors-mcp
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
pnpm install
|
|
62
|
+
pnpm run build
|
|
57
63
|
```
|
|
58
64
|
|
|
59
65
|
## Quick Start
|
|
@@ -114,14 +120,28 @@ Calculate perceptual distance between colors.
|
|
|
114
120
|
|
|
115
121
|
#### `check_contrast`
|
|
116
122
|
|
|
117
|
-
Check WCAG
|
|
123
|
+
Check contrast between two colors. Supports the WCAG 2.x luminance ratio (default), APCA Lc (WCAG 3 draft), or both side-by-side.
|
|
118
124
|
|
|
119
125
|
```typescript
|
|
120
126
|
{
|
|
121
127
|
"foreground": "#000000",
|
|
122
|
-
"background": "#ffffff"
|
|
128
|
+
"background": "#ffffff",
|
|
129
|
+
"algorithm": "both" // "wcag" (default) | "apca" | "both"
|
|
130
|
+
}
|
|
131
|
+
// Output: WCAG 21.00:1 + APCA Lc 106.0
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### `adjust_color`
|
|
135
|
+
|
|
136
|
+
Lighten / darken / saturate / desaturate / grayscale / invert / mix a color.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
{
|
|
140
|
+
"color": "#6750a4",
|
|
141
|
+
"operation": "mix",
|
|
142
|
+
"with": "#ff6b6b",
|
|
143
|
+
"amount": 0.5 // weight (0-1) for mix, percent (0-100) for the others
|
|
123
144
|
}
|
|
124
|
-
// Output: Contrast Ratio: 21.00:1 ✓ WCAG AAA
|
|
125
145
|
```
|
|
126
146
|
|
|
127
147
|
### Palette Generation
|
|
@@ -272,6 +292,93 @@ Generate Material Design theme from image colors.
|
|
|
272
292
|
}
|
|
273
293
|
```
|
|
274
294
|
|
|
295
|
+
### Visual Cohesion
|
|
296
|
+
|
|
297
|
+
#### `generate_tonal_scale`
|
|
298
|
+
|
|
299
|
+
Build a Tailwind-style 50/100/.../900/950 scale from one seed color. Uses HCT so steps are perceptually even regardless of hue.
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
{
|
|
303
|
+
"seed": "#6750a4",
|
|
304
|
+
"name": "brand", // CSS variable base name
|
|
305
|
+
"chromaBoost": 1, // multiplier on seed chroma
|
|
306
|
+
"stops": [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### `generate_state_colors`
|
|
311
|
+
|
|
312
|
+
Derive interaction states (hover/active/pressed/focus/disabled/selected) from a base color with consistent tonal deltas.
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
{
|
|
316
|
+
"base": "#6750a4",
|
|
317
|
+
"isDark": false // true to lighten on hover instead of darkening
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### `analyze_palette_consistency`
|
|
322
|
+
|
|
323
|
+
Score visual cohesion of a palette: tonal step uniformity, chroma spread, hue harmony, plus a single 0–100 score and targeted suggestions.
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
{
|
|
327
|
+
"colors": ["#6750a4", "#7f67be", "#a48dc8", "#ff0000"]
|
|
328
|
+
}
|
|
329
|
+
// Output: cohesion 77/100 + outlier #ff0000 (chroma 105 vs avg 60)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### `generate_semantic_palette`
|
|
333
|
+
|
|
334
|
+
From one brand color, generate primary/secondary/tertiary + success/warning/error/info with normalized chroma & tone so every color feels like part of the same family.
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
{
|
|
338
|
+
"brand": "#6750a4",
|
|
339
|
+
"isDark": false
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Accessibility & Color Blindness
|
|
344
|
+
|
|
345
|
+
#### `simulate_color_blindness`
|
|
346
|
+
|
|
347
|
+
Simulate how colors appear to viewers with protanopia / deuteranopia / tritanopia (and the milder anomaly forms, plus achromatopsia). Uses Machado-style linear-sRGB confusion-line matrices.
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
{
|
|
351
|
+
"colors": ["#e63946", "#2a9d8f"],
|
|
352
|
+
"types": ["protanopia", "deuteranopia"] // optional, defaults to all 7
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
#### `check_palette_accessibility`
|
|
357
|
+
|
|
358
|
+
Audit a palette for color-blind friendliness — flags pairs of colors that become indistinguishable under each CVD type.
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
{
|
|
362
|
+
"colors": ["#e63946", "#2a9d8f", "#264653", "#f4a261"],
|
|
363
|
+
"indistinguishableThreshold": 10 // ΔE2000 below which colors collide
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Palette Export
|
|
368
|
+
|
|
369
|
+
#### `export_palette`
|
|
370
|
+
|
|
371
|
+
Export a palette as CSS custom properties, SCSS variables, a Tailwind config snippet, W3C design tokens, or JSON.
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
{
|
|
375
|
+
"colors": ["#fef3c7", "#fde68a", "#fcd34d"],
|
|
376
|
+
"format": "tailwind", // "css" | "scss" | "tailwind" | "tokens" | "json"
|
|
377
|
+
"prefix": "amber",
|
|
378
|
+
"names": ["50", "100", "200"] // optional, default uses 50/100…900 scale
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
275
382
|
### Color Psychology
|
|
276
383
|
|
|
277
384
|
#### `analyze_color_likability`
|
|
@@ -332,21 +439,23 @@ Multi-factor scoring system:
|
|
|
332
439
|
|
|
333
440
|
## Development
|
|
334
441
|
|
|
442
|
+
This project uses [pnpm](https://pnpm.io). Install it once with `npm i -g pnpm` or `corepack enable`.
|
|
443
|
+
|
|
335
444
|
```bash
|
|
336
445
|
# Install dependencies
|
|
337
|
-
|
|
446
|
+
pnpm install
|
|
338
447
|
|
|
339
448
|
# Build the project
|
|
340
|
-
|
|
449
|
+
pnpm run build
|
|
341
450
|
|
|
342
451
|
# Run tests
|
|
343
|
-
|
|
452
|
+
pnpm test
|
|
344
453
|
|
|
345
454
|
# Format code
|
|
346
|
-
|
|
455
|
+
pnpm run format
|
|
347
456
|
|
|
348
457
|
# Lint
|
|
349
|
-
|
|
458
|
+
pnpm run lint
|
|
350
459
|
```
|
|
351
460
|
|
|
352
461
|
## Architecture
|
|
@@ -410,13 +519,13 @@ Create smooth, perceptually uniform gradients for modern UIs.
|
|
|
410
519
|
|
|
411
520
|
Contributions welcome! Please ensure:
|
|
412
521
|
|
|
413
|
-
- Tests pass (`
|
|
414
|
-
- Code is formatted (`
|
|
415
|
-
- Type checking passes (`
|
|
522
|
+
- Tests pass (`pnpm test`)
|
|
523
|
+
- Code is formatted (`pnpm run format`)
|
|
524
|
+
- Type checking passes (`pnpm run lint`)
|
|
416
525
|
|
|
417
526
|
## License
|
|
418
527
|
|
|
419
|
-
MIT
|
|
528
|
+
MIT © [Taras Trishchuk](https://trishchuk.com)
|
|
420
529
|
|
|
421
530
|
## Credits
|
|
422
531
|
|