diff --git a/src/preprocessors/vue-preprocessor.ts b/src/preprocessors/vue-preprocessor.ts
index b29bbc44..e79dfeb3 100644
--- a/src/preprocessors/vue-preprocessor.ts
+++ b/src/preprocessors/vue-preprocessor.ts
@@ -1,14 +1,39 @@
+import type { SFCBlock, SFCDescriptor } from '@vue/compiler-sfc';
+
import { PrettierOptions } from '../types';
import { preprocessor } from './preprocessor';
export function vuePreprocessor(code: string, options: PrettierOptions) {
const { parse } = require('@vue/compiler-sfc');
- const { descriptor } = parse(code);
+ const descriptor: SFCDescriptor = parse(code).descriptor;
- const content = (descriptor.script ?? descriptor.scriptSetup)?.content;
- if (!content) {
+ // 1. filter valid blocks
+ const blocks = [descriptor.script, descriptor.scriptSetup].filter(
+ (block) => block?.content,
+ ) as SFCBlock[];
+ if (!blocks.length) {
return code;
}
- return code.replace(content, `\n${preprocessor(content, options)}\n`);
+ // 2. sort blocks by start position
+ 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
+ let offset = 0;
+ let result = '';
+ for (const block of blocks) {
+ // https://github.com/vuejs/core/blob/9060bf0353e88cc1f4cf06981b9799c5c1e09466/packages/compiler-core/src/ast.ts#L71
+ // The node's range. The `start` is inclusive and `end` is exclusive.
+ // [start, end)
+ const { start, end } = block.loc;
+ const transformed = `\n${preprocessor(block.content, options)}\n`;
+ result += code.slice(offset, start.offset) + transformed;
+ offset = end.offset;
+ }
+
+ // 4. append the rest
+ result += code.slice(offset);
+
+ return result;
}
diff --git a/tests/Vue/__snapshots__/ppsi.spec.js.snap b/tests/Vue/__snapshots__/ppsi.spec.js.snap
index 065c444f..3c1106f3 100644
--- a/tests/Vue/__snapshots__/ppsi.spec.js.snap
+++ b/tests/Vue/__snapshots__/ppsi.spec.js.snap
@@ -57,6 +57,115 @@ function add(a, b) {
`;
+exports[`setupWithScript.vue - vue-verify: setupWithScript.vue 1`] = `
+
+
+
+
+
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+
+
+
+
+
+
+`;
+
exports[`sfc.vue - vue-verify: sfc.vue 1`] = `
+
+
+
+
+
+