Files
Aditya Gupta bcb48fd3a6 refactor: options handling and improve code readability
- Cleaned up import statements in options.ts for better organization.
- Enhanced the init function to load settings with improved formatting.
- Streamlined event listener attachments for buttons and inputs.
- Improved the rendering functions for color and semantic grids.
- Updated the parsePalette function in themeEngine.ts for better error handling and readability.
- Refactored deriveSemanticTheme to enhance clarity and maintainability.
- Adjusted tsconfig.json for better structure and readability.
- Updated vite.config.ts to improve build process and maintain consistency.
2026-03-03 23:11:33 +05:30
..

Gogh Theme Engine

A production-grade Chrome Extension (Manifest V3) that applies Gogh-style 16-color terminal palettes to all web pages by intelligently computing and rewriting styles at runtime using perceptual OKLCH color remapping.

Features

  • OKLCH Perceptual Color Model — All color math uses OKLCH for perceptually uniform transformations
  • Semantic Theme Derivation — Automatically maps 16 terminal colors to semantic roles (error, success, accent, etc.) using hue + brightness analysis
  • Smart DOM Processing — TreeWalker-based traversal, MutationObserver with batched/debounced updates, Shadow DOM support
  • WCAG Contrast Enforcement — Ensures minimum 4.5:1 contrast ratio for text
  • Gradient & SVG Support — Parses and transforms CSS gradients and inline SVG fill/stroke
  • Dynamic CSS Class Generation — Reuses CSS classes instead of inline styles for performance
  • Per-site Toggle — Enable/disable theming on a per-domain basis
  • Intensity Slider — Blend between original and themed colors (0100%)
  • Options Page — YAML editor, live preview, contrast diagnostics, site management

Build Instructions

Prerequisites

  • Node.js ≥ 18
  • npm ≥ 9

Setup

cd gogh-theme-engine
npm install

Development Build (with watch)

npm run dev

Production Build

npm run build

Load in Chrome

  1. Run npm run build
  2. Open chrome://extensions/
  3. Enable Developer mode
  4. Click Load unpacked
  5. Select the dist/ folder

Project Structure

src/
├── background.ts        # Service worker — storage, per-domain toggle, messaging
├── content.ts           # Content script — DOM processing, style injection, coordination
├── color.ts             # OKLCH color engine — all color math and transforms
├── themeEngine.ts       # YAML parsing, validation, semantic theme derivation
├── observer.ts          # DOM observation — TreeWalker, MutationObserver, Shadow DOM
├── js-yaml.d.ts         # Type declarations for js-yaml
└── options/
    ├── options.html     # Options page UI
    └── options.ts       # Options page controller

public/
├── manifest.json        # Manifest V3 configuration
└── icons/               # Extension icons

Palette Format

Provide a YAML palette in Gogh format:

name: My Theme
author: Your Name
variant: dark
color_01: "#282a36"
color_02: "#ff5555"
color_03: "#50fa7b"
color_04: "#f1fa8c"
color_05: "#bd93f9"
color_06: "#ff79c6"
color_07: "#8be9fd"
color_08: "#f8f8f2"
color_09: "#44475a"
color_10: "#ff6e6e"
color_11: "#69ff94"
color_12: "#ffffa5"
color_13: "#d6acff"
color_14: "#ff92df"
color_15: "#a4ffff"
color_16: "#ffffff"
background: "#282a36"
foreground: "#f8f8f2"
cursor: "#f8f8f2"

How It Works

Color Pipeline

  1. Parse — CSS color strings are parsed into RGBA
  2. Convert — RGBA → sRGB → Linear RGB → OKLAB → OKLCH
  3. Classify — Colors are classified as neutral (achromatic) or chromatic with a hue bucket
  4. Remap — Neutral colors map to surface/background bands; chromatic colors map to semantic roles
  5. Contrast — WCAG contrast is enforced by adjusting the L (lightness) channel
  6. Blend — Final color is blended with original based on intensity setting
  7. Cache — Results are memoized by color + context key

Theme Derivation

Instead of fixed index mapping, semantic roles are derived by analyzing each palette color's OKLCH properties:

  • Red hue range → error
  • Green → success
  • Blue/Cyan → accentPrimary / info
  • Yellow/Orange → warning
  • Purple → accentSecondary
  • Low chroma → muted
  • Surface/border colors are synthesized from background by shifting lightness

Architecture Notes

  • No naive CSS inversion or global filters
  • TreeWalker for initial traversal (faster than querySelectorAll)
  • MutationObserver with requestIdleCallback batching
  • WeakSet for tracking processed nodes
  • Element.prototype.attachShadow monkey-patching for shadow DOM
  • Dynamic CSS class generation with reuse to minimize inline styles
  • Transform results cached with LRU-like eviction (max 8192 entries)