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.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // @ts-nocheck
  2. 'use strict';
  3. const _ = require('lodash');
  4. const isContextFunctionalPseudoClass = require('../../utils/isContextFunctionalPseudoClass');
  5. const isKeyframeSelector = require('../../utils/isKeyframeSelector');
  6. const isNonNegativeInteger = require('../../utils/isNonNegativeInteger');
  7. const isOnlyWhitespace = require('../../utils/isOnlyWhitespace');
  8. const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
  9. const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector');
  10. const isStandardSyntaxTypeSelector = require('../../utils/isStandardSyntaxTypeSelector');
  11. const optionsMatches = require('../../utils/optionsMatches');
  12. const parseSelector = require('../../utils/parseSelector');
  13. const report = require('../../utils/report');
  14. const resolvedNestedSelector = require('postcss-resolve-nested-selector');
  15. const ruleMessages = require('../../utils/ruleMessages');
  16. const validateOptions = require('../../utils/validateOptions');
  17. const ruleName = 'selector-max-type';
  18. const messages = ruleMessages(ruleName, {
  19. expected: (selector, max) =>
  20. `Expected "${selector}" to have no more than ${max} type ${
  21. max === 1 ? 'selector' : 'selectors'
  22. }`,
  23. });
  24. function rule(max, options) {
  25. return (root, result) => {
  26. const validOptions = validateOptions(
  27. result,
  28. ruleName,
  29. {
  30. actual: max,
  31. possible: isNonNegativeInteger,
  32. },
  33. {
  34. actual: options,
  35. possible: {
  36. ignore: ['descendant', 'child', 'compounded', 'next-sibling'],
  37. ignoreTypes: [_.isString, _.isRegExp],
  38. },
  39. optional: true,
  40. },
  41. );
  42. if (!validOptions) {
  43. return;
  44. }
  45. const ignoreDescendant = optionsMatches(options, 'ignore', 'descendant');
  46. const ignoreChild = optionsMatches(options, 'ignore', 'child');
  47. const ignoreCompounded = optionsMatches(options, 'ignore', 'compounded');
  48. const ignoreNextSibling = optionsMatches(options, 'ignore', 'next-sibling');
  49. function checkSelector(selectorNode, ruleNode) {
  50. const count = selectorNode.reduce((total, childNode) => {
  51. // Only traverse inside actual selectors and context functional pseudo-classes
  52. if (childNode.type === 'selector' || isContextFunctionalPseudoClass(childNode)) {
  53. checkSelector(childNode, ruleNode);
  54. }
  55. if (optionsMatches(options, 'ignoreTypes', childNode.value)) {
  56. return total;
  57. }
  58. if (ignoreDescendant && hasDescendantCombinatorBefore(childNode)) {
  59. return total;
  60. }
  61. if (ignoreChild && hasChildCombinatorBefore(childNode)) {
  62. return total;
  63. }
  64. if (ignoreCompounded && hasCompoundSelector(childNode)) {
  65. return total;
  66. }
  67. if (ignoreNextSibling && hasNextSiblingCombinator(childNode)) {
  68. return total;
  69. }
  70. if (childNode.type === 'tag' && !isStandardSyntaxTypeSelector(childNode)) {
  71. return total;
  72. }
  73. return total + (childNode.type === 'tag');
  74. }, 0);
  75. if (selectorNode.type !== 'root' && selectorNode.type !== 'pseudo' && count > max) {
  76. report({
  77. ruleName,
  78. result,
  79. node: ruleNode,
  80. message: messages.expected(selectorNode, max),
  81. word: selectorNode,
  82. });
  83. }
  84. }
  85. root.walkRules((ruleNode) => {
  86. const selectors = ruleNode.selectors;
  87. if (!isStandardSyntaxRule(ruleNode)) {
  88. return;
  89. }
  90. if (selectors.some((s) => isKeyframeSelector(s))) {
  91. return;
  92. }
  93. ruleNode.selectors.forEach((selector) => {
  94. resolvedNestedSelector(selector, ruleNode).forEach((resolvedSelector) => {
  95. if (!isStandardSyntaxSelector(resolvedSelector)) {
  96. return;
  97. }
  98. parseSelector(resolvedSelector, result, ruleNode, (container) =>
  99. checkSelector(container, ruleNode),
  100. );
  101. });
  102. });
  103. });
  104. };
  105. }
  106. function hasDescendantCombinatorBefore(node) {
  107. const nodeIndex = node.parent.nodes.indexOf(node);
  108. return node.parent.nodes.slice(0, nodeIndex).some(isDescendantCombinator);
  109. }
  110. function hasChildCombinatorBefore(node) {
  111. const nodeIndex = node.parent.nodes.indexOf(node);
  112. return node.parent.nodes.slice(0, nodeIndex).some(isChildCombinator);
  113. }
  114. function hasCompoundSelector(node) {
  115. if (node.prev() && !isCombinator(node.prev())) {
  116. return true;
  117. }
  118. return node.next() && !isCombinator(node.next());
  119. }
  120. function hasNextSiblingCombinator(node) {
  121. return node.prev() && isNextSiblingCombinator(node.prev());
  122. }
  123. function isCombinator(node) {
  124. if (!node) return false;
  125. return _.get(node, 'type') === 'combinator';
  126. }
  127. function isDescendantCombinator(node) {
  128. if (!node) return false;
  129. return isCombinator(node) && isOnlyWhitespace(node.value);
  130. }
  131. function isChildCombinator(node) {
  132. if (!node) return false;
  133. return isCombinator(node) && node.value === '>';
  134. }
  135. function isNextSiblingCombinator(node) {
  136. return isCombinator(node) && node.value === '+';
  137. }
  138. rule.ruleName = ruleName;
  139. rule.messages = messages;
  140. module.exports = rule;