eslint-plugin-logical-properties
Version:
80 lines (79 loc) • 3.24 kB
JavaScript
import { MustDisablePropertyError } from '../utils/MustDisablePropertyError.js';
import { stringToTemplate, tokenizeString, } from '../utils/tokenizeString.js';
import { getValidPropertyName } from '../utils/getValidPropertyName.js';
export const generateDirectionalShorthandError = (source, targets) => (`${source} should be replaced with the following properties: \n${targets.map((it) => `- ${it}`).join('\n')}`);
export const expandShorthandOptions = (options, values, isTemplateString = false) => {
const results = [];
for (const [index, value] of Object.entries(values)) {
const localMappings = options[+index];
const localResult = localMappings.map((mapping) => {
const localValue = isTemplateString
? `\`${value}\``
: `${value}`;
return `"${mapping}":${localValue}`;
});
results.push(...localResult);
}
return results;
};
const getPropertyValues = (context, property) => {
const sourceCode = context.sourceCode.getText(property.value);
if (!/^["'`].*["'`]$/.test(sourceCode)) {
return {
isTemplateString: false,
values: [sourceCode],
replacements: [],
};
}
const stringToTokenize = stringToTemplate(sourceCode
.replace(/^["'`]/, '')
.replace(/["'`]$/, ''));
const { output, tokens } = tokenizeString(stringToTokenize);
const values = output.trim().split(/\s+/).filter(Boolean);
return {
isTemplateString: true,
values,
replacements: tokens,
};
};
const applyTokenReplacements = (input, replacements) => {
let output = input;
for (const [target, value] of replacements) {
output = output.replace(target, value);
}
return output;
};
const expandPairMappingOptions = (pairMappings, values, isTemplateString) => {
const [first, second] = values;
return expandShorthandOptions([
[...pairMappings[0]],
[...pairMappings[1]],
], [first, second], isTemplateString);
};
export const directionalShorthandTransformerFactory = ({ node, context, config: { shorthands = {}, shorthandPairMappings = {}, }, }) => (property) => {
const propertyName = getValidPropertyName(property);
const { values, replacements, isTemplateString, } = getPropertyValues(context, property);
if (values.length <= 1) {
return;
}
let results;
if (values.length === 2 && shorthandPairMappings[propertyName]) {
results = expandPairMappingOptions(shorthandPairMappings[propertyName], values, isTemplateString);
}
else {
const options = shorthands[propertyName]?.[values.length - 1];
if (!options) {
throw new MustDisablePropertyError();
}
results = expandShorthandOptions(options, values, isTemplateString);
}
const sourceText = context.sourceCode.getText(property);
const replacedResults = results.map((it) => applyTokenReplacements(it, replacements));
context.report({
node,
message: generateDirectionalShorthandError(sourceText, replacedResults),
fix(fixer) {
return fixer.replaceText(property, replacedResults.join(','));
},
});
};