GithubHelp home page GithubHelp logo

stylelint / stylelint Goto Github PK

View Code? Open in Web Editor NEW
10.8K 109.0 929.0 31.39 MB

A mighty CSS linter that helps you avoid errors and enforce conventions.

Home Page: https://stylelint.io

License: MIT License

JavaScript 99.12% CSS 0.56% Shell 0.02% HTML 0.03% TypeScript 0.18% Less 0.01% SCSS 0.09%
linter css scss less postcss css-in-js html markdown lint enforce-conventions

stylelint's Introduction

Stylelint

npm version Build Status npm downloads

A mighty CSS linter that helps you avoid errors and enforce conventions.

Features

It's mighty as it:

  • has over 100 built-in rules for modern CSS syntax and features
  • supports plugins so you can create your own custom rules
  • automatically fixes problems where possible
  • supports shareable configs that you can create or extend
  • can be customized to your exact needs
  • has 15k unit tests making it robust
  • is trusted by companies worldwide like Google and GitHub

And it can be extended to:

  • extract embedded styles from HTML, Markdown and CSS-in-JS template literals
  • parse CSS-like languages like SCSS, Sass, Less and SugarSS

How it'll help you

It'll help you avoid errors, for example:

  • invalid things, e.g. malformed grid areas
  • valid things that are problematic, e.g. duplicate selectors
  • unknown things, e.g. misspelled property names

And enforce conventions, for example:

  • disallow things, e.g. specific units
  • enforce naming patterns, e.g. for custom properties
  • set limits, e.g. the number of ID selectors
  • specify notations, e.g. for modern color functions

We recommend using a pretty printer like Prettier alongside Stylelint. Linters and pretty printers are complementary tools that work together to help you write consistent and error-free code.

Example output

Example

Guides

Contributors

Stylelint is maintained by volunteers. Without the code contributions from all these fantastic people, Stylelint would not exist. Become a contributor.

Sponsors

Thank you to all our sponsors! Become a sponsor.

Backers

Thank you to all our backers! Become a backer.

Website hosting

Deploys by Netlify

License

The MIT License.

stylelint's People

Contributors

alexander-akait avatar caydenberg avatar davidtheclark avatar dependabot-preview[bot] avatar dependabot[bot] avatar dryoma avatar evilebottnawi avatar fpetrakov avatar github-actions[bot] avatar greenkeeper[bot] avatar greenkeeperio-bot avatar gucong3000 avatar hudochenkov avatar jeddy3 avatar kangax avatar m-allanson avatar makotot avatar mattxwang avatar moox avatar mouvedia avatar nex3 avatar ntwb avatar onigoetz avatar ota-meshi avatar romainmenke avatar sendilkumarn avatar stephenwade avatar vankop avatar xhmikosr avatar ybiquitous 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  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

stylelint's Issues

Performance benchmarks (consider lodash)

Followup to discussion here: 64f72fe#commitcomment-11168302

Currently we are leaving lodash out because we don't want to include unnecessary dependencies, which is a good approach.

lodash author John-David Dalton says there should be perf benefits to using lodash even within Node.js or io.js: https://twitter.com/jdalton/status/598511373849530368?cn=cmVwbHk%3D&refsrc=email

Because we are going to be running lots and lots of checks on sometimes lots and lots of lines of CSS, I'd say that performance is a major priority, and we should seriously consider any perf benefits we can get.

I'm opening this issue so that somebody at some point might run some benchmarks and compare some of the native looping, mapping, reducing, etc. that we are already doing against the same procedures with lodash functions. If lodash performance beats out the (babel-compiled) native code, then that (on top of other things I like about lodash) should incline us to use it.

Standardised messages and docs

What do you guys think about standardising the wording within the messages? They've diverged a little bit already.

The "Expected" approach that @davidtheclark's used in declaration-bang-space and in declaration-block-trailing-semicolon LGTM. It seems to be used a lot in eslint as well.

So, the current rules would look something like:

Note: always tending towards "expected" over "unexpected"...

  • declaration-colon/bang-space: "Expected single space before "!"" and "Expected no space before "!"
  • declaration-block-trailing-semicolon: "Expected a trailing semicolon" and "Expected no trailing semicolon"
  • number-leading-zero: "Expected a leading zero for fractional value less than 1" and "Expected no leading zero for fractional value less than 1"

And "unexpected" would be mainly used for *-no-* rules e.g.

  • declaration-no-important: "Unexpected !important"
  • rule-set-no-single-line: "Unexpected single-line rule-set"

What do you think?

I'm still keen to keep the must always, must never, can, disallow, and enforce language in the documentation as I think it feels nice and clear. e.g. here and here.

Thoughts?

Consider using -before and -after rules instead of before/after options

After writing a lot of tests now, I'm think that things would be simpler if we separated out before/after rules instead of using options. So we'd have, e.g., block-opening-brace-space-before and block-opening-brace-space-after (like JSCS).

The reasoning is this:

  • Each rule function would be that much simpler, that much more focused.
  • Tests would have fewer option-permutations to test -- so we could get by writing way fewer, more straightforward tests. Right now if we want to be really thorough we have to make sure that each permutation works as expected and that changing one option doesn't affect the outcome of the other option; but if we had separate rules each of those would be tested independently and we wouldn't have to worry about them possibly overlapping and affecting each other.

Any opposition?

Add missing documetation for some rules

  • block-opening-brace-space
  • block-opening-brace-newline
  • declaration-bang-space
  • declaration-block-trailing-semicolon
  • declaration-comma-space
  • function-comma-space
  • number-leading-zero
  • rule-set-no-single-line
  • selector-combinator-space

Testing utilities and conventions

The vast majority of tests that we write for rules will be doing the exact same thing: check whether a given CSS string passes or causes a warning with an expected message.

So I'm thinking we should have some functions that make it very, very easy to run these standard tests and log meaningful messages. (Of course, if somebody has something different to do they can always not use these standard functions.)

This morning I worked out a possible approach, and I wanted to run it by you all before I went too far with it.

The following creates a ruleTester that exposes ok() and notOk() functions that check for no warnings or warnings (with correct messages) and logs in a meaningful way:

import postcss from "postcss"
import jsesc from "jsesc"

export default function ruleTester(rule) {
  return {
    ok: function (t, cssString, options) {
      postcssProcess(cssString, options, result => {
        t.comment(jsesc(cssString))
        t.equal(result.warnings().length, 0, `no warnings`)
      })
    },
    notOk: function (t, cssString, options, message) {
      postcssProcess(cssString, options, result => {
        const warnings = result.warnings()
        t.comment(jsesc(cssString))
        t.equal(warnings.length, 1, `one warning`)
        t.equal(warnings[0].text, message, `correct warning message`)
      })
    },
  }

  function postcssProcess(cssString, options, callback) {
    postcss()
      .use(rule(options))
      .process(cssString)
      .then(callback)
  }
}

I'd use it like this (the third test deliberately fails):

import test from "tape"
import { ruleTester, ruleTestTitle } from "../../../testUtils"
import blockOpeningBraceBefore, { ruleName, messages } from ".."

const testRule = ruleTester(blockOpeningBraceBefore)

test(ruleTestTitle(ruleName, "'space'"), t => {
  testRule.ok(t, "body { color: pink; }", "space")
  testRule.ok(t, "@media print { color: pink; }", "space")
  testRule.notOk(t, "body\n{ color: pink; }", "newline", messages.expected("newline"))
  testRule.notOk(t, "@media print\n{ color: pink; }", "space", messages.expected("space"))
  t.end()
})

And that outputs TAP output like this:

TAP version 13
# block-opening-brace-before: 'space'
# body { color: pink; }
ok 1 no warnings
# @media print { color: pink; }
ok 2 no warnings
# body\n{ color: pink; }
not ok 3 one warning
  ---
    operator: equal
    expected: 1
    actual:   0
  ...
# @media print\n{ color: pink; }
ok 4 one warning
ok 5 correct warning message

1..5
# tests 5
# pass  4
# fail  1

Or tap-spec output like this:

  block-opening-brace-before: 'space'


  body { color: pink; }

    โœ“ no warnings

  @media print { color: pink; }

    โœ“ no warnings

  body\n{ color: pink; }

    โœ— one warning

  @media print\n{ color: pink; }

    โœ“ one warning
    โœ“ correct warning message

Or faucet output like this:

โœ“ block-opening-brace-before: 'space'
โœ“ body { color: pink; }
โœ“ @media print { color: pink; }
โจฏ body\n{ color: pink; }
  not ok 3 one warning
    ---
      operator: equal
      expected: 1
      actual:   0
    ...
โœ“ @media print\n{ color: pink; }
# tests 5
# pass  4
โจฏ fail  1

What do you think? Is that a useful abstraction for us? Are the error messages as clear as we can make them? Any suggestions for improvement?

I think it will be very handy as we write thousands of little tests to have functions that do something like this, at least ...

Extends and disabling rules (and severities)

This is a continuation of PR 13 as there were a couple of things in there that I think are worth capturing for future reference.

We agreed that we shouldn't have built-in defaults, but we should instead, at some point, supply a mechanism to use or extend a recommended configuration.

If we provide an extends mechanism (like eslint does) then it follows that we might also need a means of disabling rules, right? e.g.

extends: recommended-suitcss, // example of a recommended styleguide config
rules: {
  declaration-block-trailing-semicolon: disable? 
  // the user doesn't wish to enforce either option i.e always semi or never semi
}

We can either:

  1. Do nothing. Which isn't bad as:
    • Power users will probably be building their own configs from scratch (maybe by copying an example recommended config from somewhere, and building on top of that).
    • New users can extend a recommend config (e.g. with a simple extends: recommended-suitcss) and add extra rules to it (but they can not subtract rules from it - they'll need to build their config from scratch just like the power users do, if they want to do that).
  2. Do something, which has the advantages of:
    1. Easier for new users to get started.
    2. If a power user is building on top a recommended styleguide then they don't need to worry about maintaining that part of the rules configuration.

Related to this, as @MoOx pointed out in the PR, is the idea of severities e.g. it looks like eslint combines severities and disabling rules into one number system.

Scsslint also has severities and it got a mention over in the original Rules thread.

I don't know enough about this to decide whether the advantages of adding severities (e.g. easier integration into build systems) out weigh the disadvantages (e.g. more complexity), or not. Does anyone have a strong opinion on this?

I don't think we need to resolve this now though as this issue shouldn't affect how we write the rules themselves, right? Is it something that can be dealt with entirely in the stylelint index.js? If so, shall we carry on as we were and just keep this issue hanging around for future reference?

Why rule-set-body-selector-background-property?

I don't understand this one. Am I right that it's trying to force the user to at some point use a background property on body? If that's the intention, I don't think this will accomplish that. If the uses the body selector twice in legitimate ways and only applies a background once, this will needlessly. Also, the user could never use the body selector and thus bypass the intention without getting warned. (Or maybe there's another reason behind this rule?)

About project structure

All in src looks strange. That __tests__ directories...

__tests__ in src, __tests__ in rules, __tests__ in rules/declaration* and etc..

Also for things like that index.js in rules directory you can use some of them

  • export-files: node.js utility for exporting a directory of files as modules.
  • export-dirs: Export directories and their files as node.js modules.
  • to-exports: Create exports from a directory of non-javascript or javascript files.

You should firstly start with that thing.

start rule documentation

Anybody have a preference about whether documentation for rules goes in the Readme or in a separate rules.md file?

I guess I'm leaning towards rules.md myself.

I could get that started.

Clarify "never" option for whitespace rules

Given a rule like declaration-bang-space --- so far I've been treating "never" to mean: "no whitespace in front of the bang". Because I'm thinking that if you want there to be no space in front of the !, you're also not going to want there to be a tab or newline or some other whitespace.

One implication of that treatment that I wanted to run by everybody is that "never" means the same, then, whether it's for a space rule or a newline rule. I was working on block-opening-brace-newline, and realized that the tests for its "never" would be the same as for block-opening-brace-space.

So does it seem that that's the right approach to everybody? Or should we instead make "never" mean "not this particular whitespace --- but other whitespaces we don't know.*

exact versions for devDependencies

What would you think about using exact versions for devDependencies?

I have seen and run into problems with CI when using carets for these (CI installs later version than you have locally, that version was improperly versioned so has some breaking change, etc.); and at the same time I don't know of any advantage to using the caret for devDependencies, since people will only install them for development so we don't have to worry about overcomplicated the dependency tree. Seems to me clearer and less error prone to be exact. Thoughts?

better place for test utilities

How about a testUtil/ directory in src/, containing test utils like testRule?

The current position (in src/rules/__tests__/utils) seems to me very unintuitive and requires a long import like import testRule from "../../__tests__/utils/testRule".

Open to that?

New rule: rule-set-no-single-line

Disallow single line rule-sets (true/false).

I will work on this soon. For this and #18 I will write a utility function to test whether a block contains any line breaks.

workflow

I probably will spend some time writing more rules this coming weekend. I don't know if anybody else was thinking of contributing yet; but I want to make sure we don't overlap efforts. So I was thinking about the following workflow: Before starting work to add a rule, you should open an issue about that rule and state there that you are going to start working on it. If anybody doesn't check the issues before starting a rule and duplicates effort, that's their bad. But this should prevent that.

Sound ok?

Logo

a logo needs to be done

API

I just opened an issue on postcss that will helps a lot us. In fact that would make us just ready to drop rules as plugin & use this new message api.

postcss/postcss#177

Please give your opinion on this guys :)

Maybe switch to Mocha?

I am generally a fan of tape, and I know @MoOx is, too; but I've been writing tests for block-opening-brace-before (neverending ...) and for a few reasons I'm wondering if for this particular situation Mocha would be more useful.

At the bottom of the message I'll paste the test file I have so far, so you can see some context for what I'm talking about. Maybe you know of ways to solve these problems with tape?

  • Being able to further organize this test files with indefinite nesting of describe() functions would be good.
  • Describing the text before the assertion also seems in my mind to make such a long test file easier to read.
  • The TAP output is pretty unreadable at such length without better nesting (unless maybe we make much longer assertion descriptions than I'm doing?) --- certainly not as nice as if it were organized into nested sections, as in the default Mocha output. Could just one of the "pretty reporters" (https://github.com/substack/tape#pretty-reporters).
  • Mocha's async handling with callbacks might provide us better means to write test utility functions that tape's plan(). For example, I imagine writing utility functions for expectSuccess() or (no warnings) or expectFailure() (check for warning and correct message), and while I can think of a straightforward way to do this with callbacks and unlimited nesting of describe(), I'm having some trouble thinking of such a way with plan() and not-unlimited-nesting. (Also, callbacks might get around the need to change the number of planned tests whenever you add or remove tests, which is a big annoyance.)

Those are my concerns. What do you think? Can we solve them with tape? Should we switch to Mocha?

I partly feel like the only reason not to switch to tape (unless these concerns are unfounded) would be some ideal of purity which we should probably ignore in favor of pragmatism... Maybe it's worth an experiment, at least.

Can anybody foresee problems with Mocha?

import test from "tape"
import testRule from "../../../testUtils/testRule"

import blockOpeningBraceBefore from ".."
import { messages } from ".."

const testRule = testRule(blockOpeningBraceBefore)

test("block-opening-brace-before success", t => {
  t.test("with `space`", st => {
    st.plan(4)

    testRule("body { color: pink; }", "space", warnings => {
      st.equal(warnings.length, 0, "single-line rule")
    })

    testRule("body {\n\tcolor: pink;\n}", "space", warnings => {
      st.equal(warnings.length, 0, "multi-line rule")
    })

    testRule("@media print { color: pink; }", "space", warnings => {
      st.equal(warnings.length, 0, "single-line at-rule")
    })

    testRule("@media print {\n\tcolor: pink;\n}", "space", warnings => {
      st.equal(warnings.length, 0, "multi-line at-rule")
    })
  })

  t.test("with `newline`", st => {
    st.plan(2)

    testRule("body\n{ color: pink; }", "newline", warnings => {
      st.equal(warnings.length, 0, "multi-line rule")
    })

    testRule("@media print\n{\n\tcolor: pink;\n}", "newline", warnings => {
      st.equal(warnings.length, 0, "multi-line at-rule")
    })
  })

  t.test("with `{ singleLine: `space`, multiLine: `space` }`", st => {
    const options = { singleLine: "space", multiLine: "space" }
    st.plan(4)

    testRule("body { color: pink; }", options, warnings => {
      st.equal(warnings.length, 0, "single-line rule")
    })

    testRule("body {\n\tcolor: pink;\n}", options, warnings => {
      st.equal(warnings.length, 0, "multi-line rule")
    })

    testRule("@media print { color: pink; }", options, warnings => {
      st.equal(warnings.length, 0, "single-line at-rule")
    })

    testRule("@media print {\n\tcolor: pink;\n}", options, warnings => {
      st.equal(warnings.length, 0, "multi-line at-rule")
    })
  })

  t.test("with `{ singleLine: `space`, multiLine: `newline` }`", st => {
    const options = { singleLine: "space", multiLine: "newline" }
    st.plan(4)

    testRule("body { color: pink; }", options, warnings => {
      st.equal(warnings.length, 0, "single-line rule")
    })

    testRule("body\n{\n\tcolor: pink;\n}", options, warnings => {
      st.equal(warnings.length, 0, "multi-line rule")
    })

    testRule("@media print { color: pink; }", options, warnings => {
      st.equal(warnings.length, 0, "single-line at-rule")
    })

    testRule("@media print\n{\n\tcolor: pink;\n}", options, warnings => {
      st.equal(warnings.length, 0, "multi-line at-rule")
    })
  })

  t.end()
})

test.only("block-opening-brace-before failure", t => {
  t.test("warns when there are no whitespaces before opening brace", st => {
    st.plan(8)

    testRule("body{ color: pink; }", "space", warnings => {
      st.equal(warnings.length, 1, "with `space` setting and rule")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })

    testRule("body{ color: pink; }", "newline", warnings => {
      st.equal(warnings.length, 1, "with `newline` setting and rule")
      st.equal(warnings[0].text, messages.expected("newline"), "warning contains expected test")
    })

    testRule("@media print{ color: pink; }", "space", warnings => {
      st.equal(warnings.length, 1, "with `space` setting and at-rule")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })

    testRule("@media print{ color: pink; }", "newline", warnings => {
      st.equal(warnings.length, 1, "with `newline` setting and at-rule")
      st.equal(warnings[0].text, messages.expected("newline"), "warning contains expected test")
    })
  })

  t.test("when there are multiple whitespaces before opening brace", st => {
    st.plan(8)

    testRule("body  { color: pink; }", "space", warnings => {
      st.equal(warnings.length, 1, "warns with two spaces before brace of rule")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })

    testRule("body\n\t{ color: pink; }", "newline", warnings => {
      st.equal(warnings.length, 1, "warns with \\n\\t before brace of rule")
      st.equal(warnings[0].text, messages.expected("newline"), "warning contains expected test")
    })

    testRule("@media print  { color: pink; }", "space", warnings => {
      st.equal(warnings.length, 1, "warns with two spaces before brace of at-rule")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })

    testRule("@media print\n\t{ color: pink; }", "newline", warnings => {
      st.equal(warnings.length, 1, "warns with \\n\\t before brace of at-rule")
      st.equal(warnings[0].text, messages.expected("newline"), "warning contains expected test")
    })
  })

  t.test("with `space`", st => {
    st.plan(4)

    testRule("body\n{ color: pink; }", "space", warnings => {
      st.equal(warnings.length, 1, "warns if actual for rule is newline")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })

    testRule("@media print\n{ color: pink; }", "space", warnings => {
      st.equal(warnings.length, 1, "warns if actual for at-rule is newline")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })
  })

  t.test("with `newline`", st => {
    st.plan(4)

    testRule("body { color: pink; }", "newline", warnings => {
      st.equal(warnings.length, 1, "warns if actual for rule is space")
      st.equal(warnings[0].text, messages.expected("newline"), "warning contains expected test")
    })

    testRule("@media print { color: pink; }", "newline", warnings => {
      st.equal(warnings.length, 1, "warns if actual for at-rule is space")
      st.equal(warnings[0].text, messages.expected("newline"), "warning contains expected test")
    })
  })

  t.test("with `{ singleLine: `space`, multiLine: `space` }`", st => {
    const options = { singleLine: "space", multiLine: "space" }
    st.plan(4)

    testRule("body\n{\ncolor: pink; }", options, warnings => {
      st.equal(warnings.length, 1, "warns if newline precedes multiline rule")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })

    testRule("@media print\n{\ncolor: pink; }", options, warnings => {
      st.equal(warnings.length, 1, "warns if newline precedes multiline at-rule")
      st.equal(warnings[0].text, messages.expected("space"), "warning contains expected test")
    })
  })

  t.end()
})

Informing user of faulty options

How are we going to inform users of faulty options?

e.g. Misspelled keywords, options that don't make sense together (e.g. for single-line rule blocks expect a newline character before braces), etc.

Should we just throw an error? Will that make it through to the user, despite the Promises in PostCSS?

New rule: function-operator-space

Typical whitespace --- but this one in combination with function-comma-space makes me think I should write a general utility for finding things in values that are inside of (or outside of) functions.

Rules

Vocabulary reference http://apps.workflower.fi/vocabs/css/en

Updated list


Rules

General (tied to the stylesheet itself)

  • no-missing-eof-newline: Disallow missing end-of-file newline
  • no-multiple-empty-lines: Disallow multiple empty white lines
  • no-eol-no-whitespace: Disallow whitespace at the end of line
  • indentation: Specify whitespace for indentation
  • max-line-length: Specify maximum line length

String (ref)

  • string-quotes: "double"|"single" Specify quotes around strings
    • "double" - strings must be doubled quoted
    • "single" - strings must be single quoted

Number (ref)

  • number-leading-zero: "always"|"never" Require or disallow a leading zero before number
    • "always" - a number must have a leading zero
    • "never" - a number must not have a leading zero
  • number-no-trailing-zeros: Disallow trailing zeros (e.g. 5.0px)
  • number-zero-length-no-unit: Disallow units for zero length values
  • number-max-precision: int Maximum number of digits after the "." in a number

Function (ref)

  • function-comma-space-after: "always"|"never"
  • function-comma-space-before: "always"|"never"
  • function-parentheses-inside-space: "always"|"never" Specify space inside parentheses (after opening, before closing)
  • function-space-after: "always"|"never" Specify space between the closing parenthesis of a function and the next value
  • function-token-no-space: Disallow space between the function's name and its opening parenthesis
  • function-calc-no-unspaced-operator: Disallow operators without space on both sides in calc()
  • function-url-quotes: "double", "single", "none" Specify quotes around URLs (URLs, unlike strings, can be unquoted)
    • "double" - URLs must be doubled quoted
    • "single" - URLs must be single quoted
    • "none" - URLs must be unquoted

Color (ref)

  • color-hex-length: "short"|"long"
  • color-hex-case: "lower"|"upper"
  • color-no-invalid-hex: Disallow invalid hex
  • color-no-named: Disallow named colors
  • color-no-hex: Disallow hex colors
  • color-function-blacklist: array Disallowed color functions e.g. ["rgba", "hsl", "hwb"]
  • color-function-whitelist: array Only allowed color functions e.g. ["gray", "color", "device-cmyk"]

:root

  • root-no-standard-properties: Disallow use of standard properties in :root

Rule

  • rule-no-single-line: Disallow single line rule-sets
  • rule-properties-order: 1 dimension array, string (preset) - "alphabetical" Order of properties within a rule
  • rule-trailing-semicolon: "always"|"never" Trailing semicolon at the end of a rule
    • "always" - there must be a trailing semicolon
    • "never" - there must not be a trailing semicolon
  • rule-no-duplicate-properties: Disallow duplicate properties within a rule
  • rule-nested-empty-line-before: Require or disallow an empty line before nested rules
  • rule-single-line-max-length: int The maximum length of a single line rule
  • rule-single-line-max-declarations: int The maximum number of declaration within a single line rule

At-rule rules

  • at-rule-no-vendor-prefix: Disallow vendor prefixes in @rules
  • at-rule-empty-line-before: Require or disallow an empty line before at-rules

Custom media (ref)

  • custom-media-pattern: string Preset or regex pattern to use to check names are matching a given pattern

Media query

  • media-query-parenthesis-inside-space: "always"|"never"
  • media-query-list-comma-space-after: "always"|"never"
  • media-query-list-comma-space-before: "always"|"never"
  • media-query-list-comma-newline-after: "always"|"never"
  • media-query-list-comma-newline-before: "always"|"never"

Media feature

  • media-feature-colon-space-after: "always"|"never"
  • media-feature-colon-space-before: "always"|"never"
  • media-feature-range-operator-space-after: "always"|"never"
  • media-feature-range-operator-space-before: "always"|"never"

Media feature

  • media-feature-colon-space-after: "always"|"never"
  • media-feature-colon-space-before: "always"|"never"
  • media-feature-range-operator-space-after: "always"|"never"
  • media-feature-range-operator-space-before: "always"|"never"

Media feature name

  • media-feature-name-no-vendor-prefix: "always"|"never" Disallow vendor prefixes for media feature names

Selector

  • selector-combinator-space-before: string Specify what space should be used before and after combinator
  • selector-combinator-space-after: string Specify what space should be used before and after combinator
  • selector-delimiter-space-after: "always"|"never"
  • selector-delimiter-space-before: "always"|"never"
  • selector-delimiter-newline-after: "always"|"never"
  • selector-delimiter-newline-before: "always"|"never"
  • selector-no-vendor-prefix: Disallow vendor prefixes in selectors
  • selector-pseudo-element-notation: Specify that pseudo element selectors need one or two
  • selector-root-no-composition: Disallow use of :root selector with others (in list, complex, or compound selectors)
  • selector-no-id: Disallow use of id in selectors e.g: #id
  • selector-no-type: Disallow use of type in selectors e.g: div
  • selector-no-universal: Disallow use of universal selector in selectors e.g: *
  • selector-no-attribute: Disallow use of attributes in selectors e.g: [attr]
  • selector-no-combinator: Disallow use of combinator in selectors
  • selector-no-qualified: Disallow use of qualified selectors e.g: div#id
  • selector-no-pseudo-class: Disallow use of pseudo-class in selectors
  • selector-no-pseudo-element: Disallow use of pseudo-element in selectors
  • selector-no-delimiter: Disallow use of delimiter in selectors
  • selector-pattern: string regex (eg: /\.([a-z]+-)?[A-Z][a-z]+(-[a-z][a-zA-Z]+)(--[a-z][a-zA-Z]+)/ to match .org-Block-eleMent--modifier

Custom selector (ref)

  • custom-selector-pattern: string Regex pattern to use to check names are matching a given pattern

Block

  • block-no-empty: Disallow empty blocks
  • block-opening-brace-space-after: "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"
  • block-opening-brace-space-before: "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"
  • block-opening-brace-newline-after: "always"|"never"|"always-multi-line"|"never-multi-line"
  • block-opening-brace-newline-before: "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"
  • block-closing-brace-space-after: "always"|"never"|"always-single-line"
  • block-closing-brace-space-before: "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"
  • block-closing-brace-newline-after: "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"
  • block-closing-brace-newline-before: "always"|"never"|"always-multi-line"|"never-multi-line"

Nesting Block

  • nesting-block-opening-brace-space-before: "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"
  • nesting-block-opening-brace-newline-before: "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"

Declaration rules

  • declaration-no-important: Disallow the use of !important
  • declaration-bang-space-after: "always"|"never"
  • declaration-bang-space-before: "always"|"never"
  • declaration-colon-space-after: "always"|"never"
  • declaration-colon-space-before: "always"|"never"
  • declaration-semicolon-space-after: "always"|"never"|"always-single-line"|"never-single-line"
  • declaration-semicolon-space-before: "always"|"never"|"always-single-line"|"never-single-line"
  • declaration-semicolon-newline-after: "always"|"never"|"always-multi-line"|"never-multi-line"
  • declaration-semicolon-newline-before: "always"|"never"|"always-multi-line"|"never-multi-line"

Unit

  • unit-blacklist: array Disallowed units e.g. ["px", "pt", "cm"]
  • unit-whitelist: array Only allowed units e.g. ["%", "rem", "em"]

Property

  • property-no-vendor-prefix: Disallow vendor prefixes in properties
  • property-blacklist: array Disallowed properties e.g. ["tranform", "background-size"]
  • property-whitelist: array Only allowed properties e.g. ["height", "width", "font-size"]
  • property-unit-blacklist: object Disallowed units for specific properties e.g. {"width": ["%"], "height": ["%"]}
  • property-unit-whitelist: object Only allowed units for specific properties e.g. {"font-size": ["em", "rem"]}

Custom property

  • custom-property-no-outside-root: Disallow custom properties outside of :root
  • custom-property-pattern: string Regex pattern to use to check names are matching a given pattern

Value

  • value-no-vendor-prefix: Disallow vendor prefixes in values

Value list

  • value-list-comma-space-after: "always"|"never"|"always-single-line"|"never-single-line"
  • value-list-comma-space-before: "always"|"never"|"always-single-line"|"never-single-line"
  • value-list-comma-newline-after: "always"|"never"|"always-multi-line"|"never-multi-line"
  • value-list-comma-newline-before: "always"|"never"|"always-multi-line"|"never-multi-line"

Comment

  • comment-space-inside: string - `"always"|"never"
  • comment-empty-line-before: Require or disallow an empty line before comments

To think about Mistakes

  • Float or absolutely positioned elements don't need display: block
  • Absolutely positioned elements will ignore float

boolean options: true/false vs always/never vs only true

We have a mistmatch in how booleans are used for options in the drafts in #1.

Case #1:
color-hex-shorthand: bool

  • true - hex colors must be shorthand
  • false - hex colors must not be shorthand

Case #2:
color-no-named: bool Disallow named colors

  • true: named colors must not be used for colors
  • false: named colors can be used for colors

The key is that sometimes false = "must not" and sometimes false = "can".

I can think of a couple of possible ways to clarify this:

  1. Make false always mean "must not" as in Case #1; so in Case #2 false just wouldn't be a possibility --- if the user wants to not disallow named colors the user should turn the rule off, not leave it on and pass false.
  2. Use always and never instead of true and false in cases like Case #1. That would not clarify Case #2, though.

(This applies to the existing declaration-no-important as well as a bunch of other ones.)

Roadmap for 0.1.0

Hello!

Do you have any Roadmap or something? is it #1?
I'm interested in preparation and implementing of rules.

I'm looking forward to try & counting on stylelint.:smile:

New rule: indentation

@MoOx I think it would help clarify this rule if you could exemplify the complex options you proposed for this rule in #1. I have some guesses as to what is meant based on the discussion but it would be more straightforward with something like example pass/fail cases for each option. Does that make sense?

New rule: number-trailing-zero

Do we think it's reasonable that a person might want to require trailing zeros?

If not, maybe this should be number-no-trailing-zero.

New rule: selector-pseudo-element-colon-notation

Originally: selector-pseudo-element-two-colons "always"|"never".

I was going to have a go at this one next. What do you guys think of renaming it to?:

selector-pseudo-element-colon-notation : "single"|"double"

As it feels like it has more in common with something like string-quotes: "single"|"double" as the values are explicit. Whereas "never" for selector-pseudo-element-two-colons implies only a single colon, which feel odd and in contrast to something clear like declaration-block-trailing-semicolon where always and never mean a semicolon must be present and must not be present respectively.

Also, there's a lot of pseudo-elements, but it looks like the single colon approach is only valid for a handful of them, "namely: :first-line, :first-letter, :before and :after". Am I right in thinking this rule should only flag warnings against these four pseudo-elements and not the rest.

Defining whitespace rules

Expanded from #20 (comment)

It seems that in most whitespace rules in #1 it is suggested that users will be able to enter their own whitespace values. Maybe one space, three spaces, newline, carriage return, etc. I'm worried this will add a lot of overhead and complexity in order to accommodate rare edge cases.

Personally I have not yet seen standardized CSS where the convention was to use anything other than one or no spaces in most of those places (around combinators, colons, bang, commas, parentheses). Only braces have varied, and only by adding the possibility of a newline to that of a single space.

Maybe you don't buy that, and think that we need to allow for lots of variations? Anybody feel this way?

If you agree with me, I can think of a few possible ways simplify things:

  • Instead of all of these whitespace -before and -after pairs, we could generally use space rules which have before and after options. So instead of media-query-list-comma-before and media-query-list-comma-after we have media-query-list-comma-space; and its options are either { before: [boolean], after: [boolean] } (where true means always and false means never) or true which must provides a standard default (for commas, that would be { before: false, after: true }). If you don't like having before/after options, we could instead keep separate rules but make them space-specific, e.g. media-query-list-comma-space-before and media-query-list-comma-space-after.
  • In the case that a particular place needs more options, we could add another rule instead of opening up the existing one. For example, selector-delimiter-before and selector-delimiter-after (first of all, why not "comma" instead of "delimiter"?) ... so that might reasonably be either a space or a newline (though almost certainly not tab, carriage return, four spaces, etc.). We could make selector-delimiter-space and selector-delimiter-newline with before/after options; or, alternately, selector-delimiter-space-before and selector-delimiter-newline-before and their -after counterparts.

Handling of PostCSS syntax errors

We need some elegant handling of PostCSS syntax errors -- especially considering that it's kind of the first line of linting (will find errors in people's code even if they have not turned on any rules).

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.