mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Admit paired quoted strings inside shadow interpolations
Review finding on #553: the interpolation subpattern excluded quotes, so a documented shadow color after ${getShadow('lg')} or a quoted ternary branch lost its context and fired as drift. Interpolations now admit complete single/double-quoted strings; the quotes pair up inside the ${...}, so an unpaired quote or the template's closing backtick still ends the context and the allowance cannot leak to a later property. AI-assisted (Cursor agent), reviewed by maintainer. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -743,11 +743,12 @@ function isShadowPropertyContext(line, match) {
|
||||
// Unlike jsColorKeyContext, the JS tail admits commas: a multi-layer shadow
|
||||
// string is comma-separated, and a later property on the same line is still
|
||||
// blocked because it sits past the string's closing quote. Both tails also
|
||||
// admit complete `${...}` interpolations, so a tokenized dynamic shadow
|
||||
// (template literal or CSS-in-JS) keeps its context; a bare `}`, quote, or
|
||||
// `;` still ends it.
|
||||
return /(?:^|[{\s;"'`(,])(?:box-shadow|text-shadow)\s*:\s*(?:\$\{[^}"'`]*\}|[^;{}"'`])*$/i.test(before)
|
||||
|| /(?:^|[,{]\s*)(?:boxShadow|textShadow)\s*[:=]\s*["'`]?(?:\$\{[^}"'`]*\}|[^"'`}])*$/i.test(before);
|
||||
// admit complete `${...}` interpolations (including paired quoted strings
|
||||
// inside them, for function arguments and ternaries), so a tokenized
|
||||
// dynamic shadow (template literal or CSS-in-JS) keeps its context; a bare
|
||||
// `}`, quote, or `;` still ends it.
|
||||
return /(?:^|[{\s;"'`(,])(?:box-shadow|text-shadow)\s*:\s*(?:\$\{(?:"[^"]*"|'[^']*'|[^}"'`])*\}|[^;{}"'`])*$/i.test(before)
|
||||
|| /(?:^|[,{]\s*)(?:boxShadow|textShadow)\s*[:=]\s*["'`]?(?:\$\{(?:"[^"]*"|'[^']*'|[^}"'`])*\}|[^"'`}])*$/i.test(before);
|
||||
}
|
||||
|
||||
function isInsideCssAttributeSelector(line, index) {
|
||||
|
||||
@@ -572,17 +572,21 @@ const leak = { boxShadow: "0 1px 2px rgba(0, 0, 0, 0.28)", color: "rgba(0, 0, 0,
|
||||
const findings = checkSourceDesignSystem(`
|
||||
const card = { boxShadow: \`0 \${offset}px 2px rgba(0, 0, 0, 0.28)\` };
|
||||
box-shadow: 0 1px \${blur}px rgba(0, 0, 0, 0.28);
|
||||
const fn = { boxShadow: \`0 \${getShadow('lg')} 2px rgba(0, 0, 0, 0.28)\` };
|
||||
const tern = { boxShadow: \`0 1px \${dark ? "4px" : "2px"} rgba(0, 0, 0, 0.28)\` };
|
||||
box-shadow: 0 \${theme('blur')} rgba(0, 0, 0, 0.28);
|
||||
const leak = { boxShadow: \`0 \${offset}px rgba(0, 0, 0, 0.28)\`, color: "rgba(0, 0, 0, 0.28)" };
|
||||
`, '/tmp/interpolated.js', { designSystem });
|
||||
const colors = findings.filter((item) => item.antipattern === 'design-system-color');
|
||||
|
||||
// The documented shadow color passes after a \${...} interpolation in
|
||||
// both the JS template literal and the CSS-in-JS line; the color key on
|
||||
// the leak line still fires because it sits past the template's closing
|
||||
// backtick.
|
||||
// the JS template literal and the CSS-in-JS line, including
|
||||
// interpolations carrying quoted function arguments or ternary branches;
|
||||
// the color key on the leak line still fires because it sits past the
|
||||
// template's closing backtick.
|
||||
assert.deepEqual(
|
||||
colors.map((item) => [item.line, item.ignoreValue]),
|
||||
[[4, 'rgba(0, 0, 0, 0.28)']],
|
||||
[[7, 'rgba(0, 0, 0, 0.28)']],
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user