mirror of https://github.com/sveltejs/svelte
Merge pull request #680 from sveltejs/gh-679
Only apply svelte-123xyz attributes where necessarypull/690/head
commit
ef33466c12
@ -0,0 +1,180 @@
|
|||||||
|
import MagicString from 'magic-string';
|
||||||
|
import { groupSelectors, isGlobalSelector, walkRules } from '../utils/css';
|
||||||
|
import { Node } from '../interfaces';
|
||||||
|
|
||||||
|
export default class Selector {
|
||||||
|
node: Node;
|
||||||
|
blocks: any; // TODO
|
||||||
|
parts: Node[];
|
||||||
|
used: boolean;
|
||||||
|
|
||||||
|
constructor(node: Node) {
|
||||||
|
this.node = node;
|
||||||
|
|
||||||
|
this.blocks = groupSelectors(this.node);
|
||||||
|
|
||||||
|
// take trailing :global(...) selectors out of consideration
|
||||||
|
let i = node.children.length;
|
||||||
|
while (i > 2) {
|
||||||
|
const last = node.children[i-1];
|
||||||
|
const penultimate = node.children[i-2];
|
||||||
|
|
||||||
|
if (last.type === 'PseudoClassSelector' && last.name === 'global') {
|
||||||
|
i -= 2;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parts = node.children.slice(0, i);
|
||||||
|
|
||||||
|
this.used = this.blocks[0].global;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(node: Node, stack: Node[]) {
|
||||||
|
const applies = selectorAppliesTo(this.parts, node, stack.slice());
|
||||||
|
|
||||||
|
if (applies) {
|
||||||
|
this.used = true;
|
||||||
|
|
||||||
|
// add svelte-123xyz attribute to outermost and innermost
|
||||||
|
// elements — no need to add it to intermediate elements
|
||||||
|
node._needsCssAttribute = true;
|
||||||
|
if (stack[0] && this.node.children.find(isDescendantSelector)) stack[0]._needsCssAttribute = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(code: MagicString, attr: string) {
|
||||||
|
function encapsulateBlock(block) {
|
||||||
|
let i = block.selectors.length;
|
||||||
|
while (i--) {
|
||||||
|
const selector = block.selectors[i];
|
||||||
|
if (selector.type === 'PseudoElementSelector' || selector.type === 'PseudoClassSelector') continue;
|
||||||
|
|
||||||
|
if (selector.type === 'TypeSelector' && selector.name === '*') {
|
||||||
|
code.overwrite(selector.start, selector.end, attr);
|
||||||
|
} else {
|
||||||
|
code.appendLeft(selector.end, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.blocks.forEach((block, i) => {
|
||||||
|
if (block.global) {
|
||||||
|
const selector = block.selectors[0];
|
||||||
|
const first = selector.children[0];
|
||||||
|
const last = selector.children[selector.children.length - 1];
|
||||||
|
code.remove(selector.start, first.start).remove(last.end, selector.end);
|
||||||
|
} else if (i === 0 || i === this.blocks.length - 1) {
|
||||||
|
encapsulateBlock(block);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDescendantSelector(selector: Node) {
|
||||||
|
return selector.type === 'WhiteSpace' || selector.type === 'Combinator';
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectorAppliesTo(parts: Node[], node: Node, stack: Node[]): boolean {
|
||||||
|
let i = parts.length;
|
||||||
|
let j = stack.length;
|
||||||
|
|
||||||
|
while (i--) {
|
||||||
|
if (!node) {
|
||||||
|
return parts.every((part: Node) => {
|
||||||
|
return part.type === 'Combinator' || (part.type === 'PseudoClassSelector' && part.name === 'global');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const part = parts[i];
|
||||||
|
|
||||||
|
if (part.type === 'PseudoClassSelector' && part.name === 'global') {
|
||||||
|
// TODO shouldn't see this here... maybe we should enforce that :global(...)
|
||||||
|
// cannot be sandwiched between non-global selectors?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.type === 'PseudoClassSelector' || part.type === 'PseudoElementSelector') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.type === 'ClassSelector') {
|
||||||
|
if (!attributeMatches(node, 'class', part.name, '~=', false)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (part.type === 'IdSelector') {
|
||||||
|
if (!attributeMatches(node, 'id', part.name, '=', false)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (part.type === 'AttributeSelector') {
|
||||||
|
if (!attributeMatches(node, part.name.name, part.value && unquote(part.value.value), part.operator, part.flags)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (part.type === 'TypeSelector') {
|
||||||
|
if (part.name === '*') return true;
|
||||||
|
if (node.name !== part.name) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (part.type === 'WhiteSpace') {
|
||||||
|
parts = parts.slice(0, i);
|
||||||
|
|
||||||
|
while (stack.length) {
|
||||||
|
if (selectorAppliesTo(parts, stack.pop(), stack)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (part.type === 'Combinator') {
|
||||||
|
if (part.name === '>') {
|
||||||
|
return selectorAppliesTo(parts.slice(0, i), stack.pop(), stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO other combinators
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
// bail. TODO figure out what these could be
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const operators = {
|
||||||
|
'=' : (value: string, flags: string) => new RegExp(`^${value}$`, flags),
|
||||||
|
'~=': (value: string, flags: string) => new RegExp(`\\b${value}\\b`, flags),
|
||||||
|
'|=': (value: string, flags: string) => new RegExp(`^${value}(-.+)?$`, flags),
|
||||||
|
'^=': (value: string, flags: string) => new RegExp(`^${value}`, flags),
|
||||||
|
'$=': (value: string, flags: string) => new RegExp(`${value}$`, flags),
|
||||||
|
'*=': (value: string, flags: string) => new RegExp(value, flags)
|
||||||
|
};
|
||||||
|
|
||||||
|
function attributeMatches(node: Node, name: string, expectedValue: string, operator: string, caseInsensitive: boolean) {
|
||||||
|
const attr = node.attributes.find((attr: Node) => attr.name === name);
|
||||||
|
if (!attr) return false;
|
||||||
|
if (attr.value === true) return operator === null;
|
||||||
|
if (isDynamic(attr.value)) return true;
|
||||||
|
|
||||||
|
const actualValue = attr.value[0].data;
|
||||||
|
|
||||||
|
const pattern = operators[operator](expectedValue, caseInsensitive ? 'i' : '');
|
||||||
|
return pattern.test(actualValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDynamic(value: Node) {
|
||||||
|
return value.length > 1 || value[0].type !== 'Text';
|
||||||
|
}
|
||||||
|
|
||||||
|
function unquote(str: string) {
|
||||||
|
if (str[0] === str[str.length - 1] && str[0] === "'" || str[0] === '"') {
|
||||||
|
return str.slice(1, str.length - 1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
import { SsrGenerator } from './index';
|
||||||
|
import { Node } from '../../interfaces';
|
||||||
|
|
||||||
|
function noop () {}
|
||||||
|
|
||||||
|
function isElseIf(node: Node) {
|
||||||
|
return (
|
||||||
|
node && node.children.length === 1 && node.children[0].type === 'IfBlock'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const preprocessors = {
|
||||||
|
MustacheTag: noop,
|
||||||
|
RawMustacheTag: noop,
|
||||||
|
Text: noop,
|
||||||
|
|
||||||
|
IfBlock: (
|
||||||
|
generator: SsrGenerator,
|
||||||
|
node: Node,
|
||||||
|
elementStack: Node[]
|
||||||
|
) => {
|
||||||
|
function attachBlocks(node: Node) {
|
||||||
|
preprocessChildren(generator, node, elementStack);
|
||||||
|
|
||||||
|
if (isElseIf(node.else)) {
|
||||||
|
attachBlocks(node.else.children[0]);
|
||||||
|
} else if (node.else) {
|
||||||
|
preprocessChildren(
|
||||||
|
generator,
|
||||||
|
node.else,
|
||||||
|
elementStack
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attachBlocks(node);
|
||||||
|
},
|
||||||
|
|
||||||
|
EachBlock: (
|
||||||
|
generator: SsrGenerator,
|
||||||
|
node: Node,
|
||||||
|
elementStack: Node[]
|
||||||
|
) => {
|
||||||
|
preprocessChildren(generator, node, elementStack);
|
||||||
|
|
||||||
|
if (node.else) {
|
||||||
|
preprocessChildren(
|
||||||
|
generator,
|
||||||
|
node.else,
|
||||||
|
elementStack
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Element: (
|
||||||
|
generator: SsrGenerator,
|
||||||
|
node: Node,
|
||||||
|
elementStack: Node[]
|
||||||
|
) => {
|
||||||
|
const isComponent =
|
||||||
|
generator.components.has(node.name) || node.name === ':Self';
|
||||||
|
|
||||||
|
if (!isComponent) {
|
||||||
|
generator.applyCss(node, elementStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.children.length) {
|
||||||
|
if (isComponent) {
|
||||||
|
preprocessChildren(generator, node, elementStack);
|
||||||
|
} else {
|
||||||
|
preprocessChildren(generator, node, elementStack.concat(node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function preprocessChildren(
|
||||||
|
generator: SsrGenerator,
|
||||||
|
node: Node,
|
||||||
|
elementStack: Node[]
|
||||||
|
) {
|
||||||
|
node.children.forEach((child: Node, i: number) => {
|
||||||
|
const preprocessor = preprocessors[child.type];
|
||||||
|
if (preprocessor) preprocessor(generator, child, elementStack);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function preprocess(generator: SsrGenerator, html: Node) {
|
||||||
|
preprocessChildren(generator, html, []);
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
import { Node } from '../interfaces';
|
||||||
|
|
||||||
|
export function isGlobalSelector(block: Node[]) {
|
||||||
|
return block[0].type === 'PseudoClassSelector' && block[0].name === 'global';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function groupSelectors(selector: Node) {
|
||||||
|
let block = {
|
||||||
|
global: selector.children[0].type === 'PseudoClassSelector' && selector.children[0].name === 'global',
|
||||||
|
selectors: [],
|
||||||
|
combinator: null
|
||||||
|
};
|
||||||
|
|
||||||
|
const blocks = [block];
|
||||||
|
|
||||||
|
selector.children.forEach((child: Node, i: number) => {
|
||||||
|
if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
|
||||||
|
const next = selector.children[i + 1];
|
||||||
|
|
||||||
|
block = {
|
||||||
|
global: next.type === 'PseudoClassSelector' && next.name === 'global',
|
||||||
|
selectors: [],
|
||||||
|
combinator: child
|
||||||
|
};
|
||||||
|
|
||||||
|
blocks.push(block);
|
||||||
|
} else {
|
||||||
|
block.selectors.push(child);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
import { groupSelectors, isGlobalSelector, walkRules } from '../../utils/css';
|
||||||
|
import { Validator } from '../index';
|
||||||
|
import { Node } from '../../interfaces';
|
||||||
|
|
||||||
|
export default function validateCss(validator: Validator, css: Node) {
|
||||||
|
walkRules(css.children, rule => {
|
||||||
|
rule.selector.children.forEach(validateSelector);
|
||||||
|
});
|
||||||
|
|
||||||
|
function validateSelector(selector: Node) {
|
||||||
|
const blocks = groupSelectors(selector);
|
||||||
|
|
||||||
|
blocks.forEach((block) => {
|
||||||
|
let i = block.selectors.length;
|
||||||
|
while (i-- > 1) {
|
||||||
|
const part = block.selectors[i];
|
||||||
|
if (part.type === 'PseudoClassSelector' && part.name === 'global') {
|
||||||
|
validator.error(`:global(...) must be the first element in a compound selector`, part.start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let start = 0;
|
||||||
|
let end = blocks.length;
|
||||||
|
|
||||||
|
for (; start < end; start += 1) {
|
||||||
|
if (!blocks[start].global) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; end > start; end -= 1) {
|
||||||
|
if (!blocks[end - 1].global) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = start; i < end; i += 1) {
|
||||||
|
if (blocks[i].global) {
|
||||||
|
validator.error(`:global(...) can be at the start or end of a selector sequence, but not in the middle`, blocks[i].selectors[0].start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
div[svelte-2278551596], [svelte-2278551596] div {
|
div[svelte-xyz], [svelte-xyz] div {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
|
|
||||||
@keyframes svelte-1647166666-why {
|
@keyframes svelte-xyz-why {
|
||||||
0% { color: red; }
|
0% { color: red; }
|
||||||
100% { color: blue; }
|
100% { color: blue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.animated[svelte-1647166666] {
|
.animated[svelte-xyz] {
|
||||||
animation: svelte-1647166666-why 2s;
|
animation: svelte-xyz-why 2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.also-animated[svelte-1647166666] {
|
.also-animated[svelte-xyz] {
|
||||||
animation: not-defined-here 2s;
|
animation: not-defined-here 2s;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
span[svelte-2146001331]::after {
|
span[svelte-xyz]::after {
|
||||||
content: 'i am a pseudo-element';
|
content: 'i am a pseudo-element';
|
||||||
}
|
}
|
||||||
|
|
||||||
span[svelte-2146001331]:first-child {
|
span[svelte-xyz]:first-child {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
span[svelte-2146001331]:last-child::after {
|
span[svelte-xyz]:last-child::after {
|
||||||
color: blue;
|
color: blue;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<div svelte-xyz=""></div>
|
@ -0,0 +1,7 @@
|
|||||||
|
<div></div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
div[svelte-781920915] {
|
div[svelte-xyz] {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.foo[svelte-781920915] {
|
div.foo[svelte-xyz] {
|
||||||
color: blue;
|
color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.foo[svelte-781920915] {
|
.foo[svelte-xyz] {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
@keyframes svelte-2931302006-why {
|
@keyframes svelte-xyz-why {
|
||||||
0% { color: red; }
|
0% { color: red; }
|
||||||
100% { color: blue; }
|
100% { color: blue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[svelte-2931302006].animated, [svelte-2931302006] .animated {
|
[svelte-xyz].animated, [svelte-xyz] .animated {
|
||||||
animation: svelte-2931302006-why 2s;
|
animation: svelte-xyz-why 2s;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
@media (min-width: 400px) {
|
@media (min-width: 400px) {
|
||||||
[svelte-411199634].large-screen, [svelte-411199634] .large-screen {
|
[svelte-xyz].large-screen, [svelte-xyz] .large-screen {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo*='bar'][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><p svelte-xyz="" data-foo="foobarbaz">this is styled</p>
|
||||||
|
<p data-foo="fooBARbaz">this is unstyled</p></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='foobarbaz'>this is styled</p>
|
||||||
|
<p data-foo='fooBARbaz'>this is unstyled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo*='bar'] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo='bar' i][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><p svelte-xyz="" data-foo="BAR">this is styled</p>
|
||||||
|
<p data-foo="BAZ">this is unstyled</p></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='BAR'>this is styled</p>
|
||||||
|
<p data-foo='BAZ'>this is unstyled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo='bar' i] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false,
|
||||||
|
data: {
|
||||||
|
dynamic: 'whatever'
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo='bar'][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><p svelte-xyz="" data-foo="whatever">this is styled</p>
|
||||||
|
<p data-foo="baz">this is unstyled</p></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='{{dynamic}}'>this is styled</p>
|
||||||
|
<p data-foo='baz'>this is unstyled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo='bar'] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo='bar'][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><p svelte-xyz="" data-foo="bar">this is styled</p>
|
||||||
|
<p data-foo="baz">this is unstyled</p></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='bar'>this is styled</p>
|
||||||
|
<p data-foo='baz'>this is unstyled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo='bar'] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo|='bar'][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
<div><p svelte-xyz="" data-foo="bar">this is styled</p>
|
||||||
|
<p svelte-xyz="" data-foo="bar-baz">this is styled</p>
|
||||||
|
<p data-foo="baz-bar">this is unstyled</p></div>
|
@ -0,0 +1,11 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='bar'>this is styled</p>
|
||||||
|
<p data-foo='bar-baz'>this is styled</p>
|
||||||
|
<p data-foo='baz-bar'>this is unstyled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo|='bar'] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo^='bar'][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><p svelte-xyz="" data-foo="barbaz">this is styled</p>
|
||||||
|
<p data-foo="bazbar">this is unstyled</p></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='barbaz'>this is styled</p>
|
||||||
|
<p data-foo='bazbar'>this is unstyled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo^='bar'] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo$='bar'][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><p data-foo="barbaz">this is unstyled</p>
|
||||||
|
<p svelte-xyz="" data-foo="bazbar">this is styled</p></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='barbaz'>this is unstyled</p>
|
||||||
|
<p data-foo='bazbar'>this is styled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo$='bar'] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[data-foo~='bar'][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><p svelte-xyz="" data-foo="qux bar">this is styled</p>
|
||||||
|
<p data-foo="qux baz">this is unstyled</p></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<p data-foo='qux bar'>this is styled</p>
|
||||||
|
<p data-foo='qux baz'>this is unstyled</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[data-foo~='bar'] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
[autoplay][svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<div><video svelte-xyz autoplay></video>
|
||||||
|
<video></video></div>
|
@ -0,0 +1,10 @@
|
|||||||
|
<div>
|
||||||
|
<video autoplay></video>
|
||||||
|
<video></video>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[autoplay] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
.foo[svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<p svelte-xyz="" class="whatever">this is styled</p>
|
||||||
|
<p class="bar">this is unstyled</p>
|
@ -0,0 +1,18 @@
|
|||||||
|
<p class='{{unknown}}'>this is styled</p>
|
||||||
|
<p class='bar'>this is unstyled</p>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.foo {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
unknown: 'whatever'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
.foo[svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<p svelte-xyz="" class="foo">this is styled</p>
|
||||||
|
<p class="bar">this is unstyled</p>
|
@ -0,0 +1,8 @@
|
|||||||
|
<p class='foo'>this is styled</p>
|
||||||
|
<p class='bar'>this is unstyled</p>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.foo {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,7 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false,
|
||||||
|
|
||||||
|
data: {
|
||||||
|
raw: '<p>raw</p>'
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
.foo[svelte-xyz] .bar {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<div svelte-xyz="" class="foo"></div>
|
@ -0,0 +1,9 @@
|
|||||||
|
<div class='foo'>
|
||||||
|
<!-- html injected somehow -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.foo :global(.bar) {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,7 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false,
|
||||||
|
|
||||||
|
data: {
|
||||||
|
raw: '<p>raw</p>'
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
div[svelte-xyz] > p > em {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<div svelte-xyz=""></div>
|
@ -0,0 +1,9 @@
|
|||||||
|
<div>
|
||||||
|
<!-- html injected somehow -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div > :global(p) > :global(em) {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,7 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false,
|
||||||
|
|
||||||
|
data: {
|
||||||
|
raw: '<p>raw</p>'
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
div[svelte-xyz] > p {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<div svelte-xyz=""></div>
|
@ -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,4 @@
|
|||||||
|
|
||||||
|
div > section > p[svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<p svelte-xyz="">this may or may not be styled</p>
|
@ -0,0 +1,7 @@
|
|||||||
|
<p>this may or may not be styled</p>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global(div) > :global(section) > p {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,7 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false,
|
||||||
|
|
||||||
|
data: {
|
||||||
|
raw: '<p>raw</p>'
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
div > p[svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<p svelte-xyz="">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,19 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false,
|
||||||
|
|
||||||
|
warnings: [{
|
||||||
|
message: 'Unused CSS selector',
|
||||||
|
loc: {
|
||||||
|
line: 8,
|
||||||
|
column: 1
|
||||||
|
},
|
||||||
|
pos: 74,
|
||||||
|
frame: `
|
||||||
|
6:
|
||||||
|
7: <style>
|
||||||
|
8: div > p {
|
||||||
|
^
|
||||||
|
9: color: red;
|
||||||
|
10: }`
|
||||||
|
}]
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
div[svelte-xyz] > p[svelte-xyz] {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<div><section><p>this is not styled</p></section></div>
|
@ -0,0 +1,11 @@
|
|||||||
|
<div>
|
||||||
|
<section>
|
||||||
|
<p>this is not styled</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div > p {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,7 @@
|
|||||||
|
export default {
|
||||||
|
cascade: false,
|
||||||
|
|
||||||
|
data: {
|
||||||
|
raw: '<p>raw</p>'
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
div {
|
||||||
|
color: red;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue