| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 | 'use strict';const numeric = require('./utils/numeric.js');const {isBigIntLiteral} = require('./ast/index.js');const MESSAGE_ID = 'numeric-separators-style';const messages = {	[MESSAGE_ID]: 'Invalid group length in numeric value.',};function addSeparator(value, {minimumDigits, groupLength}, fromLeft) {	const {length} = value;	if (length < minimumDigits) {		return value;	}	const parts = [];	if (fromLeft) {		for (let start = 0; start < length; start += groupLength) {			const end = Math.min(start + groupLength, length);			parts.push(value.slice(start, end));		}	} else {		for (let end = length; end > 0; end -= groupLength) {			const start = Math.max(end - groupLength, 0);			parts.unshift(value.slice(start, end));		}	}	return parts.join('_');}function addSeparatorFromLeft(value, options) {	return addSeparator(value, options, true);}function formatNumber(value, options) {	const {integer, dot, fractional} = numeric.parseFloatNumber(value);	return addSeparator(integer, options) + dot + addSeparatorFromLeft(fractional, options);}function format(value, {prefix, data}, options) {	const formatOption = options[prefix.toLowerCase()];	if (prefix) {		return prefix + addSeparator(data, formatOption);	}	const {		number,		mark,		sign,		power,	} = numeric.parseNumber(value);	return formatNumber(number, formatOption) + mark + sign + addSeparator(power, options['']);}const defaultOptions = {	binary: {minimumDigits: 0, groupLength: 4},	octal: {minimumDigits: 0, groupLength: 4},	hexadecimal: {minimumDigits: 0, groupLength: 2},	number: {minimumDigits: 5, groupLength: 3},};const create = context => {	const {		onlyIfContainsSeparator,		binary,		octal,		hexadecimal,		number,	} = {		onlyIfContainsSeparator: false,		...context.options[0],	};	const options = {		'0b': {			onlyIfContainsSeparator,			...defaultOptions.binary,			...binary,		},		'0o': {			onlyIfContainsSeparator,			...defaultOptions.octal,			...octal,		},		'0x': {			onlyIfContainsSeparator,			...defaultOptions.hexadecimal,			...hexadecimal,		},		'': {			onlyIfContainsSeparator,			...defaultOptions.number,			...number,		},	};	return {		Literal(node) {			if (!numeric.isNumeric(node) || numeric.isLegacyOctal(node)) {				return;			}			const {raw} = node;			let number = raw;			let suffix = '';			if (isBigIntLiteral(node)) {				number = raw.slice(0, -1);				suffix = 'n';			}			const strippedNumber = number.replace(/_/g, '');			const {prefix, data} = numeric.getPrefix(strippedNumber);			const {onlyIfContainsSeparator} = options[prefix.toLowerCase()];			if (onlyIfContainsSeparator && !raw.includes('_')) {				return;			}			const formatted = format(strippedNumber, {prefix, data}, options) + suffix;			if (raw !== formatted) {				return {					node,					messageId: MESSAGE_ID,					fix: fixer => fixer.replaceText(node, formatted),				};			}		},	};};const formatOptionsSchema = ({minimumDigits, groupLength}) => ({	type: 'object',	additionalProperties: false,	properties: {		onlyIfContainsSeparator: {			type: 'boolean',		},		minimumDigits: {			type: 'integer',			minimum: 0,			default: minimumDigits,		},		groupLength: {			type: 'integer',			minimum: 1,			default: groupLength,		},	},});const schema = [{	type: 'object',	additionalProperties: false,	properties: {		...Object.fromEntries(			Object.entries(defaultOptions).map(([type, options]) => [type, formatOptionsSchema(options)]),		),		onlyIfContainsSeparator: {			type: 'boolean',			default: false,		},	},}];/** @type {import('eslint').Rule.RuleModule} */module.exports = {	create,	meta: {		type: 'suggestion',		docs: {			description: 'Enforce the style of numeric separators by correctly grouping digits.',		},		fixable: 'code',		schema,		messages,	},};
 |