Code Monkey home page Code Monkey logo

postcss-sorting's Introduction

PostCSS Sorting

npm version npm downloads last month

PostCSS plugin to keep rules and at-rules content in order.

Lint and autofix stylesheet order with stylelint-order.

Features

  • Sorts rules and at-rules content.
  • Sorts properties.
  • Sorts at-rules by different options.
  • Groups properties, custom properties, dollar variables, nested rules, nested at-rules.
  • Supports CSS, SCSS (using postcss-scss), CSS-in-JS (with postcss-styled-syntax), HTML (with postcss-html), and most likely any other syntax added by other PostCSS plugins.

Installation

npm install --save-dev postcss postcss-sorting

Options

The plugin has no default options. Everything is disabled by default.

  • order: Specify the order of content within declaration blocks.
  • properties-order: Specify the order of properties within declaration blocks.
  • unspecified-properties-position: Specify position for properties not specified in properties-order.
  • throw-validate-errors: Throw config validation errors instead of showing and ignoring them. Defaults to false.

Caveats

Handling comments

Comments that are before node and on a separate line linked to that node. Shared-line comments are also linked to that node. Shared-line comments are comments which are located after a node and on the same line as a node.

a {
	top: 5px; /* shared-line comment belongs to `top` */
	/* comment belongs to `bottom` */
	/* comment belongs to `bottom` */
	bottom: 15px; /* shared-line comment belongs to `bottom` */
}

Ignored at-rules

Some at-rules, like control and function directives in Sass, are ignored. It means rules won't touch content inside these at-rules, as doing so could change or break functionality.

CSS-in-JS

Plugin will ignore rules, which have template literal interpolation, to avoid breaking the logic:

const Component = styled.div`
	/* The following properties WILL NOT be sorted, because interpolation is on properties level */
	z-index: 1;
	top: 1px;
	${props => props.great && 'color: red'};
	position: absolute;
	display: block;

	div {
		/* The following properties WILL be sorted, because interpolation for property value only */
		z-index: 2;
		position: static;
		top: ${2 + 10}px;
		display: inline-block;
	}
`;

Usage

See PostCSS docs for more examples.

Command Line

Add postcss-cli and PostCSS Sorting to your project:

npm install postcss postcss-cli postcss-sorting --save-dev

Create a postcss.config.js with PostCSS Sorting configuration:

module.exports = {
	plugins: {
		'postcss-sorting': {
			order: [
				'custom-properties',
				'dollar-variables',
				'declarations',
				'at-rules',
				'rules',
			],

			'properties-order': 'alphabetical',

			'unspecified-properties-position': 'bottom',
		},
	},
};

Or, add the 'postcss-sorting' section to your existing postcss-cli configuration file.

Next execute:

npx postcss --no-map --replace your-css-file.css

For more information and options, please consult the postcss-cli docs.

Gulp

Add gulp-postcss and PostCSS Sorting to your build tool:

npm install postcss gulp-postcss postcss-sorting --save-dev

Enable PostCSS Sorting within your Gulpfile:

let gulp = require('gulp');
let postcss = require('gulp-postcss');
let sorting = require('postcss-sorting');

exports['sort-css'] = () => {
	return gulp
		.src('./css/src/*.css')
		.pipe(
			postcss([
				sorting({
					/* options */
				}),
			])
		)
		.pipe(gulp.dest('./css/src'));
};

Text editor

This plugin available as Sublime Text, Atom, VS Code, and Emacs plugin. Though, seems all these plugins are not maintained.

Related tools

stylelint and stylelint-order help lint stylesheets and let you know if stylesheet order is correct. Also, they could autofix stylesheets.

I recommend Prettier for formatting stylesheets.

postcss-sorting's People

Contributors

darkpreacher avatar dependabot[bot] avatar developering avatar hudochenkov avatar jamesarosen avatar junebugfix avatar karlhorky avatar notatestuser avatar pawelgrzybek avatar redknife avatar tohuw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

postcss-sorting's Issues

Error: module.js:339

The settings in v2.0.0 (default and user) are updated to:

{
    "order": [
        "custom-properties",
        "dollar-variables",
        "declarations",
        "at-rules",
        {
            "type": "at-rule",
            "name": "include"
        },
        {
            "type": "at-rule",
            "name": "include",
            "parameter": "icon"
        },
        "rules"
    ],
    "properties-order": [
        {
            "emptyLineBefore": true,
            "properties": [
                "margin",
                "padding"
            ]
        },
        {
            "emptyLineBefore": true,
            "properties": [
                "border",
                "background"
            ]
        }
    ],
    "unspecified-properties-position": "bottom"
}

If I run PostCSS, it throws an error:

PostCSS Sorting
Error: module.js:339
    throw err;
    ^

Error: Cannot find module './terminal-highlight'
    at Function.Module._resolveFilename (module.js:337:15)
    at Function.Module._load (module.js:287:25)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at Object.<anonymous> (/Users/pl/Library/Application Support/Sublime Text 3/Packages/PostCSS Sorting/node_modules/postcss/lib/css-syntax-error.js:15:26)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Module.require (module.js:366:17)

How can this be solved?

Feature request: Add label to grouping config which adds a comment above the group

Example Input:

.element {
    display: flex;
    border: 1px solid red;
    color: red;
    margin: 10px;
    flex: 1;
    padding: 10px;
    position: absolute;
    box-shadow: ...
}

Example Output:

.element {
    // layout styles
    display: flex;
    flex: 1;
    position: absolute;

    // structural styles
    margin: 10px;
    padding: 10px;

    // visual styles
    color: red
    border: 1px solid red;
    box-shadow: ....
}

This would make it substantially easier for new team members to understand why we've sorted things the way we have, which would make the style sheets more navigable in general.

Wrong position variables in function SCSS

Input:

@function _linear-positions-parser($pos) {
  $type: type-of(nth($pos, 1));
  $spec: null;
  $degree: null;
  $side: null;
  $corner: null;
  $length: length($pos);
  // Parse Side and corner positions
  @if ($length > 1) {
    @if nth($pos, 1) == "to" { // Newer syntax
      $side: nth($pos, 2);

      @if $length == 2 { // eg. to top
        // Swap for backwards compatibility
        $degree: _position-flipper(nth($pos, 2));
      }
      @else if $length == 3 { // eg. to top left
        $corner: nth($pos, 3);
      }
    }
    @else if $length == 2 { // Older syntax ("top left")
      $side: _position-flipper(nth($pos, 1));
      $corner: _position-flipper(nth($pos, 2));
    }

    @if ("#{$side} #{$corner}" == "left top") or ("#{$side} #{$corner}" == "top left") {
      $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
    }
    @else if ("#{$side} #{$corner}" == "right top") or ("#{$side} #{$corner}" == "top right") {
      $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
    }
    @else if ("#{$side} #{$corner}" == "right bottom") or ("#{$side} #{$corner}" == "bottom right") {
      $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
    }
    @else if ("#{$side} #{$corner}" == "left bottom") or ("#{$side} #{$corner}" == "bottom left") {
      $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
    }
    $spec: to $side $corner;
  }
  @else if $length == 1 {
    // Swap for backwards compatibility
    @if $type == string {
      $degree: $pos;
      $spec: to _position-flipper($pos);
    }
    @else {
      $degree: -270 - $pos; //rotate the gradient opposite from spec
      $spec: $pos;
    }
  }
  $degree: unquote($degree + ",");
  $spec:   unquote($spec + ",");
  @return $degree $spec;
}

@function _position-flipper($pos) {
  @return if($pos == left, right, null)
         if($pos == right, left, null)
         if($pos == top, bottom, null)
         if($pos == bottom, top, null);
}

Output:

@function _linear-positions-parser($pos) {
    $type: type-of(nth($pos, 1));
    $spec: null;
    $degree: null;
    $side: null;
    $corner: null;
    $length: length($pos);
    $degree: unquote($degree + ",");
    $spec: unquote($spec + ",");

    // Parse Side and corner positions

    @if ($length > 1) {
        $spec: to $side $corner;

        @if nth($pos, 1) == "to" {
            // Newer syntax
            $side: nth($pos, 2);

            @if $length == 2 {
                // eg. to top// Swap for backwards compatibility
                $degree: _position-flipper(nth($pos, 2));
            }

            @else if $length == 3 {
                // eg. to top left
                $corner: nth($pos, 3);
            }
        }

        @else if $length == 2 {
            // Older syntax ("top left")
            $side: _position-flipper(nth($pos, 1));
            $corner: _position-flipper(nth($pos, 2));
        }

        @if ("#{$side} #{$corner}" == "left top") or ("#{$side} #{$corner}" == "top left") {
            $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
        }

        @else if ("#{$side} #{$corner}" == "right top") or ("#{$side} #{$corner}" == "top right") {
            $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
        }

        @else if ("#{$side} #{$corner}" == "right bottom") or ("#{$side} #{$corner}" == "bottom right") {
            $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
        }

        @else if ("#{$side} #{$corner}" == "left bottom") or ("#{$side} #{$corner}" == "bottom left") {
            $degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
        }
    }

    @else if $length == 1 {
        // Swap for backwards compatibility

        @if $type == string {
            $degree: $pos;
            $spec: to _position-flipper($pos);
        }

        @else {
            $degree: -270 - $pos; //rotate the gradient opposite from spec
            $spec: $pos;
        }
    }
    @return $degree $spec;
}

@function _position-flipper($pos) {
    @return if($pos == left, right, null)
         if($pos == right, left, null)
         if($pos == top, bottom, null)
         if($pos == bottom, top, null);
}

Wrong positions: $degree: unquote($degree + ","); $spec: unquote($spec + ",");

Sort by length

Hello,

I would like to share with you the way I sort my CSS properties:
I sort my CSS properties by length:

Wrong:

.accessibility {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}

Good:

.accessibility {
    clip: rect(0 0 0 0);
    position: absolute;
    overflow: hidden;
    margin: -1px;
    height: 1px;
    padding: 0;
    width: 1px;
    border: 0;
}

postcss-sorting should support this 👍 #

Thanks :)

@if @else

Hi,

is there a way to keep @else in the same line as the closing bracket of the @if statement? I want to avoid following behavior.

Before (should stay like this and not turn into what is shown in After):

.foo {
  @if $bar == 'white' {
    color: white;
  } @else {
    color: black;
  }
}

After:

.foo {
  @if $bar == 'white' {
    color: white;
  }

 @else {
    color: black;
  }
}

My settings:

{
  "at-rule-nested-empty-line-before": [true, {
    "except": ["blockless-after-same-name-blockless", "first-nested"],
    "ignore": ["after-comment", "blockless-after-same-name-blockless"]
  }],
  "clean-empty-lines": true,
  "comment-empty-line-before": [true, {
    "except": ["first-nested"],
    "ignore": ["after-comment", "stylelint-command"]
  }],
  "custom-property-empty-line-before": [true, {
    "except": ["after-comment", "after-custom-property", "first-nested"],
    "ignore": ["after-comment", "inside-single-line-block"]
  }],
  "declaration-empty-line-before": [true, {
    "except": ["after-comment", "after-declaration", "first-nested"],
    "ignore": ["after-comment", "after-declaration", "inside-single-line-block"]
  }],
  "dollar-variable-empty-line-before": [true, {
    "except": ["after-comment", "after-dollar-variable", "first-nested"],
    "ignore": ["after-comment", "inside-single-line-block"]
  }],
  "rule-nested-empty-line-before": ["always-multi-line", {
    "except": ["first-nested"],
    "ignore": ["after-comment"]
  }],
  "order": [
    "custom-properties",
    "dollar-variables",
    {
      "type": "at-rule",
      "name": "extend"
    },
    {
      "type": "at-rule",
      "name": "include"
    },
    {
      "type": "at-rule",
      "name": "include",
      "hasBlock": true
    },
    {
      "type": "at-rule",
      "hasBlock": true
    },
    {
      "type": "at-rule"
    },
    "at-rules",
    "declarations",
    "rules",
    {
      "type": "at-rule",
      "name": "media"
    },
    {
      "type": "at-rule",
      "name": "include",
      "parameter" : "breakpoint"
    }
  ]
}

Empty lines between @media rules

I have such config ( means large array of ordered properties):

{
  "empty-lines-between-children-rules": 1,
  "sort-order": [
    [
      "@mixin"
    ],
    [
      …
    ],
    [
      "@media"
    ],
    [
      ">child"
    ]
  ]
}

This config in action:

.color {
  @mixin coloring;

  color: white;

  @media (--viewport-md) {
    color: green;
  }
  @media (--viewport-lg) {
    color: red;
  }

  span {
    color: black;
  }

  span {
    color: pink;
  }
}

Is it possible to add an empty line between @media constructions too, like between spans?

group.forEach is not a function

Trying to format this CSS:

.upload-requirements {
    margin: 10px;
}

Using https://github.com/gajus/stylelint-config-canonical (v1.0.2) config, gives an error:

TypeError: group.forEach is not a function
    at /Users/gajus/Documents/dev/applaudience/static-upload-app/static-upload-app-web/src/client/node_modules/postcss-sorting/index.js:44:10
    at Array.forEach (native)
    at getSortOrderFromOptions (/Users/gajus/Documents/dev/applaudience/static-upload-app/static-upload-app-web/src/client/node_modules/postcss-sorting/index.js:43:4)
    at /Users/gajus/Documents/dev/applaudience/static-upload-app/static-upload-app-web/src/client/node_modules/postcss-sorting/index.js:231:15
    at formatOrder (/Users/gajus/Documents/dev/applaudience/static-upload-app/static-upload-app-web/src/client/node_modules/stylefmt/lib/formatOrder.js:13:3)
    at /Users/gajus/Documents/dev/applaudience/static-upload-app/static-upload-app-web/src/client/node_modules/stylefmt/index.js:19:7

Upon inspection, sortOrder is:

[{"properties":["composes"]},{"properties":["font","font-family","font-size","font-weight","font-style","font-variant","font-size-adjust","font-stretch","font-effect","font-emphasize","font-emphasize-position","font-emphasize-style","font-smooth","line-height"]},{"properties":["position","z-index","top","right","bottom","left"]},{"properties":["display","visibility","float","clear","overflow","overflow-x","overflow-y","clip","zoom","flex-direction","flex-order","flex-pack","flex-align"]},{"properties":["box-sizing","width","min-width","max-width","height","min-height","max-height","margin","margin-top","margin-right","margin-bottom","margin-left","padding","padding-top","padding-right","padding-bottom","padding-left"]},{"properties":["table-layout","empty-cells","caption-side","border-spacing","border-collapse","list-style","list-style-position","list-style-type","list-style-image"]},{"properties":["content","quotes","counter-reset","counter-increment","resize","cursor","user-select","nav-index","nav-up","nav-right","nav-down","nav-left","transition","transition-delay","transition-timing-function","transition-duration","transition-property","transform","transform-origin","animation","animation-name","animation-duration","animation-play-state","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","text-align","text-align-last","vertical-align","white-space","text-decoration","text-emphasis","text-emphasis-color","text-emphasis-style","text-emphasis-position","text-indent","text-justify","letter-spacing","word-spacing","text-outline","text-transform","text-wrap","text-overflow","text-overflow-ellipsis","text-overflow-mode","word-wrap","word-break","tab-size","hyphens","pointer-events"]},{"properties":["opacity","color","border","border-width","border-style","border-color","border-top","border-top-width","border-top-style","border-top-color","border-right","border-right-width","border-right-style","border-right-color","border-bottom","border-bottom-width","border-bottom-style","border-bottom-color","border-left","border-left-width","border-left-style","border-left-color","border-radius","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius","border-image","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat","outline","outline-width","outline-style","outline-color","outline-offset","background","background-color","background-image","background-repeat","background-attachment","background-position","background-position-x","background-position-y","background-clip","background-origin","background-size","box-decoration-break","box-shadow","text-shadow"]}]

This does not look like an expected format.

Regardless, the input format meeds the schema defined in https://github.com/stylelint/stylelint/blob/master/src/rules/declaration-block-properties-order/README.md

Add CLI

Is this really need?

What name to use? $ postcss-sorting?

Why media queries at the bottom?

When I write something like this:

.dashboard-content {

     padding: 10px;

     @media(min width: 1024px) {
          padding: 20px;
     }

    &--no-padding {
        padding: 0;
    }
}

For some reason it will be sorted to this:

.dashboard-content {

     padding: 10px;

    &--no-padding {
        padding: 0;
    }


     @media(min width: 1024px) {
          padding: 20px;
     }
}

In this case modifier no-padding doesn't apply because media query overwrite the modifier. How to fix that?

My config is:

{
    "empty-lines-between-children-rules": 1,
    "sort-order": [
        [
            "position",
            "z-index",
            "top",
            "right",
            "bottom",
            "left"
        ],
        [
            "display",
            "visibility",
            "float",
            "clear",
            "overflow",
            "overflow-x",
            "overflow-y",
            "-ms-overflow-x",
            "-ms-overflow-y",
            "-webkit-overflow-scrolling",
            "clip",
            "zoom",
            "flex-direction",
            "flex-order",
            "flex-pack",
            "flex-align"
        ],
        [
            "-webkit-box-sizing",
            "-moz-box-sizing",
            "box-sizing",
            "width",
            "min-width",
            "max-width",
            "height",
            "min-height",
            "max-height",
            "margin",
            "margin-top",
            "margin-right",
            "margin-bottom",
            "margin-left",
            "padding",
            "padding-top",
            "padding-right",
            "padding-bottom",
            "padding-left"
        ],
        [
            "table-layout",
            "empty-cells",
            "caption-side",
            "border-spacing",
            "border-collapse",
            "list-style",
            "list-style-position",
            "list-style-type",
            "list-style-image"
        ],
        [
            "content",
            "quotes",
            "counter-reset",
            "counter-increment",
            "resize",
            "cursor",
            "-webkit-user-select",
            "-moz-user-select",
            "-ms-user-select",
            "user-select",
            "nav-index",
            "nav-up",
            "nav-right",
            "nav-down",
            "nav-left",
            "-webkit-transition",
            "-moz-transition",
            "-ms-transition",
            "-o-transition",
            "transition",
            "-webkit-transition-delay",
            "-moz-transition-delay",
            "-ms-transition-delay",
            "-o-transition-delay",
            "transition-delay",
            "-webkit-transition-timing-function",
            "-moz-transition-timing-function",
            "-ms-transition-timing-function",
            "-o-transition-timing-function",
            "transition-timing-function",
            "-webkit-transition-duration",
            "-moz-transition-duration",
            "-ms-transition-duration",
            "-o-transition-duration",
            "transition-duration",
            "-webkit-transition-property",
            "-moz-transition-property",
            "-ms-transition-property",
            "-o-transition-property",
            "transition-property",
            "-webkit-transform",
            "-moz-transform",
            "-ms-transform",
            "-o-transform",
            "transform",
            "-webkit-transform-origin",
            "-moz-transform-origin",
            "-ms-transform-origin",
            "-o-transform-origin",
            "transform-origin",
            "-webkit-animation",
            "-moz-animation",
            "-ms-animation",
            "-o-animation",
            "animation",
            "-webkit-animation-name",
            "-moz-animation-name",
            "-ms-animation-name",
            "-o-animation-name",
            "animation-name",
            "-webkit-animation-duration",
            "-moz-animation-duration",
            "-ms-animation-duration",
            "-o-animation-duration",
            "animation-duration",
            "-webkit-animation-play-state",
            "-moz-animation-play-state",
            "-ms-animation-play-state",
            "-o-animation-play-state",
            "animation-play-state",
            "-webkit-animation-timing-function",
            "-moz-animation-timing-function",
            "-ms-animation-timing-function",
            "-o-animation-timing-function",
            "animation-timing-function",
            "-webkit-animation-delay",
            "-moz-animation-delay",
            "-ms-animation-delay",
            "-o-animation-delay",
            "animation-delay",
            "-webkit-animation-iteration-count",
            "-moz-animation-iteration-count",
            "-ms-animation-iteration-count",
            "-o-animation-iteration-count",
            "animation-iteration-count",
            "-webkit-animation-iteration-count",
            "-moz-animation-iteration-count",
            "-ms-animation-iteration-count",
            "-o-animation-iteration-count",
            "animation-iteration-count",
            "-webkit-animation-direction",
            "-moz-animation-direction",
            "-ms-animation-direction",
            "-o-animation-direction",
            "animation-direction",
            "text-align",
            "-webkit-text-align-last",
            "-moz-text-align-last",
            "-ms-text-align-last",
            "text-align-last",
            "vertical-align",
            "white-space",
            "text-decoration",
            "text-emphasis",
            "text-emphasis-color",
            "text-emphasis-style",
            "text-emphasis-position",
            "text-indent",
            "-ms-text-justify",
            "text-justify",
            "text-transform",
            "letter-spacing",
            "word-spacing",
            "-ms-writing-mode",
            "text-outline",
            "text-transform",
            "text-wrap",
            "text-overflow",
            "-ms-text-overflow",
            "text-overflow-ellipsis",
            "text-overflow-mode",
            "-ms-word-wrap",
            "word-wrap",
            "word-break",
            "-ms-word-break",
            "-moz-tab-size",
            "-o-tab-size",
            "tab-size",
            "-webkit-hyphens",
            "-moz-hyphens",
            "hyphens",
            "pointer-events"
        ],
        [
            "opacity",
            "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity",
            "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha",
            "-ms-interpolation-mode",
            "color",
            "border",
            "border-collapse",
            "border-width",
            "border-style",
            "border-color",
            "border-top",
            "border-top-width",
            "border-top-style",
            "border-top-color",
            "border-right",
            "border-right-width",
            "border-right-style",
            "border-right-color",
            "border-bottom",
            "border-bottom-width",
            "border-bottom-style",
            "border-bottom-color",
            "border-left",
            "border-left-width",
            "border-left-style",
            "border-left-color",
            "-webkit-border-radius",
            "-moz-border-radius",
            "border-radius",
            "-webkit-border-top-left-radius",
            "-moz-border-radius-topleft",
            "border-top-left-radius",
            "-webkit-border-top-right-radius",
            "-moz-border-radius-topright",
            "border-top-right-radius",
            "-webkit-border-bottom-right-radius",
            "-moz-border-radius-bottomright",
            "border-bottom-right-radius",
            "-webkit-border-bottom-left-radius",
            "-moz-border-radius-bottomleft",
            "border-bottom-left-radius",
            "-webkit-border-image",
            "-moz-border-image",
            "-o-border-image",
            "border-image",
            "-webkit-border-image-source",
            "-moz-border-image-source",
            "-o-border-image-source",
            "border-image-source",
            "-webkit-border-image-slice",
            "-moz-border-image-slice",
            "-o-border-image-slice",
            "border-image-slice",
            "-webkit-border-image-width",
            "-moz-border-image-width",
            "-o-border-image-width",
            "border-image-width",
            "-webkit-border-image-outset",
            "-moz-border-image-outset",
            "-o-border-image-outset",
            "border-image-outset",
            "-webkit-border-image-repeat",
            "-moz-border-image-repeat",
            "-o-border-image-repeat",
            "border-image-repeat",
            "outline",
            "outline-width",
            "outline-style",
            "outline-color",
            "outline-offset",
            "background",
            "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader",
            "background-color",
            "background-image",
            "background-repeat",
            "background-attachment",
            "background-position",
            "background-position-x",
            "-ms-background-position-x",
            "background-position-y",
            "-ms-background-position-y",
            "-webkit-background-clip",
            "-moz-background-clip",
            "background-clip",
            "background-origin",
            "-webkit-background-size",
            "-moz-background-size",
            "-o-background-size",
            "background-size",
            "box-decoration-break",
            "-webkit-box-shadow",
            "-moz-box-shadow",
            "box-shadow",
            "-webkit-box-shadow",
            "-moz-box-shadow",
            "box-shadow",
            "-webkit-box-shadow",
            "-moz-box-shadow",
            "box-shadow",
            "-webkit-box-shadow",
            "-moz-box-shadow",
            "box-shadow",
            "filter:progid:DXImageTransform.Microsoft.gradient",
            "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient",
            "text-shadow"
        ],
        [
            "font",
            "font-family",
            "font-size",
            "font-weight",
            "font-style",
            "font-variant",
            "font-size-adjust",
            "font-stretch",
            "font-effect",
            "font-emphasize",
            "font-emphasize-position",
            "font-emphasize-style",
            "font-smooth",
            "line-height"
        ],
        [">child"]
    ]
}

Why some flexbox properties go down?

Typical example:

.block {
    display: flex;
    &__item {
        color: red;
    }
    justify-content: center;
    align-items: center;
}

That is very annoying!

I use yandex preset. How to fix that?

Feature request: Line break in between groups of properties

In the case of this rule: https://github.com/hudochenkov/postcss-sorting/blob/master/docs/properties-order.md#array-of-unprefixed-property-namesarray-of-group-objects

I would like an option to add a line break in between each provided group object, which would let me separate the groups visually in the processed CSS. In this situation, the given/before/after would look like this:

Given

[
    {
        properties: [
            "position",
            "top"
        ]
    },
    {
        properties: [
            "display",
            "z-index"
        ]
    }
]

Before

a {
    z-index: 2;
    top: 0;
    position: absolute;
    display: block;
}

After

a {
    position: absolute;
    top: 0;
	
    display: block;
    z-index: 2;
}

function is no good in LessCSS

/before/
.fn1(){}
.fn2(){}
.trans{
.fn1();
.fn2();
}

/after/
.fn1(){}
.fn2(){}
.trans{
.fn1()
.fn2()
}

The semicolon is disappear. I need it.
Another question, the function is no set postion,I hope the function is before the attitudes.

Wrong position for custom properties

Should be sorted as variables in order they defined.

Before:

&--m2-pack {
    --width: 100px;
    --offset: 539px;
    background: #3d3d3d linear-gradient(135deg,
    // background: #3d3d3d linear-gradient(to right,
        transparent calc(var(--offset) + var(--width) * 0),
        #e9ab54 calc(var(--offset) + var(--width) * 0), #e9ab54 calc(var(--offset) + var(--width) * 1),
        #4cb5a4 calc(var(--offset) + var(--width) * 1), #4cb5a4 calc(var(--offset) + var(--width) * 2),
        #7288b9 calc(var(--offset) + var(--width) * 2), #7288b9 calc(var(--offset) + var(--width) * 3),
        #f16059 calc(var(--offset) + var(--width) * 3), #f16059 calc(var(--offset) + var(--width) * 4),
        transparent calc(var(--offset) + var(--width) * 4)
    );
    background-position: 50% 0;
    background-size: 2000px 100%;
}

After:

&--m2-pack {
    --width: 100px;
    background: #3d3d3d linear-gradient(135deg,
    // background: #3d3d3d linear-gradient(to right,
        transparent calc(var(--offset) + var(--width) * 0),
        #e9ab54 calc(var(--offset) + var(--width) * 0), #e9ab54 calc(var(--offset) + var(--width) * 1),
        #4cb5a4 calc(var(--offset) + var(--width) * 1), #4cb5a4 calc(var(--offset) + var(--width) * 2),
        #7288b9 calc(var(--offset) + var(--width) * 2), #7288b9 calc(var(--offset) + var(--width) * 3),
        #f16059 calc(var(--offset) + var(--width) * 3), #f16059 calc(var(--offset) + var(--width) * 4),
        transparent calc(var(--offset) + var(--width) * 4)
    );
    background-position: 50% 0;
    background-size: 2000px 100%;
    --offset: 539px;
}

Empty lines between @media and child rules

Thanks for fixing #16! There is one more issue I think.

OK, there is an empty line between media-rules now, but there is also an additional line between media-rule and between child rule. I think there should be 1 empty line too.

.color {
  @mixin coloring;

  color: white;

  @media (--viewport-md) {
    color: green;
  }

  @media (--viewport-lg) {
    color: red;
  }


  span {
    color: black;
  }

  span {
    color: pink;
  }
}

Config is such:

{
  "empty-lines-between-children-rules": 1,
  "empty-lines-between-media-rules": 1,
  "sort-order": [
    [
      "@mixin"
    ],
    [
      …
    ],
    [
      "@media"
    ],
    [
      ">child"
    ]
  ]
}

Line after dollar var

I need empty line after dollar variable. Maybe there is the option opposit to "dollar-variable-empty-line-before"?

Put options above

Examples are very important for understanding wht plugin does.

So, maybe we should put it befoore Usage, not after?

gulp & atom-plugin compatibility

I am currently using https://github.com/lysyi3m/atom-postcss-sorting plugin in atom which requires the use of .postcss-sorting.json in my project root. I am also using gulp to render all my scss and performing the following on the rendered css.

var sortOrder = require('./.postcss-sorting.json');

gulp.task('sort', function () {
    return gulp.src('./css/src/*.css').pipe(
        postcss([
            sorting({ sortOrder })
        ])
    ).pipe(
        gulp.dest('./css/src')
    );
});

but it does not seem to be working...

File config for sorting styles

It will be usefull with file config with rules for sorting styles. For example we can use filename with .psortingrc file with rules for sorting

Detect difference between @include foo; and @include foo { } (with content)

In Sass syntax I prefer to sort mixins with content to the end of the rules. For example:

.block {
  @extend %placeholder;
  @include mixin;

  position: relative;
  font-size: 15px;

  @include mixin-with-content {
    border: none;
  }
}

Is it rare/only my usecase?

UPD:
That link proof that's not only my case and sass-lint detect the same sorting https://github.com/brigade/scss-lint/blob/master/lib/scss_lint/linter/README.md#declarationorder

Dont sorting on save

// Set true to sort on save every file with supported syntax
"sort-on-save": true

Yesterday set plugin, checked - worked well.
Today, it stopped sort when saving.

Problem with config?

Hi Aleks,

I've been strugling with adding option preserve-empty-lines-between-children-rules (or empty-lines-between-children-rules, or empty-lines-between-media-rules for that matter) to my config file. Here is my config and how I run it: https://github.com/wildbit/postcss-sorting-config-wildbit

As long as config JSON has only sort-order option it works fine, but when I add anything else it fails:

gulp cleanup
[11:55:58] Using gulpfile ~/Sites/beanstalk/gulpfile.js
[11:55:58] Starting 'cleanup'...

events.js:154
      throw er; // Unhandled 'error' event
      ^
TypeError: Cannot read property 'type' of undefined
    at getApplicableNode (/Users/eugene/Sites/beanstalk/node_modules/postcss-sorting/index.js:188:14)
    at getApplicableNode (/Users/eugene/Sites/beanstalk/node_modules/postcss-sorting/index.js:193:10)
    at /Users/eugene/Sites/beanstalk/node_modules/postcss-sorting/index.js:306:25
    at Rule.each (/Users/eugene/Sites/beanstalk/node_modules/postcss/lib/container.js:68:22)
    at /Users/eugene/Sites/beanstalk/node_modules/postcss-sorting/index.js:281:10
    at /Users/eugene/Sites/beanstalk/node_modules/postcss/lib/container.js:81:26
    at Root.each (/Users/eugene/Sites/beanstalk/node_modules/postcss/lib/container.js:68:22)
    at Root.walk (/Users/eugene/Sites/beanstalk/node_modules/postcss/lib/container.js:80:21)
    at /Users/eugene/Sites/beanstalk/node_modules/postcss-sorting/index.js:219:7
    at LazyResult.run (/Users/eugene/Sites/beanstalk/node_modules/postcss/lib/lazy-result.js:206:20)

npm ERR! Darwin 15.4.0
npm ERR! argv "/Users/eugene/.nvm/versions/node/v5.11.0/bin/node" "/Users/eugene/.nvm/versions/node/v5.11.0/bin/npm" "run" "cleanup"
npm ERR! node v5.11.0
npm ERR! npm  v3.8.6
npm ERR! code ELIFECYCLE
npm ERR! [email protected] cleanup: `gulp cleanup`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] cleanup script 'gulp cleanup'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the beanstalk-app package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     gulp cleanup
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs beanstalk-app
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls beanstalk-app
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/eugene/Sites/beanstalk/npm-debug.log

I tried to look at other configs, but all of the default ones have a single sort-order option in them.

Would really appreciate if you can point me in a right direction!

An option to not change empty lines

It would be great to have a way to completely disable empty-lines-between-children-rules and empty-lines-between-media-rules. I use empty lines to group related properties together, and right now all this organization gets removed every time I run postcss-sorting.

P.S. Thanks for the awesome plugin! It's a huge time saver in cleaning up a big old codebase.

Handle multiple consecutive comments

Config: { "sort-order": [ ["border-bottom", "font-style"] ] }

Input:

div p em {
    /* upline comment 1 */
    /* upline comment 2 */
    font-style: italic;
    border-bottom: 1px solid red; /* trololo 1 */ /* trololo 2 */
}

Expected output:

div p em {
    border-bottom: 1px solid red; /* trololo 1 */ /* trololo 2 */
    /* upline comment 1 */
    /* upline comment 2 */
    font-style: italic;
}

Current output:

div p em {
    border-bottom: 1px solid red; /* trololo 1 */
    /* upline comment 2 */
    font-style: italic;
}

Is it possible to add a name for config file?

I wonder if I can add a custom name for the config file? I hate how it looks like in the notification when I press cmd + s. I want to see something like "Successfully sorted using "My name of the team" config. Thanks.

Wrong sorting with last comment

Input:

&__itself {
    position: absolute;
    top: 100%;
    right: 50%;
    transform: translateX(50%);
    margin-top: -4px;
    z-index: 2;
    display: none;
    width: 200px;

    &.is-open {
        display: block;
    }
    &:before {
        position: absolute;
        top: 0;
        left: 50%;
        display: block;
        width: 12px;
        height: 12px;
        border: 1px solid #e2e2e2;
        background: #e2e2e2;
        box-shadow: 0 0 8px rgba(0, 0, 0, .1);
        content: "";
        transform: rotate(45deg);
        transform-origin: 0 0;
    }
    // &:after {
    //  content: "";
    //  position: absolute;
    //  top: -2px;
    //  left: 50%;
    //  width: 1px;
    //  height: 10px;
    //  background: red;
    //  display: block;
    // }
}

Output:

&__itself {
    position: absolute;
    // }
    right: 50%;
    transform: translateX(50%);
    margin-top: -4px;
    z-index: 2;
    display: none;
    width: 200px;

    &.is-open {
        display: block;
    }
    &:before {
        position: absolute;
        top: 0;
        left: 50%;
        display: block;
        width: 12px;
        height: 12px;
        border: 1px solid #e2e2e2;
        background: #e2e2e2;
        box-shadow: 0 0 8px rgba(0, 0, 0, .1);
        content: "";
        transform: rotate(45deg);
        transform-origin: 0 0;
    }
    top: 100%
    //  content: "";
    //  position: absolute;
    //  top: -2px;
    //  left: 50%;
    //  width: 1px;
    //  height: 10px;
    //  background: red;
    //  display: block;
    // &:after {
}

With every run it's getting worse.

adding a custom config file

Hi, I'm trying to introduce this into my clients workflow. As part of their CSS styleguide we are ordering CSS alphabetically. I see this isn't a current config option so I've made a start on one - https://gist.github.com/sturobson/aa6fad643b45891f5725d4e4f827eeeb - the question is -- how can I easly add this? I guess it's possible to drop the file into where your existing templates are but it'd be nice to be able to add your own sort order or -- when I finish this -- send a PR to include an alphabetical config?

Thanks for this plugin.

Respecting stylelint-order value for emptyLineBefore

I currently use your stylelint-order to help keep our css in a clear group and structure using a line break between each group.

I just recently updated postcss-sorting to the v 2 branch as I had hoped to share the config so I was not maintaining 2 different configs however I noticed a slight discrepancy:

In stylelint-order you use the "always" value for the empty line:

[
    {
        "emptyLineBefore": "always",
        ....

While in postcss-sorting it is just a boolean

"properties-order": [
        {
            "emptyLineBefore": true,
            ....

This results in an error being logged:
postcss-sorting: Invalid "properties-order" option value

Is it possible that these options could match as this will cut down on extra code.

Parameters to add empty lines before or after children rules and @rules

Hello.

I'd like to have an ability to add empty lines before or after children rules and at-rules. Right now we can only specify number of empty lines between rules of similar type (like children or at-rules), but it's not too practical.

Instead of this:

.block {
    display: block;
    margin: auto;
    @media (max-width: 640px) {
        width: 100%;
    }

    @media (max-width: 1200px) {
        width: 90%;
    }
    &--modifier {
        background: red;
    }

    &--another-modifier {
        background: green;
    }
}

we should have something like this:

.block {
    display: block;
    margin: auto;

    @media (max-width: 640px) {
        width: 100%;
    }

    @media (max-width: 1200px) {
        width: 90%;
    }

    &--modifier {
        background: red;
    }

    &--another-modifier {
        background: green;
    }
}

I suggest to replace parameters empty-lines-between-media-rules and empty-lines-between-children-rules with empty-lines-before-media-rules, empty-lines-before-children-rules, empty-lines-after-media-rules, empty-lines-after-children-rules.

What do you think about it? I'd like to implement it and create a PR, if you don't mind.

Feature request: Consider "&", "&:" and "&::" as non-children for positioning.

eg)

[sorting({
    "empty-lines-between-children-rules": 1,
    "sort-order": [
        ["$variable"],
        [">child"],
        ...

input:

.class {
    &_method {
        color: blue;
    }
    & {
        color: $var;
    }
    $var: green;
    &:hover {
        color: red;
    }
    &::after {
        color: yellow;
    }
}

requested output:

.class {
    $var: green;

    & {
        color: $var;
    }
    &:hover {
        color: red;
    }
    &::after {
        color: yellow;
    }

    &_method {
        color: blue;
    }
}

Where &, &:, and &:: are treated the same as immediate properties.

Release plan for 2.0.0

There are great tools to enforce code style and order in stylesheets: stylelint with its plugins, stylefmt, and postcss-sorting. My main idea for the new release was to handle in postcss-sorting only rules sorting, and no empty lines handling. I wanted to integrate this plugin into stylefmt, so users can use only one tool to format stylesheets. But I found out that stylefmt isn't reliable right now and makes a lot of opinionated changes, which can't be disabled at the moment. It's about to change in the new stylefmt version, though. So I came up with and another idea how to use postcss-sorting while stylefmt isn't suitable for me yet. This plugin will only sort by default, but there will be options to clean up empty lines and add new ones if needed.

Breaking changes

Everything :) All new config, new behavior, no predefined configs.

Options

sort-order will be divided into two options: order and properties-order.

New

  • clean-empty-lines — will remove all empty lines. Will run before any option related to empty lines.

  • custom-property-empty-line-beforecustom-property-empty-line-before

  • dollar-variable-empty-line-before — will be similar to custom-property-empty-line-before.

  • declaration-empty-line-before — options and rule name will be almost the same as declaration-empty-line-before. Useful combination to have empty line before declaration only if there is a node before declaration except declaration or comment:

    {
        "declaration-empty-line-before": ["always", {
            except: [
                "after-comment",
                "first-nested",
            ],
            ignore: [
                "after-declaration",
            ]
        }]
    }

Replaced

Removed

  • preserve-empty-lines-between-children-rules because all empty lines will be preserved by default.
  • empty-lines-after-comment

Also

Since all options will be based on stylelint options and stylelint plugins options, I'm thinking about extends option which will work like in stylelint. Maybe it's overkill for this plugin. But it would be nice to have only one config for stylelint and this plugin.

emptyLineBefore in "order"?

Is there any way to add empty lines for order rules? Something like this:

{
  "type": "at-rule",
  "name": "extend",
  "emptyLineBefore": true
},
{
  "type": "at-rule",
  "name": "include",
  "emptyLineBefore": true
}

This still working?

I'm trying to use this, but apparently don't work anymore, i don't know if i'm doing something wrong, but this don't sort my rules of .scss file 😢

Working with SASS Syntax

Hey there,

This package is amazing, bit it doesn't seam to be working on SASS Syntax files. Does it support SASS Syntax at all? If not, is it planned to support anytime soon?

Cheers!

Unknown Word Error on variable

<css input>:8:22: Unknown word
$color-list: 'black' 'gray' 'blue' 'white';

svg
{
    display: block;
    @each $color in $color-list
    {
        &.top-wave-#{$color}
        {
            @include wave(color($color));
        }

        &.bottom-wave-#{$color}
        {
            @include wave(color($color), down);
        }
    }
}

Using an atom plugin to run PostCSS but removing removing $color and leaving #{} allows it to process the file.

Keep empty line before (comment + nested)

How can I keep the empty line before the comment for the ul element? It seems like "clean-empty-lines" overrules "comment-empty-line-before". Thanks again for the help. I really appreciate the work you're doing.

Before:

div {
  // Comment
  a {}

  // Comment keep empty line before
  ul {}
}

After:

div {
  // Comment
  a {}
  // Comment keep empty line before
  ul {}
}

Config:

{
  "at-rule-nested-empty-line-before": [true, {
    "except": ["blockless-after-same-name-blockless", "first-nested"],
    "ignore": ["after-comment", "blockless-after-same-name-blockless"],
    "ignoreAtRules": ["else"]
  }],
  "clean-empty-lines": true,
  "comment-empty-line-before": [true, {
    "except": ["first-nested"],
    "ignore": ["after-comment", "stylelint-command"]
  }],
  "custom-property-empty-line-before": [true, {
    "except": ["after-comment", "after-custom-property", "first-nested"],
    "ignore": ["after-comment", "inside-single-line-block"]
  }],
  "declaration-empty-line-before": [true, {
    "except": ["after-comment", "after-declaration", "first-nested"],
    "ignore": ["after-comment", "after-declaration", "inside-single-line-block"]
  }],
  "dollar-variable-empty-line-before": [true, {
    "except": ["after-comment", "after-dollar-variable", "first-nested"],
    "ignore": ["after-comment", "inside-single-line-block"]
  }],
  "rule-nested-empty-line-before": ["always-multi-line", {
    "except": ["first-nested"],
    "ignore": ["after-comment"]
  }]
}

Pseudo elements sorting

@hudochenkov What do you think about sorting nested pseudo elements?

.block {
    width: 100px;
    height: 100px;
    display: block;
    background-color: red;

    &::before {
        width: 20px;
        height: 20px;
    }

    &::after {
        width: 20px;
        height: 20px;
    }
}
.paragraph {
    font-size: 16px;
    line-height: 1.2;
    color: 333;

    &::first-letter {
        font-size: 24px;
    }

    &::first-letter {
        color: black;
    }

    &::selection {
        color: yellow;
        background: #333;
    }
}

Not displaying errors when run postcss-sorting via npm

Hi,
I'm trying run postcss-sorting via npm, all works, but if scss files have errors, npm do not display errors, hovewer run command without npm output errors to console

Command:

postcss --use postcss-sorting src/**/*.scss --replace

File with errors:

.test {
  padding: 1em; // ERROR HERE
}

Empty lines removal in 2.x version

Can't make it clear all empty lines:

   "properties-order":[
      {
         "clean-empty-lines":true,
         "preserve-empty-lines-between-children-rules":true,
         "properties":[
            "position",
            "top",
            "right",
            "bottom",
            "left",
            "z-index"
         ]
      },

What am I doing wrong?

Targeting custom comments on the stylesheets

Hey,

Just a quick feature request: having a way to target custom comment patterns on the stylesheets pages would be great!

For example, if I have the following code:

/* ===== BUTTONS ===== */
.buttons{
   background: #000;
}
.buttons.red{
    background: #F00;
}
.buttons.blue{
    background: #00F;
}

I wanted to have a regex or something that allowed me to specifically target my title and configure how many spaces I wanted before and after, in order to properly organise my files.

Wouldn't this be cool?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.