lintSource.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. 'use strict';
  2. const isPathNotFoundError = require('./utils/isPathNotFoundError');
  3. const lintPostcssResult = require('./lintPostcssResult');
  4. const path = require('path');
  5. /** @typedef {import('stylelint').InternalApi} StylelintInternalApi */
  6. /** @typedef {import('stylelint').GetLintSourceOptions} Options */
  7. /** @typedef {import('postcss').Result} Result */
  8. /** @typedef {import('stylelint').PostcssResult} PostcssResult */
  9. /** @typedef {import('stylelint').StylelintPostcssResult} StylelintPostcssResult */
  10. /**
  11. * Run stylelint on a PostCSS Result, either one that is provided
  12. * or one that we create
  13. * @param {StylelintInternalApi} stylelint
  14. * @param {Options} options
  15. * @returns {Promise<PostcssResult>}
  16. */
  17. module.exports = async function lintSource(stylelint, options = {}) {
  18. if (!options.filePath && options.code === undefined && !options.existingPostcssResult) {
  19. return Promise.reject(new Error('You must provide filePath, code, or existingPostcssResult'));
  20. }
  21. const isCodeNotFile = options.code !== undefined;
  22. const inputFilePath = isCodeNotFile ? options.codeFilename : options.filePath;
  23. if (inputFilePath !== undefined && !path.isAbsolute(inputFilePath)) {
  24. if (isCodeNotFile) {
  25. return Promise.reject(new Error('codeFilename must be an absolute path'));
  26. }
  27. return Promise.reject(new Error('filePath must be an absolute path'));
  28. }
  29. const isIgnored = await stylelint.isPathIgnored(inputFilePath).catch((err) => {
  30. if (isCodeNotFile && isPathNotFoundError(err)) return false;
  31. throw err;
  32. });
  33. if (isIgnored) {
  34. return options.existingPostcssResult
  35. ? Object.assign(options.existingPostcssResult, {
  36. stylelint: createEmptyStylelintPostcssResult(),
  37. })
  38. : createEmptyPostcssResult(inputFilePath);
  39. }
  40. const configSearchPath = stylelint._options.configFile || inputFilePath;
  41. const cwd = stylelint._options.cwd;
  42. const configForFile = await stylelint
  43. .getConfigForFile(configSearchPath, inputFilePath)
  44. .catch((err) => {
  45. if (isCodeNotFile && isPathNotFoundError(err)) return stylelint.getConfigForFile(cwd);
  46. throw err;
  47. });
  48. if (!configForFile) {
  49. return Promise.reject(new Error('Config file not found'));
  50. }
  51. const config = configForFile.config;
  52. const existingPostcssResult = options.existingPostcssResult;
  53. /** @type {StylelintPostcssResult} */
  54. const stylelintResult = {
  55. ruleSeverities: {},
  56. customMessages: {},
  57. ruleMetadata: {},
  58. disabledRanges: {},
  59. };
  60. const postcssResult =
  61. existingPostcssResult ||
  62. (await stylelint._getPostcssResult({
  63. code: options.code,
  64. codeFilename: options.codeFilename,
  65. filePath: inputFilePath,
  66. codeProcessors: config.codeProcessors,
  67. customSyntax: config.customSyntax,
  68. }));
  69. const stylelintPostcssResult = Object.assign(postcssResult, {
  70. stylelint: stylelintResult,
  71. });
  72. await lintPostcssResult(stylelint._options, stylelintPostcssResult, config);
  73. return stylelintPostcssResult;
  74. };
  75. /**
  76. * @returns {StylelintPostcssResult}
  77. */
  78. function createEmptyStylelintPostcssResult() {
  79. return {
  80. ruleSeverities: {},
  81. customMessages: {},
  82. ruleMetadata: {},
  83. disabledRanges: {},
  84. ignored: true,
  85. stylelintError: false,
  86. };
  87. }
  88. /**
  89. * @param {string} [filePath]
  90. * @returns {PostcssResult}
  91. */
  92. function createEmptyPostcssResult(filePath) {
  93. return {
  94. root: {
  95. source: {
  96. input: { file: filePath },
  97. },
  98. },
  99. messages: [],
  100. opts: undefined,
  101. stylelint: createEmptyStylelintPostcssResult(),
  102. warn: () => {},
  103. };
  104. }