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.

validateOptions.js 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. 'use strict';
  2. const _ = require('lodash');
  3. const IGNORED_OPTIONS = new Set(['severity', 'message', 'reportDisables']);
  4. /** @typedef {{possible: any, actual: any, optional?: boolean}} Options */
  5. /**
  6. * Validate a rule's options.
  7. *
  8. * See existing rules for examples.
  9. *
  10. * @param {import('stylelint').PostcssResult} result - postcss result
  11. * @param {string} ruleName
  12. * @param {...Options} optionDescriptions - Each optionDescription can
  13. * have the following properties:
  14. * - `actual` (required): the actual passed option value or object.
  15. * - `possible` (required): a schema representation of what values are
  16. * valid for those options. `possible` should be an object if the
  17. * options are an object, with corresponding keys; if the options are not an
  18. * object, `possible` isn't, either. All `possible` value representations
  19. * should be **arrays of either values or functions**. Values are === checked
  20. * against `actual`. Functions are fed `actual` as an argument and their
  21. * return value is interpreted: truthy = valid, falsy = invalid.
  22. * - `optional` (optional): If this is `true`, `actual` can be undefined.
  23. * @return {boolean} Whether or not the options are valid (true = valid)
  24. */
  25. module.exports = function (result, ruleName, ...optionDescriptions) {
  26. let noErrors = true;
  27. optionDescriptions.forEach((optionDescription) => {
  28. validate(optionDescription, ruleName, complain);
  29. });
  30. /**
  31. * @param {string} message
  32. */
  33. function complain(message) {
  34. noErrors = false;
  35. result.warn(message, {
  36. stylelintType: 'invalidOption',
  37. });
  38. _.set(result, 'stylelint.stylelintError', true);
  39. }
  40. return noErrors;
  41. };
  42. /**
  43. * @param {Options} opts
  44. * @param {string} ruleName
  45. * @param {(s: string) => void} complain
  46. */
  47. function validate(opts, ruleName, complain) {
  48. const possible = opts.possible;
  49. const actual = opts.actual;
  50. const optional = opts.optional;
  51. if (actual === null || _.isEqual(actual, [null])) {
  52. return;
  53. }
  54. const nothingPossible =
  55. possible === undefined || (Array.isArray(possible) && possible.length === 0);
  56. if (nothingPossible && actual === true) {
  57. return;
  58. }
  59. if (actual === undefined) {
  60. if (nothingPossible || optional) {
  61. return;
  62. }
  63. complain(`Expected option value for rule "${ruleName}"`);
  64. return;
  65. }
  66. if (nothingPossible) {
  67. if (optional) {
  68. complain(
  69. `Incorrect configuration for rule "${ruleName}". Rule should have "possible" values for options validation`,
  70. );
  71. return;
  72. }
  73. complain(`Unexpected option value "${String(actual)}" for rule "${ruleName}"`);
  74. return;
  75. }
  76. // If `possible` is a function ...
  77. if (_.isFunction(possible)) {
  78. if (!possible(actual)) {
  79. complain(`Invalid option "${JSON.stringify(actual)}" for rule ${ruleName}`);
  80. }
  81. return;
  82. }
  83. // If `possible` is an array instead of an object ...
  84. if (!_.isPlainObject(possible)) {
  85. [].concat(actual).forEach((a) => {
  86. if (isValid(possible, a)) {
  87. return;
  88. }
  89. complain(`Invalid option value "${String(a)}" for rule "${ruleName}"`);
  90. });
  91. return;
  92. }
  93. // If actual is NOT an object ...
  94. if (typeof actual !== 'object') {
  95. complain(
  96. `Invalid option value ${JSON.stringify(actual)} for rule "${ruleName}": should be an object`,
  97. );
  98. return;
  99. }
  100. Object.keys(actual).forEach((optionName) => {
  101. if (IGNORED_OPTIONS.has(optionName)) {
  102. return;
  103. }
  104. if (!possible[optionName]) {
  105. complain(`Invalid option name "${optionName}" for rule "${ruleName}"`);
  106. return;
  107. }
  108. const actualOptionValue = actual[optionName];
  109. [].concat(actualOptionValue).forEach((a) => {
  110. if (isValid(possible[optionName], a)) {
  111. return;
  112. }
  113. complain(`Invalid value "${a}" for option "${optionName}" of rule "${ruleName}"`);
  114. });
  115. });
  116. }
  117. /**
  118. * @param {any|Function} possible
  119. * @param {any} actual
  120. * @returns {boolean}
  121. */
  122. function isValid(possible, actual) {
  123. const possibleList = /** @type {Array<any|Function>} */ ([]).concat(possible);
  124. for (const possibility of possibleList) {
  125. if (typeof possibility === 'function' && possibility(actual)) {
  126. return true;
  127. }
  128. if (actual === possibility) {
  129. return true;
  130. }
  131. }
  132. return false;
  133. }