Lint and format src/compiler/compile/css/Stylesheet.js

pull/8569/head
Simon Holthausen 3 years ago
parent 205993151e
commit 61ca425898

@ -23,7 +23,8 @@ const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes'
* @param {import('./private.js').CssNode} * @param {import('./private.js').CssNode}
* @returns {true} * @returns {true}
*/ */
const at_rule_has_declaration = ({ block }) => block && block.children && block.children.find((node) => node.type === 'Declaration'); const at_rule_has_declaration = ({ block }) =>
block && block.children && block.children.find((node) => node.type === 'Declaration');
/** /**
* @param {import('magic-string').default} code * @param {import('magic-string').default} code
@ -44,7 +45,6 @@ function minify_declarations(code, start, declarations) {
return c; return c;
} }
class Rule { class Rule {
/** @type {import('./Selector.js').default[]} */ /** @type {import('./Selector.js').default[]} */
selectors; selectors;
@ -78,8 +78,7 @@ class Rule {
is_used(dev) { is_used(dev) {
if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node)) if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
return true; return true;
if (this.declarations.length === 0) if (this.declarations.length === 0) return dev;
return dev;
return this.selectors.some((s) => s.used); return this.selectors.some((s) => s.used);
} }
@ -117,7 +116,9 @@ class Rule {
if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node)) if (this.parent && this.parent.node.type === 'Atrule' && is_keyframes_node(this.parent.node))
return true; return true;
const attr = `.${id}`; const attr = `.${id}`;
this.selectors.forEach((selector) => selector.transform(code, attr, max_amount_class_specificity_increased)); this.selectors.forEach((selector) =>
selector.transform(code, attr, max_amount_class_specificity_increased)
);
this.declarations.forEach((declaration) => declaration.transform(code, keyframes)); this.declarations.forEach((declaration) => declaration.transform(code, keyframes));
} }
@ -131,16 +132,16 @@ class Rule {
/** @param {(selector: import('./Selector.js').default) => void} handler */ /** @param {(selector: import('./Selector.js').default) => void} handler */
warn_on_unused_selector(handler) { warn_on_unused_selector(handler) {
this.selectors.forEach((selector) => { this.selectors.forEach((selector) => {
if (!selector.used) if (!selector.used) handler(selector);
handler(selector);
}); });
} }
get_max_amount_class_specificity_increased() { get_max_amount_class_specificity_increased() {
return Math.max(...this.selectors.map((selector) => selector.get_amount_class_specificity_increased())); return Math.max(
...this.selectors.map((selector) => selector.get_amount_class_specificity_increased())
);
} }
} }
class Declaration { class Declaration {
/** @type {import('./private.js').CssNode} */ /** @type {import('./private.js').CssNode} */
node; node;
@ -169,24 +170,20 @@ class Declaration {
/** @param {import('magic-string').default} code */ /** @param {import('magic-string').default} code */
minify(code) { minify(code) {
if (!this.node.property) if (!this.node.property) return; // @apply, and possibly other weird cases?
return; // @apply, and possibly other weird cases?
const c = this.node.start + this.node.property.length; const c = this.node.start + this.node.property.length;
const first = this.node.value.children ? this.node.value.children[0] : this.node.value; const first = this.node.value.children ? this.node.value.children[0] : this.node.value;
// Don't minify whitespace in custom properties, since some browsers (Chromium < 99) // Don't minify whitespace in custom properties, since some browsers (Chromium < 99)
// treat --foo: ; and --foo:; differently // treat --foo: ; and --foo:; differently
if (first.type === 'Raw' && regex_only_whitespaces.test(first.value)) if (first.type === 'Raw' && regex_only_whitespaces.test(first.value)) return;
return;
let start = first.start; let start = first.start;
while (regex_whitespace.test(code.original[start])) while (regex_whitespace.test(code.original[start])) start += 1;
start += 1;
if (start - c > 1) { if (start - c > 1) {
code.update(c, start, ':'); code.update(c, start, ':');
} }
} }
} }
class Atrule { class Atrule {
/** @type {import('./private.js').CssNode} */ /** @type {import('./private.js').CssNode} */
node; node;
@ -205,15 +202,16 @@ class Atrule {
/** @param {import('../nodes/Element.js').default} node */ /** @param {import('../nodes/Element.js').default} node */
apply(node) { apply(node) {
if (this.node.name === 'container' || if (
this.node.name === 'container' ||
this.node.name === 'media' || this.node.name === 'media' ||
this.node.name === 'supports' || this.node.name === 'supports' ||
this.node.name === 'layer') { this.node.name === 'layer'
) {
this.children.forEach((child) => { this.children.forEach((child) => {
child.apply(node); child.apply(node);
}); });
} } else if (is_keyframes_node(this.node)) {
else if (is_keyframes_node(this.node)) {
this.children.forEach((rule) => { this.children.forEach((rule) => {
rule.selectors.forEach((selector) => { rule.selectors.forEach((selector) => {
selector.used = true; selector.used = true;
@ -235,29 +233,24 @@ class Atrule {
if (this.node.name === 'media') { if (this.node.name === 'media') {
const expression_char = code.original[this.node.prelude.start]; const expression_char = code.original[this.node.prelude.start];
let c = this.node.start + (expression_char === '(' ? 6 : 7); let c = this.node.start + (expression_char === '(' ? 6 : 7);
if (this.node.prelude.start > c) if (this.node.prelude.start > c) code.remove(c, this.node.prelude.start);
code.remove(c, this.node.prelude.start);
this.node.prelude.children.forEach((query) => { this.node.prelude.children.forEach((query) => {
// TODO minify queries // TODO minify queries
c = query.end; c = query.end;
}); });
code.remove(c, this.node.block.start); code.remove(c, this.node.block.start);
} } else if (this.node.name === 'supports') {
else if (this.node.name === 'supports') {
let c = this.node.start + 9; let c = this.node.start + 9;
if (this.node.prelude.start - c > 1) if (this.node.prelude.start - c > 1) code.update(c, this.node.prelude.start, ' ');
code.update(c, this.node.prelude.start, ' ');
this.node.prelude.children.forEach((query) => { this.node.prelude.children.forEach((query) => {
// TODO minify queries // TODO minify queries
c = query.end; c = query.end;
}); });
code.remove(c, this.node.block.start); code.remove(c, this.node.block.start);
} } else {
else {
let c = this.node.start + this.node.name.length + 1; let c = this.node.start + this.node.name.length + 1;
if (this.node.prelude) { if (this.node.prelude) {
if (this.node.prelude.start - c > 1) if (this.node.prelude.start - c > 1) code.update(c, this.node.prelude.start, ' ');
code.update(c, this.node.prelude.start, ' ');
c = this.node.prelude.end; c = this.node.prelude.end;
} }
if (this.node.block && this.node.block.start - c > 0) { if (this.node.block && this.node.block.start - c > 0) {
@ -270,8 +263,7 @@ class Atrule {
if (this.declarations.length) { if (this.declarations.length) {
c = minify_declarations(code, c, this.declarations); c = minify_declarations(code, c, this.declarations);
// if the atrule has children, leave the last declaration semicolon alone // if the atrule has children, leave the last declaration semicolon alone
if (this.children.length) if (this.children.length) c++;
c++;
} }
this.children.forEach((child) => { this.children.forEach((child) => {
if (child.is_used(dev)) { if (child.is_used(dev)) {
@ -301,8 +293,7 @@ class Atrule {
selector.used = true; selector.used = true;
}); });
}); });
} } else {
else {
code.update(start, end, keyframes.get(name)); code.update(start, end, keyframes.get(name));
} }
} }
@ -322,14 +313,15 @@ class Atrule {
/** @param {(selector: import('./Selector.js').default) => void} handler */ /** @param {(selector: import('./Selector.js').default) => void} handler */
warn_on_unused_selector(handler) { warn_on_unused_selector(handler) {
if (this.node.name !== 'media') if (this.node.name !== 'media') return;
return;
this.children.forEach((child) => { this.children.forEach((child) => {
child.warn_on_unused_selector(handler); child.warn_on_unused_selector(handler);
}); });
} }
get_max_amount_class_specificity_increased() { get_max_amount_class_specificity_increased() {
return Math.max(...this.children.map((rule) => rule.get_max_amount_class_specificity_increased())); return Math.max(
...this.children.map((rule) => rule.get_max_amount_class_specificity_increased())
);
} }
} }
@ -338,7 +330,6 @@ const get_default_css_hash = ({ css, hash }) => {
return `svelte-${hash(css)}`; return `svelte-${hash(css)}`;
}; };
export default class Stylesheet { export default class Stylesheet {
/** @type {string} */ /** @type {string} */
source; source;
@ -402,8 +393,7 @@ export default class Stylesheet {
stack.push(atrule); stack.push(atrule);
if (current_atrule) { if (current_atrule) {
current_atrule.children.push(atrule); current_atrule.children.push(atrule);
} } else if (depth <= 1) {
else if (depth <= 1) {
this.children.push(atrule); this.children.push(atrule);
} }
if (is_keyframes_node(node)) { if (is_keyframes_node(node)) {
@ -412,8 +402,7 @@ export default class Stylesheet {
this.keyframes.set(expression.name, `${this.id}-${expression.name}`); this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
} }
}); });
} } else if (at_rule_has_declaration(node)) {
else if (at_rule_has_declaration(node)) {
const at_rule_declarations = node.block.children const at_rule_declarations = node.block.children
.filter((node) => node.type === 'Declaration') .filter((node) => node.type === 'Declaration')
.map((node) => new Declaration(node)); .map((node) => new Declaration(node));
@ -425,8 +414,7 @@ export default class Stylesheet {
const rule = new Rule(node, this, current_atrule); const rule = new Rule(node, this, current_atrule);
if (current_atrule) { if (current_atrule) {
current_atrule.children.push(rule); current_atrule.children.push(rule);
} } else if (depth <= 1) {
else if (depth <= 1) {
this.children.push(rule); this.children.push(rule);
} }
} }
@ -440,16 +428,14 @@ export default class Stylesheet {
depth -= 1; depth -= 1;
} }
}); });
} } else {
else {
this.has_styles = false; this.has_styles = false;
} }
} }
/** @param {import('../nodes/Element.js').default} node */ /** @param {import('../nodes/Element.js').default} node */
apply(node) { apply(node) {
if (!this.has_styles) if (!this.has_styles) return;
return;
for (let i = 0; i < this.children.length; i += 1) { for (let i = 0; i < this.children.length; i += 1) {
const child = this.children[i]; const child = this.children[i];
child.apply(node); child.apply(node);
@ -473,7 +459,9 @@ export default class Stylesheet {
code.addSourcemapLocation(node.end); code.addSourcemapLocation(node.end);
} }
}); });
const max = Math.max(...this.children.map((rule) => rule.get_max_amount_class_specificity_increased())); const max = Math.max(
...this.children.map((rule) => rule.get_max_amount_class_specificity_increased())
);
this.children.forEach((child) => { this.children.forEach((child) => {
child.transform(code, this.id, this.keyframes, max); child.transform(code, this.id, this.keyframes, max);
}); });
@ -511,13 +499,14 @@ export default class Stylesheet {
component.push_ignores(ignores); component.push_ignores(ignores);
this.children.forEach((child) => { this.children.forEach((child) => {
child.warn_on_unused_selector((selector) => { child.warn_on_unused_selector((selector) => {
component.warn(selector.node, compiler_warnings.css_unused_selector(this.source.slice(selector.node.start, selector.node.end))); component.warn(
selector.node,
compiler_warnings.css_unused_selector(
this.source.slice(selector.node.start, selector.node.end)
)
);
}); });
}); });
component.pop_ignores(); component.pop_ignores();
} }
} }

Loading…
Cancel
Save