First version

This commit is contained in:
Senad Uka
2023-07-05 11:02:15 +02:00
parent f21c24b599
commit 8eabf79994
4052 changed files with 723968 additions and 232443 deletions

89
CTOAsYouGo/node_modules/postcss-nested/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,89 @@
# Change Log
This project adheres to [Semantic Versioning](http://semver.org/).
## 4.2.3
* Fixed declarations after nested rule and before at-rule (by Rodion Demikhov).
## 4.2.2
* Fixed wrong specificity order of declarations (by Rodion Demikhov).
## 4.2.1
* Fix TypeScript definitions (by Avi Vahl).
## 4.2
* Add `@at-root` support (by Jason Quense).
## 4.1.2
* Improve error messsage on broken selector
## 4.1.1
* Add `&(:hover)` support (by Ben Delarre).
## 4.1
* Add `unwrap` option.
## 4.0
* Use PostCSS 7 (by Aleks Hudochenkov).
* Remove Node.js 4 support.
## 3.0
* Add `@font-face` to bubbling at-rules (by Valeriy Komlev).
* Add special logic for `@font-face` bubbling (by Phanindra Pydisetty).
* Use PostCSS selector parser 3.0.
## 2.1.2
* Fix replacing multiple `&`.
## 2.1.1
* Fix `:not(&)` support.
## 2.1
* Add `preserveEmpty` option (by Federico Zivolo).
## 2.0.4
* Fix finding `&` in some selectors (by Stepan Mikhaylyuk).
## 2.0.3
* Doesnt replace `&` inside string (by Paul Kiddle).
## 2.0.2
* Fix comments moving regression.
## 2.0.1
* Fix rules order regression (by Dmitry Vibe).
## 2.0
* Use PostCSS 6 API.
## 1.0.1
* Clean up npm package.
## 1.0
* Use PostCSS 5.0 API.
* Do not add spaces to selector in compressed CSS.
* Move nodes with its comment above.
## 0.3.2
* Fix `@supports` at-rule support (by Ben Briggs).
## 0.3.1
* Pass PostCSS Plugin Guidelines.
## 0.3
* Do not unwrap custom at-rules.
* Add `bubble` option to unwrap some custom at-rules.
* Support PostCSS 4.1 API.
* Fix last semicolon after unwrapping.
## 0.2.2
* Module returns function to have common PostCSS API.
## 0.2.1
* Add comma support to selectors unwrap.
## 0.2
* Use PostCSS 4.0.
* Fix indent, when move rules to other parent.
## 0.1
* Initial release.

View File

@@ -2,9 +2,9 @@
<img align="right" width="135" height="95"
title="Philosophers stone, logo of PostCSS"
src="https://postcss.org/logo-leftp.svg">
src="http://postcss.github.io/postcss/logo-leftp.svg">
[PostCSS] plugin to unwrap nested rules closer to Sass syntax.
[PostCSS] plugin to unwrap nested rules like how Sass does it.
```css
.phone {
@@ -27,6 +27,7 @@
@at-root html {
--font: 16px
}
}
}
```
@@ -60,27 +61,111 @@ html {
Related plugins:
* Use [`postcss-current-selector`] **after** this plugin if you want
to use current selector in properties or variables values.
to use current selector in properties or variables values.
* Use [`postcss-nested-ancestors`] **before** this plugin if you want
to reference any ancestor element directly in your selectors with `^&`.
to reference any ancestor element directly in your selectors with `^&`.
Alternatives:
* See also [`postcss-nesting`], which implements [CSSWG draft].
* See also [`postcss-nesting`], which implements [CSSWG draft]
(requires the `&` and introduces `@nest`).
* [`postcss-nested-props`] for nested properties like `font-size`.
<a href="https://evilmartians.com/?utm_source=postcss-nested">
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
alt="Sponsored by Evil Martians" width="236" height="54">
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
</a>
[`postcss-current-selector`]: https://github.com/komlev/postcss-current-selector
[`postcss-nested-ancestors`]: https://github.com/toomuchdesign/postcss-nested-ancestors
[`postcss-nested-props`]: https://github.com/jedmao/postcss-nested-props
[`postcss-nesting`]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
[`postcss-nesting`]: https://github.com/jonathantneal/postcss-nesting
[CSSWG draft]: https://drafts.csswg.org/css-nesting-1/
[PostCSS]: https://github.com/postcss/postcss
## Usage
## Docs
Read full docs **[here](https://github.com/postcss/postcss-nested#readme)**.
```js
postcss([ require('postcss-nested') ])
```
See [PostCSS] docs for examples for your environment.
## Options
### `bubble`
By default, plugin will bubble only `@media` and `@supports` at-rules.
You can add your custom at-rules to this list by `bubble` option:
```js
postcss([ require('postcss-nested')({ bubble: ['phone'] }) ])
```
```css
/* input */
a {
color: white;
@phone {
color: black;
}
}
/* output */
a {
color: white;
}
@phone {
a {
color: black;
}
}
```
### `unwrap`
By default, plugin will unwrap only `@font-face`, `@keyframes` and `@document`
at-rules. You can add your custom at-rules to this list by `unwrap` option:
```js
postcss([ require('postcss-nested')({ unwrap: ['phone'] }) ])
```
```css
/* input */
a {
color: white;
@phone {
color: black;
}
}
/* output */
a {
color: white;
}
@phone {
color: black;
}
```
### `preserveEmpty`
By default, plugin will strip out any empty selector generated by intermediate
nesting levels. You can set `preserveEmpty` to `true` to preserve them.
```css
.a {
.b {
color: black;
}
}
```
Will be compiled to:
```css
.a { }
.a .b {
color: black;
}
```
This is especially useful if you want to export the empty classes with `postcss-modules`.

View File

@@ -1,41 +1,30 @@
// Original definitions (@types/postcss-nested)
// by Maxim Vorontsov <https://github.com/VorontsovMaxim>
// Original definitions (@types/postcss-nested) by Maxim Vorontsov <https://github.com/VorontsovMaxim>
import { PluginCreator } from 'postcss'
import { Plugin } from 'postcss';
declare namespace nested {
interface Options {
/**
* By default, plugin will bubble only `@media`, `@supports` and `@layer`
* at-rules. Use this option to add your custom at-rules to this list.
*/
bubble?: string[]
interface Options {
/**
* By default, plugin will bubble only @media and @supports at-rules.
* You can add your custom at-rules to this list by this option.
*/
bubble?: string[];
/**
* By default, plugin will unwrap only `@font-face`, `@keyframes`,
* and `@document` at-rules. You can add your custom at-rules
* to this list by this option.
*/
unwrap?: string[]
/**
* By default, plugin will unwrap only @font-face, @keyframes and @document at-rules.
* You can add your custom at-rules to this list by this option.
*/
unwrap?: string[];
/**
* By default, plugin will strip out any empty selector generated
* by intermediate nesting levels. You can set this option to `true`
* to preserve them.
*/
preserveEmpty?: boolean
/**
* By default, plugin will strip out any empty selector generated by intermediate nesting
* levels. You can set this option to true to preserve them.
*/
preserveEmpty?: boolean;
}
/**
* The plugin supports the SCSS custom at-rule `@at-root` which breaks
* rule blocks out of their nested position. If you want, you can choose
* a new custom name for this rule in your code.
*/
rootRuleName?: string
}
type Nested = PluginCreator<Options>
type Nested = Plugin<Options>;
}
declare const nested: nested.Nested
export = nested
declare const nested: nested.Nested;
export = nested;

View File

@@ -1,17 +1,15 @@
const { Rule, AtRule } = require('postcss')
let parser = require('postcss-selector-parser')
var postcss = require('postcss')
var parser = require('postcss-selector-parser')
/**
* Run a selector string through postcss-selector-parser
*/
function parse(rawSelector, rule) {
let nodes
function parse (str, rule) {
var nodes
var saver = parser(function (parsed) {
nodes = parsed
})
try {
parser(parsed => {
nodes = parsed
}).processSync(rawSelector)
saver.processSync(str)
} catch (e) {
if (rawSelector.includes(':')) {
if (str.indexOf(':') !== -1) {
throw rule ? rule.error('Missed semicolon') : e
} else {
throw rule ? rule.error(e.message) : e
@@ -20,27 +18,19 @@ function parse(rawSelector, rule) {
return nodes.at(0)
}
/**
* Replaces the "&" token in a node's selector with the parent selector
* similar to what SCSS does.
*
* Mutates the nodes list
*/
function interpolateAmpInSelector(nodes, parent) {
let replaced = false
nodes.each(node => {
if (node.type === 'nesting') {
let clonedParent = parent.clone({})
if (node.value !== '&') {
node.replaceWith(
parse(node.value.replace('&', clonedParent.toString()))
)
function replace (nodes, parent) {
var replaced = false
nodes.each(function (i) {
if (i.type === 'nesting') {
var clonedParent = parent.clone()
if (i.value !== '&') {
i.replaceWith(parse(i.value.replace('&', clonedParent.toString())))
} else {
node.replaceWith(clonedParent)
i.replaceWith(clonedParent)
}
replaced = true
} else if ('nodes' in node && node.nodes) {
if (interpolateAmpInSelector(node, parent)) {
} else if (i.nodes) {
if (replace(i, parent)) {
replaced = true
}
}
@@ -48,314 +38,170 @@ function interpolateAmpInSelector(nodes, parent) {
return replaced
}
/**
* Combines parent and child selectors, in a SCSS-like way
*/
function mergeSelectors(parent, child) {
let merged = []
parent.selectors.forEach(sel => {
let parentNode = parse(sel, parent)
function selectors (parent, child) {
var result = []
parent.selectors.forEach(function (i) {
var parentNode = parse(i, parent)
child.selectors.forEach(selector => {
if (!selector) {
return
}
let node = parse(selector, child)
let replaced = interpolateAmpInSelector(node, parentNode)
child.selectors.forEach(function (j) {
var node = parse(j, child)
var replaced = replace(node, parentNode)
if (!replaced) {
node.prepend(parser.combinator({ value: ' ' }))
node.prepend(parentNode.clone({}))
node.prepend(parentNode.clone())
}
merged.push(node.toString())
result.push(node.toString())
})
})
return merged
return result
}
/**
* Move a child and its preceeding comment(s) to after "after"
*/
function breakOut(child, after) {
let prev = child.prev()
after.after(child)
while (prev && prev.type === 'comment') {
let nextPrev = prev.prev()
after.after(prev)
prev = nextPrev
function pickComment (comment, after) {
if (comment && comment.type === 'comment') {
after.after(comment)
return comment
} else {
return after
}
return child
}
function createFnAtruleChilds(bubble) {
return function atruleChilds(rule, atrule, bubbling, mergeSels = bubbling) {
let children = []
atrule.each(child => {
if (child.type === 'rule' && bubbling) {
if (mergeSels) {
child.selectors = mergeSelectors(rule, child)
}
} else if (child.type === 'atrule' && child.nodes) {
if (bubble[child.name]) {
atruleChilds(rule, child, mergeSels)
} else if (atrule[rootRuleMergeSel] !== false) {
children.push(child)
}
} else {
children.push(child)
}
})
if (bubbling) {
if (children.length) {
let clone = rule.clone({ nodes: [] })
for (let child of children) {
clone.append(child)
}
atrule.prepend(clone)
function atruleChilds (rule, atrule, bubbling) {
var children = []
atrule.each(function (child) {
if (child.type === 'comment') {
children.push(child)
} else if (child.type === 'decl') {
children.push(child)
} else if (child.type === 'rule' && bubbling) {
child.selectors = selectors(rule, child)
} else if (child.type === 'atrule') {
atruleChilds(rule, child, bubbling)
}
})
if (bubbling) {
if (children.length) {
var clone = rule.clone({ nodes: [] })
for (var i = 0; i < children.length; i++) {
clone.append(children[i])
}
atrule.prepend(clone)
}
}
}
function pickDeclarations(selector, declarations, after) {
let parent = new Rule({
selector,
function pickDeclarations (selector, declarations, after) {
var parent = postcss.rule({
selector: selector,
nodes: []
})
parent.append(declarations)
for (var i = 0; i < declarations.length; i++) {
parent.append(declarations[i])
}
after.after(parent)
return parent
}
function atruleNames(defaults, custom) {
let list = {}
for (let name of defaults) {
list[name] = true
function processRule (rule, bubble, unwrap, preserveEmpty) {
var unwrapped = false
var after = rule
var copyDeclarations = false
var declarations = []
rule.each(function (child) {
if (child.type === 'rule') {
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
declarations = []
}
copyDeclarations = true
unwrapped = true
child.selectors = selectors(rule, child)
after = pickComment(child.prev(), after)
after.after(child)
after = child
} else if (child.type === 'atrule') {
copyDeclarations = false
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
declarations = []
}
if (child.name === 'at-root') {
unwrapped = true
atruleChilds(rule, child, false)
var nodes = child.nodes
if (child.params) {
nodes = postcss.rule({
selector: child.params,
nodes: nodes
})
}
after.after(nodes)
after = nodes
child.remove()
} else if (bubble[child.name]) {
unwrapped = true
atruleChilds(rule, child, true)
after = pickComment(child.prev(), after)
after.after(child)
after = child
} else if (unwrap[child.name]) {
unwrapped = true
atruleChilds(rule, child, false)
after = pickComment(child.prev(), after)
after.after(child)
after = child
}
} else if (child.type === 'decl' && copyDeclarations) {
declarations.push(child)
}
})
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
}
if (unwrapped && preserveEmpty !== true) {
rule.raws.semicolon = true
if (rule.nodes.length === 0) rule.remove()
}
}
function atruleNames (defaults, custom) {
var list = { }
var i, name
for (i = 0; i < defaults.length; i++) {
list[defaults[i]] = true
}
if (custom) {
for (let name of custom) {
list[name.replace(/^@/, '')] = true
for (i = 0; i < custom.length; i++) {
name = custom[i].replace(/^@/, '')
list[name] = true
}
}
return list
}
function parseRootRuleParams(params) {
params = params.trim()
let braceBlock = params.match(/^\((.*)\)$/)
if (!braceBlock) {
return { type: 'basic', selector: params }
}
let bits = braceBlock[1].match(/^(with(?:out)?):(.+)$/)
if (bits) {
let allowlist = bits[1] === 'with'
let rules = Object.fromEntries(
bits[2]
.trim()
.split(/\s+/)
.map(name => [name, true])
)
if (allowlist && rules.all) {
return { type: 'noop' }
}
let escapes = rule => !!rules[rule]
if (rules.all) {
escapes = () => true
} else if (allowlist) {
escapes = rule => (rule === 'all' ? false : !rules[rule])
}
module.exports = postcss.plugin('postcss-nested', function (opts) {
if (!opts) opts = { }
var bubble = atruleNames(['media', 'supports'], opts.bubble)
var unwrap = atruleNames(['document', 'font-face', 'keyframes'], opts.unwrap)
var preserveEmpty = opts ? opts.preserveEmpty : false
return {
type: 'withrules',
escapes
}
}
// Unrecognized brace block
return { type: 'unknown' }
}
function getAncestorRules(leaf) {
let lineage = []
let parent = leaf.parent
while (parent && parent instanceof AtRule) {
lineage.push(parent)
parent = parent.parent
}
return lineage
}
function unwrapRootRule(rule) {
let escapes = rule[rootRuleEscapes]
if (!escapes) {
rule.after(rule.nodes)
} else {
let nodes = rule.nodes
let topEscaped
let topEscapedIdx = -1
let breakoutLeaf
let breakoutRoot
let clone
let lineage = getAncestorRules(rule)
lineage.forEach((parent, i) => {
if (escapes(parent.name)) {
topEscaped = parent
topEscapedIdx = i
breakoutRoot = clone
} else {
let oldClone = clone
clone = parent.clone({ nodes: [] })
oldClone && clone.append(oldClone)
breakoutLeaf = breakoutLeaf || clone
var process = function (node) {
node.each(function (child) {
if (child.type === 'rule') {
processRule(child, bubble, unwrap, preserveEmpty)
} else if (child.type === 'atrule') {
process(child)
}
})
if (!topEscaped) {
rule.after(nodes)
} else if (!breakoutRoot) {
topEscaped.after(nodes)
} else {
let leaf = breakoutLeaf
leaf.append(nodes)
topEscaped.after(breakoutRoot)
}
if (rule.next() && topEscaped) {
let restRoot
lineage.slice(0, topEscapedIdx + 1).forEach((parent, i, arr) => {
let oldRoot = restRoot
restRoot = parent.clone({ nodes: [] })
oldRoot && restRoot.append(oldRoot)
let nextSibs = []
let _child = arr[i - 1] || rule
let next = _child.next()
while (next) {
nextSibs.push(next)
next = next.next()
}
restRoot.append(nextSibs)
})
restRoot && (breakoutRoot || nodes[nodes.length - 1]).after(restRoot)
}
}
rule.remove()
}
const rootRuleMergeSel = Symbol('rootRuleMergeSel')
const rootRuleEscapes = Symbol('rootRuleEscapes')
function normalizeRootRule(rule) {
let { params } = rule
let { type, selector, escapes } = parseRootRuleParams(params)
if (type === 'unknown') {
throw rule.error(
`Unknown @${rule.name} parameter ${JSON.stringify(params)}`
)
}
if (type === 'basic' && selector) {
let selectorBlock = new Rule({ selector, nodes: rule.nodes })
rule.removeAll()
rule.append(selectorBlock)
}
rule[rootRuleEscapes] = escapes
rule[rootRuleMergeSel] = escapes ? !escapes('all') : type === 'noop'
}
const hasRootRule = Symbol('hasRootRule')
module.exports = (opts = {}) => {
let bubble = atruleNames(
['media', 'supports', 'layer', 'container'],
opts.bubble
)
let atruleChilds = createFnAtruleChilds(bubble)
let unwrap = atruleNames(
[
'document',
'font-face',
'keyframes',
'-webkit-keyframes',
'-moz-keyframes'
],
opts.unwrap
)
let rootRuleName = (opts.rootRuleName || 'at-root').replace(/^@/, '')
let preserveEmpty = opts.preserveEmpty
return {
postcssPlugin: 'postcss-nested',
Once(root) {
root.walkAtRules(rootRuleName, node => {
normalizeRootRule(node)
root[hasRootRule] = true
})
},
Rule(rule) {
let unwrapped = false
let after = rule
let copyDeclarations = false
let declarations = []
rule.each(child => {
if (child.type === 'rule') {
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
declarations = []
}
copyDeclarations = true
unwrapped = true
child.selectors = mergeSelectors(rule, child)
after = breakOut(child, after)
} else if (child.type === 'atrule') {
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
declarations = []
}
if (child.name === rootRuleName) {
unwrapped = true
atruleChilds(rule, child, true, child[rootRuleMergeSel])
after = breakOut(child, after)
} else if (bubble[child.name]) {
copyDeclarations = true
unwrapped = true
atruleChilds(rule, child, true)
after = breakOut(child, after)
} else if (unwrap[child.name]) {
copyDeclarations = true
unwrapped = true
atruleChilds(rule, child, false)
after = breakOut(child, after)
} else if (copyDeclarations) {
declarations.push(child)
}
} else if (child.type === 'decl' && copyDeclarations) {
declarations.push(child)
}
})
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
}
if (unwrapped && preserveEmpty !== true) {
rule.raws.semicolon = true
if (rule.nodes.length === 0) rule.remove()
}
},
RootExit(root) {
if (root[hasRootRule]) {
root.walkAtRules(rootRuleName, unwrapRootRule)
root[hasRootRule] = false
}
}
}
}
module.exports.postcss = true
return process
})

View File

@@ -1,6 +1,6 @@
{
"name": "postcss-nested",
"version": "6.0.1",
"version": "4.2.3",
"description": "PostCSS plugin to unwrap nested rules like how Sass does it",
"keywords": [
"postcss",
@@ -12,17 +12,8 @@
"author": "Andrey Sitnik <andrey@sitnik.ru>",
"license": "MIT",
"repository": "postcss/postcss-nested",
"engines": {
"node": ">=12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.2.14"
},
"dependencies": {
"postcss-selector-parser": "^6.0.11"
"postcss": "^7.0.32",
"postcss-selector-parser": "^6.0.2"
}
}