Add tests and CSS 4 syntax support for hsl/hsla colors

This commit is contained in:
Dmitriy Vasyura
2025-12-19 03:21:25 -08:00
parent ae4e9e60ee
commit 192dcc20ec
2 changed files with 52 additions and 3 deletions

View File

@@ -100,8 +100,8 @@ function _findMatches(model: IDocumentColorComputerTarget | string, regex: RegEx
function computeColors(model: IDocumentColorComputerTarget): IColorInformation[] {
const result: IColorInformation[] = [];
// Early validation for RGB and HSL
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%]*\))|^(#)([A-Fa-f0-9]{3})\b|^(#)([A-Fa-f0-9]{4})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"\s])(#)([A-Fa-f0-9]{3})\b|(?<=['"\s])(#)([A-Fa-f0-9]{4})\b|(?<=['"\s])(#)([A-Fa-f0-9]{6})\b|(?<=['"\s])(#)([A-Fa-f0-9]{8})\b/gm;
// Early validation for RGB and HSL (including CSS Level 4 syntax with / separator)
const initialValidationRegex = /\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%\/]*\))|^(#)([A-Fa-f0-9]{3})\b|^(#)([A-Fa-f0-9]{4})\b|^(#)([A-Fa-f0-9]{6})\b|^(#)([A-Fa-f0-9]{8})\b|(?<=['"\s])(#)([A-Fa-f0-9]{3})\b|(?<=['"\s])(#)([A-Fa-f0-9]{4})\b|(?<=['"\s])(#)([A-Fa-f0-9]{6})\b|(?<=['"\s])(#)([A-Fa-f0-9]{8})\b/gm;
const initialValidationMatches = _findMatches(model, initialValidationRegex);
// Potential colors have been found, validate the parameters
@@ -124,7 +124,8 @@ function computeColors(model: IDocumentColorComputerTarget): IColorInformation[]
const regexParameters = /^\(\s*((?:360(?:\.0+)?|(?:36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])(?:\.\d+)?))\s*[\s,]\s*(100(?:\.0+)?|\d{1,2}[.]\d*|\d{1,2})%\s*[\s,]\s*(100(?:\.0+)?|\d{1,2}[.]\d*|\d{1,2})%\s*\)$/gm;
colorInformation = _findHSLColorInformation(_findRange(model, initialMatch), _findMatches(colorParameters, regexParameters), false);
} else if (colorScheme === 'hsla') {
const regexParameters = /^\(\s*((?:360(?:\.0+)?|(?:36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])(?:\.\d+)?))\s*[\s,]\s*(100(?:\.0+)?|\d{1,2}[.]\d*|\d{1,2})%\s*[\s,]\s*(100(?:\.0+)?|\d{1,2}[.]\d*|\d{1,2})%\s*[\s,]\s*(0[.][0-9]+|[.][0-9]+|[01][.]0*|[01])\s*\)$/gm;
// Supports both comma-separated (hsla(253, 100%, 50%, 0.5)) and CSS Level 4 syntax (hsla(253 100% 50% / 0.5))
const regexParameters = /^\(\s*((?:360(?:\.0+)?|(?:36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])(?:\.\d+)?))\s*[\s,]\s*(100(?:\.0+)?|\d{1,2}[.]\d*|\d{1,2})%\s*[\s,]\s*(100(?:\.0+)?|\d{1,2}[.]\d*|\d{1,2})%\s*(?:[\s,]|[\s]*\/)\s*(0[.][0-9]+|[.][0-9]+|[01][.]0*|[01])\s*\)$/gm;
colorInformation = _findHSLColorInformation(_findRange(model, initialMatch), _findMatches(colorParameters, regexParameters), true);
} else if (colorScheme === '#') {
colorInformation = _findHexColorInformation(_findRange(model, initialMatch), colorScheme + colorParameters);

View File

@@ -120,4 +120,52 @@ suite('Default Document Colors Computer', () => {
assert.strictEqual(colors.length, 1, 'Should detect one hsl color');
});
test('hsl with decimal hue values should work', () => {
// Test case from issue #180436 comment
const testCases = [
{ content: 'hsl(253.5, 100%, 50%)', name: 'decimal hue' },
{ content: 'hsl(360.0, 50%, 50%)', name: '360.0 hue' },
{ content: 'hsl(100.5, 50.5%, 50.5%)', name: 'all decimals' },
{ content: 'hsl(0.5, 50%, 50%)', name: 'small decimal hue' },
{ content: 'hsl(359.9, 100%, 50%)', name: 'near-max decimal hue' }
];
testCases.forEach(testCase => {
const model = new TestDocumentModel(`const color = ${testCase.content};`);
const colors = computeDefaultDocumentColors(model);
assert.strictEqual(colors.length, 1, `Should detect hsl color with ${testCase.name}: ${testCase.content}`);
});
});
test('hsla with decimal values should work', () => {
const testCases = [
{ content: 'hsla(253.5, 100%, 50%, 0.5)', name: 'decimal hue with alpha' },
{ content: 'hsla(360.0, 50.5%, 50.5%, 1)', name: 'all decimals with alpha 1' },
{ content: 'hsla(0.5, 50%, 50%, 0.25)', name: 'small decimal hue with alpha' }
];
testCases.forEach(testCase => {
const model = new TestDocumentModel(`const color = ${testCase.content};`);
const colors = computeDefaultDocumentColors(model);
assert.strictEqual(colors.length, 1, `Should detect hsla color with ${testCase.name}: ${testCase.content}`);
});
});
test('hsl with space separator (CSS Level 4 syntax) should work', () => {
// CSS Level 4 allows space-separated values instead of comma-separated
const testCases = [
{ content: 'hsl(253 100% 50%)', name: 'space-separated' },
{ content: 'hsl(253.5 100% 50%)', name: 'space-separated with decimal hue' },
{ content: 'hsla(253 100% 50% / 0.5)', name: 'hsla with slash separator for alpha' },
{ content: 'hsla(253.5 100% 50% / 0.5)', name: 'hsla with decimal hue and slash separator' },
{ content: 'hsla(253 100% 50% / 1)', name: 'hsla with slash and alpha 1' }
];
testCases.forEach(testCase => {
const model = new TestDocumentModel(`const color = ${testCase.content};`);
const colors = computeDefaultDocumentColors(model);
assert.strictEqual(colors.length, 1, `Should detect hsl color with ${testCase.name}: ${testCase.content}`);
});
});
});