mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-28 06:31:58 +00:00
Merge pull request #284423 from microsoft/dev/dmitriv/hsla-colors-regex
Add tests and CSS 4 syntax support
This commit is contained in:
commit
83f180cca3
@ -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
|
||||
@ -115,16 +115,19 @@ function computeColors(model: IDocumentColorComputerTarget): IColorInformation[]
|
||||
}
|
||||
let colorInformation;
|
||||
if (colorScheme === 'rgb') {
|
||||
const regexParameters = /^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*\)$/gm;
|
||||
// Supports both comma-separated (rgb(255, 0, 0)) and CSS Level 4 space-separated syntax (rgb(255 0 0))
|
||||
const regexParameters = /^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*[\s,]\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*[\s,]\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*\)$/gm;
|
||||
colorInformation = _findRGBColorInformation(_findRange(model, initialMatch), _findMatches(colorParameters, regexParameters), false);
|
||||
} else if (colorScheme === 'rgba') {
|
||||
const regexParameters = /^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(0[.][0-9]+|[.][0-9]+|[01][.]|[01])\s*\)$/gm;
|
||||
// Supports both comma-separated (rgba(255, 0, 0, 0.5)) and CSS Level 4 syntax (rgba(255 0 0 / 0.5))
|
||||
const regexParameters = /^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*[\s,]\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*[\s,]\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*(?:[\s,]|[\s]*\/)\s*(0[.][0-9]+|[.][0-9]+|[01][.]|[01])\s*\)$/gm;
|
||||
colorInformation = _findRGBColorInformation(_findRange(model, initialMatch), _findMatches(colorParameters, regexParameters), true);
|
||||
} else if (colorScheme === 'hsl') {
|
||||
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);
|
||||
|
||||
@ -120,4 +120,72 @@ 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}`);
|
||||
});
|
||||
});
|
||||
|
||||
test('rgb and rgba with CSS Level 4 space-separated syntax should work', () => {
|
||||
// CSS Level 4 allows space-separated values for RGB/RGBA
|
||||
const testCases = [
|
||||
{ content: 'rgb(255 0 0)', name: 'rgb space-separated' },
|
||||
{ content: 'rgb(128 128 128)', name: 'rgb space-separated gray' },
|
||||
{ content: 'rgba(255 0 0 / 0.5)', name: 'rgba with slash separator for alpha' },
|
||||
{ content: 'rgba(128 128 128 / 0.8)', name: 'rgba gray with slash separator' },
|
||||
{ content: 'rgba(255 0 0 / 1)', name: 'rgba with slash and alpha 1' },
|
||||
// Traditional comma syntax should still work
|
||||
{ content: 'rgb(255, 0, 0)', name: 'rgb comma-separated (traditional)' },
|
||||
{ content: 'rgba(255, 0, 0, 0.5)', name: 'rgba comma-separated (traditional)' }
|
||||
];
|
||||
|
||||
testCases.forEach(testCase => {
|
||||
const model = new TestDocumentModel(`const color = ${testCase.content};`);
|
||||
const colors = computeDefaultDocumentColors(model);
|
||||
assert.strictEqual(colors.length, 1, `Should detect rgb/rgba color with ${testCase.name}: ${testCase.content}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user