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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // @ts-nocheck
  2. 'use strict';
  3. const _ = require('lodash');
  4. const findAtRuleContext = require('../../utils/findAtRuleContext');
  5. const isKeyframeRule = require('../../utils/isKeyframeRule');
  6. const nodeContextLookup = require('../../utils/nodeContextLookup');
  7. const normalizeSelector = require('normalize-selector');
  8. const parseSelector = require('../../utils/parseSelector');
  9. const report = require('../../utils/report');
  10. const resolvedNestedSelector = require('postcss-resolve-nested-selector');
  11. const ruleMessages = require('../../utils/ruleMessages');
  12. const validateOptions = require('../../utils/validateOptions');
  13. const ruleName = 'no-duplicate-selectors';
  14. const messages = ruleMessages(ruleName, {
  15. rejected: (selector, firstDuplicateLine) =>
  16. `Unexpected duplicate selector "${selector}", first used at line ${firstDuplicateLine}`,
  17. });
  18. function rule(actual, options) {
  19. return (root, result) => {
  20. const validOptions = validateOptions(
  21. result,
  22. ruleName,
  23. { actual },
  24. {
  25. actual: options,
  26. possible: {
  27. disallowInList: _.isBoolean,
  28. },
  29. optional: true,
  30. },
  31. );
  32. if (!validOptions) {
  33. return;
  34. }
  35. const shouldDisallowDuplicateInList = _.get(options, 'disallowInList');
  36. // The top level of this map will be rule sources.
  37. // Each source maps to another map, which maps rule parents to a set of selectors.
  38. // This ensures that selectors are only checked against selectors
  39. // from other rules that share the same parent and the same source.
  40. const selectorContextLookup = nodeContextLookup();
  41. root.walkRules((ruleNode) => {
  42. if (isKeyframeRule(ruleNode)) {
  43. return;
  44. }
  45. const contextSelectorSet = selectorContextLookup.getContext(
  46. ruleNode,
  47. findAtRuleContext(ruleNode),
  48. );
  49. const resolvedSelectors = ruleNode.selectors.reduce((selectors, selector) => {
  50. return _.union(selectors, resolvedNestedSelector(selector, ruleNode));
  51. }, []);
  52. const normalizedSelectorList = resolvedSelectors.map(normalizeSelector);
  53. // Sort the selectors list so that the order of the constituents
  54. // doesn't matter
  55. const sortedSelectorList = normalizedSelectorList.slice().sort().join(',');
  56. const selectorLine = ruleNode.source.start.line;
  57. // Complain if the same selector list occurs twice
  58. let previousDuplicatePosition;
  59. // When `disallowInList` is true, we must parse `sortedSelectorList` into
  60. // list items.
  61. const selectorListParsed = [];
  62. if (shouldDisallowDuplicateInList) {
  63. parseSelector(sortedSelectorList, result, ruleNode, (selectors) => {
  64. selectors.each((s) => {
  65. const selector = String(s);
  66. selectorListParsed.push(selector);
  67. if (contextSelectorSet.get(selector)) {
  68. previousDuplicatePosition = contextSelectorSet.get(selector);
  69. }
  70. });
  71. });
  72. } else {
  73. previousDuplicatePosition = contextSelectorSet.get(sortedSelectorList);
  74. }
  75. if (previousDuplicatePosition) {
  76. // If the selector isn't nested we can use its raw value; otherwise,
  77. // we have to approximate something for the message -- which is close enough
  78. const isNestedSelector = resolvedSelectors.join(',') !== ruleNode.selectors.join(',');
  79. const selectorForMessage = isNestedSelector
  80. ? resolvedSelectors.join(', ')
  81. : ruleNode.selector;
  82. return report({
  83. result,
  84. ruleName,
  85. node: ruleNode,
  86. message: messages.rejected(selectorForMessage, previousDuplicatePosition),
  87. });
  88. }
  89. const presentedSelectors = new Set();
  90. const reportedSelectors = new Set();
  91. // Or complain if one selector list contains the same selector more than once
  92. ruleNode.selectors.forEach((selector) => {
  93. const normalized = normalizeSelector(selector);
  94. if (presentedSelectors.has(normalized)) {
  95. if (reportedSelectors.has(normalized)) {
  96. return;
  97. }
  98. report({
  99. result,
  100. ruleName,
  101. node: ruleNode,
  102. message: messages.rejected(selector, selectorLine),
  103. });
  104. reportedSelectors.add(normalized);
  105. } else {
  106. presentedSelectors.add(normalized);
  107. }
  108. });
  109. if (shouldDisallowDuplicateInList) {
  110. for (const selector of selectorListParsed) {
  111. // [selectorLine] will not really be accurate for multi-line
  112. // selectors, such as "bar" in "foo,\nbar {}".
  113. contextSelectorSet.set(selector, selectorLine);
  114. }
  115. } else {
  116. contextSelectorSet.set(sortedSelectorList, selectorLine);
  117. }
  118. });
  119. };
  120. }
  121. rule.ruleName = ruleName;
  122. rule.messages = messages;
  123. module.exports = rule;