@primer/stylelint-config 12.3.3-rc.c178bc3 → 12.4.0-rc.a92b3f2

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.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#232](https://github.com/primer/stylelint-config/pull/232) [`27ddfc9`](https://github.com/primer/stylelint-config/commit/27ddfc98f93ed898552bb62aa0926d35497dda72) Thanks [@jonrohan](https://github.com/jonrohan)! - Creating a responsive-widths plugin to keep fixed widths smaller than the minimum viewport size
8
+
3
9
  ## 12.3.3
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -39,6 +39,7 @@ Primer Stylelint Config extends the [stylelint-config-standard](https://github.c
39
39
  - [primer/typography](./plugins/#primertypography): Enforces the use of typography variables for certain CSS properties.
40
40
  - [primer/borders](./plugins/#primerborders): Enforces the use of certain variables for border properties.
41
41
  - [primer/box-shadow](./plugins/#primerbox-shadow): Enforces the use of certain variables for `box-shadow`.
42
+ - [primer/responsive-widths](./plugins/#primerresponsive-widths): Errors on `width` and `min-width` that is larger than the minimum browser size supported. `320px`
42
43
 
43
44
  ## License
44
45
 
package/index.js CHANGED
@@ -17,6 +17,7 @@ module.exports = {
17
17
  './plugins/borders',
18
18
  './plugins/box-shadow',
19
19
  './plugins/colors',
20
+ './plugins/responsive-widths',
20
21
  './plugins/spacing',
21
22
  './plugins/typography'
22
23
  ],
@@ -64,6 +65,7 @@ module.exports = {
64
65
  {severity: 'warning', files: 'node_modules/@primer/primitives/dist/scss/colors*/*.scss'}
65
66
  ],
66
67
  'primer/no-unused-vars': [true, {severity: 'warning'}],
68
+ 'primer/responsive-widths': true,
67
69
  'primer/spacing': true,
68
70
  'primer/typography': true,
69
71
  'scss/at-extend-no-missing-placeholder': true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/stylelint-config",
3
- "version": "12.3.3-rc.c178bc3",
3
+ "version": "12.4.0-rc.a92b3f2",
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.",
@@ -31,7 +31,7 @@
31
31
  "postcss-scss": "^4.0.2",
32
32
  "postcss-value-parser": "^4.0.2",
33
33
  "string.prototype.matchall": "^4.0.2",
34
- "stylelint-config-standard": "24.0.0",
34
+ "stylelint-config-standard": "25.0.0",
35
35
  "stylelint-no-unsupported-browser-features": "^5.0.1",
36
36
  "stylelint-order": "^5.0.0",
37
37
  "stylelint-scss": "^4.0.0",
@@ -43,20 +43,20 @@
43
43
  "stylelint": ">= 14.0.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@changesets/changelog-github": "0.4.2",
47
- "@changesets/cli": "2.20.0",
46
+ "@changesets/changelog-github": "0.4.3",
47
+ "@changesets/cli": "2.21.1",
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.8.0",
52
+ "eslint": "8.11.0",
53
53
  "eslint-plugin-github": "4.3.5",
54
- "eslint-plugin-jest": "26.0.0",
54
+ "eslint-plugin-jest": "26.1.1",
55
55
  "eslint-plugin-prettier": "4.0.0",
56
- "jest": "27.4.7",
57
- "jest-preset-stylelint": "4.2.0",
58
- "prettier": "2.5.1",
59
- "stylelint": "14.3.0"
56
+ "jest": "27.5.1",
57
+ "jest-preset-stylelint": "5.0.1",
58
+ "prettier": "2.6.0",
59
+ "stylelint": "14.6.0"
60
60
  },
61
61
  "jest": {
62
62
  "preset": "jest-preset-stylelint",
package/plugins/README.md CHANGED
@@ -17,6 +17,7 @@ This directory contains all of our custom stylelint plugins, each of which provi
17
17
  - [`primer/typography`](#primertypography)
18
18
  - [`primer/borders`](#primerborders)
19
19
  - [`primer/box-shadow`](#primerbox-shadow)
20
+ - [`primer/responsive-widths`](#primerresponsive-widths)
20
21
  - [Variable rules](#variable-rules)
21
22
  - [Variable rule options](#variable-rule-options)
22
23
 
@@ -207,6 +208,10 @@ This [variable rule](#variable-rules) enforces the use of border-specific variab
207
208
 
208
209
  This [variable rule](#variable-rules) enforces the use of `$box-shadow*` variables for the `box-shadow` CSS property. See [the configuration](./box-shadow.js) for more info.
209
210
 
211
+ ## `primer/responsive-widths`
212
+
213
+ This plugin checks for `width` and `min-width` declarations that use a value less than the minimum browser size. `320px`
214
+
210
215
  ## Variable rules
211
216
 
212
217
  Variable rules are created using a general-purpose helper that can validate constraints for matching CSS properties and values. In general, the Primer CSS variable rules enforce two basic principles for custom CSS:
@@ -0,0 +1,98 @@
1
+ const stylelint = require('stylelint')
2
+ const declarationValueIndex = require('stylelint/lib/utils/declarationValueIndex')
3
+ const valueParser = require('postcss-value-parser')
4
+
5
+ const ruleName = 'primer/responsive-widths'
6
+
7
+ const messages = stylelint.utils.ruleMessages(ruleName, {
8
+ rejected: value => {
9
+ return `A value larger than the smallest viewport could break responsive pages. Use a width value smaller than ${value}. https://primer.style/css/support/breakpoints`
10
+ }
11
+ })
12
+
13
+ // 320px is the smallest viewport size that we support
14
+
15
+ const walkGroups = (root, validate) => {
16
+ for (const node of root.nodes) {
17
+ if (node.type === 'function') {
18
+ walkGroups(node, validate)
19
+ } else {
20
+ validate(node)
21
+ }
22
+ }
23
+ return root
24
+ }
25
+
26
+ // eslint-disable-next-line no-unused-vars
27
+ module.exports = stylelint.createPlugin(ruleName, (enabled, options = {}, context) => {
28
+ if (!enabled) {
29
+ return noop
30
+ }
31
+
32
+ const lintResult = (root, result) => {
33
+ root.walk(decl => {
34
+ // Ignore things inside of breakpoints
35
+ if (decl.type === 'atrule' && decl.name === 'include' && decl.params.includes('breakpoint')) {
36
+ return false
37
+ }
38
+
39
+ if (decl.type !== 'decl' || !decl.prop.match(/^(min-width|width)/)) {
40
+ return noop
41
+ }
42
+
43
+ const problems = []
44
+
45
+ walkGroups(valueParser(decl.value), node => {
46
+ // Only check word types. https://github.com/TrySound/postcss-value-parser#word
47
+ if (node.type !== 'word') {
48
+ return
49
+ }
50
+
51
+ // Exact values to ignore.
52
+ if (['*', '+', '-', '/', '0', 'auto', 'inherit', 'initial'].includes(node.value)) {
53
+ return
54
+ }
55
+
56
+ const valueUnit = valueParser.unit(node.value)
57
+
58
+ switch (valueUnit.unit) {
59
+ case 'px':
60
+ if (parseInt(valueUnit.number) > 320) {
61
+ problems.push({
62
+ index: declarationValueIndex(decl) + node.sourceIndex,
63
+ message: messages.rejected(node.value)
64
+ })
65
+ }
66
+ break
67
+ case 'vw':
68
+ if (parseInt(valueUnit.number) > 100) {
69
+ problems.push({
70
+ index: declarationValueIndex(decl) + node.sourceIndex,
71
+ message: messages.rejected(node.value)
72
+ })
73
+ }
74
+ break
75
+ }
76
+ })
77
+
78
+ if (problems.length) {
79
+ for (const err of problems) {
80
+ stylelint.utils.report({
81
+ index: err.index,
82
+ message: err.message,
83
+ node: decl,
84
+ result,
85
+ ruleName
86
+ })
87
+ }
88
+ }
89
+ })
90
+ }
91
+
92
+ return lintResult
93
+ })
94
+
95
+ function noop() {}
96
+
97
+ module.exports.ruleName = ruleName
98
+ module.exports.messages = messages