handle :global(...) styles

pull/689/head
Rich Harris 7 years ago
parent ab40007406
commit f97ac27e2a

@ -26,7 +26,7 @@ export default function extractSelectors(css: Node) :Node[] {
function processSelector(selector: Node) {
selectors.push({
used: false,
used: false, // TODO use this! warn on unused selectors
apply: (node: Node, stack: Node[]) => {
const applies = selectorAppliesTo(selector.children, node, stack.slice());
@ -52,9 +52,15 @@ function selectorAppliesTo(parts: Node[], node: Node, stack: Node[]) {
let j = stack.length;
while (i--) {
if (!node) return;
const part = parts[i];
if (part.type === 'PseudoClassSelector' && part.name === 'global') {
// bail
return true;
}
if (!node) return false;
if (part.type === 'PseudoClassSelector' || part.type === 'PseudoElementSelector') {
continue;
}

@ -37,6 +37,29 @@ export default function processCss(
parsed.css.children.forEach(walkKeyframes);
function transformBlock(block: Node[]) {
let i = block.length;
while (i--) {
const child = block[i];
if (child.type === 'PseudoElementSelector') continue;
if (child.type === 'PseudoClassSelector') {
if (child.name === 'global') {
const first = child.children[0];
const last = child.children[child.children.length - 1];
code.remove(child.start, first.start).remove(last.end, child.end);
return;
} else {
continue;
}
}
code.appendLeft(child.end, attr);
return;
}
}
function transform(rule: Node) {
rule.selector.children.forEach((selector: Node) => {
if (cascade) {
@ -65,37 +88,22 @@ export default function processCss(
let shouldTransform = true;
let c = selector.start;
// separate .foo > .bar > .baz into three separate blocks, so
// that we can transform only the first and last
let block: Node[] = [];
const blocks: Node[][] = [block];
selector.children.forEach((child: Node) => {
if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
code.appendLeft(c, attr);
shouldTransform = true;
return;
}
if (!shouldTransform) return;
if (child.type === 'PseudoClassSelector') {
// `:global(xyz)` > xyz
if (child.name === 'global') {
const first = child.children[0];
const last = child.children[child.children.length - 1];
code.remove(child.start, first.start).remove(last.end, child.end);
} else {
code.prependRight(c, attr);
}
shouldTransform = false;
} else if (child.type === 'PseudoElementSelector') {
code.prependRight(c, attr);
shouldTransform = false;
block = [];
blocks.push(block);
} else {
block.push(child);
}
c = child.end;
});
if (shouldTransform) {
code.appendLeft(c, attr);
}
transformBlock(blocks[0]);
if (blocks.length > 1) transformBlock(blocks[blocks.length - 1]);
}
});

@ -46,7 +46,7 @@ describe("css", () => {
const Component = eval(`(function () { ${actual.code}; return SvelteComponent; }())`);
const target = window.document.querySelector("main");
new Component({ target });
new Component({ target, data: config.data });
const html = target.innerHTML;
fs.writeFileSync(`test/css/samples/${dir}/_actual.html`, html);

@ -0,0 +1,7 @@
export default {
cascade: false,
data: {
raw: '<p>raw</p>'
}
};

@ -0,0 +1,9 @@
<div>
<!-- html injected somehow -->
</div>
<style>
div > :global(p) {
color: red;
}
</style>

@ -0,0 +1,7 @@
export default {
cascade: false,
data: {
raw: '<p>raw</p>'
}
};

@ -0,0 +1 @@
<p svelte-794545435="">this may or may not be styled</p>

@ -0,0 +1,7 @@
<p>this may or may not be styled</p>
<style>
:global(div) > p {
color: red;
}
</style>

@ -0,0 +1,4 @@
div[svelte-4032668709] section p[svelte-4032668709] {
color: red;
}

@ -0,0 +1 @@
<div svelte-4032668709=""><section><p svelte-4032668709="">this is styled</p></section></div>

@ -0,0 +1,11 @@
<div>
<section>
<p>this is styled</p>
</section>
</div>
<style>
div section p {
color: red;
}
</style>
Loading…
Cancel
Save