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.

getPostcssResult.js 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. 'use strict';
  2. const fs = require('fs');
  3. const LazyResult = require('postcss/lib/lazy-result');
  4. const postcss = require('postcss');
  5. const syntaxes = require('./syntaxes');
  6. /** @typedef {import('postcss').Result} Result */
  7. /** @typedef {import('postcss').Syntax} Syntax */
  8. /** @typedef {import('stylelint').CustomSyntax} CustomSyntax */
  9. /** @typedef {import('stylelint').GetPostcssOptions} GetPostcssOptions */
  10. /** @typedef {import('stylelint').StylelintInternalApi} StylelintInternalApi */
  11. const postcssProcessor = postcss();
  12. /**
  13. * @param {StylelintInternalApi} stylelint
  14. * @param {GetPostcssOptions} options
  15. *
  16. * @returns {Promise<Result>}
  17. */
  18. module.exports = function (stylelint, options = {}) {
  19. const cached = options.filePath ? stylelint._postcssResultCache.get(options.filePath) : undefined;
  20. if (cached) return Promise.resolve(cached);
  21. /** @type {Promise<string> | undefined} */
  22. let getCode;
  23. if (options.code !== undefined) {
  24. getCode = Promise.resolve(options.code);
  25. } else if (options.filePath) {
  26. getCode = readFile(options.filePath);
  27. }
  28. if (!getCode) {
  29. throw new Error('code or filePath required');
  30. }
  31. return getCode
  32. .then((code) => {
  33. /** @type {Syntax | null} */
  34. let syntax = null;
  35. if (stylelint._options.customSyntax) {
  36. syntax = getCustomSyntax(stylelint._options.customSyntax);
  37. } else if (stylelint._options.syntax) {
  38. if (stylelint._options.syntax === 'css') {
  39. syntax = cssSyntax(stylelint);
  40. } else {
  41. const keys = Object.keys(syntaxes);
  42. if (!keys.includes(stylelint._options.syntax)) {
  43. throw new Error(
  44. `You must use a valid syntax option, either: css, ${keys
  45. .slice(0, -1)
  46. .join(', ')} or ${keys.slice(-1)}`,
  47. );
  48. }
  49. syntax = syntaxes[stylelint._options.syntax];
  50. }
  51. } else if (!(options.codeProcessors && options.codeProcessors.length)) {
  52. const autoSyntax = require('postcss-syntax');
  53. // TODO: investigate why lazy import HTML syntax causes
  54. // JS files with the word "html" to throw TypeError
  55. // https://github.com/stylelint/stylelint/issues/4793
  56. const { html, ...rest } = syntaxes;
  57. syntax = autoSyntax({
  58. css: cssSyntax(stylelint),
  59. jsx: syntaxes['css-in-js'],
  60. ...rest,
  61. });
  62. }
  63. const postcssOptions = {
  64. from: options.filePath,
  65. syntax,
  66. };
  67. const source = options.code ? options.codeFilename : options.filePath;
  68. let preProcessedCode = code;
  69. if (options.codeProcessors && options.codeProcessors.length) {
  70. if (stylelint._options.fix) {
  71. console.warn(
  72. 'Autofix is incompatible with processors and will be disabled. Are you sure you need a processor?',
  73. );
  74. stylelint._options.fix = false;
  75. }
  76. options.codeProcessors.forEach((codeProcessor) => {
  77. preProcessedCode = codeProcessor(preProcessedCode, source);
  78. });
  79. }
  80. const result = new LazyResult(postcssProcessor, preProcessedCode, postcssOptions);
  81. return result;
  82. })
  83. .then((postcssResult) => {
  84. if (options.filePath) {
  85. stylelint._postcssResultCache.set(options.filePath, postcssResult);
  86. }
  87. return postcssResult;
  88. });
  89. };
  90. /**
  91. * @param {CustomSyntax} customSyntax
  92. * @returns {Syntax}
  93. */
  94. function getCustomSyntax(customSyntax) {
  95. let resolved;
  96. if (typeof customSyntax === 'string') {
  97. try {
  98. resolved = require(customSyntax);
  99. } catch {
  100. throw new Error(
  101. `Cannot resolve custom syntax module ${customSyntax}. Check that module ${customSyntax} is available and spelled correctly.`,
  102. );
  103. }
  104. /*
  105. * PostCSS allows for syntaxes that only contain a parser, however,
  106. * it then expects the syntax to be set as the `parse` option.
  107. */
  108. if (!resolved.parse) {
  109. resolved = {
  110. parse: resolved,
  111. stringify: postcss.stringify,
  112. };
  113. }
  114. return resolved;
  115. }
  116. if (typeof customSyntax === 'object') {
  117. if (typeof customSyntax.parse === 'function') {
  118. resolved = { ...customSyntax };
  119. } else {
  120. throw new TypeError(
  121. `An object provided to the "customSyntax" option must have a "parse" property. Ensure the "parse" property exists and its value is a function.`,
  122. );
  123. }
  124. return resolved;
  125. }
  126. throw new Error(`Custom syntax must be a string or a Syntax object`);
  127. }
  128. /**
  129. * @param {string} filePath
  130. * @returns {Promise<string>}
  131. */
  132. function readFile(filePath) {
  133. return new Promise((resolve, reject) => {
  134. fs.readFile(filePath, 'utf8', (err, content) => {
  135. if (err) {
  136. return reject(err);
  137. }
  138. resolve(content);
  139. });
  140. });
  141. }
  142. /**
  143. * @param {StylelintInternalApi} stylelint
  144. * @returns {Syntax}
  145. */
  146. function cssSyntax(stylelint) {
  147. return {
  148. parse: stylelint._options.fix ? require('postcss-safe-parser') : postcss.parse,
  149. stringify: postcss.stringify,
  150. };
  151. }