| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 | 'use strict';const atRuleParamIndex = require('../../utils/atRuleParamIndex');const declarationValueIndex = require('../../utils/declarationValueIndex');const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector');const parseSelector = require('../../utils/parseSelector');const report = require('../../utils/report');const ruleMessages = require('../../utils/ruleMessages');const validateOptions = require('../../utils/validateOptions');const valueParser = require('postcss-value-parser');const ruleName = 'string-no-newline';const reNewLine = /\r?\n/;const messages = ruleMessages(ruleName, {	rejected: 'Unexpected newline in string',});const meta = {	url: 'https://stylelint.io/user-guide/rules/string-no-newline',};/** @type {import('stylelint').Rule} */const rule = (primary) => {	return (root, result) => {		const validOptions = validateOptions(result, ruleName, { actual: primary });		if (!validOptions) {			return;		}		root.walk((node) => {			switch (node.type) {				case 'atrule':					checkDeclOrAtRule(node, node.params, atRuleParamIndex);					break;				case 'decl':					checkDeclOrAtRule(node, node.value, declarationValueIndex);					break;				case 'rule':					checkRule(node);					break;			}		});		/**		 * @param {import('postcss').Rule} ruleNode		 * @returns {void}		 */		function checkRule(ruleNode) {			// Get out quickly if there are no new line			if (!reNewLine.test(ruleNode.selector)) {				return;			}			if (!isStandardSyntaxSelector(ruleNode.selector)) {				return;			}			parseSelector(ruleNode.selector, result, ruleNode, (selectorTree) => {				selectorTree.walkAttributes((attributeNode) => {					const { value, quoteMark } = attributeNode;					if (!value || !reNewLine.test(value)) {						return;					}					const openIndex = [						// length of our attribute						attributeNode.attribute,						// length of our operator , ie '='						attributeNode.operator || '',					].reduce(						(index, str) => index + str.length,						// index of the start of our attribute node in our source						// plus 1 for the opening quotation mark						attributeNode.sourceIndex + 1,					);					const valueLength = value.length + (quoteMark || '').length * 2;					report({						message: messages.rejected,						node: ruleNode,						index: openIndex,						endIndex: openIndex + valueLength,						result,						ruleName,					});				});			});		}		/**		 * @template {import('postcss').AtRule | import('postcss').Declaration} T		 * @param {T} node		 * @param {string} value		 * @param {(node: T) => number} getIndex		 * @returns {void}		 */		function checkDeclOrAtRule(node, value, getIndex) {			// Get out quickly if there are no new line			if (!reNewLine.test(value)) {				return;			}			valueParser(value).walk((valueNode) => {				if (valueNode.type !== 'string') {					return;				}				if (!reNewLine.test(valueNode.value)) {					return;				}				const nodeIndex = getIndex(node);				report({					message: messages.rejected,					node,					index: nodeIndex + valueNode.sourceIndex,					endIndex: nodeIndex + valueNode.sourceEndIndex,					result,					ruleName,				});			});		}	};};rule.ruleName = ruleName;rule.messages = messages;rule.meta = meta;module.exports = rule;
 |