From 94cd2eeb1ac80307327be318ae77c9d855d7c8df Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 1 Jul 2017 13:00:47 -0400 Subject: [PATCH] create reusable walkRules helper --- src/generators/extractSelectors.ts | 23 +++++------------------ src/generators/shared/processCss.ts | 19 ++----------------- src/utils/css.ts | 12 ++++++++++++ src/validate/css/index.ts | 22 ++++------------------ 4 files changed, 23 insertions(+), 53 deletions(-) diff --git a/src/generators/extractSelectors.ts b/src/generators/extractSelectors.ts index 782d752671..86222438b3 100644 --- a/src/generators/extractSelectors.ts +++ b/src/generators/extractSelectors.ts @@ -1,3 +1,4 @@ +import { walkRules } from '../utils/css'; import { Node } from '../interfaces'; export default function extractSelectors(css: Node) :Node[] { @@ -5,21 +6,9 @@ export default function extractSelectors(css: Node) :Node[] { const selectors = []; - function processRule(rule: Node) { - if (rule.type === 'Atrule') { - if (rule.name === 'keyframes') return; - if (rule.name == 'media') { - rule.block.children.forEach(processRule); - return; - } - - // TODO - throw new Error(`Not implemented: @${rule.name}. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!`); - } - - const selectors = rule.selector.children; - selectors.forEach(processSelector); - } + walkRules(css.children, node => { + node.selector.children.forEach(processSelector); + }); function processSelector(selector: Node) { // take trailing :global(...) selectors out of consideration @@ -50,8 +39,6 @@ export default function extractSelectors(css: Node) :Node[] { }); } - css.children.forEach(processRule); - return selectors; } @@ -59,7 +46,7 @@ function isDescendantSelector(selector: Node) { return selector.type === 'WhiteSpace'; // TODO or '>' } -function selectorAppliesTo(parts: Node[], node: Node, stack: Node[]) { +function selectorAppliesTo(parts: Node[], node: Node, stack: Node[]): boolean { let i = parts.length; let j = stack.length; diff --git a/src/generators/shared/processCss.ts b/src/generators/shared/processCss.ts index 00e564862a..77c1d4a420 100644 --- a/src/generators/shared/processCss.ts +++ b/src/generators/shared/processCss.ts @@ -1,5 +1,5 @@ import MagicString from 'magic-string'; -import { groupSelectors, isGlobalSelector } from '../../utils/css'; +import { groupSelectors, isGlobalSelector, walkRules } from '../../utils/css'; import { Parsed, Node } from '../../interfaces'; const commentsPattern = /\/\*[\s\S]*?\*\//g; @@ -114,22 +114,7 @@ export default function processCss( }); } - function walk(node: Node) { - if (node.type === 'Rule') { - transform(node); - } else if ( - node.type === 'Atrule' && - node.name.toLowerCase() === 'keyframes' - ) { - // these have already been processed - } else if (node.children) { - node.children.forEach(walk); - } else if (node.block) { - walk(node.block); - } - } - - parsed.css.children.forEach(walk); + walkRules(parsed.css.children, transform); // remove comments. TODO would be nice if this was exposed in css-tree let match; diff --git a/src/utils/css.ts b/src/utils/css.ts index 31a6a26876..ac78bdd96a 100644 --- a/src/utils/css.ts +++ b/src/utils/css.ts @@ -18,4 +18,16 @@ export function groupSelectors(selector: Node) { }); return blocks; +} + +export function walkRules(nodes: Node[], callback: (node: Node) => void) { + nodes.forEach((node: Node) => { + if (node.type === 'Rule') { + callback(node); + } else if (node.type === 'Atrule') { + if (node.name === 'media' || node.name === 'supports' || node.name === 'document') { + walkRules(node.block.children, callback); + } + } + }); } \ No newline at end of file diff --git a/src/validate/css/index.ts b/src/validate/css/index.ts index b2f26e78d0..6251f59fb0 100644 --- a/src/validate/css/index.ts +++ b/src/validate/css/index.ts @@ -1,23 +1,11 @@ -import { groupSelectors, isGlobalSelector } from '../../utils/css'; +import { groupSelectors, isGlobalSelector, walkRules } from '../../utils/css'; import { Validator } from '../index'; import { Node } from '../../interfaces'; export default function validateCss(validator: Validator, css: Node) { - function validateRule(rule: Node) { - if (rule.type === 'Atrule') { - if (rule.name === 'keyframes') return; - if (rule.name == 'media') { - rule.block.children.forEach(validateRule); - return; - } - - // TODO - throw new Error(`Not implemented: @${rule.name}. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!`); - } - - const selectors = rule.selector.children; - selectors.forEach(validateSelector); - } + walkRules(css.children, rule => { + rule.selector.children.forEach(validateSelector); + }); function validateSelector(selector: Node) { const blocks: Node[][] = groupSelectors(selector); @@ -53,6 +41,4 @@ export default function validateCss(validator: Validator, css: Node) { } } } - - css.children.forEach(validateRule); } \ No newline at end of file