├── .gitattributes
├── .github
├── dependabot.yml
└── workflows
│ └── test.yml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── RELEASE.md
├── __tests__
├── README.md
├── at-rule-disallowed-list.test.mjs
├── at-rule-no-unknown.test.mjs
├── at-rule-no-vendor-prefix.test.mjs
├── block-no-empty.test.mjs
├── block-opening-brace-space-before.test.mjs
├── color-hex-case.test.mjs
├── color-hex-length.test.mjs
├── color-named.test.mjs
├── color-no-invalid-hex.test.mjs
├── declaration-bang-space-after.test.mjs
├── declaration-bang-space-before.test.mjs
├── declaration-block-semicolon-newline-after.test.mjs
├── declaration-block-semicolon-space-before.test.mjs
├── declaration-block-single-line-max-declarations.test.mjs
├── declaration-block-trailing-semicolon.test.mjs
├── declaration-colon-space-after.test.mjs
├── declaration-colon-space-before.test.mjs
├── declaration-property-value-disallowed-list.test.mjs
├── function-comma-space-after.test.mjs
├── function-parentheses-space-inside.test.mjs
├── function-url-quotes.test.mjs
├── indentation.test.mjs
├── length-zero-no-unit.test.mjs
├── max-nesting-depth.test.mjs
├── media-feature-name-no-vendor-prefix.test.mjs
├── media-feature-parentheses-space-inside.test.mjs
├── misc-valid-scss.test.mjs
├── no-missing-end-of-source-newline.test.mjs
├── number-leading-zero.test.mjs
├── number-no-trailing-zeros.test.mjs
├── property-no-unknown.test.mjs
├── property-no-vendor-prefix.test.mjs
├── rule-empty-line-before.test.mjs
├── scss-at-extend-no-missing-placeholder.test.mjs
├── scss-at-function-pattern.test.mjs
├── scss-at-import-partial-extension-disallowed-list.test.mjs
├── scss-at-rule-no-unknown.test.mjs
├── scss-dollar-variable-colon-space-after.test.mjs
├── scss-dollar-variable-colon-space-before.test.mjs
├── scss-dollar-variable-pattern.test.mjs
├── scss-load-no-partial-leading-underscore.test.mjs
├── scss-no-global-function-names.test.mjs
├── scss-percent-placeholder-pattern.mjs
├── scss-selector-no-redundant-nesting-selector.test.mjs
├── selector-class-pattern.test.mjs
├── selector-list-comma-newline-after.test.mjs
├── selector-max-compound-selectors.test.mjs
├── selector-max-id.test.mjs
├── selector-no-qualifying-type.test.mjs
├── selector-no-vendor-prefix.test.mjs
├── selector-pseudo-element-colon-notation.test.mjs
├── selector-pseudo-element-no-unknown.test.mjs
├── shorthand-property-no-redundant-values.test.mjs
├── string-quotes.test.mjs
└── value-no-vendor-prefix.test.mjs
├── index.js
├── package-lock.json
└── package.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 10
8 | # Increase the version requirement only when required by the new version.
9 | # More info: https://help.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#versioning-strategy
10 | versioning-strategy: increase-if-necessary
11 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 | env:
4 | CI: true
5 |
6 | jobs:
7 | run:
8 | name: Node ${{ matrix.node }} on ${{ matrix.os }}
9 | runs-on: ${{ matrix.os }}
10 |
11 | strategy:
12 | fail-fast: false
13 | matrix:
14 | node: [18, 20, 22]
15 | os: [ubuntu-latest]
16 |
17 | steps:
18 | - name: Clone repository
19 | uses: actions/checkout@v2
20 |
21 | - name: Set Node.js version
22 | uses: actions/setup-node@v1
23 | with:
24 | node-version: ${{ matrix.node }}
25 |
26 | - run: node --version
27 | - run: npm --version
28 |
29 | - name: Install npm dependencies
30 | run: npm ci
31 |
32 | - name: Run tests
33 | run: npm run test
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.css.map
2 | .bundle
3 | .sass-cache
4 | node_modules
5 | npm-debug.log
6 | vendor
7 | coverage
8 | .nyc_output
9 | .history
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6 |
7 | ## [12.1.0]
8 | Full list of changes can be [viewed here](https://github.com/bjankord/stylelint-config-sass-guidelines/compare/v12.0.0...v12.1.0)
9 | ### Changed
10 | - Bumped @stylistic/stylelint-plugin from 2.1.2 to 3.0.1
11 | - Bumped stylelint from 16.6.1 to 16.9.0
12 | - Bumped postcss from 8.4.39 to 8.4.45
13 | - Bumped stylelint-scss from 6.4.1 to 6.6.0
14 |
15 | ## [12.0.0]
16 | Full list of changes can be [viewed here](https://github.com/bjankord/stylelint-config-sass-guidelines/compare/v11.1.0...v12.0.0)
17 | ### Added
18 | - Added the following stylistic rules back that were removed in v10 thanks to the [@stylistic/stylelint-plugin](https://github.com/stylelint-stylistic/stylelint-stylistic/tree/main)
19 | - `@stylistic/block-opening-brace-space-before`
20 | - `@stylistic/color-hex-case`
21 | - `@stylistic/declaration-bang-space-after`
22 | - `@stylistic/declaration-bang-space-before`
23 | - `@stylistic/declaration-block-semicolon-newline-after`
24 | - `@stylistic/declaration-block-semicolon-space-before`
25 | - `@stylistic/declaration-block-trailing-semicolon`
26 | - `@stylistic/declaration-colon-space-after`
27 | - `@stylistic/declaration-colon-space-before`
28 | - `@stylistic/function-comma-space-after`
29 | - `@stylistic/function-parentheses-space-inside`
30 | - `@stylistic/indentation`
31 | - `@stylistic/media-feature-parentheses-space-inside`
32 | - `@stylistic/no-missing-end-of-source-newline`
33 | - `@stylistic/number-leading-zero`
34 | - `@stylistic/number-no-trailing-zeros`
35 | - `@stylistic/selector-list-comma-newline-after`
36 | - `@stylistic/string-quotes`
37 |
38 | ## [11.1.0]
39 | Full list of changes can be [viewed here](https://github.com/bjankord/stylelint-config-sass-guidelines/compare/v11.0.0...v11.1.0)
40 | ### Changed
41 | - Replaced deprecated `scss/at-import-partial-extension-blacklist` with `scss/at-import-partial-extension-disallowed-list` rule. [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/317)
42 | - Modernized unit test to use node:test. [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/318)
43 | - Minor dependency updates
44 |
45 | ## [11.0.0]
46 | ### Changed
47 | - Updated package to be compatible with stylelint v16
48 | - Replaced deprecated `"scss/at-import-no-partial-leading-underscore": true` rule with new `"scss/load-no-partial-leading-underscore": true` rule
49 |
50 | ### Removed
51 | - Removed Node.js less than 18.12.0 support
52 |
53 | ## [10.0.0]
54 | ### Changed
55 | - Updated package to be compatible with stylelint v15
56 |
57 | ### Added
58 | - Added node 18 to automated test matrix
59 | - Added scss/no-global-function-names rule. Resolves [#268](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/268)
60 |
61 | ### Removed
62 | - Dropped official support for Node 12
63 | - Removed node 12 from automated test matrix
64 | - Removed stylelint-order plugin. Resolves [#214](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/214) and [#231](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/231)
65 | - Removed tests for deprecated stylelint rules
66 | - Removed deprecated stylelint rules
67 | - "block-opening-brace-space-before": "always"
68 | - "color-hex-case": "lower"
69 | - "declaration-bang-space-after": "never"
70 | - "declaration-bang-space-before": "always"
71 | - "declaration-block-semicolon-newline-after": "always"
72 | - "declaration-block-semicolon-space-before": "never"
73 | - "declaration-block-trailing-semicolon": "always"
74 | - "declaration-colon-space-after": "always-single-line"
75 | - "declaration-colon-space-before": "never"
76 | - "function-comma-space-after": "always-single-line"
77 | - "function-parentheses-space-inside": "never"
78 | - "indentation": 2
79 | - "media-feature-parentheses-space-inside": "never"
80 | - "no-missing-end-of-source-newline": true
81 | - "number-leading-zero": "always"
82 | - "number-no-trailing-zeros": true
83 | - "selector-list-comma-newline-after": "always"
84 | - "string-quotes": "single"
85 | - Removed scss/at-mixin-pattern rule. Resolves [#181](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/181) and [#191](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/191)
86 |
87 | ## [9.0.1]
88 | ### Changed
89 | - Add postcss ^8.3.3 as a peerDependency. Mitigates https://github.com/bjankord/stylelint-config-sass-guidelines/issues/203
90 |
91 | ## [9.0.0]
92 | ### Changed
93 | - Updated repo to be compatible with stylelint v14. Updated stylelint peerDependency range from `^13.0.0` to `^14.0.0` [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/197)
94 | - Renamed tests files extension from `.js`to `.spec.js`
95 | - Moved manually tested passing and failing SCSS examples into `__tests__/manual-test-cases`
96 |
97 | ### Added
98 | - Added node 16 to automated test matrix
99 |
100 | ### Removed
101 | - Dropped official support for Node 10 [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/197)
102 | - Removed node 10 from automated test matrix [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/198)
103 | - Removed babel as a dev dependency, resolves issue with security vuln in glob-parent CVE-2020-28469
104 | - Removed `src/.stylelint.json`
105 |
106 | ## [8.0.0]
107 | ### Added
108 | - Set node engine minimum to version 10.0.0
109 | - Added node 14 to automated test matrix
110 |
111 | ### Removed
112 | - Dropped official support for Node 8
113 | - Removed node 8 from automated test matrix
114 |
115 | ## [7.1.0]
116 | ### Changed
117 | - Add dependabot integration to help with keeping dependencies up to date and secure
118 | - Bumped up `stylelint` peer/dev dependency to v13.7.0
119 |
120 | ### Fixed
121 | - Replaced deprecated `at-rule-blacklist` rule with `at-rule-disallowed-list` rule
122 | - Replaced deprecated `declaration-property-value-blacklist` rule with `declaration-property-value-disallowed-list` rule
123 |
124 | ### Removed
125 | - Removed unused scss-lint files, these were only used to generate lint errors for comparison with stylelint and did not play a functional role in how this stylelint config worked
126 | - Removed unused Gemfile
127 | - Removed unused Gemfile.lock
128 | - Removed src/.scss-lint.yml
129 |
130 | ## [7.0.0]
131 | ### Changed
132 | - Updated stylelint peerDependency range from `^10.0.1 || ^11.0.0 || ^12.0.0` to `^13.0.0`
133 |
134 | **Node.js v10 or newer** is required. That's because stylelint v13 itself [doesn't support Node.js versions below 10](https://github.com/stylelint/stylelint/blob/master/CHANGELOG.md#1300).
135 |
136 | - Bumped up `stylelint-order` dependency to `^4.0.0`
137 | - Update test expectations to not require specific error message order
138 |
139 | ## [7.0.0]
140 | ### Changed
141 | - Updated stylelint peerDependency range from `^10.0.1 || ^11.0.0 || ^12.0.0` to `^13.0.0`
142 |
143 | **Node.js v10 or newer** is required. That's because stylelint v13 itself [doesn't support Node.js versions below 10](https://github.com/stylelint/stylelint/blob/master/CHANGELOG.md#1300).
144 |
145 | - Bumped up `stylelint-order` dependency to `^4.0.0`
146 | - Update test expectations to not require specific error message order
147 |
148 | ## [6.2.0]
149 | ### Changed
150 | - Updated stylelint peerDependency range from `^10.0.1 || ^11.0.0` to `^10.0.1 || ^11.0.0 || ^12.0.0` to include stylelint 12
151 |
152 | ## [6.1.0]
153 | ### Changed
154 | - Updated stylelint peerDependency range from `^10.0.1` to `^10.0.1 || ^11.0.0`
155 |
156 | ## [6.0.0]
157 | ### Changed
158 | - Bumped up `stylelint` peer/dev dependency to `^10.0.1`
159 | - Bumped up `stylelint-order` dependency to `^3.0.0`
160 | - Node.js 8.7.0 or greater is now required
161 |
162 | ## [5.4.0]
163 | ### Fixed
164 | - Fix patterns for variables like "$x1". [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/43)
165 |
166 | ### Changed
167 | - Ignore all @-rules in max-nesting-depth. [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/45)
168 |
169 | ## [5.3.0]
170 | ### Changed
171 | - Updated `stylelint-order` dependency range to pull in 1.x or 2.x versions. Both major versions are compatible. [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/41)
172 | - Updated up `stylelint-scss` dependency to pull minimum of 3.4.0 [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/41)
173 |
174 | ## [5.2.0]
175 | ### Changed
176 | - Bumped up `stylelint-order` dependency to ^1.0.0 [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/32)
177 |
178 | ## [5.1.0]
179 | ### Added
180 | - Added ability to run tests on Windows [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/34)
181 |
182 | ### Changed
183 | - Ignore @each for max-nesting-depth [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/35)
184 |
185 | ## [5.0.0]
186 | ### Added
187 | - Added scss/at-rule-no-unknown rule [#18](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/18)
188 |
189 | ### Changed
190 | - Bumped up `stylelint` peer/dev dependency to v9.0.0
191 | - Added stylelint-scss and stylelint-order as dependencies [#22](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/22)
192 | - Node.js 6.x or greater is now required [#24](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/24))
193 |
194 | ## [4.2.0]
195 | ### Added
196 | - Add "ignore" options to "max-nesting-depth" rule (fixes [#25](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/25)) [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/26)
197 |
198 | ## [4.1.0]
199 | ### Changed
200 | - Bumped up `stylelint-order` to v0.8.0
201 |
202 | ### Fixed
203 | - Fixed border zero rule. Issue [16](https://github.com/bjankord/stylelint-config-sass-guidelines/issues/16)
204 |
205 | ## [4.0.1]
206 | ### Removed
207 | - Removed `{"type": "at-rule", "hasBlock": true }` from order rule. Causes issues with `@media` queries and `@for` loops
208 | - Removed `{"type": "rule", "selector": "/^&:\\w/"},` from order rule.
209 | - Removed `{"type": "rule", "selector": "/^&::\\w/"},` from order rule.
210 |
211 | ## [4.0.0]
212 | ### Added
213 | - Add rules & tests for declaration-order [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/15)
214 |
215 | ### Changed
216 | - Moved stylelint, stylelint-scss, stylelint-order to peerDependencies / devDependencies [PR](https://github.com/bjankord/stylelint-config-sass-guidelines/pull/17/files)
217 |
218 | ## [3.0.1]
219 | ### Changed
220 | - Update copyright years in license
221 |
222 | ## [3.0.0]
223 | ### Added
224 | - Added [greenkeeper](https://greenkeeper.io/) to help keep dependencies up to date
225 |
226 | ### Changed
227 | - Bumped up `stylelint` to v8.0.0
228 | - Bumped up `stylelint-order` to v0.6.0
229 |
230 | ### Removed
231 | - Removed unused `stylelint-selector-no-utility` dependency from package.json
232 |
233 | ## [3.0.0-rc.1]
234 | ### Added
235 | - Added [greenkeeper](https://greenkeeper.io/) to help keep dependencies up to date
236 |
237 | ### Changed
238 | - Bumped up `stylelint` to v8.0.0
239 | - Bumped up `stylelint-order` to v0.6.0
240 |
241 | ### Removed
242 | - Removed unused `stylelint-selector-no-utility` dependency from package.json
243 |
244 | ## [2.2.0]
245 | ### Changed
246 | - Bumped up `stylelint` to v7.12.0
247 |
248 | ### Fixed
249 | - Replaced deprecated `selector-no-id` rule with `selector-max-id` rule
250 |
251 | ## [2.1.0]
252 | ### Changed
253 | - Bumped up `stylelint-order` to v0.4.3
254 |
255 | ### Fixed
256 | - Replaced deprecated `order/declaration-block-properties-alphabetical-order` rule with `order/properties-alphabetical-order` rule
257 |
258 | ## [2.0.0]
259 | ### Added
260 | - Added `stylelint-order` plugin
261 |
262 | ### Changed
263 | - Bumped up `stylelint` to v7.8.0
264 | - Bumped up `stylelint-scss` to v1.4.1
265 |
266 | ### Fixed
267 | - Replaced deprecated `declaration-block-properties-order` rule with `order/declaration-block-properties-alphabetical-order` rule
268 | - Replaced deprecated `rule-nested-empty-line-before` rule with `rule-empty-line-before` rule
269 | - Replaced deprecated `rule-non-nested-empty-line-before` rule with `rule-empty-line-before` rule
270 |
271 | ### Removed
272 | - `stylelint-disable-reason` rule. This rule has been deprecated in stylelint 7.8 and in 8.0 will be removed. See stylelint CHANGELOG: https://stylelint.io/CHANGELOG/#780
273 |
274 | ## [1.1.1]
275 | ### Fixed
276 | - Regex for selector-class-pattern now matches lowercase with hyphens correctly
277 | - Updated test for url-quotes.js to match updated error text
278 |
279 | ## [1.1.0]
280 | ### Added
281 | - `scss/dollar-variable-colon-space-after` rule
282 | - `scss/dollar-variable-colon-space-before` rule
283 |
284 | ### Changed
285 | - Bumped up `stylelint` to v7.1.0
286 | - Bumped up `stylelint-scss` to v1.3.4
287 |
288 | ## [1.0.0]
289 | ### Added
290 | - `stylelint-disable-reason` rule
291 | - `property-no-unknown` rule
292 | - `media-feature-parentheses-space-inside` rule
293 | - `no-missing-end-of-source-newline` rule
294 |
295 | ### Changed
296 | - Bumped up `stylelint` to v7.0.2
297 | - Bumped up `stylelint-scss` to v1.2.1
298 |
299 | ### Removed
300 | - `no-missing-eof-newline `rule
301 | - `function-calc-no-unspaced-operator` rule
302 |
303 | ## [0.2.0]
304 | ### Added
305 | - `function-parentheses-space-inside` rule
306 | - `scss/at-import-partial-extension-blacklist` rule
307 | - `declaration-block-properties-order` rule
308 | - `selector-no-vendor-prefix` rule
309 | - `media-feature-name-no-vendor-prefix` rule
310 | - `at-rule-no-vendor-prefix` rule
311 |
312 | ### Fixed
313 | - Sorted stylelint rules alphabetically in config
314 | - `max-nesting-depth` rule set to 1 to match Sass Guidelines NestingDepth max_depth: 1 rule
315 | - Cleaned up comments in `failing-test-case.scss`
316 | - Declaration order now sorted alphabetically in `passing-test-case.scss`
317 | - Updated tests to account for new rules
318 |
319 | ### Removed
320 | - `block-closing-brace-newline-after` rule
321 | - `no-extra-semicolons` rule
322 | - `string-no-newline` rule
323 |
324 | ## [0.1.0]
325 | ### Added
326 | - Initial release
327 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at osscodeofconduct@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at [http://contributor-covenant.org/version/1/4][version]
72 |
73 | [homepage]: http://contributor-covenant.org
74 | [version]: http://contributor-covenant.org/version/1/4/
75 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to this project
2 |
3 | Please take a moment to review this document in order to make the contribution
4 | process easy and effective for everyone involved.
5 |
6 | Following these guidelines helps to communicate that you respect the time of
7 | the developers managing and developing this open source project. In return,
8 | they should reciprocate that respect in addressing your issue or assessing
9 | patches and features.
10 |
11 |
12 | ## Using the issue tracker
13 |
14 | The issue tracker is the preferred channel for [bug reports](#bugs),
15 | [features requests](#features) and [submitting pull
16 | requests](#pull-requests).
17 |
18 |
19 |
20 | ## Bug reports
21 |
22 | A bug is a _demonstrable problem_ that is caused by the code in the repository.
23 | Good bug reports are extremely helpful - thank you!
24 |
25 | Guidelines for bug reports:
26 |
27 | 1. **Use the GitHub issue search** — check if the issue has already been
28 | reported.
29 |
30 | 2. **Check if the issue has been fixed** — try to reproduce it using the
31 | latest `master` or development branch in the repository.
32 |
33 | 3. **Isolate the problem** — create a [reduced test
34 | case](http://css-tricks.com/reduced-test-cases/) and a live example.
35 |
36 | A good bug report shouldn't leave others needing to chase you up for more
37 | information. Please try to be as detailed as possible in your report. What is
38 | your environment? What steps will reproduce the issue? What browser(s) and OS
39 | experience the problem? What would you expect to be the outcome? All these
40 | details will help people to fix any potential bugs.
41 |
42 | Example:
43 |
44 | > Short and descriptive example bug report title
45 | >
46 | > A summary of the issue and the browser/OS environment in which it occurs. If
47 | > suitable, include the steps required to reproduce the bug.
48 | >
49 | > 1. This is the first step
50 | > 2. This is the second step
51 | > 3. Further steps, etc.
52 | >
53 | > `` - a link to the reduced test case
54 | >
55 | > Any other information you want to share that is relevant to the issue being
56 | > reported. This might include the lines of code that you have identified as
57 | > causing the bug, and potential solutions (and your opinions on their
58 | > merits).
59 |
60 |
61 |
62 | ## Feature requests
63 |
64 | Feature requests are welcome. But take a moment to find out whether your idea
65 | fits with the scope and aims of the project. It's up to *you* to make a strong
66 | case to convince the project's developers of the merits of this feature. Please
67 | provide as much detail and context as possible.
68 |
69 |
70 |
71 | ## Pull requests
72 |
73 | Good pull requests - patches, improvements, new features - are a fantastic
74 | help. They should remain focused in scope and avoid containing unrelated
75 | commits.
76 |
77 | The scope of this project is to provide a stylelint config file with equivealent linting rules to the scss-lint rules recommended by [Sass Guidelines](https://sass-guidelin.es/)
78 |
79 | **Please ask first** before embarking on any significant pull request (e.g.
80 | implementing features, refactoring code, porting to a different language),
81 | otherwise you risk spending a lot of time working on something that the
82 | project's developers might not want to merge into the project.
83 |
84 | Please adhere to the coding conventions used throughout a project (indentation,
85 | accurate comments, etc.) and any other requirements (such as test coverage).
86 |
87 | Follow this process if you'd like your work considered for inclusion in the
88 | project:
89 |
90 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
91 | and configure the remotes:
92 |
93 | ```bash
94 | # Clone your fork of the repo into the current directory
95 | git clone https://github.com//stylelint-config-sass-guidelines
96 | # Navigate to the newly cloned directory
97 | cd stylelint-config-sass-guidelines
98 | # Assign the original repo to a remote called "upstream"
99 | git remote add upstream https://github.com/bjankord/stylelint-config-sass-guidelines
100 | ```
101 |
102 | 2. If you cloned a while ago, get the latest changes from upstream:
103 |
104 | ```bash
105 | git checkout
106 | git pull upstream
107 | ```
108 |
109 | 3. Create a new topic branch (off the main project development branch) to
110 | contain your feature, change, or fix:
111 |
112 | ```bash
113 | git checkout -b
114 | ```
115 |
116 | 4. Commit your changes in logical chunks. Please adhere to these [git commit
117 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
118 | or your code is unlikely be merged into the main project. Use Git's
119 | [interactive rebase](https://help.github.com/articles/interactive-rebase)
120 | feature to tidy up your commits before making them public.
121 |
122 | 5. Locally merge (or rebase) the upstream development branch into your topic branch:
123 |
124 | ```bash
125 | git pull [--rebase] upstream
126 | ```
127 |
128 | 6. Push your topic branch up to your fork:
129 |
130 | ```bash
131 | git push origin
132 | ```
133 |
134 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
135 | with a clear title and description.
136 |
137 | **IMPORTANT**: By submitting a patch, you agree to allow the project owner to
138 | license your work under the same license as that used by the project.
139 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-Present Brett Jankord
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # stylelint-config-sass-guidelines
2 |
3 | [](https://www.npmjs.com/package/stylelint-config-sass-guidelines)
4 | [](https://github.com/bjankord/stylelint-config-sass-guidelines/actions?workflow=CI)
5 | [](https://snyk.io//test/github/bjankord/stylelint-config-sass-guidelines)
6 | [](https://github.com/bjankord/stylelint-config-sass-guidelines/blob/main/CONTRIBUTING.md)
7 | [](https://npmcharts.com/compare/stylelint-config-sass-guidelines)
8 |
9 | > A stylelint config inspired by [sass-guidelin.es](https://sass-guidelin.es/).
10 |
11 | This linter has been designed / tested with SCSS syntax based on the SCSS guidelines documented in https://sass-guidelin.es/. It is intended for use with SCSS syntax, not Sass (tab style) syntax.
12 |
13 | This config:
14 | - includes the [`stylelint-scss` plugin module](https://github.com/stylelint-scss/stylelint-scss) and turns on rules for SCSS specific code
15 | - includes the [`@stylistic/stylelint-plugin` plugin module](https://github.com/stylelint-stylistic/stylelint-stylistic) and turns on rules for stylistic settings
16 | - includes the [`postcss-scss` custom syntax module](https://github.com/postcss/postcss-scss) and configures it
17 | - has a peer dependency on [`stylelint`](https://github.com/stylelint/stylelint)
18 | - You'll need to install this package in your project
19 | - has a peer dependency on [`postcss`](https://github.com/postcss/postcss)
20 | - You'll need to install this package in your project
21 |
22 | ## Installation
23 |
24 | Using NPM
25 | ```console
26 | $ npm i -D stylelint postcss stylelint-config-sass-guidelines
27 | ```
28 |
29 | Using Yarn
30 | ```console
31 | $ yarn add -D stylelint postcss stylelint-config-sass-guidelines
32 | ```
33 |
34 | Using PNPM
35 | ```console
36 | $ pnpm add -D stylelint postcss stylelint-config-sass-guidelines
37 | ```
38 |
39 | ## Usage
40 |
41 | Set your stylelint config to:
42 |
43 | ```json
44 | {
45 | "extends": "stylelint-config-sass-guidelines"
46 | }
47 | ```
48 |
49 | ### Extending the config
50 |
51 | Simply add a `"rules"` key to your config and add your overrides there.
52 |
53 | For example:
54 |
55 |
56 | ```json
57 | {
58 | "extends": "stylelint-config-sass-guidelines",
59 | "rules": {
60 | "selector-max-compound-selectors": 4,
61 | "value-no-vendor-prefix": false
62 | }
63 | }
64 | ```
65 |
66 | ## Documentation
67 |
68 | ### Configured lints
69 |
70 | This is a list of the lints turned on in this configuration, and what they do.
71 |
72 | #### At-Rule
73 |
74 | * [`at-rule-disallowed-list`](https://stylelint.io/user-guide/rules/at-rule-disallowed-list/): Specify a list of disallowed at-rules.
75 | * `"debug"` Disallow the use of `@debug`.
76 | * [`at-rule-no-unknown`](https://stylelint.io/user-guide/rules/at-rule-no-unknown/): Disallow unknown at-rules.
77 | * [`at-rule-no-vendor-prefix`](https://stylelint.io/user-guide/rules/at-rule-no-vendor-prefix/): Disallow vendor prefixes for at-rules.
78 |
79 | #### Block
80 |
81 | * [`block-no-empty`](https://stylelint.io/user-guide/rules/block-no-empty/): Disallow empty blocks.
82 |
83 |
84 | #### Color
85 |
86 | * [`color-hex-length`](https://stylelint.io/user-guide/rules/color-hex-length/): Always use short hex notation, where available.
87 | * [`color-named`](https://stylelint.io/user-guide/rules/color-named/): Colors must never be named.
88 | * [`color-no-invalid-hex`](https://stylelint.io/user-guide/rules/color-no-invalid-hex/): Hex values must be valid.
89 |
90 | #### Declaration Block
91 |
92 | * [`declaration-block-single-line-max-declarations`](https://stylelint.io/user-guide/rules/declaration-block-single-line-max-declarations/): There should never be more than `1` declaration per line.
93 |
94 | #### Declaration Property
95 |
96 | * [`declaration-property-value-disallowed-list`](https://stylelint.io/user-guide/rules/declaration-property-value-disallowed-list/): Specify a list of disallowed property and value pairs within declarations.
97 | * `^border`: Disallow the use of the word `none` for borders, use `0` instead. The intent of this rule is to enforce consistency, rather than define which is "better."
98 |
99 | #### Function
100 |
101 | * [`function-url-quotes`](https://stylelint.io/user-guide/rules/function-url-quotes/): URLs must always be quoted.
102 |
103 | #### General
104 |
105 | * [`length-zero-no-unit`](https://stylelint.io/user-guide/rules/length-zero-no-unit/): Disallow units for zero lengths.
106 | * [`max-nesting-depth`](https://stylelint.io/user-guide/rules/max-nesting-depth/): Limit the allowed nesting depth to `1`. _Ignore_: Nested at-rules `@media`, `@supports`, and `@include`.
107 |
108 |
109 | #### Media Feature
110 |
111 | * [`media-feature-name-no-vendor-prefix`](https://stylelint.io/user-guide/rules/media-feature-name-no-vendor-prefix/): Disallow vendor prefixes for media feature names.
112 |
113 |
114 | #### Property
115 |
116 | * [`property-no-unknown`](https://stylelint.io/user-guide/rules/property-no-unknown/): Disallow unknown properties
117 | * [`property-no-vendor-prefix`](https://stylelint.io/user-guide/rules/property-no-vendor-prefix/): Disallow vendor prefixes for properties.
118 | * [`shorthand-property-no-redundant-values`](https://stylelint.io/user-guide/rules/shorthand-property-no-redundant-values/): Disallow redundant values in shorthand properties.
119 |
120 |
121 | #### Rule
122 |
123 | * [`rule-empty-line-before`](https://stylelint.io/user-guide/rules/rule-empty-line-before/): There must always be an empty line before multi-line rules. _Except_: Nested rules that are the first of their parent rule. _Ignore_: Rules that come after a comment.
124 |
125 | #### SCSS
126 |
127 | * [`scss/at-extend-no-missing-placeholder`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/at-extend-no-missing-placeholder/README.md): Disallow at-extends (`@extend`) with missing placeholders.
128 | * [`scss/at-function-pattern`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/at-function-pattern/README.md): SCSS functions must be written in lowercase and match the regex `^[a-z]+([a-z0-9-]+[a-z0-9]+)?$`.
129 | * [`scss/at-import-partial-extension-disallowed-list`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/at-import-partial-extension-disallowed-list/README.md): Specify list of disallowed file extensions for partial names in `@import` commands.
130 | * `.scss`: Disallow the use of the `.scss` file extension in imports.
131 | * [`scss/at-rule-no-unknown`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/at-rule-no-unknown/README.md): SCSS mixins must be written in lowercase and match the regex `^[a-z]+([a-z0-9-]+[a-z0-9]+)?$`.
132 | * [`scss/dollar-variable-colon-space-after`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/dollar-variable-colon-space-after/README.md): Require a single space after the colon in $-variable declarations.
133 | * [`scss/dollar-variable-colon-space-before`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/dollar-variable-colon-space-before/README.md): Disallow whitespace before the colon in $-variable declarations.
134 | * [`scss/dollar-variable-pattern`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/dollar-variable-pattern/README.md): SCSS variables must be written in lowercase and match the regex `^[a-z]+([a-z0-9-]+[a-z0-9]+)?$`.
135 | * [`scss/load-no-partial-leading-underscore`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/load-no-partial-leading-underscore/README.md): Disallow leading underscore in partial names in `@import`.
136 | * [`scss/no-global-function-names`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/no-global-function-names/README.md): Disallows the use of global function names, as these global functions are now located inside built-in Sass modules.
137 | * [`scss/percent-placeholder-pattern`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/percent-placeholder-pattern/README.md): SCSS `%`-placeholders must be written in lowercase and match the regex `^[a-z]+([a-z0-9-]+[a-z0-9]+)?$`.
138 | * [`scss/selector-no-redundant-nesting-selector`](https://github.com/stylelint-scss/stylelint-scss/blob/master/src/rules/selector-no-redundant-nesting-selector/README.md): Disallow redundant nesting selectors (`&`).
139 |
140 | #### Selector
141 |
142 | * [`selector-class-pattern`](https://stylelint.io/user-guide/rules/selector-class-pattern/): Selectors must be written in lowercase and match the regex `^(?:u|is|has)-[a-z][a-zA-Z0-9]*$|^(?!u|is|has)[a-zA-Z][a-zA-Z0-9]*(?:-[a-z][a-zA-Z0-9]*)?(?:--[a-z][a-zA-Z0-9]*)?$`.
143 | * [`selector-max-compound-selectors`](https://stylelint.io/user-guide/rules/selector-max-compound-selectors/): Limit the number of compound selectors in a selector to `3`.
144 | * [`selector-max-id`](https://stylelint.io/user-guide/rules/selector-max-id/): Disallow id selectors.
145 | * [`selector-no-qualifying-type`](https://stylelint.io/user-guide/rules/selector-no-qualifying-type/): Disallow qualifying a selector by type.
146 | * [`selector-no-vendor-prefix`](https://stylelint.io/user-guide/rules/selector-no-vendor-prefix/): Disallow vendor prefixes for selectors.
147 | * [`selector-pseudo-element-colon-notation`](https://stylelint.io/user-guide/rules/selector-pseudo-element-colon-notation/): Applicable pseudo-elements must always use the double colon notation.
148 | * [`selector-pseudo-element-no-unknown`](https://stylelint.io/user-guide/rules/selector-pseudo-element-no-unknown/): Disallow unknown pseudo-element selectors.
149 |
150 | #### Stylistic
151 | * [`@stylistic/block-opening-brace-space-before`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/block-opening-brace-space-before/README.md): There must always be a single space before the opening brace.
152 | * [`@stylistic/color-hex-case`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/color-hex-case/README.md): Hex colors must be written in lowercase.
153 | * [`@stylistic/declaration-bang-space-after`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/declaration-bang-space-after/README.md): There must never be whitespace after the bang.
154 | * [`@stylistic/declaration-bang-space-before`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/declaration-bang-space-before/README.md): There must always be a single space before the bang.
155 | * [`@stylistic/declaration-block-semicolon-newline-after`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/declaration-block-semicolon-newline-after/README.md): There must always be a newline after the semicolon.
156 | * [`@stylistic/declaration-block-semicolon-space-before`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/declaration-block-semicolon-space-before/README.md): There must never be whitespace before the semicolons.
157 | * [`@stylistic/declaration-block-trailing-semicolon`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/declaration-block-trailing-semicolon/README.md): There must always be a trailing semicolon.
158 | * [`@stylistic/declaration-colon-space-after`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/declaration-colon-space-after/README.md): There must always be a single space after the colon if the declaration's value is single-line.
159 | * [`@stylistic/declaration-colon-space-before`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/declaration-colon-space-before/README.md): There must never be whitespace before the colon.
160 | * [`@stylistic/function-comma-space-after`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/function-comma-space-after/README.md): There must always be a single space after the commas in single-line functions.
161 | * [`@stylistic/function-parentheses-space-inside`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/function-parentheses-space-inside/README.md): There must never be whitespace on the inside of the parentheses of functions.
162 | * [`@stylistic/indentation`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/indentation/README.md): Indentation should always be 2 spaces.
163 |
164 | * [`@stylistic/media-feature-parentheses-space-inside`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/media-feature-parentheses-space-inside/README.md): There must never be whitespace on the inside of the parentheses of media features.
165 | * [`@stylistic/no-missing-end-of-source-newline`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/no-missing-end-of-source-newline/README.md): Disallow missing end-of-file newlines in non-empty files.
166 | * [`@stylistic/number-leading-zero`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/number-leading-zero/README.md): There must always be a leading zero.
167 | * [`@stylistic/number-no-trailing-zeros`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/number-no-trailing-zeros/README.md): Disallow trailing zeros in numbers.
168 | * [`@stylistic/selector-list-comma-newline-after`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/selector-list-comma-newline-after/README.md): There must always be a newline after the commas of selector lists.
169 | * [`@stylistic/string-quotes`](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/lib/rules/string-quotes/README.md): Strings must always be wrapped with single quotes.
170 |
171 | #### Value
172 |
173 | * [`value-no-vendor-prefix`](https://stylelint.io/user-guide/rules/value-no-vendor-prefix/): Disallow vendor prefixes for values.
174 |
175 | ## [Changelog](CHANGELOG.md)
176 |
177 | ## Contributors
178 | stylelint-config-sass-guidelines is maintained by Brett Jankord and contributions from the community. Without the code contributions from [all these fantastic people](https://github.com/bjankord/stylelint-config-sass-guidelines/graphs/contributors), stylelint-config-sass-guidelines would not exist.
179 |
180 | ## [License](LICENSE)
181 |
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 | # How to release
2 |
3 | This project is hosted on NPM. You can see it [here][npm-url].
4 |
5 | Releasing the project requires these steps:
6 |
7 | * Decide if you are releasing a major, minor, or patch version
8 | * Do not modify the version number in package.json or create a GitHub release.
9 | * Use the [release scripts][release-scripts-url] to create a new major, minor, or patch release.
10 | * This will update the version in package.json.
11 | * This will also create a git tag for the release.
12 | * Navigate to the GitHub [project release][github-release-url] page and add the version number to release
13 | * Add the CHANGELOG notes to the associated release.
14 |
15 |
16 |
17 | [npm-url]: https://www.npmjs.com/package/stylelint-config-sass-guidelines
18 | [release-scripts-url]: https://github.com/bjankord/stylelint-config-sass-guidelines/blob/main/package.json#L48-L50
19 | [github-release-url]: https://github.com/bjankord/stylelint-config-sass-guidelines/releases
20 |
--------------------------------------------------------------------------------
/__tests__/README.md:
--------------------------------------------------------------------------------
1 | # How to add tests
2 |
3 | * Create your test file named after stylelint rule.
4 | * For example, `__tests___/color-hex-case.test.mjs`
5 | * Copy the code from one of the other tests into your test new file
6 | * Update the test so you have code that will produce lint you want to test for
7 | * Write test assertions
8 |
--------------------------------------------------------------------------------
/__tests__/at-rule-disallowed-list.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with at-rule-disallowed lint', () => {
9 | const invalidScss = (
10 | `$color-blue: #1c94c6;
11 |
12 | .test-selector {
13 | @debug $color-blue;
14 | }
15 | `);
16 |
17 | let result;
18 |
19 | beforeEach(async () => {
20 | result = await stylelint.lint({
21 | code: invalidScss,
22 | config,
23 | });
24 | });
25 |
26 | it('did error', () => {
27 | assert.equal(result.errored, true);
28 | });
29 |
30 | it('flags warnings', () => {
31 | assert.equal(result.results[0].warnings.length, 1);
32 | });
33 |
34 | it('correct warning text', () => {
35 | assert.deepEqual(
36 | result.results[0].warnings.map((w) => w.text),
37 | [
38 | 'Unexpected at-rule "@debug" (at-rule-disallowed-list)'
39 | ],
40 | );
41 | });
42 |
43 | it('correct rule flagged', () => {
44 | assert.deepEqual(
45 | result.results[0].warnings.map((w) => w.rule),
46 | [
47 | 'at-rule-disallowed-list',
48 | ],
49 | );
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/__tests__/at-rule-no-unknown.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with at-rule-no-unknown lint', () => {
9 | const invalidScss = (
10 | `@unknown { color: #fff; }
11 |
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 1);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Unexpected unknown at-rule "@unknown" (scss/at-rule-no-unknown)',
36 | ],
37 | );
38 | });
39 |
40 | it('correct rule flagged', () => {
41 | assert.deepEqual(
42 | result.results[0].warnings.map((w) => w.rule),
43 | [
44 | 'scss/at-rule-no-unknown',
45 | ],
46 | );
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/__tests__/at-rule-no-vendor-prefix.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with at-rule-no-vendor-prefix lint', () => {
9 | const invalidScss = (
10 | `@-webkit-keyframes anim {
11 | 0% {
12 | opacity: 0;
13 | }
14 | }
15 | `);
16 |
17 | let result;
18 |
19 | beforeEach(async () => {
20 | result = await stylelint.lint({
21 | code: invalidScss,
22 | config,
23 | });
24 | });
25 |
26 | it('did error', () => {
27 | assert.equal(result.errored, true);
28 | });
29 |
30 | it('flags warnings', () => {
31 | assert.equal(result.results[0].warnings.length, 1);
32 | });
33 |
34 | it('correct warning text', () => {
35 | assert.deepEqual(
36 | result.results[0].warnings.map((w) => w.text),
37 | [
38 | 'Unexpected vendor-prefixed at-rule "@-webkit-keyframes" (at-rule-no-vendor-prefix)',
39 | ],
40 | );
41 | });
42 |
43 | it('correct rule flagged', () => {
44 | assert.deepEqual(
45 | result.results[0].warnings.map((w) => w.rule),
46 | [
47 | 'at-rule-no-vendor-prefix',
48 | ],
49 | );
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/__tests__/block-no-empty.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with block-no-empty lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | }
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 1);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Unexpected empty block (block-no-empty)',
36 | ],
37 | );
38 | });
39 |
40 | it('correct rule flagged', () => {
41 | assert.deepEqual(
42 | result.results[0].warnings.map((w) => w.rule),
43 | [
44 | 'block-no-empty',
45 | ],
46 | );
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/__tests__/block-opening-brace-space-before.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with block-opening-brace-space-before lint', () => {
9 | const invalidScss = (
10 | `.test-selector{ color: #fff; }
11 |
12 | .test-selector
13 | { color: #fff; }
14 | `);
15 |
16 | let result;
17 |
18 | beforeEach(async () => {
19 | result = await stylelint.lint({
20 | code: invalidScss,
21 | config,
22 | });
23 | });
24 |
25 | it('did error', () => {
26 | assert.equal(result.errored, true);
27 | });
28 |
29 | it('flags warnings', () => {
30 | assert.equal(result.results[0].warnings.length, 2);
31 | });
32 |
33 | it('correct warning text', () => {
34 | assert.deepEqual(
35 | result.results[0].warnings.map((w) => w.text),
36 | [
37 | 'Expected single space before "{" (@stylistic/block-opening-brace-space-before)',
38 | 'Expected single space before "{" (@stylistic/block-opening-brace-space-before)',
39 | ],
40 | );
41 | });
42 |
43 | it('correct rule flagged', () => {
44 | assert.deepEqual(
45 | result.results[0].warnings.map((w) => w.rule),
46 | [
47 | '@stylistic/block-opening-brace-space-before',
48 | '@stylistic/block-opening-brace-space-before',
49 | ],
50 | );
51 | });
52 | });
53 |
54 | describe('does not flag warnings with valid block-opening-brace-space-before', () => {
55 | const validScss = (
56 | `.test-selector {
57 | color: #fff;
58 | }
59 | `);
60 |
61 | let result;
62 |
63 | beforeEach(async () => {
64 | result = await stylelint.lint({
65 | code: validScss,
66 | config,
67 | });
68 | });
69 |
70 | it('did not error', () => {
71 | assert.equal(result.errored, false);
72 | });
73 |
74 | it('does not flag warnings', () => {
75 | assert.equal(result.results[0].warnings.length, 0);
76 | });
77 | });
--------------------------------------------------------------------------------
/__tests__/color-hex-case.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with color-hex-case lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | color: #FFF;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected "#FFF" to be "#fff" (@stylistic/color-hex-case)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/color-hex-case',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid color-hex-case', () => {
52 | const validScss = (
53 | `.test-selector {
54 | color: #fff;
55 | }
56 | `);
57 |
58 | let result;
59 |
60 | beforeEach(async () => {
61 | result = await stylelint.lint({
62 | code: validScss,
63 | config,
64 | });
65 | });
66 |
67 | it('did not error', () => {
68 | assert.equal(result.errored, false);
69 | });
70 |
71 | it('does not flag warnings', () => {
72 | assert.equal(result.results[0].warnings.length, 0);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/__tests__/color-hex-length.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with color-hex-length lint', () => {
9 | const invalidScss = (
10 | `.hexlength {
11 | color: #ff22ee;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected "#ff22ee" to be "#f2e" (color-hex-length)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'color-hex-length',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid color-hex-length', () => {
52 | const validScss = (
53 | `.test-selector {
54 | color: #fff;
55 | }
56 | `);
57 |
58 | let result;
59 |
60 | beforeEach(async () => {
61 | result = await stylelint.lint({
62 | code: validScss,
63 | config,
64 | });
65 | });
66 |
67 | it('did not error', () => {
68 | assert.equal(result.errored, false);
69 | });
70 |
71 | it('does not flag warnings', () => {
72 | assert.equal(result.results[0].warnings.length, 0);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/__tests__/color-named.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with color-named lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | color: green;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Unexpected named color "green" (color-named)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'color-named',
46 | ],
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/__tests__/color-no-invalid-hex.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with color-no-invalid-hex lint', () => {
9 | const invalidScss = (
10 | `.hex-validation {
11 | background: #ab; // Clearly a typo
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Unexpected invalid hex color "#ab" (color-no-invalid-hex)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'color-no-invalid-hex',
46 | ],
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/__tests__/declaration-bang-space-after.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-bang-space-after lint', () => {
9 | const invalidScss = (
10 | `.test-selector { color: #fff ! important; }
11 | .test-selector { color: #fff! important; }
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 3);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Unexpected whitespace after "!" (@stylistic/declaration-bang-space-after)',
36 | 'Unexpected whitespace after "!" (@stylistic/declaration-bang-space-after)',
37 | 'Expected single space before "!" (@stylistic/declaration-bang-space-before)'
38 | ],
39 | );
40 | });
41 |
42 | it('correct rule flagged', () => {
43 | assert.deepEqual(
44 | result.results[0].warnings.map((w) => w.rule),
45 | [
46 | '@stylistic/declaration-bang-space-after',
47 | '@stylistic/declaration-bang-space-after',
48 | '@stylistic/declaration-bang-space-before',
49 | ],
50 | );
51 | });
52 | });
53 |
54 | describe('does not flag warnings with valid declaration-bang-space-after', () => {
55 | const validScss = (
56 | `.test-selector {
57 | color: #000 !important;
58 | }
59 | `);
60 |
61 | let result;
62 |
63 | beforeEach(async () => {
64 | result = await stylelint.lint({
65 | code: validScss,
66 | config,
67 | });
68 | });
69 |
70 | it('did not error', () => {
71 | assert.equal(result.errored, false);
72 | });
73 |
74 | it('does not flag warnings', () => {
75 | assert.equal(result.results[0].warnings.length, 0);
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/__tests__/declaration-bang-space-before.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-bang-space-before lint', () => {
9 | const invalidScss = (
10 | `.test-selector { color: #fff!important; }
11 | .test-selector { color: #fff !important; }
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 2);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Expected single space before "!" (@stylistic/declaration-bang-space-before)',
36 | 'Expected single space before "!" (@stylistic/declaration-bang-space-before)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/declaration-bang-space-before',
46 | '@stylistic/declaration-bang-space-before',
47 | ],
48 | );
49 | });
50 | });
51 |
52 | describe('does not flag warnings with valid declaration-bang-space-before', () => {
53 | const validScss = (
54 | `.test-selector {
55 | color: #000 !important;
56 | }
57 | `);
58 |
59 | let result;
60 |
61 | beforeEach(async () => {
62 | result = await stylelint.lint({
63 | code: validScss,
64 | config,
65 | });
66 | });
67 |
68 | it('did not error', () => {
69 | assert.equal(result.errored, false);
70 | });
71 |
72 | it('does not flag warnings', () => {
73 | assert.equal(result.results[0].warnings.length, 0);
74 | });
75 | });
76 |
--------------------------------------------------------------------------------
/__tests__/declaration-block-semicolon-newline-after.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-block-semicolon-newline-after lint', () => {
9 | const invalidScss = (`.test-selector { color: #fff; top: 0; }`);
10 |
11 | let result;
12 |
13 | beforeEach(async () => {
14 | result = await stylelint.lint({
15 | code: invalidScss,
16 | config,
17 | });
18 | });
19 |
20 | it('did error', () => {
21 | assert.equal(result.errored, true);
22 | });
23 |
24 | it('flags warnings', () => {
25 | assert.equal(result.results[0].warnings.length, 3);
26 | });
27 |
28 | it('correct warning text', () => {
29 | assert.deepEqual(
30 | result.results[0].warnings.map((w) => w.text),
31 | [
32 | 'Expected newline after ";" (@stylistic/declaration-block-semicolon-newline-after)',
33 | 'Unexpected missing end-of-source newline (@stylistic/no-missing-end-of-source-newline)',
34 | 'Expected no more than 1 declaration (declaration-block-single-line-max-declarations)'
35 | ],
36 | );
37 | });
38 |
39 | it('correct rule flagged', () => {
40 | assert.deepEqual(
41 | result.results[0].warnings.map((w) => w.rule),
42 | [
43 | '@stylistic/declaration-block-semicolon-newline-after',
44 | '@stylistic/no-missing-end-of-source-newline',
45 | 'declaration-block-single-line-max-declarations'
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid declaration-block-semicolon-newline-after', () => {
52 | const validScss = (
53 | `.test-selector {
54 | color: #fff;
55 | border: 0;
56 | }
57 |
58 | `);
59 |
60 | let result;
61 |
62 | beforeEach(async () => {
63 | result = await stylelint.lint({
64 | code: validScss,
65 | config,
66 | });
67 | });
68 |
69 | it('did not error', () => {
70 | assert.equal(result.errored, false);
71 | });
72 |
73 | it('does not flag warnings', () => {
74 | assert.equal(result.results[0].warnings.length, 0);
75 | });
76 | });
77 |
--------------------------------------------------------------------------------
/__tests__/declaration-block-semicolon-space-before.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-block-semicolon-space-before lint', () => {
9 | const invalidScss = (`.test-selector { color: #fff ; }`);
10 |
11 | let result;
12 |
13 | beforeEach(async () => {
14 | result = await stylelint.lint({
15 | code: invalidScss,
16 | config,
17 | });
18 | });
19 |
20 | it('did error', () => {
21 | assert.equal(result.errored, true);
22 | });
23 |
24 | it('flags warnings', () => {
25 | assert.equal(result.results[0].warnings.length, 2);
26 | });
27 |
28 | it('correct warning text', () => {
29 | assert.deepEqual(
30 | result.results[0].warnings.map((w) => w.text),
31 | [
32 | 'Unexpected whitespace before ";" (@stylistic/declaration-block-semicolon-space-before)',
33 | 'Unexpected missing end-of-source newline (@stylistic/no-missing-end-of-source-newline)'
34 | ],
35 | );
36 | });
37 |
38 | it('correct rule flagged', () => {
39 | assert.deepEqual(
40 | result.results[0].warnings.map((w) => w.rule),
41 | [
42 | '@stylistic/declaration-block-semicolon-space-before',
43 | '@stylistic/no-missing-end-of-source-newline'
44 | ],
45 | );
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/__tests__/declaration-block-single-line-max-declarations.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-block-single-line-max-declarations lint', () => {
9 | const invalidScss = (`
10 | .test-selector { color: #fff; top: 0; }
11 |
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 2);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Expected newline after ";" (@stylistic/declaration-block-semicolon-newline-after)',
36 | 'Expected no more than 1 declaration (declaration-block-single-line-max-declarations)'
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/declaration-block-semicolon-newline-after',
46 | 'declaration-block-single-line-max-declarations'
47 | ],
48 | );
49 | });
50 | });
51 |
52 | describe('does not flag warnings with valid declaration-block-single-line-max-declarations', () => {
53 | const validScss = (
54 | `.test-selector { color: #000; }
55 | `);
56 |
57 | let result;
58 |
59 | beforeEach(async () => {
60 | result = await stylelint.lint({
61 | code: validScss,
62 | config,
63 | });
64 | });
65 |
66 | it('did not error', () => {
67 | assert.equal(result.errored, false);
68 | });
69 |
70 | it('does not flag warnings', () => {
71 | assert.equal(result.results[0].warnings.length, 0);
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/__tests__/declaration-block-trailing-semicolon.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-block-trailing-semicolon lint', () => {
9 | const invalidScss = (
10 | `.test-selector { color: #fff }
11 | .test-selector { background: #000; color: #fff }
12 | .test-selector { @include foo }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 5);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected newline after ";" (@stylistic/declaration-block-semicolon-newline-after)',
37 | 'Expected a trailing semicolon (@stylistic/declaration-block-trailing-semicolon)',
38 | 'Expected a trailing semicolon (@stylistic/declaration-block-trailing-semicolon)',
39 | 'Expected a trailing semicolon (@stylistic/declaration-block-trailing-semicolon)',
40 | 'Expected no more than 1 declaration (declaration-block-single-line-max-declarations)'
41 | ],
42 | );
43 | });
44 |
45 | it('correct rule flagged', () => {
46 | assert.deepEqual(
47 | result.results[0].warnings.map((w) => w.rule),
48 | [
49 | '@stylistic/declaration-block-semicolon-newline-after',
50 | '@stylistic/declaration-block-trailing-semicolon',
51 | '@stylistic/declaration-block-trailing-semicolon',
52 | '@stylistic/declaration-block-trailing-semicolon',
53 | 'declaration-block-single-line-max-declarations'
54 | ],
55 | );
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/__tests__/declaration-colon-space-after.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-colon-space-after lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | box-shadow:0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, 0.8);
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected single space after ":" with a single-line declaration (@stylistic/declaration-colon-space-after)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/declaration-colon-space-after',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid declaration-colon-space-after', () => {
52 | const validScss = (
53 | `.test-selector { color: #fff; }
54 | `);
55 |
56 | let result;
57 |
58 | beforeEach(async () => {
59 | result = await stylelint.lint({
60 | code: validScss,
61 | config,
62 | });
63 | });
64 |
65 | it('did not error', () => {
66 | assert.equal(result.errored, false);
67 | });
68 |
69 | it('does not flag warnings', () => {
70 | assert.equal(result.results[0].warnings.length, 0);
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/__tests__/declaration-colon-space-before.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-colon-space-before lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | color : #fff;
12 | }
13 |
14 | .test-selector {
15 | color :#fff;
16 | }
17 | `);
18 |
19 | let result;
20 |
21 | beforeEach(async () => {
22 | result = await stylelint.lint({
23 | code: invalidScss,
24 | config,
25 | });
26 | });
27 |
28 | it('did error', () => {
29 | assert.equal(result.errored, true);
30 | });
31 |
32 | it('flags warnings', () => {
33 | assert.equal(result.results[0].warnings.length, 3);
34 | });
35 |
36 | it('correct warning text', () => {
37 | assert.deepEqual(
38 | result.results[0].warnings.map((w) => w.text),
39 | [
40 | 'Expected single space after ":" with a single-line declaration (@stylistic/declaration-colon-space-after)',
41 | 'Unexpected whitespace before ":" (@stylistic/declaration-colon-space-before)',
42 | 'Unexpected whitespace before ":" (@stylistic/declaration-colon-space-before)'
43 | ],
44 | );
45 | });
46 |
47 | it('correct rule flagged', () => {
48 | assert.deepEqual(
49 | result.results[0].warnings.map((w) => w.rule),
50 | [
51 | '@stylistic/declaration-colon-space-after',
52 | '@stylistic/declaration-colon-space-before',
53 | '@stylistic/declaration-colon-space-before'
54 | ],
55 | );
56 | });
57 | });
58 |
59 | describe('does not flag warnings with valid declaration-colon-space-before', () => {
60 | const validScss = (
61 | `.test-selector { color: #fff; }
62 | `);
63 |
64 | let result;
65 |
66 | beforeEach(async () => {
67 | result = await stylelint.lint({
68 | code: validScss,
69 | config,
70 | });
71 | });
72 |
73 | it('did not error', () => {
74 | assert.equal(result.errored, false);
75 | });
76 |
77 | it('does not flag warnings', () => {
78 | assert.equal(result.results[0].warnings.length, 0);
79 | });
80 | });
--------------------------------------------------------------------------------
/__tests__/declaration-property-value-disallowed-list.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with declaration-property-value-disallowed-list border none lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | border: none;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Unexpected value "none" for property "border" (declaration-property-value-disallowed-list)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'declaration-property-value-disallowed-list',
46 | ],
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/__tests__/function-comma-space-after.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with function-comma-space-after lint', () => {
9 | const invalidScss = (
10 | `.test-selector { transform: translate(1,1); }
11 | .test-selector { transform: translate(1 ,1); }
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 2);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Expected single space after "," in a single-line function (@stylistic/function-comma-space-after)',
36 | 'Expected single space after "," in a single-line function (@stylistic/function-comma-space-after)'
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/function-comma-space-after',
46 | '@stylistic/function-comma-space-after'
47 | ],
48 | );
49 | });
50 | });
51 |
52 | describe('does not flag warnings with valid function-comma-space-after', () => {
53 | const validScss = (
54 | `.test-selector {
55 | @include box-shadow(0 2px 2px rgba(0, 0, 0, 0.2));
56 | color: rgba(0, 0, 0, 0.1);
57 | }
58 | `);
59 |
60 | let result;
61 |
62 | beforeEach(async () => {
63 | result = await stylelint.lint({
64 | code: validScss,
65 | config,
66 | });
67 | });
68 |
69 | it('did not error', () => {
70 | assert.equal(result.errored, false);
71 | });
72 |
73 | it('does not flag warnings', () => {
74 | assert.equal(result.results[0].warnings.length, 0);
75 | });
76 | });
77 |
--------------------------------------------------------------------------------
/__tests__/function-parentheses-space-inside.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with function-parentheses-space-inside lint', () => {
9 | const invalidScss = (
10 | `.test-selector { transform: translate( 1, 1 ); }
11 | .test-selector { transform: translate(1, 1 ); }
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 3);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Unexpected whitespace after "(" (@stylistic/function-parentheses-space-inside)',
36 | 'Unexpected whitespace before ")" (@stylistic/function-parentheses-space-inside)',
37 | 'Unexpected whitespace before ")" (@stylistic/function-parentheses-space-inside)'
38 | ],
39 | );
40 | });
41 |
42 | it('correct rule flagged', () => {
43 | assert.deepEqual(
44 | result.results[0].warnings.map((w) => w.rule),
45 | [
46 | '@stylistic/function-parentheses-space-inside',
47 | '@stylistic/function-parentheses-space-inside',
48 | '@stylistic/function-parentheses-space-inside'
49 | ],
50 | );
51 | });
52 | });
53 |
54 | describe('does not flag warnings with valid function-parentheses-space-inside', () => {
55 | const validScss = (
56 | `.test-selector {
57 | @include box-shadow(0 2px 2px rgba(0, 0, 0, 0.2));
58 | color: rgba(0, 0, 0, 0.1);
59 | }
60 | `);
61 |
62 | let result;
63 |
64 | beforeEach(async () => {
65 | result = await stylelint.lint({
66 | code: validScss,
67 | config,
68 | });
69 | });
70 |
71 | it('did not error', () => {
72 | assert.equal(result.errored, false);
73 | });
74 |
75 | it('does not flag warnings', () => {
76 | assert.equal(result.results[0].warnings.length, 0);
77 | });
78 | });
--------------------------------------------------------------------------------
/__tests__/function-url-quotes.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with function-url-quotes lint', () => {
9 | const invalidScss = (
10 | `.quotes-url {
11 | background: url(example.png);
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected quotes around "url" function argument (function-url-quotes)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'function-url-quotes',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid function-url-quotes', () => {
52 | const validScss = (
53 | `.test-selector {
54 | background: url('example.png');
55 | }
56 |
57 | `);
58 |
59 | let result;
60 |
61 | beforeEach(async () => {
62 | result = await stylelint.lint({
63 | code: validScss,
64 | config,
65 | });
66 | });
67 |
68 | it('did not error', () => {
69 | assert.equal(result.errored, false);
70 | });
71 |
72 | it('does not flag warnings', () => {
73 | assert.equal(result.results[0].warnings.length, 0);
74 | });
75 | });
76 |
--------------------------------------------------------------------------------
/__tests__/indentation.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with indentation lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | color: #fff;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected indentation of 2 spaces (@stylistic/indentation)'
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/indentation',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid indentation', () => {
52 | const validScss = (
53 | `.test-selector {
54 | color: #000;
55 | }
56 | `);
57 |
58 | let result;
59 |
60 | beforeEach(async () => {
61 | result = await stylelint.lint({
62 | code: validScss,
63 | config,
64 | });
65 | });
66 |
67 | it('did not error', () => {
68 | assert.equal(result.errored, false);
69 | });
70 |
71 | it('does not flag warnings', () => {
72 | assert.equal(result.results[0].warnings.length, 0);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/__tests__/length-zero-no-unit.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with length-zero-no-unit lint', () => {
9 | const invalidScss = (
10 | `.zerounit {
11 | margin: 0px;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Unexpected unit (length-zero-no-unit)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'length-zero-no-unit',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid length-zero-no-unit', () => {
52 | const validScss = (
53 | `.test-selector {
54 | margin: 0;
55 | }
56 | `);
57 |
58 | let result;
59 |
60 | beforeEach(async () => {
61 | result = await stylelint.lint({
62 | code: validScss,
63 | config,
64 | });
65 | });
66 |
67 | it('did not error', () => {
68 | assert.equal(result.errored, false);
69 | });
70 |
71 | it('does not flag warnings', () => {
72 | assert.equal(result.results[0].warnings.length, 0);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/__tests__/max-nesting-depth.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with max-nesting-depth lint', () => {
9 | const invalidScss = (
10 | `.one {
11 | .two {
12 | background-color: #c0ffee;
13 |
14 | @media (min-width: 420px) {
15 | background-color: #bada55;
16 | }
17 |
18 | @include mixin() {
19 | background-color: #ba2;
20 | }
21 |
22 | .three {
23 | color: #f00;
24 | }
25 | }
26 | }
27 | `);
28 |
29 | let result;
30 |
31 | beforeEach(async () => {
32 | result = await stylelint.lint({
33 | code: invalidScss,
34 | config,
35 | });
36 | });
37 |
38 | it('did error', () => {
39 | assert.equal(result.errored, true);
40 | });
41 |
42 | it('flags warnings', () => {
43 | assert.equal(result.results[0].warnings.length, 1);
44 | });
45 |
46 | it('correct warning text', () => {
47 | assert.deepEqual(
48 | result.results[0].warnings.map((w) => w.text),
49 | [
50 | 'Expected nesting depth to be no more than 1 (max-nesting-depth)',
51 | ],
52 | );
53 | });
54 |
55 | it('correct rule flagged', () => {
56 | assert.deepEqual(
57 | result.results[0].warnings.map((w) => w.rule),
58 | [
59 | 'max-nesting-depth'
60 | ],
61 | );
62 | });
63 | });
64 |
--------------------------------------------------------------------------------
/__tests__/media-feature-name-no-vendor-prefix.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with media-feature-name-no-vendor-prefix lint', () => {
9 | const invalidScss = (`@media (-webkit-min-device-pixel-ratio: 1) {
10 | .test-selector {
11 | color: #fff;
12 | }
13 | }
14 |
15 | `);
16 |
17 | let result;
18 |
19 | beforeEach(async () => {
20 | result = await stylelint.lint({
21 | code: invalidScss,
22 | config,
23 | });
24 | });
25 |
26 | it('did error', () => {
27 | assert.equal(result.errored, true);
28 | });
29 |
30 | it('flags warnings', () => {
31 | assert.equal(result.results[0].warnings.length, 1);
32 | });
33 |
34 | it('correct warning text', () => {
35 | assert.deepEqual(
36 | result.results[0].warnings.map((w) => w.text),
37 | [
38 | 'Unexpected vendor-prefix (media-feature-name-no-vendor-prefix)'
39 | ],
40 | );
41 | });
42 |
43 | it('correct rule flagged', () => {
44 | assert.deepEqual(
45 | result.results[0].warnings.map((w) => w.rule),
46 | [
47 | 'media-feature-name-no-vendor-prefix'
48 | ],
49 | );
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/__tests__/media-feature-parentheses-space-inside.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with media-feature-parentheses-space-inside lint', () => {
9 | const invalidScss = (`@media ( max-width: 300px ) {
10 | .test-selector {
11 | color: #fff;
12 | }
13 | }
14 |
15 | `);
16 |
17 | let result;
18 |
19 | beforeEach(async () => {
20 | result = await stylelint.lint({
21 | code: invalidScss,
22 | config,
23 | });
24 | });
25 |
26 | it('did error', () => {
27 | assert.equal(result.errored, true);
28 | });
29 |
30 | it('flags warnings', () => {
31 | assert.equal(result.results[0].warnings.length, 2);
32 | });
33 |
34 | it('correct warning text', () => {
35 | assert.deepEqual(
36 | result.results[0].warnings.map((w) => w.text),
37 | [
38 | 'Unexpected whitespace after "(" (@stylistic/media-feature-parentheses-space-inside)',
39 | 'Unexpected whitespace before ")" (@stylistic/media-feature-parentheses-space-inside)'
40 | ],
41 | );
42 | });
43 |
44 | it('correct rule flagged', () => {
45 | assert.deepEqual(
46 | result.results[0].warnings.map((w) => w.rule),
47 | [
48 | '@stylistic/media-feature-parentheses-space-inside',
49 | '@stylistic/media-feature-parentheses-space-inside'
50 | ],
51 | );
52 | });
53 | });
54 |
55 | describe('does not flag warnings with valid media-feature-parentheses-space-inside', () => {
56 | const validScss = (
57 | `@media (max-width: 300px) {
58 | .media-parens {
59 | margin: 0;
60 | }
61 | }
62 | `);
63 |
64 | let result;
65 |
66 | beforeEach(async () => {
67 | result = await stylelint.lint({
68 | code: validScss,
69 | config,
70 | });
71 | });
72 |
73 | it('did not error', () => {
74 | assert.equal(result.errored, false);
75 | });
76 |
77 | it('does not flag warnings', () => {
78 | assert.equal(result.results[0].warnings.length, 0);
79 | });
80 | });
81 |
--------------------------------------------------------------------------------
/__tests__/misc-valid-scss.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('does not error or warn on valid scss', () => {
9 | const invalidScss = (
10 | `// DeclarationOrder test
11 | // scss-lint:disable NestingDepth
12 | .declarationorder {
13 | @extend %error;
14 | @include message-box();
15 |
16 | color: #f00;
17 |
18 | p {
19 | color: #f00;
20 | }
21 | }
22 | // scss-lint:enable NestingDepth
23 |
24 | // ElsePlacement test
25 | $width: auto;
26 |
27 | .elseplacement {
28 | @if $width == 'auto' {
29 | width: $width;
30 | } @else {
31 | display: inline-block;
32 | width: $width;
33 | }
34 | }
35 |
36 | // EmptyLineBetweenBlocks test
37 | // scss-lint:disable NestingDepth
38 | p {
39 | margin: 0;
40 |
41 | em {
42 | color: #f00;
43 | }
44 | }
45 |
46 | a {
47 | color: #f00;
48 | }
49 | // scss-lint:enable NestingDepth
50 |
51 |
52 | // NameFormat Mixins test
53 | // Mixins should be declared with all lowercase letters and hyphens instead of underscores.
54 |
55 | @mixin my-mixin() {
56 | color: #fff;
57 | }
58 |
59 | // Private Naming Convention test
60 | // Enforces that functions, mixins, and variables that follow the private naming convention (default to underscore-prefixed, e.g. $_foo) are defined and used within the same file.
61 |
62 | $_foo: #f00;
63 |
64 | figure {
65 | color: $_foo;
66 | }
67 |
68 | // SpaceAroundOperator test
69 | .spacearoundoperator {
70 | margin: 5px + 10px;
71 | padding: 5px + 10px;
72 | }
73 |
74 | // Each loop test
75 | .button {
76 | @each $key, $value in $colors {
77 | &-#{$key} {
78 | background-color: $value;
79 | }
80 | }
81 | }
82 | `);
83 |
84 | let result;
85 |
86 | beforeEach(async () => {
87 | result = await stylelint.lint({
88 | code: invalidScss,
89 | config,
90 | });
91 | });
92 |
93 | it('did not error', () => {
94 | // console.log('result.results[0].warnings', result.results[0].warnings);
95 | assert.equal(result.errored, false);
96 | });
97 |
98 | it('flags no warnings', () => {
99 | assert.equal(result.results[0].warnings.length, 0);
100 | });
101 | });
102 |
--------------------------------------------------------------------------------
/__tests__/no-missing-end-of-source-newline.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with no-missing-end-of-source-newline lint', () => {
9 | const invalidScss = (`.test-selector { color: #fff; }`);
10 |
11 | let result;
12 |
13 | beforeEach(async () => {
14 | result = await stylelint.lint({
15 | code: invalidScss,
16 | config,
17 | });
18 | });
19 |
20 | it('did error', () => {
21 | assert.equal(result.errored, true);
22 | });
23 |
24 | it('flags warnings', () => {
25 | assert.equal(result.results[0].warnings.length, 1);
26 | });
27 |
28 | it('correct warning text', () => {
29 | assert.deepEqual(
30 | result.results[0].warnings.map((w) => w.text),
31 | [
32 | 'Unexpected missing end-of-source newline (@stylistic/no-missing-end-of-source-newline)',
33 | ],
34 | );
35 | });
36 |
37 | it('correct rule flagged', () => {
38 | assert.deepEqual(
39 | result.results[0].warnings.map((w) => w.rule),
40 | [
41 | '@stylistic/no-missing-end-of-source-newline',
42 | ],
43 | );
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/__tests__/number-leading-zero.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with number-leading-zero lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | line-height: .5em;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected a leading zero (@stylistic/number-leading-zero)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/number-leading-zero',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid number-leading-zero', () => {
52 | const validScss = (
53 | `.test-selector {
54 | line-height: 0.5em;
55 | }
56 | `);
57 |
58 | let result;
59 |
60 | beforeEach(async () => {
61 | result = await stylelint.lint({
62 | code: validScss,
63 | config,
64 | });
65 | });
66 |
67 | it('did not error', () => {
68 | assert.equal(result.errored, false);
69 | });
70 |
71 | it('does not flag warnings', () => {
72 | assert.equal(result.results[0].warnings.length, 0);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/__tests__/number-no-trailing-zeros.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with number-no-trailing-zeros lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | top: 1.0px;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Unexpected trailing zero(s) (@stylistic/number-no-trailing-zeros)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | '@stylistic/number-no-trailing-zeros',
46 | ],
47 | );
48 | });
49 | });
50 |
51 |
52 | describe('does not flag warnings with valid number-no-trailing-zeros', () => {
53 | const validScss = (
54 | `.test-selector {
55 | top: 1px;
56 | }
57 | `);
58 |
59 | let result;
60 |
61 | beforeEach(async () => {
62 | result = await stylelint.lint({
63 | code: validScss,
64 | config,
65 | });
66 | });
67 |
68 | it('did not error', () => {
69 | assert.equal(result.errored, false);
70 | });
71 |
72 | it('does not flag warnings', () => {
73 | assert.equal(result.results[0].warnings.length, 0);
74 | });
75 | });
76 |
--------------------------------------------------------------------------------
/__tests__/property-no-unknown.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with property-no-unknown lint', () => {
9 | const invalidScss = (
10 | `.property-spelling {
11 | diplay: none; // "display" is spelled incorrectly
12 | heigth: 100%; // "height" is spelled incorrectly
13 | }
14 | `);
15 |
16 | let result;
17 |
18 | beforeEach(async () => {
19 | result = await stylelint.lint({
20 | code: invalidScss,
21 | config,
22 | });
23 | });
24 |
25 | it('did error', () => {
26 | assert.equal(result.errored, true);
27 | });
28 |
29 | it('flags warnings', () => {
30 | assert.equal(result.results[0].warnings.length, 2);
31 | });
32 |
33 | it('correct warning text', () => {
34 | assert.deepEqual(
35 | result.results[0].warnings.map((w) => w.text),
36 | [
37 | 'Unexpected unknown property "diplay" (property-no-unknown)',
38 | 'Unexpected unknown property "heigth" (property-no-unknown)'
39 | ],
40 | );
41 | });
42 |
43 | it('correct rule flagged', () => {
44 | assert.deepEqual(
45 | result.results[0].warnings.map((w) => w.rule),
46 | [
47 | 'property-no-unknown',
48 | 'property-no-unknown',
49 | ],
50 | );
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/__tests__/property-no-vendor-prefix.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with property-no-vendor-prefix lint', () => {
9 | const invalidScss = (
10 | `.test-selector {
11 | -webkit-transform: scale(1);
12 | }
13 |
14 | `);
15 |
16 | let result;
17 |
18 | beforeEach(async () => {
19 | result = await stylelint.lint({
20 | code: invalidScss,
21 | config,
22 | });
23 | });
24 |
25 | it('did error', () => {
26 | assert.equal(result.errored, true);
27 | });
28 |
29 | it('flags warnings', () => {
30 | assert.equal(result.results[0].warnings.length, 1);
31 | });
32 |
33 | it('correct warning text', () => {
34 | assert.deepEqual(
35 | result.results[0].warnings.map((w) => w.text),
36 | [
37 | 'Unexpected vendor-prefixed property "-webkit-transform" (property-no-vendor-prefix)',
38 | ],
39 | );
40 | });
41 |
42 | it('correct rule flagged', () => {
43 | assert.deepEqual(
44 | result.results[0].warnings.map((w) => w.rule),
45 | [
46 | 'property-no-vendor-prefix',
47 | ],
48 | );
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/__tests__/rule-empty-line-before.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with rule-empty-line-before lint', () => {
9 | const invalidScss = (
10 | `p {
11 | margin: 0;
12 | em {
13 | color: #f00;
14 | }
15 | }
16 | a {
17 | color: #f00;
18 | }
19 | `);
20 |
21 | let result;
22 |
23 | beforeEach(async () => {
24 | result = await stylelint.lint({
25 | code: invalidScss,
26 | config,
27 | });
28 | });
29 |
30 | it('did error', () => {
31 | assert.equal(result.errored, true);
32 | });
33 |
34 | it('flags warnings', () => {
35 | assert.equal(result.results[0].warnings.length, 2);
36 | });
37 |
38 | it('correct warning text', () => {
39 | assert.deepEqual(
40 | result.results[0].warnings.map((w) => w.text),
41 | [
42 | 'Expected empty line before rule (rule-empty-line-before)',
43 | 'Expected empty line before rule (rule-empty-line-before)',
44 | ],
45 | );
46 | });
47 |
48 | it('correct rule flagged', () => {
49 | assert.deepEqual(
50 | result.results[0].warnings.map((w) => w.rule),
51 | [
52 | 'rule-empty-line-before',
53 | 'rule-empty-line-before',
54 | ],
55 | );
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/__tests__/scss-at-extend-no-missing-placeholder.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/at-extend-no-missing-placeholder lint', () => {
9 | const invalidScss = (
10 | `.fatal {
11 | @extend .error;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected a placeholder selector (e.g. %placeholder) to be used in @extend (scss/at-extend-no-missing-placeholder)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'scss/at-extend-no-missing-placeholder',
46 | ],
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/__tests__/scss-at-function-pattern.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/at-function-pattern lint', () => {
9 | const invalidScss = (
10 | `@function calculationFunction($some-number, $another-number) {
11 | @return $some-number + $another-number;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected @function name to match specified pattern (scss/at-function-pattern)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'scss/at-function-pattern',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid scss/at-function-pattern', () => {
52 | const validScss = (
53 | `@function calculation-function($some-number, $another-number) {
54 | @return $some-number + $another-number;
55 | }
56 | `);
57 |
58 | let result;
59 |
60 | beforeEach(async () => {
61 | result = await stylelint.lint({
62 | code: validScss,
63 | config,
64 | });
65 | });
66 |
67 | it('did not error', () => {
68 | assert.equal(result.errored, false);
69 | });
70 |
71 | it('does not flag warnings', () => {
72 | assert.equal(result.results[0].warnings.length, 0);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/__tests__/scss-at-import-partial-extension-disallowed-list.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/at-import-partial-extension-disallowed-list lint', () => {
9 | const invalidScss = (
10 | `@import 'foo/_bar.scss';
11 | @import '_bar.scss';
12 | @import '_bar';
13 | @import 'bar.scss';
14 | `);
15 |
16 | let result;
17 |
18 | beforeEach(async () => {
19 | result = await stylelint.lint({
20 | code: invalidScss,
21 | config,
22 | });
23 | });
24 |
25 | it('did error', () => {
26 | assert.equal(result.errored, true);
27 | });
28 |
29 | it('flags warnings', () => {
30 | assert.equal(result.results[0].warnings.length, 6);
31 | });
32 |
33 | it('correct warning text', () => {
34 | assert.deepEqual(
35 | result.results[0].warnings.map((w) => w.text),
36 | [
37 | 'Unexpected extension ".scss" in imported partial name (scss/at-import-partial-extension-disallowed-list)',
38 | 'Unexpected extension ".scss" in imported partial name (scss/at-import-partial-extension-disallowed-list)',
39 | 'Unexpected extension ".scss" in imported partial name (scss/at-import-partial-extension-disallowed-list)',
40 | 'Unexpected leading underscore in imported partial name (scss/load-no-partial-leading-underscore)',
41 | 'Unexpected leading underscore in imported partial name (scss/load-no-partial-leading-underscore)',
42 | 'Unexpected leading underscore in imported partial name (scss/load-no-partial-leading-underscore)',
43 | ],
44 | );
45 | });
46 |
47 | it('correct rule flagged', () => {
48 | assert.deepEqual(
49 | result.results[0].warnings.map((w) => w.rule),
50 | [
51 | 'scss/at-import-partial-extension-disallowed-list',
52 | 'scss/at-import-partial-extension-disallowed-list',
53 | 'scss/at-import-partial-extension-disallowed-list',
54 | 'scss/load-no-partial-leading-underscore',
55 | 'scss/load-no-partial-leading-underscore',
56 | 'scss/load-no-partial-leading-underscore',
57 | ],
58 | );
59 | });
60 | });
61 |
62 | describe('does not flag warnings with valid scss/at-import-partial-extension-disallowed-list lint', () => {
63 | const validScss = (
64 | `@import 'foo/bar';
65 | @import 'bar';
66 | `);
67 |
68 | let result;
69 |
70 | beforeEach(async () => {
71 | result = await stylelint.lint({
72 | code: validScss,
73 | config,
74 | });
75 | });
76 |
77 | it('did not error', () => {
78 | assert.equal(result.errored, false);
79 | });
80 |
81 | it('does not flag warnings', () => {
82 | assert.equal(result.results[0].warnings.length, 0);
83 | });
84 | });
85 |
--------------------------------------------------------------------------------
/__tests__/scss-at-rule-no-unknown.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/at-rule-no-unknown lint', () => {
9 | const invalidScss = (
10 | `@unknown { color: #fff; }
11 |
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 1);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Unexpected unknown at-rule "@unknown" (scss/at-rule-no-unknown)',
36 | ],
37 | );
38 | });
39 |
40 | it('correct rule flagged', () => {
41 | assert.deepEqual(
42 | result.results[0].warnings.map((w) => w.rule),
43 | [
44 | 'scss/at-rule-no-unknown',
45 | ],
46 | );
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/__tests__/scss-dollar-variable-colon-space-after.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/dollar-variable-colon-space-after lint', () => {
9 | const invalidScss = (
10 | `a { $var:10px;}
11 |
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 1);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Expected single space after ":" (scss/dollar-variable-colon-space-after)',
36 | ],
37 | );
38 | });
39 |
40 | it('correct rule flagged', () => {
41 | assert.deepEqual(
42 | result.results[0].warnings.map((w) => w.rule),
43 | [
44 | 'scss/dollar-variable-colon-space-after'
45 | ],
46 | );
47 | });
48 | });
49 |
50 | describe('does not flag warnings with valid scss/dollar-variable-colon-space-after', () => {
51 | const validScss = (
52 | `a { $var: 10px;}
53 |
54 | `);
55 |
56 | let result;
57 |
58 | beforeEach(async () => {
59 | result = await stylelint.lint({
60 | code: validScss,
61 | config,
62 | });
63 | });
64 |
65 | it('did not error', () => {
66 | assert.equal(result.errored, false);
67 | });
68 |
69 | it('does not flag warnings', () => {
70 | assert.equal(result.results[0].warnings.length, 0);
71 | });
72 | });
--------------------------------------------------------------------------------
/__tests__/scss-dollar-variable-colon-space-before.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/dollar-variable-colon-space-before lint', () => {
9 | const invalidScss = (
10 | `a { $var : 10px;}
11 |
12 | `);
13 |
14 | let result;
15 |
16 | beforeEach(async () => {
17 | result = await stylelint.lint({
18 | code: invalidScss,
19 | config,
20 | });
21 | });
22 |
23 | it('did error', () => {
24 | assert.equal(result.errored, true);
25 | });
26 |
27 | it('flags warnings', () => {
28 | assert.equal(result.results[0].warnings.length, 1);
29 | });
30 |
31 | it('correct warning text', () => {
32 | assert.deepEqual(
33 | result.results[0].warnings.map((w) => w.text),
34 | [
35 | 'Unexpected whitespace before ":" (scss/dollar-variable-colon-space-before)',
36 | ],
37 | );
38 | });
39 |
40 | it('correct rule flagged', () => {
41 | assert.deepEqual(
42 | result.results[0].warnings.map((w) => w.rule),
43 | [
44 | 'scss/dollar-variable-colon-space-before'
45 | ],
46 | );
47 | });
48 | });
49 |
50 | describe('does not flag warnings with valid scss/dollar-variable-colon-space-after', () => {
51 | const validScss = (
52 | `a { $var: 10px;}
53 |
54 | `);
55 |
56 | let result;
57 |
58 | beforeEach(async () => {
59 | result = await stylelint.lint({
60 | code: validScss,
61 | config,
62 | });
63 | });
64 |
65 | it('did not error', () => {
66 | assert.equal(result.errored, false);
67 | });
68 |
69 | it('does not flag warnings', () => {
70 | assert.equal(result.results[0].warnings.length, 0);
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/__tests__/scss-dollar-variable-pattern.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with invalid scss/dollar-variable-pattern lint', () => {
9 | const invalidScss = (
10 | `$myVar: 10px;
11 | `);
12 |
13 | let result;
14 |
15 | beforeEach(async () => {
16 | result = await stylelint.lint({
17 | code: invalidScss,
18 | config,
19 | });
20 | });
21 |
22 | it('did error', () => {
23 | assert.equal(result.errored, true);
24 | });
25 |
26 | it('flags warnings', () => {
27 | assert.equal(result.results[0].warnings.length, 1);
28 | });
29 |
30 | it('correct warning text', () => {
31 | assert.deepEqual(
32 | result.results[0].warnings.map((w) => w.text),
33 | [
34 | 'Expected $ variable name to match specified pattern (scss/dollar-variable-pattern)',
35 | ],
36 | );
37 | });
38 |
39 | it('correct rule flagged', () => {
40 | assert.deepEqual(
41 | result.results[0].warnings.map((w) => w.rule),
42 | [
43 | 'scss/dollar-variable-pattern',
44 | ],
45 | );
46 | });
47 | });
48 |
49 | describe('does not flag warnings with valid scss/dollar-variable-pattern lint', () => {
50 | const validScss = (
51 | `$my-var: 10px;
52 |
53 | `);
54 |
55 | let result;
56 |
57 | beforeEach(async () => {
58 | result = await stylelint.lint({
59 | code: validScss,
60 | config,
61 | });
62 | });
63 |
64 | it('did not error', () => {
65 | assert.equal(result.errored, false);
66 | });
67 |
68 | it('does not flag warnings', () => {
69 | assert.equal(result.results[0].warnings.length, 0);
70 | });
71 | });
72 |
--------------------------------------------------------------------------------
/__tests__/scss-load-no-partial-leading-underscore.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/load-no-partial-leading-underscore lint', () => {
9 | const invalidScss = (
10 | `@import 'foo/_bar.scss';
11 | @import '_bar.scss';
12 | @import '_bar';
13 | @import 'bar.scss';
14 | `);
15 |
16 | let result;
17 |
18 | beforeEach(async () => {
19 | result = await stylelint.lint({
20 | code: invalidScss,
21 | config,
22 | });
23 | });
24 |
25 | it('did error', () => {
26 | assert.equal(result.errored, true);
27 | });
28 |
29 | it('flags warnings', () => {
30 | assert.equal(result.results[0].warnings.length, 6);
31 | });
32 |
33 | it('correct warning text', () => {
34 | assert.deepEqual(
35 | result.results[0].warnings.map((w) => w.text),
36 | [
37 | 'Unexpected extension ".scss" in imported partial name (scss/at-import-partial-extension-disallowed-list)',
38 | 'Unexpected extension ".scss" in imported partial name (scss/at-import-partial-extension-disallowed-list)',
39 | 'Unexpected extension ".scss" in imported partial name (scss/at-import-partial-extension-disallowed-list)',
40 | 'Unexpected leading underscore in imported partial name (scss/load-no-partial-leading-underscore)',
41 | 'Unexpected leading underscore in imported partial name (scss/load-no-partial-leading-underscore)',
42 | 'Unexpected leading underscore in imported partial name (scss/load-no-partial-leading-underscore)',
43 | ],
44 | );
45 | });
46 |
47 | it('correct rule flagged', () => {
48 | assert.deepEqual(
49 | result.results[0].warnings.map((w) => w.rule),
50 | [
51 | 'scss/at-import-partial-extension-disallowed-list',
52 | 'scss/at-import-partial-extension-disallowed-list',
53 | 'scss/at-import-partial-extension-disallowed-list',
54 | 'scss/load-no-partial-leading-underscore',
55 | 'scss/load-no-partial-leading-underscore',
56 | 'scss/load-no-partial-leading-underscore',
57 | ],
58 | );
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/__tests__/scss-no-global-function-names.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/no-global-function-names lint', () => {
9 | const invalidScss = (
10 | `a {
11 | background: adjust-color(#6b717f, $red: 15);
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected color.adjust instead of adjust-color (scss/no-global-function-names)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'scss/no-global-function-names',
46 | ],
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/__tests__/scss-percent-placeholder-pattern.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/percent-placeholder-pattern lint', () => {
9 | const invalidScss = (
10 | `%placeHolder {
11 | color: #f00;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected %-placeholder "%placeHolder" to match specified pattern (scss/percent-placeholder-pattern)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'scss/percent-placeholder-pattern',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid scss/percent-placeholder-pattern lint', () => {
52 | const validScss = (
53 | `%place-holder {
54 | color: #f00;
55 | }
56 |
57 | `);
58 |
59 | let result;
60 |
61 | beforeEach(async () => {
62 | result = await stylelint.lint({
63 | code: validScss,
64 | config,
65 | });
66 | });
67 |
68 | it('did not error', () => {
69 | assert.equal(result.errored, false);
70 | });
71 |
72 | it('does not flag warnings', () => {
73 | assert.equal(result.results[0].warnings.length, 0);
74 | });
75 | });
76 |
--------------------------------------------------------------------------------
/__tests__/scss-selector-no-redundant-nesting-selector.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with scss/selector-no-redundant-nesting-selector lint', () => {
9 | const invalidScss = (
10 | `.parentreference {
11 | & > .bar {
12 | color: #f00;
13 | }
14 | }
15 | `);
16 |
17 | let result;
18 |
19 | beforeEach(async () => {
20 | result = await stylelint.lint({
21 | code: invalidScss,
22 | config,
23 | });
24 | });
25 |
26 | it('did error', () => {
27 | assert.equal(result.errored, true);
28 | });
29 |
30 | it('flags warnings', () => {
31 | assert.equal(result.results[0].warnings.length, 1);
32 | });
33 |
34 | it('correct warning text', () => {
35 | assert.deepEqual(
36 | result.results[0].warnings.map((w) => w.text),
37 | [
38 | 'Unnecessary nesting selector (&) (scss/selector-no-redundant-nesting-selector)',
39 | ],
40 | );
41 | });
42 |
43 | it('correct rule flagged', () => {
44 | assert.deepEqual(
45 | result.results[0].warnings.map((w) => w.rule),
46 | [
47 | 'scss/selector-no-redundant-nesting-selector',
48 | ],
49 | );
50 | });
51 | });
52 |
53 | describe('does not flag warnings with valid scss/selector-no-redundant-nesting-selector lint', () => {
54 | const validScss = (
55 | `.parentreference {
56 | > .bar {
57 | color: #f00;
58 | }
59 | }
60 |
61 | `);
62 |
63 | let result;
64 |
65 | beforeEach(async () => {
66 | result = await stylelint.lint({
67 | code: validScss,
68 | config,
69 | });
70 | });
71 |
72 | it('did not error', () => {
73 | assert.equal(result.errored, false);
74 | });
75 |
76 | it('does not flag warnings', () => {
77 | assert.equal(result.results[0].warnings.length, 0);
78 | });
79 | });
--------------------------------------------------------------------------------
/__tests__/selector-class-pattern.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-class-pattern lint', () => {
9 | const invalidScss = (
10 | `.Foo {
11 | color: #f00;
12 | }
13 |
14 | .fooBar {
15 | color: #f00;
16 | }
17 |
18 | .fooBar5 {
19 | color: #f00;
20 | }
21 |
22 | .foo-Bar {
23 | color: #f00;
24 | }
25 |
26 | .foo-Bar---baz {
27 | color: #f00;
28 | }
29 | `);
30 |
31 | let result;
32 |
33 | beforeEach(async () => {
34 | result = await stylelint.lint({
35 | code: invalidScss,
36 | config,
37 | });
38 | });
39 |
40 | it('did error', () => {
41 | assert.equal(result.errored, true);
42 | });
43 |
44 | it('flags warnings', () => {
45 | assert.equal(result.results[0].warnings.length, 5);
46 | });
47 |
48 | it('correct warning text', () => {
49 | assert.deepEqual(
50 | result.results[0].warnings.map((w) => w.text),
51 | [
52 | 'Selector should be written in lowercase with hyphens (selector-class-pattern)',
53 | 'Selector should be written in lowercase with hyphens (selector-class-pattern)',
54 | 'Selector should be written in lowercase with hyphens (selector-class-pattern)',
55 | 'Selector should be written in lowercase with hyphens (selector-class-pattern)',
56 | 'Selector should be written in lowercase with hyphens (selector-class-pattern)',
57 | ],
58 | );
59 | });
60 |
61 | it('correct rule flagged', () => {
62 | assert.deepEqual(
63 | result.results[0].warnings.map((w) => w.rule),
64 | [
65 | 'selector-class-pattern',
66 | 'selector-class-pattern',
67 | 'selector-class-pattern',
68 | 'selector-class-pattern',
69 | 'selector-class-pattern',
70 | ],
71 | );
72 | });
73 | });
74 |
75 | describe('does not flag warnings with valid selector-class-pattern', () => {
76 | const validScss = (
77 | `.selector-format {
78 | color: #f00;
79 | }
80 |
81 | .foo {
82 | color: #f00;
83 | }
84 |
85 | .foo5 {
86 | color: #f00;
87 | }
88 |
89 | .foo-5 {
90 | color: #f00;
91 | }
92 |
93 | .foo--5 {
94 | color: #f00;
95 | }
96 |
97 | .foo-bar {
98 | color: #f00;
99 | }
100 |
101 | .foo--bar {
102 | color: #f00;
103 | }
104 |
105 | .foo-bar-5 {
106 | color: #f00;
107 | }
108 |
109 | .foo-bar-baz {
110 | color: #f00;
111 | }
112 |
113 | .foo-bar--baz {
114 | color: #f00;
115 | }
116 |
117 | .foo-bar-baz--qux {
118 | color: #f00;
119 | }
120 |
121 | .foo-bar--baz--qux {
122 | color: #f00;
123 | }
124 |
125 | .foo--bar--baz--qux {
126 | color: #f00;
127 | }
128 |
129 | .u-hidden {
130 | color: #f00;
131 | }
132 |
133 | .u-class-name {
134 | color: #f00;
135 | }
136 |
137 | .is-stateclass {
138 | color: #f00;
139 | }
140 |
141 | .has-state-class {
142 | color: #f00;
143 | }
144 |
145 | .js-dependantclass {
146 | color: #f00;
147 | }
148 |
149 | .namespace-u-text-center {
150 | color: #f00;
151 | }
152 |
153 | .namespace-u-sm-size11of12 {
154 | color: #f00;
155 | }
156 |
157 | .u-foobar17 {
158 | color: #f00;
159 | }
160 |
161 | .u-16by9 {
162 | color: #f00;
163 | }
164 |
165 | `);
166 |
167 | let result;
168 |
169 | beforeEach(async () => {
170 | result = await stylelint.lint({
171 | code: validScss,
172 | config,
173 | });
174 | });
175 |
176 | it('did not error', () => {
177 | assert.equal(result.errored, false);
178 | });
179 |
180 | it('does not flag warnings', () => {
181 | assert.equal(result.results[0].warnings.length, 0);
182 | });
183 | });
184 |
--------------------------------------------------------------------------------
/__tests__/selector-list-comma-newline-after.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-list-comma-newline-after lint', () => {
9 | const invalidScss = (
10 | `a, b {
11 | color: #fff;
12 | }
13 |
14 | a
15 | , b {
16 | color: #000;
17 | }
18 | `);
19 |
20 | let result;
21 |
22 | beforeEach(async () => {
23 | result = await stylelint.lint({
24 | code: invalidScss,
25 | config,
26 | });
27 | });
28 |
29 | it('did error', () => {
30 | assert.equal(result.errored, true);
31 | });
32 |
33 | it('flags warnings', () => {
34 | assert.equal(result.results[0].warnings.length, 2);
35 | });
36 |
37 | it('correct warning text', () => {
38 | assert.deepEqual(
39 | result.results[0].warnings.map((w) => w.text),
40 | [
41 | 'Expected newline after "," (@stylistic/selector-list-comma-newline-after)',
42 | 'Expected newline after "," (@stylistic/selector-list-comma-newline-after)'
43 | ],
44 | );
45 | });
46 |
47 | it('correct rule flagged', () => {
48 | assert.deepEqual(
49 | result.results[0].warnings.map((w) => w.rule),
50 | [
51 | '@stylistic/selector-list-comma-newline-after',
52 | '@stylistic/selector-list-comma-newline-after'
53 | ],
54 | );
55 | });
56 | });
57 |
58 | describe('does not flag warnings with valid selector-list-comma-newline-after', () => {
59 | const validScss = (
60 | `a,
61 | b {
62 | color: #fff;
63 | }
64 |
65 | `);
66 |
67 | let result;
68 |
69 | beforeEach(async () => {
70 | result = await stylelint.lint({
71 | code: validScss,
72 | config,
73 | });
74 | });
75 |
76 | it('did not error', () => {
77 | assert.equal(result.errored, false);
78 | });
79 |
80 | it('does not flag warnings', () => {
81 | assert.equal(result.results[0].warnings.length, 0);
82 | });
83 | });
84 |
--------------------------------------------------------------------------------
/__tests__/selector-max-compound-selectors.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-max-compound-selectors lint', () => {
9 | const invalidScss = (
10 | `.one .two .three > .four {
11 | color: #f00;
12 | }
13 |
14 | .one .two {
15 | .three > .four {
16 | color: #f00;
17 | }
18 | }
19 | `);
20 |
21 | let result;
22 |
23 | beforeEach(async () => {
24 | result = await stylelint.lint({
25 | code: invalidScss,
26 | config,
27 | });
28 | });
29 |
30 | it('did error', () => {
31 | assert.equal(result.errored, true);
32 | });
33 |
34 | it('flags warnings', () => {
35 | assert.equal(result.results[0].warnings.length, 2);
36 | });
37 |
38 | it('correct warning text', () => {
39 | assert.deepEqual(
40 | result.results[0].warnings.map((w) => w.text),
41 | [
42 | 'Expected ".one .two .three > .four" to have no more than 3 compound selectors (selector-max-compound-selectors)',
43 | 'Expected ".three > .four" to have no more than 3 compound selectors (selector-max-compound-selectors)'
44 | ],
45 | );
46 | });
47 |
48 | it('correct rule flagged', () => {
49 | assert.deepEqual(
50 | result.results[0].warnings.map((w) => w.rule),
51 | [
52 | 'selector-max-compound-selectors',
53 | 'selector-max-compound-selectors',
54 | ],
55 | );
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/__tests__/selector-max-id.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-max-id lint', () => {
9 | const invalidScss = (
10 | `#id-selector {
11 | color: #f00;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected "#id-selector" to have no more than 0 ID selectors (selector-max-id)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'selector-max-id',
46 | ],
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/__tests__/selector-no-qualifying-type.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-no-qualifying-type lint', () => {
9 | const invalidScss = (
10 | `div#thing {
11 | color: #f00;
12 | }
13 |
14 | ul.list {
15 | color: #f00;
16 | }
17 |
18 | ul li.item {
19 | color: #f00;
20 | }
21 |
22 | a[href='place'] {
23 | color: #f00;
24 | }
25 | `);
26 |
27 | let result;
28 |
29 | beforeEach(async () => {
30 | result = await stylelint.lint({
31 | code: invalidScss,
32 | config,
33 | });
34 | });
35 |
36 | it('did error', () => {
37 | assert.equal(result.errored, true);
38 | });
39 |
40 | it('flags warnings', () => {
41 | assert.equal(result.results[0].warnings.length, 5);
42 | });
43 |
44 | it('correct warning text', () => {
45 | assert.deepEqual(
46 | result.results[0].warnings.map((w) => w.text),
47 | [
48 | 'Expected "div#thing" to have no more than 0 ID selectors (selector-max-id)',
49 | 'Unexpected qualifying type selector "div#thing" (selector-no-qualifying-type)',
50 | 'Unexpected qualifying type selector "ul.list" (selector-no-qualifying-type)',
51 | 'Unexpected qualifying type selector "li.item" (selector-no-qualifying-type)',
52 | 'Unexpected qualifying type selector "a[href=\'place\']" (selector-no-qualifying-type)'
53 | ],
54 | );
55 | });
56 |
57 | it('correct rule flagged', () => {
58 | assert.deepEqual(
59 | result.results[0].warnings.map((w) => w.rule),
60 | [
61 | 'selector-max-id',
62 | 'selector-no-qualifying-type',
63 | 'selector-no-qualifying-type',
64 | 'selector-no-qualifying-type',
65 | 'selector-no-qualifying-type',
66 | ],
67 | );
68 | });
69 | });
70 |
--------------------------------------------------------------------------------
/__tests__/selector-no-vendor-prefix.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-no-vendor-prefix lint', () => {
9 | const invalidScss = (
10 | `::-moz-placeholder {
11 | color: #f00;
12 | }
13 |
14 | `);
15 |
16 | let result;
17 |
18 | beforeEach(async () => {
19 | result = await stylelint.lint({
20 | code: invalidScss,
21 | config,
22 | });
23 | });
24 |
25 | it('did error', () => {
26 | assert.equal(result.errored, true);
27 | });
28 |
29 | it('flags warnings', () => {
30 | assert.equal(result.results[0].warnings.length, 1);
31 | });
32 |
33 | it('correct warning text', () => {
34 | assert.deepEqual(
35 | result.results[0].warnings.map((w) => w.text),
36 | [
37 | 'Unexpected vendor-prefixed selector "::-moz-placeholder" (selector-no-vendor-prefix)'
38 | ],
39 | );
40 | });
41 |
42 | it('correct rule flagged', () => {
43 | assert.deepEqual(
44 | result.results[0].warnings.map((w) => w.rule),
45 | [
46 | 'selector-no-vendor-prefix',
47 | ],
48 | );
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/__tests__/selector-pseudo-element-colon-notation.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-pseudo-element-colon-notation lint', () => {
9 | const invalidScss = (
10 | `p:before {
11 | content: '>';
12 | }
13 |
14 | p::hover {
15 | color: #f00;
16 | }
17 | `);
18 |
19 | let result;
20 |
21 | beforeEach(async () => {
22 | result = await stylelint.lint({
23 | code: invalidScss,
24 | config,
25 | });
26 | });
27 |
28 | it('did error', () => {
29 | assert.equal(result.errored, true);
30 | });
31 |
32 | it('flags warnings', () => {
33 | assert.equal(result.results[0].warnings.length, 2);
34 | });
35 |
36 | it('correct warning text', () => {
37 | assert.deepEqual(
38 | result.results[0].warnings.map((w) => w.text),
39 | [
40 | 'Expected double colon pseudo-element notation (selector-pseudo-element-colon-notation)',
41 | 'Unexpected unknown pseudo-element selector "::hover" (selector-pseudo-element-no-unknown)'
42 | ],
43 | );
44 | });
45 |
46 | it('correct rule flagged', () => {
47 | assert.deepEqual(
48 | result.results[0].warnings.map((w) => w.rule),
49 | [
50 | 'selector-pseudo-element-colon-notation',
51 | 'selector-pseudo-element-no-unknown',
52 | ],
53 | );
54 | });
55 | });
56 |
57 | describe('does not flag warnings with valid selector-pseudo-element-colon-notation lint', () => {
58 | const validScss = (
59 | `a::before {
60 | content: '>';
61 | }
62 |
63 | a:hover {
64 | color: #f00;
65 | }
66 |
67 | `);
68 |
69 | let result;
70 |
71 | beforeEach(async () => {
72 | result = await stylelint.lint({
73 | code: validScss,
74 | config,
75 | });
76 | });
77 |
78 | it('did not error', () => {
79 | assert.equal(result.errored, false);
80 | });
81 |
82 | it('does not flag warnings', () => {
83 | assert.equal(result.results[0].warnings.length, 0);
84 | });
85 | });
86 |
--------------------------------------------------------------------------------
/__tests__/selector-pseudo-element-no-unknown.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with selector-pseudo-element-no-unknown lint', () => {
9 | const invalidScss = (
10 | `p::hover {
11 | color: #f00;
12 | }
13 |
14 | `);
15 |
16 | let result;
17 |
18 | beforeEach(async () => {
19 | result = await stylelint.lint({
20 | code: invalidScss,
21 | config,
22 | });
23 | });
24 |
25 | it('did error', () => {
26 | assert.equal(result.errored, true);
27 | });
28 |
29 | it('flags warnings', () => {
30 | assert.equal(result.results[0].warnings.length, 1);
31 | });
32 |
33 | it('correct warning text', () => {
34 | assert.deepEqual(
35 | result.results[0].warnings.map((w) => w.text),
36 | [
37 | 'Unexpected unknown pseudo-element selector "::hover" (selector-pseudo-element-no-unknown)'
38 | ],
39 | );
40 | });
41 |
42 | it('correct rule flagged', () => {
43 | assert.deepEqual(
44 | result.results[0].warnings.map((w) => w.rule),
45 | [
46 | 'selector-pseudo-element-no-unknown',
47 | ],
48 | );
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/__tests__/shorthand-property-no-redundant-values.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with shorthand-property-no-redundant-values lint', () => {
9 | const invalidScss = (
10 | `.shorthand {
11 | margin: 1px 1px 1px 1px;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected "1px 1px 1px 1px" to be "1px" (shorthand-property-no-redundant-values)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'shorthand-property-no-redundant-values',
46 | ],
47 | );
48 | });
49 | });
50 |
51 | describe('does not flag warnings with valid shorthand-property-no-redundant-values', () => {
52 | const validScss = (
53 | `.shorthand {
54 | margin: 1px;
55 | }
56 | `);
57 |
58 | let result;
59 |
60 | beforeEach(async () => {
61 | result = await stylelint.lint({
62 | code: validScss,
63 | config,
64 | });
65 | });
66 |
67 | it('did not error', () => {
68 | assert.equal(result.errored, false);
69 | });
70 |
71 | it('does not flag warnings', () => {
72 | assert.equal(result.results[0].warnings.length, 0);
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/__tests__/string-quotes.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with string-quotes lint', () => {
9 | const invalidScss = (
10 | `.test-selector[data-testid="foo"] {
11 | content: "x";
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 2);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Expected single quotes (@stylistic/string-quotes)',
37 | 'Expected single quotes (@stylistic/string-quotes)'
38 | ],
39 | );
40 | });
41 |
42 | it('correct rule flagged', () => {
43 | assert.deepEqual(
44 | result.results[0].warnings.map((w) => w.rule),
45 | [
46 | '@stylistic/string-quotes',
47 | '@stylistic/string-quotes'
48 | ],
49 | );
50 | });
51 | });
52 |
53 | describe('does not flag warnings with valid string-quotes', () => {
54 | const validScss = (
55 | `.test-selector {
56 | content: 'test';
57 | }
58 |
59 |
60 | `);
61 |
62 | let result;
63 |
64 | beforeEach(async () => {
65 | result = await stylelint.lint({
66 | code: validScss,
67 | config,
68 | });
69 | });
70 |
71 | it('did not error', () => {
72 | assert.equal(result.errored, false);
73 | });
74 |
75 | it('does not flag warnings', () => {
76 | assert.equal(result.results[0].warnings.length, 0);
77 | });
78 | });
79 |
--------------------------------------------------------------------------------
/__tests__/value-no-vendor-prefix.test.mjs:
--------------------------------------------------------------------------------
1 | import { beforeEach, describe, it } from 'node:test';
2 | import assert from 'node:assert/strict';
3 |
4 | import stylelint from 'stylelint';
5 |
6 | import config from '../index.js';
7 |
8 | describe('flags warnings with value-no-vendor-prefix lint', () => {
9 | const invalidScss = (
10 | `.value-prefix {
11 | display: -webkit-flex;
12 | }
13 | `);
14 |
15 | let result;
16 |
17 | beforeEach(async () => {
18 | result = await stylelint.lint({
19 | code: invalidScss,
20 | config,
21 | });
22 | });
23 |
24 | it('did error', () => {
25 | assert.equal(result.errored, true);
26 | });
27 |
28 | it('flags warnings', () => {
29 | assert.equal(result.results[0].warnings.length, 1);
30 | });
31 |
32 | it('correct warning text', () => {
33 | assert.deepEqual(
34 | result.results[0].warnings.map((w) => w.text),
35 | [
36 | 'Unexpected vendor-prefixed value "-webkit-flex" (value-no-vendor-prefix)',
37 | ],
38 | );
39 | });
40 |
41 | it('correct rule flagged', () => {
42 | assert.deepEqual(
43 | result.results[0].warnings.map((w) => w.rule),
44 | [
45 | 'value-no-vendor-prefix',
46 | ],
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "plugins": [
3 | "stylelint-scss",
4 | "@stylistic/stylelint-plugin",
5 | ],
6 | "customSyntax": "postcss-scss",
7 | "rules": {
8 | "at-rule-disallowed-list": ["debug"],
9 | "at-rule-no-unknown": null,
10 | "at-rule-no-vendor-prefix": true,
11 | "block-no-empty": true,
12 | "color-hex-length": "short",
13 | "color-named": "never",
14 | "color-no-invalid-hex": true,
15 | "declaration-block-single-line-max-declarations": 1,
16 | "declaration-property-value-disallowed-list": {
17 | "border": ["none"],
18 | "border-top": ["none"],
19 | "border-right": ["none"],
20 | "border-bottom": ["none"],
21 | "border-left": ["none"]
22 | },
23 | "function-url-quotes": "always",
24 | "length-zero-no-unit": true,
25 | "max-nesting-depth": [
26 | 1,
27 | {
28 | "ignoreAtRules": [
29 | "each",
30 | "media",
31 | "supports",
32 | "include"
33 | ]
34 | }
35 | ],
36 | "media-feature-name-no-vendor-prefix": true,
37 | "property-no-unknown": true,
38 | "property-no-vendor-prefix": true,
39 | "rule-empty-line-before": [
40 | "always-multi-line",
41 | {
42 | "except": ["first-nested"],
43 | "ignore": ["after-comment"]
44 | }
45 | ],
46 | "selector-class-pattern": [
47 | "^[a-z0-9\\-]+$",
48 | {
49 | "message":
50 | "Selector should be written in lowercase with hyphens (selector-class-pattern)"
51 | }
52 | ],
53 | "selector-max-compound-selectors": 3,
54 | "selector-max-id": 0,
55 | "selector-no-qualifying-type": true,
56 | "selector-no-vendor-prefix": true,
57 | "selector-pseudo-element-colon-notation": "double",
58 | "selector-pseudo-element-no-unknown": true,
59 | "shorthand-property-no-redundant-values": true,
60 | "value-no-vendor-prefix": true,
61 | "@stylistic/block-opening-brace-space-before": "always",
62 | "@stylistic/color-hex-case": "lower",
63 | "@stylistic/declaration-bang-space-after": "never",
64 | "@stylistic/declaration-bang-space-before": "always",
65 | "@stylistic/declaration-block-semicolon-newline-after": "always",
66 | "@stylistic/declaration-block-semicolon-space-before": "never",
67 | "@stylistic/declaration-block-trailing-semicolon": "always",
68 | "@stylistic/declaration-colon-space-after": "always-single-line",
69 | "@stylistic/declaration-colon-space-before": "never",
70 | "@stylistic/function-comma-space-after": "always-single-line",
71 | "@stylistic/function-parentheses-space-inside": "never",
72 | "@stylistic/indentation": 2,
73 | "@stylistic/media-feature-parentheses-space-inside": "never",
74 | "@stylistic/no-missing-end-of-source-newline": true,
75 | "@stylistic/number-leading-zero": "always",
76 | "@stylistic/number-no-trailing-zeros": true,
77 | "@stylistic/selector-list-comma-newline-after": "always",
78 | "@stylistic/string-quotes": "single",
79 | "scss/at-extend-no-missing-placeholder": true,
80 | "scss/at-function-pattern": "^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
81 | "scss/at-import-partial-extension-disallowed-list": ["scss"],
82 | "scss/at-rule-no-unknown": true,
83 | "scss/dollar-variable-colon-space-after": "always",
84 | "scss/dollar-variable-colon-space-before": "never",
85 | "scss/dollar-variable-pattern": "^[_]?[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
86 | "scss/load-no-partial-leading-underscore": true,
87 | "scss/no-global-function-names": true,
88 | "scss/percent-placeholder-pattern": "^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
89 | "scss/selector-no-redundant-nesting-selector": true,
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stylelint-config-sass-guidelines",
3 | "version": "12.1.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "stylelint-config-sass-guidelines",
9 | "version": "12.1.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "@stylistic/stylelint-plugin": "^3.0.1",
13 | "postcss-scss": "^4.0.9",
14 | "stylelint-scss": "^6.2.1"
15 | },
16 | "devDependencies": {
17 | "postcss": "^8.4.21",
18 | "stylelint": "^16.1.0"
19 | },
20 | "engines": {
21 | "node": ">=18.12.0"
22 | },
23 | "peerDependencies": {
24 | "postcss": "^8.4.21",
25 | "stylelint": "^16.1.0"
26 | }
27 | },
28 | "node_modules/@babel/code-frame": {
29 | "version": "7.26.2",
30 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
31 | "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
32 | "license": "MIT",
33 | "dependencies": {
34 | "@babel/helper-validator-identifier": "^7.25.9",
35 | "js-tokens": "^4.0.0",
36 | "picocolors": "^1.0.0"
37 | },
38 | "engines": {
39 | "node": ">=6.9.0"
40 | }
41 | },
42 | "node_modules/@babel/helper-validator-identifier": {
43 | "version": "7.25.9",
44 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
45 | "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
46 | "license": "MIT",
47 | "engines": {
48 | "node": ">=6.9.0"
49 | }
50 | },
51 | "node_modules/@csstools/css-parser-algorithms": {
52 | "version": "3.0.4",
53 | "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz",
54 | "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==",
55 | "funding": [
56 | {
57 | "type": "github",
58 | "url": "https://github.com/sponsors/csstools"
59 | },
60 | {
61 | "type": "opencollective",
62 | "url": "https://opencollective.com/csstools"
63 | }
64 | ],
65 | "license": "MIT",
66 | "engines": {
67 | "node": ">=18"
68 | },
69 | "peerDependencies": {
70 | "@csstools/css-tokenizer": "^3.0.3"
71 | }
72 | },
73 | "node_modules/@csstools/css-tokenizer": {
74 | "version": "3.0.3",
75 | "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz",
76 | "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==",
77 | "funding": [
78 | {
79 | "type": "github",
80 | "url": "https://github.com/sponsors/csstools"
81 | },
82 | {
83 | "type": "opencollective",
84 | "url": "https://opencollective.com/csstools"
85 | }
86 | ],
87 | "license": "MIT",
88 | "engines": {
89 | "node": ">=18"
90 | }
91 | },
92 | "node_modules/@csstools/media-query-list-parser": {
93 | "version": "3.0.1",
94 | "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz",
95 | "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==",
96 | "funding": [
97 | {
98 | "type": "github",
99 | "url": "https://github.com/sponsors/csstools"
100 | },
101 | {
102 | "type": "opencollective",
103 | "url": "https://opencollective.com/csstools"
104 | }
105 | ],
106 | "license": "MIT",
107 | "engines": {
108 | "node": ">=18"
109 | },
110 | "peerDependencies": {
111 | "@csstools/css-parser-algorithms": "^3.0.1",
112 | "@csstools/css-tokenizer": "^3.0.1"
113 | }
114 | },
115 | "node_modules/@dual-bundle/import-meta-resolve": {
116 | "version": "4.1.0",
117 | "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
118 | "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==",
119 | "license": "MIT",
120 | "funding": {
121 | "type": "github",
122 | "url": "https://github.com/sponsors/wooorm"
123 | }
124 | },
125 | "node_modules/@keyv/serialize": {
126 | "version": "1.0.2",
127 | "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz",
128 | "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==",
129 | "license": "MIT",
130 | "dependencies": {
131 | "buffer": "^6.0.3"
132 | }
133 | },
134 | "node_modules/@nodelib/fs.scandir": {
135 | "version": "2.1.5",
136 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
137 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
138 | "license": "MIT",
139 | "dependencies": {
140 | "@nodelib/fs.stat": "2.0.5",
141 | "run-parallel": "^1.1.9"
142 | },
143 | "engines": {
144 | "node": ">= 8"
145 | }
146 | },
147 | "node_modules/@nodelib/fs.stat": {
148 | "version": "2.0.5",
149 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
150 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
151 | "license": "MIT",
152 | "engines": {
153 | "node": ">= 8"
154 | }
155 | },
156 | "node_modules/@nodelib/fs.walk": {
157 | "version": "1.2.8",
158 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
159 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
160 | "license": "MIT",
161 | "dependencies": {
162 | "@nodelib/fs.scandir": "2.1.5",
163 | "fastq": "^1.6.0"
164 | },
165 | "engines": {
166 | "node": ">= 8"
167 | }
168 | },
169 | "node_modules/@stylistic/stylelint-plugin": {
170 | "version": "3.1.1",
171 | "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.1.1.tgz",
172 | "integrity": "sha512-XagAHHIa528EvyGybv8EEYGK5zrVW74cHpsjhtovVATbhDRuJYfE+X4HCaAieW9lCkwbX6L+X0I4CiUG3w/hFw==",
173 | "license": "MIT",
174 | "dependencies": {
175 | "@csstools/css-parser-algorithms": "^3.0.1",
176 | "@csstools/css-tokenizer": "^3.0.1",
177 | "@csstools/media-query-list-parser": "^3.0.1",
178 | "is-plain-object": "^5.0.0",
179 | "postcss-selector-parser": "^6.1.2",
180 | "postcss-value-parser": "^4.2.0",
181 | "style-search": "^0.1.0",
182 | "stylelint": "^16.8.2"
183 | },
184 | "engines": {
185 | "node": "^18.12 || >=20.9"
186 | },
187 | "peerDependencies": {
188 | "stylelint": "^16.8.0"
189 | }
190 | },
191 | "node_modules/ajv": {
192 | "version": "8.17.1",
193 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
194 | "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
195 | "license": "MIT",
196 | "dependencies": {
197 | "fast-deep-equal": "^3.1.3",
198 | "fast-uri": "^3.0.1",
199 | "json-schema-traverse": "^1.0.0",
200 | "require-from-string": "^2.0.2"
201 | },
202 | "funding": {
203 | "type": "github",
204 | "url": "https://github.com/sponsors/epoberezkin"
205 | }
206 | },
207 | "node_modules/ansi-regex": {
208 | "version": "5.0.1",
209 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
210 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
211 | "license": "MIT",
212 | "engines": {
213 | "node": ">=8"
214 | }
215 | },
216 | "node_modules/ansi-styles": {
217 | "version": "4.3.0",
218 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
219 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
220 | "license": "MIT",
221 | "dependencies": {
222 | "color-convert": "^2.0.1"
223 | },
224 | "engines": {
225 | "node": ">=8"
226 | },
227 | "funding": {
228 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
229 | }
230 | },
231 | "node_modules/argparse": {
232 | "version": "2.0.1",
233 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
234 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
235 | "license": "Python-2.0"
236 | },
237 | "node_modules/array-union": {
238 | "version": "2.1.0",
239 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
240 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
241 | "license": "MIT",
242 | "engines": {
243 | "node": ">=8"
244 | }
245 | },
246 | "node_modules/astral-regex": {
247 | "version": "2.0.0",
248 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
249 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
250 | "license": "MIT",
251 | "engines": {
252 | "node": ">=8"
253 | }
254 | },
255 | "node_modules/balanced-match": {
256 | "version": "2.0.0",
257 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz",
258 | "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==",
259 | "license": "MIT"
260 | },
261 | "node_modules/base64-js": {
262 | "version": "1.5.1",
263 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
264 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
265 | "funding": [
266 | {
267 | "type": "github",
268 | "url": "https://github.com/sponsors/feross"
269 | },
270 | {
271 | "type": "patreon",
272 | "url": "https://www.patreon.com/feross"
273 | },
274 | {
275 | "type": "consulting",
276 | "url": "https://feross.org/support"
277 | }
278 | ],
279 | "license": "MIT"
280 | },
281 | "node_modules/braces": {
282 | "version": "3.0.3",
283 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
284 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
285 | "license": "MIT",
286 | "dependencies": {
287 | "fill-range": "^7.1.1"
288 | },
289 | "engines": {
290 | "node": ">=8"
291 | }
292 | },
293 | "node_modules/buffer": {
294 | "version": "6.0.3",
295 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
296 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
297 | "funding": [
298 | {
299 | "type": "github",
300 | "url": "https://github.com/sponsors/feross"
301 | },
302 | {
303 | "type": "patreon",
304 | "url": "https://www.patreon.com/feross"
305 | },
306 | {
307 | "type": "consulting",
308 | "url": "https://feross.org/support"
309 | }
310 | ],
311 | "license": "MIT",
312 | "dependencies": {
313 | "base64-js": "^1.3.1",
314 | "ieee754": "^1.2.1"
315 | }
316 | },
317 | "node_modules/cacheable": {
318 | "version": "1.8.7",
319 | "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.7.tgz",
320 | "integrity": "sha512-AbfG7dAuYNjYxFUtL1lAqmlWdxczCJ47w7cFjhGcnGnUdwSo6VgmSojfoW3tUI12HUkgTJ5kqj78yyq6TsFtlg==",
321 | "license": "MIT",
322 | "dependencies": {
323 | "hookified": "^1.6.0",
324 | "keyv": "^5.2.3"
325 | }
326 | },
327 | "node_modules/callsites": {
328 | "version": "3.1.0",
329 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
330 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
331 | "license": "MIT",
332 | "engines": {
333 | "node": ">=6"
334 | }
335 | },
336 | "node_modules/color-convert": {
337 | "version": "2.0.1",
338 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
339 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
340 | "license": "MIT",
341 | "dependencies": {
342 | "color-name": "~1.1.4"
343 | },
344 | "engines": {
345 | "node": ">=7.0.0"
346 | }
347 | },
348 | "node_modules/color-name": {
349 | "version": "1.1.4",
350 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
351 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
352 | "license": "MIT"
353 | },
354 | "node_modules/colord": {
355 | "version": "2.9.3",
356 | "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
357 | "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
358 | "license": "MIT"
359 | },
360 | "node_modules/cosmiconfig": {
361 | "version": "9.0.0",
362 | "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
363 | "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
364 | "license": "MIT",
365 | "dependencies": {
366 | "env-paths": "^2.2.1",
367 | "import-fresh": "^3.3.0",
368 | "js-yaml": "^4.1.0",
369 | "parse-json": "^5.2.0"
370 | },
371 | "engines": {
372 | "node": ">=14"
373 | },
374 | "funding": {
375 | "url": "https://github.com/sponsors/d-fischer"
376 | },
377 | "peerDependencies": {
378 | "typescript": ">=4.9.5"
379 | },
380 | "peerDependenciesMeta": {
381 | "typescript": {
382 | "optional": true
383 | }
384 | }
385 | },
386 | "node_modules/css-functions-list": {
387 | "version": "3.2.3",
388 | "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz",
389 | "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==",
390 | "license": "MIT",
391 | "engines": {
392 | "node": ">=12 || >=16"
393 | }
394 | },
395 | "node_modules/css-tree": {
396 | "version": "3.1.0",
397 | "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz",
398 | "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==",
399 | "license": "MIT",
400 | "dependencies": {
401 | "mdn-data": "2.12.2",
402 | "source-map-js": "^1.0.1"
403 | },
404 | "engines": {
405 | "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
406 | }
407 | },
408 | "node_modules/cssesc": {
409 | "version": "3.0.0",
410 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
411 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
412 | "license": "MIT",
413 | "bin": {
414 | "cssesc": "bin/cssesc"
415 | },
416 | "engines": {
417 | "node": ">=4"
418 | }
419 | },
420 | "node_modules/debug": {
421 | "version": "4.4.0",
422 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
423 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
424 | "license": "MIT",
425 | "dependencies": {
426 | "ms": "^2.1.3"
427 | },
428 | "engines": {
429 | "node": ">=6.0"
430 | },
431 | "peerDependenciesMeta": {
432 | "supports-color": {
433 | "optional": true
434 | }
435 | }
436 | },
437 | "node_modules/dir-glob": {
438 | "version": "3.0.1",
439 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
440 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
441 | "license": "MIT",
442 | "dependencies": {
443 | "path-type": "^4.0.0"
444 | },
445 | "engines": {
446 | "node": ">=8"
447 | }
448 | },
449 | "node_modules/emoji-regex": {
450 | "version": "8.0.0",
451 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
452 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
453 | "license": "MIT"
454 | },
455 | "node_modules/env-paths": {
456 | "version": "2.2.1",
457 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
458 | "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
459 | "license": "MIT",
460 | "engines": {
461 | "node": ">=6"
462 | }
463 | },
464 | "node_modules/error-ex": {
465 | "version": "1.3.2",
466 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
467 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
468 | "license": "MIT",
469 | "dependencies": {
470 | "is-arrayish": "^0.2.1"
471 | }
472 | },
473 | "node_modules/fast-deep-equal": {
474 | "version": "3.1.3",
475 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
476 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
477 | "license": "MIT"
478 | },
479 | "node_modules/fast-glob": {
480 | "version": "3.3.3",
481 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
482 | "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
483 | "license": "MIT",
484 | "dependencies": {
485 | "@nodelib/fs.stat": "^2.0.2",
486 | "@nodelib/fs.walk": "^1.2.3",
487 | "glob-parent": "^5.1.2",
488 | "merge2": "^1.3.0",
489 | "micromatch": "^4.0.8"
490 | },
491 | "engines": {
492 | "node": ">=8.6.0"
493 | }
494 | },
495 | "node_modules/fast-uri": {
496 | "version": "3.0.5",
497 | "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz",
498 | "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==",
499 | "funding": [
500 | {
501 | "type": "github",
502 | "url": "https://github.com/sponsors/fastify"
503 | },
504 | {
505 | "type": "opencollective",
506 | "url": "https://opencollective.com/fastify"
507 | }
508 | ],
509 | "license": "BSD-3-Clause"
510 | },
511 | "node_modules/fastest-levenshtein": {
512 | "version": "1.0.16",
513 | "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
514 | "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
515 | "license": "MIT",
516 | "engines": {
517 | "node": ">= 4.9.1"
518 | }
519 | },
520 | "node_modules/fastq": {
521 | "version": "1.18.0",
522 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
523 | "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
524 | "license": "ISC",
525 | "dependencies": {
526 | "reusify": "^1.0.4"
527 | }
528 | },
529 | "node_modules/file-entry-cache": {
530 | "version": "10.0.5",
531 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.5.tgz",
532 | "integrity": "sha512-umpQsJrBNsdMDgreSryMEXvJh66XeLtZUwA8Gj7rHGearGufUFv6rB/bcXRFsiGWw/VeSUgUofF4Rf2UKEOrTA==",
533 | "license": "MIT",
534 | "dependencies": {
535 | "flat-cache": "^6.1.5"
536 | }
537 | },
538 | "node_modules/fill-range": {
539 | "version": "7.1.1",
540 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
541 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
542 | "license": "MIT",
543 | "dependencies": {
544 | "to-regex-range": "^5.0.1"
545 | },
546 | "engines": {
547 | "node": ">=8"
548 | }
549 | },
550 | "node_modules/flat-cache": {
551 | "version": "6.1.5",
552 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.5.tgz",
553 | "integrity": "sha512-QR+2kN38f8nMfiIQ1LHYjuDEmZNZVjxuxY+HufbS3BW0EX01Q5OnH7iduOYRutmgiXb797HAKcXUeXrvRjjgSQ==",
554 | "license": "MIT",
555 | "dependencies": {
556 | "cacheable": "^1.8.7",
557 | "flatted": "^3.3.2",
558 | "hookified": "^1.6.0"
559 | }
560 | },
561 | "node_modules/flatted": {
562 | "version": "3.3.2",
563 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
564 | "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
565 | "license": "ISC"
566 | },
567 | "node_modules/glob-parent": {
568 | "version": "5.1.2",
569 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
570 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
571 | "license": "ISC",
572 | "dependencies": {
573 | "is-glob": "^4.0.1"
574 | },
575 | "engines": {
576 | "node": ">= 6"
577 | }
578 | },
579 | "node_modules/global-modules": {
580 | "version": "2.0.0",
581 | "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
582 | "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
583 | "license": "MIT",
584 | "dependencies": {
585 | "global-prefix": "^3.0.0"
586 | },
587 | "engines": {
588 | "node": ">=6"
589 | }
590 | },
591 | "node_modules/global-prefix": {
592 | "version": "3.0.0",
593 | "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
594 | "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
595 | "license": "MIT",
596 | "dependencies": {
597 | "ini": "^1.3.5",
598 | "kind-of": "^6.0.2",
599 | "which": "^1.3.1"
600 | },
601 | "engines": {
602 | "node": ">=6"
603 | }
604 | },
605 | "node_modules/globby": {
606 | "version": "11.1.0",
607 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
608 | "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
609 | "license": "MIT",
610 | "dependencies": {
611 | "array-union": "^2.1.0",
612 | "dir-glob": "^3.0.1",
613 | "fast-glob": "^3.2.9",
614 | "ignore": "^5.2.0",
615 | "merge2": "^1.4.1",
616 | "slash": "^3.0.0"
617 | },
618 | "engines": {
619 | "node": ">=10"
620 | },
621 | "funding": {
622 | "url": "https://github.com/sponsors/sindresorhus"
623 | }
624 | },
625 | "node_modules/globby/node_modules/ignore": {
626 | "version": "5.3.2",
627 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
628 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
629 | "license": "MIT",
630 | "engines": {
631 | "node": ">= 4"
632 | }
633 | },
634 | "node_modules/globjoin": {
635 | "version": "0.1.4",
636 | "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
637 | "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==",
638 | "license": "MIT"
639 | },
640 | "node_modules/has-flag": {
641 | "version": "4.0.0",
642 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
643 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
644 | "license": "MIT",
645 | "engines": {
646 | "node": ">=8"
647 | }
648 | },
649 | "node_modules/hookified": {
650 | "version": "1.6.0",
651 | "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.6.0.tgz",
652 | "integrity": "sha512-se7cpwTA+iA/eY548Bu03JJqBiEZAqU2jnyKdj5B5qurtBg64CZGHTgqCv4Yh7NWu6FGI09W61MCq+NoPj9GXA==",
653 | "license": "MIT"
654 | },
655 | "node_modules/html-tags": {
656 | "version": "3.3.1",
657 | "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
658 | "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
659 | "license": "MIT",
660 | "engines": {
661 | "node": ">=8"
662 | },
663 | "funding": {
664 | "url": "https://github.com/sponsors/sindresorhus"
665 | }
666 | },
667 | "node_modules/ieee754": {
668 | "version": "1.2.1",
669 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
670 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
671 | "funding": [
672 | {
673 | "type": "github",
674 | "url": "https://github.com/sponsors/feross"
675 | },
676 | {
677 | "type": "patreon",
678 | "url": "https://www.patreon.com/feross"
679 | },
680 | {
681 | "type": "consulting",
682 | "url": "https://feross.org/support"
683 | }
684 | ],
685 | "license": "BSD-3-Clause"
686 | },
687 | "node_modules/ignore": {
688 | "version": "7.0.3",
689 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz",
690 | "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==",
691 | "license": "MIT",
692 | "engines": {
693 | "node": ">= 4"
694 | }
695 | },
696 | "node_modules/import-fresh": {
697 | "version": "3.3.0",
698 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
699 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
700 | "license": "MIT",
701 | "dependencies": {
702 | "parent-module": "^1.0.0",
703 | "resolve-from": "^4.0.0"
704 | },
705 | "engines": {
706 | "node": ">=6"
707 | },
708 | "funding": {
709 | "url": "https://github.com/sponsors/sindresorhus"
710 | }
711 | },
712 | "node_modules/import-fresh/node_modules/resolve-from": {
713 | "version": "4.0.0",
714 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
715 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
716 | "license": "MIT",
717 | "engines": {
718 | "node": ">=4"
719 | }
720 | },
721 | "node_modules/imurmurhash": {
722 | "version": "0.1.4",
723 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
724 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
725 | "license": "MIT",
726 | "engines": {
727 | "node": ">=0.8.19"
728 | }
729 | },
730 | "node_modules/ini": {
731 | "version": "1.3.8",
732 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
733 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
734 | "license": "ISC"
735 | },
736 | "node_modules/is-arrayish": {
737 | "version": "0.2.1",
738 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
739 | "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
740 | "license": "MIT"
741 | },
742 | "node_modules/is-extglob": {
743 | "version": "2.1.1",
744 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
745 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
746 | "license": "MIT",
747 | "engines": {
748 | "node": ">=0.10.0"
749 | }
750 | },
751 | "node_modules/is-fullwidth-code-point": {
752 | "version": "3.0.0",
753 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
754 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
755 | "license": "MIT",
756 | "engines": {
757 | "node": ">=8"
758 | }
759 | },
760 | "node_modules/is-glob": {
761 | "version": "4.0.3",
762 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
763 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
764 | "license": "MIT",
765 | "dependencies": {
766 | "is-extglob": "^2.1.1"
767 | },
768 | "engines": {
769 | "node": ">=0.10.0"
770 | }
771 | },
772 | "node_modules/is-number": {
773 | "version": "7.0.0",
774 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
775 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
776 | "license": "MIT",
777 | "engines": {
778 | "node": ">=0.12.0"
779 | }
780 | },
781 | "node_modules/is-plain-object": {
782 | "version": "5.0.0",
783 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
784 | "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
785 | "license": "MIT",
786 | "engines": {
787 | "node": ">=0.10.0"
788 | }
789 | },
790 | "node_modules/isexe": {
791 | "version": "2.0.0",
792 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
793 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
794 | "license": "ISC"
795 | },
796 | "node_modules/js-tokens": {
797 | "version": "4.0.0",
798 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
799 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
800 | "license": "MIT"
801 | },
802 | "node_modules/js-yaml": {
803 | "version": "4.1.0",
804 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
805 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
806 | "license": "MIT",
807 | "dependencies": {
808 | "argparse": "^2.0.1"
809 | },
810 | "bin": {
811 | "js-yaml": "bin/js-yaml.js"
812 | }
813 | },
814 | "node_modules/json-parse-even-better-errors": {
815 | "version": "2.3.1",
816 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
817 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
818 | "license": "MIT"
819 | },
820 | "node_modules/json-schema-traverse": {
821 | "version": "1.0.0",
822 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
823 | "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
824 | "license": "MIT"
825 | },
826 | "node_modules/keyv": {
827 | "version": "5.2.3",
828 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.2.3.tgz",
829 | "integrity": "sha512-AGKecUfzrowabUv0bH1RIR5Vf7w+l4S3xtQAypKaUpTdIR1EbrAcTxHCrpo9Q+IWeUlFE2palRtgIQcgm+PQJw==",
830 | "license": "MIT",
831 | "dependencies": {
832 | "@keyv/serialize": "^1.0.2"
833 | }
834 | },
835 | "node_modules/kind-of": {
836 | "version": "6.0.3",
837 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
838 | "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
839 | "license": "MIT",
840 | "engines": {
841 | "node": ">=0.10.0"
842 | }
843 | },
844 | "node_modules/known-css-properties": {
845 | "version": "0.35.0",
846 | "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz",
847 | "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==",
848 | "license": "MIT"
849 | },
850 | "node_modules/lines-and-columns": {
851 | "version": "1.2.4",
852 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
853 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
854 | "license": "MIT"
855 | },
856 | "node_modules/lodash.truncate": {
857 | "version": "4.4.2",
858 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
859 | "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
860 | "license": "MIT"
861 | },
862 | "node_modules/mathml-tag-names": {
863 | "version": "2.1.3",
864 | "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
865 | "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
866 | "license": "MIT",
867 | "funding": {
868 | "type": "github",
869 | "url": "https://github.com/sponsors/wooorm"
870 | }
871 | },
872 | "node_modules/mdn-data": {
873 | "version": "2.12.2",
874 | "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz",
875 | "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==",
876 | "license": "CC0-1.0"
877 | },
878 | "node_modules/meow": {
879 | "version": "13.2.0",
880 | "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
881 | "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==",
882 | "license": "MIT",
883 | "engines": {
884 | "node": ">=18"
885 | },
886 | "funding": {
887 | "url": "https://github.com/sponsors/sindresorhus"
888 | }
889 | },
890 | "node_modules/merge2": {
891 | "version": "1.4.1",
892 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
893 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
894 | "license": "MIT",
895 | "engines": {
896 | "node": ">= 8"
897 | }
898 | },
899 | "node_modules/micromatch": {
900 | "version": "4.0.8",
901 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
902 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
903 | "license": "MIT",
904 | "dependencies": {
905 | "braces": "^3.0.3",
906 | "picomatch": "^2.3.1"
907 | },
908 | "engines": {
909 | "node": ">=8.6"
910 | }
911 | },
912 | "node_modules/ms": {
913 | "version": "2.1.3",
914 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
915 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
916 | "license": "MIT"
917 | },
918 | "node_modules/nanoid": {
919 | "version": "3.3.8",
920 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
921 | "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
922 | "funding": [
923 | {
924 | "type": "github",
925 | "url": "https://github.com/sponsors/ai"
926 | }
927 | ],
928 | "license": "MIT",
929 | "bin": {
930 | "nanoid": "bin/nanoid.cjs"
931 | },
932 | "engines": {
933 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
934 | }
935 | },
936 | "node_modules/normalize-path": {
937 | "version": "3.0.0",
938 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
939 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
940 | "license": "MIT",
941 | "engines": {
942 | "node": ">=0.10.0"
943 | }
944 | },
945 | "node_modules/parent-module": {
946 | "version": "1.0.1",
947 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
948 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
949 | "license": "MIT",
950 | "dependencies": {
951 | "callsites": "^3.0.0"
952 | },
953 | "engines": {
954 | "node": ">=6"
955 | }
956 | },
957 | "node_modules/parse-json": {
958 | "version": "5.2.0",
959 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
960 | "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
961 | "license": "MIT",
962 | "dependencies": {
963 | "@babel/code-frame": "^7.0.0",
964 | "error-ex": "^1.3.1",
965 | "json-parse-even-better-errors": "^2.3.0",
966 | "lines-and-columns": "^1.1.6"
967 | },
968 | "engines": {
969 | "node": ">=8"
970 | },
971 | "funding": {
972 | "url": "https://github.com/sponsors/sindresorhus"
973 | }
974 | },
975 | "node_modules/path-type": {
976 | "version": "4.0.0",
977 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
978 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
979 | "license": "MIT",
980 | "engines": {
981 | "node": ">=8"
982 | }
983 | },
984 | "node_modules/picocolors": {
985 | "version": "1.1.1",
986 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
987 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
988 | "license": "ISC"
989 | },
990 | "node_modules/picomatch": {
991 | "version": "2.3.1",
992 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
993 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
994 | "license": "MIT",
995 | "engines": {
996 | "node": ">=8.6"
997 | },
998 | "funding": {
999 | "url": "https://github.com/sponsors/jonschlinkert"
1000 | }
1001 | },
1002 | "node_modules/postcss": {
1003 | "version": "8.5.1",
1004 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
1005 | "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
1006 | "funding": [
1007 | {
1008 | "type": "opencollective",
1009 | "url": "https://opencollective.com/postcss/"
1010 | },
1011 | {
1012 | "type": "tidelift",
1013 | "url": "https://tidelift.com/funding/github/npm/postcss"
1014 | },
1015 | {
1016 | "type": "github",
1017 | "url": "https://github.com/sponsors/ai"
1018 | }
1019 | ],
1020 | "license": "MIT",
1021 | "dependencies": {
1022 | "nanoid": "^3.3.8",
1023 | "picocolors": "^1.1.1",
1024 | "source-map-js": "^1.2.1"
1025 | },
1026 | "engines": {
1027 | "node": "^10 || ^12 || >=14"
1028 | }
1029 | },
1030 | "node_modules/postcss-media-query-parser": {
1031 | "version": "0.2.3",
1032 | "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
1033 | "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==",
1034 | "license": "MIT"
1035 | },
1036 | "node_modules/postcss-resolve-nested-selector": {
1037 | "version": "0.1.6",
1038 | "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz",
1039 | "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==",
1040 | "license": "MIT"
1041 | },
1042 | "node_modules/postcss-safe-parser": {
1043 | "version": "7.0.1",
1044 | "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz",
1045 | "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==",
1046 | "funding": [
1047 | {
1048 | "type": "opencollective",
1049 | "url": "https://opencollective.com/postcss/"
1050 | },
1051 | {
1052 | "type": "tidelift",
1053 | "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
1054 | },
1055 | {
1056 | "type": "github",
1057 | "url": "https://github.com/sponsors/ai"
1058 | }
1059 | ],
1060 | "license": "MIT",
1061 | "engines": {
1062 | "node": ">=18.0"
1063 | },
1064 | "peerDependencies": {
1065 | "postcss": "^8.4.31"
1066 | }
1067 | },
1068 | "node_modules/postcss-scss": {
1069 | "version": "4.0.9",
1070 | "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz",
1071 | "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==",
1072 | "funding": [
1073 | {
1074 | "type": "opencollective",
1075 | "url": "https://opencollective.com/postcss/"
1076 | },
1077 | {
1078 | "type": "tidelift",
1079 | "url": "https://tidelift.com/funding/github/npm/postcss-scss"
1080 | },
1081 | {
1082 | "type": "github",
1083 | "url": "https://github.com/sponsors/ai"
1084 | }
1085 | ],
1086 | "license": "MIT",
1087 | "engines": {
1088 | "node": ">=12.0"
1089 | },
1090 | "peerDependencies": {
1091 | "postcss": "^8.4.29"
1092 | }
1093 | },
1094 | "node_modules/postcss-selector-parser": {
1095 | "version": "6.1.2",
1096 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
1097 | "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
1098 | "license": "MIT",
1099 | "dependencies": {
1100 | "cssesc": "^3.0.0",
1101 | "util-deprecate": "^1.0.2"
1102 | },
1103 | "engines": {
1104 | "node": ">=4"
1105 | }
1106 | },
1107 | "node_modules/postcss-value-parser": {
1108 | "version": "4.2.0",
1109 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
1110 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
1111 | "license": "MIT"
1112 | },
1113 | "node_modules/queue-microtask": {
1114 | "version": "1.2.3",
1115 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1116 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1117 | "funding": [
1118 | {
1119 | "type": "github",
1120 | "url": "https://github.com/sponsors/feross"
1121 | },
1122 | {
1123 | "type": "patreon",
1124 | "url": "https://www.patreon.com/feross"
1125 | },
1126 | {
1127 | "type": "consulting",
1128 | "url": "https://feross.org/support"
1129 | }
1130 | ],
1131 | "license": "MIT"
1132 | },
1133 | "node_modules/require-from-string": {
1134 | "version": "2.0.2",
1135 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
1136 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
1137 | "license": "MIT",
1138 | "engines": {
1139 | "node": ">=0.10.0"
1140 | }
1141 | },
1142 | "node_modules/resolve-from": {
1143 | "version": "5.0.0",
1144 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
1145 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
1146 | "license": "MIT",
1147 | "engines": {
1148 | "node": ">=8"
1149 | }
1150 | },
1151 | "node_modules/reusify": {
1152 | "version": "1.0.4",
1153 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
1154 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
1155 | "license": "MIT",
1156 | "engines": {
1157 | "iojs": ">=1.0.0",
1158 | "node": ">=0.10.0"
1159 | }
1160 | },
1161 | "node_modules/run-parallel": {
1162 | "version": "1.2.0",
1163 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1164 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1165 | "funding": [
1166 | {
1167 | "type": "github",
1168 | "url": "https://github.com/sponsors/feross"
1169 | },
1170 | {
1171 | "type": "patreon",
1172 | "url": "https://www.patreon.com/feross"
1173 | },
1174 | {
1175 | "type": "consulting",
1176 | "url": "https://feross.org/support"
1177 | }
1178 | ],
1179 | "license": "MIT",
1180 | "dependencies": {
1181 | "queue-microtask": "^1.2.2"
1182 | }
1183 | },
1184 | "node_modules/signal-exit": {
1185 | "version": "4.1.0",
1186 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
1187 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
1188 | "license": "ISC",
1189 | "engines": {
1190 | "node": ">=14"
1191 | },
1192 | "funding": {
1193 | "url": "https://github.com/sponsors/isaacs"
1194 | }
1195 | },
1196 | "node_modules/slash": {
1197 | "version": "3.0.0",
1198 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
1199 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
1200 | "license": "MIT",
1201 | "engines": {
1202 | "node": ">=8"
1203 | }
1204 | },
1205 | "node_modules/slice-ansi": {
1206 | "version": "4.0.0",
1207 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
1208 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
1209 | "license": "MIT",
1210 | "dependencies": {
1211 | "ansi-styles": "^4.0.0",
1212 | "astral-regex": "^2.0.0",
1213 | "is-fullwidth-code-point": "^3.0.0"
1214 | },
1215 | "engines": {
1216 | "node": ">=10"
1217 | },
1218 | "funding": {
1219 | "url": "https://github.com/chalk/slice-ansi?sponsor=1"
1220 | }
1221 | },
1222 | "node_modules/source-map-js": {
1223 | "version": "1.2.1",
1224 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1225 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1226 | "license": "BSD-3-Clause",
1227 | "engines": {
1228 | "node": ">=0.10.0"
1229 | }
1230 | },
1231 | "node_modules/string-width": {
1232 | "version": "4.2.3",
1233 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1234 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1235 | "license": "MIT",
1236 | "dependencies": {
1237 | "emoji-regex": "^8.0.0",
1238 | "is-fullwidth-code-point": "^3.0.0",
1239 | "strip-ansi": "^6.0.1"
1240 | },
1241 | "engines": {
1242 | "node": ">=8"
1243 | }
1244 | },
1245 | "node_modules/strip-ansi": {
1246 | "version": "6.0.1",
1247 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1248 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1249 | "license": "MIT",
1250 | "dependencies": {
1251 | "ansi-regex": "^5.0.1"
1252 | },
1253 | "engines": {
1254 | "node": ">=8"
1255 | }
1256 | },
1257 | "node_modules/style-search": {
1258 | "version": "0.1.0",
1259 | "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz",
1260 | "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==",
1261 | "license": "ISC"
1262 | },
1263 | "node_modules/stylelint": {
1264 | "version": "16.13.2",
1265 | "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.13.2.tgz",
1266 | "integrity": "sha512-wDlgh0mRO9RtSa3TdidqHd0nOG8MmUyVKl+dxA6C1j8aZRzpNeEgdhFmU5y4sZx4Fc6r46p0fI7p1vR5O2DZqA==",
1267 | "funding": [
1268 | {
1269 | "type": "opencollective",
1270 | "url": "https://opencollective.com/stylelint"
1271 | },
1272 | {
1273 | "type": "github",
1274 | "url": "https://github.com/sponsors/stylelint"
1275 | }
1276 | ],
1277 | "license": "MIT",
1278 | "dependencies": {
1279 | "@csstools/css-parser-algorithms": "^3.0.4",
1280 | "@csstools/css-tokenizer": "^3.0.3",
1281 | "@csstools/media-query-list-parser": "^4.0.2",
1282 | "@csstools/selector-specificity": "^5.0.0",
1283 | "@dual-bundle/import-meta-resolve": "^4.1.0",
1284 | "balanced-match": "^2.0.0",
1285 | "colord": "^2.9.3",
1286 | "cosmiconfig": "^9.0.0",
1287 | "css-functions-list": "^3.2.3",
1288 | "css-tree": "^3.1.0",
1289 | "debug": "^4.3.7",
1290 | "fast-glob": "^3.3.3",
1291 | "fastest-levenshtein": "^1.0.16",
1292 | "file-entry-cache": "^10.0.5",
1293 | "global-modules": "^2.0.0",
1294 | "globby": "^11.1.0",
1295 | "globjoin": "^0.1.4",
1296 | "html-tags": "^3.3.1",
1297 | "ignore": "^7.0.1",
1298 | "imurmurhash": "^0.1.4",
1299 | "is-plain-object": "^5.0.0",
1300 | "known-css-properties": "^0.35.0",
1301 | "mathml-tag-names": "^2.1.3",
1302 | "meow": "^13.2.0",
1303 | "micromatch": "^4.0.8",
1304 | "normalize-path": "^3.0.0",
1305 | "picocolors": "^1.1.1",
1306 | "postcss": "^8.4.49",
1307 | "postcss-resolve-nested-selector": "^0.1.6",
1308 | "postcss-safe-parser": "^7.0.1",
1309 | "postcss-selector-parser": "^7.0.0",
1310 | "postcss-value-parser": "^4.2.0",
1311 | "resolve-from": "^5.0.0",
1312 | "string-width": "^4.2.3",
1313 | "supports-hyperlinks": "^3.1.0",
1314 | "svg-tags": "^1.0.0",
1315 | "table": "^6.9.0",
1316 | "write-file-atomic": "^5.0.1"
1317 | },
1318 | "bin": {
1319 | "stylelint": "bin/stylelint.mjs"
1320 | },
1321 | "engines": {
1322 | "node": ">=18.12.0"
1323 | }
1324 | },
1325 | "node_modules/stylelint-scss": {
1326 | "version": "6.10.0",
1327 | "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.10.0.tgz",
1328 | "integrity": "sha512-y03if6Qw9xBMoVaf7tzp5BbnYhYvudIKzURkhSHzcHG0bW0fAYvQpTUVJOe7DyhHaxeThBil4ObEMvGbV7+M+w==",
1329 | "license": "MIT",
1330 | "dependencies": {
1331 | "css-tree": "^3.0.1",
1332 | "is-plain-object": "^5.0.0",
1333 | "known-css-properties": "^0.35.0",
1334 | "mdn-data": "^2.12.2",
1335 | "postcss-media-query-parser": "^0.2.3",
1336 | "postcss-resolve-nested-selector": "^0.1.6",
1337 | "postcss-selector-parser": "^7.0.0",
1338 | "postcss-value-parser": "^4.2.0"
1339 | },
1340 | "engines": {
1341 | "node": ">=18.12.0"
1342 | },
1343 | "peerDependencies": {
1344 | "stylelint": "^16.0.2"
1345 | }
1346 | },
1347 | "node_modules/stylelint-scss/node_modules/postcss-selector-parser": {
1348 | "version": "7.0.0",
1349 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz",
1350 | "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==",
1351 | "license": "MIT",
1352 | "dependencies": {
1353 | "cssesc": "^3.0.0",
1354 | "util-deprecate": "^1.0.2"
1355 | },
1356 | "engines": {
1357 | "node": ">=4"
1358 | }
1359 | },
1360 | "node_modules/stylelint/node_modules/@csstools/media-query-list-parser": {
1361 | "version": "4.0.2",
1362 | "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz",
1363 | "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==",
1364 | "funding": [
1365 | {
1366 | "type": "github",
1367 | "url": "https://github.com/sponsors/csstools"
1368 | },
1369 | {
1370 | "type": "opencollective",
1371 | "url": "https://opencollective.com/csstools"
1372 | }
1373 | ],
1374 | "license": "MIT",
1375 | "engines": {
1376 | "node": ">=18"
1377 | },
1378 | "peerDependencies": {
1379 | "@csstools/css-parser-algorithms": "^3.0.4",
1380 | "@csstools/css-tokenizer": "^3.0.3"
1381 | }
1382 | },
1383 | "node_modules/stylelint/node_modules/@csstools/selector-specificity": {
1384 | "version": "5.0.0",
1385 | "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz",
1386 | "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==",
1387 | "funding": [
1388 | {
1389 | "type": "github",
1390 | "url": "https://github.com/sponsors/csstools"
1391 | },
1392 | {
1393 | "type": "opencollective",
1394 | "url": "https://opencollective.com/csstools"
1395 | }
1396 | ],
1397 | "license": "MIT-0",
1398 | "engines": {
1399 | "node": ">=18"
1400 | },
1401 | "peerDependencies": {
1402 | "postcss-selector-parser": "^7.0.0"
1403 | }
1404 | },
1405 | "node_modules/stylelint/node_modules/postcss-selector-parser": {
1406 | "version": "7.0.0",
1407 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz",
1408 | "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==",
1409 | "license": "MIT",
1410 | "dependencies": {
1411 | "cssesc": "^3.0.0",
1412 | "util-deprecate": "^1.0.2"
1413 | },
1414 | "engines": {
1415 | "node": ">=4"
1416 | }
1417 | },
1418 | "node_modules/supports-color": {
1419 | "version": "7.2.0",
1420 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1421 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1422 | "license": "MIT",
1423 | "dependencies": {
1424 | "has-flag": "^4.0.0"
1425 | },
1426 | "engines": {
1427 | "node": ">=8"
1428 | }
1429 | },
1430 | "node_modules/supports-hyperlinks": {
1431 | "version": "3.1.0",
1432 | "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz",
1433 | "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==",
1434 | "license": "MIT",
1435 | "dependencies": {
1436 | "has-flag": "^4.0.0",
1437 | "supports-color": "^7.0.0"
1438 | },
1439 | "engines": {
1440 | "node": ">=14.18"
1441 | },
1442 | "funding": {
1443 | "url": "https://github.com/sponsors/sindresorhus"
1444 | }
1445 | },
1446 | "node_modules/svg-tags": {
1447 | "version": "1.0.0",
1448 | "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
1449 | "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA=="
1450 | },
1451 | "node_modules/table": {
1452 | "version": "6.9.0",
1453 | "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz",
1454 | "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==",
1455 | "license": "BSD-3-Clause",
1456 | "dependencies": {
1457 | "ajv": "^8.0.1",
1458 | "lodash.truncate": "^4.4.2",
1459 | "slice-ansi": "^4.0.0",
1460 | "string-width": "^4.2.3",
1461 | "strip-ansi": "^6.0.1"
1462 | },
1463 | "engines": {
1464 | "node": ">=10.0.0"
1465 | }
1466 | },
1467 | "node_modules/to-regex-range": {
1468 | "version": "5.0.1",
1469 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1470 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1471 | "license": "MIT",
1472 | "dependencies": {
1473 | "is-number": "^7.0.0"
1474 | },
1475 | "engines": {
1476 | "node": ">=8.0"
1477 | }
1478 | },
1479 | "node_modules/util-deprecate": {
1480 | "version": "1.0.2",
1481 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1482 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1483 | "license": "MIT"
1484 | },
1485 | "node_modules/which": {
1486 | "version": "1.3.1",
1487 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
1488 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
1489 | "license": "ISC",
1490 | "dependencies": {
1491 | "isexe": "^2.0.0"
1492 | },
1493 | "bin": {
1494 | "which": "bin/which"
1495 | }
1496 | },
1497 | "node_modules/write-file-atomic": {
1498 | "version": "5.0.1",
1499 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
1500 | "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
1501 | "license": "ISC",
1502 | "dependencies": {
1503 | "imurmurhash": "^0.1.4",
1504 | "signal-exit": "^4.0.1"
1505 | },
1506 | "engines": {
1507 | "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
1508 | }
1509 | }
1510 | }
1511 | }
1512 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stylelint-config-sass-guidelines",
3 | "version": "12.1.0",
4 | "description": "Sharable stylelint config based on https://sass-guidelin.es/",
5 | "keywords": [
6 | "stylelint",
7 | "stylelint-config",
8 | "stylelint-scss",
9 | "scss",
10 | "sass",
11 | "guidelines",
12 | "lint",
13 | "linter"
14 | ],
15 | "author": "Brett Jankord",
16 | "license": "MIT",
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/bjankord/stylelint-config-sass-guidelines.git"
20 | },
21 | "homepage": "https://github.com/bjankord/stylelint-config-sass-guidelines#readme",
22 | "bugs": {
23 | "url": "https://github.com/bjankord/stylelint-config-sass-guidelines/issues"
24 | },
25 | "engines": {
26 | "node": ">=18.12.0"
27 | },
28 | "main": "index.js",
29 | "files": [
30 | "index.js"
31 | ],
32 | "dependencies": {
33 | "@stylistic/stylelint-plugin": "^3.0.1",
34 | "postcss-scss": "^4.0.9",
35 | "stylelint-scss": "^6.2.1"
36 | },
37 | "peerDependencies": {
38 | "postcss": "^8.4.21",
39 | "stylelint": "^16.1.0"
40 | },
41 | "devDependencies": {
42 | "postcss": "^8.4.21",
43 | "stylelint": "^16.1.0"
44 | },
45 | "scripts": {
46 | "release:major": "npm test && npm version major -m \"Released version %s\" && npm publish && git push --follow-tags",
47 | "release:minor": "npm test && npm version minor -m \"Released version %s\" && npm publish && git push --follow-tags",
48 | "release:patch": "npm test && npm version patch -m \"Released version %s\" && npm publish && git push --follow-tags",
49 | "test": "node --test"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------