Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show style applied on tag (p, span, div) and private selectors as parent rules instead of hiding them #5890

32 changes: 28 additions & 4 deletions src/style_manager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,8 @@ export default class StyleManager extends ItemManagerModule<
const cmp = target.toHTML ? target : target.getComponent();
const optsSel = { array: true } as const;
let cmpRules: CssRule[] = [];
let tagNameRules: CssRule[] = [];
let invisibleAndOtherRules: CssRule[] = [];
let otherRules: CssRule[] = [];
let rules: CssRule[] = [];

Expand All @@ -605,19 +607,41 @@ export default class StyleManager extends ItemManagerModule<
? []
: cssC.getRules().filter(rule => {
const rSels = rule.getSelectors().map(s => s.getFullName());
return !!rSels.length && rSels.every(rSel => values.indexOf(rSel) >= 0);

// rSels is equal to 0 when rule selectors contain tagName like : p {}, .logo path {}, ul li {}
if (rSels.length === 0) {
return false;
}

return rSels.every(rSel => values.indexOf(rSel) >= 0);
});
};

const rulesByTagName = (tagName: string) => {
return !tagName ? [] : cssC.getRules().filter(rule => rule.selectorsToString() === tagName);
};

// Componente related rule
if (cmp) {
cmpRules = cssC.getRules(`#${cmp.getId()}`);
tagNameRules = rulesByTagName(cmp.get('tagName'));
otherRules = sel ? rulesBySelectors(sel.getSelectors().getFullName(optsSel)) : [];
rules = otherRules.concat(cmpRules);
rules = otherRules.concat(tagNameRules).concat(cmpRules);
} else {
cmpRules = sel ? cssC.getRules(`#${sel.getId()}`) : [];
otherRules = rulesBySelectors(target.getSelectors().getFullName(optsSel));
rules = cmpRules.concat(otherRules);
tagNameRules = rulesByTagName(sel?.get('tagName') || '');
// Get rules set on invisible selectors like private one
const allCmpClasses = sel?.getSelectors().getFullName(optsSel) || [];
const invisibleSel = allCmpClasses.filter(
(item: string) =>
target
.getSelectors()
.getFullName(optsSel)
.findIndex(sel => sel === item) === -1
);
// Get rules set on active and visible selectors
invisibleAndOtherRules = rulesBySelectors(invisibleSel.concat(target.getSelectors().getFullName(optsSel)));
rules = tagNameRules.concat(cmpRules).concat(invisibleAndOtherRules);
}

const all = rules
Expand Down
66 changes: 66 additions & 0 deletions test/specs/style_manager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,72 @@ describe('StyleManager', () => {
expect(obj.getSelectedParents()).toEqual([rule1]);
});

test('With multiple classes, should both be in parents list', () => {
const cmp = domc.addComponent('<div class="cls cls2"></div>');
const [rule1, rule2] = cssc.addRules(`
.cls { color: red; }
.cls2 { color: blue; }
`);
em.setSelected(cmp);
obj.__upSel();
expect(obj.getSelected()).not.toBe(rule1);
expect(obj.getSelected()).not.toBe(rule2);
expect(obj.getSelectedParents()).toEqual([rule2, rule1]);
});

test('With tagName + class, class first', () => {
const cmp = domc.addComponent('<div class="cls" id="id-test"></div>');
const [rule1, rule2] = cssc.addRules(`
.cls { color: red; }
div { color: yellow; }
`);
em.setSelected(cmp);
obj.__upSel();
expect(obj.getSelected()).toBe(rule1);
expect(obj.getSelectedParents()).toEqual([rule2]);
});

test('Should ignore rules with tagName in the selector path but the rule is not apply on the tagName', () => {
const cmp = domc.addComponent('<div class="cls" id="id-test"></div>');
const [rule1, rule2] = cssc.addRules(`
.cls { color: red; }
div { color: yellow; }
div .child { padding: 10px; }
`);
em.setSelected(cmp);
obj.__upSel();
// getSelectedParents should only have 1 rule as the third one is not applied on the div
expect(obj.getSelected()).toBe(rule1);
expect(obj.getSelectedParents()).toEqual([rule2]);
});

test('Should tagName rules if the selectors does not contain only the tagNale', () => {
const cmp = domc.addComponent('<div class="cls" id="id-test"></div>');
const [rule1, rule2] = cssc.addRules(`
.cls { color: red; }
div { color: yellow; }
.child div { padding: 10px; }
`);
em.setSelected(cmp);
obj.__upSel();
// getSelectedParents should only have 1 rule as the third one is not applied on the div
expect(obj.getSelected()).toBe(rule1);
expect(obj.getSelectedParents()).toEqual([rule2]);
});

test('With tagName + ID + class, class first, ID second', () => {
const cmp = domc.addComponent('<div class="cls" id="id-test"></div>');
const [rule1, rule2, rule3] = cssc.addRules(`
.cls { color: red; }
div { color: yellow; }
#id-test { color: blue; }
`);
em.setSelected(cmp);
obj.__upSel();
expect(obj.getSelected()).toBe(rule1);
expect(obj.getSelectedParents()).toEqual([rule3, rule2]);
});

test('With ID + class, multiple devices', () => {
sm.setComponentFirst(true);
const cmp = domc.addComponent('<div class="cls" id="id-test"></div>');
Expand Down
Loading