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.

index.js 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // @ts-nocheck
  2. 'use strict';
  3. const _ = require('lodash');
  4. const addEmptyLineBefore = require('../../utils/addEmptyLineBefore');
  5. const getPreviousNonSharedLineCommentNode = require('../../utils/getPreviousNonSharedLineCommentNode');
  6. const hasEmptyLine = require('../../utils/hasEmptyLine');
  7. const isAfterComment = require('../../utils/isAfterComment');
  8. const isBlocklessAtRuleAfterBlocklessAtRule = require('../../utils/isBlocklessAtRuleAfterBlocklessAtRule');
  9. const isBlocklessAtRuleAfterSameNameBlocklessAtRule = require('../../utils/isBlocklessAtRuleAfterSameNameBlocklessAtRule');
  10. const isFirstNested = require('../../utils/isFirstNested');
  11. const isFirstNodeOfRoot = require('../../utils/isFirstNodeOfRoot');
  12. const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule');
  13. const optionsMatches = require('../../utils/optionsMatches');
  14. const removeEmptyLinesBefore = require('../../utils/removeEmptyLinesBefore');
  15. const report = require('../../utils/report');
  16. const ruleMessages = require('../../utils/ruleMessages');
  17. const validateOptions = require('../../utils/validateOptions');
  18. const ruleName = 'at-rule-empty-line-before';
  19. const messages = ruleMessages(ruleName, {
  20. expected: 'Expected empty line before at-rule',
  21. rejected: 'Unexpected empty line before at-rule',
  22. });
  23. function rule(expectation, options, context) {
  24. return (root, result) => {
  25. const validOptions = validateOptions(
  26. result,
  27. ruleName,
  28. {
  29. actual: expectation,
  30. possible: ['always', 'never'],
  31. },
  32. {
  33. actual: options,
  34. possible: {
  35. except: [
  36. 'after-same-name',
  37. 'inside-block',
  38. 'blockless-after-same-name-blockless',
  39. 'blockless-after-blockless',
  40. 'first-nested',
  41. ],
  42. ignore: [
  43. 'after-comment',
  44. 'first-nested',
  45. 'inside-block',
  46. 'blockless-after-same-name-blockless',
  47. 'blockless-after-blockless',
  48. ],
  49. ignoreAtRules: [_.isString],
  50. },
  51. optional: true,
  52. },
  53. );
  54. if (!validOptions) {
  55. return;
  56. }
  57. root.walkAtRules((atRule) => {
  58. const isNested = atRule.parent.type !== 'root';
  59. // Ignore the first node
  60. if (isFirstNodeOfRoot(atRule)) {
  61. return;
  62. }
  63. if (!isStandardSyntaxAtRule(atRule)) {
  64. return;
  65. }
  66. // Return early if at-rule is to be ignored
  67. if (optionsMatches(options, 'ignoreAtRules', atRule.name)) {
  68. return;
  69. }
  70. // Optionally ignore the expectation if the node is blockless
  71. if (
  72. optionsMatches(options, 'ignore', 'blockless-after-blockless') &&
  73. isBlocklessAtRuleAfterBlocklessAtRule(atRule)
  74. ) {
  75. return;
  76. }
  77. // Optionally ignore the node if it is the first nested
  78. if (optionsMatches(options, 'ignore', 'first-nested') && isFirstNested(atRule)) {
  79. return;
  80. }
  81. // Optionally ignore the expectation if the node is blockless
  82. // and following another blockless at-rule with the same name
  83. if (
  84. optionsMatches(options, 'ignore', 'blockless-after-same-name-blockless') &&
  85. isBlocklessAtRuleAfterSameNameBlocklessAtRule(atRule)
  86. ) {
  87. return;
  88. }
  89. // Optionally ignore the expectation if the node is inside a block
  90. if (optionsMatches(options, 'ignore', 'inside-block') && isNested) {
  91. return;
  92. }
  93. // Optionally ignore the expectation if a comment precedes this node
  94. if (optionsMatches(options, 'ignore', 'after-comment') && isAfterComment(atRule)) {
  95. return;
  96. }
  97. const hasEmptyLineBefore = hasEmptyLine(atRule.raws.before);
  98. let expectEmptyLineBefore = expectation === 'always';
  99. // Optionally reverse the expectation if any exceptions apply
  100. if (
  101. (optionsMatches(options, 'except', 'after-same-name') &&
  102. isAtRuleAfterSameNameAtRule(atRule)) ||
  103. (optionsMatches(options, 'except', 'inside-block') && isNested) ||
  104. (optionsMatches(options, 'except', 'first-nested') && isFirstNested(atRule)) ||
  105. (optionsMatches(options, 'except', 'blockless-after-blockless') &&
  106. isBlocklessAtRuleAfterBlocklessAtRule(atRule)) ||
  107. (optionsMatches(options, 'except', 'blockless-after-same-name-blockless') &&
  108. isBlocklessAtRuleAfterSameNameBlocklessAtRule(atRule))
  109. ) {
  110. expectEmptyLineBefore = !expectEmptyLineBefore;
  111. }
  112. // Return if the expectation is met
  113. if (expectEmptyLineBefore === hasEmptyLineBefore) {
  114. return;
  115. }
  116. // Fix
  117. if (context.fix) {
  118. if (expectEmptyLineBefore) {
  119. addEmptyLineBefore(atRule, context.newline);
  120. } else {
  121. removeEmptyLinesBefore(atRule, context.newline);
  122. }
  123. return;
  124. }
  125. const message = expectEmptyLineBefore ? messages.expected : messages.rejected;
  126. report({ message, node: atRule, result, ruleName });
  127. });
  128. };
  129. }
  130. function isAtRuleAfterSameNameAtRule(atRule) {
  131. const previousNode = getPreviousNonSharedLineCommentNode(atRule);
  132. return previousNode && previousNode.type === 'atrule' && previousNode.name === atRule.name;
  133. }
  134. rule.ruleName = ruleName;
  135. rule.messages = messages;
  136. module.exports = rule;