Skip to content

Commit

Permalink
Merge pull request #53 from primer/release-9.0.0
Browse files Browse the repository at this point in the history
Release 9.0.0
  • Loading branch information
shawnbot authored Oct 30, 2019
2 parents 1f4a005 + 8d6512f commit 6e88bbf
Show file tree
Hide file tree
Showing 27 changed files with 1,551 additions and 993 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
version: 11
node-version: 11
- name: install
run: npm install
- name: lint
Expand Down
45 changes: 44 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
# HEAD
# 9.0.0

### :boom: Breaking Change
- `primer/variables` is no longer supported; please use the `primer/colors`, `primer/borders`, `primer/box-shadow`, `primer/spacing`, and `primer/typography` rules instead. #50

### :rocket: Enhancements
- The new `primer/colors` rule enforces color variable usage in `color`, `background-color`, and `fill` properties
- The new `primer/borders` rule enforces border variable usage in border CSS props
- The new `primer/box-shadow` rule enforces `$box-shadow*` variables
- The new `primer/spacing` rule enforces `$spacer-*` variables in margin and padding props
- The new `primer/typography` rule enforces typography variable use in `font-family`, `line-height`, and `font-weight` props
- Variable replacements for autofixing are automatically detected in variable data from Primer CSS (see: https://github.com/primer/css/pull/949) #52
- It is now possible to define variable rules using functions that take the variables, as in:
```js
module.exports = createVariableRule('primer/whatever', ({variables}) => {
/* do something with variables here */
})
```
- It's also now possible to provide rule _overrides_ in local stylelint configs as functions:
```js
module.exports = {
extends: 'stylelint-config-primer',
rules: {
'primer/colors': [true, {
rules: ({variables, rules}) => {
/* do something with variables and/or rules here */
return rules
}]
}
})
```
- This release adds support for an optional `singular: true` flag to rule configs, which skips the parsing of individual values in the matched properties. We use this in `primer/box-shadow` to prevent multiple warnings for a single value like `box-shadow: inset 0 1px $blue` (before there would be 4 separate ones!).
### :bug: Bug fixes
- Use `requirePrimerFile()` when loading `dist/variables.json` so that we can access the right file when running _within_ the `@primer/css` repo.
- Walk only declarations (`prop: value`) in rules (blocks with selectors, _not_ `@rules`), and skip linting for declarations nested in `@each`, `@for`, `@function`, and `@mixin` blocks, since those can define their own variables and we can't reliably assert their values.
- Allow `$*-shadow` variable patterns in `primer/box-shadow` to match `$btn-active-shadow` and `$form-control-shadow`
- Allow `color: inherit` in `primer/colors`
- Allow `$em-spacer-*` in `padding` and `margin` properties
- Allow (and auto-fix!) negative spacer variables in `margin` properties
- Make `primer/colors` smarter re: `background` property shorthand values (allowing positions and image `url(*)` values)
- Remove `100%` from allowed values for `border-radius`, and suggest `50%` instead
- Prohibit negative spacer values in `padding` properties
- Allow `$h000-size` for marketing 😬

# 2.0.0

Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ Within your [stylelint config object](http://stylelint.io/user-guide/configurati
* [stylelint-scss](https://github.com/kristerkari/stylelint-scss): A collection of SCSS specific linting rules for stylelint
* [scss/selector-no-redundant-nesting-selector](https://github.com/kristerkari/stylelint-scss/blob/master/src/rules/selector-no-redundant-nesting-selector/README.md): Disallow redundant nesting selectors (`&`).
* [primer/no-override](./plugins/#primerno-override): Prohibits custom styles that target Primer CSS selectors.
* [primer/no-unused-vars](./plugins/primerno-unused-vars): Warns about SCSS variables that are declared by not used in your local files.
* [primer/variables](./plugins/primervariables): Constrains certain CSS properties to Primer CSS variables for consistency of color, typography, whitespace, etc.
* [primer/no-unused-vars](./plugins/#primerno-unused-vars): Warns about SCSS variables that are declared by not used in your local files.
- [primer/colors](./plugins/#primercolors): Enforces the use of certain color variables.
- [primer/spacing](./plugins/#primerspacing): Enforces the use of spacing variables for margin and padding.
- [primer/typography](./plugins/#primertypography): Enforces the use of typography variables for certain CSS properties.
- [primer/borders](./plugins/#primerborders): Enforces the use of certain variables for border properties.
- [primer/box-shadow](./plugins/#primerbox-shadow): Enforces the use of certain variables for `box-shadow`.

### Configured lints

Expand Down
132 changes: 132 additions & 0 deletions __tests__/borders.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
const dedent = require('dedent')
const stylelint = require('stylelint')
const pluginPath = require.resolve('../plugins/borders')

const ruleName = 'primer/borders'
const configWithOptions = args => ({
plugins: [pluginPath],
rules: {
[ruleName]: args
}
})

describe(ruleName, () => {
it('reports compound border properties', () => {
return stylelint
.lint({
code: `
.foo { border: $red; }
`,
config: configWithOptions(true)
})
.then(data => {
expect(data).toHaveErrored()
expect(data).toHaveWarnings([`Please use "$border-red" instead of "$red". (${ruleName})`])
})
})

it('reports multiple border properties', () => {
return stylelint
.lint({
code: `
.foo { border: 1px solid gray; }
`,
config: configWithOptions(true)
})
.then(data => {
expect(data).toHaveErrored()
expect(data).toHaveWarnings([
`Please use "$border-width" instead of "1px". (${ruleName})`,
`Please use "$border-style" instead of "solid". (${ruleName})`,
`Please use a border color variable instead of "gray". (${ruleName})`
])
})
})

it('recognizes function calls as whole tokens', () => {
return stylelint
.lint({
code: `
.foo { border: calc($spacer-2 + var(--derp)) $border-style rgba($border-gray-dark, 50%); }
`,
config: configWithOptions(true)
})
.then(data => {
expect(data).toHaveErrored()
expect(data).toHaveWarnings([
`Please use a border width variable instead of "calc($spacer-2 + var(--derp))". (${ruleName})`,
`Please use a border color variable instead of "rgba($border-gray-dark, 50%)". (${ruleName})`
])
})
})

it('allows $border shorthand in border{,-top,-right,-bottom,-left}', () => {
return stylelint
.lint({
code: dedent`
.a { border: $border; }
.b { border-top: $border; }
.c { border-right: $border; }
.d { border-bottom: $border; }
.e { border-left: $border; }
`,
config: configWithOptions(true)
})
.then(data => {
expect(data).not.toHaveErrored()
expect(data).toHaveWarningsLength(0)
})
})

describe('autofix', () => {
it('fixes border variables', () => {
return stylelint
.lint({
code: dedent`
.a { border: 1px solid $gray-300; }
.b { border: 1px solid $gray-200; }
.c { border: solid 1px $border-gray; }
.d { border: 1px $border-color solid; }
`,
config: configWithOptions(true),
fix: true
})
.then(data => {
expect(data).not.toHaveErrored()
expect(data).toHaveWarningsLength(0)
expect(data.output).toEqual(dedent`
.a { border: $border-width $border-style $border-gray-dark; }
.b { border: $border; }
.c { border: $border; }
.d { border: $border; }
`)
})
})

it('fixes border radius', () => {
return stylelint
.lint({
code: dedent`
.x { border-radius: 3px; }
.y {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
`,
config: configWithOptions(true),
fix: true
})
.then(data => {
expect(data).not.toHaveErrored()
expect(data).toHaveWarningsLength(0)
expect(data.output).toEqual(dedent`
.x { border-radius: $border-radius; }
.y {
border-top-left-radius: $border-radius;
border-bottom-left-radius: $border-radius;
}
`)
})
})
})
})
48 changes: 48 additions & 0 deletions __tests__/box-shadow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const dedent = require('dedent')
const stylelint = require('stylelint')
const pluginPath = require.resolve('../plugins/box-shadow')

const ruleName = 'primer/box-shadow'
const configWithOptions = args => ({
plugins: [pluginPath],
rules: {
[ruleName]: args
}
})

describe(ruleName, () => {
it('works', () => {
return stylelint
.lint({
code: `.x { box-shadow: 0 1px 1px rgba($black, 0.1); }`,
config: configWithOptions(true)
})
.then(data => {
expect(data).toHaveErrored()
expect(data).toHaveWarningsLength(1)
expect(data).toHaveWarnings([
`Please use "$box-shadow" instead of "0 1px 1px rgba($black, 0.1)". (${ruleName})`
])
})
})

describe('autofix', () => {
it('fixes box shadow variables', () => {
return stylelint
.lint({
code: dedent`
.x { box-shadow: 0 1px 1px rgba($black, 0.1); }
`,
config: configWithOptions(true),
fix: true
})
.then(data => {
expect(data).not.toHaveErrored()
expect(data).toHaveWarningsLength(0)
expect(data.output).toEqual(dedent`
.x { box-shadow: $box-shadow; }
`)
})
})
})
})
Loading

0 comments on commit 6e88bbf

Please sign in to comment.