Skip to content

Commit 1e817df

Browse files
Lightning00BladeDevtools-frontend LUCI CQ
authored andcommitted
[AI Assistance] Fix CSS nested selector
Strip the special selector, this allows us to at least apply a change, else we didn't pick anything and we failed to update the styles. Bug: 402735143 Change-Id: Iadacb4df3afae67dbcb15b1347bcc1d52bdc2876 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6346593 Auto-Submit: Nikolay Vitkov <[email protected]> Reviewed-by: Ergün Erdoğmuş <[email protected]> Commit-Queue: Nikolay Vitkov <[email protected]>
1 parent 792ed74 commit 1e817df

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

front_end/panels/ai_assistance/ExtensionScope.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,27 @@ describe('ExtensionScope', () => {
233233
const selector = await getSelector({matchedPayload});
234234
assert.strictEqual(selector, '.test');
235235
});
236+
237+
it('should work with nested selector and strip the &', async () => {
238+
// Order is reversed we know that specificity order will
239+
// be returned correctly
240+
// front_end/core/sdk/CSSMatchedStyles.ts:373
241+
const matchedPayload = [
242+
ruleMatch('.test', MOCK_STYLE),
243+
ruleMatch(
244+
{
245+
selectors: [{text: 'div&'}],
246+
text: 'div&',
247+
},
248+
MOCK_STYLE,
249+
{
250+
nestingSelectors: ['.my-parent-selector'],
251+
},
252+
)
253+
];
254+
const selector = await getSelector({matchedPayload});
255+
assert.strictEqual(selector, 'div');
256+
});
236257
});
237258

238259
describeWithMockConnection('getSourceLocation', () => {

front_end/panels/ai_assistance/ExtensionScope.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ export class ExtensionScope {
148148

149149
static getStyleRuleFromMatchesStyles(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles): SDK.CSSRule.CSSStyleRule
150150
|undefined {
151-
let styleRule: SDK.CSSRule.CSSStyleRule|undefined;
152151
for (const style of matchedStyles.nodeStyles()) {
153152
// Ignore inline as we can't override them
154153
if (style.type === 'Inline') {
@@ -168,11 +167,10 @@ export class ExtensionScope {
168167
continue;
169168
}
170169

171-
styleRule = rule;
172-
break;
170+
return rule;
173171
}
174172
}
175-
return styleRule;
173+
return;
176174
}
177175

178176
static getSelectorsFromStyleRule(
@@ -199,8 +197,16 @@ export class ExtensionScope {
199197
return b.specificity.b - a.specificity.b;
200198
});
201199

200+
const selector = selectors.at(0);
201+
if (!selector) {
202+
return '';
203+
}
202204
// See https://developer.mozilla.org/en-US/docs/Web/CSS/Privacy_and_the_:visited_selector
203-
return selectors.at(0)?.text.replace(':visited', '') ?? '';
205+
let cssSelector = selector.text.replaceAll(':visited', '');
206+
// See https://www.w3.org/TR/css-nesting-1/#nest-selector
207+
cssSelector = cssSelector.replaceAll('&', '');
208+
209+
return cssSelector.trim();
204210
}
205211

206212
static getSelectorForNode(node: SDK.DOMModel.DOMNode): string {

test/shared/helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ export const $$textContent = async (textContent: string, root?: puppeteer.Elemen
237237
return await $$(textContent, root, 'pierceShadowText');
238238
};
239239

240-
export const timeout = (duration: number) => new Promise(resolve => setTimeout(resolve, duration));
240+
export const timeout = (duration: number) => new Promise<void>(resolve => setTimeout(resolve, duration));
241241

242242
export const getTextContent =
243243
async<ElementType extends Element = Element>(selector: string, root?: puppeteer.ElementHandle) => {

0 commit comments

Comments
 (0)