From c3f4cebb7aceb41da7421bd7a0aedeaed54df524 Mon Sep 17 00:00:00 2001 From: SwetaTanwar Date: Fri, 29 Aug 2025 22:30:54 +0530 Subject: [PATCH 1/2] fix: allow relative color syntax for rgb() and rgba() --- data/patch.json | 9 ++ lib/__tests/lexer-relative-colors.js | 134 +++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 lib/__tests/lexer-relative-colors.js diff --git a/data/patch.json b/data/patch.json index 1b902d12..3bfe65f6 100644 --- a/data/patch.json +++ b/data/patch.json @@ -584,6 +584,9 @@ "comment": "missed, https://drafts.csswg.org/css-contain-3/#container-rule", "syntax": "not | [ [ and ]* | [ or ]* ]" }, + "component-ident": { + "syntax": "r | g | b | alpha" + }, "coord-box": { "syntax": "content-box | padding-box | border-box | fill-box | stroke-box | view-box" }, @@ -770,6 +773,12 @@ "color()": { "syntax": "color( [ / [ | none ] ]? )" }, + "rgb()": { + "syntax": "rgb( #{3} , ? ) | rgb( [ | | none ]{3} [ / [ | none ] ]? ) | rgb( from [ | | | ]{3} [ / [ | | ] ]? )" + }, + "rgba()": { + "syntax": "rgba( #{3} , ? ) | rgba( [ | | none ]{3} [ / [ | none ] ]? ) | rgba( from [ | | | ]{3} [ / [ | | ] ]? )" + }, "colorspace-params": { "syntax": "[ | ]" }, diff --git a/lib/__tests/lexer-relative-colors.js b/lib/__tests/lexer-relative-colors.js new file mode 100644 index 00000000..d599e714 --- /dev/null +++ b/lib/__tests/lexer-relative-colors.js @@ -0,0 +1,134 @@ +import assert from 'assert'; +import { lexer } from '../index.js'; + +describe('lexer relative colors', () => { + describe('rgb() with relative colors', () => { + it('should match rgb(25 25 25 / 50%)', () => { + const result = lexer.matchProperty('color', 'rgb(25 25 25 / 50%)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgb(from hsl(0 100% 50%) r g b)', () => { + const result = lexer.matchProperty('color', 'rgb(from hsl(0 100% 50%) r g b)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgb(from hsl(0 100% 50%) 132 132 224)', () => { + const result = lexer.matchProperty('color', 'rgb(from hsl(0 100% 50%) 132 132 224)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgb(from #123456 calc(r + 40) calc(g + 40) b)', () => { + const result = lexer.matchProperty('color', 'rgb(from #123456 calc(r + 40) calc(g + 40) b)'); + + assert(result.matched, 'Should match relative color with calc functions'); + }); + + it('should match rgb(from hwb(120deg 10% 20%) r g calc(b + 200))', () => { + const result = lexer.matchProperty('color', 'rgb(from hwb(120deg 10% 20%) r g calc(b + 200))'); + + assert(result.matched, 'Should match relative color with hwb and calc'); + }); + + it('should match rgb(25 25 25 / 50%)', () => { + const result = lexer.matchProperty('color', 'rgb(25 25 25 / 50%)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgb(from hsl(0 100% 50%) r 80 80)', () => { + const result = lexer.matchProperty('color', 'rgb(from hsl(0 100% 50%) r 80 80)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgb(from hsl(0 100% 50% / 0.8) r g b / alpha)', () => { + const result = lexer.matchProperty('color', 'rgb(from hsl(0 100% 50% / 0.8) r g b / alpha)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgb(from hsl(0 100% 50% / 0.8) r g b / 0.5)', () => { + const result = lexer.matchProperty('color', 'rgb(from hsl(0 100% 50% / 0.8) r g b / 0.5)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgb(from hsl(0 100% 50%) calc(r/2) calc(g + 25) calc(b + 175) / calc(alpha - 0.1))', () => { + const result = lexer.matchProperty('color', 'rgb(from hsl(0 100% 50%) calc(r/2) calc(g + 25) calc(b + 175) / calc(alpha - 0.1))'); + + assert(result.matched, 'Should match relative color syntax'); + }); + }); + + describe('rgba() with relative colors', () => { + it('should match rgba(25 25 25)', () => { + const result = lexer.matchProperty('color', 'rgba(25 25 25)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(25 25 25 / 50%)', () => { + const result = lexer.matchProperty('color', 'rgba(25 25 25 / 50%)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(from hsl(0 100% 50%) r g b)', () => { + const result = lexer.matchProperty('color', 'rgba(from hsl(0 100% 50%) r g b)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(from hsl(0 100% 50%) 132 132 224)', () => { + const result = lexer.matchProperty('color', 'rgba(from hsl(0 100% 50%) 132 132 224)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(from #123456 calc(r + 40) calc(g + 40) b)', () => { + const result = lexer.matchProperty('color', 'rgba(from #123456 calc(r + 40) calc(g + 40) b)'); + + assert(result.matched, 'Should match relative color with calc functions'); + }); + + it('should match rgba(from hwb(120deg 10% 20%) r g calc(b + 200))', () => { + const result = lexer.matchProperty('color', 'rgba(from hwb(120deg 10% 20%) r g calc(b + 200))'); + + assert(result.matched, 'Should match relative color with hwb and calc'); + }); + + it('should match rgba(25 25 25 / 50%)', () => { + const result = lexer.matchProperty('color', 'rgba(25 25 25 / 50%)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(from hsl(0 100% 50%) r 80 80)', () => { + const result = lexer.matchProperty('color', 'rgba(from hsl(0 100% 50%) r 80 80)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(from hsl(0 100% 50% / 0.8) r g b / alpha)', () => { + const result = lexer.matchProperty('color', 'rgba(from hsl(0 100% 50% / 0.8) r g b / alpha)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(from hsl(0 100% 50% / 0.8) r g b / 0.5)', () => { + const result = lexer.matchProperty('color', 'rgba(from hsl(0 100% 50% / 0.8) r g b / 0.5)'); + + assert(result.matched, 'Should match relative color syntax'); + }); + + it('should match rgba(from hsl(0 100% 50%) calc(r/2) calc(g + 25) calc(b + 175) / calc(alpha - 0.1))', () => { + const result = lexer.matchProperty('color', 'rgba(from hsl(0 100% 50%) calc(r/2) calc(g + 25) calc(b + 175) / calc(alpha - 0.1))'); + + assert(result.matched, 'Should match relative color syntax'); + }); + }); +}); From 8cbe7e1b0da7ecf7fe409fff161d08c23821842d Mon Sep 17 00:00:00 2001 From: SwetaTanwar Date: Sun, 31 Aug 2025 20:28:49 +0530 Subject: [PATCH 2/2] chore: fix lint --- data/patch.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/patch.json b/data/patch.json index 3bfe65f6..3789d460 100644 --- a/data/patch.json +++ b/data/patch.json @@ -774,10 +774,10 @@ "syntax": "color( [ / [ | none ] ]? )" }, "rgb()": { - "syntax": "rgb( #{3} , ? ) | rgb( [ | | none ]{3} [ / [ | none ] ]? ) | rgb( from [ | | | ]{3} [ / [ | | ] ]? )" + "syntax": "rgb( #{3} , ? ) | rgb( [ | | none ]{3} [ / [ | none ] ]? ) | rgb( from [ | | | ]{3} [ / [ | | ] ]? )" }, "rgba()": { - "syntax": "rgba( #{3} , ? ) | rgba( [ | | none ]{3} [ / [ | none ] ]? ) | rgba( from [ | | | ]{3} [ / [ | | ] ]? )" + "syntax": "rgba( #{3} , ? ) | rgba( [ | | none ]{3} [ / [ | none ] ]? ) | rgba( from [ | | | ]{3} [ / [ | | ] ]? )" }, "colorspace-params": { "syntax": "[ | ]"