mirror of
https://github.com/withastro/astro.git
synced 2025-01-13 22:11:20 -05:00
Fix scoping issues (#58)
This commit is contained in:
parent
aa333c2f29
commit
008ffc2951
6 changed files with 159 additions and 108 deletions
182
package-lock.json
generated
182
package-lock.json
generated
|
@ -479,13 +479,13 @@
|
|||
}
|
||||
},
|
||||
"@vue/compiler-core": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.0.10.tgz",
|
||||
"integrity": "sha512-rayD+aODgX9CWgWv0cAI+whPLyMmtkWfNGsZpdpsaIloh8mY2hX8+SvE1Nn3755YhGWJ/7oaDEcNpOctGwZbsA==",
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.0.11.tgz",
|
||||
"integrity": "sha512-6sFj6TBac1y2cWCvYCA8YzHJEbsVkX7zdRs/3yK/n1ilvRqcn983XvpBbnN3v4mZ1UiQycTvOiajJmOgN9EVgw==",
|
||||
"requires": {
|
||||
"@babel/parser": "^7.12.0",
|
||||
"@babel/types": "^7.12.0",
|
||||
"@vue/shared": "3.0.10",
|
||||
"@vue/shared": "3.0.11",
|
||||
"estree-walker": "^2.0.1",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
|
@ -498,12 +498,12 @@
|
|||
}
|
||||
},
|
||||
"@vue/compiler-dom": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.0.10.tgz",
|
||||
"integrity": "sha512-SzN1li9xAxtqkZimR1AFU2t1N0vzsAJxR/5764xoS0xedwhUU9s8s+Tks2FNMLsXiqdkP2Qd4zAM+9EwTbZmRw==",
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.0.11.tgz",
|
||||
"integrity": "sha512-+3xB50uGeY5Fv9eMKVJs2WSRULfgwaTJsy23OIltKgMrynnIj8hTYY2UL97HCoz78aDw1VDXdrBQ4qepWjnQcw==",
|
||||
"requires": {
|
||||
"@vue/compiler-core": "3.0.10",
|
||||
"@vue/shared": "3.0.10"
|
||||
"@vue/compiler-core": "3.0.11",
|
||||
"@vue/shared": "3.0.11"
|
||||
}
|
||||
},
|
||||
"@vue/compiler-sfc": {
|
||||
|
@ -618,87 +618,45 @@
|
|||
}
|
||||
},
|
||||
"@vue/reactivity": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.10.tgz",
|
||||
"integrity": "sha512-0GOSqlIv/a5wy4r6fAcdaglQ8v2sLYMRUpu49yK8Z2vHccK85Ym3R9C9K3vo6dfBRGbbCVvoKxYtQw49LvE8Ug==",
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.11.tgz",
|
||||
"integrity": "sha512-SKM3YKxtXHBPMf7yufXeBhCZ4XZDKP9/iXeQSC8bBO3ivBuzAi4aZi0bNoeE2IF2iGfP/AHEt1OU4ARj4ao/Xw==",
|
||||
"requires": {
|
||||
"@vue/shared": "3.0.10"
|
||||
"@vue/shared": "3.0.11"
|
||||
}
|
||||
},
|
||||
"@vue/runtime-core": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.10.tgz",
|
||||
"integrity": "sha512-qKhCOwHGff5YEdyClO1gf9Q9xgaPPz/qJ2GyzNZkPb00WcXJ3l+yTgHZWaSywRLs9GD1y9Ff3C0MIowzj95NHA==",
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.11.tgz",
|
||||
"integrity": "sha512-87XPNwHfz9JkmOlayBeCCfMh9PT2NBnv795DSbi//C/RaAnc/bGZgECjmkD7oXJ526BZbgk9QZBPdFT8KMxkAg==",
|
||||
"requires": {
|
||||
"@vue/reactivity": "3.0.10",
|
||||
"@vue/shared": "3.0.10"
|
||||
"@vue/reactivity": "3.0.11",
|
||||
"@vue/shared": "3.0.11"
|
||||
}
|
||||
},
|
||||
"@vue/runtime-dom": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.10.tgz",
|
||||
"integrity": "sha512-8yRAALc/884UlYWY7hJImecvow1Cngbl2B6n0ThYTms08FVQ3W9tdW0MEvR3JVit06JyQLS1Qvwdn1PwNPPDqg==",
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.11.tgz",
|
||||
"integrity": "sha512-jm3FVQESY3y2hKZ2wlkcmFDDyqaPyU3p1IdAX92zTNeCH7I8zZ37PtlE1b9NlCtzV53WjB4TZAYh9yDCMIEumA==",
|
||||
"requires": {
|
||||
"@vue/runtime-core": "3.0.10",
|
||||
"@vue/shared": "3.0.10",
|
||||
"@vue/runtime-core": "3.0.11",
|
||||
"@vue/shared": "3.0.11",
|
||||
"csstype": "^2.6.8"
|
||||
}
|
||||
},
|
||||
"@vue/server-renderer": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.0.10.tgz",
|
||||
"integrity": "sha512-8WR/OdFdwLIhLmw82euU4NEQcucz1h3LWgKsfFfzmx0OLaQiaafXm2vNpYlN3lPpVi3s2GzDbMBmIrUNSliI7g==",
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.0.11.tgz",
|
||||
"integrity": "sha512-NtXRxCq+jJWohce7s2kgUdO7gD6LRrWhvpGUMrpp65ODxuwolVHVyacyvAnU9bxTj11xw+ErC7Q2+su9mJusEg==",
|
||||
"requires": {
|
||||
"@vue/compiler-ssr": "3.0.10",
|
||||
"@vue/shared": "3.0.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.0.10.tgz",
|
||||
"integrity": "sha512-rayD+aODgX9CWgWv0cAI+whPLyMmtkWfNGsZpdpsaIloh8mY2hX8+SvE1Nn3755YhGWJ/7oaDEcNpOctGwZbsA==",
|
||||
"requires": {
|
||||
"@babel/parser": "^7.12.0",
|
||||
"@babel/types": "^7.12.0",
|
||||
"@vue/shared": "3.0.10",
|
||||
"estree-walker": "^2.0.1",
|
||||
"source-map": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"@vue/compiler-dom": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.0.10.tgz",
|
||||
"integrity": "sha512-SzN1li9xAxtqkZimR1AFU2t1N0vzsAJxR/5764xoS0xedwhUU9s8s+Tks2FNMLsXiqdkP2Qd4zAM+9EwTbZmRw==",
|
||||
"requires": {
|
||||
"@vue/compiler-core": "3.0.10",
|
||||
"@vue/shared": "3.0.10"
|
||||
}
|
||||
},
|
||||
"@vue/compiler-ssr": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.0.10.tgz",
|
||||
"integrity": "sha512-skrPSp9pjZG3unqHpUaEaRRpO1yYxbCXRfJ1kZW8PTGAg5g3Y/hrUet5+Q6zCIZwr5j1mSMBSLXMDCjFuyyZLg==",
|
||||
"requires": {
|
||||
"@vue/compiler-dom": "3.0.10",
|
||||
"@vue/shared": "3.0.10"
|
||||
}
|
||||
},
|
||||
"@vue/shared": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.10.tgz",
|
||||
"integrity": "sha512-p8GJ+bGpEGiEHICwcCH/EtJnkZQllrOfm1J2J+Ep0ydMte25bPnArgrY/h2Tn1LKqqR3LXyQlOSYY6gJgiW2LQ=="
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
}
|
||||
"@vue/compiler-ssr": "3.0.11",
|
||||
"@vue/shared": "3.0.11"
|
||||
}
|
||||
},
|
||||
"@vue/shared": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.10.tgz",
|
||||
"integrity": "sha512-p8GJ+bGpEGiEHICwcCH/EtJnkZQllrOfm1J2J+Ep0ydMte25bPnArgrY/h2Tn1LKqqR3LXyQlOSYY6gJgiW2LQ=="
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.11.tgz",
|
||||
"integrity": "sha512-b+zB8A2so8eCE0JsxjL24J7vdGl8rzPQ09hZNhystm+KqSbKcAej1A+Hbva1rCMmTTqA+hFnUSDc5kouEo0JzA=="
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
|
@ -2988,6 +2946,72 @@
|
|||
"source-map": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"postcss-icss-keyframes": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-icss-keyframes/-/postcss-icss-keyframes-0.2.1.tgz",
|
||||
"integrity": "sha1-gMRFXgESsPL5w8Bax1FQYruf8pU=",
|
||||
"requires": {
|
||||
"icss-utils": "^3.0.1",
|
||||
"postcss": "^6.0.2",
|
||||
"postcss-value-parser": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"icss-utils": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-3.0.1.tgz",
|
||||
"integrity": "sha1-7nDTroysOMa+XtkehRsn7tNDrQ8=",
|
||||
"requires": {
|
||||
"postcss": "^6.0.2"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"version": "6.0.23",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
|
||||
"integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
|
||||
"requires": {
|
||||
"chalk": "^2.4.1",
|
||||
"source-map": "^0.6.1",
|
||||
"supports-color": "^5.4.0"
|
||||
}
|
||||
},
|
||||
"postcss-value-parser": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
|
||||
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss-modules": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.0.0.tgz",
|
||||
|
@ -3909,13 +3933,13 @@
|
|||
}
|
||||
},
|
||||
"vue": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.0.10.tgz",
|
||||
"integrity": "sha512-6arZ722uqIArSNUU94aqx0Pq0IMHFqYZuJ+U+q9HGdZZu11VFpyFP/L/hakijGFKp56Jr0yxJdWbDiJGWPxwww==",
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.0.11.tgz",
|
||||
"integrity": "sha512-3/eUi4InQz8MPzruHYSTQPxtM3LdZ1/S/BvaU021zBnZi0laRUyH6pfuE4wtUeLvI8wmUNwj5wrZFvbHUXL9dw==",
|
||||
"requires": {
|
||||
"@vue/compiler-dom": "3.0.10",
|
||||
"@vue/runtime-dom": "3.0.10",
|
||||
"@vue/shared": "3.0.10"
|
||||
"@vue/compiler-dom": "3.0.11",
|
||||
"@vue/runtime-dom": "3.0.11",
|
||||
"@vue/shared": "3.0.11"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"@snowpack/plugin-sass": "^1.4.0",
|
||||
"@snowpack/plugin-svelte": "^3.6.0",
|
||||
"@snowpack/plugin-vue": "^2.4.0",
|
||||
"@vue/server-renderer": "^3.0.10",
|
||||
"@vue/server-renderer": "^3.0.11",
|
||||
"acorn": "^7.4.0",
|
||||
"acorn-jsx": "^5.3.1",
|
||||
"astring": "^1.7.0",
|
||||
|
@ -54,6 +54,7 @@
|
|||
"micromark-extension-mdx-jsx": "^0.3.3",
|
||||
"node-fetch": "^2.6.1",
|
||||
"postcss": "^8.2.8",
|
||||
"postcss-icss-keyframes": "^0.2.1",
|
||||
"preact": "^10.5.13",
|
||||
"preact-render-to-string": "^5.1.18",
|
||||
"react": "^17.0.1",
|
||||
|
@ -63,7 +64,7 @@
|
|||
"sass": "^1.32.8",
|
||||
"snowpack": "^3.2.2",
|
||||
"svelte": "^3.35.0",
|
||||
"vue": "^3.0.10",
|
||||
"vue": "^3.0.11",
|
||||
"yargs-parser": "^20.2.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
5
src/@types/postcss-icss-keyframes.d.ts
vendored
Normal file
5
src/@types/postcss-icss-keyframes.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
declare module 'postcss-icss-keyframes' {
|
||||
import type { Plugin } from 'postcss';
|
||||
|
||||
export default function (options: { generateScopedName(keyframesName: string, filepath: string, css: string): string }): Plugin;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { Plugin } from 'postcss';
|
||||
import { Declaration, Plugin } from 'postcss';
|
||||
|
||||
interface AstroScopedOptions {
|
||||
className: string;
|
||||
|
@ -11,17 +11,24 @@ interface Selector {
|
|||
}
|
||||
|
||||
const CSS_SEPARATORS = new Set([' ', ',', '+', '>', '~']);
|
||||
const KEYFRAME_PERCENT = /\d+\.?\d*%/;
|
||||
|
||||
/** HTML tags that should never get scoped classes */
|
||||
export const NEVER_SCOPED_TAGS = new Set<string>(['base', 'body', 'font', 'frame', 'frameset', 'head', 'html', 'link', 'meta', 'noframes', 'noscript', 'script', 'style', 'title']);
|
||||
|
||||
/**
|
||||
* Scope Selectors
|
||||
* Scope Rules
|
||||
* Given a selector string (`.btn>span,.nav>span`), add an additional CSS class to every selector (`.btn.myClass>span.myClass,.nav.myClass>span.myClass`)
|
||||
* @param {string} selector The minified selector string to parse. Cannot contain arbitrary whitespace (other than child selector syntax).
|
||||
* @param {string} className The CSS class to apply.
|
||||
*/
|
||||
export function scopeSelectors(selector: string, className: string) {
|
||||
export function scopeRule(selector: string, className: string) {
|
||||
// if this is a keyframe keyword, return original selector
|
||||
if (selector === 'from' || selector === 'to' || KEYFRAME_PERCENT.test(selector)) {
|
||||
return selector;
|
||||
}
|
||||
|
||||
// For everything else, parse & scope
|
||||
const c = className.replace(/^\.?/, '.'); // make sure class always has leading '.'
|
||||
const selectors: Selector[] = [];
|
||||
let ss = selector; // final output
|
||||
|
@ -30,9 +37,12 @@ export function scopeSelectors(selector: string, className: string) {
|
|||
{
|
||||
let start = 0;
|
||||
let lastValue = '';
|
||||
let parensOpen = false;
|
||||
for (let n = 0; n < ss.length; n++) {
|
||||
const isEnd = n === selector.length - 1;
|
||||
if (isEnd || CSS_SEPARATORS.has(selector[n])) {
|
||||
if (selector[n] === '(') parensOpen = true;
|
||||
if (selector[n] === ')') parensOpen = false;
|
||||
if (isEnd || (parensOpen === false && CSS_SEPARATORS.has(selector[n]))) {
|
||||
lastValue = selector.substring(start, isEnd ? undefined : n);
|
||||
if (!lastValue) continue;
|
||||
selectors.push({ start, end: isEnd ? n + 1 : n, value: lastValue });
|
||||
|
@ -90,7 +100,7 @@ export default function astroScopedStyles(options: AstroScopedOptions): Plugin {
|
|||
return {
|
||||
postcssPlugin: '@astro/postcss-scoped-styles',
|
||||
Rule(rule) {
|
||||
rule.selector = scopeSelectors(rule.selector, options.className);
|
||||
rule.selector = scopeRule(rule.selector, options.className);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ import crypto from 'crypto';
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import autoprefixer from 'autoprefixer';
|
||||
import esbuild from 'esbuild';
|
||||
import postcss, { Plugin } from 'postcss';
|
||||
import postcssKeyframes from 'postcss-icss-keyframes';
|
||||
import findUp from 'find-up';
|
||||
import sass from 'sass';
|
||||
import type { RuntimeMode } from '../../@types/astro';
|
||||
|
@ -27,11 +27,9 @@ const getStyleType: Map<string, StyleType> = new Map([
|
|||
['.sass', 'sass'],
|
||||
['.scss', 'scss'],
|
||||
['css', 'css'],
|
||||
['postcss', 'postcss'],
|
||||
['sass', 'sass'],
|
||||
['scss', 'scss'],
|
||||
['text/css', 'css'],
|
||||
['text/postcss', 'postcss'],
|
||||
['text/sass', 'sass'],
|
||||
['text/scss', 'scss'],
|
||||
]);
|
||||
|
@ -134,7 +132,16 @@ async function transformStyle(code: string, { type, filename, scopedClass, mode
|
|||
// 2b. Astro scoped styles (always on)
|
||||
postcssPlugins.push(astroScopedStyles({ className: scopedClass }));
|
||||
|
||||
// 2c. Autoprefixer (always on)
|
||||
// 2c. Scoped @keyframes
|
||||
postcssPlugins.push(
|
||||
postcssKeyframes({
|
||||
generateScopedName(keyframesName) {
|
||||
return `${keyframesName}-${scopedClass}`;
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// 2d. Autoprefixer (always on)
|
||||
postcssPlugins.push(autoprefixer());
|
||||
|
||||
// 2e. Run PostCSS
|
||||
|
|
|
@ -1,29 +1,33 @@
|
|||
import { suite } from 'uvu';
|
||||
import * as assert from 'uvu/assert';
|
||||
import { scopeSelectors } from '../lib/compiler/optimize/postcss-scoped-styles/index.js';
|
||||
import { scopeRule } from '../lib/compiler/optimize/postcss-scoped-styles/index.js';
|
||||
|
||||
const ScopedStyles = suite('Astro PostCSS Scoped Styles Plugin');
|
||||
|
||||
const className = '.astro-abcd1234';
|
||||
const className = 'astro-abcd1234';
|
||||
|
||||
// Note: assume all selectors have no unnecessary spaces (i.e. must be minified)
|
||||
const tests = {
|
||||
'.class': `.class${className}`,
|
||||
h1: `h1${className}`,
|
||||
'.nav h1': `.nav${className} h1${className}`,
|
||||
'.class+.class': `.class${className}+.class${className}`,
|
||||
'.class~:global(a)': `.class${className}~a`,
|
||||
'.class *': `.class${className} ${className}`,
|
||||
'.class>*': `.class${className}>${className}`,
|
||||
'.class :global(*)': `.class${className} *`,
|
||||
'.class :global(.nav:not(.is-active))': `.class${className} .nav:not(.is-active)`, // preserve nested parens
|
||||
'.class:not(.is-active)': `.class${className}:not(.is-active)`, // Note: the :not() selector can NOT contain multiple classes, so this is correct; if this causes issues for some people then it‘s worth a discussion
|
||||
'body h1': `body h1${className}`, // body shouldn‘t be scoped; it‘s not a component
|
||||
};
|
||||
ScopedStyles('Scopes rules correctly', () => {
|
||||
// Note: assume all selectors have no unnecessary spaces (i.e. must be minified)
|
||||
const tests = {
|
||||
'.class': `.class.${className}`,
|
||||
h1: `h1.${className}`,
|
||||
'.nav h1': `.nav.${className} h1.${className}`,
|
||||
'.class+.class': `.class.${className}+.class.${className}`,
|
||||
'.class~:global(a)': `.class.${className}~a`,
|
||||
'.class *': `.class.${className} .${className}`,
|
||||
'.class>*': `.class.${className}>.${className}`,
|
||||
'.class :global(*)': `.class.${className} *`,
|
||||
'.class :global(.nav:not(.is-active))': `.class.${className} .nav:not(.is-active)`, // preserve nested parens
|
||||
'.class :global(ul li)': `.class.${className} ul li`, // allow doubly-scoped selectors
|
||||
'.class:not(.is-active)': `.class.${className}:not(.is-active)`, // Note: the :not() selector can NOT contain multiple classes, so this is correct; if this causes issues for some people then it‘s worth a discussion
|
||||
'body h1': `body h1.${className}`, // body shouldn‘t be scoped; it‘s not a component
|
||||
from: 'from', // ignore keyframe keywords (below)
|
||||
to: 'to',
|
||||
'55%': '55%',
|
||||
};
|
||||
|
||||
ScopedStyles('Scopes correctly', () => {
|
||||
for (const [given, expected] of Object.entries(tests)) {
|
||||
assert.equal(scopeSelectors(given, className), expected);
|
||||
assert.equal(scopeRule(given, className), expected);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue