mirror of https://github.com/sveltejs/svelte
parent
d9aa3ec5ae
commit
5499327a70
@ -0,0 +1,21 @@
|
||||
import { Node } from '../interfaces';
|
||||
|
||||
export function isGlobalSelector(block: Node[]) {
|
||||
return block.length === 1 && block[0].type === 'PseudoClassSelector' && block[0].name === 'global';
|
||||
}
|
||||
|
||||
export function groupSelectors(selector: Node) {
|
||||
let block: Node[] = [];
|
||||
const blocks: Node[][] = [block];
|
||||
|
||||
selector.children.forEach((child: Node) => {
|
||||
if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
|
||||
block = [];
|
||||
blocks.push(block);
|
||||
} else {
|
||||
block.push(child);
|
||||
}
|
||||
});
|
||||
|
||||
return blocks;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
import { groupSelectors, isGlobalSelector } 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);
|
||||
}
|
||||
|
||||
function validateSelector(selector: Node) {
|
||||
const blocks: Node[][] = groupSelectors(selector);
|
||||
|
||||
blocks.forEach((block, i) => {
|
||||
if (block.find((part: Node) => part.type === 'PseudoClassSelector' && part.name === 'global')) {
|
||||
// check that :global(...) is by itself
|
||||
if (block.length !== 1) {
|
||||
validator.error(`:global(...) cannot be mixed with non-global selectors`, block[0].start);
|
||||
}
|
||||
|
||||
// check that :global(...) isn't sandwiched by other selectors
|
||||
// if (i > 0 && i < blocks.length - 1) {
|
||||
// validator.error(`:global(...) can be at the start or end of a selector sequence, but not in the middle`, block[0].start);
|
||||
// }
|
||||
}
|
||||
});
|
||||
|
||||
let start = 0;
|
||||
let end = blocks.length;
|
||||
|
||||
for (; start < end; start += 1) {
|
||||
if (!isGlobalSelector(blocks[start])) break;
|
||||
}
|
||||
|
||||
for (; end > start; end -= 1) {
|
||||
if (!isGlobalSelector(blocks[end - 1])) break;
|
||||
}
|
||||
|
||||
for (let i = start; i < end; i += 1) {
|
||||
if (isGlobalSelector(blocks[i])) {
|
||||
validator.error(`:global(...) can be at the start or end of a selector sequence, but not in the middle`, blocks[i][0].start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
css.children.forEach(validateRule);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
|
||||
div[svelte-3386191472] > p > em {
|
||||
color: red;
|
||||
}
|
@ -0,0 +1 @@
|
||||
<div svelte-3386191472=""></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 > section > p[svelte-3390623146] {
|
||||
color: red;
|
||||
}
|
@ -0,0 +1 @@
|
||||
<p svelte-3390623146="">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,8 @@
|
||||
[{
|
||||
"message": ":global(...) can be at the start or end of a selector sequence, but not in the middle",
|
||||
"loc": {
|
||||
"line": 2,
|
||||
"column": 6
|
||||
},
|
||||
"pos": 14
|
||||
}]
|
@ -0,0 +1,5 @@
|
||||
<style>
|
||||
.foo :global(.bar) .baz {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,8 @@
|
||||
[{
|
||||
"message": ":global(...) cannot be mixed with non-global selectors",
|
||||
"loc": {
|
||||
"line": 2,
|
||||
"column": 1
|
||||
},
|
||||
"pos": 9
|
||||
}]
|
@ -0,0 +1,5 @@
|
||||
<style>
|
||||
:global(.foo).bar {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
Loading…
Reference in new issue