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