diff --git a/.github/ISSUE_TEMPLATE/css-issue.yml b/.github/ISSUE_TEMPLATE/css-issue.yml
index 058743751..1d902d28c 100644
--- a/.github/ISSUE_TEMPLATE/css-issue.yml
+++ b/.github/ISSUE_TEMPLATE/css-issue.yml
@@ -98,6 +98,7 @@ body:
- PostCSS Pseudo Class Any Link
- PostCSS Rebeccapurple
- PostCSS Replace Overflow Wrap
+ - PostCSS Scope Pseudo Class
- PostCSS Selector Not
- PostCSS Stepped Value Functions
- PostCSS System Ui Font Family
diff --git a/.github/ISSUE_TEMPLATE/plugin-issue.yml b/.github/ISSUE_TEMPLATE/plugin-issue.yml
index 239b81211..114a2aada 100644
--- a/.github/ISSUE_TEMPLATE/plugin-issue.yml
+++ b/.github/ISSUE_TEMPLATE/plugin-issue.yml
@@ -100,6 +100,7 @@ body:
- PostCSS Pseudo Class Any Link
- PostCSS Rebeccapurple
- PostCSS Replace Overflow Wrap
+ - PostCSS Scope Pseudo Class
- PostCSS Selector Not
- PostCSS Stepped Value Functions
- PostCSS System Ui Font Family
diff --git a/.github/labeler.yml b/.github/labeler.yml
index b0fdd3039..7be909787 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -176,6 +176,10 @@
- plugins/postcss-pseudo-class-any-link/**
- experimental/postcss-pseudo-class-any-link/**
+"plugins/postcss-scope-pseudo-class":
+ - plugins/postcss-scope-pseudo-class/**
+ - experimental/postcss-scope-pseudo-class/**
+
"plugins/postcss-color-rebeccapurple":
- plugins/postcss-color-rebeccapurple/**
- experimental/postcss-color-rebeccapurple/**
diff --git a/package-lock.json b/package-lock.json
index 27284982f..fb16c71e9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1892,6 +1892,10 @@
"resolved": "plugins/postcss-progressive-custom-properties",
"link": true
},
+ "node_modules/@csstools/postcss-scope-pseudo-class": {
+ "resolved": "plugins/postcss-scope-pseudo-class",
+ "link": true
+ },
"node_modules/@csstools/postcss-stepped-value-functions": {
"resolved": "plugins/postcss-stepped-value-functions",
"link": true
@@ -7623,6 +7627,23 @@
"postcss": "^8.2"
}
},
+ "plugins/postcss-scope-pseudo-class": {
+ "version": "1.0.0",
+ "license": "CC0-1.0",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
"plugins/postcss-selector-not": {
"version": "6.0.1",
"license": "MIT",
@@ -9045,6 +9066,12 @@
"postcss-value-parser": "^4.2.0"
}
},
+ "@csstools/postcss-scope-pseudo-class": {
+ "version": "file:plugins/postcss-scope-pseudo-class",
+ "requires": {
+ "postcss-selector-parser": "^6.0.10"
+ }
+ },
"@csstools/postcss-stepped-value-functions": {
"version": "file:plugins/postcss-stepped-value-functions",
"requires": {
diff --git a/packages/generate-test-cases/src/index.mjs b/packages/generate-test-cases/src/index.mjs
index cd6b0bfad..64ab32bfb 100644
--- a/packages/generate-test-cases/src/index.mjs
+++ b/packages/generate-test-cases/src/index.mjs
@@ -21,6 +21,14 @@ import { generate } from './generate.mjs';
],
),
+ generate(
+ 'selector',
+ path.join('../../plugins', 'postcss-scope-pseudo-class'),
+ [
+ ':scope',
+ ],
+ ),
+
generate(
'selector',
path.join('../../plugins', 'postcss-focus-visible'),
diff --git a/plugins/postcss-scope-pseudo-class/.gitignore b/plugins/postcss-scope-pseudo-class/.gitignore
new file mode 100644
index 000000000..7172b04f1
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+package-lock.json
+yarn.lock
+*.result.css
+*.result.css.map
+dist/*
diff --git a/plugins/postcss-scope-pseudo-class/.nvmrc b/plugins/postcss-scope-pseudo-class/.nvmrc
new file mode 100644
index 000000000..f0b10f153
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/.nvmrc
@@ -0,0 +1 @@
+v16.13.1
diff --git a/plugins/postcss-scope-pseudo-class/.tape.mjs b/plugins/postcss-scope-pseudo-class/.tape.mjs
new file mode 100644
index 000000000..c869236e8
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/.tape.mjs
@@ -0,0 +1,27 @@
+import postcssTape from '../../packages/postcss-tape/dist/index.mjs';
+import plugin from '@csstools/postcss-scope-pseudo-class';
+
+postcssTape(plugin)({
+ basic: {
+ message: "supports basic usage",
+ },
+ 'basic:preserve-true': {
+ message: "supports basic usage",
+ options: {
+ preserve: true
+ }
+ },
+ 'generated-selector-cases': {
+ message: 'handles all generated selector cases correctly',
+ warnings: 1,
+ },
+ 'examples/example': {
+ message: 'minimal example',
+ },
+ 'examples/example:preserve-true': {
+ message: 'minimal example',
+ options: {
+ preserve: true
+ }
+ },
+});
diff --git a/plugins/postcss-scope-pseudo-class/CHANGELOG.md b/plugins/postcss-scope-pseudo-class/CHANGELOG.md
new file mode 100644
index 000000000..d3a404923
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Changes to PostCSS Scope Pseudo Class
+
+### 1.0.0 (Unreleased)
+
+- Initial version
diff --git a/plugins/postcss-scope-pseudo-class/INSTALL.md b/plugins/postcss-scope-pseudo-class/INSTALL.md
new file mode 100644
index 000000000..2dde05fcb
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/INSTALL.md
@@ -0,0 +1,176 @@
+# Installing PostCSS Scope Pseudo Class
+
+[PostCSS Scope Pseudo Class] runs in all Node environments, with special instructions for:
+
+| [Node](#node) | [PostCSS CLI](#postcss-cli) | [Webpack](#webpack) | [Create React App](#create-react-app) | [Gulp](#gulp) | [Grunt](#grunt) |
+| --- | --- | --- | --- | --- | --- |
+
+## Node
+
+Add [PostCSS Scope Pseudo Class] to your project:
+
+```bash
+npm install postcss @csstools/postcss-scope-pseudo-class --save-dev
+```
+
+Use it as a [PostCSS] plugin:
+
+```js
+const postcss = require('postcss');
+const postcssScopePseudoClass = require('@csstools/postcss-scope-pseudo-class');
+
+postcss([
+ postcssScopePseudoClass(/* pluginOptions */)
+]).process(YOUR_CSS /*, processOptions */);
+```
+
+## PostCSS CLI
+
+Add [PostCSS CLI] to your project:
+
+```bash
+npm install postcss-cli @csstools/postcss-scope-pseudo-class --save-dev
+```
+
+Use [PostCSS Scope Pseudo Class] in your `postcss.config.js` configuration file:
+
+```js
+const postcssScopePseudoClass = require('@csstools/postcss-scope-pseudo-class');
+
+module.exports = {
+ plugins: [
+ postcssScopePseudoClass(/* pluginOptions */)
+ ]
+}
+```
+
+## Webpack
+
+_Webpack version 5_
+
+Add [PostCSS Loader] to your project:
+
+```bash
+npm install postcss-loader @csstools/postcss-scope-pseudo-class --save-dev
+```
+
+Use [PostCSS Scope Pseudo Class] in your Webpack configuration:
+
+```js
+module.exports = {
+ module: {
+ rules: [
+ {
+ test: /\.css$/i,
+ use: [
+ "style-loader",
+ {
+ loader: "css-loader",
+ options: { importLoaders: 1 },
+ },
+ {
+ loader: "postcss-loader",
+ options: {
+ postcssOptions: {
+ plugins: [
+ [
+ "@csstools/postcss-scope-pseudo-class",
+ {
+ // Options
+ },
+ ],
+ ],
+ },
+ },
+ },
+ ],
+ },
+ ],
+ },
+};
+```
+
+## Create React App
+
+Add [React App Rewired] and [React App Rewire PostCSS] to your project:
+
+```bash
+npm install react-app-rewired react-app-rewire-postcss @csstools/postcss-scope-pseudo-class --save-dev
+```
+
+Use [React App Rewire PostCSS] and [PostCSS Scope Pseudo Class] in your
+`config-overrides.js` file:
+
+```js
+const reactAppRewirePostcss = require('react-app-rewire-postcss');
+const postcssScopePseudoClass = require('@csstools/postcss-scope-pseudo-class');
+
+module.exports = config => reactAppRewirePostcss(config, {
+ plugins: () => [
+ postcssScopePseudoClass(/* pluginOptions */)
+ ]
+});
+```
+
+## Gulp
+
+Add [Gulp PostCSS] to your project:
+
+```bash
+npm install gulp-postcss @csstools/postcss-scope-pseudo-class --save-dev
+```
+
+Use [PostCSS Scope Pseudo Class] in your Gulpfile:
+
+```js
+const postcss = require('gulp-postcss');
+const postcssScopePseudoClass = require('@csstools/postcss-scope-pseudo-class');
+
+gulp.task('css', function () {
+ var plugins = [
+ postcssScopePseudoClass(/* pluginOptions */)
+ ];
+
+ return gulp.src('./src/*.css')
+ .pipe(postcss(plugins))
+ .pipe(gulp.dest('.'));
+});
+```
+
+## Grunt
+
+Add [Grunt PostCSS] to your project:
+
+```bash
+npm install grunt-postcss @csstools/postcss-scope-pseudo-class --save-dev
+```
+
+Use [PostCSS Scope Pseudo Class] in your Gruntfile:
+
+```js
+const postcssScopePseudoClass = require('@csstools/postcss-scope-pseudo-class');
+
+grunt.loadNpmTasks('grunt-postcss');
+
+grunt.initConfig({
+ postcss: {
+ options: {
+ processors: [
+ postcssScopePseudoClass(/* pluginOptions */)
+ ]
+ },
+ dist: {
+ src: '*.css'
+ }
+ }
+});
+```
+
+[Gulp PostCSS]: https://github.com/postcss/gulp-postcss
+[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss
+[PostCSS]: https://github.com/postcss/postcss
+[PostCSS CLI]: https://github.com/postcss/postcss-cli
+[PostCSS Loader]: https://github.com/postcss/postcss-loader
+[PostCSS Scope Pseudo Class]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-scope-pseudo-class
+[React App Rewire PostCSS]: https://github.com/csstools/react-app-rewire-postcss
+[React App Rewired]: https://github.com/timarney/react-app-rewired
diff --git a/plugins/postcss-scope-pseudo-class/LICENSE.md b/plugins/postcss-scope-pseudo-class/LICENSE.md
new file mode 100644
index 000000000..0bc1fa706
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/LICENSE.md
@@ -0,0 +1,108 @@
+# CC0 1.0 Universal
+
+## Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator and
+subsequent owner(s) (each and all, an “owner”) of an original work of
+authorship and/or a database (each, a “Work”).
+
+Certain owners wish to permanently relinquish those rights to a Work for the
+purpose of contributing to a commons of creative, cultural and scientific works
+(“Commons”) that the public can reliably and without fear of later claims of
+infringement build upon, modify, incorporate in other works, reuse and
+redistribute as freely as possible in any form whatsoever and for any purposes,
+including without limitation commercial purposes. These owners may contribute
+to the Commons to promote the ideal of a free culture and the further
+production of creative, cultural and scientific works, or to gain reputation or
+greater distribution for their Work in part through the use and efforts of
+others.
+
+For these and/or other purposes and motivations, and without any expectation of
+additional consideration or compensation, the person associating CC0 with a
+Work (the “Affirmer”), to the extent that he or she is an owner of Copyright
+and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and
+publicly distribute the Work under its terms, with knowledge of his or her
+Copyright and Related Rights in the Work and the meaning and intended legal
+effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+ protected by copyright and related or neighboring rights (“Copyright and
+ Related Rights”). Copyright and Related Rights include, but are not limited
+ to, the following:
+ 1. the right to reproduce, adapt, distribute, perform, display, communicate,
+ and translate a Work;
+ 2. moral rights retained by the original author(s) and/or performer(s);
+ 3. publicity and privacy rights pertaining to a person’s image or likeness
+ depicted in a Work;
+ 4. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(i), below;
+ 5. rights protecting the extraction, dissemination, use and reuse of data in
+ a Work;
+ 6. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation thereof,
+ including any amended or successor version of such directive); and
+ 7. other similar, equivalent or corresponding rights throughout the world
+ based on applicable law or treaty, and any national implementations
+ thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention of,
+ applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
+ unconditionally waives, abandons, and surrenders all of Affirmer’s Copyright
+ and Related Rights and associated claims and causes of action, whether now
+ known or unknown (including existing as well as future claims and causes of
+ action), in the Work (i) in all territories worldwide, (ii) for the maximum
+ duration provided by applicable law or treaty (including future time
+ extensions), (iii) in any current or future medium and for any number of
+ copies, and (iv) for any purpose whatsoever, including without limitation
+ commercial, advertising or promotional purposes (the “Waiver”). Affirmer
+ makes the Waiver for the benefit of each member of the public at large and
+ to the detriment of Affirmer’s heirs and successors, fully intending that
+ such Waiver shall not be subject to revocation, rescission, cancellation,
+ termination, or any other legal or equitable action to disrupt the quiet
+ enjoyment of the Work by the public as contemplated by Affirmer’s express
+ Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason be
+ judged legally invalid or ineffective under applicable law, then the Waiver
+ shall be preserved to the maximum extent permitted taking into account
+ Affirmer’s express Statement of Purpose. In addition, to the extent the
+ Waiver is so judged Affirmer hereby grants to each affected person a
+ royalty-free, non transferable, non sublicensable, non exclusive,
+ irrevocable and unconditional license to exercise Affirmer’s Copyright and
+ Related Rights in the Work (i) in all territories worldwide, (ii) for the
+ maximum duration provided by applicable law or treaty (including future time
+ extensions), (iii) in any current or future medium and for any number of
+ copies, and (iv) for any purpose whatsoever, including without limitation
+ commercial, advertising or promotional purposes (the “License”). The License
+ shall be deemed effective as of the date CC0 was applied by Affirmer to the
+ Work. Should any part of the License for any reason be judged legally
+ invalid or ineffective under applicable law, such partial invalidity or
+ ineffectiveness shall not invalidate the remainder of the License, and in
+ such case Affirmer hereby affirms that he or she will not (i) exercise any
+ of his or her remaining Copyright and Related Rights in the Work or (ii)
+ assert any associated claims and causes of action with respect to the Work,
+ in either case contrary to Affirmer’s express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+ 1. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ 2. Affirmer offers the Work as-is and makes no representations or warranties
+ of any kind concerning the Work, express, implied, statutory or
+ otherwise, including without limitation warranties of title,
+ merchantability, fitness for a particular purpose, non infringement, or
+ the absence of latent or other defects, accuracy, or the present or
+ absence of errors, whether or not discoverable, all to the greatest
+ extent permissible under applicable law.
+ 3. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person’s Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the Work.
+ 4. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to this
+ CC0 or use of the Work.
+
+For more information, please see
+http://creativecommons.org/publicdomain/zero/1.0/.
diff --git a/plugins/postcss-scope-pseudo-class/README.md b/plugins/postcss-scope-pseudo-class/README.md
new file mode 100644
index 000000000..d2310f398
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/README.md
@@ -0,0 +1,80 @@
+# PostCSS Scope Pseudo Class [
][postcss]
+
+[
][npm-url] [
][css-url] [
][cli-url] [
][discord]
+
+[PostCSS Scope Pseudo Class] lets you use the `:scope` Pseudo-class following the [Selectors 4 specification].
+
+```pcss
+:scope {
+ color: green;
+}
+
+/* becomes */
+
+:root {
+ color: green;
+}
+```
+
+## Usage
+
+Add [PostCSS Scope Pseudo Class] to your project:
+
+```bash
+npm install postcss @csstools/postcss-scope-pseudo-class --save-dev
+```
+
+Use it as a [PostCSS] plugin:
+
+```js
+const postcss = require('postcss');
+const postcssScopePseudoClass = require('@csstools/postcss-scope-pseudo-class');
+
+postcss([
+ postcssScopePseudoClass(/* pluginOptions */)
+]).process(YOUR_CSS /*, processOptions */);
+```
+
+[PostCSS Scope Pseudo Class] runs in all Node environments, with special
+instructions for:
+
+| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) |
+| --- | --- | --- | --- | --- | --- |
+
+## Options
+
+### preserve
+
+The `preserve` option determines whether the original notation
+is preserved. By default, it is not preserved.
+
+```js
+postcssScopePseudoClass({ preserve: true })
+```
+
+```pcss
+:scope {
+ color: green;
+}
+
+/* becomes */
+
+:root {
+ color: green;
+}
+:scope {
+ color: green;
+}
+```
+
+[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
+[css-url]: https://cssdb.org/#scope-pseudo-class
+[discord]: https://discord.gg/bUadyRwkJS
+[npm-url]: https://www.npmjs.com/package/@csstools/postcss-scope-pseudo-class
+
+[Gulp PostCSS]: https://github.com/postcss/gulp-postcss
+[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss
+[PostCSS]: https://github.com/postcss/postcss
+[PostCSS Loader]: https://github.com/postcss/postcss-loader
+[PostCSS Scope Pseudo Class]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-scope-pseudo-class
+[Selectors 4 specification]: https://www.w3.org/TR/selectors-4/#the-scope-pseudo
diff --git a/plugins/postcss-scope-pseudo-class/docs/README.md b/plugins/postcss-scope-pseudo-class/docs/README.md
new file mode 100644
index 000000000..38116e051
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/docs/README.md
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[] lets you use the `:scope` Pseudo-class following the [Selectors 4 specification].
+
+```pcss
+
+
+/* becomes */
+
+
+```
+
+
+
+
+
+## Options
+
+### preserve
+
+The `preserve` option determines whether the original notation
+is preserved. By default, it is not preserved.
+
+```js
+({ preserve: true })
+```
+
+```pcss
+
+
+/* becomes */
+
+
+```
+
+
+[Selectors 4 specification]:
diff --git a/plugins/postcss-scope-pseudo-class/package.json b/plugins/postcss-scope-pseudo-class/package.json
new file mode 100644
index 000000000..4b0ff3ea7
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/package.json
@@ -0,0 +1,77 @@
+{
+ "name": "@csstools/postcss-scope-pseudo-class",
+ "description": "The Reference Element Pseudo-class: :scope",
+ "version": "1.0.0",
+ "contributors": [
+ {
+ "name": "Antonio Laguna",
+ "email": "antonio@laguna.es",
+ "url": "https://antonio.laguna.es"
+ },
+ {
+ "name": "Romain Menke",
+ "email": "romainmenke@gmail.com"
+ }
+ ],
+ "license": "CC0-1.0",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "main": "dist/index.cjs",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "import": "./dist/index.mjs",
+ "require": "./dist/index.cjs",
+ "default": "./dist/index.mjs"
+ }
+ },
+ "files": [
+ "CHANGELOG.md",
+ "LICENSE.md",
+ "README.md",
+ "dist"
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ },
+ "scripts": {
+ "build": "rollup -c ../../rollup/default.js",
+ "clean": "node -e \"fs.rmSync('./dist', { recursive: true, force: true });\"",
+ "docs": "node ../../.github/bin/generate-docs/install.mjs && node ../../.github/bin/generate-docs/readme.mjs",
+ "lint": "npm run lint:eslint && npm run lint:package-json",
+ "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern",
+ "lint:package-json": "node ../../.github/bin/format-package-json.mjs",
+ "prepublishOnly": "npm run clean && npm run build && npm run test",
+ "test": "node .tape.mjs && npm run test:exports",
+ "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs",
+ "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs"
+ },
+ "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-scope-pseudo-class#readme",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/csstools/postcss-plugins.git",
+ "directory": "plugins/postcss-scope-pseudo-class"
+ },
+ "bugs": "https://github.com/csstools/postcss-plugins/issues",
+ "keywords": [
+ "postcss-plugin"
+ ],
+ "csstools": {
+ "cssdbId": "scope-pseudo-class",
+ "exportName": "postcssScopePseudoClass",
+ "humanReadableName": "PostCSS Scope Pseudo Class",
+ "specUrl": "https://www.w3.org/TR/selectors-4/#the-scope-pseudo"
+ },
+ "volta": {
+ "extends": "../../package.json"
+ }
+}
diff --git a/plugins/postcss-scope-pseudo-class/src/index.ts b/plugins/postcss-scope-pseudo-class/src/index.ts
new file mode 100644
index 000000000..dde981c83
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/src/index.ts
@@ -0,0 +1,75 @@
+import type { AtRule, Container, Node, PluginCreator } from 'postcss';
+import parser from 'postcss-selector-parser';
+
+type pluginOptions = { preserve?: boolean };
+
+const creator: PluginCreator = (opts?: pluginOptions) => {
+ const options = Object.assign(
+ // Default options
+ {
+ preserve: false,
+ },
+ // Provided options
+ opts,
+ );
+
+ return {
+ postcssPlugin: 'postcss-scope-pseudo-class',
+ Rule(rule, { result }) {
+ if (!rule.selector.toLowerCase().includes(':scope')) {
+ return;
+ }
+
+ {
+ // We ignore rules withing `@scope`
+ let parent: Container = rule.parent;
+ while (parent) {
+ if (parent.type === 'atrule' && (parent as AtRule).name.toLowerCase() === 'scope') {
+ return;
+ }
+
+ parent = parent.parent;
+ }
+ }
+
+ let modifiedSelector = rule.selector;
+ try {
+ const selectorAST = parser().astSync(modifiedSelector);
+ if (!selectorAST) {
+ return;
+ }
+
+ selectorAST.walkPseudos((pseudo) => {
+ if (pseudo.value.toLowerCase() === ':has') {
+ return false;
+ }
+
+ if (pseudo.value.toLowerCase() === ':scope') {
+ pseudo.value = ':root';
+ }
+ });
+
+ modifiedSelector = selectorAST.toString();
+ } catch (err) {
+ rule.warn(result, `Unable to parse selector: "${rule.selector}"`);
+ }
+
+ if (modifiedSelector === rule.selector) {
+ return;
+ }
+
+ rule.cloneBefore({
+ selector: modifiedSelector,
+ });
+
+ if (!options.preserve) {
+ rule.remove();
+ }
+ },
+ };
+};
+
+creator.postcss = true;
+
+export default creator;
+
diff --git a/plugins/postcss-scope-pseudo-class/test/_import.mjs b/plugins/postcss-scope-pseudo-class/test/_import.mjs
new file mode 100644
index 000000000..fe9d178eb
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/_import.mjs
@@ -0,0 +1,6 @@
+import assert from 'assert';
+import plugin from '@csstools/postcss-scope-pseudo-class';
+plugin();
+
+assert.ok(plugin.postcss, 'should have "postcss flag"');
+assert.equal(typeof plugin, 'function', 'should return a function');
diff --git a/plugins/postcss-scope-pseudo-class/test/_require.cjs b/plugins/postcss-scope-pseudo-class/test/_require.cjs
new file mode 100644
index 000000000..588458c35
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/_require.cjs
@@ -0,0 +1,6 @@
+const assert = require('assert');
+const plugin = require('@csstools/postcss-scope-pseudo-class');
+plugin();
+
+assert.ok(plugin.postcss, 'should have "postcss flag"');
+assert.equal(typeof plugin, 'function', 'should return a function');
diff --git a/plugins/postcss-scope-pseudo-class/test/basic.css b/plugins/postcss-scope-pseudo-class/test/basic.css
new file mode 100644
index 000000000..a6ba59829
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/basic.css
@@ -0,0 +1,23 @@
+:scope {
+ order: 1;
+}
+
+@scope (.foo) {
+ :scope {
+ order: 2;
+ }
+}
+
+@media screen {
+ :scope {
+ order: 3;
+ }
+}
+
+:has(.foo > :scope + .bar) {
+ order: 3;
+}
+
+:has(.foo > :not(:scope) + .bar) {
+ order: 4;
+}
diff --git a/plugins/postcss-scope-pseudo-class/test/basic.expect.css b/plugins/postcss-scope-pseudo-class/test/basic.expect.css
new file mode 100644
index 000000000..c32cc12da
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/basic.expect.css
@@ -0,0 +1,23 @@
+:root {
+ order: 1;
+}
+
+@scope (.foo) {
+ :scope {
+ order: 2;
+ }
+}
+
+@media screen {
+ :root {
+ order: 3;
+ }
+}
+
+:has(.foo > :scope + .bar) {
+ order: 3;
+}
+
+:has(.foo > :not(:scope) + .bar) {
+ order: 4;
+}
diff --git a/plugins/postcss-scope-pseudo-class/test/basic.preserve-true.expect.css b/plugins/postcss-scope-pseudo-class/test/basic.preserve-true.expect.css
new file mode 100644
index 000000000..ee0b266e5
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/basic.preserve-true.expect.css
@@ -0,0 +1,30 @@
+:root {
+ order: 1;
+}
+
+:scope {
+ order: 1;
+}
+
+@scope (.foo) {
+ :scope {
+ order: 2;
+ }
+}
+
+@media screen {
+ :root {
+ order: 3;
+ }
+ :scope {
+ order: 3;
+ }
+}
+
+:has(.foo > :scope + .bar) {
+ order: 3;
+}
+
+:has(.foo > :not(:scope) + .bar) {
+ order: 4;
+}
diff --git a/plugins/postcss-scope-pseudo-class/test/examples/example.css b/plugins/postcss-scope-pseudo-class/test/examples/example.css
new file mode 100644
index 000000000..41a7c6e4a
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/examples/example.css
@@ -0,0 +1,3 @@
+:scope {
+ color: green;
+}
diff --git a/plugins/postcss-scope-pseudo-class/test/examples/example.expect.css b/plugins/postcss-scope-pseudo-class/test/examples/example.expect.css
new file mode 100644
index 000000000..929c0fb71
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/examples/example.expect.css
@@ -0,0 +1,3 @@
+:root {
+ color: green;
+}
diff --git a/plugins/postcss-scope-pseudo-class/test/examples/example.preserve-true.expect.css b/plugins/postcss-scope-pseudo-class/test/examples/example.preserve-true.expect.css
new file mode 100644
index 000000000..a764898d4
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/examples/example.preserve-true.expect.css
@@ -0,0 +1,6 @@
+:root {
+ color: green;
+}
+:scope {
+ color: green;
+}
diff --git a/plugins/postcss-scope-pseudo-class/test/generated-selector-cases.css b/plugins/postcss-scope-pseudo-class/test/generated-selector-cases.css
new file mode 100644
index 000000000..5271ed1ab
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/generated-selector-cases.css
@@ -0,0 +1,905 @@
+:scope:scope {
+ order: 0;
+}
+
+:scope:scope {
+ order: 1;
+}
+
+:scope :scope {
+ order: 2;
+}
+
+:scope :scope {
+ order: 3;
+}
+
+:scope :scope {
+ order: 4;
+}
+
+:scope :scope {
+ order: 5;
+}
+
+:scope+:scope {
+ order: 6;
+}
+
+:scope+:scope {
+ order: 7;
+}
+
+:scope + :scope {
+ order: 8;
+}
+
+:scope + :scope {
+ order: 9;
+}
+
+:scope~:scope {
+ order: 10;
+}
+
+:scope~:scope {
+ order: 11;
+}
+
+:scope ~ :scope {
+ order: 12;
+}
+
+:scope ~ :scope {
+ order: 13;
+}
+
+:scope>:scope {
+ order: 14;
+}
+
+:scope>:scope {
+ order: 15;
+}
+
+:scope > :scope {
+ order: 16;
+}
+
+:scope > :scope {
+ order: 17;
+}
+
+:scope, :scope {
+ order: 18;
+}
+
+:scope, :scope {
+ order: 19;
+}
+
+button:scope {
+ order: 20;
+}
+
+:scopebutton {
+ order: 21;
+}
+
+button :scope {
+ order: 22;
+}
+
+:scope button {
+ order: 23;
+}
+
+button :scope {
+ order: 24;
+}
+
+:scope button {
+ order: 25;
+}
+
+button+:scope {
+ order: 26;
+}
+
+:scope+button {
+ order: 27;
+}
+
+button + :scope {
+ order: 28;
+}
+
+:scope + button {
+ order: 29;
+}
+
+button~:scope {
+ order: 30;
+}
+
+:scope~button {
+ order: 31;
+}
+
+button ~ :scope {
+ order: 32;
+}
+
+:scope ~ button {
+ order: 33;
+}
+
+button>:scope {
+ order: 34;
+}
+
+:scope>button {
+ order: 35;
+}
+
+button > :scope {
+ order: 36;
+}
+
+:scope > button {
+ order: 37;
+}
+
+button, :scope {
+ order: 38;
+}
+
+:scope, button {
+ order: 39;
+}
+
+.🧑🏾🎤:scope {
+ order: 40;
+}
+
+:scope.🧑🏾🎤 {
+ order: 41;
+}
+
+.🧑🏾🎤 :scope {
+ order: 42;
+}
+
+:scope .🧑🏾🎤 {
+ order: 43;
+}
+
+.🧑🏾🎤 :scope {
+ order: 44;
+}
+
+:scope .🧑🏾🎤 {
+ order: 45;
+}
+
+.🧑🏾🎤+:scope {
+ order: 46;
+}
+
+:scope+.🧑🏾🎤 {
+ order: 47;
+}
+
+.🧑🏾🎤 + :scope {
+ order: 48;
+}
+
+:scope + .🧑🏾🎤 {
+ order: 49;
+}
+
+.🧑🏾🎤~:scope {
+ order: 50;
+}
+
+:scope~.🧑🏾🎤 {
+ order: 51;
+}
+
+.🧑🏾🎤 ~ :scope {
+ order: 52;
+}
+
+:scope ~ .🧑🏾🎤 {
+ order: 53;
+}
+
+.🧑🏾🎤>:scope {
+ order: 54;
+}
+
+:scope>.🧑🏾🎤 {
+ order: 55;
+}
+
+.🧑🏾🎤 > :scope {
+ order: 56;
+}
+
+:scope > .🧑🏾🎤 {
+ order: 57;
+}
+
+.🧑🏾🎤, :scope {
+ order: 58;
+}
+
+:scope, .🧑🏾🎤 {
+ order: 59;
+}
+
+.foo:scope {
+ order: 60;
+}
+
+:scope.foo {
+ order: 61;
+}
+
+.foo :scope {
+ order: 62;
+}
+
+:scope .foo {
+ order: 63;
+}
+
+.foo :scope {
+ order: 64;
+}
+
+:scope .foo {
+ order: 65;
+}
+
+.foo+:scope {
+ order: 66;
+}
+
+:scope+.foo {
+ order: 67;
+}
+
+.foo + :scope {
+ order: 68;
+}
+
+:scope + .foo {
+ order: 69;
+}
+
+.foo~:scope {
+ order: 70;
+}
+
+:scope~.foo {
+ order: 71;
+}
+
+.foo ~ :scope {
+ order: 72;
+}
+
+:scope ~ .foo {
+ order: 73;
+}
+
+.foo>:scope {
+ order: 74;
+}
+
+:scope>.foo {
+ order: 75;
+}
+
+.foo > :scope {
+ order: 76;
+}
+
+:scope > .foo {
+ order: 77;
+}
+
+.foo, :scope {
+ order: 78;
+}
+
+:scope, .foo {
+ order: 79;
+}
+
+#foo:scope {
+ order: 80;
+}
+
+:scope#foo {
+ order: 81;
+}
+
+#foo :scope {
+ order: 82;
+}
+
+:scope #foo {
+ order: 83;
+}
+
+#foo :scope {
+ order: 84;
+}
+
+:scope #foo {
+ order: 85;
+}
+
+#foo+:scope {
+ order: 86;
+}
+
+:scope+#foo {
+ order: 87;
+}
+
+#foo + :scope {
+ order: 88;
+}
+
+:scope + #foo {
+ order: 89;
+}
+
+#foo~:scope {
+ order: 90;
+}
+
+:scope~#foo {
+ order: 91;
+}
+
+#foo ~ :scope {
+ order: 92;
+}
+
+:scope ~ #foo {
+ order: 93;
+}
+
+#foo>:scope {
+ order: 94;
+}
+
+:scope>#foo {
+ order: 95;
+}
+
+#foo > :scope {
+ order: 96;
+}
+
+:scope > #foo {
+ order: 97;
+}
+
+#foo, :scope {
+ order: 98;
+}
+
+:scope, #foo {
+ order: 99;
+}
+
+__foo:scope {
+ order: 100;
+}
+
+:scope__foo {
+ order: 101;
+}
+
+__foo :scope {
+ order: 102;
+}
+
+:scope __foo {
+ order: 103;
+}
+
+__foo :scope {
+ order: 104;
+}
+
+:scope __foo {
+ order: 105;
+}
+
+__foo+:scope {
+ order: 106;
+}
+
+:scope+__foo {
+ order: 107;
+}
+
+__foo + :scope {
+ order: 108;
+}
+
+:scope + __foo {
+ order: 109;
+}
+
+__foo~:scope {
+ order: 110;
+}
+
+:scope~__foo {
+ order: 111;
+}
+
+__foo ~ :scope {
+ order: 112;
+}
+
+:scope ~ __foo {
+ order: 113;
+}
+
+__foo>:scope {
+ order: 114;
+}
+
+:scope>__foo {
+ order: 115;
+}
+
+__foo > :scope {
+ order: 116;
+}
+
+:scope > __foo {
+ order: 117;
+}
+
+__foo, :scope {
+ order: 118;
+}
+
+:scope, __foo {
+ order: 119;
+}
+
+:--foo:scope {
+ order: 120;
+}
+
+:scope:--foo {
+ order: 121;
+}
+
+:--foo :scope {
+ order: 122;
+}
+
+:scope :--foo {
+ order: 123;
+}
+
+:--foo :scope {
+ order: 124;
+}
+
+:scope :--foo {
+ order: 125;
+}
+
+:--foo+:scope {
+ order: 126;
+}
+
+:scope+:--foo {
+ order: 127;
+}
+
+:--foo + :scope {
+ order: 128;
+}
+
+:scope + :--foo {
+ order: 129;
+}
+
+:--foo~:scope {
+ order: 130;
+}
+
+:scope~:--foo {
+ order: 131;
+}
+
+:--foo ~ :scope {
+ order: 132;
+}
+
+:scope ~ :--foo {
+ order: 133;
+}
+
+:--foo>:scope {
+ order: 134;
+}
+
+:scope>:--foo {
+ order: 135;
+}
+
+:--foo > :scope {
+ order: 136;
+}
+
+:scope > :--foo {
+ order: 137;
+}
+
+:--foo, :scope {
+ order: 138;
+}
+
+:scope, :--foo {
+ order: 139;
+}
+
+[foo="baz"]:scope {
+ order: 140;
+}
+
+:scope[foo="baz"] {
+ order: 141;
+}
+
+[foo="baz"] :scope {
+ order: 142;
+}
+
+:scope [foo="baz"] {
+ order: 143;
+}
+
+[foo="baz"] :scope {
+ order: 144;
+}
+
+:scope [foo="baz"] {
+ order: 145;
+}
+
+[foo="baz"]+:scope {
+ order: 146;
+}
+
+:scope+[foo="baz"] {
+ order: 147;
+}
+
+[foo="baz"] + :scope {
+ order: 148;
+}
+
+:scope + [foo="baz"] {
+ order: 149;
+}
+
+[foo="baz"]~:scope {
+ order: 150;
+}
+
+:scope~[foo="baz"] {
+ order: 151;
+}
+
+[foo="baz"] ~ :scope {
+ order: 152;
+}
+
+:scope ~ [foo="baz"] {
+ order: 153;
+}
+
+[foo="baz"]>:scope {
+ order: 154;
+}
+
+:scope>[foo="baz"] {
+ order: 155;
+}
+
+[foo="baz"] > :scope {
+ order: 156;
+}
+
+:scope > [foo="baz"] {
+ order: 157;
+}
+
+[foo="baz"], :scope {
+ order: 158;
+}
+
+:scope, [foo="baz"] {
+ order: 159;
+}
+
+*:scope {
+ order: 160;
+}
+
+:scope* {
+ order: 161;
+}
+
+* :scope {
+ order: 162;
+}
+
+:scope * {
+ order: 163;
+}
+
+* :scope {
+ order: 164;
+}
+
+:scope * {
+ order: 165;
+}
+
+*+:scope {
+ order: 166;
+}
+
+:scope+* {
+ order: 167;
+}
+
+* + :scope {
+ order: 168;
+}
+
+:scope + * {
+ order: 169;
+}
+
+*~:scope {
+ order: 170;
+}
+
+:scope~* {
+ order: 171;
+}
+
+* ~ :scope {
+ order: 172;
+}
+
+:scope ~ * {
+ order: 173;
+}
+
+*>:scope {
+ order: 174;
+}
+
+:scope>* {
+ order: 175;
+}
+
+* > :scope {
+ order: 176;
+}
+
+:scope > * {
+ order: 177;
+}
+
+*, :scope {
+ order: 178;
+}
+
+:scope, * {
+ order: 179;
+}
+
+:hover:scope {
+ order: 180;
+}
+
+:scope:hover {
+ order: 181;
+}
+
+:hover :scope {
+ order: 182;
+}
+
+:scope :hover {
+ order: 183;
+}
+
+:hover :scope {
+ order: 184;
+}
+
+:scope :hover {
+ order: 185;
+}
+
+:hover+:scope {
+ order: 186;
+}
+
+:scope+:hover {
+ order: 187;
+}
+
+:hover + :scope {
+ order: 188;
+}
+
+:scope + :hover {
+ order: 189;
+}
+
+:hover~:scope {
+ order: 190;
+}
+
+:scope~:hover {
+ order: 191;
+}
+
+:hover ~ :scope {
+ order: 192;
+}
+
+:scope ~ :hover {
+ order: 193;
+}
+
+:hover>:scope {
+ order: 194;
+}
+
+:scope>:hover {
+ order: 195;
+}
+
+:hover > :scope {
+ order: 196;
+}
+
+:scope > :hover {
+ order: 197;
+}
+
+:hover, :scope {
+ order: 198;
+}
+
+:scope, :hover {
+ order: 199;
+}
+
+::before:scope {
+ order: 200;
+}
+
+:scope::before {
+ order: 201;
+}
+
+::before :scope {
+ order: 202;
+}
+
+:scope ::before {
+ order: 203;
+}
+
+::before :scope {
+ order: 204;
+}
+
+:scope ::before {
+ order: 205;
+}
+
+::before+:scope {
+ order: 206;
+}
+
+:scope+::before {
+ order: 207;
+}
+
+::before + :scope {
+ order: 208;
+}
+
+:scope + ::before {
+ order: 209;
+}
+
+::before~:scope {
+ order: 210;
+}
+
+:scope~::before {
+ order: 211;
+}
+
+::before ~ :scope {
+ order: 212;
+}
+
+:scope ~ ::before {
+ order: 213;
+}
+
+::before>:scope {
+ order: 214;
+}
+
+:scope>::before {
+ order: 215;
+}
+
+::before > :scope {
+ order: 216;
+}
+
+:scope > ::before {
+ order: 217;
+}
+
+::before, :scope {
+ order: 218;
+}
+
+:scope, ::before {
+ order: 219;
+}
+
+foo[:scope] {
+ order: 220;
+}
+
+foo[baz=":scope"] {
+ order: 221;
+}
+
+:not(:scope) {
+ order: 222;
+}
+
+::scope {
+ order: 223;
+}
+
+:--:scope {
+ order: 224;
+}
+
+__:scope {
+ order: 225;
+}
+
+/* :scope */
diff --git a/plugins/postcss-scope-pseudo-class/test/generated-selector-cases.expect.css b/plugins/postcss-scope-pseudo-class/test/generated-selector-cases.expect.css
new file mode 100644
index 000000000..116eb0966
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/test/generated-selector-cases.expect.css
@@ -0,0 +1,905 @@
+:root:root {
+ order: 0;
+}
+
+:root:root {
+ order: 1;
+}
+
+:root :root {
+ order: 2;
+}
+
+:root :root {
+ order: 3;
+}
+
+:root :root {
+ order: 4;
+}
+
+:root :root {
+ order: 5;
+}
+
+:root+:root {
+ order: 6;
+}
+
+:root+:root {
+ order: 7;
+}
+
+:root + :root {
+ order: 8;
+}
+
+:root + :root {
+ order: 9;
+}
+
+:root~:root {
+ order: 10;
+}
+
+:root~:root {
+ order: 11;
+}
+
+:root ~ :root {
+ order: 12;
+}
+
+:root ~ :root {
+ order: 13;
+}
+
+:root>:root {
+ order: 14;
+}
+
+:root>:root {
+ order: 15;
+}
+
+:root > :root {
+ order: 16;
+}
+
+:root > :root {
+ order: 17;
+}
+
+:root, :root {
+ order: 18;
+}
+
+:root, :root {
+ order: 19;
+}
+
+button:root {
+ order: 20;
+}
+
+:scopebutton {
+ order: 21;
+}
+
+button :root {
+ order: 22;
+}
+
+:root button {
+ order: 23;
+}
+
+button :root {
+ order: 24;
+}
+
+:root button {
+ order: 25;
+}
+
+button+:root {
+ order: 26;
+}
+
+:root+button {
+ order: 27;
+}
+
+button + :root {
+ order: 28;
+}
+
+:root + button {
+ order: 29;
+}
+
+button~:root {
+ order: 30;
+}
+
+:root~button {
+ order: 31;
+}
+
+button ~ :root {
+ order: 32;
+}
+
+:root ~ button {
+ order: 33;
+}
+
+button>:root {
+ order: 34;
+}
+
+:root>button {
+ order: 35;
+}
+
+button > :root {
+ order: 36;
+}
+
+:root > button {
+ order: 37;
+}
+
+button, :root {
+ order: 38;
+}
+
+:root, button {
+ order: 39;
+}
+
+.🧑🏾🎤:root {
+ order: 40;
+}
+
+:root.🧑🏾🎤 {
+ order: 41;
+}
+
+.🧑🏾🎤 :root {
+ order: 42;
+}
+
+:root .🧑🏾🎤 {
+ order: 43;
+}
+
+.🧑🏾🎤 :root {
+ order: 44;
+}
+
+:root .🧑🏾🎤 {
+ order: 45;
+}
+
+.🧑🏾🎤+:root {
+ order: 46;
+}
+
+:root+.🧑🏾🎤 {
+ order: 47;
+}
+
+.🧑🏾🎤 + :root {
+ order: 48;
+}
+
+:root + .🧑🏾🎤 {
+ order: 49;
+}
+
+.🧑🏾🎤~:root {
+ order: 50;
+}
+
+:root~.🧑🏾🎤 {
+ order: 51;
+}
+
+.🧑🏾🎤 ~ :root {
+ order: 52;
+}
+
+:root ~ .🧑🏾🎤 {
+ order: 53;
+}
+
+.🧑🏾🎤>:root {
+ order: 54;
+}
+
+:root>.🧑🏾🎤 {
+ order: 55;
+}
+
+.🧑🏾🎤 > :root {
+ order: 56;
+}
+
+:root > .🧑🏾🎤 {
+ order: 57;
+}
+
+.🧑🏾🎤, :root {
+ order: 58;
+}
+
+:root, .🧑🏾🎤 {
+ order: 59;
+}
+
+.foo:root {
+ order: 60;
+}
+
+:root.foo {
+ order: 61;
+}
+
+.foo :root {
+ order: 62;
+}
+
+:root .foo {
+ order: 63;
+}
+
+.foo :root {
+ order: 64;
+}
+
+:root .foo {
+ order: 65;
+}
+
+.foo+:root {
+ order: 66;
+}
+
+:root+.foo {
+ order: 67;
+}
+
+.foo + :root {
+ order: 68;
+}
+
+:root + .foo {
+ order: 69;
+}
+
+.foo~:root {
+ order: 70;
+}
+
+:root~.foo {
+ order: 71;
+}
+
+.foo ~ :root {
+ order: 72;
+}
+
+:root ~ .foo {
+ order: 73;
+}
+
+.foo>:root {
+ order: 74;
+}
+
+:root>.foo {
+ order: 75;
+}
+
+.foo > :root {
+ order: 76;
+}
+
+:root > .foo {
+ order: 77;
+}
+
+.foo, :root {
+ order: 78;
+}
+
+:root, .foo {
+ order: 79;
+}
+
+#foo:root {
+ order: 80;
+}
+
+:root#foo {
+ order: 81;
+}
+
+#foo :root {
+ order: 82;
+}
+
+:root #foo {
+ order: 83;
+}
+
+#foo :root {
+ order: 84;
+}
+
+:root #foo {
+ order: 85;
+}
+
+#foo+:root {
+ order: 86;
+}
+
+:root+#foo {
+ order: 87;
+}
+
+#foo + :root {
+ order: 88;
+}
+
+:root + #foo {
+ order: 89;
+}
+
+#foo~:root {
+ order: 90;
+}
+
+:root~#foo {
+ order: 91;
+}
+
+#foo ~ :root {
+ order: 92;
+}
+
+:root ~ #foo {
+ order: 93;
+}
+
+#foo>:root {
+ order: 94;
+}
+
+:root>#foo {
+ order: 95;
+}
+
+#foo > :root {
+ order: 96;
+}
+
+:root > #foo {
+ order: 97;
+}
+
+#foo, :root {
+ order: 98;
+}
+
+:root, #foo {
+ order: 99;
+}
+
+__foo:root {
+ order: 100;
+}
+
+:scope__foo {
+ order: 101;
+}
+
+__foo :root {
+ order: 102;
+}
+
+:root __foo {
+ order: 103;
+}
+
+__foo :root {
+ order: 104;
+}
+
+:root __foo {
+ order: 105;
+}
+
+__foo+:root {
+ order: 106;
+}
+
+:root+__foo {
+ order: 107;
+}
+
+__foo + :root {
+ order: 108;
+}
+
+:root + __foo {
+ order: 109;
+}
+
+__foo~:root {
+ order: 110;
+}
+
+:root~__foo {
+ order: 111;
+}
+
+__foo ~ :root {
+ order: 112;
+}
+
+:root ~ __foo {
+ order: 113;
+}
+
+__foo>:root {
+ order: 114;
+}
+
+:root>__foo {
+ order: 115;
+}
+
+__foo > :root {
+ order: 116;
+}
+
+:root > __foo {
+ order: 117;
+}
+
+__foo, :root {
+ order: 118;
+}
+
+:root, __foo {
+ order: 119;
+}
+
+:--foo:root {
+ order: 120;
+}
+
+:root:--foo {
+ order: 121;
+}
+
+:--foo :root {
+ order: 122;
+}
+
+:root :--foo {
+ order: 123;
+}
+
+:--foo :root {
+ order: 124;
+}
+
+:root :--foo {
+ order: 125;
+}
+
+:--foo+:root {
+ order: 126;
+}
+
+:root+:--foo {
+ order: 127;
+}
+
+:--foo + :root {
+ order: 128;
+}
+
+:root + :--foo {
+ order: 129;
+}
+
+:--foo~:root {
+ order: 130;
+}
+
+:root~:--foo {
+ order: 131;
+}
+
+:--foo ~ :root {
+ order: 132;
+}
+
+:root ~ :--foo {
+ order: 133;
+}
+
+:--foo>:root {
+ order: 134;
+}
+
+:root>:--foo {
+ order: 135;
+}
+
+:--foo > :root {
+ order: 136;
+}
+
+:root > :--foo {
+ order: 137;
+}
+
+:--foo, :root {
+ order: 138;
+}
+
+:root, :--foo {
+ order: 139;
+}
+
+[foo="baz"]:root {
+ order: 140;
+}
+
+:root[foo="baz"] {
+ order: 141;
+}
+
+[foo="baz"] :root {
+ order: 142;
+}
+
+:root [foo="baz"] {
+ order: 143;
+}
+
+[foo="baz"] :root {
+ order: 144;
+}
+
+:root [foo="baz"] {
+ order: 145;
+}
+
+[foo="baz"]+:root {
+ order: 146;
+}
+
+:root+[foo="baz"] {
+ order: 147;
+}
+
+[foo="baz"] + :root {
+ order: 148;
+}
+
+:root + [foo="baz"] {
+ order: 149;
+}
+
+[foo="baz"]~:root {
+ order: 150;
+}
+
+:root~[foo="baz"] {
+ order: 151;
+}
+
+[foo="baz"] ~ :root {
+ order: 152;
+}
+
+:root ~ [foo="baz"] {
+ order: 153;
+}
+
+[foo="baz"]>:root {
+ order: 154;
+}
+
+:root>[foo="baz"] {
+ order: 155;
+}
+
+[foo="baz"] > :root {
+ order: 156;
+}
+
+:root > [foo="baz"] {
+ order: 157;
+}
+
+[foo="baz"], :root {
+ order: 158;
+}
+
+:root, [foo="baz"] {
+ order: 159;
+}
+
+*:root {
+ order: 160;
+}
+
+:root* {
+ order: 161;
+}
+
+* :root {
+ order: 162;
+}
+
+:root * {
+ order: 163;
+}
+
+* :root {
+ order: 164;
+}
+
+:root * {
+ order: 165;
+}
+
+*+:root {
+ order: 166;
+}
+
+:root+* {
+ order: 167;
+}
+
+* + :root {
+ order: 168;
+}
+
+:root + * {
+ order: 169;
+}
+
+*~:root {
+ order: 170;
+}
+
+:root~* {
+ order: 171;
+}
+
+* ~ :root {
+ order: 172;
+}
+
+:root ~ * {
+ order: 173;
+}
+
+*>:root {
+ order: 174;
+}
+
+:root>* {
+ order: 175;
+}
+
+* > :root {
+ order: 176;
+}
+
+:root > * {
+ order: 177;
+}
+
+*, :root {
+ order: 178;
+}
+
+:root, * {
+ order: 179;
+}
+
+:hover:root {
+ order: 180;
+}
+
+:root:hover {
+ order: 181;
+}
+
+:hover :root {
+ order: 182;
+}
+
+:root :hover {
+ order: 183;
+}
+
+:hover :root {
+ order: 184;
+}
+
+:root :hover {
+ order: 185;
+}
+
+:hover+:root {
+ order: 186;
+}
+
+:root+:hover {
+ order: 187;
+}
+
+:hover + :root {
+ order: 188;
+}
+
+:root + :hover {
+ order: 189;
+}
+
+:hover~:root {
+ order: 190;
+}
+
+:root~:hover {
+ order: 191;
+}
+
+:hover ~ :root {
+ order: 192;
+}
+
+:root ~ :hover {
+ order: 193;
+}
+
+:hover>:root {
+ order: 194;
+}
+
+:root>:hover {
+ order: 195;
+}
+
+:hover > :root {
+ order: 196;
+}
+
+:root > :hover {
+ order: 197;
+}
+
+:hover, :root {
+ order: 198;
+}
+
+:root, :hover {
+ order: 199;
+}
+
+::before:root {
+ order: 200;
+}
+
+:root::before {
+ order: 201;
+}
+
+::before :root {
+ order: 202;
+}
+
+:root ::before {
+ order: 203;
+}
+
+::before :root {
+ order: 204;
+}
+
+:root ::before {
+ order: 205;
+}
+
+::before+:root {
+ order: 206;
+}
+
+:root+::before {
+ order: 207;
+}
+
+::before + :root {
+ order: 208;
+}
+
+:root + ::before {
+ order: 209;
+}
+
+::before~:root {
+ order: 210;
+}
+
+:root~::before {
+ order: 211;
+}
+
+::before ~ :root {
+ order: 212;
+}
+
+:root ~ ::before {
+ order: 213;
+}
+
+::before>:root {
+ order: 214;
+}
+
+:root>::before {
+ order: 215;
+}
+
+::before > :root {
+ order: 216;
+}
+
+:root > ::before {
+ order: 217;
+}
+
+::before, :root {
+ order: 218;
+}
+
+:root, ::before {
+ order: 219;
+}
+
+foo[:scope] {
+ order: 220;
+}
+
+foo[baz=":scope"] {
+ order: 221;
+}
+
+:not(:root) {
+ order: 222;
+}
+
+::scope {
+ order: 223;
+}
+
+:--:root {
+ order: 224;
+}
+
+__:root {
+ order: 225;
+}
+
+/* :scope */
diff --git a/plugins/postcss-scope-pseudo-class/tsconfig.json b/plugins/postcss-scope-pseudo-class/tsconfig.json
new file mode 100644
index 000000000..e0d06239c
--- /dev/null
+++ b/plugins/postcss-scope-pseudo-class/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "declarationDir": "."
+ },
+ "include": ["./src/**/*"],
+ "exclude": ["dist"],
+}