Skip to content

Commit

Permalink
Use PostCSS 8
Browse files Browse the repository at this point in the history
  • Loading branch information
ai committed Aug 24, 2020
1 parent 1773972 commit 1a4fbd9
Show file tree
Hide file tree
Showing 9 changed files with 2,860 additions and 1,445 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
coverage/
node_modules/
npm-debug.log
yarn-error.log

coverage/
8 changes: 2 additions & 6 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
.editorconfig

node_modules/
npm-debug.log
yarn-error.log
yarn.lock

coverage/
*.test.js
.travis.yml
coverage/
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,3 @@ node_js:
- node
- "12"
- "10"
- "8"
- "6"
install:
- yarn install --ignore-engines
29 changes: 24 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<img align="right" width="135" height="95"
title="Philosopher’s stone, logo of PostCSS"
src="http://postcss.github.io/postcss/logo-leftp.svg">
src="https://postcss.org/logo-leftp.svg">

[PostCSS] plugin to unwrap nested rules like how Sass does it.

Expand Down Expand Up @@ -72,7 +72,8 @@ Alternatives:
* [`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
Expand All @@ -82,13 +83,29 @@ Alternatives:
[CSSWG draft]: https://drafts.csswg.org/css-nesting-1/
[PostCSS]: https://github.com/postcss/postcss


## Usage

```js
postcss([ require('postcss-nested') ])
**Step 1:** Check you project for existed PostCSS config: `postcss.config.js`
in the project root, `"postcss"` section in `package.json`
or `postcss` in bundle config.

If you do not use PostCSS, add it according to [official docs]
and set this plugin in settings.

**Step 2:** Add the plugin to plugins list:

```diff
module.exports = {
plugins: [
+ require('postcss-nested'),
require('autoprefixer')
]
}
```

See [PostCSS] docs for examples for your environment.
[official docs]: https://github.com/postcss/postcss#usage


## Options

Expand Down Expand Up @@ -120,6 +137,7 @@ a {
}
```


### `unwrap`

By default, plugin will unwrap only `@font-face`, `@keyframes` and `@document`
Expand All @@ -146,6 +164,7 @@ a {
}
```


### `preserveEmpty`

By default, plugin will strip out any empty selector generated by intermediate
Expand Down
38 changes: 19 additions & 19 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
// Original definitions (@types/postcss-nested) by Maxim Vorontsov <https://github.com/VorontsovMaxim>

import { Plugin } from 'postcss';
import { PluginCreator } from 'postcss';

declare namespace nested {
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[];
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;
}

type Nested = Plugin<Options>;
type Nested = PluginCreator<Options>;
}

declare const nested: nested.Nested;
Expand Down
118 changes: 59 additions & 59 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
var postcss = require('postcss')
var parser = require('postcss-selector-parser')
let parser = require('postcss-selector-parser')

function parse (str, rule) {
var nodes
var saver = parser(function (parsed) {
let nodes
let saver = parser(parsed => {
nodes = parsed
})
try {
saver.processSync(str)
} catch (e) {
if (str.indexOf(':') !== -1) {
if (str.includes(':')) {
throw rule ? rule.error('Missed semicolon') : e
} else {
throw rule ? rule.error(e.message) : e
Expand All @@ -19,10 +18,10 @@ function parse (str, rule) {
}

function replace (nodes, parent) {
var replaced = false
nodes.each(function (i) {
let replaced = false
nodes.each(i => {
if (i.type === 'nesting') {
var clonedParent = parent.clone()
let clonedParent = parent.clone()
if (i.value !== '&') {
i.replaceWith(parse(i.value.replace('&', clonedParent.toString())))
} else {
Expand All @@ -39,13 +38,13 @@ function replace (nodes, parent) {
}

function selectors (parent, child) {
var result = []
parent.selectors.forEach(function (i) {
var parentNode = parse(i, parent)
let result = []
parent.selectors.forEach(i => {
let parentNode = parse(i, parent)

child.selectors.forEach(function (j) {
var node = parse(j, child)
var replaced = replace(node, parentNode)
child.selectors.forEach(j => {
let node = parse(j, child)
let replaced = replace(node, parentNode)
if (!replaced) {
node.prepend(parser.combinator({ value: ' ' }))
node.prepend(parentNode.clone())
Expand All @@ -66,8 +65,8 @@ function pickComment (comment, after) {
}

function atruleChilds (rule, atrule, bubbling) {
var children = []
atrule.each(function (child) {
let children = []
atrule.each(child => {
if (child.type === 'comment') {
children.push(child)
} else if (child.type === 'decl') {
Expand All @@ -80,39 +79,39 @@ function atruleChilds (rule, atrule, bubbling) {
})
if (bubbling) {
if (children.length) {
var clone = rule.clone({ nodes: [] })
for (var i = 0; i < children.length; i++) {
clone.append(children[i])
let clone = rule.clone({ nodes: [] })
for (let child of children) {
clone.append(child)
}
atrule.prepend(clone)
}
}
}

function pickDeclarations (selector, declarations, after) {
var parent = postcss.rule({
selector: selector,
function pickDeclarations (selector, declarations, after, Rule) {
let parent = new Rule({
selector,
nodes: []
})

for (var i = 0; i < declarations.length; i++) {
parent.append(declarations[i])
for (let declaration of declarations) {
parent.append(declaration)
}

after.after(parent)
return parent
}

function processRule (rule, bubble, unwrap, preserveEmpty) {
var unwrapped = false
var after = rule
var copyDeclarations = false
var declarations = []
function processRule (rule, bubble, unwrap, preserveEmpty, Rule) {
let unwrapped = false
let after = rule
let copyDeclarations = false
let declarations = []

rule.each(function (child) {
rule.each(child => {
if (child.type === 'rule') {
if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
after = pickDeclarations(rule.selector, declarations, after, Rule)
declarations = []
}

Expand All @@ -126,20 +125,17 @@ function processRule (rule, bubble, unwrap, preserveEmpty) {
copyDeclarations = false

if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
after = pickDeclarations(rule.selector, declarations, after, Rule)
declarations = []
}

if (child.name === 'at-root') {
unwrapped = true
atruleChilds(rule, child, false)

var nodes = child.nodes
let nodes = child.nodes
if (child.params) {
nodes = postcss.rule({
selector: child.params,
nodes: nodes
})
nodes = new Rule({ selector: child.params, nodes })
}

after.after(nodes)
Expand All @@ -164,7 +160,7 @@ function processRule (rule, bubble, unwrap, preserveEmpty) {
})

if (declarations.length) {
after = pickDeclarations(rule.selector, declarations, after)
after = pickDeclarations(rule.selector, declarations, after, Rule)
}

if (unwrapped && preserveEmpty !== true) {
Expand All @@ -174,34 +170,38 @@ function processRule (rule, bubble, unwrap, preserveEmpty) {
}

function atruleNames (defaults, custom) {
var list = { }
var i, name
for (i = 0; i < defaults.length; i++) {
list[defaults[i]] = true
let list = {}
for (let i of defaults) {
list[i] = true
}
if (custom) {
for (i = 0; i < custom.length; i++) {
name = custom[i].replace(/^@/, '')
for (let i of custom) {
let name = i.replace(/^@/, '')
list[name] = true
}
}
return list
}

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

var process = function (node) {
node.each(function (child) {
if (child.type === 'rule') {
processRule(child, bubble, unwrap, preserveEmpty)
} else if (child.type === 'atrule') {
process(child)
module.exports = (opts = {}) => {
let bubble = atruleNames(['media', 'supports'], opts.bubble)
let unwrap = atruleNames(['document', 'font-face', 'keyframes'], opts.unwrap)
let preserveEmpty = opts.preserveEmpty

return {
postcssPlugin: 'postcss-nested',
Root (root, { Rule }) {
let process = function (node) {
node.each(child => {
if (child.type === 'rule') {
processRule(child, bubble, unwrap, preserveEmpty, Rule)
} else if (child.type === 'atrule') {
process(child)
}
})
}
})
process(root)
}
}
return process
})
}
module.exports.postcss = true
Loading

0 comments on commit 1a4fbd9

Please sign in to comment.