diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 3f7d249..7035803 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -60,3 +60,4 @@ - Tooling - [SolidTV Devtools](/tools/solid_devtools.md) - [JSX Locator Plugin](/tools/jsx_locator.md) + - [Hex Color Transform](/tools/hex_color_transform.md) diff --git a/docs/tools/hex_color_transform.md b/docs/tools/hex_color_transform.md new file mode 100644 index 0000000..57252a0 --- /dev/null +++ b/docs/tools/hex_color_transform.md @@ -0,0 +1,96 @@ +# Hex Color Transform + +A Vite plugin that transforms hex color strings (`"#RRGGBB"`, `"#RGB"`, `"#RRGGBBAA"`, `"#RGBA"`) into the `0xRRGGBBAA` numeric format required by the SolidTV renderer at build time. + +This means you can write natural hex color strings in your code and have them automatically converted to the correct format. + +## Installation + +The plugin is included in `@solidtv/solid` — no additional packages needed. + +## Usage + +Import and add the plugin to your `vite.config.ts`: + +```typescript +import { defineConfig } from 'vite'; +import { hexColorTransform } from '@solidtv/solid/devtools'; + +export default defineConfig({ + plugins: [hexColorTransform()], +}); +``` + +### With Include/Exclude Filters + +You can control which files the plugin processes: + +```typescript +import { defineConfig } from 'vite'; +import { hexColorTransform } from '@solidtv/solid/devtools'; + +export default defineConfig({ + plugins: [ + hexColorTransform({ + include: ['src/**/*.ts', 'src/**/*.tsx'], + exclude: 'src/ignore-this-directory/**', + }), + ], +}); +``` + +### Options + +| Option | Type | Default | Description | +| --------- | -------------------- | ------------- | ------------------------------------------------- | +| `include` | `string \| string[]` | all files | Glob pattern(s) specifying which files to process | +| `exclude` | `string \| string[]` | no exclusions | Glob pattern(s) specifying which files to skip | + +## How It Works + +The plugin runs during Vite's `transform` step and converts all hex color string literals to `0xRRGGBBAA` numeric literals. + +### Before + +```typescript +const color = '#f6f6f6'; +const shortColor = '#fff'; +const alphaColor = '#f6f6f680'; +const shortAlpha = '#fff8'; +``` + +### After + +```typescript +const color = 0xf6f6f6ff; +const shortColor = 0xffffffff; +const alphaColor = 0xf6f6f680; +const shortAlpha = 0xffffff88; +``` + +- 3-character hex (`#RGB`) is expanded to `#RRGGBBFF` (full opacity) +- 4-character hex (`#RGBA`) is expanded to `#RRGGBBAA` +- 6-character hex (`#RRGGBB`) gets `FF` appended for full opacity +- 8-character hex (`#RRGGBBAA`) is used as-is + +## Migrating from `hexColor()` + +If you were previously using the `hexColor()` helper function, you can remove all calls with a find-and-replace: + +**VSCode regex find:** + +``` +hexColor\("(#[A-Fa-f0-9]{4,8})"\) +``` + +**Replace with:** + +``` +"$1" +``` + +> Be mindful of single vs double quotes — the regex matches double quotes. + +After removing `hexColor()` calls, the Vite plugin handles the conversion automatically at build time. + +**Tip:** Enable `editor.defaultColorDecorators` in VSCode settings (Command + , to search) to get built-in color highlighting for hex strings. diff --git a/src/devtools/hexColorTransform.ts b/src/devtools/hexColorTransform.ts new file mode 100644 index 0000000..196f4ca --- /dev/null +++ b/src/devtools/hexColorTransform.ts @@ -0,0 +1,56 @@ +import { createFilter, type Plugin } from 'vite'; + +export interface HexColorTransformOptions { + include?: string | string[]; + exclude?: string | string[]; +} + +export default function hexColorTransform( + options: HexColorTransformOptions = {}, +): Plugin { + const filter = createFilter(options.include, options.exclude); + + return { + name: 'vite-plugin-hex-color-transform', + + transform(code, id) { + if (!filter(id)) { + return null; + } + + const hexColorRegex = + /["']#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})["']/g; + + const convertHexTo0x = (_match: string, p1: string) => { + let hex = p1; + + if (hex.length === 3) { + hex = + hex + .split('') + .map((char) => char + char) + .join('') + 'FF'; + } else if (hex.length === 4) { + const alpha = hex[3]! + hex[3]!; + hex = + hex + .slice(0, 3) + .split('') + .map((char) => char + char) + .join('') + alpha; + } else if (hex.length === 6) { + hex += 'FF'; + } + + return `0x${hex.toUpperCase()}`; + }; + + const transformedCode = code.replace(hexColorRegex, convertHexTo0x); + + return { + code: transformedCode, + map: null, + }; + }, + }; +} diff --git a/src/devtools/index.ts b/src/devtools/index.ts index a6d6d8c..7b44b4a 100644 --- a/src/devtools/index.ts +++ b/src/devtools/index.ts @@ -1,6 +1,9 @@ import * as debug from '@solid-devtools/debugger/types'; import * as lng from '../core/index.js'; +export { default as hexColorTransform } from './hexColorTransform.js'; +export type { HexColorTransformOptions } from './hexColorTransform.js'; + const EMPTY_CHILDREN: (lng.ElementNode | lng.ElementText)[] = []; /**