@primer/stylelint-config 13.0.0-rc.980b8d0 → 13.0.0-rc.99be5f2
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/dist/index.cjs +1732 -0
- package/dist/index.mjs +1729 -0
- package/package.json +11 -5
- package/plugins/lib/primitives.js +33 -0
- package/plugins/spacing.js +68 -63
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primer/stylelint-config",
|
|
3
|
-
"version": "13.0.0-rc.
|
|
3
|
+
"version": "13.0.0-rc.99be5f2",
|
|
4
4
|
"description": "Sharable stylelint config used by GitHub's CSS",
|
|
5
5
|
"author": "GitHub, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@github/browserslist-config": "^1.0.0",
|
|
47
47
|
"@primer/css": "^21.0.8",
|
|
48
|
-
"@primer/primitives": "^7.
|
|
48
|
+
"@primer/primitives": "^7.17.1",
|
|
49
49
|
"anymatch": "^3.1.1",
|
|
50
50
|
"postcss-scss": "^4.0.2",
|
|
51
51
|
"postcss-styled-syntax": "^0.6.4",
|
|
@@ -53,22 +53,28 @@
|
|
|
53
53
|
"string.prototype.matchall": "^4.0.2",
|
|
54
54
|
"stylelint": "^16.3.1",
|
|
55
55
|
"stylelint-config-standard": "^36.0.0",
|
|
56
|
+
"stylelint-css-modules-no-global-scoped-selector": "^1.0.2",
|
|
56
57
|
"stylelint-no-unsupported-browser-features": "^8.0.0",
|
|
57
58
|
"stylelint-order": "^6.0.4",
|
|
58
59
|
"stylelint-scss": "^6.2.0",
|
|
59
60
|
"stylelint-value-no-unknown-custom-properties": "^6.0.1",
|
|
60
61
|
"tap-map": "^1.0.0"
|
|
61
62
|
},
|
|
63
|
+
"overrides": {
|
|
64
|
+
"stylelint-css-modules-no-global-scoped-selector": {
|
|
65
|
+
"stylelint": "$stylelint"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
62
68
|
"prettier": "@github/prettier-config",
|
|
63
69
|
"devDependencies": {
|
|
64
|
-
"@changesets/changelog-github": "0.
|
|
65
|
-
"@changesets/cli": "2.
|
|
70
|
+
"@changesets/changelog-github": "^0.5.0",
|
|
71
|
+
"@changesets/cli": "2.27.1",
|
|
66
72
|
"@github/prettier-config": "^0.0.6",
|
|
67
73
|
"@rollup/plugin-commonjs": "^25.0.7",
|
|
68
74
|
"@rollup/plugin-json": "^6.1.0",
|
|
69
75
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
70
76
|
"@typescript-eslint/parser": "^7.7.0",
|
|
71
|
-
"dedent": "1.5.
|
|
77
|
+
"dedent": "^1.5.3",
|
|
72
78
|
"eslint": "^8.0.1",
|
|
73
79
|
"eslint-plugin-github": "^4.10.2",
|
|
74
80
|
"eslint-plugin-jest": "^28.2.0",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {createRequire} from 'node:module'
|
|
2
|
+
|
|
3
|
+
const require = createRequire(import.meta.url)
|
|
4
|
+
|
|
5
|
+
export async function primitivesVariables(type) {
|
|
6
|
+
const variables = []
|
|
7
|
+
|
|
8
|
+
const files = []
|
|
9
|
+
switch (type) {
|
|
10
|
+
case 'size':
|
|
11
|
+
files.push('base/size/size.json')
|
|
12
|
+
break
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
for (const file of files) {
|
|
16
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
17
|
+
const data = require(`@primer/primitives/dist/styleLint/${file}`)
|
|
18
|
+
|
|
19
|
+
for (const key of Object.keys(data)) {
|
|
20
|
+
const size = data[key]
|
|
21
|
+
const values = size['value']
|
|
22
|
+
values.push(`${parseInt(size['original']['value']) + 1}px`)
|
|
23
|
+
values.push(`${parseInt(size['original']['value']) - 1}px`)
|
|
24
|
+
|
|
25
|
+
variables.push({
|
|
26
|
+
name: `--${size['name']}`,
|
|
27
|
+
values,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return variables
|
|
33
|
+
}
|
package/plugins/spacing.js
CHANGED
|
@@ -1,39 +1,12 @@
|
|
|
1
1
|
import stylelint from 'stylelint'
|
|
2
2
|
import declarationValueIndex from 'stylelint/lib/utils/declarationValueIndex.cjs'
|
|
3
3
|
import valueParser from 'postcss-value-parser'
|
|
4
|
+
import {primitivesVariables} from './lib/primitives.js'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
'$spacer-3': '16px',
|
|
10
|
-
'$spacer-4': '24px',
|
|
11
|
-
'$spacer-5': '32px',
|
|
12
|
-
'$spacer-6': '40px',
|
|
13
|
-
'$spacer-7': '48px',
|
|
14
|
-
'$spacer-8': '64px',
|
|
15
|
-
'$spacer-9': '80px',
|
|
16
|
-
'$spacer-10': '96px',
|
|
17
|
-
'$spacer-11': '112px',
|
|
18
|
-
'$spacer-12': '128px',
|
|
19
|
-
'$em-spacer-1': '0.0625em',
|
|
20
|
-
'$em-spacer-2': '0.125em',
|
|
21
|
-
'$em-spacer-3': '0.25em',
|
|
22
|
-
'$em-spacer-4': '0.375em',
|
|
23
|
-
'$em-spacer-5': '0.5em',
|
|
24
|
-
'$em-spacer-6': '0.75em',
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const ruleName = 'primer/spacing'
|
|
28
|
-
export const messages = stylelint.utils.ruleMessages(ruleName, {
|
|
29
|
-
rejected: (value, replacement) => {
|
|
30
|
-
if (replacement === null) {
|
|
31
|
-
return `Please use a primer spacer variable instead of '${value}'. Consult the primer docs for a suitable replacement. https://primer.style/css/storybook/?path=/docs/support-spacing--docs`
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return `Please replace ${value} with spacing variable '${replacement}'.`
|
|
35
|
-
},
|
|
36
|
-
})
|
|
6
|
+
const {
|
|
7
|
+
createPlugin,
|
|
8
|
+
utils: {report, ruleMessages, validateOptions},
|
|
9
|
+
} = stylelint
|
|
37
10
|
|
|
38
11
|
const walkGroups = (root, validate) => {
|
|
39
12
|
for (const node of root.nodes) {
|
|
@@ -46,24 +19,47 @@ const walkGroups = (root, validate) => {
|
|
|
46
19
|
return root
|
|
47
20
|
}
|
|
48
21
|
|
|
49
|
-
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
22
|
+
export const ruleName = 'primer/spacing'
|
|
23
|
+
export const messages = ruleMessages(ruleName, {
|
|
24
|
+
rejected: (value, replacement) => {
|
|
25
|
+
if (!replacement) {
|
|
26
|
+
return `Please use a primer size variable instead of '${value}'. Consult the primer docs for a suitable replacement. https://primer.style/foundations/primitives/size`
|
|
27
|
+
}
|
|
54
28
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return noop
|
|
59
|
-
}
|
|
29
|
+
return `Please replace '${value}' with size variable '${replacement['name']}'. https://primer.style/foundations/primitives/size`
|
|
30
|
+
},
|
|
31
|
+
})
|
|
60
32
|
|
|
61
|
-
|
|
33
|
+
const meta = {
|
|
34
|
+
fixable: true,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** @type {import('stylelint').Rule} */
|
|
38
|
+
const ruleFunction = (primary, secondaryOptions, context) => {
|
|
39
|
+
return async (root, result) => {
|
|
40
|
+
// Props that we want to check
|
|
41
|
+
const propList = ['padding', 'margin', 'top', 'right', 'bottom', 'left']
|
|
42
|
+
// Values that we want to ignore
|
|
43
|
+
const valueList = ['${']
|
|
44
|
+
|
|
45
|
+
const sizes = await primitivesVariables('size')
|
|
46
|
+
|
|
47
|
+
const validOptions = validateOptions(result, ruleName, {
|
|
48
|
+
actual: primary,
|
|
49
|
+
possible: [true],
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
if (!validOptions) return
|
|
53
|
+
|
|
54
|
+
root.walkDecls(declNode => {
|
|
55
|
+
const {prop, value} = declNode
|
|
62
56
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const cleanValue = node.value.replace(/^-/g, '')
|
|
57
|
+
if (!propList.some(spacingProp => prop.startsWith(spacingProp))) return
|
|
58
|
+
if (valueList.some(valueToIgnore => value.includes(valueToIgnore))) return
|
|
66
59
|
|
|
60
|
+
const problems = []
|
|
61
|
+
|
|
62
|
+
const parsedValue = walkGroups(valueParser(value), node => {
|
|
67
63
|
// Only check word types. https://github.com/TrySound/postcss-value-parser#word
|
|
68
64
|
if (node.type !== 'word') {
|
|
69
65
|
return
|
|
@@ -74,30 +70,36 @@ export default stylelint.createPlugin(ruleName, (enabled, options = {}, context)
|
|
|
74
70
|
return
|
|
75
71
|
}
|
|
76
72
|
|
|
77
|
-
const valueUnit = valueParser.unit(
|
|
73
|
+
const valueUnit = valueParser.unit(node.value)
|
|
78
74
|
|
|
79
|
-
if (valueUnit && (valueUnit.unit === '' ||
|
|
75
|
+
if (valueUnit && (valueUnit.unit === '' || !/^-?[0-9.]+$/.test(valueUnit.number))) {
|
|
80
76
|
return
|
|
81
77
|
}
|
|
82
78
|
|
|
83
|
-
//
|
|
79
|
+
// Skip if the value unit isn't a supported unit.
|
|
80
|
+
if (valueUnit && !['px', 'rem', 'em'].includes(valueUnit.unit)) {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// If the variable is found in the value, skip it.
|
|
84
85
|
if (
|
|
85
|
-
|
|
86
|
-
new RegExp(`${variable.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(
|
|
86
|
+
sizes.some(variable =>
|
|
87
|
+
new RegExp(`${variable['name'].replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(node.value),
|
|
87
88
|
)
|
|
88
89
|
) {
|
|
89
90
|
return
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
const replacement =
|
|
93
|
-
const
|
|
93
|
+
const replacement = sizes.find(variable => variable.values.includes(node.value.replace('-', '')))
|
|
94
|
+
const fixable = replacement && valueUnit && !valueUnit.number.includes('-')
|
|
94
95
|
|
|
95
|
-
if (
|
|
96
|
-
node.value = node.value.replace(
|
|
96
|
+
if (fixable && context.fix) {
|
|
97
|
+
node.value = node.value.replace(node.value, `var(${replacement['name']})`)
|
|
97
98
|
} else {
|
|
98
99
|
problems.push({
|
|
99
|
-
index: declarationValueIndex(
|
|
100
|
-
|
|
100
|
+
index: declarationValueIndex(declNode) + node.sourceIndex,
|
|
101
|
+
endIndex: declarationValueIndex(declNode) + node.sourceIndex + node.value.length,
|
|
102
|
+
message: messages.rejected(node.value, replacement),
|
|
101
103
|
})
|
|
102
104
|
}
|
|
103
105
|
|
|
@@ -105,15 +107,16 @@ export default stylelint.createPlugin(ruleName, (enabled, options = {}, context)
|
|
|
105
107
|
})
|
|
106
108
|
|
|
107
109
|
if (context.fix) {
|
|
108
|
-
|
|
110
|
+
declNode.value = parsedValue.toString()
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
if (problems.length) {
|
|
112
114
|
for (const err of problems) {
|
|
113
|
-
|
|
115
|
+
report({
|
|
114
116
|
index: err.index,
|
|
117
|
+
endIndex: err.endIndex,
|
|
115
118
|
message: err.message,
|
|
116
|
-
node:
|
|
119
|
+
node: declNode,
|
|
117
120
|
result,
|
|
118
121
|
ruleName,
|
|
119
122
|
})
|
|
@@ -121,8 +124,10 @@ export default stylelint.createPlugin(ruleName, (enabled, options = {}, context)
|
|
|
121
124
|
}
|
|
122
125
|
})
|
|
123
126
|
}
|
|
127
|
+
}
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
ruleFunction.ruleName = ruleName
|
|
130
|
+
ruleFunction.messages = messages
|
|
131
|
+
ruleFunction.meta = meta
|
|
127
132
|
|
|
128
|
-
|
|
133
|
+
export default createPlugin(ruleName, ruleFunction)
|