You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/src/generators/shared/processCss.ts

97 lines
2.8 KiB

import { Parsed, Node } from '../../interfaces';
const commentsPattern = /\/\*[\s\S]*?\*\//g;
export default function processCss ( parsed: Parsed, code ) {
const css = parsed.css.content.styles;
const offset = parsed.css.content.start;
const attr = `[svelte-${parsed.hash}]`;
const keyframes = new Map();
function walkKeyframes ( node: Node ) {
if ( node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes' ) {
node.expression.children.forEach( ( expression: Node ) => {
if ( expression.type === 'Identifier' ) {
const newName = `svelte-${parsed.hash}-${expression.name}`;
code.overwrite( expression.start, expression.end, newName );
keyframes.set( expression.name, newName );
}
});
} else if ( node.children ) {
node.children.forEach( walkKeyframes );
} else if ( node.block ) {
walkKeyframes( node.block );
}
}
parsed.css.children.forEach( walkKeyframes );
function transform ( rule: Node ) {
rule.selector.children.forEach( ( selector: Node ) => {
const start = selector.start - offset;
const end = selector.end - offset;
const selectorString = css.slice( start, end );
const firstToken = selector.children[0];
let transformed;
if ( firstToken.type === 'TypeSelector' ) {
const insert = firstToken.end - offset;
const head = css.slice( start, insert );
const tail = css.slice( insert, end );
transformed = `${head}${attr}${tail}, ${attr} ${selectorString}`;
} else {
transformed = `${attr}${selectorString}, ${attr} ${selectorString}`;
}
code.overwrite( start + offset, end + offset, transformed );
});
rule.block.children.forEach( ( block: Node ) => {
if ( block.type === 'Declaration' ) {
const property = block.property.toLowerCase();
if ( property === 'animation' || property === 'animation-name' ) {
block.value.children.forEach( ( block: Node ) => {
if ( block.type === 'Identifier' ) {
const name = block.name;
if ( keyframes.has( name ) ) {
code.overwrite( block.start, block.end, keyframes.get( name ) );
}
}
});
}
}
});
}
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 );
// remove comments. TODO would be nice if this was exposed in css-tree
let match;
while ( match = commentsPattern.exec( css ) ) {
const start = match.index + offset;
const end = start + match[0].length;
code.remove( start, end );
}
return code.slice( parsed.css.content.start, parsed.css.content.end );
}