diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8e7b1fe..3ee0e8d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -29,7 +29,7 @@ jobs: run: jq '.name = "pierre-theme"' package.json > tmp.json && mv tmp.json package.json - name: Swap in VSCE README - run: cp README.package.md README.md + run: cp scripts/README.package.md README.md - name: Publish to VS Marketplace env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 368e2f3..94eac72 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,19 +34,37 @@ jobs: - name: Verify theme files exist run: | - if [ ! -f "themes/pierre-light.json" ]; then - echo "❌ pierre-light.json not generated" - exit 1 - fi - if [ ! -f "themes/pierre-dark.json" ]; then - echo "❌ pierre-dark.json not generated" - exit 1 - fi + for theme in \ + pierre-light \ + pierre-light-protanopia-deuteranopia \ + pierre-light-soft \ + pierre-light-tritanopia \ + pierre-light-vibrant \ + pierre-dark \ + pierre-dark-protanopia-deuteranopia \ + pierre-dark-soft \ + pierre-dark-tritanopia \ + pierre-dark-vibrant; do + if [ ! -f "themes/${theme}.json" ]; then + echo "❌ ${theme}.json not generated" + exit 1 + fi + done echo "✅ All theme files generated successfully" - name: Verify ESM wrapper modules exist run: | - for theme in pierre-dark pierre-light pierre-dark-vibrant pierre-light-vibrant; do + for theme in \ + pierre-light \ + pierre-light-protanopia-deuteranopia \ + pierre-light-soft \ + pierre-light-tritanopia \ + pierre-light-vibrant \ + pierre-dark \ + pierre-dark-protanopia-deuteranopia \ + pierre-dark-soft \ + pierre-dark-tritanopia \ + pierre-dark-vibrant; do if [ ! -f "dist/${theme}.mjs" ]; then echo "❌ dist/${theme}.mjs not generated" exit 1 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d161c23..7fe8652 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,14 +3,14 @@ "tasks": [ { "type": "npm", - "script": "start", + "script": "dev", "group": { "kind": "build", "isDefault": true }, "problemMatcher": [], - "label": "npm: start", - "detail": "nodemon --watch src src/index.js" + "label": "npm: dev", + "detail": "nodemon --watch src --watch scripts --ext ts --exec \"npm run build && npm run preview\"" }, { "type": "npm", @@ -18,7 +18,7 @@ "group": "build", "problemMatcher": [], "label": "npm: build", - "detail": "node src/index.js" + "detail": "ts-node scripts/build.ts" } ] } diff --git a/ACCESSIBILITY.md b/ACCESSIBILITY.md new file mode 100644 index 0000000..1c2b122 --- /dev/null +++ b/ACCESSIBILITY.md @@ -0,0 +1,133 @@ +# Accessibility + +## Color-Vision-Deficiency (CVD) themes + +Pierre ships four themes designed for people with a **color vision deficiency +(CVD)**, the condition commonly called "color blindness." This document explains +what CVD is and how the themes are engineered around it. + +| `name` | label | type | targets | +|---|---|---|---| +| `pierre-light-protanopia-deuteranopia` | Pierre Light Protanopia & Deuteranopia | light | red-green | +| `pierre-light-tritanopia` | Pierre Light Tritanopia | light | blue-yellow | +| `pierre-dark-protanopia-deuteranopia` | Pierre Dark Protanopia & Deuteranopia | dark | red-green | +| `pierre-dark-tritanopia` | Pierre Dark Tritanopia | dark | blue-yellow | + +--- + +### What is CVD? + +The retina senses color with three cone types — **L** (long / "red"), **M** +(medium / "green") and **S** (short / "blue") wavelengths. When one type is +missing or shifted, colors that differ mainly along that cone's axis collapse +into the same perceived color. CVD affects roughly **8% of men and 0.5% of +women**. + +The three dichromacies (the strongest, "complete" forms) we target: + +| Type | Missing cone | Confuses | **Preserved** axis (what can still be told apart) | +|---|---|---|---| +| **Protanopia** | L ("red") | red ↔ green | **blue ↔ orange/yellow** + luminance | +| **Deuteranopia** | M ("green") | red ↔ green | **blue ↔ orange/yellow** + luminance | +| **Tritanopia** | S ("blue") | blue ↔ green (and yellow ↔ violet) | **red ↔ cyan/teal** + luminance | + +> Tritanopia is loosely called "blue-yellow," but blue and yellow differ a lot in +> *luminance* (which is preserved), so they stay apparent. The pair that truly +> collapses is **blue ↔ green**. + +The key consequence for a code editor: a normal theme encodes the most important +signals — **added vs deleted**, **pass vs fail**, **error vs warning** — as +**red vs green**. To a protanope or deuteranope (the most common CVD), red and +green look nearly identical, so those signals become ambiguous. + +--- + +### How the themes are engineered + +Four principles, each enforced or made checkable by the build: + +1. **Identical chrome = family fit.** Each CVD theme reuses the base + `light`/`dark` roles for `bg`, `fg`, and `border` **verbatim**. Windows, text, + and borders are pixel-for-pixel identical to Pierre Light / Pierre Dark — that + is what keeps them recognizably "Pierre." Only the chromatic roles + (`accent`, `states`, `syntax`, `ansi`) change. + +2. **Signals ride the preserved axis.** Every meaningful color is re-mapped onto + the hue axis that the target deficiency keeps: + - **Protan/Deutan:** positive/added → **blue**, negative/deleted → **orange**. + - **Tritan:** positive/added → **teal/cyan**, negative/deleted → **red/vermillion**. + +3. **Luminance is the backup channel.** Under dichromacy there are only ~2 usable + hue poles + luminance, but ~20 chromatic roles. Where two roles must share a + pole (e.g. several "cool" syntax tokens), they are separated by **luminance** + (different palette stops) — the channel CVD users rely on most. + +4. **Reuse the existing palette.** All colors come from scales already in + `src/palettes.ts` (`blue`, `orange`, `teal`, `vermillion`, `magenta`, …). No + off-brand hues were invented. + +#### Role mapping (the actual choices) + +Stops shift lighter on dark backgrounds (mirroring how `dark` shifts vs `light`). + +**Protan/Deutan — axis blue ↔ orange:** + +| Role | Light | Dark | Why | +|---|---|---|---| +| `accent.primary` / `link` | blue 500 | blue 500 | keep Pierre blue (brand) | +| `success` (added) | blue 700 | blue 300 | positive → blue, luminance-split from accent | +| `danger` (deleted/error) | orange 700 | orange 400 | negative → orange | +| `warn` | yellow 500 | yellow 300 | bright caution; big luminance gap from danger | +| `info` | cyan 700 | cyan 400 | cool side; pairs against merge | +| `merge` | violet 700 | violet 400 | blue-violet conflict color | +| `ansi.red` / `ansi.green` | orange / blue | orange / blue | terminal pass/fail separable | +| `syntax.string` (=inserted) | blue 800 | blue 300 | added pole | +| `syntax.tag` (=deleted) | orange 700 | orange 400 | deleted pole | + +**Tritanopia — axis red ↔ cyan/teal:** + +| Role | Light | Dark | Why | +|---|---|---|---| +| `accent.primary` / `link` | blue 500 | blue 500 | reads cyan-blue, clearly ≠ red | +| `success` (added) | teal 700 | teal 300 | positive → teal/cyan | +| `danger` (deleted/error) | vermillion 600 | vermillion 400 | negative → red (preserved) | +| `warn` | amber 600 | amber 400 | caution; ΔE-separated from danger | +| `info` | blue 600 | blue 400 | cyan side | +| `merge` | magenta 700 | magenta 400 | reddish-purple — tritan-safe, far from blue *and* red | +| `ansi.red` / `ansi.green` | vermillion / teal | vermillion / teal | terminal pass/fail separable | +| `syntax.string` (=inserted) | teal 700 | teal 300 | added pole | +| `syntax.tag` (=deleted) | vermillion 600 | vermillion 400 | deleted pole | + +--- + +### The objective test + +A hard gate in `test/` simulates every chromatic role for each deficiency — under +*both* the linear-RGB and gamma-sRGB Machado (2009) conventions — and fails the +build if any must-distinguish pair stops being separable (CIEDE2000 ΔE) or legible +(WCAG contrast). It enforces the tiers and contrast policy below. For how to run and +read the report, see [CONTRIBUTING.md](CONTRIBUTING.md#testing). + +#### Tiers — graded by *what carries the signal when color fails* + +Under dichromacy not every pair can be hue-unique, so we gate hardest where color +is the *only* cue and lean on the editor's built-in non-color cues elsewhere: + +| Tier | Bar | What | Why this bar | +|---|---|---|---| +| **1** | ΔE ≥ 11 | diff add/delete backgrounds, diff inserted/deleted **text**, merge-conflict backgrounds, terminal red/green | color is the **sole** disambiguator — no glyph fallback | +| **2** | ΔE ≥ 8 | diagnostics (error/warn/info), core syntax (keyword/string/variable), comment-vs-code | color **plus** a non-color cue (icon shapes; position) | +| **3** | advisory | git-tree clique, extended syntax | every git entry has an **M/A/D/U/C letter badge**; syntax has bold/italic + position. Reported, not gated. | + +#### Contrast policy + +We hold the themes to WCAG bars, but only the bar that fits how each color renders: + +- **Body text** (editor foreground) → **4.5:1** (SC 1.4.3 normal text). +- **Syntax tokens & meaningful signal colors** → **3:1** (SC 1.4.11 UI / large + text), checked normal **and** after simulation. +- **Report-only** (printed, never fails the build): colors whose canonical/brand + hue is intrinsically high-luminance and that base Pierre itself keeps bright — + `accent.primary`/`link` (brand blue), `warn` (caution yellow/amber), and the + decorative ansi colors. Their *distinguishability* is gated; their raw contrast + is not. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 92153d2..606dda0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,19 +56,30 @@ To override this (or any other) theme in your personal config file, please follo 2. Run `npm install` to install the dependencies. 3. Press `F5` to open a new window with your extension loaded 4. Open `Code > Preferences > Color Theme` [`⌘k ⌘t`] and pick the "Pierre…" theme you want to test. -5. Make changes to the [`/src/theme.ts`](https://github.com/pierrecomputer/theme/blob/main/src/theme.ts) file. -6. Run `npm run build` to update the theme. You can also run `npm run start` instead to automatically rebuild the theme while making changes and no reloading should be necessary. -7. Run `npm test` to validate your changes (this runs automatically on PRs). +5. Make changes under [`/src`](https://github.com/pierrecomputer/theme/blob/main/src). Theme construction lives in `src/createTheme.ts`; role values live in `src/roles`. +6. Run `npm run build` to update the theme. You can also run `npm run dev` instead to automatically rebuild the themes and previews while making changes and no reloading should be necessary. +7. Run `npm test` to validate your changes (this runs automatically on PRs); see + [Testing](#testing) below. 8. Once you're happy, commit your changes and open a PR. +## Testing + +`npm test` builds the themes, runs structural validation, and runs the CVD +accessibility gate (the design it enforces is documented in +[`ACCESSIBILITY.md`](ACCESSIBILITY.md)). The gate, in `test/`:g + +For visual proofing, `npm run preview` writes `preview/*.html`: the palette +scales, the Display-P3 conversions, and a normal-vs-simulated CVD proof sheet. + ## Scripts | Script | Description | | --- | --- | | `npm run build` | Builds the theme `.json` files in `./themes` directory | -| `npm test` | Runs validation tests on the theme (includes build) | -| `npm run package` | Compiles the theme `.vsix` file at the project root | -| `npm start` | Automatically runs build on file change | +| `npm test` | Runs validation tests + the CVD accessibility gate (includes build) | +| `npm run preview` | Writes preview HTML files from `src/previews` into `preview/` | +| `npm run package` | Temporarily applies the VSIX package name/README shim, then writes the `.vsix` file at the project root | +| `npm run dev` | Rebuilds themes and previews on file change | ## Credit diff --git a/DISPLAY-P3.md b/DISPLAY-P3.md index 1983fcf..42fc7ed 100644 --- a/DISPLAY-P3.md +++ b/DISPLAY-P3.md @@ -91,22 +91,9 @@ const html = highlighter.codeToHtml(code, { ## Relevant files -- **`src/color-p3.ts`** - Color conversion and enhancement -- **`src/demo-p3.ts`** - Demo showing conversions (`npx ts-node src/demo-p3.ts`) -- **`color-comparison.html`** - Visual comparison tool (open in Safari on P3 display) - -## Testing - -```bash -# View color conversions -npx ts-node src/demo-p3.ts - -# Rebuild themes -npm run build - -# Run tests -npm test -``` +- **`src/color/p3.ts`** - Display-P3 conversion and gamut enhancement +- **`src/color/`** - Shared color science (sRGB, contrast, CIEDE2000, CVD) +- **`src/previews/p3.ts`** - Preview showing conversions (`npm run preview`) ## Why this matters diff --git a/README b/README index e931dec..a27bec9 100644 --- a/README +++ b/README @@ -29,10 +29,20 @@ Usage: import pierreLight from '@pierre/theme/pierre-light' Available themes: - - @pierre/theme/pierre-dark - @pierre/theme/pierre-light - - @pierre/theme/pierre-dark-vibrant (Display P3) - - @pierre/theme/pierre-light-vibrant (Display P3) + - @pierre/theme/pierre-light-protanopia-deuteranopia (CVD, red-green) + - @pierre/theme/pierre-light-tritanopia (CVD, blue-yellow) + - @pierre/theme/pierre-light-vibrant (Display P3) + - @pierre/theme/pierre-dark + - @pierre/theme/pierre-dark-protanopia-deuteranopia (CVD, red-green) + - @pierre/theme/pierre-dark-tritanopia (CVD, blue-yellow) + - @pierre/theme/pierre-dark-vibrant (Display P3) Zed: Install "Pierre" from the Zed extension registry + +~~~ + +Contributing: + - Development, build, and testing: [CONTRIBUTING.md](CONTRIBUTING.md) + - Accessibility (CVD themes): [ACCESSIBILITY.md](ACCESSIBILITY.md) diff --git a/package-lock.json b/package-lock.json index 3204fc6..076721b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,9 @@ "version": "1.0.3", "license": "MIT", "devDependencies": { + "@types/culori": "^4.0.1", "@vscode/vsce": "^3.2.2", + "culori": "^4.0.2", "nodemon": "^3.1.11", "ts-node": "^10.9.2", "typescript": "^5.9.3" @@ -749,6 +751,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/culori": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/culori/-/culori-4.0.1.tgz", + "integrity": "sha512-43M51r/22CjhbOXyGT361GZ9vncSVQ39u62x5eJdBQFviI8zWp2X5jzqg7k4M6PVgDQAClpy2bUe2dtwEgEDVQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "25.0.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.9.tgz", @@ -1659,6 +1668,16 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/culori": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/culori/-/culori-4.0.2.tgz", + "integrity": "sha512-1+BhOB8ahCn4O0cep0Sh2l9KCOfOdY+BXJnKMHFFzDEouSr/el18QwXEMRlOj9UY5nCeA8UN3a/82rUWRBeyBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", diff --git a/package.json b/package.json index 1acf545..ab25524 100644 --- a/package.json +++ b/package.json @@ -36,33 +36,55 @@ "uiTheme": "vs", "path": "./themes/pierre-light.json" }, + { + "label": "Pierre Light Protanopia & Deuteranopia", + "uiTheme": "vs", + "path": "./themes/pierre-light-protanopia-deuteranopia.json" + }, { "label": "Pierre Light Soft", "uiTheme": "vs", "path": "./themes/pierre-light-soft.json" }, + { + "label": "Pierre Light Tritanopia", + "uiTheme": "vs", + "path": "./themes/pierre-light-tritanopia.json" + }, { "label": "Pierre Dark", "uiTheme": "vs-dark", "path": "./themes/pierre-dark.json" }, + { + "label": "Pierre Dark Protanopia & Deuteranopia", + "uiTheme": "vs-dark", + "path": "./themes/pierre-dark-protanopia-deuteranopia.json" + }, { "label": "Pierre Dark Soft", "uiTheme": "vs-dark", "path": "./themes/pierre-dark-soft.json" + }, + { + "label": "Pierre Dark Tritanopia", + "uiTheme": "vs-dark", + "path": "./themes/pierre-dark-tritanopia.json" } ] }, "scripts": { - "build": "ts-node src/build.ts", - "preview": "ts-node src/palette-preview.ts", - "test": "npm run build && ts-node src/test.ts", - "start": "nodemon --watch src --ext ts --exec npm run build", - "package": "ts-node src/package-vsix.ts", + "build": "ts-node scripts/build.ts", + "preview": "ts-node scripts/createPreviews.ts", + "test": "npm run build && node --require ts-node/register --test --test-reporter spec test/*.test.ts", + "dev": "nodemon --watch src --watch scripts --ext ts --exec \"npm run build && npm run preview\"", + "package": "ts-node scripts/buildVsCodePackage.ts", "prepublishOnly": "npm run build" }, "devDependencies": { + "@types/culori": "^4.0.1", "@vscode/vsce": "^3.2.2", + "culori": "^4.0.2", "nodemon": "^3.1.11", "ts-node": "^10.9.2", "typescript": "^5.9.3" @@ -79,30 +101,46 @@ "types": "./dist/index.d.mts", "default": "./dist/index.mjs" }, - "./pierre-dark": { - "types": "./dist/pierre-dark.d.mts", - "default": "./dist/pierre-dark.mjs" - }, - "./pierre-dark-soft": { - "types": "./dist/pierre-dark-soft.d.mts", - "default": "./dist/pierre-dark-soft.mjs" - }, "./pierre-light": { "types": "./dist/pierre-light.d.mts", "default": "./dist/pierre-light.mjs" }, + "./pierre-light-protanopia-deuteranopia": { + "types": "./dist/pierre-light-protanopia-deuteranopia.d.mts", + "default": "./dist/pierre-light-protanopia-deuteranopia.mjs" + }, "./pierre-light-soft": { "types": "./dist/pierre-light-soft.d.mts", "default": "./dist/pierre-light-soft.mjs" }, - "./pierre-dark-vibrant": { - "types": "./dist/pierre-dark-vibrant.d.mts", - "default": "./dist/pierre-dark-vibrant.mjs" + "./pierre-light-tritanopia": { + "types": "./dist/pierre-light-tritanopia.d.mts", + "default": "./dist/pierre-light-tritanopia.mjs" }, "./pierre-light-vibrant": { "types": "./dist/pierre-light-vibrant.d.mts", "default": "./dist/pierre-light-vibrant.mjs" }, + "./pierre-dark": { + "types": "./dist/pierre-dark.d.mts", + "default": "./dist/pierre-dark.mjs" + }, + "./pierre-dark-protanopia-deuteranopia": { + "types": "./dist/pierre-dark-protanopia-deuteranopia.d.mts", + "default": "./dist/pierre-dark-protanopia-deuteranopia.mjs" + }, + "./pierre-dark-soft": { + "types": "./dist/pierre-dark-soft.d.mts", + "default": "./dist/pierre-dark-soft.mjs" + }, + "./pierre-dark-tritanopia": { + "types": "./dist/pierre-dark-tritanopia.d.mts", + "default": "./dist/pierre-dark-tritanopia.mjs" + }, + "./pierre-dark-vibrant": { + "types": "./dist/pierre-dark-vibrant.d.mts", + "default": "./dist/pierre-dark-vibrant.mjs" + }, "./themes/*": "./themes/*" }, "publishConfig": { diff --git a/README.package.md b/scripts/README.package.md similarity index 100% rename from README.package.md rename to scripts/README.package.md diff --git a/src/build.ts b/scripts/build.ts similarity index 64% rename from src/build.ts rename to scripts/build.ts index c6d312c..1a08c76 100644 --- a/src/build.ts +++ b/scripts/build.ts @@ -1,9 +1,17 @@ -// src/build.ts import { writeFileSync, mkdirSync } from "node:fs"; -import { light as rolesLight, lightSoft as rolesLightSoft, dark as rolesDark, darkSoft as rolesDarkSoft } from "./palette"; -import { makeTheme } from "./theme"; -import { makeZedThemeFamily } from "./zed-theme"; -import { convertRolesToP3 } from "./color-p3"; +import { + light as rolesLight, + lightSoft as rolesLightSoft, + dark as rolesDark, + darkSoft as rolesDarkSoft, + protanDeutanLight as rolesProtanDeutanLight, + protanDeutanDark as rolesProtanDeutanDark, + tritanopiaLight as rolesTritanopiaLight, + tritanopiaDark as rolesTritanopiaDark, +} from "../src/roles"; +import { createTheme } from "../src/createTheme"; +import { createZedTheme } from "../src/createZedTheme"; +import { convertRolesToP3 } from "../src/color"; mkdirSync("themes", { recursive: true }); mkdirSync("zed/themes", { recursive: true }); @@ -18,34 +26,70 @@ const rolesDarkP3 = convertRolesToP3(rolesDark); const vscodeThemes = [ { file: "themes/pierre-light.json", - theme: makeTheme({ + theme: createTheme({ name: "pierre-light", displayName: "Pierre Light", type: "light", roles: rolesLight }) }, + { + file: "themes/pierre-light-protanopia-deuteranopia.json", + theme: createTheme({ + name: "pierre-light-protanopia-deuteranopia", + displayName: "Pierre Light Protanopia & Deuteranopia", + type: "light", + roles: rolesProtanDeutanLight + }) + }, { file: "themes/pierre-light-soft.json", - theme: makeTheme({ + theme: createTheme({ name: "pierre-light-soft", displayName: "Pierre Light Soft", type: "light", roles: rolesLightSoft }) }, + { + file: "themes/pierre-light-tritanopia.json", + theme: createTheme({ + name: "pierre-light-tritanopia", + displayName: "Pierre Light Tritanopia", + type: "light", + roles: rolesTritanopiaLight + }) + }, + { + file: "themes/pierre-light-vibrant.json", + theme: createTheme({ + name: "pierre-light-vibrant", + displayName: "Pierre Light Vibrant", + type: "light", + roles: rolesLightP3 + }) + }, { file: "themes/pierre-dark.json", - theme: makeTheme({ + theme: createTheme({ name: "pierre-dark", displayName: "Pierre Dark", type: "dark", roles: rolesDark }) }, + { + file: "themes/pierre-dark-protanopia-deuteranopia.json", + theme: createTheme({ + name: "pierre-dark-protanopia-deuteranopia", + displayName: "Pierre Dark Protanopia & Deuteranopia", + type: "dark", + roles: rolesProtanDeutanDark + }) + }, { file: "themes/pierre-dark-soft.json", - theme: makeTheme({ + theme: createTheme({ name: "pierre-dark-soft", displayName: "Pierre Dark Soft", type: "dark", @@ -53,17 +97,17 @@ const vscodeThemes = [ }) }, { - file: "themes/pierre-light-vibrant.json", - theme: makeTheme({ - name: "pierre-light-vibrant", - displayName: "Pierre Light Vibrant", - type: "light", - roles: rolesLightP3 + file: "themes/pierre-dark-tritanopia.json", + theme: createTheme({ + name: "pierre-dark-tritanopia", + displayName: "Pierre Dark Tritanopia", + type: "dark", + roles: rolesTritanopiaDark }) }, { file: "themes/pierre-dark-vibrant.json", - theme: makeTheme({ + theme: createTheme({ name: "pierre-dark-vibrant", displayName: "Pierre Dark Vibrant", type: "dark", @@ -80,11 +124,15 @@ for (const {file, theme} of vscodeThemes) { // ============================================ // Zed Theme Family // ============================================ -const zedTheme = makeZedThemeFamily("Pierre", "pierrecomputer", [ +const zedTheme = createZedTheme("Pierre", "pierrecomputer", [ { name: "Pierre Light", appearance: "light", roles: rolesLight }, + { name: "Pierre Light Protanopia & Deuteranopia", appearance: "light", roles: rolesProtanDeutanLight }, { name: "Pierre Light Soft", appearance: "light", roles: rolesLightSoft }, + { name: "Pierre Light Tritanopia", appearance: "light", roles: rolesTritanopiaLight }, { name: "Pierre Dark", appearance: "dark", roles: rolesDark }, + { name: "Pierre Dark Protanopia & Deuteranopia", appearance: "dark", roles: rolesProtanDeutanDark }, { name: "Pierre Dark Soft", appearance: "dark", roles: rolesDarkSoft }, + { name: "Pierre Dark Tritanopia", appearance: "dark", roles: rolesTritanopiaDark }, ]); writeFileSync("zed/themes/pierre.json", JSON.stringify(zedTheme, null, 2), "utf8"); diff --git a/src/package-vsix.ts b/scripts/buildVsCodePackage.ts similarity index 71% rename from src/package-vsix.ts rename to scripts/buildVsCodePackage.ts index 8c25dcc..b5196cb 100644 --- a/src/package-vsix.ts +++ b/scripts/buildVsCodePackage.ts @@ -1,3 +1,10 @@ +// VS Code Marketplace packaging shim. The npm package is scoped as +// @pierre/theme, but VSIX packaging expects the extension name to be unscoped +// and reads README.md as the marketplace description. This script temporarily +// swaps package.json's name to pierre-theme and this directory's +// README.package.md to the repo-root README.md, runs `vsce package`, then +// restores the working tree in a finally block. + import { readFileSync, writeFileSync, existsSync, renameSync } from "fs"; import { execSync } from "child_process"; import { join } from "path"; @@ -5,7 +12,7 @@ import { join } from "path"; const root = join(__dirname, ".."); const pkgPath = join(root, "package.json"); const readmePath = join(root, "README.md"); -const vsceReadmePath = join(root, "README.package.md"); +const vsceReadmePath = join(__dirname, "README.package.md"); const readmeBackupPath = join(root, "README.md.bak"); const original = readFileSync(pkgPath, "utf-8"); diff --git a/scripts/createPreviews.ts b/scripts/createPreviews.ts new file mode 100644 index 0000000..61c1a09 --- /dev/null +++ b/scripts/createPreviews.ts @@ -0,0 +1,34 @@ +// Discovers preview modules in src/previews and writes each rendered HTML file +// to preview/. + +import { mkdirSync, readdirSync, writeFileSync } from "node:fs"; +import { basename, extname, join, relative } from "node:path"; + +type Preview = { + filename: string; + render: () => string; +}; + +const root = join(__dirname, ".."); +const previewSourceDir = join(root, "src", "previews"); +const outputDir = join(root, "preview"); + +mkdirSync(outputDir, { recursive: true }); + +const files = readdirSync(previewSourceDir) + .filter((file) => extname(file) === ".ts") + .sort(); + +for (const file of files) { + const exportName = basename(file, ".ts"); + const mod = require(join(previewSourceDir, file)); + const preview = mod[exportName] as Preview | undefined; + + if (!preview || typeof preview.filename !== "string" || typeof preview.render !== "function") { + throw new Error(`${file} must export ${exportName}: { filename, render }`); + } + + const outputPath = join(outputDir, preview.filename); + writeFileSync(outputPath, preview.render(), "utf8"); + console.log("Wrote", relative(root, outputPath)); +} diff --git a/src/color-p3.ts b/src/color-p3.ts deleted file mode 100644 index 41d48be..0000000 --- a/src/color-p3.ts +++ /dev/null @@ -1,229 +0,0 @@ -// src/color-p3.ts -// Convert sRGB hex colors to CSS Display P3 color space format - -/** - * Convert hex color to RGB values (0-1 range) - */ -function hexToRgb01(hex: string): [number, number, number] { - const cleaned = hex.replace('#', ''); - const expanded = cleaned.length === 3 - ? cleaned.split('').map(x => x + x).join('') - : cleaned; - - const num = parseInt(expanded, 16); - const r = ((num >> 16) & 255) / 255; - const g = ((num >> 8) & 255) / 255; - const b = (num & 255) / 255; - - return [r, g, b]; -} - -/** - * Apply sRGB gamma correction (linearize) - */ -function srgbToLinear(c: number): number { - if (c <= 0.04045) { - return c / 12.92; - } - return Math.pow((c + 0.055) / 1.055, 2.4); -} - -/** - * Remove sRGB gamma correction (to display) - */ -function linearToSrgb(c: number): number { - if (c <= 0.0031308) { - return c * 12.92; - } - return 1.055 * Math.pow(c, 1 / 2.4) - 0.055; -} - -/** - * Apply Display P3 gamma correction (same as sRGB) - */ -const linearToP3 = linearToSrgb; - -/** - * Convert linear sRGB to linear Display P3 - * Using the standard conversion matrix from sRGB to P3 - */ -function linearSrgbToLinearP3(r: number, g: number, b: number): [number, number, number] { - // Conversion matrix from linear sRGB to linear Display P3 - // This matrix converts from sRGB primaries to P3 primaries via XYZ - const rOut = 0.82246197 * r + 0.17753803 * g + 0.00000000 * b; - const gOut = 0.03319420 * r + 0.96680580 * g + 0.00000000 * b; - const bOut = 0.01708263 * r + 0.07239744 * g + 0.91051993 * b; - - return [rOut, gOut, bOut]; -} - -/** - * Format a number for CSS color function (round to reasonable precision) - */ -function formatColorValue(value: number): string { - // Clamp to 0-1 range - const clamped = Math.max(0, Math.min(1, value)); - // Round to 6 decimal places for precision without being excessive - return clamped.toFixed(6); -} - -/** - * Convert RGB to HSL color space - */ -function rgbToHsl(r: number, g: number, b: number): [number, number, number] { - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - const delta = max - min; - - let h = 0; - let s = 0; - const l = (max + min) / 2; - - if (delta !== 0) { - s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min); - - switch (max) { - case r: - h = ((g - b) / delta + (g < b ? 6 : 0)) / 6; - break; - case g: - h = ((b - r) / delta + 2) / 6; - break; - case b: - h = ((r - g) / delta + 4) / 6; - break; - } - } - - return [h, s, l]; -} - -/** - * Convert HSL to RGB color space - */ -function hslToRgb(h: number, s: number, l: number): [number, number, number] { - let r, g, b; - - if (s === 0) { - r = g = b = l; - } else { - const hue2rgb = (p: number, q: number, t: number) => { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1/6) return p + (q - p) * 6 * t; - if (t < 1/2) return q; - if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; - return p; - }; - - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; - - r = hue2rgb(p, q, h + 1/3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3); - } - - return [r, g, b]; -} - -/** - * Enhance colors to take advantage of P3's wider gamut - * Increases saturation and vibrancy for colors that can benefit from P3 - */ -function enhanceForP3Gamut(r: number, g: number, b: number): [number, number, number] { - // Convert to HSL for easier saturation manipulation - const [h, s, l] = rgbToHsl(r, g, b); - - // Only enhance colors that have some saturation and aren't too light or dark - // (grays and near-blacks/whites don't benefit from P3 enhancement) - if (s < 0.1 || l < 0.1 || l > 0.9) { - return [r, g, b]; - } - - // Calculate enhancement factor based on original saturation - // More saturated colors get more enhancement (they can handle it) - const saturationBoost = 0.15 + (s * 0.15); // 15-30% boost depending on saturation - - // Boost saturation, but not beyond 1.0 - let newS = s + (s * saturationBoost); - newS = Math.min(1.0, newS); - - // For highly saturated colors, also slightly increase luminance to make them "pop" - // but only if they're not already too light - let newL = l; - if (s > 0.5 && l < 0.7) { - newL = l + (l * 0.05); // Slight 5% luminance boost for vibrant colors - newL = Math.min(0.9, newL); - } - - // Convert back to RGB - return hslToRgb(h, newS, newL); -} - -/** - * Convert sRGB hex color to CSS Display P3 color format with enhancement - * Returns: "color(display-p3 r g b)" or "color(display-p3 r g b / alpha)" - */ -export function srgbHexToP3Color(srgbHex: string, enhance: boolean = true): string { - // Handle alpha channel if present - const hasAlpha = srgbHex.length === 9 || (srgbHex.startsWith('#') && srgbHex.length === 9); - let alpha = ''; - let colorHex = srgbHex; - - if (hasAlpha) { - const alphaHex = srgbHex.slice(-2); - const alphaValue = parseInt(alphaHex, 16) / 255; - alpha = ` / ${formatColorValue(alphaValue)}`; - colorHex = srgbHex.slice(0, -2); - } - - // Convert to linear sRGB - const [sR, sG, sB] = hexToRgb01(colorHex); - const linearSR = srgbToLinear(sR); - const linearSG = srgbToLinear(sG); - const linearSB = srgbToLinear(sB); - - // Convert to linear P3 - const [linearPR, linearPG, linearPB] = linearSrgbToLinearP3(linearSR, linearSG, linearSB); - - // Apply P3 gamma to get display values - let pR = linearToP3(linearPR); - let pG = linearToP3(linearPG); - let pB = linearToP3(linearPB); - - // Enhance colors to take advantage of P3's wider gamut - if (enhance) { - [pR, pG, pB] = enhanceForP3Gamut(pR, pG, pB); - } - - // Format as CSS color(display-p3 ...) function - return `color(display-p3 ${formatColorValue(pR)} ${formatColorValue(pG)} ${formatColorValue(pB)}${alpha})`; -} - -/** - * Convert all colors in a Roles object to Display P3 - */ -export function convertRolesToP3(obj: T): T { - if (typeof obj === 'string') { - // If it's a hex color string, convert it - if ((obj as string).match(/^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$/)) { - return srgbHexToP3Color(obj as string) as any; - } - return obj; - } - - if (Array.isArray(obj)) { - return obj.map(item => convertRolesToP3(item)) as any; - } - - if (obj !== null && typeof obj === 'object') { - const result: any = {}; - for (const [key, value] of Object.entries(obj as any)) { - result[key] = convertRolesToP3(value); - } - return result; - } - - return obj; -} diff --git a/src/color/contrast.ts b/src/color/contrast.ts new file mode 100644 index 0000000..f58c98e --- /dev/null +++ b/src/color/contrast.ts @@ -0,0 +1,20 @@ +// WCAG 2.1 contrast ratio — a legibility check, independent of hue. Relative +// luminance uses the linear-RGB luma coefficients; contrast is +// (lighter + 0.05) / (darker + 0.05), from 1:1 (identical) to 21:1 (black on +// white). WCAG AA wants ≥ 4.5:1 for normal text and ≥ 3:1 for large text / UI +// glyphs. The CVD gate re-checks contrast *after* simulation, since simulation +// shifts luminance. + +import { hexToRgb01, srgbToLinear } from "./srgb"; + +function relativeLuminance(hex: string): number { + const [r, g, b] = hexToRgb01(hex).map(srgbToLinear) as [number, number, number]; + return 0.2126 * r + 0.7152 * g + 0.0722 * b; +} + +/** WCAG 2.1 contrast ratio between two sRGB hex colors (order-independent). */ +export function contrastRatio(a: string, b: string): number { + const la = relativeLuminance(a); + const lb = relativeLuminance(b); + return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05); +} diff --git a/src/color/cvd.ts b/src/color/cvd.ts new file mode 100644 index 0000000..8f25f48 --- /dev/null +++ b/src/color/cvd.ts @@ -0,0 +1,196 @@ +// CVD (Color Vision Deficiency) simulation — "what does this color look like to a +// protan/deutan/tritan viewer?". Consumed by the objective gate (test/cvd.test.ts) +// and the proof-sheet preview (src/previews/cvd.ts). +// +// ───────────────────────────────────────────────────────────────────────────── +// WHAT IS CVD? (the 30-second version for engineers new to this) +// ───────────────────────────────────────────────────────────────────────────── +// "Color vision deficiency" (colloquially "color blindness") means one of the +// three cone types in the retina is missing or shifted, so some hues that look +// distinct to most people collapse into the same perceived color. The three +// dichromacies we target: +// +// • Protanopia — missing L (long/red) cones ┐ both confuse RED ↔ GREEN. +// • Deuteranopia— missing M (medium/green)cones┘ The axis that can still be +// told apart is roughly BLUE ↔ ORANGE/YELLOW. +// • Tritanopia — missing S (short/blue) cones. Confuses BLUE ↔ GREEN. The +// axis that survives is roughly RED ↔ CYAN/TEAL. +// +// Design consequence: a CVD-safe theme must carry meaning (added vs deleted, +// pass vs fail, error vs warning) on the axis that *survives* for that +// deficiency, and lean on LUMINANCE (light/dark) as a second channel whenever a +// hue pole has to be reused. We don't guess whether a palette works — we +// *simulate* how each color looks to a dichromat, then measure separations with +// deltaE2000() and legibility with contrastRatio() (sibling color-science +// modules). The objective gate in test/cvd.test.ts ties those together. +// +// Standards / sources (also cited in ACCESSIBILITY.md): +// • Machado, Oliveira & Fernandes (2009), "A Physiologically-Based Model for +// Simulation of Color Vision Deficiency", IEEE TVCG — the simulation matrices. + +import { hexToRgb01, srgbToLinear, linearToSrgb } from "./srgb"; +import { deltaE2000 } from "./deltaE"; + +export type CVDType = "protan" | "deutan" | "tritan"; + +// ───────────────────────────────────────────────────────────────────────────── +// CVD SIMULATION — Machado, Oliveira & Fernandes (2009) +// ───────────────────────────────────────────────────────────────────────────── +// The Machado model reduces "how a dichromat sees a color" to a single 3×3 +// matrix multiply. The authors published one matrix per deficiency at 11 severity +// steps (0.0 = normal vision … 1.0 = full dichromacy). We embed all 11 (the same +// values the colorspace R package and culori use) but gate the themes at severity +// 1.0 — the worst case — so anything that survives also works for milder +// anomalous trichromacy. +// +// Each matrix row sums to ~1.0, so neutral grays (R=G=B) map to themselves — a +// useful check that the tables were transcribed correctly. +// +// GAMMA CONVENTION (genuinely debated — read before changing). We apply the +// matrices in LINEAR RGB: linearize the sRGB hex, multiply, re-encode. The +// rationale is consistency with the model's derivation — the RGB↔LMS step it +// approximates lives in linear light. But this is a *theoretical* preference, not +// an empirical one: there is no published study proving linear-applied Machado +// matches real dichromat perception better than the gamma-sRGB application used +// by culori and the `colorspace` R package (which it follows). The two only +// diverge noticeably on saturated colors. We implement linear here and the gate +// in test/cvd.test.ts additionally checks culori's gamma convention for Tier-1 +// and Tier-2 distinguishability. + +type Matrix3 = readonly [ + number, number, number, + number, number, number, + number, number, number, +]; + +// Severity 0.0 → 1.0 in 0.1 steps. Index 10 (severity 1.0) is the dichromacy. +const MACHADO: Record = { + protan: [ + [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000], + [0.856167, 0.182038, -0.038205, 0.029342, 0.955115, 0.015544, -0.002880, -0.001563, 1.004443], + [0.734766, 0.334872, -0.069637, 0.051840, 0.919198, 0.028963, -0.004928, -0.004209, 1.009137], + [0.630323, 0.465641, -0.095964, 0.069181, 0.890046, 0.040773, -0.006308, -0.007724, 1.014032], + [0.539009, 0.579343, -0.118352, 0.082546, 0.866121, 0.051332, -0.007136, -0.011959, 1.019095], + [0.458064, 0.679578, -0.137642, 0.092785, 0.846313, 0.060902, -0.007494, -0.016807, 1.024301], + [0.385450, 0.769005, -0.154455, 0.100526, 0.829802, 0.069673, -0.007442, -0.022190, 1.029632], + [0.319627, 0.849633, -0.169261, 0.106241, 0.815969, 0.077790, -0.007025, -0.028051, 1.035076], + [0.259411, 0.923008, -0.182420, 0.110296, 0.804340, 0.085364, -0.006276, -0.034346, 1.040622], + [0.203876, 0.990338, -0.194214, 0.112975, 0.794542, 0.092483, -0.005222, -0.041043, 1.046265], + [0.152286, 1.052583, -0.204868, 0.114503, 0.786281, 0.099216, -0.003882, -0.048116, 1.051998], + ], + deutan: [ + [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000], + [0.866435, 0.177704, -0.044139, 0.049567, 0.939063, 0.011370, -0.003453, 0.007233, 0.996220], + [0.760729, 0.319078, -0.079807, 0.090568, 0.889315, 0.020117, -0.006027, 0.013325, 0.992702], + [0.675425, 0.433850, -0.109275, 0.125303, 0.847755, 0.026942, -0.007950, 0.018572, 0.989378], + [0.605511, 0.528560, -0.134071, 0.155318, 0.812366, 0.032316, -0.009376, 0.023176, 0.986200], + [0.547494, 0.607765, -0.155259, 0.181692, 0.781742, 0.036566, -0.010410, 0.027275, 0.983136], + [0.498864, 0.674741, -0.173604, 0.205199, 0.754872, 0.039929, -0.011131, 0.030969, 0.980162], + [0.457771, 0.731899, -0.189670, 0.226409, 0.731012, 0.042579, -0.011595, 0.034333, 0.977261], + [0.422823, 0.781057, -0.203881, 0.245752, 0.709602, 0.044646, -0.011843, 0.037423, 0.974421], + [0.392952, 0.823610, -0.216562, 0.263559, 0.690210, 0.046232, -0.011910, 0.040281, 0.971630], + [0.367322, 0.860646, -0.227968, 0.280085, 0.672501, 0.047413, -0.011820, 0.042940, 0.968881], + ], + tritan: [ + [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000], + [0.926670, 0.092514, -0.019184, 0.021191, 0.964503, 0.014306, 0.008437, 0.054813, 0.936750], + [0.895720, 0.133330, -0.029050, 0.029997, 0.945400, 0.024603, 0.013027, 0.104707, 0.882266], + [0.905871, 0.127791, -0.033662, 0.026856, 0.941251, 0.031893, 0.013410, 0.148296, 0.838294], + [0.948035, 0.089490, -0.037526, 0.014364, 0.946792, 0.038844, 0.010853, 0.193991, 0.795156], + [1.017277, 0.027029, -0.044306, -0.006113, 0.958479, 0.047634, 0.006379, 0.248708, 0.744913], + [1.104996, -0.046633, -0.058363, -0.032137, 0.971635, 0.060503, 0.001336, 0.317922, 0.680742], + [1.193214, -0.109812, -0.083402, -0.058496, 0.979410, 0.079086, -0.002346, 0.403492, 0.598854], + [1.257728, -0.139648, -0.118081, -0.078003, 0.975409, 0.102594, -0.003316, 0.501214, 0.502102], + [1.278864, -0.125333, -0.153531, -0.084748, 0.957674, 0.127074, -0.000989, 0.601151, 0.399838], + [1.255528, -0.076749, -0.178779, -0.078411, 0.930809, 0.147602, 0.004733, 0.691367, 0.303900], + ], +}; + +function clamp01(v: number): number { + return v < 0 ? 0 : v > 1 ? 1 : v; +} + +function channelToHex(v01: number): string { + return Math.round(clamp01(v01) * 255).toString(16).padStart(2, "0"); +} + +/** + * Simulate how `hex` appears to someone with the given dichromacy. + * + * @param hex sRGB hex color, e.g. "#1a85d4". + * @param type "protan" | "deutan" | "tritan". + * @param severity 0.0 (normal) … 1.0 (full dichromacy). Defaults to 1.0 — the + * worst case the themes are gated against. Snapped to the nearest + * published 0.1 step. + * @returns a new sRGB hex string of the simulated appearance. + */ +export function simulateCVD(hex: string, type: CVDType, severity = 1.0): string { + if (!/^#?[0-9a-fA-F]{6}$/.test(hex)) { + throw new Error(`simulateCVD expects a 6-digit hex color, got: ${hex}`); + } + const step = Math.round(clamp01(severity) * 10); // 0..10 + const m = MACHADO[type][step]; + + // sRGB hex → linear RGB (the matrix lives in linear light, see GAMMA note). + const [r, g, b] = hexToRgb01(hex).map(srgbToLinear) as [number, number, number]; + + const lr = m[0] * r + m[1] * g + m[2] * b; + const lg = m[3] * r + m[4] * g + m[5] * b; + const lb = m[6] * r + m[7] * g + m[8] * b; + + // linear RGB → sRGB hex. + const R = channelToHex(linearToSrgb(clamp01(lr))); + const G = channelToHex(linearToSrgb(clamp01(lg))); + const B = channelToHex(linearToSrgb(clamp01(lb))); + return `#${R}${G}${B}`; +} + +// ───────────────────────────────────────────────────────────────────────────── +// SELF-CHECKS — prove the simulation is wired up correctly +// ───────────────────────────────────────────────────────────────────────────── +// Provable invariants of the model: severity-0 is the identity, neutral grays are +// preserved (every Machado row sums to ~1), and the expected confusable axis +// actually collapses. (contrast/ΔE are additionally cross-checked against culori +// in test/cvd.test.ts.) These run from cvd.test.ts. + +export type SelfCheckResult = { name: string; ok: boolean; detail: string }; + +export function cvdSelfChecks(): SelfCheckResult[] { + const results: SelfCheckResult[] = []; + const near = (a: string, b: string, tol = 2) => { + const [r1, g1, b1] = hexToRgb01(a).map((x) => x * 255); + const [r2, g2, b2] = hexToRgb01(b).map((x) => x * 255); + return Math.abs(r1 - r2) <= tol && Math.abs(g1 - g2) <= tol && Math.abs(b1 - b2) <= tol; + }; + + // (a) Severity 0 is the identity transform for every type. + for (const t of ["protan", "deutan", "tritan"] as CVDType[]) { + const samples = ["#1a85d4", "#d52c36", "#199f43", "#ffca00"]; + const ok = samples.every((h) => near(simulateCVD(h, t, 0), h, 1)); + results.push({ name: `severity-0 identity (${t})`, ok, detail: ok ? "input preserved" : "drifted" }); + } + + // (b) Neutral axis is preserved: gray/white/black map to themselves. + for (const t of ["protan", "deutan", "tritan"] as CVDType[]) { + const grays = ["#000000", "#808080", "#bcbcbc", "#ffffff"]; + const ok = grays.every((h) => near(simulateCVD(h, t, 1), h, 3)); + results.push({ name: `neutral axis preserved (${t})`, ok, detail: ok ? "grays stable" : "grays shifted" }); + } + + // (c) Behavioral: the simulation actually *removes* the confusable axis. + // RED↔GREEN collapses under protan/deutan; BLUE↔GREEN under tritan. + // (Tritanopia is loosely "blue-yellow", but blue & yellow differ in + // luminance — which tritanopes keep — so blue↔green is the real collapse.) + const red = "#ff2e3f", green = "#199f43", blue = "#009fff"; + const collapses = (name: string, t: CVDType, x: string, y: string) => { + const before = deltaE2000(x, y); + const after = deltaE2000(simulateCVD(x, t, 1), simulateCVD(y, t, 1)); + const ok = after < before * 0.5; // confusable axis loses at least half its separation + results.push({ name, ok, detail: `ΔE ${before.toFixed(1)} → ${after.toFixed(1)} under ${t}` }); + }; + collapses("protan collapses red↔green", "protan", red, green); + collapses("deutan collapses red↔green", "deutan", red, green); + collapses("tritan collapses blue↔green", "tritan", blue, green); + + return results; +} diff --git a/src/color/deltaE.ts b/src/color/deltaE.ts new file mode 100644 index 0000000..56824ee --- /dev/null +++ b/src/color/deltaE.ts @@ -0,0 +1,88 @@ +// CIEDE2000 perceptual color difference (ΔE₀₀) — "how far apart do two colors +// look?". The modern CIE standard, tuned to human perception in CIE Lab space. +// Rough reading: <1 imperceptible, ~2–3 just noticeable, > ~10 "clearly +// different / not confused". The CVD gate computes ΔE between the *simulated* +// versions of two roles to prove a dichromat can still tell them apart. +// Pipeline: sRGB → linear → XYZ (D65) → Lab → CIEDE2000. + +import { hexToRgb01, srgbToLinear } from "./srgb"; + +function hexToLab(hex: string): [number, number, number] { + const [r, g, b] = hexToRgb01(hex).map(srgbToLinear) as [number, number, number]; + // linear sRGB → CIE XYZ (D65, Y of white = 1). + const x = 0.4124564 * r + 0.3575761 * g + 0.1804375 * b; + const y = 0.2126729 * r + 0.7151522 * g + 0.072175 * b; + const z = 0.0193339 * r + 0.119192 * g + 0.9503041 * b; + // XYZ → Lab, D65 reference white. + const xn = 0.95047, yn = 1.0, zn = 1.08883; + const f = (t: number) => (t > 0.008856 ? Math.cbrt(t) : 7.787 * t + 16 / 116); + const fx = f(x / xn), fy = f(y / yn), fz = f(z / zn); + return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)]; +} + +const deg2rad = (d: number) => (d * Math.PI) / 180; +const rad2deg = (r: number) => (r * 180) / Math.PI; + +/** CIEDE2000 color difference (ΔE₀₀) between two sRGB hex colors. */ +export function deltaE2000(hexA: string, hexB: string): number { + const [L1, a1, b1] = hexToLab(hexA); + const [L2, a2, b2] = hexToLab(hexB); + + const avgL = (L1 + L2) / 2; + const C1 = Math.hypot(a1, b1); + const C2 = Math.hypot(a2, b2); + const avgC = (C1 + C2) / 2; + + const G = 0.5 * (1 - Math.sqrt(Math.pow(avgC, 7) / (Math.pow(avgC, 7) + Math.pow(25, 7)))); + const a1p = a1 * (1 + G); + const a2p = a2 * (1 + G); + const C1p = Math.hypot(a1p, b1); + const C2p = Math.hypot(a2p, b2); + const avgCp = (C1p + C2p) / 2; + + const hp = (ap: number, bp: number) => { + if (ap === 0 && bp === 0) return 0; + let h = rad2deg(Math.atan2(bp, ap)); + if (h < 0) h += 360; + return h; + }; + const h1p = hp(a1p, b1); + const h2p = hp(a2p, b2); + + let dhp: number; + if (C1p * C2p === 0) dhp = 0; + else if (Math.abs(h2p - h1p) <= 180) dhp = h2p - h1p; + else if (h2p - h1p > 180) dhp = h2p - h1p - 360; + else dhp = h2p - h1p + 360; + + const dLp = L2 - L1; + const dCp = C2p - C1p; + const dHp = 2 * Math.sqrt(C1p * C2p) * Math.sin(deg2rad(dhp) / 2); + + let avgHp: number; + if (C1p * C2p === 0) avgHp = h1p + h2p; + else if (Math.abs(h1p - h2p) <= 180) avgHp = (h1p + h2p) / 2; + else if (h1p + h2p < 360) avgHp = (h1p + h2p + 360) / 2; + else avgHp = (h1p + h2p - 360) / 2; + + const T = + 1 - + 0.17 * Math.cos(deg2rad(avgHp - 30)) + + 0.24 * Math.cos(deg2rad(2 * avgHp)) + + 0.32 * Math.cos(deg2rad(3 * avgHp + 6)) - + 0.2 * Math.cos(deg2rad(4 * avgHp - 63)); + + const dTheta = 30 * Math.exp(-Math.pow((avgHp - 275) / 25, 2)); + const Rc = 2 * Math.sqrt(Math.pow(avgCp, 7) / (Math.pow(avgCp, 7) + Math.pow(25, 7))); + const Sl = 1 + (0.015 * Math.pow(avgL - 50, 2)) / Math.sqrt(20 + Math.pow(avgL - 50, 2)); + const Sc = 1 + 0.045 * avgCp; + const Sh = 1 + 0.015 * avgCp * T; + const Rt = -Math.sin(deg2rad(2 * dTheta)) * Rc; + + return Math.sqrt( + Math.pow(dLp / Sl, 2) + + Math.pow(dCp / Sc, 2) + + Math.pow(dHp / Sh, 2) + + Rt * (dCp / Sc) * (dHp / Sh) + ); +} diff --git a/src/color/index.ts b/src/color/index.ts new file mode 100644 index 0000000..62b0da6 --- /dev/null +++ b/src/color/index.ts @@ -0,0 +1,9 @@ +// Color science: pure, dependency-free color math shared by the theme build +// (Display-P3 vibrant variants), the previews, and the CVD accessibility gate. +// Each concern is a discrete module; this barrel re-exports the public surface. + +export { hexToRgb01, srgbToLinear, linearToSrgb } from "./srgb"; +export { srgbHexToP3Color, convertRolesToP3 } from "./p3"; +export { contrastRatio } from "./contrast"; +export { deltaE2000 } from "./deltaE"; +export { simulateCVD, cvdSelfChecks, type CVDType, type SelfCheckResult } from "./cvd"; diff --git a/src/color/p3.ts b/src/color/p3.ts new file mode 100644 index 0000000..62b9106 --- /dev/null +++ b/src/color/p3.ts @@ -0,0 +1,156 @@ +// Convert sRGB hex colors to the CSS Display P3 color space, with an optional +// saturation/luminance boost that pushes colors into P3's wider gamut. This is +// how the "vibrant" theme variants are defined (see scripts/build.ts) and +// previewed (src/previews/p3.ts). + +import { hexToRgb01, srgbToLinear, linearToSrgb } from "./srgb"; + +// Display P3 uses the same transfer function (gamma) as sRGB. +const linearToP3 = linearToSrgb; + +/** Linear sRGB → linear Display P3 (sRGB primaries → P3 primaries via XYZ). */ +function linearSrgbToLinearP3(r: number, g: number, b: number): [number, number, number] { + const rOut = 0.82246197 * r + 0.17753803 * g + 0.0 * b; + const gOut = 0.0331942 * r + 0.9668058 * g + 0.0 * b; + const bOut = 0.01708263 * r + 0.07239744 * g + 0.91051993 * b; + return [rOut, gOut, bOut]; +} + +/** Format a 0–1 channel for a CSS color() function (clamped, 6 dp). */ +function formatColorValue(value: number): string { + const clamped = Math.max(0, Math.min(1, value)); + return clamped.toFixed(6); +} + +function rgbToHsl(r: number, g: number, b: number): [number, number, number] { + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + const delta = max - min; + + let h = 0; + let s = 0; + const l = (max + min) / 2; + + if (delta !== 0) { + s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min); + switch (max) { + case r: + h = ((g - b) / delta + (g < b ? 6 : 0)) / 6; + break; + case g: + h = ((b - r) / delta + 2) / 6; + break; + case b: + h = ((r - g) / delta + 4) / 6; + break; + } + } + + return [h, s, l]; +} + +function hslToRgb(h: number, s: number, l: number): [number, number, number] { + let r, g, b; + + if (s === 0) { + r = g = b = l; + } else { + const hue2rgb = (p: number, q: number, t: number) => { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + }; + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + return [r, g, b]; +} + +/** + * Enhance colors to take advantage of P3's wider gamut: boost saturation + * (15–30% by original saturation) and, for vivid mid-tones, luminance (~5%). + * Grays and near-black/white are left untouched. + */ +function enhanceForP3Gamut(r: number, g: number, b: number): [number, number, number] { + const [h, s, l] = rgbToHsl(r, g, b); + + if (s < 0.1 || l < 0.1 || l > 0.9) { + return [r, g, b]; + } + + const saturationBoost = 0.15 + s * 0.15; // 15–30% depending on saturation + let newS = Math.min(1.0, s + s * saturationBoost); + + let newL = l; + if (s > 0.5 && l < 0.7) { + newL = Math.min(0.9, l + l * 0.05); + } + + return hslToRgb(h, newS, newL); +} + +/** + * Convert an sRGB hex color to a CSS Display P3 string, + * "color(display-p3 r g b)" (or "… / alpha"). + */ +export function srgbHexToP3Color(srgbHex: string, enhance: boolean = true): string { + const hasAlpha = srgbHex.length === 9 || (srgbHex.startsWith("#") && srgbHex.length === 9); + let alpha = ""; + let colorHex = srgbHex; + + if (hasAlpha) { + const alphaHex = srgbHex.slice(-2); + const alphaValue = parseInt(alphaHex, 16) / 255; + alpha = ` / ${formatColorValue(alphaValue)}`; + colorHex = srgbHex.slice(0, -2); + } + + const [sR, sG, sB] = hexToRgb01(colorHex); + const [linearPR, linearPG, linearPB] = linearSrgbToLinearP3( + srgbToLinear(sR), + srgbToLinear(sG), + srgbToLinear(sB) + ); + + let pR = linearToP3(linearPR); + let pG = linearToP3(linearPG); + let pB = linearToP3(linearPB); + + if (enhance) { + [pR, pG, pB] = enhanceForP3Gamut(pR, pG, pB); + } + + return `color(display-p3 ${formatColorValue(pR)} ${formatColorValue(pG)} ${formatColorValue(pB)}${alpha})`; +} + +/** Recursively convert every hex color in a Roles-shaped object to Display P3. */ +export function convertRolesToP3(obj: T): T { + if (typeof obj === "string") { + if ((obj as string).match(/^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$/)) { + return srgbHexToP3Color(obj as string) as any; + } + return obj; + } + + if (Array.isArray(obj)) { + return obj.map((item) => convertRolesToP3(item)) as any; + } + + if (obj !== null && typeof obj === "object") { + const result: any = {}; + for (const [key, value] of Object.entries(obj as any)) { + result[key] = convertRolesToP3(value); + } + return result; + } + + return obj; +} diff --git a/src/color/srgb.ts b/src/color/srgb.ts new file mode 100644 index 0000000..c86e716 --- /dev/null +++ b/src/color/srgb.ts @@ -0,0 +1,34 @@ +// Low-level sRGB primitives shared across the color-science modules (P3 +// conversion, CVD simulation, WCAG contrast, CIEDE2000). These are not +// Display-P3 concerns — they're the generic hex ↔ RGB and gamma conversions that +// everything else builds on. + +/** Parse a hex color ("#rgb" or "#rrggbb") to RGB channels in the 0–1 range. */ +export function hexToRgb01(hex: string): [number, number, number] { + const cleaned = hex.replace("#", ""); + const expanded = + cleaned.length === 3 ? cleaned.split("").map((x) => x + x).join("") : cleaned; + + const num = parseInt(expanded, 16); + const r = ((num >> 16) & 255) / 255; + const g = ((num >> 8) & 255) / 255; + const b = (num & 255) / 255; + + return [r, g, b]; +} + +/** Linearize an sRGB channel (remove the sRGB gamma curve). */ +export function srgbToLinear(c: number): number { + if (c <= 0.04045) { + return c / 12.92; + } + return Math.pow((c + 0.055) / 1.055, 2.4); +} + +/** Apply the sRGB gamma curve to a linear channel (encode for display). */ +export function linearToSrgb(c: number): number { + if (c <= 0.0031308) { + return c * 12.92; + } + return 1.055 * Math.pow(c, 1 / 2.4) - 0.055; +} diff --git a/src/theme.ts b/src/createTheme.ts similarity index 99% rename from src/theme.ts rename to src/createTheme.ts index e20e87e..c8f4133 100644 --- a/src/theme.ts +++ b/src/createTheme.ts @@ -1,5 +1,4 @@ -// src/theme.ts -import type { Roles } from "./palette"; +import type { Roles } from "./roles"; type VSCodeTheme = { name: string; @@ -10,14 +9,14 @@ type VSCodeTheme = { semanticTokenColors: Record; }; -type MakeThemeOptions = { +type CreateThemeOptions = { name: string; displayName: string; type: "light" | "dark"; roles: Roles; }; -export function makeTheme({ name, displayName, type: kind, roles: c }: MakeThemeOptions): VSCodeTheme { +export function createTheme({ name, displayName, type: kind, roles: c }: CreateThemeOptions): VSCodeTheme { return { name, displayName, diff --git a/src/zed-theme.ts b/src/createZedTheme.ts similarity index 99% rename from src/zed-theme.ts rename to src/createZedTheme.ts index af83d37..1eb2347 100644 --- a/src/zed-theme.ts +++ b/src/createZedTheme.ts @@ -1,5 +1,4 @@ -// src/zed-theme.ts -import type { Roles } from "./palette"; +import type { Roles } from "./roles"; type ZedHighlightStyle = { color?: string; @@ -196,13 +195,13 @@ type ZedThemeFamilyContent = { themes: ZedTheme[]; }; -export type ZedThemeVariant = { +type ZedThemeVariant = { name: string; appearance: "light" | "dark"; roles: Roles; }; -export function makeZedThemeFamily( +export function createZedTheme( familyName: string, author: string, variants: ZedThemeVariant[] diff --git a/src/demo-p3.ts b/src/demo-p3.ts deleted file mode 100644 index f2d2c7a..0000000 --- a/src/demo-p3.ts +++ /dev/null @@ -1,44 +0,0 @@ -// src/demo-p3.ts -// Demonstration of Display P3 color conversion with enhancement - -import { srgbHexToP3Color } from "./color-p3"; - -console.log("Display P3 Color Conversion Demo"); -console.log("=".repeat(70)); -console.log(""); - -const testColors = [ - { name: "Blue", srgb: "#008cff" }, - { name: "Green", srgb: "#0dbe4e" }, - { name: "Red", srgb: "#ff2e3f" }, - { name: "Purple", srgb: "#c635e4" }, - { name: "Pink", srgb: "#fc2b73" }, - { name: "Orange", srgb: "#fe8c2c" }, - { name: "Cyan", srgb: "#08c0ef" }, - { name: "Teal", srgb: "#00c5d2" } -]; - -console.log("Color conversions from sRGB to Enhanced Display P3:"); -console.log("(Enhanced to take advantage of P3's wider gamut)"); -console.log(""); - -for (const { name, srgb } of testColors) { - const p3Basic = srgbHexToP3Color(srgb, false); - const p3Enhanced = srgbHexToP3Color(srgb, true); - console.log(`${name.padEnd(10)} ${srgb}`); - console.log(`${''.padEnd(10)} Basic: ${p3Basic}`); - console.log(`${''.padEnd(10)} Enhanced: ${p3Enhanced}`); - console.log(""); -} - -console.log("=".repeat(70)); -console.log(""); -console.log("Enhancement Details:"); -console.log("- Saturation boost: 15-30% depending on original saturation"); -console.log("- Luminance boost: 5% for highly saturated colors"); -console.log("- Grays and near-blacks/whites are left unchanged"); -console.log(""); -console.log("These enhanced colors take full advantage of Display P3's"); -console.log("wider color gamut (~25% more colors than sRGB)."); -console.log(""); -console.log("Browser support: Safari 10+, Chrome 111+, Firefox 113+, Edge 111+"); diff --git a/src/palette.ts b/src/palette.ts deleted file mode 100644 index 46ead47..0000000 --- a/src/palette.ts +++ /dev/null @@ -1,662 +0,0 @@ -// src/palette.ts - -// gray is a slightly blue-tinted neutral scale kept as a reference palette for consumers. -// It is not used in any built-in role; all four theme variants use `neutral` instead. -const gray = { - "020":"#fbfbfb", - "040":"#f9f9f9", - "060":"#f8f8f8", - "080":"#f2f2f3", - "100":"#eeeeef", - "200":"#dbdbdd", - "300":"#c6c6c8", - "400":"#adadb1", - "500":"#8E8E95", - "600":"#84848A", - "700":"#79797F", - "800":"#6C6C71", - "900":"#4A4A4E", - "920":"#424245", - "940":"#39393c", - "960":"#2e2e30", - "980":"#1F1F21", - "1000":"#141415", - "1020":"#0B0B0C", - "1040":"#070707" -}; - -const neutral = { - "020":"#fafafa", - "040":"#f7f7f7", - "060":"#f5f5f5", - "080":"#ededed", - "100":"#e5e5e5", - "200":"#d4d4d4", - "300":"#bcbcbc", - "400":"#a3a3a3", - "500":"#8a8a8a", - "600":"#737373", - "700":"#636363", - "800":"#525252", - "900":"#404040", - "920":"#363636", - "940":"#2c2c2c", - "960":"#262626", - "980":"#1d1d1d", - "1000":"#171717", - "1020":"#101010", - "1040":"#0a0a0a" -}; - -const red = { - "050":"#ffedea", - "100":"#ffdbd6", - "200":"#ffb7ae", - "300":"#ff9187", - "400":"#ff6762", - "500":"#ff2e3f", - "600":"#d52c36", - "700":"#ad292e", - "800":"#862425", - "900":"#611e1d", - "950":"#3e1715" -}; - -const vermillion = { - "050":"#fff0ea", - "100":"#ffe2d6", - "200":"#ffc4ad", - "300":"#ffa685", - "400":"#ff855e", - "500":"#ff5d36", - "600":"#d5512f", - "700":"#ad4529", - "800":"#863822", - "900":"#612b1b", - "950":"#3e1e14" -}; - -const orange = { - "050":"#fff3ea", - "100":"#ffe8d5", - "200":"#ffd1ab", - "300":"#ffba82", - "400":"#ffa359", - "500":"#fe8c2c", - "600":"#d47628", - "700":"#ac6023", - "800":"#854c1e", - "900":"#603819", - "950":"#3d2513" -}; - -const amber = { - "050": "#fff6ea", - "100": "#ffeed5", - "200": "#ffddab", - "300": "#ffcc81", - "400": "#ffbc56", - "500": "#ffab16", - "600": "#d5901c", - "700": "#ac741d", - "800": "#855b1b", - "900": "#604218", - "950": "#3d2b13" -}; - -const yellow = { - "050": "#fff9ea", - "100": "#fff4d5", - "200": "#ffe9ab", - "300": "#ffde80", - "400": "#ffd452", - "500": "#ffca00", - "600": "#d5a910", - "700": "#ac8816", - "800": "#856a17", - "900": "#604c16", - "950": "#3d3112" -}; - -const lime = { - "050": "#f6f9ec", - "100": "#edf4d8", - "200": "#dae8b1", - "300": "#c6dc8a", - "400": "#afd062", - "500": "#86c427", - "600": "#77a42a", - "700": "#658527", - "800": "#516723", - "900": "#3e4b1d", - "950": "#2a3016" -}; - -const green = { - "050": "#edf9ed", - "100": "#daf3db", - "200": "#b4e7b7", - "300": "#8cda94", - "400": "#5ecc71", - "500": "#0dbe4e", - "600": "#199f43", - "700": "#1d8138", - "800": "#1d642e", - "900": "#1b4923", - "950": "#162f19" -}; - -const jade = { - "050": "#edfaf2", - "100": "#dbf4e5", - "200": "#b6e9cb", - "300": "#8eddb2", - "400": "#60d199", - "500": "#07c480", - "600": "#18a46c", - "700": "#1d8558", - "800": "#1e6746", - "900": "#1c4b34", - "950": "#163023" -}; - -const mint = { - "050": "#edfaf7", - "100": "#dbf5ef", - "200": "#b7ebdf", - "300": "#8fe0d0", - "400": "#61d5c0", - "500": "#00cab1", - "600": "#16a994", - "700": "#1d8978", - "800": "#1e6a5e", - "900": "#1c4d44", - "950": "#16312c" -}; - -const teal = { - "050": "#eef9fa", - "100": "#ddf4f6", - "200": "#b9e8ed", - "300": "#92dde4", - "400": "#64d1db", - "500": "#00c5d2", - "600": "#17a5af", - "700": "#1e858e", - "800": "#1f686e", - "900": "#1d4b4f", - "950": "#173033" -}; - -const cyan = { - "050": "#eff9fe", - "100": "#def2fc", - "200": "#bce6f9", - "300": "#96d9f6", - "400": "#68cdf2", - "500": "#08c0ef", - "600": "#1ca1c7", - "700": "#2182a1", - "800": "#22657c", - "900": "#1e4959", - "950": "#182f38" -}; - -const blue = { - "050": "#eff5ff", - "100": "#dfebff", - "200": "#bdd7ff", - "300": "#97c4ff", - "400": "#69b1ff", - "500": "#009fff", - "600": "#1a85d4", - "700": "#216cab", - "800": "#215584", - "900": "#1f3e5e", - "950": "#19283c" -}; - -const indigo = { - "050": "#f5ecff", - "100": "#ead9ff", - "200": "#d3b4fe", - "300": "#ba8ffd", - "400": "#9d6afb", - "500": "#7b43f8", - "600": "#693acf", - "700": "#5731a7", - "800": "#462981", - "900": "#35205c", - "950": "#24173a" -}; - -const violet = { - "050": "#f8edfe", - "100": "#f1dafd", - "200": "#e1b5fa", - "300": "#ce90f7", - "400": "#b969f3", - "500": "#a13cee", - "600": "#8836c7", - "700": "#6f2ea1", - "800": "#58287c", - "900": "#412059", - "950": "#2b1738" -}; - -const purple = { - "050": "#fbedfd", - "100": "#f7dbfb", - "200": "#eeb6f6", - "300": "#e290f0", - "400": "#d568ea", - "500": "#c635e4", - "600": "#a631be", - "700": "#872b9a", - "800": "#692677", - "900": "#4d1f56", - "950": "#321736" -}; - -const magenta = { - "050": "#fdedf7", - "100": "#fbdbee", - "200": "#f7b7dd", - "300": "#f191cc", - "400": "#ea68bc", - "500": "#e130ac", - "600": "#bd2e90", - "700": "#992a75", - "800": "#77255b", - "900": "#561f43", - "950": "#38172b" -}; - -const pink = { - "050": "#ffedf0", - "100": "#ffdbe1", - "200": "#ffb7c4", - "300": "#ff91a8", - "400": "#ff678d", - "500": "#fc2b73", - "600": "#d32a61", - "700": "#aa2850", - "800": "#84243f", - "900": "#5f1e2f", - "950": "#3d1720" -}; - -const rose = { - "050": "#ffeded", - "100": "#ffdbdc", - "200": "#ffb7b9", - "300": "#ff9198", - "400": "#ff6778", - "500": "#fe2d59", - "600": "#d42b4c", - "700": "#ac293f", - "800": "#852432", - "900": "#601e26", - "950": "#3e171b" -}; - -const brown = { - "050": "#f8f2ee", - "100": "#f1e4dd", - "200": "#e3cabb", - "300": "#d3b19b", - "400": "#c3987b", - "500": "#b27f5c", - "600": "#956b4f", - "700": "#7a5841", - "800": "#5f4534", - "900": "#453327", - "950": "#2d221b" -}; - -export const palettes = { - gray, neutral, - red, vermillion, orange, amber, yellow, lime, - green, jade, mint, teal, cyan, blue, - indigo, violet, purple, magenta, pink, rose, - brown -}; - -export type Roles = { - bg: { - editor: string; // main editor background (brightest in light, darkest in dark) - window: string; // sidebar, activity bar, status bar, title bar, inactive tabs - inset: string; // inputs, dropdowns - elevated: string; // panels, hover backgrounds - }; - fg: { base: string; fg1: string; fg2: string; fg3: string; fg4: string }; - border: { - window: string; // borders for sidebar, activity bar, status bar, title bar - editor: string; // general editor borders - indentGuide: string; // indent guide lines - indentGuideActive: string; // active indent guide line - inset: string; // borders for inputs, dropdowns - elevated: string; // borders for panels - }; - accent: { primary: string; link: string; subtle: string; contrastOnAccent: string }; - states: { merge: string, success: string; danger: string; warn: string; info: string }; - syntax: { - comment: string; string: string; number: string; keyword: string; - regexp: string; func: string; type: string; variable: string; - // Extended token types - operator: string; punctuation: string; constant: string; - parameter: string; namespace: string; decorator: string; - escape: string; invalid: string; tag: string; attribute: string; - }; - ansi: { - black: string; red: string; green: string; yellow: string; - blue: string; magenta: string; cyan: string; white: string; - brightBlack: string; brightRed: string; brightGreen: string; brightYellow: string; - brightBlue: string; brightMagenta: string; brightCyan: string; brightWhite: string; - }; -}; - -export const light: Roles = { - bg: { - editor: "#ffffff", - window: neutral["060"], - inset: neutral["080"], - elevated: neutral["040"] - }, - fg: { - base: neutral["1040"], - fg1: neutral["900"], - fg2: neutral["800"], - fg3: neutral["600"], - fg4: neutral["500"] - }, - border: { - window: neutral["100"], - editor: neutral["200"], - indentGuide: neutral["100"], - indentGuideActive: neutral["200"], - inset: neutral["200"], - elevated: neutral["100"] - }, - accent: { - primary: blue["500"], - link: blue["500"], - subtle: blue["100"], - contrastOnAccent: "#ffffff" - }, - states: { - merge: indigo["600"], - success: jade["600"], - danger: red["600"], - warn: yellow["600"], - info: cyan["600"] - }, - syntax: { - comment: neutral["600"], - string: green["600"], - number: cyan["600"], - keyword: pink["600"], - regexp: teal["600"], - func: indigo["600"], - type: purple["600"], - variable: orange["600"], - // Extended token types - operator: cyan["500"], - punctuation: neutral["700"], - constant: yellow["600"], - parameter: neutral["700"], - namespace: amber["600"], - decorator: blue["600"], - escape: mint["600"], - invalid: neutral["1040"], - tag: vermillion["600"], - attribute: jade["600"] - }, - ansi: { - black: neutral["980"], - red: red["600"], - green: jade["600"], - yellow: yellow["600"], - blue: blue["600"], - magenta: magenta["600"], - cyan: cyan["600"], - white: neutral["300"], - // make bright colors match the non-bright counterparts - brightBlack: neutral["980"], - brightRed: red["600"], - brightGreen: lime["600"], - brightYellow: yellow["600"], - brightBlue: blue["600"], - brightMagenta: magenta["600"], - brightCyan: cyan["600"], - brightWhite: neutral["300"] - } -}; - -export const lightSoft: Roles = { - bg: { - editor: "#ffffff", - window: neutral["040"], - inset: neutral["060"], - elevated: neutral["020"] - }, - fg: { - base: neutral["800"], - fg1: neutral["700"], - fg2: neutral["600"], - fg3: neutral["500"], - fg4: neutral["400"] - }, - border: { - window: neutral["080"], - editor: neutral["100"], - indentGuide: neutral["080"], - indentGuideActive: neutral["100"], - inset: neutral["200"], - elevated: neutral["100"] - }, - accent: { - primary: blue["500"], - link: blue["500"], - subtle: blue["100"], - contrastOnAccent: "#ffffff" - }, - states: { - merge: indigo["500"], - success: jade["500"], - danger: red["500"], - warn: yellow["500"], - info: cyan["500"] - }, - syntax: { - comment: neutral["500"], - string: green["500"], - number: cyan["500"], - keyword: pink["400"], - regexp: teal["500"], - func: indigo["400"], - type: purple["400"], - variable: orange["500"], - // Extended token types - operator: cyan["400"], - punctuation: neutral["600"], - constant: yellow["500"], - parameter: neutral["600"], - namespace: amber["500"], - decorator: blue["400"], - escape: mint["500"], - invalid: neutral["1000"], - tag: vermillion["500"], - attribute: jade["500"] - }, - ansi: { - black: neutral["980"], - red: red["500"], - green: green["500"], - yellow: yellow["500"], - blue: blue["500"], - magenta: magenta["500"], - cyan: cyan["500"], - white: neutral["300"], - brightBlack: neutral["980"], - brightRed: red["500"], - brightGreen: lime["500"], - brightYellow: yellow["500"], - brightBlue: blue["500"], - brightMagenta: magenta["500"], - brightCyan: cyan["500"], - brightWhite: neutral["300"] - } -}; - -export const dark: Roles = { - bg: { - editor: neutral["1040"], - window: neutral["1000"], - inset: neutral["980"], - elevated: neutral["1020"] - }, - fg: { - base: neutral["020"], - fg1: neutral["200"], - fg2: neutral["400"], - fg3: neutral["600"], - fg4: neutral["700"] - }, - border: { - window: neutral["1040"], - editor: neutral["980"], - indentGuide: neutral["980"], - indentGuideActive: neutral["960"], - inset: neutral["980"], - elevated: neutral["980"] - }, - accent: { - primary: blue["500"], - link: blue["500"], - subtle: blue["950"], - contrastOnAccent: neutral["1040"] - }, - states: { - merge: indigo["500"], - success: jade["500"], - danger: red["500"], - warn: yellow["500"], - info: cyan["500"] - }, - syntax: { - comment: neutral["600"], - string: green["400"], - number: cyan["400"], - keyword: pink["400"], - regexp: teal["400"], - func: indigo["400"], - type: purple["400"], - variable: orange["400"], - // Extended token types - operator: cyan["500"], - punctuation: neutral["700"], - constant: yellow["400"], - parameter: neutral["400"], - namespace: amber["500"], - decorator: blue["400"], - escape: mint["400"], - invalid: neutral["020"], - tag: vermillion["400"], - attribute: jade["400"] - }, - ansi: { - black: neutral["1000"], - red: red["500"], - green: green["500"], - yellow: yellow["500"], - blue: blue["500"], - magenta: magenta["500"], - cyan: cyan["500"], - white: neutral["300"], - brightBlack: neutral["1000"], - brightRed: red["500"], - brightGreen: lime["500"], - brightYellow: yellow["500"], - brightBlue: blue["500"], - brightMagenta: magenta["500"], - brightCyan: cyan["500"], - brightWhite: neutral["300"] - } -}; - -export const darkSoft: Roles = { - bg: { - editor: neutral["1000"], - window: neutral["1020"], - inset: neutral["960"], - elevated: neutral["980"] - }, - fg: { - base: neutral["200"], - fg1: neutral["300"], - fg2: neutral["500"], - fg3: neutral["700"], - fg4: neutral["800"] - }, - border: { - window: neutral["980"], - editor: neutral["940"], - indentGuide: neutral["960"], - indentGuideActive: neutral["940"], - inset: neutral["940"], - elevated: neutral["960"] - }, - accent: { - primary: blue["400"], - link: blue["400"], - subtle: blue["900"], - contrastOnAccent: neutral["1000"] - }, - states: { - merge: indigo["400"], - success: jade["400"], - danger: red["400"], - warn: yellow["400"], - info: cyan["400"] - }, - syntax: { - comment: neutral["700"], - string: green["300"], - number: cyan["300"], - keyword: pink["300"], - regexp: teal["300"], - func: indigo["300"], - type: purple["300"], - variable: orange["300"], - // Extended token types - operator: cyan["400"], - punctuation: neutral["600"], - constant: yellow["300"], - parameter: neutral["500"], - namespace: amber["400"], - decorator: blue["300"], - escape: mint["300"], - invalid: neutral["200"], - tag: vermillion["300"], - attribute: jade["300"] - }, - ansi: { - black: neutral["1000"], - red: red["500"], - green: green["500"], - yellow: yellow["500"], - blue: blue["500"], - magenta: magenta["500"], - cyan: cyan["500"], - white: neutral["300"], - brightBlack: neutral["1000"], - brightRed: red["500"], - brightGreen: lime["500"], - brightYellow: yellow["500"], - brightBlue: blue["500"], - brightMagenta: magenta["500"], - brightCyan: cyan["500"], - brightWhite: neutral["300"] - } -}; diff --git a/src/palettes.ts b/src/palettes.ts new file mode 100644 index 0000000..4ab9bcc --- /dev/null +++ b/src/palettes.ts @@ -0,0 +1,321 @@ +// gray is a slightly blue-tinted neutral scale kept as a reference palette for consumers. +// It is not used in any built-in role; all four theme variants use `neutral` instead. +const gray = { + "020":"#fbfbfb", + "040":"#f9f9f9", + "060":"#f8f8f8", + "080":"#f2f2f3", + "100":"#eeeeef", + "200":"#dbdbdd", + "300":"#c6c6c8", + "400":"#adadb1", + "500":"#8E8E95", + "600":"#84848A", + "700":"#79797F", + "800":"#6C6C71", + "900":"#4A4A4E", + "920":"#424245", + "940":"#39393c", + "960":"#2e2e30", + "980":"#1F1F21", + "1000":"#141415", + "1020":"#0B0B0C", + "1040":"#070707" +}; + +const neutral = { + "020":"#fafafa", + "040":"#f7f7f7", + "060":"#f5f5f5", + "080":"#ededed", + "100":"#e5e5e5", + "200":"#d4d4d4", + "300":"#bcbcbc", + "400":"#a3a3a3", + "500":"#8a8a8a", + "600":"#737373", + "700":"#636363", + "800":"#525252", + "900":"#404040", + "920":"#363636", + "940":"#2c2c2c", + "960":"#262626", + "980":"#1d1d1d", + "1000":"#171717", + "1020":"#101010", + "1040":"#0a0a0a" +}; + +const red = { + "050":"#ffedea", + "100":"#ffdbd6", + "200":"#ffb7ae", + "300":"#ff9187", + "400":"#ff6762", + "500":"#ff2e3f", + "600":"#d52c36", + "700":"#ad292e", + "800":"#862425", + "900":"#611e1d", + "950":"#3e1715" +}; + +const vermillion = { + "050":"#fff0ea", + "100":"#ffe2d6", + "200":"#ffc4ad", + "300":"#ffa685", + "400":"#ff855e", + "500":"#ff5d36", + "600":"#d5512f", + "700":"#ad4529", + "800":"#863822", + "900":"#612b1b", + "950":"#3e1e14" +}; + +const orange = { + "050":"#fff3ea", + "100":"#ffe8d5", + "200":"#ffd1ab", + "300":"#ffba82", + "400":"#ffa359", + "500":"#fe8c2c", + "600":"#d47628", + "700":"#ac6023", + "800":"#854c1e", + "900":"#603819", + "950":"#3d2513" +}; + +const amber = { + "050": "#fff6ea", + "100": "#ffeed5", + "200": "#ffddab", + "300": "#ffcc81", + "400": "#ffbc56", + "500": "#ffab16", + "600": "#d5901c", + "700": "#ac741d", + "800": "#855b1b", + "900": "#604218", + "950": "#3d2b13" +}; + +const yellow = { + "050": "#fff9ea", + "100": "#fff4d5", + "200": "#ffe9ab", + "300": "#ffde80", + "400": "#ffd452", + "500": "#ffca00", + "600": "#d5a910", + "700": "#ac8816", + "800": "#856a17", + "900": "#604c16", + "950": "#3d3112" +}; + +const lime = { + "050": "#f6f9ec", + "100": "#edf4d8", + "200": "#dae8b1", + "300": "#c6dc8a", + "400": "#afd062", + "500": "#86c427", + "600": "#77a42a", + "700": "#658527", + "800": "#516723", + "900": "#3e4b1d", + "950": "#2a3016" +}; + +const green = { + "050": "#edf9ed", + "100": "#daf3db", + "200": "#b4e7b7", + "300": "#8cda94", + "400": "#5ecc71", + "500": "#0dbe4e", + "600": "#199f43", + "700": "#1d8138", + "800": "#1d642e", + "900": "#1b4923", + "950": "#162f19" +}; + +const jade = { + "050": "#edfaf2", + "100": "#dbf4e5", + "200": "#b6e9cb", + "300": "#8eddb2", + "400": "#60d199", + "500": "#07c480", + "600": "#18a46c", + "700": "#1d8558", + "800": "#1e6746", + "900": "#1c4b34", + "950": "#163023" +}; + +const mint = { + "050": "#edfaf7", + "100": "#dbf5ef", + "200": "#b7ebdf", + "300": "#8fe0d0", + "400": "#61d5c0", + "500": "#00cab1", + "600": "#16a994", + "700": "#1d8978", + "800": "#1e6a5e", + "900": "#1c4d44", + "950": "#16312c" +}; + +const teal = { + "050": "#eef9fa", + "100": "#ddf4f6", + "200": "#b9e8ed", + "300": "#92dde4", + "400": "#64d1db", + "500": "#00c5d2", + "600": "#17a5af", + "700": "#1e858e", + "800": "#1f686e", + "900": "#1d4b4f", + "950": "#173033" +}; + +const cyan = { + "050": "#eff9fe", + "100": "#def2fc", + "200": "#bce6f9", + "300": "#96d9f6", + "400": "#68cdf2", + "500": "#08c0ef", + "600": "#1ca1c7", + "700": "#2182a1", + "800": "#22657c", + "900": "#1e4959", + "950": "#182f38" +}; + +const blue = { + "050": "#eff5ff", + "100": "#dfebff", + "200": "#bdd7ff", + "300": "#97c4ff", + "400": "#69b1ff", + "500": "#009fff", + "600": "#1a85d4", + "700": "#216cab", + "800": "#215584", + "900": "#1f3e5e", + "950": "#19283c" +}; + +const indigo = { + "050": "#f5ecff", + "100": "#ead9ff", + "200": "#d3b4fe", + "300": "#ba8ffd", + "400": "#9d6afb", + "500": "#7b43f8", + "600": "#693acf", + "700": "#5731a7", + "800": "#462981", + "900": "#35205c", + "950": "#24173a" +}; + +const violet = { + "050": "#f8edfe", + "100": "#f1dafd", + "200": "#e1b5fa", + "300": "#ce90f7", + "400": "#b969f3", + "500": "#a13cee", + "600": "#8836c7", + "700": "#6f2ea1", + "800": "#58287c", + "900": "#412059", + "950": "#2b1738" +}; + +const purple = { + "050": "#fbedfd", + "100": "#f7dbfb", + "200": "#eeb6f6", + "300": "#e290f0", + "400": "#d568ea", + "500": "#c635e4", + "600": "#a631be", + "700": "#872b9a", + "800": "#692677", + "900": "#4d1f56", + "950": "#321736" +}; + +const magenta = { + "050": "#fdedf7", + "100": "#fbdbee", + "200": "#f7b7dd", + "300": "#f191cc", + "400": "#ea68bc", + "500": "#e130ac", + "600": "#bd2e90", + "700": "#992a75", + "800": "#77255b", + "900": "#561f43", + "950": "#38172b" +}; + +const pink = { + "050": "#ffedf0", + "100": "#ffdbe1", + "200": "#ffb7c4", + "300": "#ff91a8", + "400": "#ff678d", + "500": "#fc2b73", + "600": "#d32a61", + "700": "#aa2850", + "800": "#84243f", + "900": "#5f1e2f", + "950": "#3d1720" +}; + +const rose = { + "050": "#ffeded", + "100": "#ffdbdc", + "200": "#ffb7b9", + "300": "#ff9198", + "400": "#ff6778", + "500": "#fe2d59", + "600": "#d42b4c", + "700": "#ac293f", + "800": "#852432", + "900": "#601e26", + "950": "#3e171b" +}; + +const brown = { + "050": "#f8f2ee", + "100": "#f1e4dd", + "200": "#e3cabb", + "300": "#d3b19b", + "400": "#c3987b", + "500": "#b27f5c", + "600": "#956b4f", + "700": "#7a5841", + "800": "#5f4534", + "900": "#453327", + "950": "#2d221b" +}; + +export const palettes = { + gray, neutral, + red, vermillion, orange, amber, yellow, lime, + green, jade, mint, teal, cyan, blue, + indigo, violet, purple, magenta, pink, rose, + brown +}; diff --git a/src/previews/cvd.ts b/src/previews/cvd.ts new file mode 100644 index 0000000..e68db7b --- /dev/null +++ b/src/previews/cvd.ts @@ -0,0 +1,179 @@ +// src/previews/cvd.ts +// Builds preview/cvd.html (returned as a string; written by scripts/createPreviews.ts) — +// a human-eyeballing companion to the objective gate (test/cvd.test.ts). For each +// CVD (color-vision-deficiency) theme it shows, +// side by side: the colors as defined in the theme, and the same colors pushed +// through the Machado-2009 simulation for that deficiency — i.e. what a person +// with that CVD sees. If the design works, the simulated column still reads as +// "added vs deleted", "pass vs fail", "error vs warning", etc. +// +// The numbers are proven by the gate; this page is for sanity-checking that the +// proof matches intuition. Run with `npm run preview`. +import { + protanDeutanLight, protanDeutanDark, tritanopiaLight, tritanopiaDark, + type Roles, +} from "../roles"; +import { simulateCVD, type CVDType } from "../color"; + +type View = { title: string; roles: Roles; cvd: CVDType; type: "light" | "dark" }; +// The protan/deutan theme targets two deficiencies, so it gets one row per +// deficiency (protanopia and deuteranopia) — both are gated in tests. The +// "normal vision" column is the same in both rows, which is expected. +const VIEWS: View[] = [ + // Light + { title: "Pierre Light Protanopia & Deuteranopia", roles: protanDeutanLight, cvd: "protan", type: "light" }, + { title: "Pierre Light Protanopia & Deuteranopia", roles: protanDeutanLight, cvd: "deutan", type: "light" }, + { title: "Pierre Light Tritanopia", roles: tritanopiaLight, cvd: "tritan", type: "light" }, + // Dark + { title: "Pierre Dark Protanopia & Deuteranopia", roles: protanDeutanDark, cvd: "protan", type: "dark" }, + { title: "Pierre Dark Protanopia & Deuteranopia", roles: protanDeutanDark, cvd: "deutan", type: "dark" }, + { title: "Pierre Dark Tritanopia", roles: tritanopiaDark, cvd: "tritan", type: "dark" }, +]; + +// Simulate every hex in a Roles object → "what the CVD viewer sees". +function simulateRoles(r: Roles, cvd: CVDType): Roles { + const walk = (o: any): any => { + if (typeof o === "string") return /^#[0-9a-fA-F]{6}$/.test(o) ? simulateCVD(o, cvd) : o; + const out: any = {}; + for (const [k, v] of Object.entries(o)) out[k] = walk(v); + return out; + }; + return walk(r); +} + +// Blend a foreground color over a background at the given alpha (for diff tints). +function mix(fg: string, bg: string, a: number): string { + const h = (c: string) => [1, 3, 5].map((i) => parseInt(c.slice(i, i + 2), 16)); + const [r1, g1, b1] = h(fg), [r2, g2, b2] = h(bg); + const m = (x: number, y: number) => Math.round(x * a + y * (1 - a)); + return `#${[m(r1, r2), m(g1, g2), m(b1, b2)].map((x) => x.toString(16).padStart(2, "0")).join("")}`; +} + +const swatch = (label: string, hex: string) => + `
${label}${hex}
`; + +// A mini code-review / editor mock built only from a theme's roles. +function mock(r: Roles): string { + const ed = r.bg.editor, win = r.bg.window; + const addBg = mix(r.states.success, ed, 0.18); + const delBg = mix(r.states.danger, ed, 0.18); + const dot = (c: string, letter: string) => + `${letter}`; + return ` +
+
git
+
+
${dot(r.states.success, "A")}added.ts
+
${dot(r.accent.primary, "M")}changed.ts
+
${dot(r.states.danger, "D")}removed.ts
+
${dot(r.states.merge, "C")}conflict.ts
+
+
+
+ "inserted line"
+
- "deleted line"
+
+
+ const + total = + sum(42); + // note +
+
+ ✓ 12 passed + ✗ 3 failed + ⚠ 1 warning +
+
`; +} + +const CVD_LABEL: Record = { + protan: "protanopia", + deutan: "deuteranopia", + tritan: "tritanopia", +}; + +function section(v: View): string { + const sim = simulateRoles(v.roles, v.cvd); + const roleList: [string, (r: Roles) => string][] = [ + ["success (added)", (r) => r.states.success], + ["danger (deleted)", (r) => r.states.danger], + ["warn", (r) => r.states.warn], + ["info", (r) => r.states.info], + ["merge", (r) => r.states.merge], + ["accent", (r) => r.accent.primary], + ["ansi.red", (r) => r.ansi.red], + ["ansi.green", (r) => r.ansi.green], + ["string", (r) => r.syntax.string], + ["keyword", (r) => r.syntax.keyword], + ["variable", (r) => r.syntax.variable], + ["func", (r) => r.syntax.func], + ]; + const swatches = (r: Roles) => roleList.map(([n, sel]) => swatch(n, sel(r))).join(""); + return ` +
+

${v.title} ${v.type} · simulated as ${CVD_LABEL[v.cvd]}

+
+
+

Colors as defined

+
${swatches(v.roles)}
+ ${mock(v.roles)} +
+
+

Simulated (${CVD_LABEL[v.cvd]})

+
${swatches(sim)}
+ ${mock(sim)} +
+
+
`; +} + +/** Render the CVD normal-vs-simulated proof sheet as a standalone HTML document. */ +function renderCvdHtml(): string { + return ` +Pierre CVD Themes + + +
+

Pierre CVD Themes — proof sheet

+

Left = the colors as defined in the theme. Right = the same colors pushed through + the Machado-2009 simulation for that deficiency. If the design holds, the right column + still reads as added-vs-deleted, pass-vs-fail, and error-vs-warning. + Objective ΔE/contrast checks live in test/cvd.test.ts (run via npm test).

+
+
+ ${VIEWS.map(section).join("\n")} +
+ +`; +} + +export const cvd = { + filename: "cvd.html", + render: renderCvdHtml, +}; diff --git a/src/previews/p3.ts b/src/previews/p3.ts new file mode 100644 index 0000000..f4afdcf --- /dev/null +++ b/src/previews/p3.ts @@ -0,0 +1,111 @@ +// Builds preview/p3.html: a compact comparison of basic and enhanced Display P3 +// conversions for representative Pierre palette colors. +import { srgbHexToP3Color } from "../color"; + +const testColors = [ + { name: "Blue", srgb: "#008cff" }, + { name: "Green", srgb: "#0dbe4e" }, + { name: "Red", srgb: "#ff2e3f" }, + { name: "Purple", srgb: "#c635e4" }, + { name: "Pink", srgb: "#fc2b73" }, + { name: "Orange", srgb: "#fe8c2c" }, + { name: "Cyan", srgb: "#08c0ef" }, + { name: "Teal", srgb: "#00c5d2" }, +]; + +function renderP3Html(): string { + const rows = testColors.map(({ name, srgb }) => { + const basic = srgbHexToP3Color(srgb, false); + const enhanced = srgbHexToP3Color(srgb, true); + return ` + ${name} + ${srgb} + ${basic} + ${enhanced} + `; + }).join("\n"); + + return ` + + + + Pierre Display P3 Preview + + + +
+
+

Pierre Display P3 Preview

+

Basic conversion maps sRGB into Display P3. Enhanced conversion applies the + saturation and luminance boost used by the vibrant theme roles.

+
+ + + + + + + + + + +${rows} + +
ColorsRGBDisplay P3 basicDisplay P3 enhanced
+
+ + +`; +} + +export const p3 = { + filename: "p3.html", + render: renderP3Html, +}; diff --git a/src/palette-preview.ts b/src/previews/palette.ts similarity index 88% rename from src/palette-preview.ts rename to src/previews/palette.ts index eff72cb..d0846f7 100644 --- a/src/palette-preview.ts +++ b/src/previews/palette.ts @@ -1,10 +1,9 @@ -// src/palette-preview.ts -// Generates preview/palette.html — a swatch sheet of every palette in palette.ts. -import { writeFileSync, mkdirSync } from "node:fs"; -import { palettes } from "./palette"; - -mkdirSync("preview", { recursive: true }); +// Builds the palette swatch sheet (every scale in palettes.ts) and returns it as +// HTML. Writing to disk is done by scripts/createPreviews.ts. +import { palettes } from "../palettes"; +/** Render the palette swatch sheet as a standalone HTML document. */ +function renderPaletteHtml(): string { const sections = Object.entries(palettes) .map(([name, scale]) => { // JS reorders integer-indexed keys ahead of string keys, which would move @@ -146,5 +145,10 @@ ${sections} `; -writeFileSync("preview/palette.html", html, "utf8"); -console.log("Wrote preview/palette.html"); + return html; +} + +export const palette = { + filename: "palette.html", + render: renderPaletteHtml, +}; diff --git a/src/roles/Roles.ts b/src/roles/Roles.ts new file mode 100644 index 0000000..d884cbc --- /dev/null +++ b/src/roles/Roles.ts @@ -0,0 +1,33 @@ +export type Roles = { + bg: { + editor: string; // main editor background (brightest in light, darkest in dark) + window: string; // sidebar, activity bar, status bar, title bar, inactive tabs + inset: string; // inputs, dropdowns + elevated: string; // panels, hover backgrounds + }; + fg: { base: string; fg1: string; fg2: string; fg3: string; fg4: string }; + border: { + window: string; // borders for sidebar, activity bar, status bar, title bar + editor: string; // general editor borders + indentGuide: string; // indent guide lines + indentGuideActive: string; // active indent guide line + inset: string; // borders for inputs, dropdowns + elevated: string; // borders for panels + }; + accent: { primary: string; link: string; subtle: string; contrastOnAccent: string }; + states: { merge: string, success: string; danger: string; warn: string; info: string }; + syntax: { + comment: string; string: string; number: string; keyword: string; + regexp: string; func: string; type: string; variable: string; + // Extended token types + operator: string; punctuation: string; constant: string; + parameter: string; namespace: string; decorator: string; + escape: string; invalid: string; tag: string; attribute: string; + }; + ansi: { + black: string; red: string; green: string; yellow: string; + blue: string; magenta: string; cyan: string; white: string; + brightBlack: string; brightRed: string; brightGreen: string; brightYellow: string; + brightBlue: string; brightMagenta: string; brightCyan: string; brightWhite: string; + }; +}; diff --git a/src/roles/dark.ts b/src/roles/dark.ts new file mode 100644 index 0000000..303dbd5 --- /dev/null +++ b/src/roles/dark.ts @@ -0,0 +1,79 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const dark: Roles = { + bg: { + editor: neutral["1040"], + window: neutral["1000"], + inset: neutral["980"], + elevated: neutral["1020"] + }, + fg: { + base: neutral["020"], + fg1: neutral["200"], + fg2: neutral["400"], + fg3: neutral["600"], + fg4: neutral["700"] + }, + border: { + window: neutral["1040"], + editor: neutral["980"], + indentGuide: neutral["980"], + indentGuideActive: neutral["960"], + inset: neutral["980"], + elevated: neutral["980"] + }, + accent: { + primary: blue["500"], + link: blue["500"], + subtle: blue["950"], + contrastOnAccent: neutral["1040"] + }, + states: { + merge: indigo["500"], + success: jade["500"], + danger: red["500"], + warn: yellow["500"], + info: cyan["500"] + }, + syntax: { + comment: neutral["600"], + string: green["400"], + number: cyan["400"], + keyword: pink["400"], + regexp: teal["400"], + func: indigo["400"], + type: purple["400"], + variable: orange["400"], + // Extended token types + operator: cyan["500"], + punctuation: neutral["700"], + constant: yellow["400"], + parameter: neutral["400"], + namespace: amber["500"], + decorator: blue["400"], + escape: mint["400"], + invalid: neutral["020"], + tag: vermillion["400"], + attribute: jade["400"] + }, + ansi: { + black: neutral["1000"], + red: red["500"], + green: green["500"], + yellow: yellow["500"], + blue: blue["500"], + magenta: magenta["500"], + cyan: cyan["500"], + white: neutral["300"], + brightBlack: neutral["1000"], + brightRed: red["500"], + brightGreen: lime["500"], + brightYellow: yellow["500"], + brightBlue: blue["500"], + brightMagenta: magenta["500"], + brightCyan: cyan["500"], + brightWhite: neutral["300"] + } +}; diff --git a/src/roles/darkSoft.ts b/src/roles/darkSoft.ts new file mode 100644 index 0000000..01b5ceb --- /dev/null +++ b/src/roles/darkSoft.ts @@ -0,0 +1,79 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const darkSoft: Roles = { + bg: { + editor: neutral["1000"], + window: neutral["1020"], + inset: neutral["960"], + elevated: neutral["980"] + }, + fg: { + base: neutral["200"], + fg1: neutral["300"], + fg2: neutral["500"], + fg3: neutral["700"], + fg4: neutral["800"] + }, + border: { + window: neutral["980"], + editor: neutral["940"], + indentGuide: neutral["960"], + indentGuideActive: neutral["940"], + inset: neutral["940"], + elevated: neutral["960"] + }, + accent: { + primary: blue["400"], + link: blue["400"], + subtle: blue["900"], + contrastOnAccent: neutral["1000"] + }, + states: { + merge: indigo["400"], + success: jade["400"], + danger: red["400"], + warn: yellow["400"], + info: cyan["400"] + }, + syntax: { + comment: neutral["700"], + string: green["300"], + number: cyan["300"], + keyword: pink["300"], + regexp: teal["300"], + func: indigo["300"], + type: purple["300"], + variable: orange["300"], + // Extended token types + operator: cyan["400"], + punctuation: neutral["600"], + constant: yellow["300"], + parameter: neutral["500"], + namespace: amber["400"], + decorator: blue["300"], + escape: mint["300"], + invalid: neutral["200"], + tag: vermillion["300"], + attribute: jade["300"] + }, + ansi: { + black: neutral["1000"], + red: red["500"], + green: green["500"], + yellow: yellow["500"], + blue: blue["500"], + magenta: magenta["500"], + cyan: cyan["500"], + white: neutral["300"], + brightBlack: neutral["1000"], + brightRed: red["500"], + brightGreen: lime["500"], + brightYellow: yellow["500"], + brightBlue: blue["500"], + brightMagenta: magenta["500"], + brightCyan: cyan["500"], + brightWhite: neutral["300"] + } +}; diff --git a/src/roles/index.ts b/src/roles/index.ts new file mode 100644 index 0000000..ef2f616 --- /dev/null +++ b/src/roles/index.ts @@ -0,0 +1,9 @@ +export type { Roles } from "./Roles"; +export { light } from "./light"; +export { lightSoft } from "./lightSoft"; +export { dark } from "./dark"; +export { darkSoft } from "./darkSoft"; +export { protanDeutanLight } from "./protanDeutanLight"; +export { protanDeutanDark } from "./protanDeutanDark"; +export { tritanopiaLight } from "./tritanopiaLight"; +export { tritanopiaDark } from "./tritanopiaDark"; diff --git a/src/roles/light.ts b/src/roles/light.ts new file mode 100644 index 0000000..dfd8f81 --- /dev/null +++ b/src/roles/light.ts @@ -0,0 +1,80 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const light: Roles = { + bg: { + editor: "#ffffff", + window: neutral["060"], + inset: neutral["080"], + elevated: neutral["040"] + }, + fg: { + base: neutral["1040"], + fg1: neutral["900"], + fg2: neutral["800"], + fg3: neutral["600"], + fg4: neutral["500"] + }, + border: { + window: neutral["100"], + editor: neutral["200"], + indentGuide: neutral["100"], + indentGuideActive: neutral["200"], + inset: neutral["200"], + elevated: neutral["100"] + }, + accent: { + primary: blue["500"], + link: blue["500"], + subtle: blue["100"], + contrastOnAccent: "#ffffff" + }, + states: { + merge: indigo["600"], + success: jade["600"], + danger: red["600"], + warn: yellow["600"], + info: cyan["600"] + }, + syntax: { + comment: neutral["600"], + string: green["600"], + number: cyan["600"], + keyword: pink["600"], + regexp: teal["600"], + func: indigo["600"], + type: purple["600"], + variable: orange["600"], + // Extended token types + operator: cyan["500"], + punctuation: neutral["700"], + constant: yellow["600"], + parameter: neutral["700"], + namespace: amber["600"], + decorator: blue["600"], + escape: mint["600"], + invalid: neutral["1040"], + tag: vermillion["600"], + attribute: jade["600"] + }, + ansi: { + black: neutral["980"], + red: red["600"], + green: jade["600"], + yellow: yellow["600"], + blue: blue["600"], + magenta: magenta["600"], + cyan: cyan["600"], + white: neutral["300"], + // make bright colors match the non-bright counterparts + brightBlack: neutral["980"], + brightRed: red["600"], + brightGreen: lime["600"], + brightYellow: yellow["600"], + brightBlue: blue["600"], + brightMagenta: magenta["600"], + brightCyan: cyan["600"], + brightWhite: neutral["300"] + } +}; diff --git a/src/roles/lightSoft.ts b/src/roles/lightSoft.ts new file mode 100644 index 0000000..f11f2a7 --- /dev/null +++ b/src/roles/lightSoft.ts @@ -0,0 +1,79 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const lightSoft: Roles = { + bg: { + editor: "#ffffff", + window: neutral["040"], + inset: neutral["060"], + elevated: neutral["020"] + }, + fg: { + base: neutral["800"], + fg1: neutral["700"], + fg2: neutral["600"], + fg3: neutral["500"], + fg4: neutral["400"] + }, + border: { + window: neutral["080"], + editor: neutral["100"], + indentGuide: neutral["080"], + indentGuideActive: neutral["100"], + inset: neutral["200"], + elevated: neutral["100"] + }, + accent: { + primary: blue["500"], + link: blue["500"], + subtle: blue["100"], + contrastOnAccent: "#ffffff" + }, + states: { + merge: indigo["500"], + success: jade["500"], + danger: red["500"], + warn: yellow["500"], + info: cyan["500"] + }, + syntax: { + comment: neutral["500"], + string: green["500"], + number: cyan["500"], + keyword: pink["400"], + regexp: teal["500"], + func: indigo["400"], + type: purple["400"], + variable: orange["500"], + // Extended token types + operator: cyan["400"], + punctuation: neutral["600"], + constant: yellow["500"], + parameter: neutral["600"], + namespace: amber["500"], + decorator: blue["400"], + escape: mint["500"], + invalid: neutral["1000"], + tag: vermillion["500"], + attribute: jade["500"] + }, + ansi: { + black: neutral["980"], + red: red["500"], + green: green["500"], + yellow: yellow["500"], + blue: blue["500"], + magenta: magenta["500"], + cyan: cyan["500"], + white: neutral["300"], + brightBlack: neutral["980"], + brightRed: red["500"], + brightGreen: lime["500"], + brightYellow: yellow["500"], + brightBlue: blue["500"], + brightMagenta: magenta["500"], + brightCyan: cyan["500"], + brightWhite: neutral["300"] + } +}; diff --git a/src/roles/protanDeutanDark.ts b/src/roles/protanDeutanDark.ts new file mode 100644 index 0000000..5d4b764 --- /dev/null +++ b/src/roles/protanDeutanDark.ts @@ -0,0 +1,61 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +import { dark } from "./dark"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const protanDeutanDark: Roles = { + bg: dark.bg, + fg: dark.fg, + border: dark.border, + accent: { + primary: blue["500"], + link: blue["500"], + subtle: blue["950"], + contrastOnAccent: neutral["1040"] + }, + states: { + success: blue["300"], // added → light blue (luminance-split from accent blue 500) + danger: orange["500"], // deleted/error → orange (deeper stop widens the luminance gap from warn yellow) + warn: yellow["300"], // bright caution yellow + info: cyan["400"], // cool side + merge: violet["400"] // blue-violet + }, + syntax: { + comment: neutral["600"], + string: blue["300"], // = diff inserted → blue + number: cyan["300"], + keyword: violet["400"], + regexp: cyan["400"], + func: indigo["300"], + type: purple["300"], + variable: orange["400"], // orange pole + operator: cyan["500"], + punctuation: neutral["700"], + constant: amber["300"], + parameter: neutral["400"], + namespace: amber["400"], + decorator: blue["400"], + escape: teal["400"], + invalid: neutral["020"], + tag: orange["400"], // = diff deleted → orange + attribute: amber["400"] + }, + ansi: { + black: neutral["1000"], + red: orange["400"], + green: blue["400"], + yellow: yellow["400"], + blue: blue["500"], + magenta: violet["400"], + cyan: cyan["400"], + white: neutral["300"], + brightBlack: neutral["1000"], + brightRed: orange["300"], + brightGreen: blue["300"], + brightYellow: yellow["300"], + brightBlue: blue["400"], + brightMagenta: violet["300"], + brightCyan: cyan["300"], + brightWhite: neutral["300"] + } +}; diff --git a/src/roles/protanDeutanLight.ts b/src/roles/protanDeutanLight.ts new file mode 100644 index 0000000..cd289d4 --- /dev/null +++ b/src/roles/protanDeutanLight.ts @@ -0,0 +1,61 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +import { light } from "./light"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const protanDeutanLight: Roles = { + bg: light.bg, + fg: light.fg, + border: light.border, + accent: { + primary: blue["500"], // keep Pierre blue (brand). Intrinsically bright → + link: blue["500"], // contrast is report-only in the gate, like base Pierre. + subtle: blue["100"], + contrastOnAccent: "#ffffff" + }, + states: { + success: blue["700"], // added/positive → blue pole (diff-add bg, git "A") + danger: orange["700"], // deleted/error → orange pole (diff-del bg, git "D") + warn: yellow["500"], // bright "caution" yellow; ΔE-separated from danger by big luminance gap + info: cyan["700"], // cool side; pairs against merge in the conflict view + merge: violet["800"] // blue-violet conflict color; deep stop widens the luminance split from info + }, + syntax: { + comment: neutral["600"], // neutral — luminance only + string: blue["800"], // = diff "inserted" text → deep blue (≥8 ΔE from keyword) + number: cyan["700"], // cool side + keyword: violet["600"], // blue-violet + regexp: cyan["700"], + func: indigo["700"], // deep blue-violet + type: purple["600"], // reads blue-violet under red-green CVD + variable: orange["700"], // orange pole — workhorse identifier (deep stop clears 3:1 after simulation) + operator: cyan["700"], + punctuation: neutral["700"], + constant: amber["700"], // orange side, deep + parameter: neutral["700"], + namespace: amber["700"], + decorator: blue["700"], + escape: teal["700"], + invalid: neutral["1040"], + tag: orange["700"], // = diff "deleted" text → orange pole + attribute: amber["700"] + }, + ansi: { + black: neutral["980"], + red: orange["700"], // terminal "error red" → orange so red≠green + green: blue["700"], // terminal "success green" → blue + yellow: yellow["500"], + blue: blue["600"], + magenta: violet["600"], + cyan: cyan["700"], + white: neutral["300"], + brightBlack: neutral["980"], + brightRed: orange["600"], + brightGreen: blue["600"], + brightYellow: yellow["500"], + brightBlue: blue["500"], + brightMagenta: violet["500"], + brightCyan: cyan["600"], + brightWhite: neutral["300"] + } +}; diff --git a/src/roles/tritanopiaDark.ts b/src/roles/tritanopiaDark.ts new file mode 100644 index 0000000..04ee85d --- /dev/null +++ b/src/roles/tritanopiaDark.ts @@ -0,0 +1,61 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +import { dark } from "./dark"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const tritanopiaDark: Roles = { + bg: dark.bg, + fg: dark.fg, + border: dark.border, + accent: { + primary: blue["500"], + link: blue["500"], + subtle: blue["950"], + contrastOnAccent: neutral["1040"] + }, + states: { + success: teal["300"], // added → teal + danger: vermillion["400"],// deleted/error → red + warn: amber["400"], // caution + info: blue["400"], // cyan side + merge: magenta["400"] // reddish-purple + }, + syntax: { + comment: neutral["600"], + string: teal["300"], // = diff inserted → teal + number: blue["400"], + keyword: purple["400"], // reddish-purple (≥8 ΔE from red variable) + regexp: teal["400"], + func: blue["300"], + type: magenta["400"], + variable: vermillion["400"], // red pole + operator: teal["500"], + punctuation: neutral["700"], + constant: amber["300"], + parameter: neutral["400"], + namespace: vermillion["400"], + decorator: blue["400"], + escape: teal["400"], + invalid: neutral["020"], + tag: vermillion["400"], // = diff deleted → red + attribute: teal["400"] + }, + ansi: { + black: neutral["1000"], + red: vermillion["400"], + green: teal["400"], + yellow: amber["400"], + blue: blue["400"], + magenta: magenta["400"], + cyan: teal["300"], + white: neutral["300"], + brightBlack: neutral["1000"], + brightRed: vermillion["300"], + brightGreen: teal["300"], + brightYellow: amber["300"], + brightBlue: blue["300"], + brightMagenta: magenta["300"], + brightCyan: teal["300"], + brightWhite: neutral["300"] + } +}; diff --git a/src/roles/tritanopiaLight.ts b/src/roles/tritanopiaLight.ts new file mode 100644 index 0000000..6c2f80a --- /dev/null +++ b/src/roles/tritanopiaLight.ts @@ -0,0 +1,61 @@ +import type { Roles } from "./Roles"; +import { palettes } from "../palettes"; +import { light } from "./light"; +const { gray, neutral, red, vermillion, orange, amber, yellow, lime, green, jade, mint, teal, cyan, blue, indigo, violet, purple, magenta, pink, rose, brown } = palettes; + +export const tritanopiaLight: Roles = { + bg: light.bg, + fg: light.fg, + border: light.border, + accent: { + primary: blue["500"], // keep Pierre blue (reads cyan-blue, clearly ≠ red) + link: blue["500"], + subtle: blue["100"], + contrastOnAccent: "#ffffff" + }, + states: { + success: teal["700"], // added/positive → teal (cyan pole) + danger: vermillion["600"],// deleted/error → red (red pole preserved under tritanopia) + warn: amber["500"], // caution; brighter stop widens the luminance gap from danger vermillion (report-only contrast) + info: blue["600"], // cyan side + merge: magenta["700"] // reddish-purple — tritan-safe, far from blue/teal AND from vermillion + }, + syntax: { + comment: neutral["600"], + string: teal["700"], // = diff inserted → teal (cyan pole) + number: blue["600"], // cyan side + keyword: purple["600"], // reddish-purple (≥8 ΔE from red variable) + regexp: teal["700"], + func: blue["700"], // deep blue + type: magenta["600"], // reddish-purple + variable: vermillion["700"], // red pole — workhorse identifier + operator: teal["700"], + punctuation: neutral["700"], + constant: amber["700"], + parameter: neutral["700"], + namespace: vermillion["600"], + decorator: blue["600"], + escape: teal["700"], + invalid: neutral["1040"], + tag: vermillion["600"], // = diff deleted → red pole + attribute: teal["700"] + }, + ansi: { + black: neutral["980"], + red: vermillion["600"], // red preserved + green: teal["700"], // success green → teal so red≠green + yellow: amber["600"], + blue: blue["600"], + magenta: magenta["700"], + cyan: teal["600"], + white: neutral["300"], + brightBlack: neutral["980"], + brightRed: vermillion["500"], + brightGreen: teal["600"], + brightYellow: amber["500"], + brightBlue: blue["500"], + brightMagenta: magenta["600"], + brightCyan: teal["500"], + brightWhite: neutral["300"] + } +}; diff --git a/src/test.ts b/src/test.ts deleted file mode 100644 index 4ebbaa2..0000000 --- a/src/test.ts +++ /dev/null @@ -1,301 +0,0 @@ -// src/test.ts -import { readFileSync, existsSync } from "node:fs"; -import { light as rolesLight, dark as rolesDark } from "./palette"; -import { makeTheme } from "./theme"; - -// Color tracking for detecting undefined values -const usedColors = new Set(); - -// Helper functions -function isValidHexColor(color: string): boolean { - // Match #RGB, #RRGGBB, #RRGGBBAA formats - return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(color); -} - -function isValidP3Color(color: string): boolean { - // Match color(display-p3 r g b) or color(display-p3 r g b / alpha) - return /^color\(display-p3\s+[\d.]+\s+[\d.]+\s+[\d.]+(\s+\/\s+[\d.]+)?\)$/.test(color); -} - -function isValidColor(color: string): boolean { - return isValidHexColor(color) || isValidP3Color(color); -} - -function collectColors(obj: any, path = ""): string[] { - const issues: string[] = []; - - for (const [key, value] of Object.entries(obj)) { - const currentPath = path ? `${path}.${key}` : key; - - if (typeof value === "string") { - usedColors.add(value); - if (value.startsWith("#") || value.startsWith("color(")) { - if (!isValidColor(value)) { - issues.push(`Invalid color at ${currentPath}: ${value}`); - } - } - } else if (typeof value === "object" && value !== null) { - issues.push(...collectColors(value, currentPath)); - } - } - - return issues; -} - -function testThemeGeneration( - expectedName: string, - displayName: string, - themeType: "light" | "dark", - roles: any -) { - console.log(`\n🧪 Testing ${displayName}...`); - const errors: string[] = []; - - try { - const theme = makeTheme({ - name: expectedName, - displayName, - type: themeType, - roles - }); - const themeMetadata = theme as { name?: string; displayName?: string }; - - // Test 1: Required properties exist - if (!themeMetadata.name) errors.push("Missing theme name"); - if (!themeMetadata.displayName) errors.push("Missing theme displayName"); - if (!theme.type) errors.push("Missing theme type"); - if (!theme.colors) errors.push("Missing colors object"); - if (!theme.tokenColors) errors.push("Missing tokenColors array"); - if (!theme.semanticTokenColors) errors.push("Missing semanticTokenColors object"); - - // Test 2: Theme metadata uses package-safe names plus display labels - if (themeMetadata.name !== expectedName) { - errors.push(`Expected name "${expectedName}" but got "${themeMetadata.name}"`); - } - if (themeMetadata.displayName !== displayName) { - errors.push(`Expected displayName "${displayName}" but got "${themeMetadata.displayName}"`); - } - - // Test 3: Type is correct - if (theme.type !== themeType) { - errors.push(`Expected type "${themeType}" but got "${theme.type}"`); - } - - // Test 4: Critical editor colors exist - const criticalColors = [ - "editor.background", - "editor.foreground", - "foreground", - "focusBorder", - "sideBar.background", - "activityBar.background", - "statusBar.background" - ]; - - for (const key of criticalColors) { - if (!theme.colors[key]) { - errors.push(`Missing critical color: ${key}`); - } - } - - // Test 5: Validate all color values - const colorIssues = collectColors(theme.colors); - errors.push(...colorIssues); - - // Test 6: Check for undefined/null values in colors - for (const [key, value] of Object.entries(theme.colors)) { - if (value === undefined || value === null) { - errors.push(`Color "${key}" is ${value}`); - } - } - - // Test 7: TokenColors should be an array with entries - if (!Array.isArray(theme.tokenColors)) { - errors.push("tokenColors is not an array"); - } else if (theme.tokenColors.length === 0) { - errors.push("tokenColors array is empty"); - } - - // Test 8: Validate tokenColors structure - theme.tokenColors.forEach((token, idx) => { - if (!token.scope) { - errors.push(`tokenColors[${idx}] missing scope`); - } - if (!token.settings) { - errors.push(`tokenColors[${idx}] missing settings`); - } else if (token.settings.foreground) { - usedColors.add(token.settings.foreground); - if (!isValidColor(token.settings.foreground)) { - errors.push(`tokenColors[${idx}] has invalid foreground color: ${token.settings.foreground}`); - } - } - }); - - // Test 9: Semantic tokens validation - for (const [key, value] of Object.entries(theme.semanticTokenColors)) { - if (typeof value === "string") { - usedColors.add(value); - if (!isValidColor(value)) { - errors.push(`semanticTokenColors["${key}"] has invalid color: ${value}`); - } - } else if (typeof value === "object" && value !== null) { - const semanticValue = value as any; - if (semanticValue.foreground) { - usedColors.add(semanticValue.foreground); - if (!isValidColor(semanticValue.foreground)) { - errors.push(`semanticTokenColors["${key}"].foreground has invalid color: ${semanticValue.foreground}`); - } - } - } - } - - if (errors.length === 0) { - console.log(`✅ ${displayName} passed all checks`); - return true; - } else { - console.error(`❌ ${displayName} failed with ${errors.length} error(s):`); - errors.forEach(err => console.error(` - ${err}`)); - return false; - } - } catch (error) { - console.error(`❌ ${displayName} threw an error:`, error); - return false; - } -} - -function testGeneratedFiles() { - console.log("\n🧪 Testing generated theme files..."); - const errors: string[] = []; - - const files = [ - { path: "themes/pierre-light.json", expectedType: "light", expectedName: "pierre-light", expectedDisplayName: "Pierre Light" }, - { path: "themes/pierre-light-soft.json", expectedType: "light", expectedName: "pierre-light-soft", expectedDisplayName: "Pierre Light Soft" }, - { path: "themes/pierre-dark.json", expectedType: "dark", expectedName: "pierre-dark", expectedDisplayName: "Pierre Dark" }, - { path: "themes/pierre-dark-soft.json", expectedType: "dark", expectedName: "pierre-dark-soft", expectedDisplayName: "Pierre Dark Soft" }, - { path: "themes/pierre-light-vibrant.json", expectedType: "light", expectedName: "pierre-light-vibrant", expectedDisplayName: "Pierre Light Vibrant" }, - { path: "themes/pierre-dark-vibrant.json", expectedType: "dark", expectedName: "pierre-dark-vibrant", expectedDisplayName: "Pierre Dark Vibrant" } - ]; - - for (const { path, expectedType, expectedName, expectedDisplayName } of files) { - // Test 1: File exists - if (!existsSync(path)) { - errors.push(`File does not exist: ${path}`); - continue; - } - - try { - // Test 2: File is valid JSON - const content = readFileSync(path, "utf8"); - if (content.trim() === "") { - errors.push(`File is empty: ${path}`); - continue; - } - - const theme = JSON.parse(content); - - // Test 3: Has required structure - if (!theme.name) errors.push(`${path}: Missing name`); - if (!theme.displayName) errors.push(`${path}: Missing displayName`); - if (theme.name !== expectedName) { - errors.push(`${path}: Expected name "${expectedName}" but got "${theme.name}"`); - } - if (theme.displayName !== expectedDisplayName) { - errors.push(`${path}: Expected displayName "${expectedDisplayName}" but got "${theme.displayName}"`); - } - if (!theme.type) errors.push(`${path}: Missing type`); - if (theme.type !== expectedType) { - errors.push(`${path}: Expected type "${expectedType}" but got "${theme.type}"`); - } - if (!theme.colors || Object.keys(theme.colors).length === 0) { - errors.push(`${path}: Missing or empty colors object`); - } - if (!Array.isArray(theme.tokenColors) || theme.tokenColors.length === 0) { - errors.push(`${path}: Missing or empty tokenColors array`); - } - - console.log(`✅ ${path} is valid`); - } catch (error) { - errors.push(`${path}: Invalid JSON - ${error}`); - } - } - - if (errors.length > 0) { - console.error(`❌ Generated files validation failed:`); - errors.forEach(err => console.error(` - ${err}`)); - return false; - } - - console.log("✅ All generated files are valid"); - return true; -} - -function testPaletteRoles() { - console.log("\n🧪 Testing palette roles..."); - const errors: string[] = []; - - function validateRoles(roles: any, name: string) { - // Check all required role categories exist - const requiredCategories = ["bg", "fg", "border", "accent", "states", "syntax", "ansi"]; - for (const category of requiredCategories) { - if (!roles[category]) { - errors.push(`${name}: Missing "${category}" category`); - } - } - - // Validate that all role values are hex colors - function checkRoleColors(obj: any, path: string) { - for (const [key, value] of Object.entries(obj)) { - const fullPath = `${path}.${key}`; - if (typeof value === "string") { - if (!isValidHexColor(value)) { - errors.push(`${name}.${fullPath}: Invalid color "${value}"`); - } - } else if (typeof value === "object" && value !== null) { - checkRoleColors(value, fullPath); - } - } - } - - checkRoleColors(roles, name); - } - - validateRoles(rolesLight, "light"); - validateRoles(rolesDark, "dark"); - - if (errors.length > 0) { - console.error(`❌ Palette roles validation failed:`); - errors.forEach(err => console.error(` - ${err}`)); - return false; - } - - console.log("✅ Palette roles are valid"); - return true; -} - -// Run all tests -console.log("🚀 Running Pierre Theme Tests\n"); -console.log("=" .repeat(50)); - -let allPassed = true; - -// Test palette roles first -allPassed = testPaletteRoles() && allPassed; - -// Test theme generation -allPassed = testThemeGeneration("pierre-light", "Pierre Light", "light", rolesLight) && allPassed; -allPassed = testThemeGeneration("pierre-dark", "Pierre Dark", "dark", rolesDark) && allPassed; - -// Test generated files (only if they exist - they should after build) -allPassed = testGeneratedFiles() && allPassed; - -// Summary -console.log("\n" + "=".repeat(50)); -console.log(`\n📊 Total unique colors used: ${usedColors.size}`); - -if (allPassed) { - console.log("\n✅ All tests passed!"); - process.exit(0); -} else { - console.log("\n❌ Some tests failed!"); - process.exit(1); -} diff --git a/test/build.test.ts b/test/build.test.ts new file mode 100644 index 0000000..b52aad1 --- /dev/null +++ b/test/build.test.ts @@ -0,0 +1,105 @@ +/** + * Guards the build *output* rather than theme design. After `npm run build` writes + * themes/*.json, this checks each expected file exists and carries the right + * metadata — catching build-step regressions (a missing, empty, or misnamed file). + */ +import { describe, test } from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync, existsSync } from "node:fs"; + +type GeneratedFile = { path: string; expectedType: "light" | "dark"; expectedName: string; expectedDisplayName: string }; + +const GENERATED_FILES: GeneratedFile[] = [ + { + path: "themes/pierre-light.json", + expectedType: "light", + expectedName: "pierre-light", + expectedDisplayName: "Pierre Light" + }, + { + path: "themes/pierre-light-protanopia-deuteranopia.json", + expectedType: "light", + expectedName: "pierre-light-protanopia-deuteranopia", + expectedDisplayName: "Pierre Light Protanopia & Deuteranopia" + }, + { + path: "themes/pierre-light-soft.json", + expectedType: "light", + expectedName: "pierre-light-soft", + expectedDisplayName: "Pierre Light Soft" + }, + { + path: "themes/pierre-light-tritanopia.json", + expectedType: "light", + expectedName: "pierre-light-tritanopia", + expectedDisplayName: "Pierre Light Tritanopia" + }, + { + path: "themes/pierre-light-vibrant.json", + expectedType: "light", + expectedName: "pierre-light-vibrant", + expectedDisplayName: "Pierre Light Vibrant" + }, + { + path: "themes/pierre-dark.json", + expectedType: "dark", + expectedName: "pierre-dark", + expectedDisplayName: "Pierre Dark" + }, + { + path: "themes/pierre-dark-protanopia-deuteranopia.json", + expectedType: "dark", + expectedName: "pierre-dark-protanopia-deuteranopia", + expectedDisplayName: "Pierre Dark Protanopia & Deuteranopia" + }, + { + path: "themes/pierre-dark-soft.json", + expectedType: "dark", + expectedName: "pierre-dark-soft", + expectedDisplayName: "Pierre Dark Soft" + }, + { + path: "themes/pierre-dark-tritanopia.json", + expectedType: "dark", + expectedName: "pierre-dark-tritanopia", + expectedDisplayName: "Pierre Dark Tritanopia" + }, + { + path: "themes/pierre-dark-vibrant.json", + expectedType: "dark", + expectedName: "pierre-dark-vibrant", + expectedDisplayName: "Pierre Dark Vibrant" + }, +]; + +describe("generated theme files", () => { + for (const file of GENERATED_FILES) { + describe(file.path, () => { + test("exists", () => { + assert.ok(existsSync(file.path), `file does not exist: ${file.path}`); + }); + + test("is non-empty, valid JSON with the expected metadata", () => { + const content = readFileSync(file.path, "utf8"); + assert.notEqual(content.trim(), "", `file is empty: ${file.path}`); + + const theme = JSON.parse(content); + + assert.ok(theme.name, `${file.path}: missing name`); + assert.ok(theme.displayName, `${file.path}: missing displayName`); + assert.equal(theme.name, file.expectedName, `${file.path}: unexpected name`); + assert.equal(theme.displayName, file.expectedDisplayName, `${file.path}: unexpected displayName`); + assert.ok(theme.type, `${file.path}: missing type`); + assert.equal(theme.type, file.expectedType, `${file.path}: unexpected type`); + assert.ok( + theme.colors && Object.keys(theme.colors).length > 0, + `${file.path}: missing or empty colors object` + ); + assert.ok( + Array.isArray(theme.tokenColors) && theme.tokenColors.length > 0, + `${file.path}: missing or empty tokenColors array` + ); + }); + }); + } +}); diff --git a/test/cvd.test.ts b/test/cvd.test.ts new file mode 100644 index 0000000..6123449 --- /dev/null +++ b/test/cvd.test.ts @@ -0,0 +1,300 @@ +/** + * OBJECTIVE GATE for the CVD (Color Vision Deficiency) themes. + * This file turns the design rules from src/roles into machine-checked assertions + * and is run as part of `npm test` (via the node:test runner). It fails the build + * if any Tier-1 or Tier-2 requirement regresses, so the themes cannot silently drift + * into an ambiguous state. + * + * How it works: + * 1. simulate — recolor each role as a protan/deutan/tritan viewer would see it + * (Machado 2009 model), at full dichromacy (severity 1.0). + * 2. distinguishability — for every pair of roles that co-occurs on screen, + * measure the perceptual distance (ΔE₀₀) between the simulated colors. If + * two signals (e.g. "added" vs "deleted") still look far apart, then they can + * be distinguished. ΔE₀₀ > ~10 ≈ "clearly different". + * 3. contrast — WCAG legibility of each foreground vs its background, checked + * both normally and after simulation (simulation shifts luminance). + * + * TIERS + * Graded by what carries the signal when color fails. Under full dichromacy there + * are only ~2 usable hue poles + luminance but ~20 chromatic roles, so not every + * pair can be hue-unique. We gate hardest where color is the only cue, and lean on + * the editor's built-in non-color cues elsewhere. + * • Tier 1 (hard gate, ΔE ≥ 11) — color is the SOLE disambiguator: + * diff add/delete backgrounds (success/danger), diff inserted/deleted TEXT + * (string/tag), merge-conflict backgrounds (merge/info), terminal pass/fail + * (ansi red/green). None of these has a glyph fallback. + * • Tier 2 (hard gate, ΔE ≥ 8) — color PLUS a non-color cue: + * diagnostics (error/warn/info — distinct icon SHAPES), and the + * highest-frequency syntax adjacencies + comment-vs-code. + * • Tier 3 (advisory, reported only) — color is tertiary: + * the git-tree group (every entry already carries an M/A/D/U/C letter + * badge) and extended syntax (bold/italic + position carry it). Reported + * via test diagnostics so regressions stay visible without blocking the build. + */ +import { describe, test } from "node:test"; +import assert from "node:assert/strict"; +import { + protanDeutanLight, + protanDeutanDark, + tritanopiaLight, + tritanopiaDark, + type Roles, +} from "../src/roles"; +import { contrastRatio, cvdSelfChecks, type CVDType } from "../src/color"; +import { simulatedContrast, worstDeltaE, referenceCrossChecks } from "./helpers/cvd"; + +// Thresholds (standards-derived, tuned empirically during build-out) +const TIER1_DELTA_E = 11; // co-occurring opposite-meaning signals +const TIER2_DELTA_E = 8; // critical syntax adjacencies +const TEXT_CONTRAST = 4.5; // WCAG 2.1 SC 1.4.3 normal text +const UI_CONTRAST = 3.0; // WCAG 2.1 SC 1.4.11 UI glyphs / SC 1.4.3 large text + +// The role-color pairs the gate checks +// A Selector plucks one concrete hex from a resolved Roles object, so a RolePair +// names two roles whose simulated colors we then compare. +type Selector = (r: Roles) => string; +type RolePair = { tier: 1 | 2 | 3; label: string; a: Selector; b: Selector; group: string }; + +// Named selectors for every role the gate references, so the pair list below can +// say `selectors.success` instead of repeating `(r) => r.states.success`. +const selectors = { + success: (r: Roles) => r.states.success, + danger: (r: Roles) => r.states.danger, + warn: (r: Roles) => r.states.warn, + info: (r: Roles) => r.states.info, + merge: (r: Roles) => r.states.merge, + accent: (r: Roles) => r.accent.primary, + ansiRed: (r: Roles) => r.ansi.red, + ansiGreen: (r: Roles) => r.ansi.green, + comment: (r: Roles) => r.syntax.comment, + string: (r: Roles) => r.syntax.string, + keyword: (r: Roles) => r.syntax.keyword, + variable: (r: Roles) => r.syntax.variable, + func: (r: Roles) => r.syntax.func, + type: (r: Roles) => r.syntax.type, + number: (r: Roles) => r.syntax.number, + tag: (r: Roles) => r.syntax.tag, // = diff "deleted" text token +}; + +// Expand a group whose members must each be distinguishable from every other into +// one RolePair per unordered combination — e.g. [danger, warn, info] becomes +// danger·warn, danger·info, warn·info. +function allPairsWithin(group: string, tier: 1 | 2 | 3, members: [string, Selector][]): RolePair[] { + const out: RolePair[] = []; + for (let i = 0; i < members.length; i++) { + for (let j = i + 1; j < members.length; j++) { + out.push({ + tier, + group, + label: `${members[i][0]} vs ${members[j][0]}`, + a: members[i][1], + b: members[j][1], + }); + } + } + return out; +} + +// Every role-color pair the gate measures, grouped by tier (see the header for +// what each tier means and why). +const DISTINGUISHABILITY_PAIRS: RolePair[] = [ + // ── Tier 1 — color is the only cue (ΔE ≥ 11) ────────────────────────────── + // Diff gutter / overview ruler: added vs deleted backgrounds (no glyph). + { tier: 1, group: "diff bg", label: "success(added) vs danger(deleted)", a: selectors.success, b: selectors.danger }, + // Diff TEXT tokens: inserted vs deleted, the semantic core of a review. + { tier: 1, group: "diff text", label: "string(inserted) vs tag(deleted)", a: selectors.string, b: selectors.tag }, + // Merge conflict view: current(merge) vs incoming(info) tinted backgrounds. + { tier: 1, group: "merge conflict", label: "merge vs info", a: selectors.merge, b: selectors.info }, + // Terminal pass/fail. + { tier: 1, group: "terminal", label: "ansi.red vs ansi.green", a: selectors.ansiRed, b: selectors.ansiGreen }, + + // ── Tier 2 — color + a non-color cue (ΔE ≥ 8) ───────────────────────────── + // Diagnostics & notifications: error/warn/info — backed by distinct icon + // shapes (✕ / △ / ⓘ), so color is the secondary channel. + ...allPairsWithin("diagnostics", 2, [ + ["danger", selectors.danger], + ["warn", selectors.warn], + ["info", selectors.info], + ]), + // Comment must never be mistaken for live code, so pair it against each token + // kind it sits next to (we only care about comment-vs-X, not X-vs-Y here). + { tier: 2, group: "comment vs code", label: "comment vs string", a: selectors.comment, b: selectors.string }, + { tier: 2, group: "comment vs code", label: "comment vs keyword", a: selectors.comment, b: selectors.keyword }, + { tier: 2, group: "comment vs code", label: "comment vs variable", a: selectors.comment, b: selectors.variable }, + // The three highest-frequency code tokens. + ...allPairsWithin("core syntax", 2, [ + ["keyword", selectors.keyword], + ["string", selectors.string], + ["variable", selectors.variable], + ]), + + // ── Tier 3 (advisory) ───────────────────────────────────────────────────── + // Git tree: added/modified/deleted/conflict — every entry has an M/A/D/U/C + // letter badge, so identical-looking colors are still unambiguous. Reported. + ...allPairsWithin("git tree", 3, [ + ["success", selectors.success], + ["danger", selectors.danger], + ["merge", selectors.merge], + ["accent.primary", selectors.accent], + ]), + ...allPairsWithin("extended syntax", 3, [ + ["func", selectors.func], + ["type", selectors.type], + ["number", selectors.number], + ["keyword", selectors.keyword], + ["string", selectors.string], + ["variable", selectors.variable], + ]), +]; + +// ── Theme registry ────────────────────────────────────────────────────────── +// Each protan/deutan theme must satisfy the gate under BOTH protan and deutan +// simulation; tritanopia themes under tritan. +type CvdThemeDef = { name: string; roles: Roles; cvds: CVDType[] }; +const THEMES: CvdThemeDef[] = [ + { name: "Pierre Light Protanopia & Deuteranopia", roles: protanDeutanLight, cvds: ["protan", "deutan"] }, + { name: "Pierre Dark Protanopia & Deuteranopia", roles: protanDeutanDark, cvds: ["protan", "deutan"] }, + { name: "Pierre Light Tritanopia", roles: tritanopiaLight, cvds: ["tritan"] }, + { name: "Pierre Dark Tritanopia", roles: tritanopiaDark, cvds: ["tritan"] }, +]; + +// ── Tests ───────────────────────────────────────────────────────────────────── + +// Color-science self-checks (prove the simulation/contrast/ΔE math itself). +describe("color-science self-checks (Machado 2009 / WCAG / CIEDE2000)", () => { + for (const c of cvdSelfChecks()) { + test(c.name, () => assert.ok(c.ok, c.detail)); + } +}); + +// Reference cross-validation vs culori (a dev-only oracle; ships nothing). +describe("reference cross-validation vs culori", () => { + for (const r of referenceCrossChecks()) { + test(r.name, () => assert.ok(r.ok, `${r.name}: ${r.detail}`)); + } +}); + +// CONTRAST POLICY. We hold the CVD themes to WCAG bars, but only the bar that fits +// how each color renders — and we do NOT impose a bar the *standard* Pierre themes +// never met (base Pierre LIGHT runs syntax/signal colors at 2–4.5:1 by design; see +// ACCESSIBILITY.md): +// • Body text (editor foreground) → 4.5:1 (SC 1.4.3 normal text) +// • Syntax tokens & meaningful signal colors → 3.0:1 (SC 1.4.11 UI / large text), +// checked NORMAL and AFTER simulation (simulation shifts luminance). +// • Report-only (printed, never fails): intrinsically-bright / brand colors that +// base Pierre itself keeps bright — their *distinguishability* (ΔE) is gated, +// not their raw contrast. +describe("CVD theme gate", () => { + for (const { name, roles, cvds } of THEMES) { + describe(`${name} [simulated as: ${cvds.join(", ")}]`, () => { + const bgEditor = roles.bg.editor; + const bgWindow = roles.bg.window; + + // Contrast (normal + simulated). The simulated check takes the worst case + // across both gamma conventions; backgrounds are near-neutral so they barely + // move, but we simulate them under each convention for correctness. + describe("contrast", () => { + // Syntax tokens are text-on-editor at the 3:1 bar; `invalid` is a + // background tint, not a foreground, so it's excluded (all others gated). + const syntaxForegrounds = Object.entries(roles.syntax).filter(([k]) => k !== "invalid"); + // Signal colors gated at 3:1 (carry meaning): states except the bright + // `warn`, plus the terminal pass/fail pair. + const signalForegrounds: [string, string][] = [ + ["states.success", roles.states.success], + ["states.danger", roles.states.danger], + ["states.info", roles.states.info], + ["states.merge", roles.states.merge], + ["ansi.red", roles.ansi.red], + ["ansi.green", roles.ansi.green], + ]; + + for (const cvd of cvds) { + // Body text — the one role held to the full 4.5:1 text bar. + test(`fg.base on editor — body text ≥ ${TEXT_CONTRAST}:1 (${cvd})`, () => { + const normal = contrastRatio(roles.fg.base, bgEditor); + const sim = simulatedContrast(roles.fg.base, bgEditor, cvd); + assert.ok( + normal >= TEXT_CONTRAST && sim >= TEXT_CONTRAST, + `fg.base on editor — normal ${normal.toFixed(2)}, ${cvd} ${sim.toFixed(2)} (< ${TEXT_CONTRAST})` + ); + }); + + for (const [key, hex] of syntaxForegrounds) { + test(`syntax.${key} on editor ≥ ${UI_CONTRAST}:1 (${cvd})`, () => { + const normal = contrastRatio(hex, bgEditor); + const sim = simulatedContrast(hex, bgEditor, cvd); + assert.ok( + normal >= UI_CONTRAST && sim >= UI_CONTRAST, + `syntax.${key} on editor — normal ${normal.toFixed(2)}, ${cvd} ${sim.toFixed(2)} (< ${UI_CONTRAST})` + ); + }); + } + + for (const [key, hex] of signalForegrounds) { + test(`${key} on window ≥ ${UI_CONTRAST}:1 (${cvd})`, () => { + const normal = contrastRatio(hex, bgWindow); + const sim = simulatedContrast(hex, bgWindow, cvd); + assert.ok( + normal >= UI_CONTRAST && sim >= UI_CONTRAST, + `${key} on window — normal ${normal.toFixed(2)}, ${cvd} ${sim.toFixed(2)} (< ${UI_CONTRAST})` + ); + }); + } + } + + // Report-only: worst contrast seen for the intrinsically-bright / brand + // colors, surfaced as a diagnostic (never fails the build). + test("report-only contrast (intrinsically-bright / brand colors)", (t) => { + const reportOnlyForegrounds: [string, string][] = [ + ["accent.primary", roles.accent.primary], + ["states.warn", roles.states.warn], + ["ansi.yellow", roles.ansi.yellow], + ["ansi.blue", roles.ansi.blue], + ["ansi.cyan", roles.ansi.cyan], + ["ansi.magenta", roles.ansi.magenta], + ]; + const reportOnlyMin: Record = {}; + for (const cvd of cvds) { + for (const [key, hex] of reportOnlyForegrounds) { + const c = Math.min(contrastRatio(hex, bgWindow), simulatedContrast(hex, bgWindow, cvd)); + reportOnlyMin[key] = Math.min(reportOnlyMin[key] ?? Infinity, c); + } + } + t.diagnostic( + Object.entries(reportOnlyMin) + .map(([k, v]) => `${k} ${v.toFixed(2)}`) + .join(", ") + ); + }); + }); + + // Distinguishability under simulation. + describe("distinguishability under simulation", () => { + for (const tier of [1, 2] as const) { + const threshold = tier === 1 ? TIER1_DELTA_E : TIER2_DELTA_E; + describe(`Tier ${tier} (ΔE ≥ ${threshold})`, () => { + for (const p of DISTINGUISHABILITY_PAIRS.filter((p) => p.tier === tier)) { + test(`[${p.group}] ${p.label}`, () => { + const { worst, worstCvd, worstConvention } = worstDeltaE(p.a(roles), p.b(roles), cvds); + assert.ok( + worst >= threshold, + `${p.label} = ΔE ${worst.toFixed(1)} under ${worstCvd}/${worstConvention} (need ≥ ${threshold})` + ); + }); + } + }); + } + + // Tier 3 is advisory: reported via diagnostics so regressions stay visible + // without blocking the build. + test("Tier 3 (advisory — reported, never fails)", (t) => { + for (const p of DISTINGUISHABILITY_PAIRS.filter((p) => p.tier === 3)) { + const { worst, worstCvd, worstConvention } = worstDeltaE(p.a(roles), p.b(roles), cvds); + t.diagnostic(`[${p.group}] ${p.label} — ΔE ${worst.toFixed(1)} (${worstCvd}, ${worstConvention})`); + } + }); + }); + }); + } +}); diff --git a/test/helpers/cvd.ts b/test/helpers/cvd.ts new file mode 100644 index 0000000..76829e7 --- /dev/null +++ b/test/helpers/cvd.ts @@ -0,0 +1,111 @@ +/** + * Color-science utilities shared by the CVD accessibility gate: + * simulate a color as a dichromat sees it, measure WCAG contrast and CIEDE2000 + * separation after simulation, and cross-validate our hand-rolled math against + * culori. + */ +import { simulateCVD, contrastRatio, deltaE2000, type CVDType } from "../../src/color"; +import { + filterDeficiencyProt, filterDeficiencyDeuter, filterDeficiencyTrit, + differenceCiede2000, wcagContrast, formatHex, +} from "culori"; + +// The two common Machado gamma conventions: linear RGB (our implementation) and +// gamma-encoded sRGB (culori / the `colorspace` R package). The gate checks both. +export type SimulationConvention = "linear" | "gamma"; + +const gammaSim: Record unknown> = { + protan: filterDeficiencyProt(1) as unknown as (c: string) => unknown, + deutan: filterDeficiencyDeuter(1) as unknown as (c: string) => unknown, + tritan: filterDeficiencyTrit(1) as unknown as (c: string) => unknown, +}; + +export function simulateForConvention(hex: string, cvd: CVDType, convention: SimulationConvention): string { + if (convention === "linear") return simulateCVD(hex, cvd); + const simulated = formatHex(gammaSim[cvd](hex) as any); + if (!simulated) throw new Error(`culori could not simulate ${hex} for ${cvd}`); + return simulated; +} + +// Worst-case contrast of fg on bg after simulation, across both gamma conventions +// (the same linear + gamma pair the distinguishability check uses). +export function simulatedContrast(fg: string, bg: string, cvd: CVDType): number { + let worst = Infinity; + for (const convention of ["linear", "gamma"] as const) { + worst = Math.min( + worst, + contrastRatio(simulateForConvention(fg, cvd, convention), simulateForConvention(bg, cvd, convention)) + ); + } + return worst; +} + +// Worst-case ΔE for a pair across every CVD type a theme targets and both Machado +// gamma conventions; reports which (cvd, convention) produced the minimum. +export function worstDeltaE(aHex: string, bHex: string, cvds: CVDType[]) { + let worst = Infinity; + let worstCvd: CVDType = cvds[0]; + let worstConvention: SimulationConvention = "linear"; + for (const cvd of cvds) { + for (const convention of ["linear", "gamma"] as const) { + const d = deltaE2000( + simulateForConvention(aHex, cvd, convention), + simulateForConvention(bHex, cvd, convention) + ); + if (d < worst) { + worst = d; + worstCvd = cvd; + worstConvention = convention; + } + } + } + return { worst, worstCvd, worstConvention }; +} + +// Cross-validate our hand-rolled color math against culori (dev-only oracle). We +// keep our own implementation (its CVD simulation uses the more-correct linear-RGB +// convention), but prove the standardized formulas agree with a vetted library: +// contrast and ΔE must match to floating-point noise, and our simulation must +// collapse the same confusable axes culori's does (it differs only in gamma +// convention, by design — see src/color/cvd.ts). +export function referenceCrossChecks(): { name: string; ok: boolean; detail: string }[] { + const ciede = differenceCiede2000(); + // culori parses hex strings at runtime; its types want parsed Color objects, so + // we loosen the signatures here (dev-only oracle). + const samples = [ + "#009fff", "#d52c36", "#199f43", "#ffca00", "#1a85d4", "#d47628", + "#a13cee", "#00c5d2", "#ff5d36", "#737373", "#ffffff", "#0a0a0a", + ]; + + // contrast & ΔE: must match culori to floating-point noise. + let maxC = 0, maxDe = 0; + for (let i = 0; i < samples.length; i++) { + for (let j = i + 1; j < samples.length; j++) { + const a = samples[i], b = samples[j]; + maxC = Math.max(maxC, Math.abs(contrastRatio(a, b) - (wcagContrast(a, b) as number))); + maxDe = Math.max(maxDe, Math.abs(deltaE2000(a, b) - ciede(a, b))); + } + } + + // simulation: differs from culori only in gamma convention, but must collapse + // the same axis — verify each maps the confusable pair to a much smaller ΔE. + const axisOk = (["protan", "deutan", "tritan"] as CVDType[]).every((t) => { + const x = t === "tritan" ? "#009fff" : "#ff2e3f"; // blue (tritan) / red (protan,deutan) + const y = "#199f43"; // green + const before = deltaE2000(x, y); + const ours = deltaE2000(simulateCVD(x, t), simulateCVD(y, t)); + const lib = ciede( + simulateForConvention(x, t, "gamma"), + simulateForConvention(y, t, "gamma") + ); + // Both implementations must collapse the confusable pair to under half its + // un-simulated separation (exact residual differs by gamma convention). + return ours < before * 0.5 && lib < before * 0.5; + }); + + return [ + { name: "contrast matches culori", ok: maxC < 0.01, detail: `max |Δ| ${maxC.toFixed(4)}` }, + { name: "ΔE2000 matches culori", ok: maxDe < 0.1, detail: `max |Δ| ${maxDe.toFixed(4)}` }, + { name: "simulation collapses same axis", ok: axisOk, detail: axisOk ? "ours & culori agree" : "axis mismatch" }, + ]; +} diff --git a/test/theme.test.ts b/test/theme.test.ts new file mode 100644 index 0000000..3b3fb60 --- /dev/null +++ b/test/theme.test.ts @@ -0,0 +1,235 @@ +/** + * Structural validation for the themes: it proves that createTheme produces + * well-formed VS Code themes and that the palette role tables are valid hex. + */ +import { describe, test, after } from "node:test"; +import assert from "node:assert/strict"; +import { + dark as rolesDark, + light as rolesLight, + protanDeutanDark as rolesProtanDeutanDark, + protanDeutanLight as rolesProtanDeutanLight, + tritanopiaDark as rolesTritanopiaDark, + tritanopiaLight as rolesTritanopiaLight, + type Roles, +} from "../src/roles"; +import { createTheme } from "../src/createTheme"; + +// ── Color-string validators (shared across the theme / token / semantic checks) ── +function isValidHexColor(color: string): boolean { + // Match #RGB, #RRGGBB, #RRGGBBAA formats + return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(color); +} + +function isValidColor(color: string): boolean { + // Hex, or a Display-P3 color() — color(display-p3 r g b) with optional / alpha. + return ( + isValidHexColor(color) || + /^color\(display-p3\s+[\d.]+\s+[\d.]+\s+[\d.]+(\s+\/\s+[\d.]+)?\)$/.test(color) + ); +} + +// Every color string the suite touches — surfaced as a diagnostic at the end so +// the palette's breadth stays visible (the old runner printed this total). +const usedColors = new Set(); + +// ── Palette roles ───────────────────────────────────────────────────────────── +const REQUIRED_ROLE_CATEGORIES = ["bg", "fg", "border", "accent", "states", "syntax", "ansi"]; + +const ROLE_SETS: [string, Roles][] = [ + ["dark", rolesDark], + ["light", rolesLight], + ["protanDeutanDark", rolesProtanDeutanDark], + ["protanDeutanLight", rolesProtanDeutanDark], + ["tritanopiaDark", rolesTritanopiaDark], + ["tritanopiaLight", rolesTritanopiaLight], +]; + +describe("palette roles", () => { + for (const [name, roles] of ROLE_SETS) { + describe(name, () => { + test("defines every required role category", () => { + for (const category of REQUIRED_ROLE_CATEGORIES) { + assert.ok((roles as Record)[category], `${name}: missing "${category}" category`); + } + }); + + test("uses only valid hex colors", () => { + // Collect every role-table path whose value is not valid hex. Role tables + // are authored in hex; P3 conversion happens later, at build time. + const issues: string[] = []; + const collectRoleHexIssues = (obj: unknown, path: string) => { + for (const [key, value] of Object.entries(obj as Record)) { + const fullPath = `${path}.${key}`; + if (typeof value === "string") { + if (!isValidHexColor(value)) issues.push(`${fullPath}: invalid color "${value}"`); + } else if (value && typeof value === "object") { + collectRoleHexIssues(value, fullPath); + } + } + }; + collectRoleHexIssues(roles, name); + assert.deepEqual(issues, [], issues.join("\n")); + }); + }); + } +}); + +// ── Theme generation ────────────────────────────────────────────────────────── +const CRITICAL_COLORS = [ + "editor.background", + "editor.foreground", + "foreground", + "focusBorder", + "sideBar.background", + "activityBar.background", + "statusBar.background", +]; + +type ThemeVariant = { name: string; displayName: string; type: "light" | "dark"; roles: Roles }; + +// CVD distinguishability is handled by the gate in cvd.test.ts; here we only +// validate the structure of each generated light/dark variant. +const THEME_VARIANTS: ThemeVariant[] = [ + { + name: "pierre-dark", + displayName: "Pierre Dark", + type: "dark", + roles: rolesDark + }, + { + name: "pierre-dark-protanopia-deuteranopia", + displayName: "Pierre Dark Protanopia & Deuteranopia", + type: "dark", + roles: rolesProtanDeutanDark + }, + { + name: "pierre-dark-tritanopia", + displayName: "Pierre Dark Tritanopia", + type: "dark", + roles: rolesTritanopiaDark + }, + { + name: "pierre-light", + displayName: "Pierre Light", + type: "light", + roles: rolesLight + }, + { + name: "pierre-light-protanopia-deuteranopia", + displayName: "Pierre Light Protanopia & Deuteranopia", + type: "light", + roles: rolesProtanDeutanLight + }, + { + name: "pierre-light-tritanopia", + displayName: "Pierre Light Tritanopia", + type: "light", + roles: rolesTritanopiaLight + }, +]; + +describe("theme generation", () => { + for (const variant of THEME_VARIANTS) { + describe(variant.displayName, () => { + const theme = createTheme({ + name: variant.name, + displayName: variant.displayName, + type: variant.type, + roles: variant.roles, + }); + + test("has the required top-level properties", () => { + assert.ok(theme.name, "missing theme name"); + assert.ok(theme.displayName, "missing theme displayName"); + assert.ok(theme.type, "missing theme type"); + assert.ok(theme.colors, "missing colors object"); + assert.ok(theme.tokenColors, "missing tokenColors array"); + assert.ok(theme.semanticTokenColors, "missing semanticTokenColors object"); + }); + + test("uses the expected package-safe name and display label", () => { + assert.equal(theme.name, variant.name); + assert.equal(theme.displayName, variant.displayName); + }); + + test(`has type "${variant.type}"`, () => { + assert.equal(theme.type, variant.type); + }); + + test("defines the critical editor colors", () => { + for (const key of CRITICAL_COLORS) { + assert.ok(theme.colors[key], `missing critical color: ${key}`); + } + }); + + test("has only valid color values", () => { + // Walk the colors tree: record every color string (for the unique-color + // tally) and flag any malformed #hex / color() value. + const issues: string[] = []; + const collectColorIssues = (obj: unknown, path: string) => { + for (const [key, value] of Object.entries(obj as Record)) { + const currentPath = path ? `${path}.${key}` : key; + if (typeof value === "string") { + usedColors.add(value); + if ((value.startsWith("#") || value.startsWith("color(")) && !isValidColor(value)) { + issues.push(`Invalid color at ${currentPath}: ${value}`); + } + } else if (value && typeof value === "object") { + collectColorIssues(value, currentPath); + } + } + }; + collectColorIssues(theme.colors, ""); + assert.deepEqual(issues, [], issues.join("\n")); + }); + + test("has no undefined or null colors", () => { + for (const [key, value] of Object.entries(theme.colors)) { + assert.ok(value !== undefined && value !== null, `color "${key}" is ${value}`); + } + }); + + test("tokenColors is a non-empty array", () => { + assert.ok(Array.isArray(theme.tokenColors), "tokenColors is not an array"); + assert.ok(theme.tokenColors.length > 0, "tokenColors array is empty"); + }); + + test("every tokenColors entry is well-formed", () => { + theme.tokenColors.forEach((token, idx) => { + assert.ok(token.scope, `tokenColors[${idx}] missing scope`); + assert.ok(token.settings, `tokenColors[${idx}] missing settings`); + if (token.settings?.foreground) { + usedColors.add(token.settings.foreground); + assert.ok( + isValidColor(token.settings.foreground), + `tokenColors[${idx}] has invalid foreground color: ${token.settings.foreground}` + ); + } + }); + }); + + test("every semanticTokenColors entry is valid", () => { + for (const [key, value] of Object.entries(theme.semanticTokenColors)) { + if (typeof value === "string") { + usedColors.add(value); + assert.ok(isValidColor(value), `semanticTokenColors["${key}"] has invalid color: ${value}`); + } else if (typeof value === "object" && value !== null) { + const foreground = (value as { foreground?: string }).foreground; + if (foreground) { + usedColors.add(foreground); + assert.ok( + isValidColor(foreground), + `semanticTokenColors["${key}"].foreground has invalid color: ${foreground}` + ); + } + } + } + }); + }); + } +}); + +after(() => { + console.log(`📊 Total unique colors used: ${usedColors.size}`); +}); diff --git a/themes/pierre-dark-protanopia-deuteranopia.json b/themes/pierre-dark-protanopia-deuteranopia.json new file mode 100644 index 0000000..be2db96 --- /dev/null +++ b/themes/pierre-dark-protanopia-deuteranopia.json @@ -0,0 +1,1961 @@ +{ + "name": "pierre-dark-protanopia-deuteranopia", + "displayName": "Pierre Dark Protanopia & Deuteranopia", + "type": "dark", + "colors": { + "editor.background": "#0a0a0a", + "editor.foreground": "#fafafa", + "foreground": "#fafafa", + "focusBorder": "#009fff", + "selection.background": "#19283c", + "editor.selectionBackground": "#009fff4d", + "editor.lineHighlightBackground": "#19283c8c", + "editorCursor.foreground": "#009fff", + "editorLineNumber.foreground": "#737373", + "editorLineNumber.activeForeground": "#a3a3a3", + "editorIndentGuide.background": "#1d1d1d", + "editorIndentGuide.activeBackground": "#262626", + "diffEditor.insertedTextBackground": "#97c4ff1a", + "diffEditor.deletedTextBackground": "#fe8c2c1a", + "sideBar.background": "#171717", + "sideBar.foreground": "#a3a3a3", + "sideBar.border": "#0a0a0a", + "sideBarTitle.foreground": "#fafafa", + "sideBarSectionHeader.background": "#171717", + "sideBarSectionHeader.foreground": "#a3a3a3", + "sideBarSectionHeader.border": "#0a0a0a", + "activityBar.background": "#171717", + "activityBar.foreground": "#fafafa", + "activityBar.border": "#0a0a0a", + "activityBar.activeBorder": "#009fff", + "activityBarBadge.background": "#009fff", + "activityBarBadge.foreground": "#0a0a0a", + "titleBar.activeBackground": "#171717", + "titleBar.activeForeground": "#fafafa", + "titleBar.inactiveBackground": "#171717", + "titleBar.inactiveForeground": "#737373", + "titleBar.border": "#0a0a0a", + "list.activeSelectionBackground": "#19283c99", + "list.activeSelectionForeground": "#fafafa", + "list.inactiveSelectionBackground": "#19283c73", + "list.hoverBackground": "#19283c59", + "list.focusOutline": "#009fff", + "tab.activeBackground": "#0a0a0a", + "tab.activeForeground": "#fafafa", + "tab.activeBorderTop": "#009fff", + "tab.inactiveBackground": "#171717", + "tab.inactiveForeground": "#737373", + "tab.border": "#0a0a0a", + "editorGroupHeader.tabsBackground": "#171717", + "editorGroupHeader.tabsBorder": "#0a0a0a", + "panel.background": "#171717", + "panel.border": "#0a0a0a", + "panelTitle.activeBorder": "#009fff", + "panelTitle.activeForeground": "#fafafa", + "panelTitle.inactiveForeground": "#737373", + "statusBar.background": "#171717", + "statusBar.foreground": "#a3a3a3", + "statusBar.border": "#0a0a0a", + "statusBar.noFolderBackground": "#171717", + "statusBar.debuggingBackground": "#ffde80", + "statusBar.debuggingForeground": "#0a0a0a", + "statusBarItem.remoteBackground": "#171717", + "statusBarItem.remoteForeground": "#a3a3a3", + "input.background": "#1d1d1d", + "input.border": "#1d1d1d", + "input.foreground": "#fafafa", + "input.placeholderForeground": "#636363", + "dropdown.background": "#1d1d1d", + "dropdown.border": "#1d1d1d", + "dropdown.foreground": "#fafafa", + "button.background": "#009fff", + "button.foreground": "#0a0a0a", + "button.hoverBackground": "#0190e7", + "textLink.foreground": "#009fff", + "textLink.activeForeground": "#009fff", + "notifications.background": "#101010", + "notifications.foreground": "#fafafa", + "notifications.border": "#1d1d1d", + "notificationToast.border": "#1d1d1d", + "notificationCenter.border": "#1d1d1d", + "notificationCenterHeader.background": "#101010", + "notificationCenterHeader.foreground": "#a3a3a3", + "notificationLink.foreground": "#009fff", + "notificationsErrorIcon.foreground": "#fe8c2c", + "notificationsWarningIcon.foreground": "#ffde80", + "notificationsInfoIcon.foreground": "#68cdf2", + "quickInput.background": "#101010", + "quickInput.foreground": "#fafafa", + "quickInputTitle.background": "#101010", + "widget.border": "#1d1d1d", + "gitDecoration.addedResourceForeground": "#97c4ff", + "gitDecoration.conflictingResourceForeground": "#b969f3", + "gitDecoration.modifiedResourceForeground": "#009fff", + "gitDecoration.deletedResourceForeground": "#fe8c2c", + "gitDecoration.untrackedResourceForeground": "#97c4ff", + "gitDecoration.ignoredResourceForeground": "#737373", + "merge.currentHeaderBackground": "#b969f34d", + "merge.currentContentBackground": "#b969f31f", + "merge.incomingHeaderBackground": "#68cdf24d", + "merge.incomingContentBackground": "#68cdf21f", + "editorOverviewRuler.currentContentForeground": "#b969f3", + "editorOverviewRuler.incomingContentForeground": "#68cdf2", + "terminal.titleForeground": "#a3a3a3", + "terminal.titleInactiveForeground": "#737373", + "terminal.background": "#171717", + "terminal.foreground": "#a3a3a3", + "terminal.ansiBlack": "#171717", + "terminal.ansiRed": "#ffa359", + "terminal.ansiGreen": "#69b1ff", + "terminal.ansiYellow": "#ffd452", + "terminal.ansiBlue": "#009fff", + "terminal.ansiMagenta": "#b969f3", + "terminal.ansiCyan": "#68cdf2", + "terminal.ansiWhite": "#bcbcbc", + "terminal.ansiBrightBlack": "#171717", + "terminal.ansiBrightRed": "#ffba82", + "terminal.ansiBrightGreen": "#97c4ff", + "terminal.ansiBrightYellow": "#ffde80", + "terminal.ansiBrightBlue": "#69b1ff", + "terminal.ansiBrightMagenta": "#ce90f7", + "terminal.ansiBrightCyan": "#96d9f6", + "terminal.ansiBrightWhite": "#bcbcbc" + }, + "tokenColors": [ + { + "scope": [ + "comment", + "punctuation.definition.comment" + ], + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "comment markup.link", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "string", + "constant.other.symbol" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "punctuation.definition.string.begin", + "punctuation.definition.string.end" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "constant.numeric", + "constant.language.boolean" + ], + "settings": { + "foreground": "#96d9f6" + } + }, + { + "scope": "constant", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "punctuation.definition.constant", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "constant.language", + "settings": { + "foreground": "#96d9f6" + } + }, + { + "scope": "variable.other.constant", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "keyword.control", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "storage", + "storage.type", + "storage.modifier" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "token.storage", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "keyword.operator.new", + "keyword.operator.expression.instanceof", + "keyword.operator.expression.typeof", + "keyword.operator.expression.void", + "keyword.operator.expression.delete", + "keyword.operator.expression.in", + "keyword.operator.expression.of", + "keyword.operator.expression.keyof" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "keyword.operator.delete", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "variable", + "identifier", + "meta.definition.variable" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "variable.other.readwrite", + "meta.object-literal.key", + "support.variable.property", + "support.variable.object.process", + "support.variable.object.node" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "variable.language", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "variable.parameter.function", + "settings": { + "foreground": "#a3a3a3" + } + }, + { + "scope": "function.parameter", + "settings": { + "foreground": "#a3a3a3" + } + }, + { + "scope": "variable.parameter", + "settings": { + "foreground": "#a3a3a3" + } + }, + { + "scope": "variable.parameter.function.language.python", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "variable.parameter.function.python", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "support.function", + "entity.name.function", + "meta.function-call", + "meta.require", + "support.function.any-method", + "variable.function" + ], + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "keyword.other.special-method", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "entity.name.function", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "support.function.console", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": [ + "support.type", + "entity.name.type", + "entity.name.class", + "storage.type" + ], + "settings": { + "foreground": "#e290f0" + } + }, + { + "scope": [ + "support.class", + "entity.name.type.class" + ], + "settings": { + "foreground": "#e290f0" + } + }, + { + "scope": [ + "entity.name.class", + "variable.other.class.js", + "variable.other.class.ts" + ], + "settings": { + "foreground": "#e290f0" + } + }, + { + "scope": "entity.name.class.identifier.namespace.type", + "settings": { + "foreground": "#e290f0" + } + }, + { + "scope": "entity.name.type.namespace", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "entity.other.inherited-class", + "settings": { + "foreground": "#e290f0" + } + }, + { + "scope": "entity.name.namespace", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "keyword.operator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.logical", + "keyword.operator.bitwise", + "keyword.operator.channel" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": [ + "keyword.operator.arithmetic", + "keyword.operator.comparison", + "keyword.operator.relational", + "keyword.operator.increment", + "keyword.operator.decrement" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "keyword.operator.assignment", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "keyword.operator.assignment.compound", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "keyword.operator.assignment.compound.js", + "keyword.operator.assignment.compound.ts" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "keyword.operator.ternary", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "keyword.operator.optional", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "punctuation", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.delimiter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.key-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.terminator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.square", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.round", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "function.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.parameters", + "punctuation.definition.typeparameters" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.block", + "punctuation.definition.tag" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "meta.tag.tsx", + "meta.tag.jsx", + "meta.tag.js", + "meta.tag.ts" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.expression.import", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "keyword.operator.module", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "support.type.object.console", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "support.module.node", + "support.type.object.module", + "entity.name.type.module" + ], + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "support.constant.math", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "support.constant.property.math", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "support.constant.json", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "support.type.object.dom", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": [ + "support.variable.dom", + "support.variable.property.dom" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "support.variable.property.process", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "meta.property.object", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "variable.parameter.function.js", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "keyword.other.template.begin", + "keyword.other.template.end" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "keyword.other.substitution.begin", + "keyword.other.substitution.end" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "punctuation.definition.template-expression.begin", + "punctuation.definition.template-expression.end" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "meta.template.expression", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.section.embedded", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "variable.interpolation", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "punctuation.section.embedded.begin", + "punctuation.section.embedded.end" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "punctuation.quasi.element", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "support.type.primitive.ts", + "support.type.builtin.ts", + "support.type.primitive.tsx", + "support.type.builtin.tsx" + ], + "settings": { + "foreground": "#e290f0" + } + }, + { + "scope": "support.type.type.flowtype", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "support.type.primitive", + "settings": { + "foreground": "#e290f0" + } + }, + { + "scope": [ + "meta.decorator", + "meta.decorator punctuation.decorator" + ], + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "entity.name.function.decorator", + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "punctuation.definition.decorator", + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "support.variable.magic.python", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "variable.parameter.function.language.special.self.python", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "punctuation.separator.period.python", + "punctuation.separator.element.python", + "punctuation.parenthesis.begin.python", + "punctuation.parenthesis.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.arguments.begin.python", + "punctuation.definition.arguments.end.python", + "punctuation.separator.arguments.python", + "punctuation.definition.list.begin.python", + "punctuation.definition.list.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.python", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "keyword.operator.logical.python", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "meta.function-call.generic.python", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "constant.character.format.placeholder.other.python", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "meta.function.decorator.python", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": [ + "support.token.decorator.python", + "meta.function.decorator.identifier.python" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "storage.modifier.lifetime.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.function.std.rust", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "entity.name.lifetime.rust", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "variable.language.rust", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "keyword.operator.misc.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.sigil.rust", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "support.constant.core.rust", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "meta.function.c", + "meta.function.cpp" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "punctuation.section.block.begin.bracket.curly.cpp", + "punctuation.section.block.end.bracket.curly.cpp", + "punctuation.terminator.statement.c", + "punctuation.section.block.begin.bracket.curly.c", + "punctuation.section.block.end.bracket.curly.c", + "punctuation.section.parens.begin.bracket.round.c", + "punctuation.section.parens.end.bracket.round.c", + "punctuation.section.parameters.begin.bracket.round.c", + "punctuation.section.parameters.end.bracket.round.c" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.assignment.c", + "keyword.operator.comparison.c", + "keyword.operator.c", + "keyword.operator.increment.c", + "keyword.operator.decrement.c", + "keyword.operator.bitwise.shift.c" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "keyword.operator.assignment.cpp", + "keyword.operator.comparison.cpp", + "keyword.operator.cpp", + "keyword.operator.increment.cpp", + "keyword.operator.decrement.cpp", + "keyword.operator.bitwise.shift.cpp" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "punctuation.separator.c", + "punctuation.separator.cpp" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "support.type.posix-reserved.c", + "support.type.posix-reserved.cpp" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": [ + "keyword.operator.sizeof.c", + "keyword.operator.sizeof.cpp" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "variable.c", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.annotation.java", + "storage.type.object.array.java" + ], + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "source.java", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "punctuation.section.block.begin.java", + "punctuation.section.block.end.java", + "punctuation.definition.method-parameters.begin.java", + "punctuation.definition.method-parameters.end.java", + "meta.method.identifier.java", + "punctuation.section.method.begin.java", + "punctuation.section.method.end.java", + "punctuation.terminator.java", + "punctuation.section.class.begin.java", + "punctuation.section.class.end.java", + "punctuation.section.inner-class.begin.java", + "punctuation.section.inner-class.end.java", + "meta.method-call.java", + "punctuation.section.class.begin.bracket.curly.java", + "punctuation.section.class.end.bracket.curly.java", + "punctuation.section.method.begin.bracket.curly.java", + "punctuation.section.method.end.bracket.curly.java", + "punctuation.separator.period.java", + "punctuation.bracket.angle.java", + "punctuation.definition.annotation.java", + "meta.method.body.java" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.method.java", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": [ + "storage.modifier.import.java", + "storage.type.java", + "storage.type.generic.java" + ], + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "keyword.operator.instanceof.java", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "meta.definition.variable.name.java", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "token.variable.parameter.java", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "import.storage.java", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "token.package.keyword", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "token.package", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.storage.type.java", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "keyword.operator.assignment.go", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "keyword.operator.arithmetic.go", + "keyword.operator.address.go" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "entity.name.package.go", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "support.other.namespace.use.php", + "support.other.namespace.use-as.php", + "support.other.namespace.php", + "entity.other.alias.php", + "meta.interface.php" + ], + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "keyword.operator.error-control.php", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "keyword.operator.type.php", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "punctuation.section.array.begin.php", + "punctuation.section.array.end.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.php", + "meta.other.type.phpdoc.php", + "keyword.other.type.php", + "keyword.other.array.phpdoc.php" + ], + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "meta.function-call.php", + "meta.function-call.object.php", + "meta.function-call.static.php" + ], + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": [ + "punctuation.definition.parameters.begin.bracket.round.php", + "punctuation.definition.parameters.end.bracket.round.php", + "punctuation.separator.delimiter.php", + "punctuation.section.scope.begin.php", + "punctuation.section.scope.end.php", + "punctuation.terminator.expression.php", + "punctuation.definition.arguments.begin.bracket.round.php", + "punctuation.definition.arguments.end.bracket.round.php", + "punctuation.definition.storage-type.begin.bracket.round.php", + "punctuation.definition.storage-type.end.bracket.round.php", + "punctuation.definition.array.begin.bracket.round.php", + "punctuation.definition.array.end.bracket.round.php", + "punctuation.definition.begin.bracket.round.php", + "punctuation.definition.end.bracket.round.php", + "punctuation.definition.begin.bracket.curly.php", + "punctuation.definition.end.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php", + "punctuation.definition.section.switch-block.start.bracket.curly.php", + "punctuation.definition.section.switch-block.begin.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "support.constant.ext.php", + "support.constant.std.php", + "support.constant.core.php", + "support.constant.parser-token.php" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "entity.name.goto-label.php", + "support.other.php" + ], + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": [ + "keyword.operator.logical.php", + "keyword.operator.bitwise.php", + "keyword.operator.arithmetic.php" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "keyword.operator.regexp.php", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "keyword.operator.comparison.php", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": [ + "keyword.operator.heredoc.php", + "keyword.operator.nowdoc.php" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "variable.other.class.php", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "invalid.illegal.non-null-typehinted.php", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "variable.other.generic-type.haskell", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "storage.type.haskell", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "storage.type.cs", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "entity.name.variable.local.cs", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "entity.name.label.cs", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "entity.name.scope-resolution.function.call", + "entity.name.scope-resolution.function.definition" + ], + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "punctuation.definition.delayed.unison", + "punctuation.definition.list.begin.unison", + "punctuation.definition.list.end.unison", + "punctuation.definition.ability.begin.unison", + "punctuation.definition.ability.end.unison", + "punctuation.operator.assignment.as.unison", + "punctuation.separator.pipe.unison", + "punctuation.separator.delimiter.unison", + "punctuation.definition.hash.unison" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "support.constant.edge", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "support.type.prelude.elm", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "support.constant.elm", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "entity.global.clojure", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "meta.symbol.clojure", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "constant.keyword.clojure", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": [ + "meta.arguments.coffee", + "variable.parameter.function.coffee" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "storage.modifier.import.groovy", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "meta.method.groovy", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "meta.definition.variable.name.groovy", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "meta.definition.class.inherited.classes.groovy", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "support.variable.semantic.hlsl", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "support.type.texture.hlsl", + "support.type.sampler.hlsl", + "support.type.object.hlsl", + "support.type.object.rw.hlsl", + "support.type.fx.hlsl", + "support.type.object.hlsl" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "text.variable", + "text.bracketed" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "support.type.swift", + "support.type.vb.asp" + ], + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "meta.scope.prerequisites.makefile", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "source.makefile", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "source.ini", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "constant.language.symbol.ruby", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": [ + "function.parameter.ruby", + "function.parameter.cs" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "constant.language.symbol.elixir", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "entity.name.function.xi", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "entity.name.class.xi", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "constant.character.character-class.regexp.xi", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "constant.regexp.xi", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "keyword.control.xi", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "invalid.xi", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "beginning.punctuation.definition.quote.markdown.xi", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "constant.character.xi", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "accent.xi", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "wikiword.xi", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "constant.other.color.rgb-value.xi", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "punctuation.definition.tag.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "support.constant.property-value.scss", + "support.constant.property-value.css" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "keyword.operator.css", + "keyword.operator.scss", + "keyword.operator.less" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": [ + "support.constant.color.w3c-standard-color-name.css", + "support.constant.color.w3c-standard-color-name.scss" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "punctuation.separator.list.comma.css", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.vendored.property-name.css", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "support.type.property-name.css", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "support.type.property-name", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.property-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.font-name", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "entity.other.attribute-name.class.css", + "settings": { + "foreground": "#ffbc56", + "fontStyle": "normal" + } + }, + { + "scope": "entity.other.attribute-name.id", + "settings": { + "foreground": "#ba8ffd", + "fontStyle": "normal" + } + }, + { + "scope": [ + "entity.other.attribute-name.pseudo-element", + "entity.other.attribute-name.pseudo-class" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "meta.selector", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "selector.sass", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "rgb-value", + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "inline-color-decoration rgb-value", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "less rgb-value", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "control.elements", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "keyword.operator.less", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "entity.name.tag", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "entity.other.attribute-name", + "settings": { + "foreground": "#ffbc56", + "fontStyle": "normal" + } + }, + { + "scope": "constant.character.entity", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "meta.tag", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "invalid.illegal.bad-ampersand.html", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "markup.heading", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "markup.heading punctuation.definition.heading", + "entity.name.section" + ], + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "entity.name.section.markdown", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "punctuation.definition.heading.markdown", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "markup.heading.setext", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "markup.heading.setext.1.markdown", + "markup.heading.setext.2.markdown" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "markup.bold", + "todo.bold" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "punctuation.definition.bold", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": "punctuation.definition.bold.markdown", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "markup.italic", + "punctuation.definition.italic", + "todo.emphasis" + ], + "settings": { + "foreground": "#b969f3", + "fontStyle": "italic" + } + }, + { + "scope": "emphasis md", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "markup.italic.markdown", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": [ + "markup.underline.link.markdown", + "markup.underline.link.image.markdown" + ], + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": [ + "string.other.link.title.markdown", + "string.other.link.description.markdown" + ], + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "punctuation.definition.metadata.markdown", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "markup.inline.raw.markdown", + "markup.inline.raw.string.markdown" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "punctuation.definition.list.begin.markdown", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "punctuation.definition.list.markdown", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "punctuation.definition.string.begin.markdown", + "punctuation.definition.string.end.markdown" + ], + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "markup.quote.markdown", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "keyword.other.unit", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "markup.changed.diff", + "settings": { + "foreground": "#ffbc56" + } + }, + { + "scope": [ + "meta.diff.header.from-file", + "meta.diff.header.to-file", + "punctuation.definition.from-file.diff", + "punctuation.definition.to-file.diff" + ], + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "markup.inserted.diff", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "markup.deleted.diff", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "string.regexp", + "settings": { + "foreground": "#68cdf2" + } + }, + { + "scope": "constant.other.character-class.regexp", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#64d1db" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > value.json > string.quoted.json", + "source.json meta.structure.array.json > value.json > string.quoted.json", + "source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation", + "source.json meta.structure.array.json > value.json > string.quoted.json > punctuation" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > constant.language.json", + "source.json meta.structure.array.json > constant.language.json" + ], + "settings": { + "foreground": "#08c0ef" + } + }, + { + "scope": "support.type.property-name.json", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "support.type.property-name.json punctuation", + "settings": { + "foreground": "#ffa359" + } + }, + { + "scope": "punctuation.definition.block.sequence.item.yaml", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.end", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.begin", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.info-token", + "settings": { + "foreground": "#ba8ffd" + } + }, + { + "scope": "token.warn-token", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "token.error-token", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "token.debug-token", + "settings": { + "foreground": "#b969f3" + } + }, + { + "scope": "invalid.illegal", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "invalid.broken", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "invalid.deprecated", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "invalid.unimplemented", + "settings": { + "foreground": "#fafafa" + } + } + ], + "semanticTokenColors": { + "comment": "#737373", + "string": "#97c4ff", + "number": "#96d9f6", + "regexp": "#68cdf2", + "keyword": "#b969f3", + "variable": "#ffa359", + "parameter": "#a3a3a3", + "property": "#ffa359", + "function": "#ba8ffd", + "method": "#ba8ffd", + "type": "#e290f0", + "class": "#e290f0", + "namespace": "#ffbc56", + "enumMember": "#08c0ef", + "variable.constant": "#ffcc81", + "variable.defaultLibrary": "#ffbc56", + "decorator": "#69b1ff" + } +} \ No newline at end of file diff --git a/themes/pierre-dark-tritanopia.json b/themes/pierre-dark-tritanopia.json new file mode 100644 index 0000000..3f57407 --- /dev/null +++ b/themes/pierre-dark-tritanopia.json @@ -0,0 +1,1961 @@ +{ + "name": "pierre-dark-tritanopia", + "displayName": "Pierre Dark Tritanopia", + "type": "dark", + "colors": { + "editor.background": "#0a0a0a", + "editor.foreground": "#fafafa", + "foreground": "#fafafa", + "focusBorder": "#009fff", + "selection.background": "#19283c", + "editor.selectionBackground": "#009fff4d", + "editor.lineHighlightBackground": "#19283c8c", + "editorCursor.foreground": "#009fff", + "editorLineNumber.foreground": "#737373", + "editorLineNumber.activeForeground": "#a3a3a3", + "editorIndentGuide.background": "#1d1d1d", + "editorIndentGuide.activeBackground": "#262626", + "diffEditor.insertedTextBackground": "#92dde41a", + "diffEditor.deletedTextBackground": "#ff855e1a", + "sideBar.background": "#171717", + "sideBar.foreground": "#a3a3a3", + "sideBar.border": "#0a0a0a", + "sideBarTitle.foreground": "#fafafa", + "sideBarSectionHeader.background": "#171717", + "sideBarSectionHeader.foreground": "#a3a3a3", + "sideBarSectionHeader.border": "#0a0a0a", + "activityBar.background": "#171717", + "activityBar.foreground": "#fafafa", + "activityBar.border": "#0a0a0a", + "activityBar.activeBorder": "#009fff", + "activityBarBadge.background": "#009fff", + "activityBarBadge.foreground": "#0a0a0a", + "titleBar.activeBackground": "#171717", + "titleBar.activeForeground": "#fafafa", + "titleBar.inactiveBackground": "#171717", + "titleBar.inactiveForeground": "#737373", + "titleBar.border": "#0a0a0a", + "list.activeSelectionBackground": "#19283c99", + "list.activeSelectionForeground": "#fafafa", + "list.inactiveSelectionBackground": "#19283c73", + "list.hoverBackground": "#19283c59", + "list.focusOutline": "#009fff", + "tab.activeBackground": "#0a0a0a", + "tab.activeForeground": "#fafafa", + "tab.activeBorderTop": "#009fff", + "tab.inactiveBackground": "#171717", + "tab.inactiveForeground": "#737373", + "tab.border": "#0a0a0a", + "editorGroupHeader.tabsBackground": "#171717", + "editorGroupHeader.tabsBorder": "#0a0a0a", + "panel.background": "#171717", + "panel.border": "#0a0a0a", + "panelTitle.activeBorder": "#009fff", + "panelTitle.activeForeground": "#fafafa", + "panelTitle.inactiveForeground": "#737373", + "statusBar.background": "#171717", + "statusBar.foreground": "#a3a3a3", + "statusBar.border": "#0a0a0a", + "statusBar.noFolderBackground": "#171717", + "statusBar.debuggingBackground": "#ffbc56", + "statusBar.debuggingForeground": "#0a0a0a", + "statusBarItem.remoteBackground": "#171717", + "statusBarItem.remoteForeground": "#a3a3a3", + "input.background": "#1d1d1d", + "input.border": "#1d1d1d", + "input.foreground": "#fafafa", + "input.placeholderForeground": "#636363", + "dropdown.background": "#1d1d1d", + "dropdown.border": "#1d1d1d", + "dropdown.foreground": "#fafafa", + "button.background": "#009fff", + "button.foreground": "#0a0a0a", + "button.hoverBackground": "#0190e7", + "textLink.foreground": "#009fff", + "textLink.activeForeground": "#009fff", + "notifications.background": "#101010", + "notifications.foreground": "#fafafa", + "notifications.border": "#1d1d1d", + "notificationToast.border": "#1d1d1d", + "notificationCenter.border": "#1d1d1d", + "notificationCenterHeader.background": "#101010", + "notificationCenterHeader.foreground": "#a3a3a3", + "notificationLink.foreground": "#009fff", + "notificationsErrorIcon.foreground": "#ff855e", + "notificationsWarningIcon.foreground": "#ffbc56", + "notificationsInfoIcon.foreground": "#69b1ff", + "quickInput.background": "#101010", + "quickInput.foreground": "#fafafa", + "quickInputTitle.background": "#101010", + "widget.border": "#1d1d1d", + "gitDecoration.addedResourceForeground": "#92dde4", + "gitDecoration.conflictingResourceForeground": "#ea68bc", + "gitDecoration.modifiedResourceForeground": "#009fff", + "gitDecoration.deletedResourceForeground": "#ff855e", + "gitDecoration.untrackedResourceForeground": "#92dde4", + "gitDecoration.ignoredResourceForeground": "#737373", + "merge.currentHeaderBackground": "#ea68bc4d", + "merge.currentContentBackground": "#ea68bc1f", + "merge.incomingHeaderBackground": "#69b1ff4d", + "merge.incomingContentBackground": "#69b1ff1f", + "editorOverviewRuler.currentContentForeground": "#ea68bc", + "editorOverviewRuler.incomingContentForeground": "#69b1ff", + "terminal.titleForeground": "#a3a3a3", + "terminal.titleInactiveForeground": "#737373", + "terminal.background": "#171717", + "terminal.foreground": "#a3a3a3", + "terminal.ansiBlack": "#171717", + "terminal.ansiRed": "#ff855e", + "terminal.ansiGreen": "#64d1db", + "terminal.ansiYellow": "#ffbc56", + "terminal.ansiBlue": "#69b1ff", + "terminal.ansiMagenta": "#ea68bc", + "terminal.ansiCyan": "#92dde4", + "terminal.ansiWhite": "#bcbcbc", + "terminal.ansiBrightBlack": "#171717", + "terminal.ansiBrightRed": "#ffa685", + "terminal.ansiBrightGreen": "#92dde4", + "terminal.ansiBrightYellow": "#ffcc81", + "terminal.ansiBrightBlue": "#97c4ff", + "terminal.ansiBrightMagenta": "#f191cc", + "terminal.ansiBrightCyan": "#92dde4", + "terminal.ansiBrightWhite": "#bcbcbc" + }, + "tokenColors": [ + { + "scope": [ + "comment", + "punctuation.definition.comment" + ], + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "comment markup.link", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "string", + "constant.other.symbol" + ], + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": [ + "punctuation.definition.string.begin", + "punctuation.definition.string.end" + ], + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": [ + "constant.numeric", + "constant.language.boolean" + ], + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "constant", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "punctuation.definition.constant", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "constant.language", + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "variable.other.constant", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "keyword.control", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "storage", + "storage.type", + "storage.modifier" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "token.storage", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "keyword.operator.new", + "keyword.operator.expression.instanceof", + "keyword.operator.expression.typeof", + "keyword.operator.expression.void", + "keyword.operator.expression.delete", + "keyword.operator.expression.in", + "keyword.operator.expression.of", + "keyword.operator.expression.keyof" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "keyword.operator.delete", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "variable", + "identifier", + "meta.definition.variable" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "variable.other.readwrite", + "meta.object-literal.key", + "support.variable.property", + "support.variable.object.process", + "support.variable.object.node" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "variable.language", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "variable.parameter.function", + "settings": { + "foreground": "#a3a3a3" + } + }, + { + "scope": "function.parameter", + "settings": { + "foreground": "#a3a3a3" + } + }, + { + "scope": "variable.parameter", + "settings": { + "foreground": "#a3a3a3" + } + }, + { + "scope": "variable.parameter.function.language.python", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "variable.parameter.function.python", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "support.function", + "entity.name.function", + "meta.function-call", + "meta.require", + "support.function.any-method", + "variable.function" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "keyword.other.special-method", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "entity.name.function", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "support.function.console", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "support.type", + "entity.name.type", + "entity.name.class", + "storage.type" + ], + "settings": { + "foreground": "#ea68bc" + } + }, + { + "scope": [ + "support.class", + "entity.name.type.class" + ], + "settings": { + "foreground": "#ea68bc" + } + }, + { + "scope": [ + "entity.name.class", + "variable.other.class.js", + "variable.other.class.ts" + ], + "settings": { + "foreground": "#ea68bc" + } + }, + { + "scope": "entity.name.class.identifier.namespace.type", + "settings": { + "foreground": "#ea68bc" + } + }, + { + "scope": "entity.name.type.namespace", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "entity.other.inherited-class", + "settings": { + "foreground": "#ea68bc" + } + }, + { + "scope": "entity.name.namespace", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "keyword.operator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.logical", + "keyword.operator.bitwise", + "keyword.operator.channel" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": [ + "keyword.operator.arithmetic", + "keyword.operator.comparison", + "keyword.operator.relational", + "keyword.operator.increment", + "keyword.operator.decrement" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "keyword.operator.assignment", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "keyword.operator.assignment.compound", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "keyword.operator.assignment.compound.js", + "keyword.operator.assignment.compound.ts" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "keyword.operator.ternary", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "keyword.operator.optional", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "punctuation", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.delimiter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.key-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.terminator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.square", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.round", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "function.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.parameters", + "punctuation.definition.typeparameters" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.block", + "punctuation.definition.tag" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "meta.tag.tsx", + "meta.tag.jsx", + "meta.tag.js", + "meta.tag.ts" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.expression.import", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "keyword.operator.module", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "support.type.object.console", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "support.module.node", + "support.type.object.module", + "entity.name.type.module" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "support.constant.math", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "support.constant.property.math", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "support.constant.json", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "support.type.object.dom", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": [ + "support.variable.dom", + "support.variable.property.dom" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "support.variable.property.process", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "meta.property.object", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "variable.parameter.function.js", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "keyword.other.template.begin", + "keyword.other.template.end" + ], + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": [ + "keyword.other.substitution.begin", + "keyword.other.substitution.end" + ], + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": [ + "punctuation.definition.template-expression.begin", + "punctuation.definition.template-expression.end" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "meta.template.expression", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.section.embedded", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "variable.interpolation", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "punctuation.section.embedded.begin", + "punctuation.section.embedded.end" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "punctuation.quasi.element", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "support.type.primitive.ts", + "support.type.builtin.ts", + "support.type.primitive.tsx", + "support.type.builtin.tsx" + ], + "settings": { + "foreground": "#ea68bc" + } + }, + { + "scope": "support.type.type.flowtype", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "support.type.primitive", + "settings": { + "foreground": "#ea68bc" + } + }, + { + "scope": [ + "meta.decorator", + "meta.decorator punctuation.decorator" + ], + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "entity.name.function.decorator", + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "punctuation.definition.decorator", + "settings": { + "foreground": "#69b1ff" + } + }, + { + "scope": "support.variable.magic.python", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "variable.parameter.function.language.special.self.python", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "punctuation.separator.period.python", + "punctuation.separator.element.python", + "punctuation.parenthesis.begin.python", + "punctuation.parenthesis.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.arguments.begin.python", + "punctuation.definition.arguments.end.python", + "punctuation.separator.arguments.python", + "punctuation.definition.list.begin.python", + "punctuation.definition.list.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.python", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "keyword.operator.logical.python", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "meta.function-call.generic.python", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "constant.character.format.placeholder.other.python", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "meta.function.decorator.python", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "support.token.decorator.python", + "meta.function.decorator.identifier.python" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "storage.modifier.lifetime.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.function.std.rust", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "entity.name.lifetime.rust", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "variable.language.rust", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "keyword.operator.misc.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.sigil.rust", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "support.constant.core.rust", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "meta.function.c", + "meta.function.cpp" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "punctuation.section.block.begin.bracket.curly.cpp", + "punctuation.section.block.end.bracket.curly.cpp", + "punctuation.terminator.statement.c", + "punctuation.section.block.begin.bracket.curly.c", + "punctuation.section.block.end.bracket.curly.c", + "punctuation.section.parens.begin.bracket.round.c", + "punctuation.section.parens.end.bracket.round.c", + "punctuation.section.parameters.begin.bracket.round.c", + "punctuation.section.parameters.end.bracket.round.c" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.assignment.c", + "keyword.operator.comparison.c", + "keyword.operator.c", + "keyword.operator.increment.c", + "keyword.operator.decrement.c", + "keyword.operator.bitwise.shift.c" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "keyword.operator.assignment.cpp", + "keyword.operator.comparison.cpp", + "keyword.operator.cpp", + "keyword.operator.increment.cpp", + "keyword.operator.decrement.cpp", + "keyword.operator.bitwise.shift.cpp" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "punctuation.separator.c", + "punctuation.separator.cpp" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "support.type.posix-reserved.c", + "support.type.posix-reserved.cpp" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": [ + "keyword.operator.sizeof.c", + "keyword.operator.sizeof.cpp" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "variable.c", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.annotation.java", + "storage.type.object.array.java" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "source.java", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "punctuation.section.block.begin.java", + "punctuation.section.block.end.java", + "punctuation.definition.method-parameters.begin.java", + "punctuation.definition.method-parameters.end.java", + "meta.method.identifier.java", + "punctuation.section.method.begin.java", + "punctuation.section.method.end.java", + "punctuation.terminator.java", + "punctuation.section.class.begin.java", + "punctuation.section.class.end.java", + "punctuation.section.inner-class.begin.java", + "punctuation.section.inner-class.end.java", + "meta.method-call.java", + "punctuation.section.class.begin.bracket.curly.java", + "punctuation.section.class.end.bracket.curly.java", + "punctuation.section.method.begin.bracket.curly.java", + "punctuation.section.method.end.bracket.curly.java", + "punctuation.separator.period.java", + "punctuation.bracket.angle.java", + "punctuation.definition.annotation.java", + "meta.method.body.java" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.method.java", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "storage.modifier.import.java", + "storage.type.java", + "storage.type.generic.java" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "keyword.operator.instanceof.java", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "meta.definition.variable.name.java", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "token.variable.parameter.java", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "import.storage.java", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "token.package.keyword", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "token.package", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.storage.type.java", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "keyword.operator.assignment.go", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "keyword.operator.arithmetic.go", + "keyword.operator.address.go" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "entity.name.package.go", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "support.other.namespace.use.php", + "support.other.namespace.use-as.php", + "support.other.namespace.php", + "entity.other.alias.php", + "meta.interface.php" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "keyword.operator.error-control.php", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "keyword.operator.type.php", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "punctuation.section.array.begin.php", + "punctuation.section.array.end.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.php", + "meta.other.type.phpdoc.php", + "keyword.other.type.php", + "keyword.other.array.phpdoc.php" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "meta.function-call.php", + "meta.function-call.object.php", + "meta.function-call.static.php" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "punctuation.definition.parameters.begin.bracket.round.php", + "punctuation.definition.parameters.end.bracket.round.php", + "punctuation.separator.delimiter.php", + "punctuation.section.scope.begin.php", + "punctuation.section.scope.end.php", + "punctuation.terminator.expression.php", + "punctuation.definition.arguments.begin.bracket.round.php", + "punctuation.definition.arguments.end.bracket.round.php", + "punctuation.definition.storage-type.begin.bracket.round.php", + "punctuation.definition.storage-type.end.bracket.round.php", + "punctuation.definition.array.begin.bracket.round.php", + "punctuation.definition.array.end.bracket.round.php", + "punctuation.definition.begin.bracket.round.php", + "punctuation.definition.end.bracket.round.php", + "punctuation.definition.begin.bracket.curly.php", + "punctuation.definition.end.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php", + "punctuation.definition.section.switch-block.start.bracket.curly.php", + "punctuation.definition.section.switch-block.begin.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "support.constant.ext.php", + "support.constant.std.php", + "support.constant.core.php", + "support.constant.parser-token.php" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "entity.name.goto-label.php", + "support.other.php" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": [ + "keyword.operator.logical.php", + "keyword.operator.bitwise.php", + "keyword.operator.arithmetic.php" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "keyword.operator.regexp.php", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "keyword.operator.comparison.php", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": [ + "keyword.operator.heredoc.php", + "keyword.operator.nowdoc.php" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "variable.other.class.php", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "invalid.illegal.non-null-typehinted.php", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "variable.other.generic-type.haskell", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "storage.type.haskell", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "storage.type.cs", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "entity.name.variable.local.cs", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "entity.name.label.cs", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "entity.name.scope-resolution.function.call", + "entity.name.scope-resolution.function.definition" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "punctuation.definition.delayed.unison", + "punctuation.definition.list.begin.unison", + "punctuation.definition.list.end.unison", + "punctuation.definition.ability.begin.unison", + "punctuation.definition.ability.end.unison", + "punctuation.operator.assignment.as.unison", + "punctuation.separator.pipe.unison", + "punctuation.separator.delimiter.unison", + "punctuation.definition.hash.unison" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "support.constant.edge", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "support.type.prelude.elm", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "support.constant.elm", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "entity.global.clojure", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "meta.symbol.clojure", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "constant.keyword.clojure", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": [ + "meta.arguments.coffee", + "variable.parameter.function.coffee" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "storage.modifier.import.groovy", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "meta.method.groovy", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "meta.definition.variable.name.groovy", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "meta.definition.class.inherited.classes.groovy", + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": "support.variable.semantic.hlsl", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "support.type.texture.hlsl", + "support.type.sampler.hlsl", + "support.type.object.hlsl", + "support.type.object.rw.hlsl", + "support.type.fx.hlsl", + "support.type.object.hlsl" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "text.variable", + "text.bracketed" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "support.type.swift", + "support.type.vb.asp" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "meta.scope.prerequisites.makefile", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "source.makefile", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "source.ini", + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": "constant.language.symbol.ruby", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": [ + "function.parameter.ruby", + "function.parameter.cs" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "constant.language.symbol.elixir", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "entity.name.function.xi", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "entity.name.class.xi", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "constant.character.character-class.regexp.xi", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "constant.regexp.xi", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "keyword.control.xi", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "invalid.xi", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "beginning.punctuation.definition.quote.markdown.xi", + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "constant.character.xi", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "accent.xi", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "wikiword.xi", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "constant.other.color.rgb-value.xi", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "punctuation.definition.tag.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "support.constant.property-value.scss", + "support.constant.property-value.css" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "keyword.operator.css", + "keyword.operator.scss", + "keyword.operator.less" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": [ + "support.constant.color.w3c-standard-color-name.css", + "support.constant.color.w3c-standard-color-name.scss" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "punctuation.separator.list.comma.css", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.vendored.property-name.css", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "support.type.property-name.css", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "support.type.property-name", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.property-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.font-name", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "entity.other.attribute-name.class.css", + "settings": { + "foreground": "#64d1db", + "fontStyle": "normal" + } + }, + { + "scope": "entity.other.attribute-name.id", + "settings": { + "foreground": "#97c4ff", + "fontStyle": "normal" + } + }, + { + "scope": [ + "entity.other.attribute-name.pseudo-element", + "entity.other.attribute-name.pseudo-class" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "meta.selector", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "selector.sass", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "rgb-value", + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "inline-color-decoration rgb-value", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "less rgb-value", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "control.elements", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "keyword.operator.less", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "entity.name.tag", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "entity.other.attribute-name", + "settings": { + "foreground": "#64d1db", + "fontStyle": "normal" + } + }, + { + "scope": "constant.character.entity", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "meta.tag", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "invalid.illegal.bad-ampersand.html", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "markup.heading", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "markup.heading punctuation.definition.heading", + "entity.name.section" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "entity.name.section.markdown", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "punctuation.definition.heading.markdown", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "markup.heading.setext", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "markup.heading.setext.1.markdown", + "markup.heading.setext.2.markdown" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "markup.bold", + "todo.bold" + ], + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "punctuation.definition.bold", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "punctuation.definition.bold.markdown", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": [ + "markup.italic", + "punctuation.definition.italic", + "todo.emphasis" + ], + "settings": { + "foreground": "#d568ea", + "fontStyle": "italic" + } + }, + { + "scope": "emphasis md", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "markup.italic.markdown", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": [ + "markup.underline.link.markdown", + "markup.underline.link.image.markdown" + ], + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": [ + "string.other.link.title.markdown", + "string.other.link.description.markdown" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "punctuation.definition.metadata.markdown", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "markup.inline.raw.markdown", + "markup.inline.raw.string.markdown" + ], + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": "punctuation.definition.list.begin.markdown", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "punctuation.definition.list.markdown", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "punctuation.definition.string.begin.markdown", + "punctuation.definition.string.end.markdown" + ], + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "markup.quote.markdown", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "keyword.other.unit", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "markup.changed.diff", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "meta.diff.header.from-file", + "meta.diff.header.to-file", + "punctuation.definition.from-file.diff", + "punctuation.definition.to-file.diff" + ], + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "markup.inserted.diff", + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": "markup.deleted.diff", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "string.regexp", + "settings": { + "foreground": "#64d1db" + } + }, + { + "scope": "constant.other.character-class.regexp", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#64d1db" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > value.json > string.quoted.json", + "source.json meta.structure.array.json > value.json > string.quoted.json", + "source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation", + "source.json meta.structure.array.json > value.json > string.quoted.json > punctuation" + ], + "settings": { + "foreground": "#92dde4" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > constant.language.json", + "source.json meta.structure.array.json > constant.language.json" + ], + "settings": { + "foreground": "#00c5d2" + } + }, + { + "scope": "support.type.property-name.json", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "support.type.property-name.json punctuation", + "settings": { + "foreground": "#ff855e" + } + }, + { + "scope": "punctuation.definition.block.sequence.item.yaml", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.end", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.begin", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.info-token", + "settings": { + "foreground": "#97c4ff" + } + }, + { + "scope": "token.warn-token", + "settings": { + "foreground": "#ffcc81" + } + }, + { + "scope": "token.error-token", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "token.debug-token", + "settings": { + "foreground": "#d568ea" + } + }, + { + "scope": "invalid.illegal", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "invalid.broken", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "invalid.deprecated", + "settings": { + "foreground": "#fafafa" + } + }, + { + "scope": "invalid.unimplemented", + "settings": { + "foreground": "#fafafa" + } + } + ], + "semanticTokenColors": { + "comment": "#737373", + "string": "#92dde4", + "number": "#69b1ff", + "regexp": "#64d1db", + "keyword": "#d568ea", + "variable": "#ff855e", + "parameter": "#a3a3a3", + "property": "#ff855e", + "function": "#97c4ff", + "method": "#97c4ff", + "type": "#ea68bc", + "class": "#ea68bc", + "namespace": "#ff855e", + "enumMember": "#00c5d2", + "variable.constant": "#ffcc81", + "variable.defaultLibrary": "#ff855e", + "decorator": "#69b1ff" + } +} \ No newline at end of file diff --git a/themes/pierre-light-protanopia-deuteranopia.json b/themes/pierre-light-protanopia-deuteranopia.json new file mode 100644 index 0000000..b454eae --- /dev/null +++ b/themes/pierre-light-protanopia-deuteranopia.json @@ -0,0 +1,1961 @@ +{ + "name": "pierre-light-protanopia-deuteranopia", + "displayName": "Pierre Light Protanopia & Deuteranopia", + "type": "light", + "colors": { + "editor.background": "#ffffff", + "editor.foreground": "#0a0a0a", + "foreground": "#0a0a0a", + "focusBorder": "#009fff", + "selection.background": "#dfebff", + "editor.selectionBackground": "#009fff2e", + "editor.lineHighlightBackground": "#dfebff8c", + "editorCursor.foreground": "#009fff", + "editorLineNumber.foreground": "#737373", + "editorLineNumber.activeForeground": "#525252", + "editorIndentGuide.background": "#e5e5e5", + "editorIndentGuide.activeBackground": "#d4d4d4", + "diffEditor.insertedTextBackground": "#216cab33", + "diffEditor.deletedTextBackground": "#ac602333", + "sideBar.background": "#f5f5f5", + "sideBar.foreground": "#525252", + "sideBar.border": "#e5e5e5", + "sideBarTitle.foreground": "#0a0a0a", + "sideBarSectionHeader.background": "#f5f5f5", + "sideBarSectionHeader.foreground": "#525252", + "sideBarSectionHeader.border": "#e5e5e5", + "activityBar.background": "#f5f5f5", + "activityBar.foreground": "#0a0a0a", + "activityBar.border": "#e5e5e5", + "activityBar.activeBorder": "#009fff", + "activityBarBadge.background": "#009fff", + "activityBarBadge.foreground": "#ffffff", + "titleBar.activeBackground": "#f5f5f5", + "titleBar.activeForeground": "#0a0a0a", + "titleBar.inactiveBackground": "#f5f5f5", + "titleBar.inactiveForeground": "#737373", + "titleBar.border": "#e5e5e5", + "list.activeSelectionBackground": "#dfebffcc", + "list.activeSelectionForeground": "#0a0a0a", + "list.inactiveSelectionBackground": "#dfebff73", + "list.hoverBackground": "#dfebff59", + "list.focusOutline": "#009fff", + "tab.activeBackground": "#ffffff", + "tab.activeForeground": "#0a0a0a", + "tab.activeBorderTop": "#009fff", + "tab.inactiveBackground": "#f5f5f5", + "tab.inactiveForeground": "#737373", + "tab.border": "#e5e5e5", + "editorGroupHeader.tabsBackground": "#f5f5f5", + "editorGroupHeader.tabsBorder": "#e5e5e5", + "panel.background": "#f5f5f5", + "panel.border": "#e5e5e5", + "panelTitle.activeBorder": "#009fff", + "panelTitle.activeForeground": "#0a0a0a", + "panelTitle.inactiveForeground": "#737373", + "statusBar.background": "#f5f5f5", + "statusBar.foreground": "#525252", + "statusBar.border": "#e5e5e5", + "statusBar.noFolderBackground": "#f5f5f5", + "statusBar.debuggingBackground": "#ffca00", + "statusBar.debuggingForeground": "#ffffff", + "statusBarItem.remoteBackground": "#f5f5f5", + "statusBarItem.remoteForeground": "#525252", + "input.background": "#ededed", + "input.border": "#d4d4d4", + "input.foreground": "#0a0a0a", + "input.placeholderForeground": "#8a8a8a", + "dropdown.background": "#ededed", + "dropdown.border": "#d4d4d4", + "dropdown.foreground": "#0a0a0a", + "button.background": "#009fff", + "button.foreground": "#ffffff", + "button.hoverBackground": "#1aa9ff", + "textLink.foreground": "#009fff", + "textLink.activeForeground": "#009fff", + "notifications.background": "#f7f7f7", + "notifications.foreground": "#0a0a0a", + "notifications.border": "#e5e5e5", + "notificationToast.border": "#e5e5e5", + "notificationCenter.border": "#e5e5e5", + "notificationCenterHeader.background": "#f7f7f7", + "notificationCenterHeader.foreground": "#525252", + "notificationLink.foreground": "#009fff", + "notificationsErrorIcon.foreground": "#ac6023", + "notificationsWarningIcon.foreground": "#ffca00", + "notificationsInfoIcon.foreground": "#2182a1", + "quickInput.background": "#f7f7f7", + "quickInput.foreground": "#0a0a0a", + "quickInputTitle.background": "#f7f7f7", + "widget.border": "#e5e5e5", + "gitDecoration.addedResourceForeground": "#216cab", + "gitDecoration.conflictingResourceForeground": "#58287c", + "gitDecoration.modifiedResourceForeground": "#009fff", + "gitDecoration.deletedResourceForeground": "#ac6023", + "gitDecoration.untrackedResourceForeground": "#216cab", + "gitDecoration.ignoredResourceForeground": "#737373", + "merge.currentHeaderBackground": "#58287c33", + "merge.currentContentBackground": "#58287c14", + "merge.incomingHeaderBackground": "#2182a133", + "merge.incomingContentBackground": "#2182a114", + "editorOverviewRuler.currentContentForeground": "#58287c", + "editorOverviewRuler.incomingContentForeground": "#2182a1", + "terminal.titleForeground": "#525252", + "terminal.titleInactiveForeground": "#737373", + "terminal.background": "#f5f5f5", + "terminal.foreground": "#525252", + "terminal.ansiBlack": "#1d1d1d", + "terminal.ansiRed": "#ac6023", + "terminal.ansiGreen": "#216cab", + "terminal.ansiYellow": "#ffca00", + "terminal.ansiBlue": "#1a85d4", + "terminal.ansiMagenta": "#8836c7", + "terminal.ansiCyan": "#2182a1", + "terminal.ansiWhite": "#bcbcbc", + "terminal.ansiBrightBlack": "#1d1d1d", + "terminal.ansiBrightRed": "#d47628", + "terminal.ansiBrightGreen": "#1a85d4", + "terminal.ansiBrightYellow": "#ffca00", + "terminal.ansiBrightBlue": "#009fff", + "terminal.ansiBrightMagenta": "#a13cee", + "terminal.ansiBrightCyan": "#1ca1c7", + "terminal.ansiBrightWhite": "#bcbcbc" + }, + "tokenColors": [ + { + "scope": [ + "comment", + "punctuation.definition.comment" + ], + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "comment markup.link", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "string", + "constant.other.symbol" + ], + "settings": { + "foreground": "#215584" + } + }, + { + "scope": [ + "punctuation.definition.string.begin", + "punctuation.definition.string.end" + ], + "settings": { + "foreground": "#215584" + } + }, + { + "scope": [ + "constant.numeric", + "constant.language.boolean" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "constant", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "punctuation.definition.constant", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "constant.language", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "variable.other.constant", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "keyword.control", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "storage", + "storage.type", + "storage.modifier" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "token.storage", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "keyword.operator.new", + "keyword.operator.expression.instanceof", + "keyword.operator.expression.typeof", + "keyword.operator.expression.void", + "keyword.operator.expression.delete", + "keyword.operator.expression.in", + "keyword.operator.expression.of", + "keyword.operator.expression.keyof" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "keyword.operator.delete", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "variable", + "identifier", + "meta.definition.variable" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "variable.other.readwrite", + "meta.object-literal.key", + "support.variable.property", + "support.variable.object.process", + "support.variable.object.node" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "variable.language", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "variable.parameter.function", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "function.parameter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "variable.parameter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "variable.parameter.function.language.python", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "variable.parameter.function.python", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "support.function", + "entity.name.function", + "meta.function-call", + "meta.require", + "support.function.any-method", + "variable.function" + ], + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "keyword.other.special-method", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "entity.name.function", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "support.function.console", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": [ + "support.type", + "entity.name.type", + "entity.name.class", + "storage.type" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "support.class", + "entity.name.type.class" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "entity.name.class", + "variable.other.class.js", + "variable.other.class.ts" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "entity.name.class.identifier.namespace.type", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "entity.name.type.namespace", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.other.inherited-class", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "entity.name.namespace", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "keyword.operator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.logical", + "keyword.operator.bitwise", + "keyword.operator.channel" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": [ + "keyword.operator.arithmetic", + "keyword.operator.comparison", + "keyword.operator.relational", + "keyword.operator.increment", + "keyword.operator.decrement" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "keyword.operator.assignment", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "keyword.operator.assignment.compound", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "keyword.operator.assignment.compound.js", + "keyword.operator.assignment.compound.ts" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "keyword.operator.ternary", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "keyword.operator.optional", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "punctuation", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.delimiter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.key-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.terminator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.square", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.round", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "function.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.parameters", + "punctuation.definition.typeparameters" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.block", + "punctuation.definition.tag" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "meta.tag.tsx", + "meta.tag.jsx", + "meta.tag.js", + "meta.tag.ts" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.expression.import", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "keyword.operator.module", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "support.type.object.console", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "support.module.node", + "support.type.object.module", + "entity.name.type.module" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "support.constant.math", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "support.constant.property.math", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "support.constant.json", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "support.type.object.dom", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": [ + "support.variable.dom", + "support.variable.property.dom" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "support.variable.property.process", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "meta.property.object", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "variable.parameter.function.js", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "keyword.other.template.begin", + "keyword.other.template.end" + ], + "settings": { + "foreground": "#215584" + } + }, + { + "scope": [ + "keyword.other.substitution.begin", + "keyword.other.substitution.end" + ], + "settings": { + "foreground": "#215584" + } + }, + { + "scope": [ + "punctuation.definition.template-expression.begin", + "punctuation.definition.template-expression.end" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "meta.template.expression", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.section.embedded", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "variable.interpolation", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "punctuation.section.embedded.begin", + "punctuation.section.embedded.end" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "punctuation.quasi.element", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "support.type.primitive.ts", + "support.type.builtin.ts", + "support.type.primitive.tsx", + "support.type.builtin.tsx" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "support.type.type.flowtype", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "support.type.primitive", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "meta.decorator", + "meta.decorator punctuation.decorator" + ], + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "entity.name.function.decorator", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "punctuation.definition.decorator", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "support.variable.magic.python", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "variable.parameter.function.language.special.self.python", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "punctuation.separator.period.python", + "punctuation.separator.element.python", + "punctuation.parenthesis.begin.python", + "punctuation.parenthesis.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.arguments.begin.python", + "punctuation.definition.arguments.end.python", + "punctuation.separator.arguments.python", + "punctuation.definition.list.begin.python", + "punctuation.definition.list.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.python", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "keyword.operator.logical.python", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "meta.function-call.generic.python", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "constant.character.format.placeholder.other.python", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "meta.function.decorator.python", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": [ + "support.token.decorator.python", + "meta.function.decorator.identifier.python" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "storage.modifier.lifetime.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.function.std.rust", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "entity.name.lifetime.rust", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "variable.language.rust", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "keyword.operator.misc.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.sigil.rust", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "support.constant.core.rust", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "meta.function.c", + "meta.function.cpp" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "punctuation.section.block.begin.bracket.curly.cpp", + "punctuation.section.block.end.bracket.curly.cpp", + "punctuation.terminator.statement.c", + "punctuation.section.block.begin.bracket.curly.c", + "punctuation.section.block.end.bracket.curly.c", + "punctuation.section.parens.begin.bracket.round.c", + "punctuation.section.parens.end.bracket.round.c", + "punctuation.section.parameters.begin.bracket.round.c", + "punctuation.section.parameters.end.bracket.round.c" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.assignment.c", + "keyword.operator.comparison.c", + "keyword.operator.c", + "keyword.operator.increment.c", + "keyword.operator.decrement.c", + "keyword.operator.bitwise.shift.c" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "keyword.operator.assignment.cpp", + "keyword.operator.comparison.cpp", + "keyword.operator.cpp", + "keyword.operator.increment.cpp", + "keyword.operator.decrement.cpp", + "keyword.operator.bitwise.shift.cpp" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "punctuation.separator.c", + "punctuation.separator.cpp" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "support.type.posix-reserved.c", + "support.type.posix-reserved.cpp" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": [ + "keyword.operator.sizeof.c", + "keyword.operator.sizeof.cpp" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "variable.c", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.annotation.java", + "storage.type.object.array.java" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "source.java", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "punctuation.section.block.begin.java", + "punctuation.section.block.end.java", + "punctuation.definition.method-parameters.begin.java", + "punctuation.definition.method-parameters.end.java", + "meta.method.identifier.java", + "punctuation.section.method.begin.java", + "punctuation.section.method.end.java", + "punctuation.terminator.java", + "punctuation.section.class.begin.java", + "punctuation.section.class.end.java", + "punctuation.section.inner-class.begin.java", + "punctuation.section.inner-class.end.java", + "meta.method-call.java", + "punctuation.section.class.begin.bracket.curly.java", + "punctuation.section.class.end.bracket.curly.java", + "punctuation.section.method.begin.bracket.curly.java", + "punctuation.section.method.end.bracket.curly.java", + "punctuation.separator.period.java", + "punctuation.bracket.angle.java", + "punctuation.definition.annotation.java", + "meta.method.body.java" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.method.java", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": [ + "storage.modifier.import.java", + "storage.type.java", + "storage.type.generic.java" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "keyword.operator.instanceof.java", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "meta.definition.variable.name.java", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "token.variable.parameter.java", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "import.storage.java", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "token.package.keyword", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "token.package", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.storage.type.java", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "keyword.operator.assignment.go", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "keyword.operator.arithmetic.go", + "keyword.operator.address.go" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "entity.name.package.go", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "support.other.namespace.use.php", + "support.other.namespace.use-as.php", + "support.other.namespace.php", + "entity.other.alias.php", + "meta.interface.php" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "keyword.operator.error-control.php", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "keyword.operator.type.php", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "punctuation.section.array.begin.php", + "punctuation.section.array.end.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.php", + "meta.other.type.phpdoc.php", + "keyword.other.type.php", + "keyword.other.array.phpdoc.php" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "meta.function-call.php", + "meta.function-call.object.php", + "meta.function-call.static.php" + ], + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": [ + "punctuation.definition.parameters.begin.bracket.round.php", + "punctuation.definition.parameters.end.bracket.round.php", + "punctuation.separator.delimiter.php", + "punctuation.section.scope.begin.php", + "punctuation.section.scope.end.php", + "punctuation.terminator.expression.php", + "punctuation.definition.arguments.begin.bracket.round.php", + "punctuation.definition.arguments.end.bracket.round.php", + "punctuation.definition.storage-type.begin.bracket.round.php", + "punctuation.definition.storage-type.end.bracket.round.php", + "punctuation.definition.array.begin.bracket.round.php", + "punctuation.definition.array.end.bracket.round.php", + "punctuation.definition.begin.bracket.round.php", + "punctuation.definition.end.bracket.round.php", + "punctuation.definition.begin.bracket.curly.php", + "punctuation.definition.end.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php", + "punctuation.definition.section.switch-block.start.bracket.curly.php", + "punctuation.definition.section.switch-block.begin.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "support.constant.ext.php", + "support.constant.std.php", + "support.constant.core.php", + "support.constant.parser-token.php" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "entity.name.goto-label.php", + "support.other.php" + ], + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": [ + "keyword.operator.logical.php", + "keyword.operator.bitwise.php", + "keyword.operator.arithmetic.php" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "keyword.operator.regexp.php", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "keyword.operator.comparison.php", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": [ + "keyword.operator.heredoc.php", + "keyword.operator.nowdoc.php" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "variable.other.class.php", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "invalid.illegal.non-null-typehinted.php", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "variable.other.generic-type.haskell", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "storage.type.haskell", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "storage.type.cs", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.name.variable.local.cs", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "entity.name.label.cs", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "entity.name.scope-resolution.function.call", + "entity.name.scope-resolution.function.definition" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "punctuation.definition.delayed.unison", + "punctuation.definition.list.begin.unison", + "punctuation.definition.list.end.unison", + "punctuation.definition.ability.begin.unison", + "punctuation.definition.ability.end.unison", + "punctuation.operator.assignment.as.unison", + "punctuation.separator.pipe.unison", + "punctuation.separator.delimiter.unison", + "punctuation.definition.hash.unison" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "support.constant.edge", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "support.type.prelude.elm", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "support.constant.elm", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.global.clojure", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "meta.symbol.clojure", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "constant.keyword.clojure", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": [ + "meta.arguments.coffee", + "variable.parameter.function.coffee" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "storage.modifier.import.groovy", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "meta.method.groovy", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "meta.definition.variable.name.groovy", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "meta.definition.class.inherited.classes.groovy", + "settings": { + "foreground": "#215584" + } + }, + { + "scope": "support.variable.semantic.hlsl", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "support.type.texture.hlsl", + "support.type.sampler.hlsl", + "support.type.object.hlsl", + "support.type.object.rw.hlsl", + "support.type.fx.hlsl", + "support.type.object.hlsl" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "text.variable", + "text.bracketed" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "support.type.swift", + "support.type.vb.asp" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "meta.scope.prerequisites.makefile", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "source.makefile", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "source.ini", + "settings": { + "foreground": "#215584" + } + }, + { + "scope": "constant.language.symbol.ruby", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": [ + "function.parameter.ruby", + "function.parameter.cs" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "constant.language.symbol.elixir", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "entity.name.function.xi", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.name.class.xi", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "constant.character.character-class.regexp.xi", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "constant.regexp.xi", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "keyword.control.xi", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "invalid.xi", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "beginning.punctuation.definition.quote.markdown.xi", + "settings": { + "foreground": "#215584" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "constant.character.xi", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "accent.xi", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "wikiword.xi", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "constant.other.color.rgb-value.xi", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "punctuation.definition.tag.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "support.constant.property-value.scss", + "support.constant.property-value.css" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "keyword.operator.css", + "keyword.operator.scss", + "keyword.operator.less" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": [ + "support.constant.color.w3c-standard-color-name.css", + "support.constant.color.w3c-standard-color-name.scss" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "punctuation.separator.list.comma.css", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.vendored.property-name.css", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "support.type.property-name.css", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "support.type.property-name", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.property-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.font-name", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.other.attribute-name.class.css", + "settings": { + "foreground": "#ac741d", + "fontStyle": "normal" + } + }, + { + "scope": "entity.other.attribute-name.id", + "settings": { + "foreground": "#5731a7", + "fontStyle": "normal" + } + }, + { + "scope": [ + "entity.other.attribute-name.pseudo-element", + "entity.other.attribute-name.pseudo-class" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "meta.selector", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "selector.sass", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "rgb-value", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "inline-color-decoration rgb-value", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "less rgb-value", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "control.elements", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "keyword.operator.less", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.name.tag", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "entity.other.attribute-name", + "settings": { + "foreground": "#ac741d", + "fontStyle": "normal" + } + }, + { + "scope": "constant.character.entity", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "meta.tag", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "invalid.illegal.bad-ampersand.html", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "markup.heading", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "markup.heading punctuation.definition.heading", + "entity.name.section" + ], + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "entity.name.section.markdown", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "punctuation.definition.heading.markdown", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "markup.heading.setext", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "markup.heading.setext.1.markdown", + "markup.heading.setext.2.markdown" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "markup.bold", + "todo.bold" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "punctuation.definition.bold", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "punctuation.definition.bold.markdown", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "markup.italic", + "punctuation.definition.italic", + "todo.emphasis" + ], + "settings": { + "foreground": "#8836c7", + "fontStyle": "italic" + } + }, + { + "scope": "emphasis md", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "markup.italic.markdown", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": [ + "markup.underline.link.markdown", + "markup.underline.link.image.markdown" + ], + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": [ + "string.other.link.title.markdown", + "string.other.link.description.markdown" + ], + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "punctuation.definition.metadata.markdown", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "markup.inline.raw.markdown", + "markup.inline.raw.string.markdown" + ], + "settings": { + "foreground": "#215584" + } + }, + { + "scope": "punctuation.definition.list.begin.markdown", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "punctuation.definition.list.markdown", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "punctuation.definition.string.begin.markdown", + "punctuation.definition.string.end.markdown" + ], + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "markup.quote.markdown", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "keyword.other.unit", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "markup.changed.diff", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "meta.diff.header.from-file", + "meta.diff.header.to-file", + "punctuation.definition.from-file.diff", + "punctuation.definition.to-file.diff" + ], + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "markup.inserted.diff", + "settings": { + "foreground": "#215584" + } + }, + { + "scope": "markup.deleted.diff", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "string.regexp", + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "constant.other.character-class.regexp", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > value.json > string.quoted.json", + "source.json meta.structure.array.json > value.json > string.quoted.json", + "source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation", + "source.json meta.structure.array.json > value.json > string.quoted.json > punctuation" + ], + "settings": { + "foreground": "#215584" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > constant.language.json", + "source.json meta.structure.array.json > constant.language.json" + ], + "settings": { + "foreground": "#2182a1" + } + }, + { + "scope": "support.type.property-name.json", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "support.type.property-name.json punctuation", + "settings": { + "foreground": "#ac6023" + } + }, + { + "scope": "punctuation.definition.block.sequence.item.yaml", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.end", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.begin", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.info-token", + "settings": { + "foreground": "#5731a7" + } + }, + { + "scope": "token.warn-token", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "token.error-token", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "token.debug-token", + "settings": { + "foreground": "#8836c7" + } + }, + { + "scope": "invalid.illegal", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "invalid.broken", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "invalid.deprecated", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "invalid.unimplemented", + "settings": { + "foreground": "#0a0a0a" + } + } + ], + "semanticTokenColors": { + "comment": "#737373", + "string": "#215584", + "number": "#2182a1", + "regexp": "#2182a1", + "keyword": "#8836c7", + "variable": "#ac6023", + "parameter": "#636363", + "property": "#ac6023", + "function": "#5731a7", + "method": "#5731a7", + "type": "#a631be", + "class": "#a631be", + "namespace": "#ac741d", + "enumMember": "#2182a1", + "variable.constant": "#ac741d", + "variable.defaultLibrary": "#ac741d", + "decorator": "#216cab" + } +} \ No newline at end of file diff --git a/themes/pierre-light-tritanopia.json b/themes/pierre-light-tritanopia.json new file mode 100644 index 0000000..304b560 --- /dev/null +++ b/themes/pierre-light-tritanopia.json @@ -0,0 +1,1961 @@ +{ + "name": "pierre-light-tritanopia", + "displayName": "Pierre Light Tritanopia", + "type": "light", + "colors": { + "editor.background": "#ffffff", + "editor.foreground": "#0a0a0a", + "foreground": "#0a0a0a", + "focusBorder": "#009fff", + "selection.background": "#dfebff", + "editor.selectionBackground": "#009fff2e", + "editor.lineHighlightBackground": "#dfebff8c", + "editorCursor.foreground": "#009fff", + "editorLineNumber.foreground": "#737373", + "editorLineNumber.activeForeground": "#525252", + "editorIndentGuide.background": "#e5e5e5", + "editorIndentGuide.activeBackground": "#d4d4d4", + "diffEditor.insertedTextBackground": "#1e858e33", + "diffEditor.deletedTextBackground": "#d5512f33", + "sideBar.background": "#f5f5f5", + "sideBar.foreground": "#525252", + "sideBar.border": "#e5e5e5", + "sideBarTitle.foreground": "#0a0a0a", + "sideBarSectionHeader.background": "#f5f5f5", + "sideBarSectionHeader.foreground": "#525252", + "sideBarSectionHeader.border": "#e5e5e5", + "activityBar.background": "#f5f5f5", + "activityBar.foreground": "#0a0a0a", + "activityBar.border": "#e5e5e5", + "activityBar.activeBorder": "#009fff", + "activityBarBadge.background": "#009fff", + "activityBarBadge.foreground": "#ffffff", + "titleBar.activeBackground": "#f5f5f5", + "titleBar.activeForeground": "#0a0a0a", + "titleBar.inactiveBackground": "#f5f5f5", + "titleBar.inactiveForeground": "#737373", + "titleBar.border": "#e5e5e5", + "list.activeSelectionBackground": "#dfebffcc", + "list.activeSelectionForeground": "#0a0a0a", + "list.inactiveSelectionBackground": "#dfebff73", + "list.hoverBackground": "#dfebff59", + "list.focusOutline": "#009fff", + "tab.activeBackground": "#ffffff", + "tab.activeForeground": "#0a0a0a", + "tab.activeBorderTop": "#009fff", + "tab.inactiveBackground": "#f5f5f5", + "tab.inactiveForeground": "#737373", + "tab.border": "#e5e5e5", + "editorGroupHeader.tabsBackground": "#f5f5f5", + "editorGroupHeader.tabsBorder": "#e5e5e5", + "panel.background": "#f5f5f5", + "panel.border": "#e5e5e5", + "panelTitle.activeBorder": "#009fff", + "panelTitle.activeForeground": "#0a0a0a", + "panelTitle.inactiveForeground": "#737373", + "statusBar.background": "#f5f5f5", + "statusBar.foreground": "#525252", + "statusBar.border": "#e5e5e5", + "statusBar.noFolderBackground": "#f5f5f5", + "statusBar.debuggingBackground": "#ffab16", + "statusBar.debuggingForeground": "#ffffff", + "statusBarItem.remoteBackground": "#f5f5f5", + "statusBarItem.remoteForeground": "#525252", + "input.background": "#ededed", + "input.border": "#d4d4d4", + "input.foreground": "#0a0a0a", + "input.placeholderForeground": "#8a8a8a", + "dropdown.background": "#ededed", + "dropdown.border": "#d4d4d4", + "dropdown.foreground": "#0a0a0a", + "button.background": "#009fff", + "button.foreground": "#ffffff", + "button.hoverBackground": "#1aa9ff", + "textLink.foreground": "#009fff", + "textLink.activeForeground": "#009fff", + "notifications.background": "#f7f7f7", + "notifications.foreground": "#0a0a0a", + "notifications.border": "#e5e5e5", + "notificationToast.border": "#e5e5e5", + "notificationCenter.border": "#e5e5e5", + "notificationCenterHeader.background": "#f7f7f7", + "notificationCenterHeader.foreground": "#525252", + "notificationLink.foreground": "#009fff", + "notificationsErrorIcon.foreground": "#d5512f", + "notificationsWarningIcon.foreground": "#ffab16", + "notificationsInfoIcon.foreground": "#1a85d4", + "quickInput.background": "#f7f7f7", + "quickInput.foreground": "#0a0a0a", + "quickInputTitle.background": "#f7f7f7", + "widget.border": "#e5e5e5", + "gitDecoration.addedResourceForeground": "#1e858e", + "gitDecoration.conflictingResourceForeground": "#992a75", + "gitDecoration.modifiedResourceForeground": "#009fff", + "gitDecoration.deletedResourceForeground": "#d5512f", + "gitDecoration.untrackedResourceForeground": "#1e858e", + "gitDecoration.ignoredResourceForeground": "#737373", + "merge.currentHeaderBackground": "#992a7533", + "merge.currentContentBackground": "#992a7514", + "merge.incomingHeaderBackground": "#1a85d433", + "merge.incomingContentBackground": "#1a85d414", + "editorOverviewRuler.currentContentForeground": "#992a75", + "editorOverviewRuler.incomingContentForeground": "#1a85d4", + "terminal.titleForeground": "#525252", + "terminal.titleInactiveForeground": "#737373", + "terminal.background": "#f5f5f5", + "terminal.foreground": "#525252", + "terminal.ansiBlack": "#1d1d1d", + "terminal.ansiRed": "#d5512f", + "terminal.ansiGreen": "#1e858e", + "terminal.ansiYellow": "#d5901c", + "terminal.ansiBlue": "#1a85d4", + "terminal.ansiMagenta": "#992a75", + "terminal.ansiCyan": "#17a5af", + "terminal.ansiWhite": "#bcbcbc", + "terminal.ansiBrightBlack": "#1d1d1d", + "terminal.ansiBrightRed": "#ff5d36", + "terminal.ansiBrightGreen": "#17a5af", + "terminal.ansiBrightYellow": "#ffab16", + "terminal.ansiBrightBlue": "#009fff", + "terminal.ansiBrightMagenta": "#bd2e90", + "terminal.ansiBrightCyan": "#00c5d2", + "terminal.ansiBrightWhite": "#bcbcbc" + }, + "tokenColors": [ + { + "scope": [ + "comment", + "punctuation.definition.comment" + ], + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "comment markup.link", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "string", + "constant.other.symbol" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "punctuation.definition.string.begin", + "punctuation.definition.string.end" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "constant.numeric", + "constant.language.boolean" + ], + "settings": { + "foreground": "#1a85d4" + } + }, + { + "scope": "constant", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "punctuation.definition.constant", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "constant.language", + "settings": { + "foreground": "#1a85d4" + } + }, + { + "scope": "variable.other.constant", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "keyword.control", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "storage", + "storage.type", + "storage.modifier" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "token.storage", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "keyword.operator.new", + "keyword.operator.expression.instanceof", + "keyword.operator.expression.typeof", + "keyword.operator.expression.void", + "keyword.operator.expression.delete", + "keyword.operator.expression.in", + "keyword.operator.expression.of", + "keyword.operator.expression.keyof" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "keyword.operator.delete", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "variable", + "identifier", + "meta.definition.variable" + ], + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": [ + "variable.other.readwrite", + "meta.object-literal.key", + "support.variable.property", + "support.variable.object.process", + "support.variable.object.node" + ], + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": "variable.language", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "variable.parameter.function", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "function.parameter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "variable.parameter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "variable.parameter.function.language.python", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "variable.parameter.function.python", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "support.function", + "entity.name.function", + "meta.function-call", + "meta.require", + "support.function.any-method", + "variable.function" + ], + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "keyword.other.special-method", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "entity.name.function", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "support.function.console", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": [ + "support.type", + "entity.name.type", + "entity.name.class", + "storage.type" + ], + "settings": { + "foreground": "#bd2e90" + } + }, + { + "scope": [ + "support.class", + "entity.name.type.class" + ], + "settings": { + "foreground": "#bd2e90" + } + }, + { + "scope": [ + "entity.name.class", + "variable.other.class.js", + "variable.other.class.ts" + ], + "settings": { + "foreground": "#bd2e90" + } + }, + { + "scope": "entity.name.class.identifier.namespace.type", + "settings": { + "foreground": "#bd2e90" + } + }, + { + "scope": "entity.name.type.namespace", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "entity.other.inherited-class", + "settings": { + "foreground": "#bd2e90" + } + }, + { + "scope": "entity.name.namespace", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "keyword.operator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.logical", + "keyword.operator.bitwise", + "keyword.operator.channel" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "keyword.operator.arithmetic", + "keyword.operator.comparison", + "keyword.operator.relational", + "keyword.operator.increment", + "keyword.operator.decrement" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "keyword.operator.assignment", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "keyword.operator.assignment.compound", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "keyword.operator.assignment.compound.js", + "keyword.operator.assignment.compound.ts" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "keyword.operator.ternary", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "keyword.operator.optional", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "punctuation", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.delimiter", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.separator.key-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.terminator", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.square", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.brace.round", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "function.brace", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.parameters", + "punctuation.definition.typeparameters" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.block", + "punctuation.definition.tag" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "meta.tag.tsx", + "meta.tag.jsx", + "meta.tag.js", + "meta.tag.ts" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.expression.import", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "keyword.operator.module", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "support.type.object.console", + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": [ + "support.module.node", + "support.type.object.module", + "entity.name.type.module" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "support.constant.math", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "support.constant.property.math", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "support.constant.json", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "support.type.object.dom", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "support.variable.dom", + "support.variable.property.dom" + ], + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": "support.variable.property.process", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "meta.property.object", + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": "variable.parameter.function.js", + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": [ + "keyword.other.template.begin", + "keyword.other.template.end" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "keyword.other.substitution.begin", + "keyword.other.substitution.end" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "punctuation.definition.template-expression.begin", + "punctuation.definition.template-expression.end" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "meta.template.expression", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "punctuation.section.embedded", + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": "variable.interpolation", + "settings": { + "foreground": "#ad4529" + } + }, + { + "scope": [ + "punctuation.section.embedded.begin", + "punctuation.section.embedded.end" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "punctuation.quasi.element", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "support.type.primitive.ts", + "support.type.builtin.ts", + "support.type.primitive.tsx", + "support.type.builtin.tsx" + ], + "settings": { + "foreground": "#bd2e90" + } + }, + { + "scope": "support.type.type.flowtype", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "support.type.primitive", + "settings": { + "foreground": "#bd2e90" + } + }, + { + "scope": [ + "meta.decorator", + "meta.decorator punctuation.decorator" + ], + "settings": { + "foreground": "#1a85d4" + } + }, + { + "scope": "entity.name.function.decorator", + "settings": { + "foreground": "#1a85d4" + } + }, + { + "scope": "punctuation.definition.decorator", + "settings": { + "foreground": "#1a85d4" + } + }, + { + "scope": "support.variable.magic.python", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "variable.parameter.function.language.special.self.python", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "punctuation.separator.period.python", + "punctuation.separator.element.python", + "punctuation.parenthesis.begin.python", + "punctuation.parenthesis.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "punctuation.definition.arguments.begin.python", + "punctuation.definition.arguments.end.python", + "punctuation.separator.arguments.python", + "punctuation.definition.list.begin.python", + "punctuation.definition.list.end.python" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.python", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "keyword.operator.logical.python", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "meta.function-call.generic.python", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "constant.character.format.placeholder.other.python", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "meta.function.decorator.python", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": [ + "support.token.decorator.python", + "meta.function.decorator.identifier.python" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "storage.modifier.lifetime.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.function.std.rust", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "entity.name.lifetime.rust", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "variable.language.rust", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "keyword.operator.misc.rust", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "keyword.operator.sigil.rust", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "support.constant.core.rust", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "meta.function.c", + "meta.function.cpp" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "punctuation.section.block.begin.bracket.curly.cpp", + "punctuation.section.block.end.bracket.curly.cpp", + "punctuation.terminator.statement.c", + "punctuation.section.block.begin.bracket.curly.c", + "punctuation.section.block.end.bracket.curly.c", + "punctuation.section.parens.begin.bracket.round.c", + "punctuation.section.parens.end.bracket.round.c", + "punctuation.section.parameters.begin.bracket.round.c", + "punctuation.section.parameters.end.bracket.round.c" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "keyword.operator.assignment.c", + "keyword.operator.comparison.c", + "keyword.operator.c", + "keyword.operator.increment.c", + "keyword.operator.decrement.c", + "keyword.operator.bitwise.shift.c" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "keyword.operator.assignment.cpp", + "keyword.operator.comparison.cpp", + "keyword.operator.cpp", + "keyword.operator.increment.cpp", + "keyword.operator.decrement.cpp", + "keyword.operator.bitwise.shift.cpp" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "punctuation.separator.c", + "punctuation.separator.cpp" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "support.type.posix-reserved.c", + "support.type.posix-reserved.cpp" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "keyword.operator.sizeof.c", + "keyword.operator.sizeof.cpp" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "variable.c", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.annotation.java", + "storage.type.object.array.java" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "source.java", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "punctuation.section.block.begin.java", + "punctuation.section.block.end.java", + "punctuation.definition.method-parameters.begin.java", + "punctuation.definition.method-parameters.end.java", + "meta.method.identifier.java", + "punctuation.section.method.begin.java", + "punctuation.section.method.end.java", + "punctuation.terminator.java", + "punctuation.section.class.begin.java", + "punctuation.section.class.end.java", + "punctuation.section.inner-class.begin.java", + "punctuation.section.inner-class.end.java", + "meta.method-call.java", + "punctuation.section.class.begin.bracket.curly.java", + "punctuation.section.class.end.bracket.curly.java", + "punctuation.section.method.begin.bracket.curly.java", + "punctuation.section.method.end.bracket.curly.java", + "punctuation.separator.period.java", + "punctuation.bracket.angle.java", + "punctuation.definition.annotation.java", + "meta.method.body.java" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "meta.method.java", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": [ + "storage.modifier.import.java", + "storage.type.java", + "storage.type.generic.java" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "keyword.operator.instanceof.java", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "meta.definition.variable.name.java", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "token.variable.parameter.java", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "import.storage.java", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "token.package.keyword", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "token.package", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.storage.type.java", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "keyword.operator.assignment.go", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "keyword.operator.arithmetic.go", + "keyword.operator.address.go" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "entity.name.package.go", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "support.other.namespace.use.php", + "support.other.namespace.use-as.php", + "support.other.namespace.php", + "entity.other.alias.php", + "meta.interface.php" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "keyword.operator.error-control.php", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "keyword.operator.type.php", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "punctuation.section.array.begin.php", + "punctuation.section.array.end.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "storage.type.php", + "meta.other.type.phpdoc.php", + "keyword.other.type.php", + "keyword.other.array.phpdoc.php" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "meta.function-call.php", + "meta.function-call.object.php", + "meta.function-call.static.php" + ], + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": [ + "punctuation.definition.parameters.begin.bracket.round.php", + "punctuation.definition.parameters.end.bracket.round.php", + "punctuation.separator.delimiter.php", + "punctuation.section.scope.begin.php", + "punctuation.section.scope.end.php", + "punctuation.terminator.expression.php", + "punctuation.definition.arguments.begin.bracket.round.php", + "punctuation.definition.arguments.end.bracket.round.php", + "punctuation.definition.storage-type.begin.bracket.round.php", + "punctuation.definition.storage-type.end.bracket.round.php", + "punctuation.definition.array.begin.bracket.round.php", + "punctuation.definition.array.end.bracket.round.php", + "punctuation.definition.begin.bracket.round.php", + "punctuation.definition.end.bracket.round.php", + "punctuation.definition.begin.bracket.curly.php", + "punctuation.definition.end.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php", + "punctuation.definition.section.switch-block.start.bracket.curly.php", + "punctuation.definition.section.switch-block.begin.bracket.curly.php", + "punctuation.definition.section.switch-block.end.bracket.curly.php" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "support.constant.ext.php", + "support.constant.std.php", + "support.constant.core.php", + "support.constant.parser-token.php" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "entity.name.goto-label.php", + "support.other.php" + ], + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": [ + "keyword.operator.logical.php", + "keyword.operator.bitwise.php", + "keyword.operator.arithmetic.php" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "keyword.operator.regexp.php", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "keyword.operator.comparison.php", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "keyword.operator.heredoc.php", + "keyword.operator.nowdoc.php" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "variable.other.class.php", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "invalid.illegal.non-null-typehinted.php", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "variable.other.generic-type.haskell", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "storage.type.haskell", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "storage.type.cs", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "entity.name.variable.local.cs", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "entity.name.label.cs", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "entity.name.scope-resolution.function.call", + "entity.name.scope-resolution.function.definition" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "punctuation.definition.delayed.unison", + "punctuation.definition.list.begin.unison", + "punctuation.definition.list.end.unison", + "punctuation.definition.ability.begin.unison", + "punctuation.definition.ability.end.unison", + "punctuation.operator.assignment.as.unison", + "punctuation.separator.pipe.unison", + "punctuation.separator.delimiter.unison", + "punctuation.definition.hash.unison" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "support.constant.edge", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "support.type.prelude.elm", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "support.constant.elm", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.global.clojure", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "meta.symbol.clojure", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "constant.keyword.clojure", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "meta.arguments.coffee", + "variable.parameter.function.coffee" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "storage.modifier.import.groovy", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "meta.method.groovy", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "meta.definition.variable.name.groovy", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "meta.definition.class.inherited.classes.groovy", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "support.variable.semantic.hlsl", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "support.type.texture.hlsl", + "support.type.sampler.hlsl", + "support.type.object.hlsl", + "support.type.object.rw.hlsl", + "support.type.fx.hlsl", + "support.type.object.hlsl" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "text.variable", + "text.bracketed" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "support.type.swift", + "support.type.vb.asp" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "meta.scope.prerequisites.makefile", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "source.makefile", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "source.ini", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "constant.language.symbol.ruby", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "function.parameter.ruby", + "function.parameter.cs" + ], + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "constant.language.symbol.elixir", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "entity.name.function.xi", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "entity.name.class.xi", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "constant.character.character-class.regexp.xi", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "constant.regexp.xi", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "keyword.control.xi", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "invalid.xi", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "beginning.punctuation.definition.quote.markdown.xi", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "constant.character.xi", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "accent.xi", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "wikiword.xi", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "constant.other.color.rgb-value.xi", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "punctuation.definition.tag.xi", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": [ + "support.constant.property-value.scss", + "support.constant.property-value.css" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "keyword.operator.css", + "keyword.operator.scss", + "keyword.operator.less" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "support.constant.color.w3c-standard-color-name.css", + "support.constant.color.w3c-standard-color-name.scss" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "punctuation.separator.list.comma.css", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.type.vendored.property-name.css", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "support.type.property-name.css", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "support.type.property-name", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.property-value", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "support.constant.font-name", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.other.attribute-name.class.css", + "settings": { + "foreground": "#1e858e", + "fontStyle": "normal" + } + }, + { + "scope": "entity.other.attribute-name.id", + "settings": { + "foreground": "#216cab", + "fontStyle": "normal" + } + }, + { + "scope": [ + "entity.other.attribute-name.pseudo-element", + "entity.other.attribute-name.pseudo-class" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "meta.selector", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "selector.sass", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "rgb-value", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "inline-color-decoration rgb-value", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "less rgb-value", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "control.elements", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "keyword.operator.less", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "entity.name.tag", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "entity.other.attribute-name", + "settings": { + "foreground": "#1e858e", + "fontStyle": "normal" + } + }, + { + "scope": "constant.character.entity", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "meta.tag", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "invalid.illegal.bad-ampersand.html", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "markup.heading", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "markup.heading punctuation.definition.heading", + "entity.name.section" + ], + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "entity.name.section.markdown", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "punctuation.definition.heading.markdown", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "markup.heading.setext", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": [ + "markup.heading.setext.1.markdown", + "markup.heading.setext.2.markdown" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "markup.bold", + "todo.bold" + ], + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "punctuation.definition.bold", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "punctuation.definition.bold.markdown", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": [ + "markup.italic", + "punctuation.definition.italic", + "todo.emphasis" + ], + "settings": { + "foreground": "#a631be", + "fontStyle": "italic" + } + }, + { + "scope": "emphasis md", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "markup.italic.markdown", + "settings": { + "fontStyle": "italic" + } + }, + { + "scope": [ + "markup.underline.link.markdown", + "markup.underline.link.image.markdown" + ], + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": [ + "string.other.link.title.markdown", + "string.other.link.description.markdown" + ], + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "punctuation.definition.metadata.markdown", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "markup.inline.raw.markdown", + "markup.inline.raw.string.markdown" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "punctuation.definition.list.begin.markdown", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "punctuation.definition.list.markdown", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "beginning.punctuation.definition.list.markdown", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "punctuation.definition.string.begin.markdown", + "punctuation.definition.string.end.markdown" + ], + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "markup.quote.markdown", + "settings": { + "foreground": "#737373" + } + }, + { + "scope": "keyword.other.unit", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "markup.changed.diff", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "meta.diff.header.from-file", + "meta.diff.header.to-file", + "punctuation.definition.from-file.diff", + "punctuation.definition.to-file.diff" + ], + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "markup.inserted.diff", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "markup.deleted.diff", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "string.regexp", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "constant.other.character-class.regexp", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > value.json > string.quoted.json", + "source.json meta.structure.array.json > value.json > string.quoted.json", + "source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation", + "source.json meta.structure.array.json > value.json > string.quoted.json > punctuation" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": [ + "source.json meta.structure.dictionary.json > constant.language.json", + "source.json meta.structure.array.json > constant.language.json" + ], + "settings": { + "foreground": "#1e858e" + } + }, + { + "scope": "support.type.property-name.json", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "support.type.property-name.json punctuation", + "settings": { + "foreground": "#d5512f" + } + }, + { + "scope": "punctuation.definition.block.sequence.item.yaml", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.end", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "block.scope.begin", + "settings": { + "foreground": "#636363" + } + }, + { + "scope": "token.info-token", + "settings": { + "foreground": "#216cab" + } + }, + { + "scope": "token.warn-token", + "settings": { + "foreground": "#ac741d" + } + }, + { + "scope": "token.error-token", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "token.debug-token", + "settings": { + "foreground": "#a631be" + } + }, + { + "scope": "invalid.illegal", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "invalid.broken", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "invalid.deprecated", + "settings": { + "foreground": "#0a0a0a" + } + }, + { + "scope": "invalid.unimplemented", + "settings": { + "foreground": "#0a0a0a" + } + } + ], + "semanticTokenColors": { + "comment": "#737373", + "string": "#1e858e", + "number": "#1a85d4", + "regexp": "#1e858e", + "keyword": "#a631be", + "variable": "#ad4529", + "parameter": "#636363", + "property": "#ad4529", + "function": "#216cab", + "method": "#216cab", + "type": "#bd2e90", + "class": "#bd2e90", + "namespace": "#d5512f", + "enumMember": "#1e858e", + "variable.constant": "#ac741d", + "variable.defaultLibrary": "#d5512f", + "decorator": "#1a85d4" + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index adf931b..bf2df98 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,14 +8,13 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, - "outDir": "./dist", - "rootDir": "./src" + "outDir": "./dist" }, "ts-node": { "compilerOptions": { "module": "CommonJS" } }, - "include": ["src/**/*"], + "include": ["src/**/*", "scripts/**/*", "test/**/*"], "exclude": ["node_modules"] } diff --git a/zed/extension.toml b/zed/extension.toml index da6d905..58ab0fd 100644 --- a/zed/extension.toml +++ b/zed/extension.toml @@ -1,7 +1,7 @@ id = "pierre-theme" name = "Pierre" description = "Modern light and dark color themes built by Pierre for Diffs.com, and now for you." -version = "0.0.29" +version = "0.0.30" schema_version = 1 authors = ["pierrecomputer"] repository = "https://github.com/pierrecomputer/pierre-theme" diff --git a/zed/themes/pierre.json b/zed/themes/pierre.json index 7111bb1..4e1b168 100644 --- a/zed/themes/pierre.json +++ b/zed/themes/pierre.json @@ -502,132 +502,132 @@ } }, { - "name": "Pierre Light Soft", + "name": "Pierre Light Protanopia & Deuteranopia", "appearance": "light", "style": { - "background": "#f7f7f7", - "surface.background": "#f7f7f7", - "elevated_surface.background": "#fafafa", + "background": "#f5f5f5", + "surface.background": "#f5f5f5", + "elevated_surface.background": "#f7f7f7", "drop_target.background": "#009fff26", "editor.background": "#ffffff", - "editor.foreground": "#525252", + "editor.foreground": "#0a0a0a", "editor.gutter.background": "#ffffff", "editor.active_line.background": "#dfebff8c", - "editor.active_line_number": "#737373", - "editor.line_number": "#8a8a8a", + "editor.active_line_number": "#525252", + "editor.line_number": "#737373", "editor.highlighted_line.background": "#dfebff59", - "editor.indent_guide": "#ededed", - "editor.indent_guide_active": "#e5e5e5", - "editor.invisible": "#a3a3a3", - "editor.wrap_guide": "#ededed", - "editor.active_wrap_guide": "#e5e5e5", + "editor.indent_guide": "#e5e5e5", + "editor.indent_guide_active": "#d4d4d4", + "editor.invisible": "#8a8a8a", + "editor.wrap_guide": "#e5e5e5", + "editor.active_wrap_guide": "#d4d4d4", "editor.document_highlight.read_background": "#009fff1a", "editor.document_highlight.write_background": "#009fff2e", "editor.document_highlight.bracket_background": "#009fff33", - "editor.subheader.background": "#f7f7f7", - "text": "#525252", - "text.muted": "#8a8a8a", - "text.placeholder": "#a3a3a3", - "text.disabled": "#a3a3a3", + "editor.subheader.background": "#f5f5f5", + "text": "#0a0a0a", + "text.muted": "#737373", + "text.placeholder": "#8a8a8a", + "text.disabled": "#8a8a8a", "text.accent": "#009fff", - "border": "#e5e5e5", - "border.variant": "#ededed", + "border": "#d4d4d4", + "border.variant": "#e5e5e5", "border.focused": "#009fff", "border.selected": "#009fff", "border.transparent": "transparent", "border.disabled": "#d4d4d4", - "element.background": "#f5f5f5", + "element.background": "#ededed", "element.hover": "#dfebff80", "element.active": "#dfebffb3", "element.selected": "#dfebffcc", - "element.disabled": "#f5f5f580", + "element.disabled": "#ededed80", "ghost_element.background": "transparent", "ghost_element.hover": "#dfebff59", "ghost_element.active": "#dfebff8c", "ghost_element.selected": "#dfebffa6", "ghost_element.disabled": "transparent", - "icon": "#737373", - "icon.muted": "#8a8a8a", - "icon.disabled": "#a3a3a3", - "icon.placeholder": "#a3a3a3", + "icon": "#525252", + "icon.muted": "#737373", + "icon.disabled": "#8a8a8a", + "icon.placeholder": "#8a8a8a", "icon.accent": "#009fff", "link_text.hover": "#009fff", - "error": "#ff2e3f", - "error.background": "#ff2e3f1a", - "error.border": "#ff2e3f4d", + "error": "#ac6023", + "error.background": "#ac60231a", + "error.border": "#ac60234d", "warning": "#009fff", "warning.background": "#009fff1a", "warning.border": "#009fff4d", - "success": "#07c480", - "success.background": "#07c4801a", - "success.border": "#07c4804d", - "info": "#08c0ef", - "info.background": "#08c0ef1a", - "info.border": "#08c0ef4d", - "hint": "#8a8a8a", - "hint.background": "#8a8a8a1a", - "hint.border": "#8a8a8a33", - "predictive": "#a3a3a3", - "predictive.background": "#a3a3a31a", - "predictive.border": "#a3a3a333", - "unreachable": "#a3a3a3", - "unreachable.background": "#a3a3a30d", - "unreachable.border": "#a3a3a31a", - "created": "#07c480", - "created.background": "#07c4801a", - "created.border": "#07c4804d", + "success": "#216cab", + "success.background": "#216cab1a", + "success.border": "#216cab4d", + "info": "#2182a1", + "info.background": "#2182a11a", + "info.border": "#2182a14d", + "hint": "#737373", + "hint.background": "#7373731a", + "hint.border": "#73737333", + "predictive": "#8a8a8a", + "predictive.background": "#8a8a8a1a", + "predictive.border": "#8a8a8a33", + "unreachable": "#8a8a8a", + "unreachable.background": "#8a8a8a0d", + "unreachable.border": "#8a8a8a1a", + "created": "#216cab", + "created.background": "#216cab1a", + "created.border": "#216cab4d", "modified": "#009fff", "modified.background": "#009fff1a", "modified.border": "#009fff4d", - "deleted": "#ff2e3f", - "deleted.background": "#ff2e3f1a", - "deleted.border": "#ff2e3f4d", - "conflict": "#7b43f8", - "conflict.background": "#7b43f81a", - "conflict.border": "#7b43f84d", - "hidden": "#a3a3a3", - "hidden.background": "#a3a3a30d", - "hidden.border": "#a3a3a31a", - "ignored": "#8a8a8a", - "ignored.background": "#8a8a8a0d", - "ignored.border": "#8a8a8a1a", - "renamed": "#08c0ef", - "renamed.background": "#08c0ef1a", - "renamed.border": "#08c0ef4d", + "deleted": "#ac6023", + "deleted.background": "#ac60231a", + "deleted.border": "#ac60234d", + "conflict": "#58287c", + "conflict.background": "#58287c1a", + "conflict.border": "#58287c4d", + "hidden": "#8a8a8a", + "hidden.background": "#8a8a8a0d", + "hidden.border": "#8a8a8a1a", + "ignored": "#737373", + "ignored.background": "#7373730d", + "ignored.border": "#7373731a", + "renamed": "#2182a1", + "renamed.background": "#2182a11a", + "renamed.border": "#2182a14d", "search.match_background": "#ffca004d", - "tab_bar.background": "#f7f7f7", - "tab.active_background": "#f7f7f7", - "tab.inactive_background": "#f7f7f7", - "toolbar.background": "#f7f7f7", - "title_bar.background": "#f7f7f7", - "title_bar.inactive_background": "#f7f7f7", - "panel.background": "#f7f7f7", + "tab_bar.background": "#f5f5f5", + "tab.active_background": "#f5f5f5", + "tab.inactive_background": "#f5f5f5", + "toolbar.background": "#f5f5f5", + "title_bar.background": "#f5f5f5", + "title_bar.inactive_background": "#f5f5f5", + "panel.background": "#f5f5f5", "panel.focused_border": "#009fff", - "status_bar.background": "#f7f7f7", - "scrollbar.thumb.background": "#a3a3a34d", - "scrollbar.thumb.hover_background": "#a3a3a380", + "status_bar.background": "#f5f5f5", + "scrollbar.thumb.background": "#8a8a8a4d", + "scrollbar.thumb.hover_background": "#8a8a8a80", "scrollbar.thumb.border": "transparent", "scrollbar.track.background": "transparent", "scrollbar.track.border": "transparent", - "terminal.background": "#f7f7f7", - "terminal.foreground": "#737373", - "terminal.bright_foreground": "#525252", - "terminal.dim_foreground": "#8a8a8a", + "terminal.background": "#f5f5f5", + "terminal.foreground": "#525252", + "terminal.bright_foreground": "#0a0a0a", + "terminal.dim_foreground": "#737373", "terminal.ansi.black": "#1d1d1d", - "terminal.ansi.red": "#ff2e3f", - "terminal.ansi.green": "#0dbe4e", + "terminal.ansi.red": "#ac6023", + "terminal.ansi.green": "#216cab", "terminal.ansi.yellow": "#ffca00", - "terminal.ansi.blue": "#009fff", - "terminal.ansi.magenta": "#e130ac", - "terminal.ansi.cyan": "#08c0ef", + "terminal.ansi.blue": "#1a85d4", + "terminal.ansi.magenta": "#8836c7", + "terminal.ansi.cyan": "#2182a1", "terminal.ansi.white": "#bcbcbc", "terminal.ansi.bright_black": "#1d1d1d", - "terminal.ansi.bright_red": "#ff2e3f", - "terminal.ansi.bright_green": "#86c427", + "terminal.ansi.bright_red": "#d47628", + "terminal.ansi.bright_green": "#1a85d4", "terminal.ansi.bright_yellow": "#ffca00", "terminal.ansi.bright_blue": "#009fff", - "terminal.ansi.bright_magenta": "#e130ac", - "terminal.ansi.bright_cyan": "#08c0ef", + "terminal.ansi.bright_magenta": "#a13cee", + "terminal.ansi.bright_cyan": "#1ca1c7", "terminal.ansi.bright_white": "#bcbcbc", "players": [ { @@ -636,24 +636,24 @@ "selection": "#009fff40" }, { - "cursor": "#07c480", - "background": "#07c480", - "selection": "#07c48040" + "cursor": "#216cab", + "background": "#216cab", + "selection": "#216cab40" }, { - "cursor": "#ff678d", - "background": "#ff678d", - "selection": "#ff678d40" + "cursor": "#8836c7", + "background": "#8836c7", + "selection": "#8836c740" }, { - "cursor": "#9d6afb", - "background": "#9d6afb", - "selection": "#9d6afb40" + "cursor": "#5731a7", + "background": "#5731a7", + "selection": "#5731a740" }, { - "cursor": "#0dbe4e", - "background": "#0dbe4e", - "selection": "#0dbe4e40" + "cursor": "#215584", + "background": "#215584", + "selection": "#21558440" }, { "cursor": "#ffca00", @@ -661,94 +661,94 @@ "selection": "#ffca0040" }, { - "cursor": "#d568ea", - "background": "#d568ea", - "selection": "#d568ea40" + "cursor": "#a631be", + "background": "#a631be", + "selection": "#a631be40" }, { - "cursor": "#08c0ef", - "background": "#08c0ef", - "selection": "#08c0ef40" + "cursor": "#2182a1", + "background": "#2182a1", + "selection": "#2182a140" } ], "syntax": { "comment": { - "color": "#8a8a8a" + "color": "#737373" }, "comment.doc": { - "color": "#8a8a8a" + "color": "#737373" }, "string": { - "color": "#0dbe4e" + "color": "#215584" }, "string.escape": { - "color": "#00cab1" + "color": "#1e858e" }, "string.regex": { - "color": "#00c5d2" + "color": "#2182a1" }, "string.special": { - "color": "#00cab1" + "color": "#1e858e" }, "string.special.symbol": { - "color": "#ffca00" + "color": "#ac741d" }, "number": { - "color": "#08c0ef" + "color": "#2182a1" }, "constant": { - "color": "#ffca00" + "color": "#ac741d" }, "boolean": { - "color": "#08c0ef" + "color": "#2182a1" }, "keyword": { - "color": "#ff678d" + "color": "#8836c7" }, "keyword.operator": { - "color": "#68cdf2" + "color": "#2182a1" }, "function": { - "color": "#9d6afb" + "color": "#5731a7" }, "function.method": { - "color": "#9d6afb" + "color": "#5731a7" }, "function.builtin": { - "color": "#9d6afb" + "color": "#5731a7" }, "function.special.definition": { - "color": "#9d6afb" + "color": "#5731a7" }, "function.call": { - "color": "#9d6afb" + "color": "#5731a7" }, "type": { - "color": "#d568ea" + "color": "#a631be" }, "type.builtin": { - "color": "#d568ea" + "color": "#a631be" }, "constructor": { - "color": "#d568ea" + "color": "#a631be" }, "variable": { - "color": "#fe8c2c" + "color": "#ac6023" }, "variable.builtin": { - "color": "#ffab16" + "color": "#ac741d" }, "variable.member": { - "color": "#fe8c2c" + "color": "#ac6023" }, "variable.parameter": { - "color": "#737373" + "color": "#636363" }, "variable.special": { - "color": "#ffab16" + "color": "#ac741d" }, "property": { - "color": "#fe8c2c" + "color": "#ac6023" }, "property.css": { "color": "#009fff" @@ -760,215 +760,215 @@ "color": "#009fff" }, "value": { - "color": "#08c0ef" + "color": "#2182a1" }, "constant.css": { - "color": "#ffca00" + "color": "#ac741d" }, "string.plain": { - "color": "#08c0ef" + "color": "#2182a1" }, "plain_value": { - "color": "#08c0ef" + "color": "#2182a1" }, "tag.css": { - "color": "#ff5d36" + "color": "#ac6023" }, "tag_name": { - "color": "#ff5d36" + "color": "#ac6023" }, "class": { - "color": "#07c480" + "color": "#ac741d" }, "class_name": { - "color": "#07c480" + "color": "#ac741d" }, "selector.class": { - "color": "#07c480" + "color": "#ac741d" }, "selector.id": { - "color": "#9d6afb" + "color": "#5731a7" }, "id_name": { - "color": "#9d6afb" + "color": "#5731a7" }, "selector.pseudo": { - "color": "#68cdf2" + "color": "#2182a1" }, "pseudo_class_selector": { - "color": "#68cdf2" + "color": "#2182a1" }, "pseudo_element_selector": { - "color": "#68cdf2" + "color": "#2182a1" }, "keyword.directive": { - "color": "#ff678d" + "color": "#8836c7" }, "keyword.control.at-rule": { - "color": "#ff678d" + "color": "#8836c7" }, "at_keyword": { - "color": "#ff678d" + "color": "#8836c7" }, "variable.scss": { - "color": "#fe8c2c" + "color": "#ac6023" }, "variable.css": { - "color": "#fe8c2c" + "color": "#ac6023" }, "property.custom": { - "color": "#fe8c2c" + "color": "#ac6023" }, "unit": { - "color": "#08c0ef" + "color": "#2182a1" }, "number.unit": { - "color": "#08c0ef" + "color": "#2182a1" }, "color": { - "color": "#ffca00" + "color": "#ac741d" }, "constant.color": { - "color": "#ffca00" + "color": "#ac741d" }, "keyword.important": { - "color": "#ff678d" + "color": "#8836c7" }, "variable.language": { - "color": "#ffab16" + "color": "#ac741d" }, "this": { - "color": "#ffab16" + "color": "#ac741d" }, "self": { - "color": "#ffab16" + "color": "#ac741d" }, "type.class": { - "color": "#d568ea" + "color": "#a631be" }, "property.object": { - "color": "#fe8c2c" + "color": "#ac6023" }, "property_identifier": { - "color": "#fe8c2c" + "color": "#ac6023" }, "shorthand_property_identifier": { - "color": "#fe8c2c" + "color": "#ac6023" }, "shorthand_property_identifier_pattern": { - "color": "#fe8c2c" + "color": "#ac6023" }, "method_definition": { - "color": "#9d6afb" + "color": "#5731a7" }, "function.method.call": { - "color": "#9d6afb" + "color": "#5731a7" }, "string.template": { - "color": "#0dbe4e" + "color": "#215584" }, "template_string": { - "color": "#0dbe4e" + "color": "#215584" }, "tag.jsx": { - "color": "#ff5d36" + "color": "#ac6023" }, "tag.component": { - "color": "#d568ea" + "color": "#a631be" }, "punctuation": { - "color": "#737373" + "color": "#636363" }, "punctuation.bracket": { - "color": "#737373" + "color": "#636363" }, "punctuation.delimiter": { - "color": "#737373" + "color": "#636363" }, "punctuation.list_marker": { - "color": "#737373" + "color": "#636363" }, "punctuation.special": { - "color": "#ff678d" + "color": "#8836c7" }, "operator": { - "color": "#68cdf2" + "color": "#2182a1" }, "tag": { - "color": "#ff5d36" + "color": "#ac6023" }, "attribute": { - "color": "#07c480" + "color": "#ac741d" }, "label": { - "color": "#ffab16" + "color": "#ac741d" }, "namespace": { - "color": "#ffab16" + "color": "#ac741d" }, "decorator": { - "color": "#69b1ff" + "color": "#216cab" }, "attribute.builtin": { - "color": "#69b1ff" + "color": "#216cab" }, "embedded": { - "color": "#525252" + "color": "#0a0a0a" }, "preproc": { - "color": "#ff678d" + "color": "#8836c7" }, "text.literal": { - "color": "#0dbe4e" + "color": "#215584" }, "markup.heading": { - "color": "#ff5d36", + "color": "#ac6023", "font_weight": 700 }, "markup.bold": { - "color": "#ffca00", + "color": "#ac741d", "font_weight": 700 }, "markup.italic": { - "color": "#ff678d", + "color": "#8836c7", "font_style": "italic" }, "markup.strikethrough": { - "color": "#8a8a8a" + "color": "#737373" }, "markup.link.url": { "color": "#009fff" }, "markup.link.text": { - "color": "#9d6afb" + "color": "#5731a7" }, "markup.quote": { - "color": "#8a8a8a", + "color": "#737373", "font_style": "italic" }, "markup.list": { - "color": "#ff5d36" + "color": "#ac6023" }, "markup.list.numbered": { - "color": "#ff5d36" + "color": "#ac6023" }, "markup.list.unnumbered": { - "color": "#ff5d36" + "color": "#ac6023" }, "markup.raw": { - "color": "#0dbe4e" + "color": "#215584" }, "markup.raw.inline": { - "color": "#0dbe4e" + "color": "#215584" }, "markup.raw.block": { - "color": "#0dbe4e" + "color": "#215584" }, "diff.plus": { - "color": "#07c480" + "color": "#216cab" }, "diff.minus": { - "color": "#ff2e3f" + "color": "#ac6023" }, "diff.delta": { "color": "#ffca00" @@ -977,7 +977,7 @@ "color": "#009fff" }, "link_uri": { - "color": "#ff678d" + "color": "#8836c7" }, "emphasis": { "font_style": "italic" @@ -989,65 +989,65 @@ "color": "#009fff" }, "title": { - "color": "#ff5d36", + "color": "#ac6023", "font_weight": 700 }, "predictive": { - "color": "#a3a3a3", + "color": "#8a8a8a", "font_style": "italic" } } } }, { - "name": "Pierre Dark", - "appearance": "dark", + "name": "Pierre Light Soft", + "appearance": "light", "style": { - "background": "#171717", - "surface.background": "#171717", - "elevated_surface.background": "#101010", + "background": "#f7f7f7", + "surface.background": "#f7f7f7", + "elevated_surface.background": "#fafafa", "drop_target.background": "#009fff26", - "editor.background": "#0a0a0a", - "editor.foreground": "#fafafa", - "editor.gutter.background": "#0a0a0a", - "editor.active_line.background": "#19283c8c", - "editor.active_line_number": "#a3a3a3", - "editor.line_number": "#737373", - "editor.highlighted_line.background": "#19283c59", - "editor.indent_guide": "#1d1d1d", - "editor.indent_guide_active": "#262626", - "editor.invisible": "#636363", - "editor.wrap_guide": "#1d1d1d", - "editor.active_wrap_guide": "#262626", - "editor.document_highlight.read_background": "#009fff26", - "editor.document_highlight.write_background": "#009fff40", + "editor.background": "#ffffff", + "editor.foreground": "#525252", + "editor.gutter.background": "#ffffff", + "editor.active_line.background": "#dfebff8c", + "editor.active_line_number": "#737373", + "editor.line_number": "#8a8a8a", + "editor.highlighted_line.background": "#dfebff59", + "editor.indent_guide": "#ededed", + "editor.indent_guide_active": "#e5e5e5", + "editor.invisible": "#a3a3a3", + "editor.wrap_guide": "#ededed", + "editor.active_wrap_guide": "#e5e5e5", + "editor.document_highlight.read_background": "#009fff1a", + "editor.document_highlight.write_background": "#009fff2e", "editor.document_highlight.bracket_background": "#009fff33", - "editor.subheader.background": "#171717", - "text": "#fafafa", - "text.muted": "#737373", - "text.placeholder": "#636363", - "text.disabled": "#636363", + "editor.subheader.background": "#f7f7f7", + "text": "#525252", + "text.muted": "#8a8a8a", + "text.placeholder": "#a3a3a3", + "text.disabled": "#a3a3a3", "text.accent": "#009fff", - "border": "#1d1d1d", - "border.variant": "#262626", + "border": "#e5e5e5", + "border.variant": "#ededed", "border.focused": "#009fff", "border.selected": "#009fff", "border.transparent": "transparent", - "border.disabled": "#262626", - "element.background": "#1d1d1d", - "element.hover": "#19283c80", - "element.active": "#19283cb3", - "element.selected": "#19283c99", - "element.disabled": "#1d1d1d80", + "border.disabled": "#d4d4d4", + "element.background": "#f5f5f5", + "element.hover": "#dfebff80", + "element.active": "#dfebffb3", + "element.selected": "#dfebffcc", + "element.disabled": "#f5f5f580", "ghost_element.background": "transparent", - "ghost_element.hover": "#19283c59", - "ghost_element.active": "#19283c8c", - "ghost_element.selected": "#19283c80", + "ghost_element.hover": "#dfebff59", + "ghost_element.active": "#dfebff8c", + "ghost_element.selected": "#dfebffa6", "ghost_element.disabled": "transparent", - "icon": "#a3a3a3", - "icon.muted": "#737373", - "icon.disabled": "#636363", - "icon.placeholder": "#636363", + "icon": "#737373", + "icon.muted": "#8a8a8a", + "icon.disabled": "#a3a3a3", + "icon.placeholder": "#a3a3a3", "icon.accent": "#009fff", "link_text.hover": "#009fff", "error": "#ff2e3f", @@ -1062,15 +1062,15 @@ "info": "#08c0ef", "info.background": "#08c0ef1a", "info.border": "#08c0ef4d", - "hint": "#737373", - "hint.background": "#7373731a", - "hint.border": "#73737333", - "predictive": "#636363", - "predictive.background": "#6363631a", - "predictive.border": "#63636333", - "unreachable": "#636363", - "unreachable.background": "#6363630d", - "unreachable.border": "#6363631a", + "hint": "#8a8a8a", + "hint.background": "#8a8a8a1a", + "hint.border": "#8a8a8a33", + "predictive": "#a3a3a3", + "predictive.background": "#a3a3a31a", + "predictive.border": "#a3a3a333", + "unreachable": "#a3a3a3", + "unreachable.background": "#a3a3a30d", + "unreachable.border": "#a3a3a31a", "created": "#07c480", "created.background": "#07c4801a", "created.border": "#07c4804d", @@ -1083,35 +1083,35 @@ "conflict": "#7b43f8", "conflict.background": "#7b43f81a", "conflict.border": "#7b43f84d", - "hidden": "#636363", - "hidden.background": "#6363630d", - "hidden.border": "#6363631a", - "ignored": "#737373", - "ignored.background": "#7373730d", - "ignored.border": "#7373731a", + "hidden": "#a3a3a3", + "hidden.background": "#a3a3a30d", + "hidden.border": "#a3a3a31a", + "ignored": "#8a8a8a", + "ignored.background": "#8a8a8a0d", + "ignored.border": "#8a8a8a1a", "renamed": "#08c0ef", "renamed.background": "#08c0ef1a", "renamed.border": "#08c0ef4d", "search.match_background": "#ffca004d", - "tab_bar.background": "#171717", - "tab.active_background": "#171717", - "tab.inactive_background": "#171717", - "toolbar.background": "#171717", - "title_bar.background": "#171717", - "title_bar.inactive_background": "#171717", - "panel.background": "#171717", + "tab_bar.background": "#f7f7f7", + "tab.active_background": "#f7f7f7", + "tab.inactive_background": "#f7f7f7", + "toolbar.background": "#f7f7f7", + "title_bar.background": "#f7f7f7", + "title_bar.inactive_background": "#f7f7f7", + "panel.background": "#f7f7f7", "panel.focused_border": "#009fff", - "status_bar.background": "#171717", - "scrollbar.thumb.background": "#6363634d", - "scrollbar.thumb.hover_background": "#63636380", + "status_bar.background": "#f7f7f7", + "scrollbar.thumb.background": "#a3a3a34d", + "scrollbar.thumb.hover_background": "#a3a3a380", "scrollbar.thumb.border": "transparent", "scrollbar.track.background": "transparent", "scrollbar.track.border": "transparent", - "terminal.background": "#171717", - "terminal.foreground": "#a3a3a3", - "terminal.bright_foreground": "#fafafa", - "terminal.dim_foreground": "#737373", - "terminal.ansi.black": "#171717", + "terminal.background": "#f7f7f7", + "terminal.foreground": "#737373", + "terminal.bright_foreground": "#525252", + "terminal.dim_foreground": "#8a8a8a", + "terminal.ansi.black": "#1d1d1d", "terminal.ansi.red": "#ff2e3f", "terminal.ansi.green": "#0dbe4e", "terminal.ansi.yellow": "#ffca00", @@ -1119,7 +1119,7 @@ "terminal.ansi.magenta": "#e130ac", "terminal.ansi.cyan": "#08c0ef", "terminal.ansi.white": "#bcbcbc", - "terminal.ansi.bright_black": "#171717", + "terminal.ansi.bright_black": "#1d1d1d", "terminal.ansi.bright_red": "#ff2e3f", "terminal.ansi.bright_green": "#86c427", "terminal.ansi.bright_yellow": "#ffca00", @@ -1149,9 +1149,9 @@ "selection": "#9d6afb40" }, { - "cursor": "#5ecc71", - "background": "#5ecc71", - "selection": "#5ecc7140" + "cursor": "#0dbe4e", + "background": "#0dbe4e", + "selection": "#0dbe4e40" }, { "cursor": "#ffca00", @@ -1171,40 +1171,40 @@ ], "syntax": { "comment": { - "color": "#737373" + "color": "#8a8a8a" }, "comment.doc": { - "color": "#737373" + "color": "#8a8a8a" }, "string": { - "color": "#5ecc71" + "color": "#0dbe4e" }, "string.escape": { - "color": "#61d5c0" + "color": "#00cab1" }, "string.regex": { - "color": "#64d1db" + "color": "#00c5d2" }, "string.special": { - "color": "#61d5c0" + "color": "#00cab1" }, "string.special.symbol": { - "color": "#ffd452" + "color": "#ffca00" }, "number": { - "color": "#68cdf2" + "color": "#08c0ef" }, "constant": { - "color": "#ffd452" + "color": "#ffca00" }, "boolean": { - "color": "#68cdf2" + "color": "#08c0ef" }, "keyword": { "color": "#ff678d" }, "keyword.operator": { - "color": "#08c0ef" + "color": "#68cdf2" }, "function": { "color": "#9d6afb" @@ -1231,22 +1231,22 @@ "color": "#d568ea" }, "variable": { - "color": "#ffa359" + "color": "#fe8c2c" }, "variable.builtin": { "color": "#ffab16" }, "variable.member": { - "color": "#ffa359" + "color": "#fe8c2c" }, "variable.parameter": { - "color": "#a3a3a3" + "color": "#737373" }, "variable.special": { "color": "#ffab16" }, "property": { - "color": "#ffa359" + "color": "#fe8c2c" }, "property.css": { "color": "#009fff" @@ -1258,31 +1258,31 @@ "color": "#009fff" }, "value": { - "color": "#68cdf2" + "color": "#08c0ef" }, "constant.css": { - "color": "#ffd452" + "color": "#ffca00" }, "string.plain": { - "color": "#68cdf2" + "color": "#08c0ef" }, "plain_value": { - "color": "#68cdf2" + "color": "#08c0ef" }, "tag.css": { - "color": "#ff855e" + "color": "#ff5d36" }, "tag_name": { - "color": "#ff855e" + "color": "#ff5d36" }, "class": { - "color": "#60d199" + "color": "#07c480" }, "class_name": { - "color": "#60d199" + "color": "#07c480" }, "selector.class": { - "color": "#60d199" + "color": "#07c480" }, "selector.id": { "color": "#9d6afb" @@ -1291,13 +1291,13 @@ "color": "#9d6afb" }, "selector.pseudo": { - "color": "#08c0ef" + "color": "#68cdf2" }, "pseudo_class_selector": { - "color": "#08c0ef" + "color": "#68cdf2" }, "pseudo_element_selector": { - "color": "#08c0ef" + "color": "#68cdf2" }, "keyword.directive": { "color": "#ff678d" @@ -1309,25 +1309,25 @@ "color": "#ff678d" }, "variable.scss": { - "color": "#ffa359" + "color": "#fe8c2c" }, "variable.css": { - "color": "#ffa359" + "color": "#fe8c2c" }, "property.custom": { - "color": "#ffa359" + "color": "#fe8c2c" }, "unit": { - "color": "#68cdf2" + "color": "#08c0ef" }, "number.unit": { - "color": "#68cdf2" + "color": "#08c0ef" }, "color": { - "color": "#ffd452" + "color": "#ffca00" }, "constant.color": { - "color": "#ffd452" + "color": "#ffca00" }, "keyword.important": { "color": "#ff678d" @@ -1345,16 +1345,16 @@ "color": "#d568ea" }, "property.object": { - "color": "#ffa359" + "color": "#fe8c2c" }, "property_identifier": { - "color": "#ffa359" + "color": "#fe8c2c" }, "shorthand_property_identifier": { - "color": "#ffa359" + "color": "#fe8c2c" }, "shorthand_property_identifier_pattern": { - "color": "#ffa359" + "color": "#fe8c2c" }, "method_definition": { "color": "#9d6afb" @@ -1363,40 +1363,40 @@ "color": "#9d6afb" }, "string.template": { - "color": "#5ecc71" + "color": "#0dbe4e" }, "template_string": { - "color": "#5ecc71" + "color": "#0dbe4e" }, "tag.jsx": { - "color": "#ff855e" + "color": "#ff5d36" }, "tag.component": { "color": "#d568ea" }, "punctuation": { - "color": "#636363" + "color": "#737373" }, "punctuation.bracket": { - "color": "#636363" + "color": "#737373" }, "punctuation.delimiter": { - "color": "#636363" + "color": "#737373" }, "punctuation.list_marker": { - "color": "#636363" + "color": "#737373" }, "punctuation.special": { "color": "#ff678d" }, "operator": { - "color": "#08c0ef" + "color": "#68cdf2" }, "tag": { - "color": "#ff855e" + "color": "#ff5d36" }, "attribute": { - "color": "#60d199" + "color": "#07c480" }, "label": { "color": "#ffab16" @@ -1411,20 +1411,20 @@ "color": "#69b1ff" }, "embedded": { - "color": "#fafafa" + "color": "#525252" }, "preproc": { "color": "#ff678d" }, "text.literal": { - "color": "#5ecc71" + "color": "#0dbe4e" }, "markup.heading": { - "color": "#ff855e", + "color": "#ff5d36", "font_weight": 700 }, "markup.bold": { - "color": "#ffd452", + "color": "#ffca00", "font_weight": 700 }, "markup.italic": { @@ -1432,7 +1432,7 @@ "font_style": "italic" }, "markup.strikethrough": { - "color": "#737373" + "color": "#8a8a8a" }, "markup.link.url": { "color": "#009fff" @@ -1441,26 +1441,26 @@ "color": "#9d6afb" }, "markup.quote": { - "color": "#737373", + "color": "#8a8a8a", "font_style": "italic" }, "markup.list": { - "color": "#ff855e" + "color": "#ff5d36" }, "markup.list.numbered": { - "color": "#ff855e" + "color": "#ff5d36" }, "markup.list.unnumbered": { - "color": "#ff855e" + "color": "#ff5d36" }, "markup.raw": { - "color": "#5ecc71" + "color": "#0dbe4e" }, "markup.raw.inline": { - "color": "#5ecc71" + "color": "#0dbe4e" }, "markup.raw.block": { - "color": "#5ecc71" + "color": "#0dbe4e" }, "diff.plus": { "color": "#07c480" @@ -1487,493 +1487,2485 @@ "color": "#009fff" }, "title": { - "color": "#ff855e", + "color": "#ff5d36", "font_weight": 700 }, "predictive": { - "color": "#636363", + "color": "#a3a3a3", "font_style": "italic" } } } }, { - "name": "Pierre Dark Soft", - "appearance": "dark", + "name": "Pierre Light Tritanopia", + "appearance": "light", "style": { - "background": "#101010", - "surface.background": "#101010", - "elevated_surface.background": "#1d1d1d", - "drop_target.background": "#69b1ff26", - "editor.background": "#171717", - "editor.foreground": "#d4d4d4", - "editor.gutter.background": "#171717", - "editor.active_line.background": "#1f3e5e8c", - "editor.active_line_number": "#8a8a8a", - "editor.line_number": "#636363", - "editor.highlighted_line.background": "#1f3e5e59", - "editor.indent_guide": "#262626", - "editor.indent_guide_active": "#2c2c2c", - "editor.invisible": "#525252", - "editor.wrap_guide": "#262626", - "editor.active_wrap_guide": "#2c2c2c", - "editor.document_highlight.read_background": "#69b1ff26", - "editor.document_highlight.write_background": "#69b1ff40", - "editor.document_highlight.bracket_background": "#69b1ff33", - "editor.subheader.background": "#101010", - "text": "#d4d4d4", - "text.muted": "#636363", - "text.placeholder": "#525252", - "text.disabled": "#525252", - "text.accent": "#69b1ff", - "border": "#262626", - "border.variant": "#2c2c2c", - "border.focused": "#69b1ff", - "border.selected": "#69b1ff", + "background": "#f5f5f5", + "surface.background": "#f5f5f5", + "elevated_surface.background": "#f7f7f7", + "drop_target.background": "#009fff26", + "editor.background": "#ffffff", + "editor.foreground": "#0a0a0a", + "editor.gutter.background": "#ffffff", + "editor.active_line.background": "#dfebff8c", + "editor.active_line_number": "#525252", + "editor.line_number": "#737373", + "editor.highlighted_line.background": "#dfebff59", + "editor.indent_guide": "#e5e5e5", + "editor.indent_guide_active": "#d4d4d4", + "editor.invisible": "#8a8a8a", + "editor.wrap_guide": "#e5e5e5", + "editor.active_wrap_guide": "#d4d4d4", + "editor.document_highlight.read_background": "#009fff1a", + "editor.document_highlight.write_background": "#009fff2e", + "editor.document_highlight.bracket_background": "#009fff33", + "editor.subheader.background": "#f5f5f5", + "text": "#0a0a0a", + "text.muted": "#737373", + "text.placeholder": "#8a8a8a", + "text.disabled": "#8a8a8a", + "text.accent": "#009fff", + "border": "#d4d4d4", + "border.variant": "#e5e5e5", + "border.focused": "#009fff", + "border.selected": "#009fff", "border.transparent": "transparent", - "border.disabled": "#2c2c2c", - "element.background": "#262626", - "element.hover": "#1f3e5e80", - "element.active": "#1f3e5eb3", - "element.selected": "#1f3e5e99", - "element.disabled": "#26262680", + "border.disabled": "#d4d4d4", + "element.background": "#ededed", + "element.hover": "#dfebff80", + "element.active": "#dfebffb3", + "element.selected": "#dfebffcc", + "element.disabled": "#ededed80", "ghost_element.background": "transparent", - "ghost_element.hover": "#1f3e5e59", - "ghost_element.active": "#1f3e5e8c", - "ghost_element.selected": "#1f3e5e80", + "ghost_element.hover": "#dfebff59", + "ghost_element.active": "#dfebff8c", + "ghost_element.selected": "#dfebffa6", "ghost_element.disabled": "transparent", - "icon": "#8a8a8a", - "icon.muted": "#636363", - "icon.disabled": "#525252", - "icon.placeholder": "#525252", - "icon.accent": "#69b1ff", - "link_text.hover": "#69b1ff", - "error": "#ff6762", - "error.background": "#ff67621a", - "error.border": "#ff67624d", - "warning": "#69b1ff", - "warning.background": "#69b1ff1a", - "warning.border": "#69b1ff4d", - "success": "#60d199", - "success.background": "#60d1991a", - "success.border": "#60d1994d", - "info": "#68cdf2", - "info.background": "#68cdf21a", - "info.border": "#68cdf24d", - "hint": "#636363", - "hint.background": "#6363631a", - "hint.border": "#63636333", - "predictive": "#525252", - "predictive.background": "#5252521a", - "predictive.border": "#52525233", - "unreachable": "#525252", - "unreachable.background": "#5252520d", - "unreachable.border": "#5252521a", - "created": "#60d199", - "created.background": "#60d1991a", - "created.border": "#60d1994d", - "modified": "#69b1ff", - "modified.background": "#69b1ff1a", - "modified.border": "#69b1ff4d", - "deleted": "#ff6762", - "deleted.background": "#ff67621a", - "deleted.border": "#ff67624d", - "conflict": "#9d6afb", - "conflict.background": "#9d6afb1a", - "conflict.border": "#9d6afb4d", - "hidden": "#525252", - "hidden.background": "#5252520d", - "hidden.border": "#5252521a", - "ignored": "#636363", - "ignored.background": "#6363630d", - "ignored.border": "#6363631a", - "renamed": "#68cdf2", - "renamed.background": "#68cdf21a", - "renamed.border": "#68cdf24d", - "search.match_background": "#ffd4524d", - "tab_bar.background": "#101010", - "tab.active_background": "#101010", - "tab.inactive_background": "#101010", - "toolbar.background": "#101010", - "title_bar.background": "#101010", - "title_bar.inactive_background": "#101010", - "panel.background": "#101010", - "panel.focused_border": "#69b1ff", - "status_bar.background": "#101010", - "scrollbar.thumb.background": "#5252524d", - "scrollbar.thumb.hover_background": "#52525280", + "icon": "#525252", + "icon.muted": "#737373", + "icon.disabled": "#8a8a8a", + "icon.placeholder": "#8a8a8a", + "icon.accent": "#009fff", + "link_text.hover": "#009fff", + "error": "#d5512f", + "error.background": "#d5512f1a", + "error.border": "#d5512f4d", + "warning": "#009fff", + "warning.background": "#009fff1a", + "warning.border": "#009fff4d", + "success": "#1e858e", + "success.background": "#1e858e1a", + "success.border": "#1e858e4d", + "info": "#1a85d4", + "info.background": "#1a85d41a", + "info.border": "#1a85d44d", + "hint": "#737373", + "hint.background": "#7373731a", + "hint.border": "#73737333", + "predictive": "#8a8a8a", + "predictive.background": "#8a8a8a1a", + "predictive.border": "#8a8a8a33", + "unreachable": "#8a8a8a", + "unreachable.background": "#8a8a8a0d", + "unreachable.border": "#8a8a8a1a", + "created": "#1e858e", + "created.background": "#1e858e1a", + "created.border": "#1e858e4d", + "modified": "#009fff", + "modified.background": "#009fff1a", + "modified.border": "#009fff4d", + "deleted": "#d5512f", + "deleted.background": "#d5512f1a", + "deleted.border": "#d5512f4d", + "conflict": "#992a75", + "conflict.background": "#992a751a", + "conflict.border": "#992a754d", + "hidden": "#8a8a8a", + "hidden.background": "#8a8a8a0d", + "hidden.border": "#8a8a8a1a", + "ignored": "#737373", + "ignored.background": "#7373730d", + "ignored.border": "#7373731a", + "renamed": "#1a85d4", + "renamed.background": "#1a85d41a", + "renamed.border": "#1a85d44d", + "search.match_background": "#ffab164d", + "tab_bar.background": "#f5f5f5", + "tab.active_background": "#f5f5f5", + "tab.inactive_background": "#f5f5f5", + "toolbar.background": "#f5f5f5", + "title_bar.background": "#f5f5f5", + "title_bar.inactive_background": "#f5f5f5", + "panel.background": "#f5f5f5", + "panel.focused_border": "#009fff", + "status_bar.background": "#f5f5f5", + "scrollbar.thumb.background": "#8a8a8a4d", + "scrollbar.thumb.hover_background": "#8a8a8a80", + "scrollbar.thumb.border": "transparent", + "scrollbar.track.background": "transparent", + "scrollbar.track.border": "transparent", + "terminal.background": "#f5f5f5", + "terminal.foreground": "#525252", + "terminal.bright_foreground": "#0a0a0a", + "terminal.dim_foreground": "#737373", + "terminal.ansi.black": "#1d1d1d", + "terminal.ansi.red": "#d5512f", + "terminal.ansi.green": "#1e858e", + "terminal.ansi.yellow": "#d5901c", + "terminal.ansi.blue": "#1a85d4", + "terminal.ansi.magenta": "#992a75", + "terminal.ansi.cyan": "#17a5af", + "terminal.ansi.white": "#bcbcbc", + "terminal.ansi.bright_black": "#1d1d1d", + "terminal.ansi.bright_red": "#ff5d36", + "terminal.ansi.bright_green": "#17a5af", + "terminal.ansi.bright_yellow": "#ffab16", + "terminal.ansi.bright_blue": "#009fff", + "terminal.ansi.bright_magenta": "#bd2e90", + "terminal.ansi.bright_cyan": "#00c5d2", + "terminal.ansi.bright_white": "#bcbcbc", + "players": [ + { + "cursor": "#009fff", + "background": "#009fff", + "selection": "#009fff40" + }, + { + "cursor": "#1e858e", + "background": "#1e858e", + "selection": "#1e858e40" + }, + { + "cursor": "#a631be", + "background": "#a631be", + "selection": "#a631be40" + }, + { + "cursor": "#216cab", + "background": "#216cab", + "selection": "#216cab40" + }, + { + "cursor": "#1e858e", + "background": "#1e858e", + "selection": "#1e858e40" + }, + { + "cursor": "#ffab16", + "background": "#ffab16", + "selection": "#ffab1640" + }, + { + "cursor": "#bd2e90", + "background": "#bd2e90", + "selection": "#bd2e9040" + }, + { + "cursor": "#1a85d4", + "background": "#1a85d4", + "selection": "#1a85d440" + } + ], + "syntax": { + "comment": { + "color": "#737373" + }, + "comment.doc": { + "color": "#737373" + }, + "string": { + "color": "#1e858e" + }, + "string.escape": { + "color": "#1e858e" + }, + "string.regex": { + "color": "#1e858e" + }, + "string.special": { + "color": "#1e858e" + }, + "string.special.symbol": { + "color": "#ac741d" + }, + "number": { + "color": "#1a85d4" + }, + "constant": { + "color": "#ac741d" + }, + "boolean": { + "color": "#1a85d4" + }, + "keyword": { + "color": "#a631be" + }, + "keyword.operator": { + "color": "#1e858e" + }, + "function": { + "color": "#216cab" + }, + "function.method": { + "color": "#216cab" + }, + "function.builtin": { + "color": "#216cab" + }, + "function.special.definition": { + "color": "#216cab" + }, + "function.call": { + "color": "#216cab" + }, + "type": { + "color": "#bd2e90" + }, + "type.builtin": { + "color": "#bd2e90" + }, + "constructor": { + "color": "#bd2e90" + }, + "variable": { + "color": "#ad4529" + }, + "variable.builtin": { + "color": "#d5512f" + }, + "variable.member": { + "color": "#ad4529" + }, + "variable.parameter": { + "color": "#636363" + }, + "variable.special": { + "color": "#d5512f" + }, + "property": { + "color": "#ad4529" + }, + "property.css": { + "color": "#009fff" + }, + "property.definition": { + "color": "#009fff" + }, + "property_name": { + "color": "#009fff" + }, + "value": { + "color": "#1a85d4" + }, + "constant.css": { + "color": "#ac741d" + }, + "string.plain": { + "color": "#1a85d4" + }, + "plain_value": { + "color": "#1a85d4" + }, + "tag.css": { + "color": "#d5512f" + }, + "tag_name": { + "color": "#d5512f" + }, + "class": { + "color": "#1e858e" + }, + "class_name": { + "color": "#1e858e" + }, + "selector.class": { + "color": "#1e858e" + }, + "selector.id": { + "color": "#216cab" + }, + "id_name": { + "color": "#216cab" + }, + "selector.pseudo": { + "color": "#1e858e" + }, + "pseudo_class_selector": { + "color": "#1e858e" + }, + "pseudo_element_selector": { + "color": "#1e858e" + }, + "keyword.directive": { + "color": "#a631be" + }, + "keyword.control.at-rule": { + "color": "#a631be" + }, + "at_keyword": { + "color": "#a631be" + }, + "variable.scss": { + "color": "#ad4529" + }, + "variable.css": { + "color": "#ad4529" + }, + "property.custom": { + "color": "#ad4529" + }, + "unit": { + "color": "#1a85d4" + }, + "number.unit": { + "color": "#1a85d4" + }, + "color": { + "color": "#ac741d" + }, + "constant.color": { + "color": "#ac741d" + }, + "keyword.important": { + "color": "#a631be" + }, + "variable.language": { + "color": "#d5512f" + }, + "this": { + "color": "#d5512f" + }, + "self": { + "color": "#d5512f" + }, + "type.class": { + "color": "#bd2e90" + }, + "property.object": { + "color": "#ad4529" + }, + "property_identifier": { + "color": "#ad4529" + }, + "shorthand_property_identifier": { + "color": "#ad4529" + }, + "shorthand_property_identifier_pattern": { + "color": "#ad4529" + }, + "method_definition": { + "color": "#216cab" + }, + "function.method.call": { + "color": "#216cab" + }, + "string.template": { + "color": "#1e858e" + }, + "template_string": { + "color": "#1e858e" + }, + "tag.jsx": { + "color": "#d5512f" + }, + "tag.component": { + "color": "#bd2e90" + }, + "punctuation": { + "color": "#636363" + }, + "punctuation.bracket": { + "color": "#636363" + }, + "punctuation.delimiter": { + "color": "#636363" + }, + "punctuation.list_marker": { + "color": "#636363" + }, + "punctuation.special": { + "color": "#a631be" + }, + "operator": { + "color": "#1e858e" + }, + "tag": { + "color": "#d5512f" + }, + "attribute": { + "color": "#1e858e" + }, + "label": { + "color": "#d5512f" + }, + "namespace": { + "color": "#d5512f" + }, + "decorator": { + "color": "#1a85d4" + }, + "attribute.builtin": { + "color": "#1a85d4" + }, + "embedded": { + "color": "#0a0a0a" + }, + "preproc": { + "color": "#a631be" + }, + "text.literal": { + "color": "#1e858e" + }, + "markup.heading": { + "color": "#d5512f", + "font_weight": 700 + }, + "markup.bold": { + "color": "#ac741d", + "font_weight": 700 + }, + "markup.italic": { + "color": "#a631be", + "font_style": "italic" + }, + "markup.strikethrough": { + "color": "#737373" + }, + "markup.link.url": { + "color": "#009fff" + }, + "markup.link.text": { + "color": "#216cab" + }, + "markup.quote": { + "color": "#737373", + "font_style": "italic" + }, + "markup.list": { + "color": "#d5512f" + }, + "markup.list.numbered": { + "color": "#d5512f" + }, + "markup.list.unnumbered": { + "color": "#d5512f" + }, + "markup.raw": { + "color": "#1e858e" + }, + "markup.raw.inline": { + "color": "#1e858e" + }, + "markup.raw.block": { + "color": "#1e858e" + }, + "diff.plus": { + "color": "#1e858e" + }, + "diff.minus": { + "color": "#d5512f" + }, + "diff.delta": { + "color": "#ffab16" + }, + "link_text": { + "color": "#009fff" + }, + "link_uri": { + "color": "#a631be" + }, + "emphasis": { + "font_style": "italic" + }, + "emphasis.strong": { + "font_weight": 700 + }, + "primary": { + "color": "#009fff" + }, + "title": { + "color": "#d5512f", + "font_weight": 700 + }, + "predictive": { + "color": "#8a8a8a", + "font_style": "italic" + } + } + } + }, + { + "name": "Pierre Dark", + "appearance": "dark", + "style": { + "background": "#171717", + "surface.background": "#171717", + "elevated_surface.background": "#101010", + "drop_target.background": "#009fff26", + "editor.background": "#0a0a0a", + "editor.foreground": "#fafafa", + "editor.gutter.background": "#0a0a0a", + "editor.active_line.background": "#19283c8c", + "editor.active_line_number": "#a3a3a3", + "editor.line_number": "#737373", + "editor.highlighted_line.background": "#19283c59", + "editor.indent_guide": "#1d1d1d", + "editor.indent_guide_active": "#262626", + "editor.invisible": "#636363", + "editor.wrap_guide": "#1d1d1d", + "editor.active_wrap_guide": "#262626", + "editor.document_highlight.read_background": "#009fff26", + "editor.document_highlight.write_background": "#009fff40", + "editor.document_highlight.bracket_background": "#009fff33", + "editor.subheader.background": "#171717", + "text": "#fafafa", + "text.muted": "#737373", + "text.placeholder": "#636363", + "text.disabled": "#636363", + "text.accent": "#009fff", + "border": "#1d1d1d", + "border.variant": "#262626", + "border.focused": "#009fff", + "border.selected": "#009fff", + "border.transparent": "transparent", + "border.disabled": "#262626", + "element.background": "#1d1d1d", + "element.hover": "#19283c80", + "element.active": "#19283cb3", + "element.selected": "#19283c99", + "element.disabled": "#1d1d1d80", + "ghost_element.background": "transparent", + "ghost_element.hover": "#19283c59", + "ghost_element.active": "#19283c8c", + "ghost_element.selected": "#19283c80", + "ghost_element.disabled": "transparent", + "icon": "#a3a3a3", + "icon.muted": "#737373", + "icon.disabled": "#636363", + "icon.placeholder": "#636363", + "icon.accent": "#009fff", + "link_text.hover": "#009fff", + "error": "#ff2e3f", + "error.background": "#ff2e3f1a", + "error.border": "#ff2e3f4d", + "warning": "#009fff", + "warning.background": "#009fff1a", + "warning.border": "#009fff4d", + "success": "#07c480", + "success.background": "#07c4801a", + "success.border": "#07c4804d", + "info": "#08c0ef", + "info.background": "#08c0ef1a", + "info.border": "#08c0ef4d", + "hint": "#737373", + "hint.background": "#7373731a", + "hint.border": "#73737333", + "predictive": "#636363", + "predictive.background": "#6363631a", + "predictive.border": "#63636333", + "unreachable": "#636363", + "unreachable.background": "#6363630d", + "unreachable.border": "#6363631a", + "created": "#07c480", + "created.background": "#07c4801a", + "created.border": "#07c4804d", + "modified": "#009fff", + "modified.background": "#009fff1a", + "modified.border": "#009fff4d", + "deleted": "#ff2e3f", + "deleted.background": "#ff2e3f1a", + "deleted.border": "#ff2e3f4d", + "conflict": "#7b43f8", + "conflict.background": "#7b43f81a", + "conflict.border": "#7b43f84d", + "hidden": "#636363", + "hidden.background": "#6363630d", + "hidden.border": "#6363631a", + "ignored": "#737373", + "ignored.background": "#7373730d", + "ignored.border": "#7373731a", + "renamed": "#08c0ef", + "renamed.background": "#08c0ef1a", + "renamed.border": "#08c0ef4d", + "search.match_background": "#ffca004d", + "tab_bar.background": "#171717", + "tab.active_background": "#171717", + "tab.inactive_background": "#171717", + "toolbar.background": "#171717", + "title_bar.background": "#171717", + "title_bar.inactive_background": "#171717", + "panel.background": "#171717", + "panel.focused_border": "#009fff", + "status_bar.background": "#171717", + "scrollbar.thumb.background": "#6363634d", + "scrollbar.thumb.hover_background": "#63636380", + "scrollbar.thumb.border": "transparent", + "scrollbar.track.background": "transparent", + "scrollbar.track.border": "transparent", + "terminal.background": "#171717", + "terminal.foreground": "#a3a3a3", + "terminal.bright_foreground": "#fafafa", + "terminal.dim_foreground": "#737373", + "terminal.ansi.black": "#171717", + "terminal.ansi.red": "#ff2e3f", + "terminal.ansi.green": "#0dbe4e", + "terminal.ansi.yellow": "#ffca00", + "terminal.ansi.blue": "#009fff", + "terminal.ansi.magenta": "#e130ac", + "terminal.ansi.cyan": "#08c0ef", + "terminal.ansi.white": "#bcbcbc", + "terminal.ansi.bright_black": "#171717", + "terminal.ansi.bright_red": "#ff2e3f", + "terminal.ansi.bright_green": "#86c427", + "terminal.ansi.bright_yellow": "#ffca00", + "terminal.ansi.bright_blue": "#009fff", + "terminal.ansi.bright_magenta": "#e130ac", + "terminal.ansi.bright_cyan": "#08c0ef", + "terminal.ansi.bright_white": "#bcbcbc", + "players": [ + { + "cursor": "#009fff", + "background": "#009fff", + "selection": "#009fff40" + }, + { + "cursor": "#07c480", + "background": "#07c480", + "selection": "#07c48040" + }, + { + "cursor": "#ff678d", + "background": "#ff678d", + "selection": "#ff678d40" + }, + { + "cursor": "#9d6afb", + "background": "#9d6afb", + "selection": "#9d6afb40" + }, + { + "cursor": "#5ecc71", + "background": "#5ecc71", + "selection": "#5ecc7140" + }, + { + "cursor": "#ffca00", + "background": "#ffca00", + "selection": "#ffca0040" + }, + { + "cursor": "#d568ea", + "background": "#d568ea", + "selection": "#d568ea40" + }, + { + "cursor": "#08c0ef", + "background": "#08c0ef", + "selection": "#08c0ef40" + } + ], + "syntax": { + "comment": { + "color": "#737373" + }, + "comment.doc": { + "color": "#737373" + }, + "string": { + "color": "#5ecc71" + }, + "string.escape": { + "color": "#61d5c0" + }, + "string.regex": { + "color": "#64d1db" + }, + "string.special": { + "color": "#61d5c0" + }, + "string.special.symbol": { + "color": "#ffd452" + }, + "number": { + "color": "#68cdf2" + }, + "constant": { + "color": "#ffd452" + }, + "boolean": { + "color": "#68cdf2" + }, + "keyword": { + "color": "#ff678d" + }, + "keyword.operator": { + "color": "#08c0ef" + }, + "function": { + "color": "#9d6afb" + }, + "function.method": { + "color": "#9d6afb" + }, + "function.builtin": { + "color": "#9d6afb" + }, + "function.special.definition": { + "color": "#9d6afb" + }, + "function.call": { + "color": "#9d6afb" + }, + "type": { + "color": "#d568ea" + }, + "type.builtin": { + "color": "#d568ea" + }, + "constructor": { + "color": "#d568ea" + }, + "variable": { + "color": "#ffa359" + }, + "variable.builtin": { + "color": "#ffab16" + }, + "variable.member": { + "color": "#ffa359" + }, + "variable.parameter": { + "color": "#a3a3a3" + }, + "variable.special": { + "color": "#ffab16" + }, + "property": { + "color": "#ffa359" + }, + "property.css": { + "color": "#009fff" + }, + "property.definition": { + "color": "#009fff" + }, + "property_name": { + "color": "#009fff" + }, + "value": { + "color": "#68cdf2" + }, + "constant.css": { + "color": "#ffd452" + }, + "string.plain": { + "color": "#68cdf2" + }, + "plain_value": { + "color": "#68cdf2" + }, + "tag.css": { + "color": "#ff855e" + }, + "tag_name": { + "color": "#ff855e" + }, + "class": { + "color": "#60d199" + }, + "class_name": { + "color": "#60d199" + }, + "selector.class": { + "color": "#60d199" + }, + "selector.id": { + "color": "#9d6afb" + }, + "id_name": { + "color": "#9d6afb" + }, + "selector.pseudo": { + "color": "#08c0ef" + }, + "pseudo_class_selector": { + "color": "#08c0ef" + }, + "pseudo_element_selector": { + "color": "#08c0ef" + }, + "keyword.directive": { + "color": "#ff678d" + }, + "keyword.control.at-rule": { + "color": "#ff678d" + }, + "at_keyword": { + "color": "#ff678d" + }, + "variable.scss": { + "color": "#ffa359" + }, + "variable.css": { + "color": "#ffa359" + }, + "property.custom": { + "color": "#ffa359" + }, + "unit": { + "color": "#68cdf2" + }, + "number.unit": { + "color": "#68cdf2" + }, + "color": { + "color": "#ffd452" + }, + "constant.color": { + "color": "#ffd452" + }, + "keyword.important": { + "color": "#ff678d" + }, + "variable.language": { + "color": "#ffab16" + }, + "this": { + "color": "#ffab16" + }, + "self": { + "color": "#ffab16" + }, + "type.class": { + "color": "#d568ea" + }, + "property.object": { + "color": "#ffa359" + }, + "property_identifier": { + "color": "#ffa359" + }, + "shorthand_property_identifier": { + "color": "#ffa359" + }, + "shorthand_property_identifier_pattern": { + "color": "#ffa359" + }, + "method_definition": { + "color": "#9d6afb" + }, + "function.method.call": { + "color": "#9d6afb" + }, + "string.template": { + "color": "#5ecc71" + }, + "template_string": { + "color": "#5ecc71" + }, + "tag.jsx": { + "color": "#ff855e" + }, + "tag.component": { + "color": "#d568ea" + }, + "punctuation": { + "color": "#636363" + }, + "punctuation.bracket": { + "color": "#636363" + }, + "punctuation.delimiter": { + "color": "#636363" + }, + "punctuation.list_marker": { + "color": "#636363" + }, + "punctuation.special": { + "color": "#ff678d" + }, + "operator": { + "color": "#08c0ef" + }, + "tag": { + "color": "#ff855e" + }, + "attribute": { + "color": "#60d199" + }, + "label": { + "color": "#ffab16" + }, + "namespace": { + "color": "#ffab16" + }, + "decorator": { + "color": "#69b1ff" + }, + "attribute.builtin": { + "color": "#69b1ff" + }, + "embedded": { + "color": "#fafafa" + }, + "preproc": { + "color": "#ff678d" + }, + "text.literal": { + "color": "#5ecc71" + }, + "markup.heading": { + "color": "#ff855e", + "font_weight": 700 + }, + "markup.bold": { + "color": "#ffd452", + "font_weight": 700 + }, + "markup.italic": { + "color": "#ff678d", + "font_style": "italic" + }, + "markup.strikethrough": { + "color": "#737373" + }, + "markup.link.url": { + "color": "#009fff" + }, + "markup.link.text": { + "color": "#9d6afb" + }, + "markup.quote": { + "color": "#737373", + "font_style": "italic" + }, + "markup.list": { + "color": "#ff855e" + }, + "markup.list.numbered": { + "color": "#ff855e" + }, + "markup.list.unnumbered": { + "color": "#ff855e" + }, + "markup.raw": { + "color": "#5ecc71" + }, + "markup.raw.inline": { + "color": "#5ecc71" + }, + "markup.raw.block": { + "color": "#5ecc71" + }, + "diff.plus": { + "color": "#07c480" + }, + "diff.minus": { + "color": "#ff2e3f" + }, + "diff.delta": { + "color": "#ffca00" + }, + "link_text": { + "color": "#009fff" + }, + "link_uri": { + "color": "#ff678d" + }, + "emphasis": { + "font_style": "italic" + }, + "emphasis.strong": { + "font_weight": 700 + }, + "primary": { + "color": "#009fff" + }, + "title": { + "color": "#ff855e", + "font_weight": 700 + }, + "predictive": { + "color": "#636363", + "font_style": "italic" + } + } + } + }, + { + "name": "Pierre Dark Protanopia & Deuteranopia", + "appearance": "dark", + "style": { + "background": "#171717", + "surface.background": "#171717", + "elevated_surface.background": "#101010", + "drop_target.background": "#009fff26", + "editor.background": "#0a0a0a", + "editor.foreground": "#fafafa", + "editor.gutter.background": "#0a0a0a", + "editor.active_line.background": "#19283c8c", + "editor.active_line_number": "#a3a3a3", + "editor.line_number": "#737373", + "editor.highlighted_line.background": "#19283c59", + "editor.indent_guide": "#1d1d1d", + "editor.indent_guide_active": "#262626", + "editor.invisible": "#636363", + "editor.wrap_guide": "#1d1d1d", + "editor.active_wrap_guide": "#262626", + "editor.document_highlight.read_background": "#009fff26", + "editor.document_highlight.write_background": "#009fff40", + "editor.document_highlight.bracket_background": "#009fff33", + "editor.subheader.background": "#171717", + "text": "#fafafa", + "text.muted": "#737373", + "text.placeholder": "#636363", + "text.disabled": "#636363", + "text.accent": "#009fff", + "border": "#1d1d1d", + "border.variant": "#262626", + "border.focused": "#009fff", + "border.selected": "#009fff", + "border.transparent": "transparent", + "border.disabled": "#262626", + "element.background": "#1d1d1d", + "element.hover": "#19283c80", + "element.active": "#19283cb3", + "element.selected": "#19283c99", + "element.disabled": "#1d1d1d80", + "ghost_element.background": "transparent", + "ghost_element.hover": "#19283c59", + "ghost_element.active": "#19283c8c", + "ghost_element.selected": "#19283c80", + "ghost_element.disabled": "transparent", + "icon": "#a3a3a3", + "icon.muted": "#737373", + "icon.disabled": "#636363", + "icon.placeholder": "#636363", + "icon.accent": "#009fff", + "link_text.hover": "#009fff", + "error": "#fe8c2c", + "error.background": "#fe8c2c1a", + "error.border": "#fe8c2c4d", + "warning": "#009fff", + "warning.background": "#009fff1a", + "warning.border": "#009fff4d", + "success": "#97c4ff", + "success.background": "#97c4ff1a", + "success.border": "#97c4ff4d", + "info": "#68cdf2", + "info.background": "#68cdf21a", + "info.border": "#68cdf24d", + "hint": "#737373", + "hint.background": "#7373731a", + "hint.border": "#73737333", + "predictive": "#636363", + "predictive.background": "#6363631a", + "predictive.border": "#63636333", + "unreachable": "#636363", + "unreachable.background": "#6363630d", + "unreachable.border": "#6363631a", + "created": "#97c4ff", + "created.background": "#97c4ff1a", + "created.border": "#97c4ff4d", + "modified": "#009fff", + "modified.background": "#009fff1a", + "modified.border": "#009fff4d", + "deleted": "#fe8c2c", + "deleted.background": "#fe8c2c1a", + "deleted.border": "#fe8c2c4d", + "conflict": "#b969f3", + "conflict.background": "#b969f31a", + "conflict.border": "#b969f34d", + "hidden": "#636363", + "hidden.background": "#6363630d", + "hidden.border": "#6363631a", + "ignored": "#737373", + "ignored.background": "#7373730d", + "ignored.border": "#7373731a", + "renamed": "#68cdf2", + "renamed.background": "#68cdf21a", + "renamed.border": "#68cdf24d", + "search.match_background": "#ffde804d", + "tab_bar.background": "#171717", + "tab.active_background": "#171717", + "tab.inactive_background": "#171717", + "toolbar.background": "#171717", + "title_bar.background": "#171717", + "title_bar.inactive_background": "#171717", + "panel.background": "#171717", + "panel.focused_border": "#009fff", + "status_bar.background": "#171717", + "scrollbar.thumb.background": "#6363634d", + "scrollbar.thumb.hover_background": "#63636380", + "scrollbar.thumb.border": "transparent", + "scrollbar.track.background": "transparent", + "scrollbar.track.border": "transparent", + "terminal.background": "#171717", + "terminal.foreground": "#a3a3a3", + "terminal.bright_foreground": "#fafafa", + "terminal.dim_foreground": "#737373", + "terminal.ansi.black": "#171717", + "terminal.ansi.red": "#ffa359", + "terminal.ansi.green": "#69b1ff", + "terminal.ansi.yellow": "#ffd452", + "terminal.ansi.blue": "#009fff", + "terminal.ansi.magenta": "#b969f3", + "terminal.ansi.cyan": "#68cdf2", + "terminal.ansi.white": "#bcbcbc", + "terminal.ansi.bright_black": "#171717", + "terminal.ansi.bright_red": "#ffba82", + "terminal.ansi.bright_green": "#97c4ff", + "terminal.ansi.bright_yellow": "#ffde80", + "terminal.ansi.bright_blue": "#69b1ff", + "terminal.ansi.bright_magenta": "#ce90f7", + "terminal.ansi.bright_cyan": "#96d9f6", + "terminal.ansi.bright_white": "#bcbcbc", + "players": [ + { + "cursor": "#009fff", + "background": "#009fff", + "selection": "#009fff40" + }, + { + "cursor": "#97c4ff", + "background": "#97c4ff", + "selection": "#97c4ff40" + }, + { + "cursor": "#b969f3", + "background": "#b969f3", + "selection": "#b969f340" + }, + { + "cursor": "#ba8ffd", + "background": "#ba8ffd", + "selection": "#ba8ffd40" + }, + { + "cursor": "#97c4ff", + "background": "#97c4ff", + "selection": "#97c4ff40" + }, + { + "cursor": "#ffde80", + "background": "#ffde80", + "selection": "#ffde8040" + }, + { + "cursor": "#e290f0", + "background": "#e290f0", + "selection": "#e290f040" + }, + { + "cursor": "#68cdf2", + "background": "#68cdf2", + "selection": "#68cdf240" + } + ], + "syntax": { + "comment": { + "color": "#737373" + }, + "comment.doc": { + "color": "#737373" + }, + "string": { + "color": "#97c4ff" + }, + "string.escape": { + "color": "#64d1db" + }, + "string.regex": { + "color": "#68cdf2" + }, + "string.special": { + "color": "#64d1db" + }, + "string.special.symbol": { + "color": "#ffcc81" + }, + "number": { + "color": "#96d9f6" + }, + "constant": { + "color": "#ffcc81" + }, + "boolean": { + "color": "#96d9f6" + }, + "keyword": { + "color": "#b969f3" + }, + "keyword.operator": { + "color": "#08c0ef" + }, + "function": { + "color": "#ba8ffd" + }, + "function.method": { + "color": "#ba8ffd" + }, + "function.builtin": { + "color": "#ba8ffd" + }, + "function.special.definition": { + "color": "#ba8ffd" + }, + "function.call": { + "color": "#ba8ffd" + }, + "type": { + "color": "#e290f0" + }, + "type.builtin": { + "color": "#e290f0" + }, + "constructor": { + "color": "#e290f0" + }, + "variable": { + "color": "#ffa359" + }, + "variable.builtin": { + "color": "#ffbc56" + }, + "variable.member": { + "color": "#ffa359" + }, + "variable.parameter": { + "color": "#a3a3a3" + }, + "variable.special": { + "color": "#ffbc56" + }, + "property": { + "color": "#ffa359" + }, + "property.css": { + "color": "#009fff" + }, + "property.definition": { + "color": "#009fff" + }, + "property_name": { + "color": "#009fff" + }, + "value": { + "color": "#96d9f6" + }, + "constant.css": { + "color": "#ffcc81" + }, + "string.plain": { + "color": "#96d9f6" + }, + "plain_value": { + "color": "#96d9f6" + }, + "tag.css": { + "color": "#ffa359" + }, + "tag_name": { + "color": "#ffa359" + }, + "class": { + "color": "#ffbc56" + }, + "class_name": { + "color": "#ffbc56" + }, + "selector.class": { + "color": "#ffbc56" + }, + "selector.id": { + "color": "#ba8ffd" + }, + "id_name": { + "color": "#ba8ffd" + }, + "selector.pseudo": { + "color": "#08c0ef" + }, + "pseudo_class_selector": { + "color": "#08c0ef" + }, + "pseudo_element_selector": { + "color": "#08c0ef" + }, + "keyword.directive": { + "color": "#b969f3" + }, + "keyword.control.at-rule": { + "color": "#b969f3" + }, + "at_keyword": { + "color": "#b969f3" + }, + "variable.scss": { + "color": "#ffa359" + }, + "variable.css": { + "color": "#ffa359" + }, + "property.custom": { + "color": "#ffa359" + }, + "unit": { + "color": "#96d9f6" + }, + "number.unit": { + "color": "#96d9f6" + }, + "color": { + "color": "#ffcc81" + }, + "constant.color": { + "color": "#ffcc81" + }, + "keyword.important": { + "color": "#b969f3" + }, + "variable.language": { + "color": "#ffbc56" + }, + "this": { + "color": "#ffbc56" + }, + "self": { + "color": "#ffbc56" + }, + "type.class": { + "color": "#e290f0" + }, + "property.object": { + "color": "#ffa359" + }, + "property_identifier": { + "color": "#ffa359" + }, + "shorthand_property_identifier": { + "color": "#ffa359" + }, + "shorthand_property_identifier_pattern": { + "color": "#ffa359" + }, + "method_definition": { + "color": "#ba8ffd" + }, + "function.method.call": { + "color": "#ba8ffd" + }, + "string.template": { + "color": "#97c4ff" + }, + "template_string": { + "color": "#97c4ff" + }, + "tag.jsx": { + "color": "#ffa359" + }, + "tag.component": { + "color": "#e290f0" + }, + "punctuation": { + "color": "#636363" + }, + "punctuation.bracket": { + "color": "#636363" + }, + "punctuation.delimiter": { + "color": "#636363" + }, + "punctuation.list_marker": { + "color": "#636363" + }, + "punctuation.special": { + "color": "#b969f3" + }, + "operator": { + "color": "#08c0ef" + }, + "tag": { + "color": "#ffa359" + }, + "attribute": { + "color": "#ffbc56" + }, + "label": { + "color": "#ffbc56" + }, + "namespace": { + "color": "#ffbc56" + }, + "decorator": { + "color": "#69b1ff" + }, + "attribute.builtin": { + "color": "#69b1ff" + }, + "embedded": { + "color": "#fafafa" + }, + "preproc": { + "color": "#b969f3" + }, + "text.literal": { + "color": "#97c4ff" + }, + "markup.heading": { + "color": "#ffa359", + "font_weight": 700 + }, + "markup.bold": { + "color": "#ffcc81", + "font_weight": 700 + }, + "markup.italic": { + "color": "#b969f3", + "font_style": "italic" + }, + "markup.strikethrough": { + "color": "#737373" + }, + "markup.link.url": { + "color": "#009fff" + }, + "markup.link.text": { + "color": "#ba8ffd" + }, + "markup.quote": { + "color": "#737373", + "font_style": "italic" + }, + "markup.list": { + "color": "#ffa359" + }, + "markup.list.numbered": { + "color": "#ffa359" + }, + "markup.list.unnumbered": { + "color": "#ffa359" + }, + "markup.raw": { + "color": "#97c4ff" + }, + "markup.raw.inline": { + "color": "#97c4ff" + }, + "markup.raw.block": { + "color": "#97c4ff" + }, + "diff.plus": { + "color": "#97c4ff" + }, + "diff.minus": { + "color": "#fe8c2c" + }, + "diff.delta": { + "color": "#ffde80" + }, + "link_text": { + "color": "#009fff" + }, + "link_uri": { + "color": "#b969f3" + }, + "emphasis": { + "font_style": "italic" + }, + "emphasis.strong": { + "font_weight": 700 + }, + "primary": { + "color": "#009fff" + }, + "title": { + "color": "#ffa359", + "font_weight": 700 + }, + "predictive": { + "color": "#636363", + "font_style": "italic" + } + } + } + }, + { + "name": "Pierre Dark Soft", + "appearance": "dark", + "style": { + "background": "#101010", + "surface.background": "#101010", + "elevated_surface.background": "#1d1d1d", + "drop_target.background": "#69b1ff26", + "editor.background": "#171717", + "editor.foreground": "#d4d4d4", + "editor.gutter.background": "#171717", + "editor.active_line.background": "#1f3e5e8c", + "editor.active_line_number": "#8a8a8a", + "editor.line_number": "#636363", + "editor.highlighted_line.background": "#1f3e5e59", + "editor.indent_guide": "#262626", + "editor.indent_guide_active": "#2c2c2c", + "editor.invisible": "#525252", + "editor.wrap_guide": "#262626", + "editor.active_wrap_guide": "#2c2c2c", + "editor.document_highlight.read_background": "#69b1ff26", + "editor.document_highlight.write_background": "#69b1ff40", + "editor.document_highlight.bracket_background": "#69b1ff33", + "editor.subheader.background": "#101010", + "text": "#d4d4d4", + "text.muted": "#636363", + "text.placeholder": "#525252", + "text.disabled": "#525252", + "text.accent": "#69b1ff", + "border": "#262626", + "border.variant": "#2c2c2c", + "border.focused": "#69b1ff", + "border.selected": "#69b1ff", + "border.transparent": "transparent", + "border.disabled": "#2c2c2c", + "element.background": "#262626", + "element.hover": "#1f3e5e80", + "element.active": "#1f3e5eb3", + "element.selected": "#1f3e5e99", + "element.disabled": "#26262680", + "ghost_element.background": "transparent", + "ghost_element.hover": "#1f3e5e59", + "ghost_element.active": "#1f3e5e8c", + "ghost_element.selected": "#1f3e5e80", + "ghost_element.disabled": "transparent", + "icon": "#8a8a8a", + "icon.muted": "#636363", + "icon.disabled": "#525252", + "icon.placeholder": "#525252", + "icon.accent": "#69b1ff", + "link_text.hover": "#69b1ff", + "error": "#ff6762", + "error.background": "#ff67621a", + "error.border": "#ff67624d", + "warning": "#69b1ff", + "warning.background": "#69b1ff1a", + "warning.border": "#69b1ff4d", + "success": "#60d199", + "success.background": "#60d1991a", + "success.border": "#60d1994d", + "info": "#68cdf2", + "info.background": "#68cdf21a", + "info.border": "#68cdf24d", + "hint": "#636363", + "hint.background": "#6363631a", + "hint.border": "#63636333", + "predictive": "#525252", + "predictive.background": "#5252521a", + "predictive.border": "#52525233", + "unreachable": "#525252", + "unreachable.background": "#5252520d", + "unreachable.border": "#5252521a", + "created": "#60d199", + "created.background": "#60d1991a", + "created.border": "#60d1994d", + "modified": "#69b1ff", + "modified.background": "#69b1ff1a", + "modified.border": "#69b1ff4d", + "deleted": "#ff6762", + "deleted.background": "#ff67621a", + "deleted.border": "#ff67624d", + "conflict": "#9d6afb", + "conflict.background": "#9d6afb1a", + "conflict.border": "#9d6afb4d", + "hidden": "#525252", + "hidden.background": "#5252520d", + "hidden.border": "#5252521a", + "ignored": "#636363", + "ignored.background": "#6363630d", + "ignored.border": "#6363631a", + "renamed": "#68cdf2", + "renamed.background": "#68cdf21a", + "renamed.border": "#68cdf24d", + "search.match_background": "#ffd4524d", + "tab_bar.background": "#101010", + "tab.active_background": "#101010", + "tab.inactive_background": "#101010", + "toolbar.background": "#101010", + "title_bar.background": "#101010", + "title_bar.inactive_background": "#101010", + "panel.background": "#101010", + "panel.focused_border": "#69b1ff", + "status_bar.background": "#101010", + "scrollbar.thumb.background": "#5252524d", + "scrollbar.thumb.hover_background": "#52525280", + "scrollbar.thumb.border": "transparent", + "scrollbar.track.background": "transparent", + "scrollbar.track.border": "transparent", + "terminal.background": "#101010", + "terminal.foreground": "#8a8a8a", + "terminal.bright_foreground": "#d4d4d4", + "terminal.dim_foreground": "#636363", + "terminal.ansi.black": "#171717", + "terminal.ansi.red": "#ff2e3f", + "terminal.ansi.green": "#0dbe4e", + "terminal.ansi.yellow": "#ffca00", + "terminal.ansi.blue": "#009fff", + "terminal.ansi.magenta": "#e130ac", + "terminal.ansi.cyan": "#08c0ef", + "terminal.ansi.white": "#bcbcbc", + "terminal.ansi.bright_black": "#171717", + "terminal.ansi.bright_red": "#ff2e3f", + "terminal.ansi.bright_green": "#86c427", + "terminal.ansi.bright_yellow": "#ffca00", + "terminal.ansi.bright_blue": "#009fff", + "terminal.ansi.bright_magenta": "#e130ac", + "terminal.ansi.bright_cyan": "#08c0ef", + "terminal.ansi.bright_white": "#bcbcbc", + "players": [ + { + "cursor": "#69b1ff", + "background": "#69b1ff", + "selection": "#69b1ff40" + }, + { + "cursor": "#60d199", + "background": "#60d199", + "selection": "#60d19940" + }, + { + "cursor": "#ff91a8", + "background": "#ff91a8", + "selection": "#ff91a840" + }, + { + "cursor": "#ba8ffd", + "background": "#ba8ffd", + "selection": "#ba8ffd40" + }, + { + "cursor": "#8cda94", + "background": "#8cda94", + "selection": "#8cda9440" + }, + { + "cursor": "#ffd452", + "background": "#ffd452", + "selection": "#ffd45240" + }, + { + "cursor": "#e290f0", + "background": "#e290f0", + "selection": "#e290f040" + }, + { + "cursor": "#68cdf2", + "background": "#68cdf2", + "selection": "#68cdf240" + } + ], + "syntax": { + "comment": { + "color": "#636363" + }, + "comment.doc": { + "color": "#636363" + }, + "string": { + "color": "#8cda94" + }, + "string.escape": { + "color": "#8fe0d0" + }, + "string.regex": { + "color": "#92dde4" + }, + "string.special": { + "color": "#8fe0d0" + }, + "string.special.symbol": { + "color": "#ffde80" + }, + "number": { + "color": "#96d9f6" + }, + "constant": { + "color": "#ffde80" + }, + "boolean": { + "color": "#96d9f6" + }, + "keyword": { + "color": "#ff91a8" + }, + "keyword.operator": { + "color": "#68cdf2" + }, + "function": { + "color": "#ba8ffd" + }, + "function.method": { + "color": "#ba8ffd" + }, + "function.builtin": { + "color": "#ba8ffd" + }, + "function.special.definition": { + "color": "#ba8ffd" + }, + "function.call": { + "color": "#ba8ffd" + }, + "type": { + "color": "#e290f0" + }, + "type.builtin": { + "color": "#e290f0" + }, + "constructor": { + "color": "#e290f0" + }, + "variable": { + "color": "#ffba82" + }, + "variable.builtin": { + "color": "#ffbc56" + }, + "variable.member": { + "color": "#ffba82" + }, + "variable.parameter": { + "color": "#8a8a8a" + }, + "variable.special": { + "color": "#ffbc56" + }, + "property": { + "color": "#ffba82" + }, + "property.css": { + "color": "#69b1ff" + }, + "property.definition": { + "color": "#69b1ff" + }, + "property_name": { + "color": "#69b1ff" + }, + "value": { + "color": "#96d9f6" + }, + "constant.css": { + "color": "#ffde80" + }, + "string.plain": { + "color": "#96d9f6" + }, + "plain_value": { + "color": "#96d9f6" + }, + "tag.css": { + "color": "#ffa685" + }, + "tag_name": { + "color": "#ffa685" + }, + "class": { + "color": "#8eddb2" + }, + "class_name": { + "color": "#8eddb2" + }, + "selector.class": { + "color": "#8eddb2" + }, + "selector.id": { + "color": "#ba8ffd" + }, + "id_name": { + "color": "#ba8ffd" + }, + "selector.pseudo": { + "color": "#68cdf2" + }, + "pseudo_class_selector": { + "color": "#68cdf2" + }, + "pseudo_element_selector": { + "color": "#68cdf2" + }, + "keyword.directive": { + "color": "#ff91a8" + }, + "keyword.control.at-rule": { + "color": "#ff91a8" + }, + "at_keyword": { + "color": "#ff91a8" + }, + "variable.scss": { + "color": "#ffba82" + }, + "variable.css": { + "color": "#ffba82" + }, + "property.custom": { + "color": "#ffba82" + }, + "unit": { + "color": "#96d9f6" + }, + "number.unit": { + "color": "#96d9f6" + }, + "color": { + "color": "#ffde80" + }, + "constant.color": { + "color": "#ffde80" + }, + "keyword.important": { + "color": "#ff91a8" + }, + "variable.language": { + "color": "#ffbc56" + }, + "this": { + "color": "#ffbc56" + }, + "self": { + "color": "#ffbc56" + }, + "type.class": { + "color": "#e290f0" + }, + "property.object": { + "color": "#ffba82" + }, + "property_identifier": { + "color": "#ffba82" + }, + "shorthand_property_identifier": { + "color": "#ffba82" + }, + "shorthand_property_identifier_pattern": { + "color": "#ffba82" + }, + "method_definition": { + "color": "#ba8ffd" + }, + "function.method.call": { + "color": "#ba8ffd" + }, + "string.template": { + "color": "#8cda94" + }, + "template_string": { + "color": "#8cda94" + }, + "tag.jsx": { + "color": "#ffa685" + }, + "tag.component": { + "color": "#e290f0" + }, + "punctuation": { + "color": "#737373" + }, + "punctuation.bracket": { + "color": "#737373" + }, + "punctuation.delimiter": { + "color": "#737373" + }, + "punctuation.list_marker": { + "color": "#737373" + }, + "punctuation.special": { + "color": "#ff91a8" + }, + "operator": { + "color": "#68cdf2" + }, + "tag": { + "color": "#ffa685" + }, + "attribute": { + "color": "#8eddb2" + }, + "label": { + "color": "#ffbc56" + }, + "namespace": { + "color": "#ffbc56" + }, + "decorator": { + "color": "#97c4ff" + }, + "attribute.builtin": { + "color": "#97c4ff" + }, + "embedded": { + "color": "#d4d4d4" + }, + "preproc": { + "color": "#ff91a8" + }, + "text.literal": { + "color": "#8cda94" + }, + "markup.heading": { + "color": "#ffa685", + "font_weight": 700 + }, + "markup.bold": { + "color": "#ffde80", + "font_weight": 700 + }, + "markup.italic": { + "color": "#ff91a8", + "font_style": "italic" + }, + "markup.strikethrough": { + "color": "#636363" + }, + "markup.link.url": { + "color": "#69b1ff" + }, + "markup.link.text": { + "color": "#ba8ffd" + }, + "markup.quote": { + "color": "#636363", + "font_style": "italic" + }, + "markup.list": { + "color": "#ffa685" + }, + "markup.list.numbered": { + "color": "#ffa685" + }, + "markup.list.unnumbered": { + "color": "#ffa685" + }, + "markup.raw": { + "color": "#8cda94" + }, + "markup.raw.inline": { + "color": "#8cda94" + }, + "markup.raw.block": { + "color": "#8cda94" + }, + "diff.plus": { + "color": "#60d199" + }, + "diff.minus": { + "color": "#ff6762" + }, + "diff.delta": { + "color": "#ffd452" + }, + "link_text": { + "color": "#69b1ff" + }, + "link_uri": { + "color": "#ff91a8" + }, + "emphasis": { + "font_style": "italic" + }, + "emphasis.strong": { + "font_weight": 700 + }, + "primary": { + "color": "#69b1ff" + }, + "title": { + "color": "#ffa685", + "font_weight": 700 + }, + "predictive": { + "color": "#525252", + "font_style": "italic" + } + } + } + }, + { + "name": "Pierre Dark Tritanopia", + "appearance": "dark", + "style": { + "background": "#171717", + "surface.background": "#171717", + "elevated_surface.background": "#101010", + "drop_target.background": "#009fff26", + "editor.background": "#0a0a0a", + "editor.foreground": "#fafafa", + "editor.gutter.background": "#0a0a0a", + "editor.active_line.background": "#19283c8c", + "editor.active_line_number": "#a3a3a3", + "editor.line_number": "#737373", + "editor.highlighted_line.background": "#19283c59", + "editor.indent_guide": "#1d1d1d", + "editor.indent_guide_active": "#262626", + "editor.invisible": "#636363", + "editor.wrap_guide": "#1d1d1d", + "editor.active_wrap_guide": "#262626", + "editor.document_highlight.read_background": "#009fff26", + "editor.document_highlight.write_background": "#009fff40", + "editor.document_highlight.bracket_background": "#009fff33", + "editor.subheader.background": "#171717", + "text": "#fafafa", + "text.muted": "#737373", + "text.placeholder": "#636363", + "text.disabled": "#636363", + "text.accent": "#009fff", + "border": "#1d1d1d", + "border.variant": "#262626", + "border.focused": "#009fff", + "border.selected": "#009fff", + "border.transparent": "transparent", + "border.disabled": "#262626", + "element.background": "#1d1d1d", + "element.hover": "#19283c80", + "element.active": "#19283cb3", + "element.selected": "#19283c99", + "element.disabled": "#1d1d1d80", + "ghost_element.background": "transparent", + "ghost_element.hover": "#19283c59", + "ghost_element.active": "#19283c8c", + "ghost_element.selected": "#19283c80", + "ghost_element.disabled": "transparent", + "icon": "#a3a3a3", + "icon.muted": "#737373", + "icon.disabled": "#636363", + "icon.placeholder": "#636363", + "icon.accent": "#009fff", + "link_text.hover": "#009fff", + "error": "#ff855e", + "error.background": "#ff855e1a", + "error.border": "#ff855e4d", + "warning": "#009fff", + "warning.background": "#009fff1a", + "warning.border": "#009fff4d", + "success": "#92dde4", + "success.background": "#92dde41a", + "success.border": "#92dde44d", + "info": "#69b1ff", + "info.background": "#69b1ff1a", + "info.border": "#69b1ff4d", + "hint": "#737373", + "hint.background": "#7373731a", + "hint.border": "#73737333", + "predictive": "#636363", + "predictive.background": "#6363631a", + "predictive.border": "#63636333", + "unreachable": "#636363", + "unreachable.background": "#6363630d", + "unreachable.border": "#6363631a", + "created": "#92dde4", + "created.background": "#92dde41a", + "created.border": "#92dde44d", + "modified": "#009fff", + "modified.background": "#009fff1a", + "modified.border": "#009fff4d", + "deleted": "#ff855e", + "deleted.background": "#ff855e1a", + "deleted.border": "#ff855e4d", + "conflict": "#ea68bc", + "conflict.background": "#ea68bc1a", + "conflict.border": "#ea68bc4d", + "hidden": "#636363", + "hidden.background": "#6363630d", + "hidden.border": "#6363631a", + "ignored": "#737373", + "ignored.background": "#7373730d", + "ignored.border": "#7373731a", + "renamed": "#69b1ff", + "renamed.background": "#69b1ff1a", + "renamed.border": "#69b1ff4d", + "search.match_background": "#ffbc564d", + "tab_bar.background": "#171717", + "tab.active_background": "#171717", + "tab.inactive_background": "#171717", + "toolbar.background": "#171717", + "title_bar.background": "#171717", + "title_bar.inactive_background": "#171717", + "panel.background": "#171717", + "panel.focused_border": "#009fff", + "status_bar.background": "#171717", + "scrollbar.thumb.background": "#6363634d", + "scrollbar.thumb.hover_background": "#63636380", "scrollbar.thumb.border": "transparent", "scrollbar.track.background": "transparent", "scrollbar.track.border": "transparent", - "terminal.background": "#101010", - "terminal.foreground": "#8a8a8a", - "terminal.bright_foreground": "#d4d4d4", - "terminal.dim_foreground": "#636363", + "terminal.background": "#171717", + "terminal.foreground": "#a3a3a3", + "terminal.bright_foreground": "#fafafa", + "terminal.dim_foreground": "#737373", "terminal.ansi.black": "#171717", - "terminal.ansi.red": "#ff2e3f", - "terminal.ansi.green": "#0dbe4e", - "terminal.ansi.yellow": "#ffca00", - "terminal.ansi.blue": "#009fff", - "terminal.ansi.magenta": "#e130ac", - "terminal.ansi.cyan": "#08c0ef", + "terminal.ansi.red": "#ff855e", + "terminal.ansi.green": "#64d1db", + "terminal.ansi.yellow": "#ffbc56", + "terminal.ansi.blue": "#69b1ff", + "terminal.ansi.magenta": "#ea68bc", + "terminal.ansi.cyan": "#92dde4", "terminal.ansi.white": "#bcbcbc", "terminal.ansi.bright_black": "#171717", - "terminal.ansi.bright_red": "#ff2e3f", - "terminal.ansi.bright_green": "#86c427", - "terminal.ansi.bright_yellow": "#ffca00", - "terminal.ansi.bright_blue": "#009fff", - "terminal.ansi.bright_magenta": "#e130ac", - "terminal.ansi.bright_cyan": "#08c0ef", + "terminal.ansi.bright_red": "#ffa685", + "terminal.ansi.bright_green": "#92dde4", + "terminal.ansi.bright_yellow": "#ffcc81", + "terminal.ansi.bright_blue": "#97c4ff", + "terminal.ansi.bright_magenta": "#f191cc", + "terminal.ansi.bright_cyan": "#92dde4", "terminal.ansi.bright_white": "#bcbcbc", "players": [ { - "cursor": "#69b1ff", - "background": "#69b1ff", - "selection": "#69b1ff40" + "cursor": "#009fff", + "background": "#009fff", + "selection": "#009fff40" }, { - "cursor": "#60d199", - "background": "#60d199", - "selection": "#60d19940" + "cursor": "#92dde4", + "background": "#92dde4", + "selection": "#92dde440" }, { - "cursor": "#ff91a8", - "background": "#ff91a8", - "selection": "#ff91a840" + "cursor": "#d568ea", + "background": "#d568ea", + "selection": "#d568ea40" }, { - "cursor": "#ba8ffd", - "background": "#ba8ffd", - "selection": "#ba8ffd40" + "cursor": "#97c4ff", + "background": "#97c4ff", + "selection": "#97c4ff40" }, { - "cursor": "#8cda94", - "background": "#8cda94", - "selection": "#8cda9440" + "cursor": "#92dde4", + "background": "#92dde4", + "selection": "#92dde440" }, { - "cursor": "#ffd452", - "background": "#ffd452", - "selection": "#ffd45240" + "cursor": "#ffbc56", + "background": "#ffbc56", + "selection": "#ffbc5640" }, { - "cursor": "#e290f0", - "background": "#e290f0", - "selection": "#e290f040" + "cursor": "#ea68bc", + "background": "#ea68bc", + "selection": "#ea68bc40" }, { - "cursor": "#68cdf2", - "background": "#68cdf2", - "selection": "#68cdf240" + "cursor": "#69b1ff", + "background": "#69b1ff", + "selection": "#69b1ff40" } ], "syntax": { "comment": { - "color": "#636363" + "color": "#737373" }, "comment.doc": { - "color": "#636363" + "color": "#737373" }, "string": { - "color": "#8cda94" + "color": "#92dde4" }, "string.escape": { - "color": "#8fe0d0" + "color": "#64d1db" }, "string.regex": { - "color": "#92dde4" + "color": "#64d1db" }, "string.special": { - "color": "#8fe0d0" + "color": "#64d1db" }, "string.special.symbol": { - "color": "#ffde80" + "color": "#ffcc81" }, "number": { - "color": "#96d9f6" + "color": "#69b1ff" }, "constant": { - "color": "#ffde80" + "color": "#ffcc81" }, "boolean": { - "color": "#96d9f6" + "color": "#69b1ff" }, "keyword": { - "color": "#ff91a8" + "color": "#d568ea" }, "keyword.operator": { - "color": "#68cdf2" + "color": "#00c5d2" }, "function": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "function.method": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "function.builtin": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "function.special.definition": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "function.call": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "type": { - "color": "#e290f0" + "color": "#ea68bc" }, "type.builtin": { - "color": "#e290f0" + "color": "#ea68bc" }, "constructor": { - "color": "#e290f0" + "color": "#ea68bc" }, "variable": { - "color": "#ffba82" + "color": "#ff855e" }, "variable.builtin": { - "color": "#ffbc56" + "color": "#ff855e" }, "variable.member": { - "color": "#ffba82" + "color": "#ff855e" }, "variable.parameter": { - "color": "#8a8a8a" + "color": "#a3a3a3" }, "variable.special": { - "color": "#ffbc56" + "color": "#ff855e" }, "property": { - "color": "#ffba82" + "color": "#ff855e" }, "property.css": { - "color": "#69b1ff" + "color": "#009fff" }, "property.definition": { - "color": "#69b1ff" + "color": "#009fff" }, "property_name": { - "color": "#69b1ff" + "color": "#009fff" }, "value": { - "color": "#96d9f6" + "color": "#69b1ff" }, "constant.css": { - "color": "#ffde80" + "color": "#ffcc81" }, "string.plain": { - "color": "#96d9f6" + "color": "#69b1ff" }, "plain_value": { - "color": "#96d9f6" + "color": "#69b1ff" }, "tag.css": { - "color": "#ffa685" + "color": "#ff855e" }, "tag_name": { - "color": "#ffa685" + "color": "#ff855e" }, "class": { - "color": "#8eddb2" + "color": "#64d1db" }, "class_name": { - "color": "#8eddb2" + "color": "#64d1db" }, "selector.class": { - "color": "#8eddb2" + "color": "#64d1db" }, "selector.id": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "id_name": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "selector.pseudo": { - "color": "#68cdf2" + "color": "#00c5d2" }, "pseudo_class_selector": { - "color": "#68cdf2" + "color": "#00c5d2" }, "pseudo_element_selector": { - "color": "#68cdf2" + "color": "#00c5d2" }, "keyword.directive": { - "color": "#ff91a8" + "color": "#d568ea" }, "keyword.control.at-rule": { - "color": "#ff91a8" + "color": "#d568ea" }, "at_keyword": { - "color": "#ff91a8" + "color": "#d568ea" }, "variable.scss": { - "color": "#ffba82" + "color": "#ff855e" }, "variable.css": { - "color": "#ffba82" + "color": "#ff855e" }, "property.custom": { - "color": "#ffba82" + "color": "#ff855e" }, "unit": { - "color": "#96d9f6" + "color": "#69b1ff" }, "number.unit": { - "color": "#96d9f6" + "color": "#69b1ff" }, "color": { - "color": "#ffde80" + "color": "#ffcc81" }, "constant.color": { - "color": "#ffde80" + "color": "#ffcc81" }, "keyword.important": { - "color": "#ff91a8" + "color": "#d568ea" }, "variable.language": { - "color": "#ffbc56" + "color": "#ff855e" }, "this": { - "color": "#ffbc56" + "color": "#ff855e" }, "self": { - "color": "#ffbc56" + "color": "#ff855e" }, "type.class": { - "color": "#e290f0" + "color": "#ea68bc" }, "property.object": { - "color": "#ffba82" + "color": "#ff855e" }, "property_identifier": { - "color": "#ffba82" + "color": "#ff855e" }, "shorthand_property_identifier": { - "color": "#ffba82" + "color": "#ff855e" }, "shorthand_property_identifier_pattern": { - "color": "#ffba82" + "color": "#ff855e" }, "method_definition": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "function.method.call": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "string.template": { - "color": "#8cda94" + "color": "#92dde4" }, "template_string": { - "color": "#8cda94" + "color": "#92dde4" }, "tag.jsx": { - "color": "#ffa685" + "color": "#ff855e" }, "tag.component": { - "color": "#e290f0" + "color": "#ea68bc" }, "punctuation": { - "color": "#737373" + "color": "#636363" }, "punctuation.bracket": { - "color": "#737373" + "color": "#636363" }, "punctuation.delimiter": { - "color": "#737373" + "color": "#636363" }, "punctuation.list_marker": { - "color": "#737373" + "color": "#636363" }, "punctuation.special": { - "color": "#ff91a8" + "color": "#d568ea" }, "operator": { - "color": "#68cdf2" + "color": "#00c5d2" }, "tag": { - "color": "#ffa685" + "color": "#ff855e" }, "attribute": { - "color": "#8eddb2" + "color": "#64d1db" }, "label": { - "color": "#ffbc56" + "color": "#ff855e" }, "namespace": { - "color": "#ffbc56" + "color": "#ff855e" }, "decorator": { - "color": "#97c4ff" + "color": "#69b1ff" }, "attribute.builtin": { - "color": "#97c4ff" + "color": "#69b1ff" }, "embedded": { - "color": "#d4d4d4" + "color": "#fafafa" }, "preproc": { - "color": "#ff91a8" + "color": "#d568ea" }, "text.literal": { - "color": "#8cda94" + "color": "#92dde4" }, "markup.heading": { - "color": "#ffa685", + "color": "#ff855e", "font_weight": 700 }, "markup.bold": { - "color": "#ffde80", + "color": "#ffcc81", "font_weight": 700 }, "markup.italic": { - "color": "#ff91a8", + "color": "#d568ea", "font_style": "italic" }, "markup.strikethrough": { - "color": "#636363" + "color": "#737373" }, "markup.link.url": { - "color": "#69b1ff" + "color": "#009fff" }, "markup.link.text": { - "color": "#ba8ffd" + "color": "#97c4ff" }, "markup.quote": { - "color": "#636363", + "color": "#737373", "font_style": "italic" }, "markup.list": { - "color": "#ffa685" + "color": "#ff855e" }, "markup.list.numbered": { - "color": "#ffa685" + "color": "#ff855e" }, "markup.list.unnumbered": { - "color": "#ffa685" + "color": "#ff855e" }, "markup.raw": { - "color": "#8cda94" + "color": "#92dde4" }, "markup.raw.inline": { - "color": "#8cda94" + "color": "#92dde4" }, "markup.raw.block": { - "color": "#8cda94" + "color": "#92dde4" }, "diff.plus": { - "color": "#60d199" + "color": "#92dde4" }, "diff.minus": { - "color": "#ff6762" + "color": "#ff855e" }, "diff.delta": { - "color": "#ffd452" + "color": "#ffbc56" }, "link_text": { - "color": "#69b1ff" + "color": "#009fff" }, "link_uri": { - "color": "#ff91a8" + "color": "#d568ea" }, "emphasis": { "font_style": "italic" @@ -1982,14 +3974,14 @@ "font_weight": 700 }, "primary": { - "color": "#69b1ff" + "color": "#009fff" }, "title": { - "color": "#ffa685", + "color": "#ff855e", "font_weight": 700 }, "predictive": { - "color": "#525252", + "color": "#636363", "font_style": "italic" } }