getPostcssResult.cjs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // NOTICE: This file is generated by Rollup. To modify it,
  2. // please instead edit the ESM counterpart and rebuild with Rollup (npm run build).
  3. 'use strict';
  4. const promises = require('node:fs/promises');
  5. const postcss = require('postcss');
  6. const dynamicImport = require('./utils/dynamicImport.cjs');
  7. const getModulePath = require('./utils/getModulePath.cjs');
  8. const normalizeFixMode = require('./utils/normalizeFixMode.cjs');
  9. /** @import {Result, Syntax} from 'postcss' */
  10. /** @import {CustomSyntax, GetPostcssOptions, InternalApi as StylelintInternalApi} from 'stylelint' */
  11. const postcssProcessor = postcss();
  12. /**
  13. * @param {StylelintInternalApi} stylelint
  14. * @param {GetPostcssOptions} options
  15. *
  16. * @returns {Promise<Result>}
  17. */
  18. async function getPostcssResult(stylelint, { customSyntax, filePath, code } = {}) {
  19. const cached = filePath ? stylelint._postcssResultCache.get(filePath) : undefined;
  20. if (cached) {
  21. return cached;
  22. }
  23. const fix = normalizeFixMode(stylelint._options.fix);
  24. const syntax = await (customSyntax
  25. ? getCustomSyntax(customSyntax, stylelint._options.configBasedir)
  26. : cssSyntax(fix === 'lax'));
  27. const postcssOptions = {
  28. from: filePath,
  29. syntax,
  30. };
  31. /** @type {string | undefined} */
  32. let getCode;
  33. if (code !== undefined) {
  34. getCode = code;
  35. } else if (filePath) {
  36. getCode = await promises.readFile(filePath, 'utf8');
  37. }
  38. if (getCode === undefined) {
  39. throw new Error('code or filePath required');
  40. }
  41. const postcssResult = await postcssProcessor.process(getCode, postcssOptions).async();
  42. if (filePath) {
  43. stylelint._postcssResultCache.set(filePath, postcssResult);
  44. }
  45. return postcssResult;
  46. }
  47. /**
  48. * @param {CustomSyntax} customSyntax
  49. * @param {string | undefined} basedir
  50. * @returns {Promise<Syntax>}
  51. */
  52. async function getCustomSyntax(customSyntax, basedir) {
  53. if (typeof customSyntax === 'string') {
  54. const customSyntaxLookup = basedir ? getModulePath(basedir, customSyntax) : customSyntax;
  55. let resolved;
  56. try {
  57. resolved = await dynamicImport(customSyntaxLookup);
  58. resolved = resolved.default ?? resolved;
  59. } catch (error) {
  60. if (
  61. error &&
  62. typeof error === 'object' &&
  63. 'code' in error &&
  64. // TODO: Remove 'MODULE_NOT_FOUND' when we drop the CommonJS support.
  65. // See https://nodejs.org/api/errors.html#module_not_found
  66. (error.code === 'MODULE_NOT_FOUND' || error.code === 'ERR_MODULE_NOT_FOUND') &&
  67. 'message' in error &&
  68. typeof error.message === 'string' &&
  69. error.message.includes(customSyntax)
  70. ) {
  71. throw new Error(
  72. `Cannot resolve custom syntax module "${customSyntax}". Check that module "${customSyntax}" is available and spelled correctly.\n\nCaused by: ${error}`,
  73. );
  74. }
  75. throw error;
  76. }
  77. /*
  78. * PostCSS allows for syntaxes that only contain a parser, however,
  79. * it then expects the syntax to be set as the `parse` option.
  80. */
  81. if (!resolved.parse) {
  82. resolved = {
  83. parse: resolved,
  84. stringify: postcss.stringify,
  85. };
  86. }
  87. return resolved;
  88. }
  89. if (typeof customSyntax === 'object') {
  90. if (typeof customSyntax.parse === 'function') {
  91. return { ...customSyntax };
  92. }
  93. throw new TypeError(
  94. 'An object provided to the "customSyntax" option must have a "parse" property. Ensure the "parse" property exists and its value is a function.',
  95. );
  96. }
  97. throw new Error('Custom syntax must be a string or a Syntax object');
  98. }
  99. /**
  100. * @param {boolean} fix
  101. * @returns {Promise<Syntax>}
  102. */
  103. async function cssSyntax(fix) {
  104. const parse = await (fix ? import('postcss-safe-parser').then((m) => m.default) : postcss.parse);
  105. return { parse, stringify: postcss.stringify };
  106. }
  107. module.exports = getPostcssResult;