import type { File, Store } from './store' import type { BindingMetadata, CompilerOptions, SFCDescriptor, } from 'vue/compiler-sfc' import { type Transform, transform } from 'sucrase' import hashId from 'hash-sum' import { getSourceMap, toVisualizer, trimAnalyzedBindings } from './sourcemap' export const COMP_IDENTIFIER = `__sfc__` const REGEX_JS = /\.[jt]sx?$/ function testTs(filename: string | undefined | null) { return !!(filename && /(\.|\b)tsx?$/.test(filename)) } function testJsx(filename: string | undefined | null) { return !!(filename && /(\.|\b)[jt]sx$/.test(filename)) } function transformTS(src: string, isJSX?: boolean) { return transform(src, { transforms: ['typescript', ...(isJSX ? (['jsx'] as Transform[]) : [])], jsxRuntime: 'preserve', }).code } export async function compileFile( store: Store, { filename, code, compiled }: File, ): Promise<(string | Error)[]> { if (!code.trim()) { return [] } if (filename.endsWith('.css')) { compiled.css = code return [] } if (REGEX_JS.test(filename)) { const isJSX = testJsx(filename) if (testTs(filename)) { code = transformTS(code, isJSX) } if (isJSX) { code = await import('./jsx').then(({ transformJSX }) => transformJSX(code), ) } compiled.js = compiled.ssr = code return [] } if (filename.endsWith('.json')) { let parsed try { parsed = JSON.parse(code) } catch (err: any) { console.error(`Error parsing ${filename}`, err.message) return [err.message] } compiled.js = compiled.ssr = `export default ${JSON.stringify(parsed)}` return [] } if (!filename.endsWith('.vue')) { return [] } const id = hashId(filename) const { errors, descriptor } = store.compiler.parse(code, { filename, sourceMap: true, templateParseOptions: store.sfcOptions?.template?.compilerOptions, }) if (errors.length) { return errors } const styleLangs = descriptor.styles.map((s) => s.lang).filter(Boolean) const templateLang = descriptor.template?.lang if (styleLangs.length && templateLang) { return [ `lang="${styleLangs.join( ',', )}" pre-processors for