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