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`] = ` + + + +