@primer/stylelint-config 12.2.0 → 12.3.0-rc.f3d0e89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 12.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#191](https://github.com/primer/stylelint-config/pull/191) [`71c7985`](https://github.com/primer/stylelint-config/commit/71c79853b679b674c1d27686f8d2168660b24a45) Thanks [@jonrohan](https://github.com/jonrohan)! - Refactoring the primer/spacing plugin to better match results
8
+
3
9
  ## 12.2.0
4
10
 
5
11
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/stylelint-config",
3
- "version": "12.2.0",
3
+ "version": "12.3.0-rc.f3d0e89",
4
4
  "description": "Sharable stylelint config used by GitHub's CSS",
5
5
  "homepage": "http://primer.style/css/tools/linting",
6
6
  "author": "GitHub, Inc.",
@@ -44,16 +44,16 @@
44
44
  },
45
45
  "devDependencies": {
46
46
  "@changesets/changelog-github": "0.4.2",
47
- "@changesets/cli": "2.18.1",
47
+ "@changesets/cli": "2.19.0",
48
48
  "@github/prettier-config": "0.0.4",
49
49
  "@primer/css": "^19.0.0",
50
50
  "@primer/primitives": "^7.0.1",
51
51
  "dedent": "0.7.0",
52
- "eslint": "8.4.0",
52
+ "eslint": "8.5.0",
53
53
  "eslint-plugin-github": "4.3.5",
54
54
  "eslint-plugin-jest": "25.3.0",
55
55
  "eslint-plugin-prettier": "4.0.0",
56
- "jest": "27.4.3",
56
+ "jest": "27.4.5",
57
57
  "jest-preset-stylelint": "4.2.0",
58
58
  "prettier": "2.5.1",
59
59
  "stylelint": "14.1.0"
@@ -1,31 +1,123 @@
1
- const anymatch = require('anymatch')
2
- const {createVariableRule} = require('./lib/variable-rules')
3
-
4
- const spacerVarPatterns = ['$spacer-*', '$em-spacer-*']
5
- const values = [...spacerVarPatterns, '0', 'auto', 'inherit']
6
-
7
- module.exports = createVariableRule(
8
- 'primer/spacing',
9
- ({variables}) => {
10
- const spacerVars = Object.keys(variables).filter(anymatch(spacerVarPatterns))
11
- const negativeValues = spacerVarPatterns.map(p => `-${p}`)
12
- const replacements = {}
13
- for (const name of spacerVars) {
14
- replacements[`-${variables[name].computed}`] = `-${name}`
1
+ const stylelint = require('stylelint')
2
+ const declarationValueIndex = require('stylelint/lib/utils/declarationValueIndex')
3
+ const valueParser = require('postcss-value-parser')
4
+
5
+ const spacerValues = {
6
+ '$spacer-1': '4px',
7
+ '$spacer-2': '8px',
8
+ '$spacer-3': '16px',
9
+ '$spacer-4': '24px',
10
+ '$spacer-5': '32px',
11
+ '$spacer-6': '40px',
12
+ '$spacer-7': '48px',
13
+ '$spacer-8': '64px',
14
+ '$spacer-9': '80px',
15
+ '$spacer-10': '96px',
16
+ '$spacer-11': '112px',
17
+ '$spacer-12': '128px',
18
+ '$em-spacer-1': '0.0625em',
19
+ '$em-spacer-2': '0.125em',
20
+ '$em-spacer-3': '0.25em',
21
+ '$em-spacer-4': '0.375em',
22
+ '$em-spacer-5': '0.5em',
23
+ '$em-spacer-6': '0.75em'
24
+ }
25
+
26
+ const ruleName = 'primer/spacing'
27
+ const messages = stylelint.utils.ruleMessages(ruleName, {
28
+ rejected: (value, replacement) => {
29
+ if (replacement === null) {
30
+ return `Please use a primer spacer variable instead of '${value}'. Consult the primer docs for a suitable replacement. https://primer.style/css/support/spacing`
15
31
  }
16
- return {
17
- margin: {
18
- expects: 'a spacer variable',
19
- props: 'margin{,-top,-right,-bottom,-left}',
20
- values: values.concat(negativeValues),
21
- replacements
22
- },
23
- padding: {
24
- expects: 'a non-negative spacer variable',
25
- props: 'padding{,-top,-right,-bottom,-left}',
26
- values
32
+
33
+ return `Please replace ${value} with spacing variable '${replacement}'.`
34
+ }
35
+ })
36
+
37
+ // eslint-disable-next-line no-unused-vars
38
+ module.exports = stylelint.createPlugin(ruleName, (enabled, options = {}, context) => {
39
+ if (!enabled) {
40
+ return noop
41
+ }
42
+
43
+ const lintResult = (root, result) => {
44
+ root.walkDecls(/^(padding|margin)/, decl => {
45
+ const problems = []
46
+ let containsMath = false
47
+ let conatinsVariable = false
48
+ const parsedValue = valueParser(decl.value).walk(declValue => {
49
+ // Only check word types. https://github.com/TrySound/postcss-value-parser#word
50
+ if (!['word', 'function'].includes(declValue.type)) {
51
+ return false
52
+ }
53
+
54
+ // Ignore values that are not numbers.
55
+ if (['0', 'auto', 'inherit', 'initial'].includes(declValue.value)) {
56
+ return false
57
+ }
58
+ // Remove leading negative sign, if any.
59
+ const cleanDeclValue = declValue.value.replace(/^-/g, '')
60
+
61
+ // If the a variable is found in the value, skip it.
62
+ if (
63
+ Object.keys(spacerValues).some(variable =>
64
+ new RegExp(`${variable.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(cleanDeclValue)
65
+ )
66
+ ) {
67
+ conatinsVariable = true
68
+ return false
69
+ }
70
+
71
+ // For now we're going to ignore math.
72
+ if (['*', '+', '-', '/'].includes(declValue.value)) {
73
+ containsMath = true
74
+ return false
75
+ }
76
+
77
+ let valueMatch = null
78
+ if ((valueMatch = Object.keys(spacerValues).find(spacer => spacerValues[spacer] === cleanDeclValue))) {
79
+ if (context.fix) {
80
+ declValue.value = declValue.value.replace(spacerValues[valueMatch], valueMatch)
81
+ } else {
82
+ problems.push({
83
+ index: declarationValueIndex(decl) + declValue.sourceIndex,
84
+ message: messages.rejected(spacerValues[valueMatch], valueMatch)
85
+ })
86
+ }
87
+ } else if (declValue.value !== '' && declValue.type !== 'function' && !containsMath) {
88
+ problems.push({
89
+ index: declarationValueIndex(decl) + declValue.sourceIndex,
90
+ message: messages.rejected(declValue.value, null)
91
+ })
92
+ }
93
+ })
94
+
95
+ if (context.fix) {
96
+ decl.value = parsedValue.toString()
27
97
  }
28
- }
29
- },
30
- 'https://primer.style/css/support/spacing'
31
- )
98
+
99
+ if (containsMath && conatinsVariable) {
100
+ return false
101
+ }
102
+
103
+ if (problems.length) {
104
+ for (const err of problems) {
105
+ stylelint.utils.report({
106
+ index: err.index,
107
+ message: err.message,
108
+ node: decl,
109
+ result,
110
+ ruleName
111
+ })
112
+ }
113
+ }
114
+ })
115
+ }
116
+
117
+ return lintResult
118
+ })
119
+
120
+ function noop() {}
121
+
122
+ module.exports.ruleName = ruleName
123
+ module.exports.messages = messages