feat: initial commit of Railtrack Pro prototype with complete test suite

This commit is contained in:
Railtrack Pro Dev committed 2026-03-13 14:26:16 +00:00
commit 40500bb503
7790 files changed
+986332

No files matched your search

+10
View File
@@ -0,0 +1,10 @@
# Changes to CSS Color Parser
### 4.0.2
_February 21, 2026_
- Updated [`@csstools/css-calc`](https://github.com/csstools/postcss-plugins/tree/main/packages/css-calc) to [`3.1.1`](https://github.com/csstools/postcss-plugins/tree/main/packages/css-calc/CHANGELOG.md#311) (minor)
- Updated [`@csstools/color-helpers`](https://github.com/csstools/postcss-plugins/tree/main/packages/color-helpers) to [`6.0.2`](https://github.com/csstools/postcss-plugins/tree/main/packages/color-helpers/CHANGELOG.md#602) (patch)
[Full CHANGELOG](https://github.com/csstools/postcss-plugins/tree/main/packages/css-color-parser/CHANGELOG.md)
+20
View File
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright 2022 Romain Menke, Antonio Laguna <antonio@laguna.es>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+37
View File
@@ -0,0 +1,37 @@
# CSS Color Parser <img src="https://cssdb.org/images/css.svg" alt="for CSS" width="90" height="90" align="right">
[<img alt="npm version" src="https://img.shields.io/npm/v/@csstools/css-color-parser.svg" height="20">][npm-url]
[<img alt="Build Status" src="https://github.com/csstools/postcss-plugins/actions/workflows/test.yml/badge.svg?branch=main" height="20">][cli-url]
[<img alt="Discord" src="https://shields.io/badge/Discord-5865F2?logo=discord&logoColor=white">][discord]
## Usage
Add [CSS Color Parser] to your project:
```bash
npm install @csstools/css-color-parser @csstools/css-parser-algorithms @csstools/css-tokenizer --save-dev
```
```ts
import { color } from '@csstools/css-color-parser';
import { isFunctionNode, parseComponentValue } from '@csstools/css-parser-algorithms';
import { serializeRGB } from '@csstools/css-color-parser';
import { tokenize } from '@csstools/css-tokenizer';
// color() expects a parsed component value.
const hwbComponentValue = parseComponentValue(tokenize({ css: 'hwb(10deg 10% 20%)' }));
const colorData = color(hwbComponentValue);
if (colorData) {
console.log(colorData);
// serializeRGB() returns a component value.
const rgbComponentValue = serializeRGB(colorData);
console.log(rgbComponentValue.toString());
}
```
[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
[discord]: https://discord.gg/bUadyRwkJS
[npm-url]: https://www.npmjs.com/package/@csstools/css-color-parser
[CSS Color Parser]: https://github.com/csstools/postcss-plugins/tree/main/packages/css-color-parser
+168
View File
@@ -0,0 +1,168 @@
import type { Color } from '@csstools/color-helpers';
import type { ComponentValue } from '@csstools/css-parser-algorithms';
import { FunctionNode } from '@csstools/css-parser-algorithms';
/**
* Convert a color function to a `ColorData` object.
*
* @param {ComponentValue} colorNode - The color function to be converted.
* @returns {ColorData|false} The color function as a `ColorData` object or `false` if it could not be converted.
*/
export declare function color(colorNode: ComponentValue): ColorData | false;
/**
* A color data object.
* It contains as much information as possible about the color and the original parsed syntax.
*/
export declare interface ColorData {
/**
* The color notation of the color data.
*
* We use "color notation" and not "color space" because these represent the original notation and not the actual color space.
* The actual color space is however always implied by the color notation.
*/
colorNotation: ColorNotation;
/**
* The color channels.
* This is always an array of three numbers
* but the channels can only be interpreted by looking at the color notation.
*/
channels: Color;
/**
* The alpha channel.
* This is either a number between `0` and `1` or a `ComponentValue` object.
*
* Since most computations are not dependent on the alpha channel,
* we allow things like `var(--some-alpha)` as an alpha channel value for most inputs.
*/
alpha: number | ComponentValue;
/**
* Information about the original syntax.
*/
syntaxFlags: Set<SyntaxFlag>;
}
/**
* Check if a color data object fits the `display-p3` gamut.
*
* @param {ColorData} x - The color data to be checked.
* @returns {boolean} Whether the color data fits the `display-p3` gamut.
*/
export declare function colorDataFitsDisplayP3_Gamut(x: ColorData): boolean;
/**
* Check if a color data object fits the `sRGB` gamut.
*
* @param {ColorData} x - The color data to be checked.
* @returns {boolean} Whether the color data fits the `sRGB` gamut.
*/
export declare function colorDataFitsRGB_Gamut(x: ColorData): boolean;
export declare enum ColorNotation {
/** Adobe 1999, expressed through `color(a98-rgb 0 0 0)` */
A98_RGB = "a98-rgb",
/** Display P3, expressed through `color(display-p3 0 0 0)` */
Display_P3 = "display-p3",
/** Display P3, expressed through `color(display-p3-linear 0 0 0)` */
Linear_Display_P3 = "display-p3-linear",
/** Hex, expressed through `#000` */
HEX = "hex",
/** HSL, expressed through `hsl(0 0% 0%)` */
HSL = "hsl",
/** HWB, expressed through `hwb(0 0% 0%)` */
HWB = "hwb",
/** LCH, expressed through `lch(0 0% 0deg)` */
LCH = "lch",
/** Lab, expressed through `lab(0 0 0)` */
Lab = "lab",
/** Linear sRGB, expressed through `color(linear-srgb 0 0 0)` */
Linear_sRGB = "srgb-linear",
/** Oklch, expressed through `oklch(0 0% 0deg)` */
OKLCH = "oklch",
/** Oklab, expressed through `oklab(0 0 0)` */
OKLab = "oklab",
/** ProPhoto RGB, expressed through `color(prophoto-rgb 0 0 0)` */
ProPhoto_RGB = "prophoto-rgb",
/** RGB, expressed through `rgb(0 0 0)` */
RGB = "rgb",
/** sRGB, expressed through `color(srgb 0 0 0)` */
sRGB = "srgb",
/** Rec. 2020, expressed through `color(rec2020 0 0 0)` */
Rec2020 = "rec2020",
/** XYZ, expressed through `color(xyz-d50 0 0 0)` */
XYZ_D50 = "xyz-d50",
/** XYZ, expressed through `color(xyz-d65 0 0 0)` */
XYZ_D65 = "xyz-d65"
}
export declare function serializeHSL(color: ColorData, gamutMapping?: boolean): FunctionNode;
/**
* Convert color data to component values in the OKLCH color space.
* The return value can be converted to a string by calling `toString()` on it.
*
* @param {ColorData} color - The color data to be serialized.
* @returns {FunctionNode} The serialized color data as a FunctionNode object.
*/
export declare function serializeOKLCH(color: ColorData): FunctionNode;
/**
* Convert color data to component values in the display-p3 color space.
* The return value can be converted to a string by calling `toString()` on it.
*
* @param {ColorData} color - The color data to be serialized.
* @param {boolean} gamutMapping - Whether to perform gamut mapping, defaults to `true`.
* @returns {FunctionNode} The serialized color data as a FunctionNode object.
*/
export declare function serializeP3(color: ColorData, gamutMapping?: boolean): FunctionNode;
/**
* Convert color data to component values in the srgb color space.
* The return value can be converted to a string by calling `toString()` on it.
*
* @param {ColorData} color - The color data to be serialized.
* @param {boolean} gamutMapping - Whether to perform gamut mapping, defaults to `true`.
* @returns {FunctionNode} The serialized color data as a FunctionNode object.
*/
export declare function serializeRGB(color: ColorData, gamutMapping?: boolean): FunctionNode;
export declare enum SyntaxFlag {
/** Is a color keyword, e.g. `transparent`, `currentColor`, ... */
ColorKeyword = "color-keyword",
/** Has an explicit alpha channel */
HasAlpha = "has-alpha",
/** Has a channel with a dimension value, e.g. `50deg` */
HasDimensionValues = "has-dimension-values",
/** Has a channel with the `none` keyword */
HasNoneKeywords = "has-none-keywords",
/** Has a channel with a number value */
HasNumberValues = "has-number-values",
/** Has an alpha channel with a percentage value */
HasPercentageAlpha = "has-percentage-alpha",
/** Has a channel with a percentage value */
HasPercentageValues = "has-percentage-values",
/** Has an alpha channel with a `var()` function value */
HasVariableAlpha = "has-variable-alpha",
/** Is Hex notation */
Hex = "hex",
/** Is legacy HSL, e.g. `hsl(50deg, 0%, 0%)` */
LegacyHSL = "legacy-hsl",
/** Is legacy RGB, e.g. `rgb(0, 0, 0)` */
LegacyRGB = "legacy-rgb",
/** Is a named color, e.g. `red`, `blue` */
NamedColor = "named-color",
/** Is a relative color syntax, e.g. `rgb(from purple r g b)` */
RelativeColorSyntax = "relative-color-syntax",
/** Is a mixed color, e.g. `color-mix(in oklch, red, blue)` */
ColorMix = "color-mix",
/** Is a variadic mixed color, e.g. `color-mix(in oklch, red)` `color-mix(in oklch, red, blue, green)` */
ColorMixVariadic = "color-mix-variadic",
/** Is a contrasting color, e.g. `contrast-color()` */
ContrastColor = "contrast-color",
/** Is a relative alpha syntax `alpha(from red / 0.5)` */
RelativeAlphaSyntax = "relative-alpha-syntax",
/** Is an experimental color syntax */
Experimental = "experimental"
}
export { }
+1
View File
@@ -0,0 +1 @@
import{TokenType as e,NumberType as a,isTokenIdent as n,isTokenPercentage as r,isTokenNumber as o,isTokenDelim as t,isTokenNumeric as l,isTokenComma as s,isTokenDimension as u,isTokenHash as i}from"@csstools/css-tokenizer";import{XYZ_D50_to_XYZ_D65 as c,XYZ_D50_to_XYZ_D50 as h,XYZ_D50_to_OKLab as m,XYZ_D50_to_OKLCH as p,XYZ_D50_to_LCH as N,XYZ_D50_to_Lab as b,XYZ_D50_to_HWB as v,XYZ_D50_to_HSL as g,XYZ_D50_to_a98_RGB as f,XYZ_D50_to_ProPhoto as d,XYZ_D50_to_rec_2020 as y,XYZ_D50_to_lin_P3 as _,XYZ_D50_to_P3 as C,XYZ_D50_to_lin_sRGB as w,XYZ_D50_to_sRGB as x,XYZ_D65_to_XYZ_D50 as L,OKLCH_to_XYZ_D50 as H,LCH_to_XYZ_D50 as P,OKLab_to_XYZ_D50 as k,Lab_to_XYZ_D50 as S,HWB_to_XYZ_D50 as D,HSL_to_XYZ_D50 as M,ProPhoto_RGB_to_XYZ_D50 as F,a98_RGB_to_XYZ_D50 as z,rec_2020_to_XYZ_D50 as Z,lin_P3_to_XYZ_D50 as R,P3_to_XYZ_D50 as B,lin_sRGB_to_XYZ_D50 as V,sRGB_to_XYZ_D50 as T,namedColors as G,inGamut as A,clip as X,gam_sRGB as K,mapGamutRayTrace as Y,OKLCH_to_OKLab as I,OKLab_to_XYZ as O,XYZ_to_lin_sRGB as W,lin_sRGB_to_XYZ as E,XYZ_to_OKLab as U,OKLab_to_OKLCH as $,contrast_ratio_wcag_2_1 as j,gam_P3 as q,XYZ_to_lin_P3 as J,lin_P3_to_XYZ as Q}from"@csstools/color-helpers";import{isWhitespaceNode as ee,isCommentNode as ae,isTokenNode as ne,isFunctionNode as re,TokenNode as oe,isWhiteSpaceOrCommentNode as te,replaceComponentValues as le,FunctionNode as se,WhitespaceNode as ue}from"@csstools/css-parser-algorithms";import{mathFunctionNames as ie,calcFromComponentValues as ce}from"@csstools/css-calc";var he,me;function convertNaNToZero(e){return[Number.isNaN(e[0])?0:e[0],Number.isNaN(e[1])?0:e[1],Number.isNaN(e[2])?0:e[2]]}function colorData_to_XYZ_D50(e){switch(e.colorNotation){case he.HEX:case he.RGB:case he.sRGB:return{...e,colorNotation:he.XYZ_D50,channels:T(convertNaNToZero(e.channels))};case he.Linear_sRGB:return{...e,colorNotation:he.XYZ_D50,channels:V(convertNaNToZero(e.channels))};case he.Display_P3:return{...e,colorNotation:he.XYZ_D50,channels:B(convertNaNToZero(e.channels))};case he.Linear_Display_P3:return{...e,colorNotation:he.XYZ_D50,channels:R(convertNaNToZero(e.channels))};case he.Rec2020:return{...e,colorNotation:he.XYZ_D50,channels:Z(convertNaNToZero(e.channels))};case he.A98_RGB:return{...e,colorNotation:he.XYZ_D50,channels:z(convertNaNToZero(e.channels))};case he.ProPhoto_RGB:return{...e,colorNotation:he.XYZ_D50,channels:F(convertNaNToZero(e.channels))};case he.HSL:return{...e,colorNotation:he.XYZ_D50,channels:M(convertNaNToZero(e.channels))};case he.HWB:return{...e,colorNotation:he.XYZ_D50,channels:D(convertNaNToZero(e.channels))};case he.Lab:return{...e,colorNotation:he.XYZ_D50,channels:S(convertNaNToZero(e.channels))};case he.OKLab:return{...e,colorNotation:he.XYZ_D50,channels:k(convertNaNToZero(e.channels))};case he.LCH:return{...e,colorNotation:he.XYZ_D50,channels:P(convertNaNToZero(e.channels))};case he.OKLCH:return{...e,colorNotation:he.XYZ_D50,channels:H(convertNaNToZero(e.channels))};case he.XYZ_D50:return{...e,colorNotation:he.XYZ_D50,channels:h(convertNaNToZero(e.channels))};case he.XYZ_D65:return{...e,colorNotation:he.XYZ_D50,channels:L(convertNaNToZero(e.channels))};default:throw new Error("Unsupported color notation")}}!function(e){e.A98_RGB="a98-rgb",e.Display_P3="display-p3",e.Linear_Display_P3="display-p3-linear",e.HEX="hex",e.HSL="hsl",e.HWB="hwb",e.LCH="lch",e.Lab="lab",e.Linear_sRGB="srgb-linear",e.OKLCH="oklch",e.OKLab="oklab",e.ProPhoto_RGB="prophoto-rgb",e.RGB="rgb",e.sRGB="srgb",e.Rec2020="rec2020",e.XYZ_D50="xyz-d50",e.XYZ_D65="xyz-d65"}(he||(he={})),function(e){e.ColorKeyword="color-keyword",e.HasAlpha="has-alpha",e.HasDimensionValues="has-dimension-values",e.HasNoneKeywords="has-none-keywords",e.HasNumberValues="has-number-values",e.HasPercentageAlpha="has-percentage-alpha",e.HasPercentageValues="has-percentage-values",e.HasVariableAlpha="has-variable-alpha",e.Hex="hex",e.LegacyHSL="legacy-hsl",e.LegacyRGB="legacy-rgb",e.NamedColor="named-color",e.RelativeColorSyntax="relative-color-syntax",e.ColorMix="color-mix",e.ColorMixVariadic="color-mix-variadic",e.ContrastColor="contrast-color",e.RelativeAlphaSyntax="relative-alpha-syntax",e.Experimental="experimental"}(me||(me={}));const pe=new Set([he.A98_RGB,he.Display_P3,he.Linear_Display_P3,he.HEX,he.Linear_sRGB,he.ProPhoto_RGB,he.RGB,he.sRGB,he.Rec2020,he.XYZ_D50,he.XYZ_D65]);function colorDataTo(e,a){const n={...e};if(e.colorNotation!==a){const e=colorData_to_XYZ_D50(n);switch(a){case he.HEX:case he.RGB:n.colorNotation=he.RGB,n.channels=x(e.channels);break;case he.sRGB:n.colorNotation=he.sRGB,n.channels=x(e.channels);break;case he.Linear_sRGB:n.colorNotation=he.Linear_sRGB,n.channels=w(e.channels);break;case he.Display_P3:n.colorNotation=he.Display_P3,n.channels=C(e.channels);break;case he.Linear_Display_P3:n.colorNotation=he.Linear_Display_P3,n.channels=_(e.channels);break;case he.Rec2020:n.colorNotation=he.Rec2020,n.channels=y(e.channels);break;case he.ProPhoto_RGB:n.colorNotation=he.ProPhoto_RGB,n.channels=d(e.channels);breaLine truncated
+64
View File
@@ -0,0 +1,64 @@
{
"name": "@csstools/css-color-parser",
"description": "Parse CSS color values",
"version": "4.0.2",
"contributors": [
{
"name": "Antonio Laguna",
"email": "[email protected]",
"url": "https://antonio.laguna.es"
},
{
"name": "Romain Menke",
"email": "[email protected]"
}
],
"license": "MIT",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"engines": {
"node": ">=20.19.0"
},
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.mjs"
}
},
"files": [
"CHANGELOG.md",
"LICENSE.md",
"README.md",
"dist"
],
"dependencies": {
"@csstools/color-helpers": "^6.0.2",
"@csstools/css-calc": "^3.1.1"
},
"peerDependencies": {
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0"
},
"scripts": {},
"homepage": "https://github.com/csstools/postcss-plugins/tree/main/packages/css-color-parser#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/csstools/postcss-plugins.git",
"directory": "packages/css-color-parser"
},
"bugs": "https://github.com/csstools/postcss-plugins/issues",
"keywords": [
"color",
"css",
"parser"
]
}