diff --git a/extensions/vscode-vue-language-features/schemas/vue-tsconfig.schema.json b/extensions/vscode-vue-language-features/schemas/vue-tsconfig.schema.json index de9d83169..02e383623 100644 --- a/extensions/vscode-vue-language-features/schemas/vue-tsconfig.schema.json +++ b/extensions/vscode-vue-language-features/schemas/vue-tsconfig.schema.json @@ -16,6 +16,10 @@ ], "markdownDescription": "https://github.com/johnsoncodehk/volar/pull/351" }, + "experimentalShamefullySupportOptionsApi": { + "type": "boolean", + "markdownDescription": "Support intellisense compoonents that export options without `Vue.extend` and `defineComponent`. This is essentially a hack and not recommended to use it." + }, "experimentalTemplateCompilerOptions": { "type": "object", "markdownDescription": "https://github.com/johnsoncodehk/volar/issues/576" diff --git a/packages/vue-code-gen/src/generators/script.ts b/packages/vue-code-gen/src/generators/script.ts index 56c2e828c..2e4a2b15c 100644 --- a/packages/vue-code-gen/src/generators/script.ts +++ b/packages/vue-code-gen/src/generators/script.ts @@ -22,6 +22,7 @@ export function generate( getHtmlGen: () => ReturnType | undefined, getStyleBindTexts: () => string[], vueLibName: string, + shimComponentOptions: boolean, ) { const codeGen = new CodeGen(); @@ -166,7 +167,20 @@ export function generate( addVirtualCode('script', scriptRanges.exportDefault.end, script.content.length); } else { - addVirtualCode('script', 0, script.content.length); + let isExportRawObject = false; + if (scriptRanges?.exportDefault) { + isExportRawObject = script.content.substring(scriptRanges.exportDefault.expression.start, scriptRanges.exportDefault.expression.end).startsWith('{'); + } + if (isExportRawObject && shimComponentOptions && scriptRanges?.exportDefault) { + addVirtualCode('script', 0, scriptRanges.exportDefault.expression.start); + codeGen.addText(`(await import('${vueLibName}')).defineComponent(`); + addVirtualCode('script', scriptRanges.exportDefault.expression.start, scriptRanges.exportDefault.expression.end); + codeGen.addText(`)`); + addVirtualCode('script', scriptRanges.exportDefault.expression.end, script.content.length); + } + else { + addVirtualCode('script', 0, script.content.length); + } } } function addVirtualCode(vueTag: 'script' | 'scriptSetup', start: number, end: number) { diff --git a/packages/vue-code-gen/src/index.ts b/packages/vue-code-gen/src/index.ts index 603d785f1..0a792d4bd 100644 --- a/packages/vue-code-gen/src/index.ts +++ b/packages/vue-code-gen/src/index.ts @@ -18,6 +18,7 @@ export function generateSFCScriptTypeCheckCode( scriptLang: 'js' | 'jsx' | 'ts' | 'tsx', scriptCode: string | undefined, scriptSetupCode: string | undefined, + shimComponentOptions: boolean, templateAst?: CompilerDOM.RootNode, cssVars?: string[], vueLibName = 'vue', @@ -43,6 +44,7 @@ export function generateSFCScriptTypeCheckCode( // () => templateAst ? generateTemplateScript(templateAst) : undefined, () => cssVars ?? [], vueLibName, + shimComponentOptions, ); return { diff --git a/packages/vue-typescript/src/types.ts b/packages/vue-typescript/src/types.ts index 927bd1751..f56c48774 100644 --- a/packages/vue-typescript/src/types.ts +++ b/packages/vue-typescript/src/types.ts @@ -13,6 +13,7 @@ export interface ITemplateScriptData { export interface VueCompilerOptions { experimentalCompatMode?: 2 | 3; + experimentalShamefullySupportOptionsApi?: boolean; experimentalTemplateCompilerOptions?: any; experimentalTemplateCompilerOptionsRequirePath?: string; experimentalDisableTemplateSupport?: boolean; diff --git a/packages/vue-typescript/src/use/useSfcScriptGen.ts b/packages/vue-typescript/src/use/useSfcScriptGen.ts index c1b8a7f2f..e25c3522c 100644 --- a/packages/vue-typescript/src/use/useSfcScriptGen.ts +++ b/packages/vue-typescript/src/use/useSfcScriptGen.ts @@ -8,6 +8,7 @@ import type { parseScriptSetupRanges } from '@volar/vue-code-gen/out/parsers/scr import { getVueLibraryName } from '../utils/localTypes'; import type { EmbeddedFileMappingData, TextRange } from '@volar/vue-code-gen'; import { Embedded, EmbeddedFile, Sfc } from '../vueFile'; +import { VueCompilerOptions } from '../types'; export function useSfcScriptGen( lsType: T, @@ -20,7 +21,7 @@ export function useSfcScriptGen( scriptSetupRanges: Ref | undefined>, htmlGen: Ref | undefined>, sfcStyles: ReturnType<(typeof import('./useSfcStyles'))['useSfcStyles']>['files'], - isVue2: boolean, + compilerOptions: VueCompilerOptions, getCssVBindRanges: (cssEmbeddeFile: EmbeddedFile) => TextRange[], ) { @@ -44,7 +45,8 @@ export function useSfcScriptGen( } return bindTexts; }, - getVueLibraryName(isVue2), + getVueLibraryName(compilerOptions.experimentalCompatMode === 2), + !!compilerOptions.experimentalShamefullySupportOptionsApi, ) ); const file = computed(() => { diff --git a/packages/vue-typescript/src/vueFile.ts b/packages/vue-typescript/src/vueFile.ts index d25bcf814..4bbff44e7 100644 --- a/packages/vue-typescript/src/vueFile.ts +++ b/packages/vue-typescript/src/vueFile.ts @@ -199,7 +199,7 @@ export function createVueFile( computed(() => scriptSetupRanges.value), sfcTemplateScript.templateCodeGens, computed(() => sfcStyles.files.value), - compilerOptions.experimentalCompatMode === 2, + compilerOptions, getCssVBindRanges, ); const sfcScriptForScriptLs = useSfcScriptGen( @@ -213,7 +213,7 @@ export function createVueFile( computed(() => scriptSetupRanges.value), sfcTemplateScript.templateCodeGens, computed(() => sfcStyles.files.value), - compilerOptions.experimentalCompatMode === 2, + compilerOptions, getCssVBindRanges, ); const sfcRefSugarRanges = computed(() => (sfcScriptSetup.ast.value ? {