Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rules.md 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. # Working on rules
  2. Please help us create, enhance, and debug our rules!
  3. ## Add a rule
  4. You should:
  5. 1. Get yourself ready to [contribute code](../../CONTRIBUTING.md#code-contributions).
  6. 2. Familiarize yourself with the [conventions and patterns](../user-guide/rules/about.md) for rules.
  7. ### Write the rule
  8. When writing the rule, you should:
  9. - make the rule strict by default
  10. - add secondary `ignore` options to make the rule more permissive
  11. - not include code specific to language extensions, e.g. SCSS
  12. You should make use of the:
  13. - PostCSS API
  14. - construct-specific parsers
  15. - utility functions
  16. #### PostCSS API
  17. Use the [PostCSS API](https://api.postcss.org/) to navigate and analyze the CSS syntax tree. We recommend using the `walk` iterators (e.g. `walkDecls`), rather than using `forEach` to loop through the nodes.
  18. When using array methods on nodes, e.g. `find`, `some`, `filter` etc, you should explicitly check the `type` property of the node before attempting to access other properties. For example:
  19. ```js
  20. const hasProperty = nodes.find(
  21. ({ type, prop }) => type === "decl" && prop === propertyName
  22. );
  23. ```
  24. Use `node.raws` instead of `node.raw()` when accessing raw strings from the [PostCSS AST](https://astexplorer.net/#/gist/ef718daf3e03f1d200b03dc5a550ec60/c8cbe9c6809a85894cebf3fb66de46215c377f1a).
  25. #### Construct-specific parsers
  26. Depending on the rule, we also recommend using:
  27. - [postcss-value-parser](https://github.com/TrySound/postcss-value-parser)
  28. - [postcss-selector-parser](https://github.com/postcss/postcss-selector-parser)
  29. There are significant benefits to using these parsers instead of regular expressions or `indexOf` searches (even if they aren't always the most performant method).
  30. #### Utility functions
  31. stylelint has [utility functions](https://github.com/stylelint/stylelint/tree/master/lib/utils) that are used in existing rules and might prove useful to you, as well. Please look through those so that you know what's available. (And if you have a new function that you think might prove generally helpful, let's add it to the list!).
  32. Use the:
  33. - `validateOptions()` utility to warn users about invalid options
  34. - `isStandardSyntax*` utilities to ignore non-standard syntax
  35. ### Add options
  36. Only add an option to a rule if it addresses a _requested_ use case to avoid polluting the tool with unused features.
  37. If your rule can accept an array as its primary option, you must designate this by setting the property `primaryOptionArray = true` on your rule function. For example:
  38. ```js
  39. function rule(primary, secondary) {
  40. return (root, result) => {
  41. /* .. */
  42. };
  43. }
  44. rule.primaryOptionArray = true;
  45. module.exports = rule;
  46. ```
  47. There is one caveat here: If your rule accepts a primary option array, it cannot also accept a primary option object. Whenever possible, if you want your rule to accept a primary option array, you should make an array the only possibility, instead of allowing for various data structures.
  48. ### Add autofix
  49. Depending on the rule, it might be possible to automatically fix the rule's violations by mutating the PostCSS AST (Abstract Syntax Tree) using the [PostCSS API](http://api.postcss.org/).
  50. Add `context` variable to rule parameters:
  51. ```js
  52. function rule(primary, secondary, context) {
  53. return (root, result) => {
  54. /* .. */
  55. };
  56. }
  57. ```
  58. `context` is an object which could have two properties:
  59. - `fix`(boolean): If `true`, your rule can apply autofixes.
  60. - `newline`(string): Line-ending used in current linted file.
  61. If `context.fix` is `true`, then change `root` using PostCSS API and return early before `report()` is called.
  62. ```js
  63. if (context.fix) {
  64. // Apply fixes using PostCSS API
  65. return; // Return and don't report a problem
  66. }
  67. report(/* .. */);
  68. ```
  69. ### Write tests
  70. Each rule must have tests that cover all patterns that:
  71. - are considered violations
  72. - should _not_ be considered violations
  73. Write as many as you can stand to.
  74. You should:
  75. - test errors in multiple positions, not the same place every time
  76. - use realistic (if simple) CSS, and avoid the use of ellipses
  77. - use standard CSS syntax by default, and only swap parsers when testing a specific piece of non-standard syntax
  78. #### Commonly overlooked edge-cases
  79. You should ask yourself how does your rule handle:
  80. - variables (`$sass`, `@less` or `var(--custom-property)`)?
  81. - CSS strings (e.g. `content: "anything goes";`)?
  82. - CSS comments (e.g. `/* anything goes */`)?
  83. - `url()` functions, including data URIs (e.g. `url(anything/goes.jpg)`)?
  84. - vendor prefixes (e.g. `@-webkit-keyframes name {}`)?
  85. - case sensitivity (e.g. `@KEYFRAMES name {}`)?
  86. - a pseudo-class _combined_ with a pseudo-element (e.g. `a:hover::before`)?
  87. - nesting (e.g. do you resolve `& a {}`, or check it as is?)?
  88. - whitespace and punctuation (e.g. comparing `rgb(0,0,0)` with `rgb(0, 0, 0)`)?
  89. ### Write the README
  90. You should:
  91. - only use standard CSS syntax in example code and options
  92. - use `<!-- prettier-ignore -->` before `css` code fences
  93. - use "this rule" to refer to the rule, e.g. "This rule ignores ..."
  94. - align the arrows within the prototypical code example with the beginning of the highlighted construct
  95. - align the text within the prototypical code example as far to the left as possible
  96. For example:
  97. <!-- prettier-ignore -->
  98. ```css
  99. @media screen and (min-width: 768px) {}
  100. /** ↑ ↑
  101. * These names and values */
  102. ```
  103. When writing examples, you should use:
  104. - complete CSS patterns i.e. avoid ellipses (`...`)
  105. - the minimum amount of code possible to communicate the pattern, e.g. if the rule targets selectors then use an empty rule, e.g. `{}`
  106. - `{}`, rather than `{ }` for empty rules
  107. - the `a` type selector by default
  108. - the `@media` at-rules by default
  109. - the `color` property by default
  110. - _foo_, _bar_ and _baz_ for names, e.g. `.foo`, `#bar`, `--baz`
  111. Look at the READMEs of other rules to glean more conventional patterns.
  112. ### Wire up the rule
  113. The final step is to add references to the new rule in the following places:
  114. - [The rules `index.js` file](../../lib/rules/index.js)
  115. - [The list of rules](../user-guide/rules/list.md)
  116. ## Add an option to a rule
  117. You should:
  118. 1. Get ready to [contribute code](../../CONTRIBUTING.md#code-contributions).
  119. 2. Change the rule's validation to allow for the new option.
  120. 3. Add new unit tests to test the option.
  121. 4. Add (as little as possible) logic to the rule to make the tests pass.
  122. 5. Add documentation about the new option.
  123. ## Fix a bug in a rule
  124. You should:
  125. 1. Get ready to [contribute code](../../CONTRIBUTING.md#code-contributions).
  126. 2. Write failing unit tests that exemplify the bug.
  127. 3. Fiddle with the rule until those new tests pass.
  128. ## Deprecate a rule
  129. Deprecating rules doesn't happen very often. When you do, you must:
  130. 1. Point the `stylelintReference` link to the specific version of the rule README on the GitHub website, so that it is always accessible.
  131. 2. Add the appropriate meta data to mark the rule as deprecated.
  132. ## Improve the performance of a rule
  133. You can run a benchmarks on any given rule with any valid config using:
  134. ```shell
  135. npm run benchmark-rule -- ruleName ruleOptions [ruleContext]
  136. ```
  137. If the `ruleOptions` argument is anything other than a string or a boolean, it must be valid JSON wrapped in quotation marks.
  138. ```shell
  139. npm run benchmark-rule -- selector-combinator-space-after never
  140. ```
  141. ```shell
  142. npm run benchmark-rule -- selector-combinator-space-after always
  143. ```
  144. ```shell
  145. npm run benchmark-rule -- block-opening-brace-space-before "[\"always\", {\"ignoreAtRules\": [\"else\"]}]"
  146. ```
  147. If the `ruleContext` argument is specified, the sames procedure would apply:
  148. ```shell
  149. npm run benchmark-rule -- block-opening-brace-space-before "[\"always\", {\"ignoreAtRules\": [\"else\"]}]" "{\"fix\": \"true\"}"
  150. ```
  151. The script loads Bootstrap's CSS (from its CDN) and runs it through the configured rule.
  152. It will end up printing some simple stats like this:
  153. ```shell
  154. Warnings: 1441
  155. Mean: 74.17598357142856 ms
  156. Deviation: 16.63969674310928 ms
  157. ```
  158. When writing new rules or refactoring existing rules, use these measurements to determine the efficiency of your code.
  159. A stylelint rule can repeat its core logic many, many times (e.g. checking every value node of every declaration in a vast CSS codebase). So it's worth paying attention to performance and doing what we can to improve it!
  160. **Improving the performance of a rule is a great way to contribute if you want a quick little project.** Try picking a rule and seeing if there's anything you can do to speed it up.
  161. Make sure you include benchmark measurements in your pull request!