@ianvs/prettier-plugin-sort-imports
Version:
A prettier plugins to sort imports in provided RegEx order
84 lines (83 loc) • 3.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.vuePreprocessor = vuePreprocessor;
const get_experimental_parser_plugins_1 = require("../utils/get-experimental-parser-plugins");
const preprocessor_1 = require("./preprocessor");
function vuePreprocessor(code, options) {
try {
const { parse } = require('@vue/compiler-sfc');
const version = require('@vue/compiler-sfc/package.json').version?.split('.')[0];
const descriptor = version === '2' ? parse({ source: code }) : parse(code).descriptor;
// 1. Filter valid blocks.
const blocks = [descriptor.script, descriptor.scriptSetup].filter((block) => Boolean(block?.content));
if (!blocks.length) {
return code;
}
// 2. Sort blocks by start offset.
blocks.sort((a, b) => a.loc.start.offset - b.loc.start.offset);
// 3. Replace blocks.
// Using offsets to avoid string replace catching the wrong place and improve efficiency
// see https://github.com/IanVS/prettier-plugin-sort-imports/pull/90
let offset = 0;
let result = '';
for (const block of blocks) {
// https://github.com/vuejs/core/blob/b8fc18c0b23be9a77b05dc41ed452a87a0becf82/packages/compiler-core/src/ast.ts#L74-L80
// The node's range. The `start` is inclusive and `end` is exclusive.
// [start, end)
// @ts-expect-error Some vue versions have a `block.loc`, others have start and end directly on the block
let { start, end } = block;
if ('loc' in block) {
start = block.loc.start.offset;
end = block.loc.end.offset;
}
const preprocessedBlockCode = sortScript(block, options);
result += code.slice(offset, start) + preprocessedBlockCode;
offset = end;
}
// 4. Append the rest.
result += code.slice(offset);
return result;
}
catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
console.warn('[@ianvs/prettier-plugin-sort-imports]: Could not process .vue file. Please be sure that "@vue/compiler-sfc" is installed in your project.');
}
throw err;
}
}
function isTS(lang) {
return lang === 'ts' || lang === 'tsx';
}
/**
* Configures correct babel plugins, sorts imports in a script or setupScript,
* and replaces that script/setupScript within the original code
*
* Much of this was adapted from https://github.com/vuejs/vue/blob/49b6bd4264c25ea41408f066a1835f38bf6fe9f1/packages/compiler-sfc/src/compileScript.ts#L118-L134
*
* @param param0 A script or setupScript block of the SFC
* @param options Prettier options
* @returns Original code with sorted imports in the block provided
*/
function sortScript({ content, lang }, options) {
const { importOrderParserPlugins = [] } = options;
let pluginClone = [...importOrderParserPlugins];
const newPlugins = [];
if (!isTS(lang) || lang === 'tsx') {
newPlugins.push('jsx');
}
else {
// Remove jsx if typescript and not tsx
pluginClone = pluginClone.filter((p) => p !== 'jsx');
}
newPlugins.push(...pluginClone);
if (isTS(lang)) {
if (!(0, get_experimental_parser_plugins_1.hasPlugin)(newPlugins, 'typescript')) {
newPlugins.push('typescript');
}
}
const adjustedOptions = {
...options,
importOrderParserPlugins: newPlugins,
};
return `\n${(0, preprocessor_1.preprocessor)(content, { options: adjustedOptions })}\n`;
}