| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 | 'use strict';const debug = require('debug')('stylelint:standalone');const fastGlob = require('fast-glob');const fs = require('fs');const globby = require('globby');const normalizePath = require('normalize-path');const path = require('path');const createStylelint = require('./createStylelint');const createStylelintResult = require('./createStylelintResult');const filterFilePaths = require('./utils/filterFilePaths');const formatters = require('./formatters');const getFileIgnorer = require('./utils/getFileIgnorer');const getFormatterOptionsText = require('./utils/getFormatterOptionsText');const lintSource = require('./lintSource');const NoFilesFoundError = require('./utils/noFilesFoundError');const AllFilesIgnoredError = require('./utils/allFilesIgnoredError');const { assert } = require('./utils/validateTypes');const prepareReturnValue = require('./prepareReturnValue');const ALWAYS_IGNORED_GLOBS = ['**/node_modules/**'];const writeFileAtomic = require('write-file-atomic');/** @typedef {import('stylelint').LinterOptions} LinterOptions *//** @typedef {import('stylelint').LinterResult} LinterResult *//** @typedef {import('stylelint').LintResult} StylelintResult *//** @typedef {import('stylelint').Formatter} Formatter *//** @typedef {import('stylelint').FormatterType} FormatterType *//** * * @param {LinterOptions} options * @returns {Promise<LinterResult>} */async function standalone({	allowEmptyInput = false,	cache: useCache = false,	cacheLocation,	cacheStrategy,	code,	codeFilename,	config,	configBasedir,	configFile,	customSyntax,	cwd = process.cwd(),	disableDefaultIgnores,	files,	fix,	formatter,	globbyOptions,	ignoreDisables,	ignorePath,	ignorePattern,	maxWarnings,	quiet,	reportDescriptionlessDisables,	reportInvalidScopeDisables,	reportNeedlessDisables,	syntax,}) {	const startTime = Date.now();	const isValidCode = typeof code === 'string';	if ((!files && !isValidCode) || (files && (code || isValidCode))) {		return Promise.reject(			new Error('You must pass stylelint a `files` glob or a `code` string, though not both'),		);	}	// The ignorer will be used to filter file paths after the glob is checked,	// before any files are actually read	/** @type {import('ignore').Ignore} */	let ignorer;	try {		ignorer = getFileIgnorer({ cwd, ignorePath, ignorePattern });	} catch (error) {		return Promise.reject(error);	}	/** @type {Formatter} */	let formatterFunction;	try {		formatterFunction = getFormatterFunction(formatter);	} catch (error) {		return Promise.reject(error);	}	const stylelint = createStylelint({		cacheLocation,		cacheStrategy,		config,		configFile,		configBasedir,		cwd,		ignoreDisables,		ignorePath,		reportNeedlessDisables,		reportInvalidScopeDisables,		reportDescriptionlessDisables,		syntax,		customSyntax,		fix,		quiet,	});	if (!files) {		const absoluteCodeFilename =			codeFilename !== undefined && !path.isAbsolute(codeFilename)				? path.join(cwd, codeFilename)				: codeFilename;		// if file is ignored, return nothing		if (			absoluteCodeFilename &&			!filterFilePaths(ignorer, [path.relative(cwd, absoluteCodeFilename)]).length		) {			return prepareReturnValue([], maxWarnings, formatterFunction, cwd);		}		let stylelintResult;		try {			const postcssResult = await lintSource(stylelint, {				code,				codeFilename: absoluteCodeFilename,			});			stylelintResult = await createStylelintResult(stylelint, postcssResult, absoluteCodeFilename);		} catch (error) {			stylelintResult = await handleError(stylelint, error);		}		const postcssResult = stylelintResult._postcssResult;		const returnValue = prepareReturnValue([stylelintResult], maxWarnings, formatterFunction, cwd);		if (			fix &&			postcssResult &&			!postcssResult.stylelint.ignored &&			!postcssResult.stylelint.ruleDisableFix		) {			returnValue.output =				!postcssResult.stylelint.disableWritingFix && postcssResult.opts					? // If we're fixing, the output should be the fixed code					  postcssResult.root.toString(postcssResult.opts.syntax)					: // If the writing of the fix is disabled, the input code is returned as-is					  code;		}		return returnValue;	}	let fileList = [files].flat().map((entry) => {		const globCWD = (globbyOptions && globbyOptions.cwd) || cwd;		const absolutePath = !path.isAbsolute(entry)			? path.join(globCWD, entry)			: path.normalize(entry);		if (fs.existsSync(absolutePath)) {			// This path points to a file. Return an escaped path to avoid globbing			return fastGlob.escapePath(normalizePath(entry));		}		return entry;	});	if (!disableDefaultIgnores) {		fileList = fileList.concat(ALWAYS_IGNORED_GLOBS.map((glob) => `!${glob}`));	}	if (!useCache) {		stylelint._fileCache.destroy();	}	const effectiveGlobbyOptions = {		cwd,		...(globbyOptions || {}),		absolute: true,	};	const globCWD = effectiveGlobbyOptions.cwd;	let filePaths = await globby(fileList, effectiveGlobbyOptions);	// Record the length of filePaths before ignore operation	// Prevent prompting "No files matching the pattern 'xx' were found." when .stylelintignore ignore all input files	const filePathsLengthBeforeIgnore = filePaths.length;	// The ignorer filter needs to check paths relative to cwd	filePaths = filterFilePaths(		ignorer,		filePaths.map((p) => path.relative(globCWD, p)),	);	let stylelintResults;	if (filePaths.length) {		let absoluteFilePaths = filePaths.map((filePath) => {			const absoluteFilepath = !path.isAbsolute(filePath)				? path.join(globCWD, filePath)				: path.normalize(filePath);			return absoluteFilepath;		});		const getStylelintResults = absoluteFilePaths.map(async (absoluteFilepath) => {			debug(`Processing ${absoluteFilepath}`);			try {				const postcssResult = await lintSource(stylelint, {					filePath: absoluteFilepath,					cache: useCache,				});				if (					(postcssResult.stylelint.stylelintError || postcssResult.stylelint.stylelintWarning) &&					useCache				) {					debug(`${absoluteFilepath} contains linting errors and will not be cached.`);					stylelint._fileCache.removeEntry(absoluteFilepath);				}				/**				 * If we're fixing, save the file with changed code				 */				if (					postcssResult.root &&					postcssResult.opts &&					!postcssResult.stylelint.ignored &&					fix &&					!postcssResult.stylelint.disableWritingFix				) {					const fixedCss = postcssResult.root.toString(postcssResult.opts.syntax);					if (						postcssResult.root &&						postcssResult.root.source &&						postcssResult.root.source.input.css !== fixedCss					) {						await writeFileAtomic(absoluteFilepath, fixedCss);					}				}				return createStylelintResult(stylelint, postcssResult, absoluteFilepath);			} catch (error) {				// On any error, we should not cache the lint result				stylelint._fileCache.removeEntry(absoluteFilepath);				return handleError(stylelint, error, absoluteFilepath);			}		});		stylelintResults = await Promise.all(getStylelintResults);	} else if (allowEmptyInput) {		stylelintResults = await Promise.all([]);	} else if (filePathsLengthBeforeIgnore) {		// All input files ignored		stylelintResults = await Promise.reject(new AllFilesIgnoredError());	} else {		stylelintResults = await Promise.reject(new NoFilesFoundError(fileList));	}	if (useCache) {		stylelint._fileCache.reconcile();	}	const result = prepareReturnValue(stylelintResults, maxWarnings, formatterFunction, cwd);	debug(`Linting complete in ${Date.now() - startTime}ms`);	return result;}/** * @param {FormatterType | Formatter | undefined} selected * @returns {Formatter} */function getFormatterFunction(selected) {	if (typeof selected === 'string') {		const formatterFunction = formatters[selected];		if (formatterFunction === undefined) {			throw new Error(				`You must use a valid formatter option: ${getFormatterOptionsText()} or a function`,			);		}		return formatterFunction;	}	if (typeof selected === 'function') {		return selected;	}	assert(formatters.json);	return formatters.json;}/** * @param {import('stylelint').InternalApi} stylelint * @param {any} error * @param {string} [filePath] * @return {Promise<StylelintResult>} */function handleError(stylelint, error, filePath = undefined) {	if (error.name === 'CssSyntaxError') {		return createStylelintResult(stylelint, undefined, filePath, error);	}	throw error;}module.exports = /** @type {typeof import('stylelint').lint} */ (standalone);
 |