first commit

This commit is contained in:
rafaeldpsilva
2025-12-10 12:32:12 +00:00
commit adbbf6bf50
3442 changed files with 2725681 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
import type { VueCodeInformation } from '../types';
declare const raw: {
all: {
verification: true;
completion: true;
semantic: true;
navigation: true;
};
none: {};
verification: {
verification: true;
};
completion: {
completion: true;
};
additionalCompletion: {
completion: {
isAdditional: true;
};
};
withoutCompletion: {
verification: true;
semantic: true;
navigation: true;
};
navigation: {
navigation: true;
};
navigationWithoutRename: {
navigation: {
shouldRename: () => false;
};
};
navigationAndCompletion: {
navigation: true;
completion: true;
};
navigationAndAdditionalCompletion: {
navigation: true;
completion: {
isAdditional: true;
};
};
navigationAndVerification: {
navigation: true;
verification: true;
};
withoutNavigation: {
verification: true;
completion: true;
semantic: true;
};
withoutHighlight: {
semantic: {
shouldHighlight: () => false;
};
verification: true;
navigation: true;
completion: true;
};
withoutHighlightAndNavigation: {
semantic: {
shouldHighlight: () => false;
};
verification: true;
completion: true;
};
withoutHighlightAndCompletion: {
semantic: {
shouldHighlight: () => false;
};
verification: true;
navigation: true;
};
withoutHighlightAndCompletionAndNavigation: {
semantic: {
shouldHighlight: () => false;
};
verification: true;
};
};
export declare const codeFeatures: { [K in keyof typeof raw]: VueCodeInformation; };
export {};

View File

@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.codeFeatures = void 0;
const raw = {
all: {
verification: true,
completion: true,
semantic: true,
navigation: true,
},
none: {},
verification: {
verification: true,
},
completion: {
completion: true,
},
additionalCompletion: {
completion: { isAdditional: true },
},
withoutCompletion: {
verification: true,
semantic: true,
navigation: true,
},
navigation: {
navigation: true,
},
navigationWithoutRename: {
navigation: { shouldRename: () => false },
},
navigationAndCompletion: {
navigation: true,
completion: true,
},
navigationAndAdditionalCompletion: {
navigation: true,
completion: { isAdditional: true },
},
navigationAndVerification: {
navigation: true,
verification: true,
},
withoutNavigation: {
verification: true,
completion: true,
semantic: true,
},
withoutHighlight: {
semantic: { shouldHighlight: () => false },
verification: true,
navigation: true,
completion: true,
},
withoutHighlightAndNavigation: {
semantic: { shouldHighlight: () => false },
verification: true,
completion: true,
},
withoutHighlightAndCompletion: {
semantic: { shouldHighlight: () => false },
verification: true,
navigation: true,
},
withoutHighlightAndCompletionAndNavigation: {
semantic: { shouldHighlight: () => false },
verification: true,
},
};
exports.codeFeatures = raw;
//# sourceMappingURL=codeFeatures.js.map

View File

@@ -0,0 +1,3 @@
import type { VueCompilerOptions } from '../types';
export declare function getGlobalTypesFileName({ lib, target, checkUnknownProps, checkUnknownEvents, checkUnknownComponents, }: VueCompilerOptions): string;
export declare function generateGlobalTypes({ lib, target, checkUnknownProps, checkUnknownEvents, checkUnknownComponents, }: VueCompilerOptions): string;

View File

@@ -0,0 +1,151 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getGlobalTypesFileName = getGlobalTypesFileName;
exports.generateGlobalTypes = generateGlobalTypes;
const shared_1 = require("../utils/shared");
function getGlobalTypesFileName({ lib, target, checkUnknownProps, checkUnknownEvents, checkUnknownComponents, }) {
return [
lib,
target,
checkUnknownProps,
checkUnknownEvents,
checkUnknownComponents,
].map(v => (typeof v === 'boolean' ? Number(v) : v)).join('_') + '.d.ts';
}
function generateGlobalTypes({ lib, target, checkUnknownProps, checkUnknownEvents, checkUnknownComponents, }) {
const fnPropsType = `(K extends { $props: infer Props } ? Props : any)${checkUnknownProps ? '' : ' & Record<string, unknown>'}`;
let text = ``;
if (target < 3.5) {
text += `
; declare module '${lib}' {
export interface GlobalComponents { }
export interface GlobalDirectives { }
}`;
}
text += `
; declare global {
const __VLS_intrinsicElements: __VLS_IntrinsicElements;
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
const __VLS_unref: typeof import('${lib}').unref;
const __VLS_placeholder: any;
type __VLS_NativeElements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
type __VLS_IntrinsicElements = ${(target >= 3.3
? `import('${lib}/jsx-runtime').JSX.IntrinsicElements;`
: `globalThis.JSX.IntrinsicElements;`)}
type __VLS_Element = ${(target >= 3.3
? `import('${lib}/jsx-runtime').JSX.Element;`
: `globalThis.JSX.Element;`)}
type __VLS_GlobalComponents = ${(target >= 3.5
? `import('${lib}').GlobalComponents;`
: `import('${lib}').GlobalComponents & Pick<typeof import('${lib}'), 'Transition' | 'TransitionGroup' | 'KeepAlive' | 'Suspense' | 'Teleport'>;`)}
type __VLS_GlobalDirectives = import('${lib}').GlobalDirectives;
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
type __VLS_SpreadMerge<A, B> = Omit<A, keyof B> & B;
type __VLS_WithComponent<N0 extends string, LocalComponents, Self, N1 extends string, N2 extends string, N3 extends string> =
N1 extends keyof LocalComponents ? N1 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? N2 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? N3 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N3] } :
Self extends object ? { [K in N0]: Self } :
N1 extends keyof __VLS_GlobalComponents ? N1 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N1] } :
N2 extends keyof __VLS_GlobalComponents ? N2 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N2] } :
N3 extends keyof __VLS_GlobalComponents ? N3 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N3] } :
${checkUnknownComponents ? '{}' : '{ [K in N0]: unknown }'};
type __VLS_FunctionalComponentProps<T, K> =
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
: T extends (props: infer P, ...args: any) => any ? P :
{};
type __VLS_IsFunction<T, K> = K extends keyof T
? __VLS_IsAny<T[K]> extends false
? unknown extends T[K]
? false
: true
: false
: false;
type __VLS_NormalizeComponentEvent<Props, Events, onEvent extends keyof Props, Event extends keyof Events, CamelizedEvent extends keyof Events> = (
__VLS_IsFunction<Props, onEvent> extends true
? Props
: __VLS_IsFunction<Events, Event> extends true
? { [K in onEvent]?: Events[Event] }
: __VLS_IsFunction<Events, CamelizedEvent> extends true
? { [K in onEvent]?: Events[CamelizedEvent] }
: Props
)${checkUnknownEvents ? '' : ' & Record<string, unknown>'};
// fix https://github.com/vuejs/language-tools/issues/926
type __VLS_UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
type __VLS_OverloadUnionInner<T, U = unknown> = U & T extends (...args: infer A) => infer R
? U extends T
? never
: __VLS_OverloadUnionInner<T, Pick<T, keyof T> & U & ((...args: A) => R)> | ((...args: A) => R)
: never;
type __VLS_OverloadUnion<T> = Exclude<
__VLS_OverloadUnionInner<(() => never) & T>,
T extends () => never ? never : () => never
>;
type __VLS_ConstructorOverloads<T> = __VLS_OverloadUnion<T> extends infer F
? F extends (event: infer E, ...args: infer A) => any
? { [K in E & string]: (...args: A) => void; }
: never
: never;
type __VLS_NormalizeEmits<T> = __VLS_PrettifyGlobal<
__VLS_UnionToIntersection<
__VLS_ConstructorOverloads<T> & {
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
}
>
>;
type __VLS_PrettifyGlobal<T> = { [K in keyof T]: T[K]; } & {};
type __VLS_PickFunctionalComponentCtx<T, K> = NonNullable<__VLS_PickNotAny<
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: infer Ctx } ? Ctx : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
>>;
type __VLS_UseTemplateRef<T> = Readonly<import('${lib}').ShallowRef<T | null>>;
function __VLS_getVForSourceType<T extends number | string | any[] | Iterable<any>>(source: T): [
item: T extends number ? number
: T extends string ? string
: T extends any[] ? T[number]
: T extends Iterable<infer T1> ? T1
: any,
index: number,
][];
function __VLS_getVForSourceType<T>(source: T): [
item: T[keyof T],
key: keyof T,
index: number,
][];
// @ts-ignore
function __VLS_getSlotParams<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>;
// @ts-ignore
function __VLS_getSlotParam<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>[0];
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('${lib}').ObjectDirective
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
: T extends (...args: any) => any
? T
: (arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown) => void;
function __VLS_makeOptional<T>(t: T): { [K in keyof T]?: T[K] };
function __VLS_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
T extends new (...args: any) => any
? (props: ${fnPropsType}, ctx?: any) => __VLS_Element & {
__ctx?: {
attrs?: any;
slots?: K extends { ${(0, shared_1.getSlotsPropertyName)(target)}: infer Slots } ? Slots : any;
emit?: K extends { $emit: infer Emit } ? Emit : any;
expose?(exposed: K): void;
props?: ${fnPropsType};
}
}
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
: T extends (...args: any) => any ? T
: (_: {}${checkUnknownProps ? '' : ' & Record<string, unknown>'}, ctx?: any) => { __ctx?: { attrs?: any, expose?: any, slots?: any, emit?: any, props?: {}${checkUnknownProps ? '' : ' & Record<string, unknown>'} } };
function __VLS_functionalComponentArgsRest<T extends (...args: any) => any>(t: T): 2 extends Parameters<T>['length'] ? [any] : [];
function __VLS_asFunctionalElement<T>(tag: T, endTag?: T): (attrs: T${checkUnknownComponents ? '' : ' & Record<string, unknown>'}) => void;
function __VLS_asFunctionalSlot<S>(slot: S): S extends () => infer R ? (props: {}) => R : NonNullable<S>;
function __VLS_tryAsConstant<const T>(t: T): T;
}
`;
return text;
}
;
//# sourceMappingURL=globalTypes.js.map

View File

@@ -0,0 +1,11 @@
import type * as CompilerDOM from '@vue/compiler-dom';
export interface InlayHintInfo {
blockName: string;
offset: number;
setting: string;
label: string;
tooltip?: string;
paddingRight?: boolean;
paddingLeft?: boolean;
}
export declare function createVBindShorthandInlayHintInfo(loc: CompilerDOM.SourceLocation, variableName: string): InlayHintInfo;

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVBindShorthandInlayHintInfo = createVBindShorthandInlayHintInfo;
function createVBindShorthandInlayHintInfo(loc, variableName) {
return {
blockName: 'template',
offset: loc.end.offset,
setting: 'vue.inlayHints.vBindShorthand',
label: `="${variableName}"`,
tooltip: [
`This is a shorthand for \`${loc.source}="${variableName}"\`.`,
'To hide this hint, set `vue.inlayHints.vBindShorthand` to `false` in IDE settings.',
'[More info](https://github.com/vuejs/core/pull/9451)',
].join('\n\n'),
};
}
//# sourceMappingURL=inlayHints.js.map

View File

@@ -0,0 +1,13 @@
import type * as ts from 'typescript';
import { VueCompilerOptions } from '../types';
export declare function getLocalTypesGenerator(compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions): {
generate: (names: string[]) => Generator<string, void, unknown>;
getUsedNames(): Set<string>;
readonly PrettifyLocal: string;
readonly OmitKeepDiscriminatedUnion: string;
readonly WithDefaults: string;
readonly WithSlots: string;
readonly PropsChildren: string;
readonly TypePropsToOption: string;
readonly OmitIndexSignature: string;
};

View File

@@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLocalTypesGenerator = getLocalTypesGenerator;
const shared_1 = require("../utils/shared");
const utils_1 = require("./utils");
function getLocalTypesGenerator(compilerOptions, vueCompilerOptions) {
const used = new Set();
const OmitKeepDiscriminatedUnion = defineHelper(`__VLS_OmitKeepDiscriminatedUnion`, () => `
type __VLS_OmitKeepDiscriminatedUnion<T, K extends keyof any> = T extends any
? Pick<T, Exclude<keyof T, K>>
: never;
`.trimStart());
const WithDefaults = defineHelper(`__VLS_WithDefaults`, () => `
type __VLS_WithDefaults<P, D> = {
[K in keyof Pick<P, keyof P>]: K extends keyof D
? ${PrettifyLocal.name}<P[K] & { default: D[K]}>
: P[K]
};
`.trimStart());
const PrettifyLocal = defineHelper(`__VLS_PrettifyLocal`, () => `type __VLS_PrettifyLocal<T> = { [K in keyof T]: T[K]; } & {}${utils_1.endOfLine}`);
const WithSlots = defineHelper(`__VLS_WithSlots`, () => `
type __VLS_WithSlots<T, S> = T & {
new(): {
${(0, shared_1.getSlotsPropertyName)(vueCompilerOptions.target)}: S;
${vueCompilerOptions.jsxSlots ? `$props: ${PropsChildren.name}<S>;` : ''}
}
};
`.trimStart());
const PropsChildren = defineHelper(`__VLS_PropsChildren`, () => `
type __VLS_PropsChildren<S> = {
[K in keyof (
boolean extends (
// @ts-ignore
JSX.ElementChildrenAttribute extends never
? true
: false
)
? never
// @ts-ignore
: JSX.ElementChildrenAttribute
)]?: S;
};
`.trimStart());
const TypePropsToOption = defineHelper(`__VLS_TypePropsToOption`, () => compilerOptions.exactOptionalPropertyTypes ?
`
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K>
? { type: import('${vueCompilerOptions.lib}').PropType<T[K]> }
: { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true }
};
`.trimStart() :
`
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K>
? { type: import('${vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable<T[K]>> }
: { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true }
};
`.trimStart());
const OmitIndexSignature = defineHelper(`__VLS_OmitIndexSignature`, () => `type __VLS_OmitIndexSignature<T> = { [K in keyof T as {} extends Record<K, unknown> ? never : K]: T[K]; }${utils_1.endOfLine}`);
const helpers = {
[PrettifyLocal.name]: PrettifyLocal,
[OmitKeepDiscriminatedUnion.name]: OmitKeepDiscriminatedUnion,
[WithDefaults.name]: WithDefaults,
[WithSlots.name]: WithSlots,
[PropsChildren.name]: PropsChildren,
[TypePropsToOption.name]: TypePropsToOption,
[OmitIndexSignature.name]: OmitIndexSignature,
};
used.clear();
return {
generate,
getUsedNames() {
return used;
},
get PrettifyLocal() { return PrettifyLocal.name; },
get OmitKeepDiscriminatedUnion() { return OmitKeepDiscriminatedUnion.name; },
get WithDefaults() { return WithDefaults.name; },
get WithSlots() { return WithSlots.name; },
get PropsChildren() { return PropsChildren.name; },
get TypePropsToOption() { return TypePropsToOption.name; },
get OmitIndexSignature() { return OmitIndexSignature.name; },
};
function* generate(names) {
const generated = new Set();
while (names.length) {
used.clear();
for (const name of names) {
if (generated.has(name)) {
continue;
}
const helper = helpers[name];
yield helper.generate();
generated.add(name);
}
names = [...used].filter(name => !generated.has(name));
}
}
function defineHelper(name, generate) {
return {
get name() {
used.add(name);
return name;
},
generate,
};
}
}
//# sourceMappingURL=localTypes.js.map

View File

@@ -0,0 +1,8 @@
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, Sfc } from '../../types';
import type { ScriptCodegenContext } from './context';
import type { ScriptCodegenOptions } from './index';
export declare function generateComponent(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges): Generator<Code>;
export declare function generateComponentSetupReturns(scriptSetupRanges: ScriptSetupRanges): Generator<Code>;
export declare function generateEmitsOption(options: ScriptCodegenOptions, scriptSetupRanges: ScriptSetupRanges): Generator<Code>;
export declare function generatePropsOption(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges, hasEmitsOption: boolean, inheritAttrs: boolean): Generator<Code>;

View File

@@ -0,0 +1,181 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateComponent = generateComponent;
exports.generateComponentSetupReturns = generateComponentSetupReturns;
exports.generateEmitsOption = generateEmitsOption;
exports.generatePropsOption = generatePropsOption;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
function* generateComponent(options, ctx, scriptSetup, scriptSetupRanges) {
if (options.sfc.script && options.scriptRanges?.exportDefault && options.scriptRanges.exportDefault.expression.start !== options.scriptRanges.exportDefault.args.start) {
// use defineComponent() from user space code if it exist
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, options.scriptRanges.exportDefault.expression.start, options.scriptRanges.exportDefault.args.start, codeFeatures_1.codeFeatures.all);
yield `{${utils_1.newLine}`;
}
else {
yield `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${utils_1.newLine}`;
}
yield `setup() {${utils_1.newLine}`;
yield `return {${utils_1.newLine}`;
if (ctx.bypassDefineComponent) {
yield* generateComponentSetupReturns(scriptSetupRanges);
}
if (scriptSetupRanges.defineExpose) {
yield `...__VLS_exposed,${utils_1.newLine}`;
}
yield `}${utils_1.endOfLine}`;
yield `},${utils_1.newLine}`;
if (!ctx.bypassDefineComponent) {
const emitOptionCodes = [...generateEmitsOption(options, scriptSetupRanges)];
yield* emitOptionCodes;
yield* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, !!emitOptionCodes.length, true);
}
if (options.vueCompilerOptions.target >= 3.5
&& options.vueCompilerOptions.inferComponentDollarRefs
&& options.templateCodegen?.templateRefs.size) {
yield `__typeRefs: {} as __VLS_TemplateRefs,${utils_1.newLine}`;
}
if (options.vueCompilerOptions.target >= 3.5
&& options.vueCompilerOptions.inferComponentDollarEl
&& options.templateCodegen?.singleRootElTypes.length) {
yield `__typeEl: {} as __VLS_RootEl,${utils_1.newLine}`;
}
if (options.sfc.script && options.scriptRanges?.exportDefault?.args) {
const { args } = options.scriptRanges.exportDefault;
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, args.start + 1, args.end - 1, codeFeatures_1.codeFeatures.all);
}
yield `})`;
}
function* generateComponentSetupReturns(scriptSetupRanges) {
// fill $props
if (scriptSetupRanges.defineProps) {
// NOTE: defineProps is inaccurate for $props
yield `$props: __VLS_makeOptional(${scriptSetupRanges.defineProps.name ?? `__VLS_props`}),${utils_1.newLine}`;
yield `...${scriptSetupRanges.defineProps.name ?? `__VLS_props`},${utils_1.newLine}`;
}
// fill $emit
if (scriptSetupRanges.defineEmits) {
yield `$emit: ${scriptSetupRanges.defineEmits.name ?? '__VLS_emit'},${utils_1.newLine}`;
}
}
function* generateEmitsOption(options, scriptSetupRanges) {
const codes = [];
if (scriptSetupRanges.defineProp.some(p => p.isModel)) {
codes.push({
optionExp: `{} as __VLS_NormalizeEmits<typeof __VLS_modelEmit>`,
typeOptionType: `__VLS_ModelEmit`,
});
}
if (scriptSetupRanges.defineEmits) {
const { name, typeArg, hasUnionTypeArg } = scriptSetupRanges.defineEmits;
codes.push({
optionExp: `{} as __VLS_NormalizeEmits<typeof ${name ?? '__VLS_emit'}>`,
typeOptionType: typeArg && !hasUnionTypeArg
? `__VLS_Emit`
: undefined,
});
}
if (options.vueCompilerOptions.target >= 3.5 && codes.every(code => code.typeOptionType)) {
if (codes.length === 1) {
yield `__typeEmits: {} as `;
yield codes[0].typeOptionType;
yield `,${utils_1.newLine}`;
}
else if (codes.length >= 2) {
yield `__typeEmits: {} as `;
yield codes[0].typeOptionType;
for (let i = 1; i < codes.length; i++) {
yield ` & `;
yield codes[i].typeOptionType;
}
yield `,${utils_1.newLine}`;
}
}
else if (codes.every(code => code.optionExp)) {
if (codes.length === 1) {
yield `emits: `;
yield codes[0].optionExp;
yield `,${utils_1.newLine}`;
}
else if (codes.length >= 2) {
yield `emits: {${utils_1.newLine}`;
for (const code of codes) {
yield `...`;
yield code.optionExp;
yield `,${utils_1.newLine}`;
}
yield `},${utils_1.newLine}`;
}
}
}
function* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, hasEmitsOption, inheritAttrs) {
const codes = [];
if (ctx.generatedPropsType) {
codes.push({
optionExp: [
`{} as `,
scriptSetupRanges.withDefaults?.arg ? `${ctx.localTypes.WithDefaults}<` : '',
`${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`,
scriptSetupRanges.withDefaults?.arg ? `, typeof __VLS_withDefaultsArg>` : '',
].join(''),
typeOptionExp: `{} as __VLS_PublicProps`,
});
}
if (scriptSetupRanges.defineProps?.arg) {
const { arg } = scriptSetupRanges.defineProps;
codes.push({
optionExp: (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.navigation),
typeOptionExp: undefined,
});
}
if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
let attrsType = `Partial<__VLS_InheritedAttrs>`;
if (hasEmitsOption) {
attrsType = `Omit<${attrsType}, \`on\${string}\`>`;
}
const propsType = `__VLS_PickNotAny<${ctx.localTypes.OmitIndexSignature}<${attrsType}>, {}>`;
const optionType = `${ctx.localTypes.TypePropsToOption}<${propsType}>`;
codes.unshift({
optionExp: codes.length
? `{} as ${optionType}`
// workaround for https://github.com/vuejs/core/pull/7419
: `{} as keyof ${propsType} extends never ? never: ${optionType}`,
typeOptionExp: `{} as ${attrsType}`,
});
}
const useTypeOption = options.vueCompilerOptions.target >= 3.5 && codes.every(code => code.typeOptionExp);
const useOption = !useTypeOption || scriptSetupRanges.withDefaults;
if (useTypeOption) {
if (codes.length === 1) {
yield `__typeProps: `;
yield codes[0].typeOptionExp;
yield `,${utils_1.newLine}`;
}
else if (codes.length >= 2) {
yield `__typeProps: {${utils_1.newLine}`;
for (const { typeOptionExp } of codes) {
yield `...`;
yield typeOptionExp;
yield `,${utils_1.newLine}`;
}
yield `},${utils_1.newLine}`;
}
}
if (useOption) {
if (codes.length === 1) {
yield `props: `;
yield codes[0].optionExp;
yield `,${utils_1.newLine}`;
}
else if (codes.length >= 2) {
yield `props: {${utils_1.newLine}`;
for (const { optionExp } of codes) {
yield `...`;
yield optionExp;
yield `,${utils_1.newLine}`;
}
yield `},${utils_1.newLine}`;
}
}
}
//# sourceMappingURL=component.js.map

View File

@@ -0,0 +1,5 @@
import type { Code } from '../../types';
import type { TemplateCodegenContext } from '../template/context';
import type { ScriptCodegenContext } from './context';
import type { ScriptCodegenOptions } from './index';
export declare function generateComponentSelf(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, templateCodegenCtx: TemplateCodegenContext): Generator<Code>;

View File

@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateComponentSelf = generateComponentSelf;
const path = require("path-browserify");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const component_1 = require("./component");
const template_1 = require("./template");
function* generateComponentSelf(options, ctx, templateCodegenCtx) {
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
yield `const __VLS_self = (await import('${options.vueCompilerOptions.lib}')).defineComponent({${utils_1.newLine}`;
yield `setup() {${utils_1.newLine}`;
yield `return {${utils_1.newLine}`;
if (ctx.bypassDefineComponent) {
yield* (0, component_1.generateComponentSetupReturns)(options.scriptSetupRanges);
}
// bindings
const templateUsageVars = (0, template_1.getTemplateUsageVars)(options, ctx);
for (const [content, bindings] of [
[options.sfc.scriptSetup.content, options.scriptSetupRanges.bindings],
options.sfc.script && options.scriptRanges
? [options.sfc.script.content, options.scriptRanges.bindings]
: ['', []],
]) {
for (const { range } of bindings) {
const varName = content.slice(range.start, range.end);
if (!templateUsageVars.has(varName) && !templateCodegenCtx.accessExternalVariables.has(varName)) {
continue;
}
const token = Symbol(varName.length);
yield ['', undefined, 0, { __linkedToken: token }];
yield `${varName}: ${varName} as typeof `;
yield ['', undefined, 0, { __linkedToken: token }];
yield `${varName},${utils_1.newLine}`;
}
}
yield `}${utils_1.endOfLine}`; // return {
yield `},${utils_1.newLine}`; // setup() {
if (options.sfc.scriptSetup && options.scriptSetupRanges && !ctx.bypassDefineComponent) {
const emitOptionCodes = [...(0, component_1.generateEmitsOption)(options, options.scriptSetupRanges)];
yield* emitOptionCodes;
yield* (0, component_1.generatePropsOption)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges, !!emitOptionCodes.length, false);
}
if (options.sfc.script && options.scriptRanges?.exportDefault?.args) {
const { args } = options.scriptRanges.exportDefault;
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, args.start + 1, args.end - 1, codeFeatures_1.codeFeatures.all);
}
yield `})${utils_1.endOfLine}`; // defineComponent {
}
else if (options.sfc.script) {
yield `let __VLS_self!: typeof import('./${path.basename(options.fileName)}').default${utils_1.endOfLine}`;
}
else {
yield `const __VLS_self = (await import('${options.vueCompilerOptions.lib}')).defineComponent({})${utils_1.endOfLine}`;
}
}
//# sourceMappingURL=componentSelf.js.map

View File

@@ -0,0 +1,27 @@
import { InlayHintInfo } from '../inlayHints';
import type { ScriptCodegenOptions } from './index';
export interface HelperType {
name: string;
used?: boolean;
generated?: boolean;
code: string;
}
export type ScriptCodegenContext = ReturnType<typeof createScriptCodegenContext>;
export declare function createScriptCodegenContext(options: ScriptCodegenOptions): {
generatedTemplate: boolean;
generatedPropsType: boolean;
bypassDefineComponent: boolean;
bindingNames: Set<string>;
localTypes: {
generate: (names: string[]) => Generator<string, void, unknown>;
getUsedNames(): Set<string>;
readonly PrettifyLocal: string;
readonly OmitKeepDiscriminatedUnion: string;
readonly WithDefaults: string;
readonly WithSlots: string;
readonly PropsChildren: string;
readonly TypePropsToOption: string;
readonly OmitIndexSignature: string;
};
inlayHints: InlayHintInfo[];
};

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createScriptCodegenContext = createScriptCodegenContext;
const localTypes_1 = require("../localTypes");
function createScriptCodegenContext(options) {
const localTypes = (0, localTypes_1.getLocalTypesGenerator)(options.compilerOptions, options.vueCompilerOptions);
const inlayHints = [];
return {
generatedTemplate: false,
generatedPropsType: false,
bypassDefineComponent: options.lang === 'js' || options.lang === 'jsx',
bindingNames: new Set([
...options.scriptRanges?.bindings.map(({ range }) => options.sfc.script.content.slice(range.start, range.end)) ?? [],
...options.scriptSetupRanges?.bindings.map(({ range }) => options.sfc.scriptSetup.content.slice(range.start, range.end)) ?? [],
]),
localTypes,
inlayHints,
};
}
//# sourceMappingURL=context.js.map

View File

@@ -0,0 +1,25 @@
import type * as ts from 'typescript';
import type { ScriptRanges } from '../../parsers/scriptRanges';
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, Sfc, VueCompilerOptions } from '../../types';
import type { TemplateCodegenContext } from '../template/context';
import { ScriptCodegenContext } from './context';
export interface ScriptCodegenOptions {
ts: typeof ts;
compilerOptions: ts.CompilerOptions;
vueCompilerOptions: VueCompilerOptions;
sfc: Sfc;
edited: boolean;
fileName: string;
lang: string;
scriptRanges: ScriptRanges | undefined;
scriptSetupRanges: ScriptSetupRanges | undefined;
templateCodegen: TemplateCodegenContext & {
codes: Code[];
} | undefined;
destructuredPropNames: Set<string>;
templateRefNames: Set<string>;
appendGlobalTypes: boolean;
}
export declare function generateScript(options: ScriptCodegenOptions): Generator<Code, ScriptCodegenContext>;
export declare function generateScriptSectionPartiallyEnding(source: string, end: number, mark: string, delimiter?: string): Generator<Code>;

View File

@@ -0,0 +1,125 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateScript = generateScript;
exports.generateScriptSectionPartiallyEnding = generateScriptSectionPartiallyEnding;
const path = require("path-browserify");
const codeFeatures_1 = require("../codeFeatures");
const globalTypes_1 = require("../globalTypes");
const utils_1 = require("../utils");
const componentSelf_1 = require("./componentSelf");
const context_1 = require("./context");
const scriptSetup_1 = require("./scriptSetup");
const src_1 = require("./src");
const template_1 = require("./template");
function* generateScript(options) {
const ctx = (0, context_1.createScriptCodegenContext)(options);
if (options.vueCompilerOptions.__setupedGlobalTypes) {
const globalTypes = options.vueCompilerOptions.__setupedGlobalTypes;
if (typeof globalTypes === 'object') {
let relativePath = path.relative(path.dirname(options.fileName), globalTypes.absolutePath);
if (relativePath !== globalTypes.absolutePath && !relativePath.startsWith('./') && !relativePath.startsWith('../')) {
relativePath = './' + relativePath;
}
yield `/// <reference types="${relativePath}" />${utils_1.newLine}`;
}
else {
yield `/// <reference types=".vue-global-types/${(0, globalTypes_1.getGlobalTypesFileName)(options.vueCompilerOptions)}" />${utils_1.newLine}`;
}
}
else {
yield `/* placeholder */`;
}
if (options.sfc.script?.src) {
yield* (0, src_1.generateSrc)(options.sfc.script.src);
}
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
yield* (0, scriptSetup_1.generateScriptSetupImports)(options.sfc.scriptSetup, options.scriptSetupRanges);
}
if (options.sfc.script && options.scriptRanges) {
const { exportDefault, classBlockEnd } = options.scriptRanges;
const isExportRawObject = exportDefault
&& options.sfc.script.content[exportDefault.expression.start] === '{';
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
if (exportDefault) {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, exportDefault.expression.start, codeFeatures_1.codeFeatures.all);
yield* (0, scriptSetup_1.generateScriptSetup)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, exportDefault.expression.end, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
}
else {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
yield* generateScriptSectionPartiallyEnding(options.sfc.script.name, options.sfc.script.content.length, '#3632/both.vue');
yield* (0, scriptSetup_1.generateScriptSetup)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
}
}
else if (exportDefault && isExportRawObject && options.vueCompilerOptions.optionsWrapper.length) {
ctx.inlayHints.push({
blockName: options.sfc.script.name,
offset: exportDefault.expression.start,
setting: 'vue.inlayHints.optionsWrapper',
label: options.vueCompilerOptions.optionsWrapper.length
? options.vueCompilerOptions.optionsWrapper[0]
: '[Missing optionsWrapper[0]]',
tooltip: [
'This is virtual code that is automatically wrapped for type support, it does not affect your runtime behavior, you can customize it via `vueCompilerOptions.optionsWrapper` option in tsconfig / jsconfig.',
'To hide it, you can set `"vue.inlayHints.optionsWrapper": false` in IDE settings.',
].join('\n\n'),
}, {
blockName: options.sfc.script.name,
offset: exportDefault.expression.end,
setting: 'vue.inlayHints.optionsWrapper',
label: options.vueCompilerOptions.optionsWrapper.length >= 2
? options.vueCompilerOptions.optionsWrapper[1]
: '[Missing optionsWrapper[1]]',
});
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, exportDefault.expression.start, codeFeatures_1.codeFeatures.all);
yield options.vueCompilerOptions.optionsWrapper[0];
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, exportDefault.expression.start, exportDefault.expression.end, codeFeatures_1.codeFeatures.all);
yield options.vueCompilerOptions.optionsWrapper[1];
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, exportDefault.expression.end, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
}
else if (classBlockEnd !== undefined) {
if (options.vueCompilerOptions.skipTemplateCodegen) {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
}
else {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, classBlockEnd, codeFeatures_1.codeFeatures.all);
yield `__VLS_template = () => {${utils_1.newLine}`;
const templateCodegenCtx = yield* (0, template_1.generateTemplate)(options, ctx);
yield* (0, componentSelf_1.generateComponentSelf)(options, ctx, templateCodegenCtx);
yield `}${utils_1.endOfLine}`;
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, classBlockEnd, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
}
}
else {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
yield* generateScriptSectionPartiallyEnding(options.sfc.script.name, options.sfc.script.content.length, '#3632/script.vue');
}
}
else if (options.sfc.scriptSetup && options.scriptSetupRanges) {
yield* (0, scriptSetup_1.generateScriptSetup)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
}
if (options.sfc.scriptSetup) {
yield* generateScriptSectionPartiallyEnding(options.sfc.scriptSetup.name, options.sfc.scriptSetup.content.length, '#4569/main.vue', ';');
}
if (!ctx.generatedTemplate) {
const templateCodegenCtx = yield* (0, template_1.generateTemplate)(options, ctx);
yield* (0, componentSelf_1.generateComponentSelf)(options, ctx, templateCodegenCtx);
}
if (options.edited) {
yield `type __VLS_IntrinsicElementsCompletion = __VLS_IntrinsicElements${utils_1.endOfLine}`;
}
yield* ctx.localTypes.generate([...ctx.localTypes.getUsedNames()]);
if (options.appendGlobalTypes) {
yield (0, globalTypes_1.generateGlobalTypes)(options.vueCompilerOptions);
}
if (options.sfc.scriptSetup) {
yield ['', 'scriptSetup', options.sfc.scriptSetup.content.length, codeFeatures_1.codeFeatures.verification];
}
return ctx;
}
function* generateScriptSectionPartiallyEnding(source, end, mark, delimiter = 'debugger') {
yield delimiter;
yield ['', source, end, codeFeatures_1.codeFeatures.verification];
yield `/* PartiallyEnd: ${mark} */${utils_1.newLine}`;
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,6 @@
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, Sfc } from '../../types';
import type { ScriptCodegenContext } from './context';
import { type ScriptCodegenOptions } from './index';
export declare function generateScriptSetupImports(scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges): Generator<Code>;
export declare function generateScriptSetup(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges): Generator<Code>;

View File

@@ -0,0 +1,489 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateScriptSetupImports = generateScriptSetupImports;
exports.generateScriptSetup = generateScriptSetup;
const shared_1 = require("@vue/shared");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const camelized_1 = require("../utils/camelized");
const wrapWith_1 = require("../utils/wrapWith");
const component_1 = require("./component");
const componentSelf_1 = require("./componentSelf");
const index_1 = require("./index");
const template_1 = require("./template");
function* generateScriptSetupImports(scriptSetup, scriptSetupRanges) {
yield [
scriptSetup.content.slice(0, Math.max(scriptSetupRanges.importSectionEndOffset, scriptSetupRanges.leadingCommentEndOffset)),
'scriptSetup',
0,
codeFeatures_1.codeFeatures.all,
];
}
function* generateScriptSetup(options, ctx, scriptSetup, scriptSetupRanges) {
if (scriptSetup.generic) {
if (!options.scriptRanges?.exportDefault) {
// #4569
yield ['', 'scriptSetup', 0, codeFeatures_1.codeFeatures.verification];
yield `export default `;
}
yield `(`;
if (typeof scriptSetup.generic === 'object') {
yield `<`;
yield [
scriptSetup.generic.text,
'main',
scriptSetup.generic.offset,
codeFeatures_1.codeFeatures.all,
];
if (!scriptSetup.generic.text.endsWith(`,`)) {
yield `,`;
}
yield `>`;
}
yield `(${utils_1.newLine}`
+ ` __VLS_props: NonNullable<Awaited<typeof __VLS_setup>>['props'],${utils_1.newLine}`
+ ` __VLS_ctx?: ${ctx.localTypes.PrettifyLocal}<Pick<NonNullable<Awaited<typeof __VLS_setup>>, 'attrs' | 'emit' | 'slots'>>,${utils_1.newLine}` // use __VLS_Prettify for less dts code
+ ` __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>['expose'],${utils_1.newLine}`
+ ` __VLS_setup = (async () => {${utils_1.newLine}`;
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, undefined);
const emitTypes = [];
if (scriptSetupRanges.defineEmits) {
emitTypes.push(`typeof ${scriptSetupRanges.defineEmits.name ?? '__VLS_emit'}`);
}
if (scriptSetupRanges.defineProp.some(p => p.isModel)) {
emitTypes.push(`typeof __VLS_modelEmit`);
}
yield `return {} as {${utils_1.newLine}`
+ ` props: ${ctx.localTypes.PrettifyLocal}<__VLS_OwnProps & __VLS_PublicProps & Partial<__VLS_InheritedAttrs>> & __VLS_BuiltInPublicProps,${utils_1.newLine}`
+ ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.defineExpose ? 'typeof __VLS_exposed' : '{}'}>): void,${utils_1.newLine}`
+ ` attrs: any,${utils_1.newLine}`
+ ` slots: __VLS_Slots,${utils_1.newLine}`
+ ` emit: ${emitTypes.length ? emitTypes.join(' & ') : `{}`},${utils_1.newLine}`
+ `}${utils_1.endOfLine}`;
yield `})(),${utils_1.newLine}`; // __VLS_setup = (async () => {
yield `) => ({} as import('${options.vueCompilerOptions.lib}').VNode & { __ctx?: Awaited<typeof __VLS_setup> }))`;
}
else if (!options.sfc.script) {
// no script block, generate script setup code at root
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, 'export default');
}
else {
if (!options.scriptRanges?.exportDefault) {
yield `export default `;
}
yield `await (async () => {${utils_1.newLine}`;
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, 'return');
yield `})()`;
}
}
function* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, syntax) {
let setupCodeModifies = [];
for (const { comments } of scriptSetupRanges.defineProp) {
if (comments) {
setupCodeModifies.push([
[``],
comments.start,
comments.end,
]);
}
}
if (scriptSetupRanges.defineProps) {
const { name, statement, callExp, typeArg } = scriptSetupRanges.defineProps;
setupCodeModifies.push(...generateDefineWithType(scriptSetup, statement, scriptSetupRanges.withDefaults?.callExp ?? callExp, typeArg, name, `__VLS_props`, `__VLS_Props`));
}
if (scriptSetupRanges.defineEmits) {
const { name, statement, callExp, typeArg } = scriptSetupRanges.defineEmits;
setupCodeModifies.push(...generateDefineWithType(scriptSetup, statement, callExp, typeArg, name, `__VLS_emit`, `__VLS_Emit`));
}
if (scriptSetupRanges.defineSlots) {
const { name, statement, callExp, typeArg } = scriptSetupRanges.defineSlots;
setupCodeModifies.push(...generateDefineWithType(scriptSetup, statement, callExp, typeArg, name, `__VLS_slots`, `__VLS_Slots`));
}
if (scriptSetupRanges.defineExpose) {
const { callExp, arg, typeArg } = scriptSetupRanges.defineExpose;
if (typeArg) {
setupCodeModifies.push([
[
`let __VLS_exposed!: `,
(0, utils_1.generateSfcBlockSection)(scriptSetup, typeArg.start, typeArg.end, codeFeatures_1.codeFeatures.all),
`${utils_1.endOfLine}`,
],
callExp.start,
callExp.start,
], [
[`typeof __VLS_exposed`],
typeArg.start,
typeArg.end,
]);
}
else if (arg) {
setupCodeModifies.push([
[
`const __VLS_exposed = `,
(0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.all),
`${utils_1.endOfLine}`,
],
callExp.start,
callExp.start,
], [
[`__VLS_exposed`],
arg.start,
arg.end,
]);
}
else {
setupCodeModifies.push([
[`const __VLS_exposed = {}${utils_1.endOfLine}`],
callExp.start,
callExp.start,
]);
}
}
if (options.vueCompilerOptions.inferTemplateDollarAttrs) {
for (const { callExp } of scriptSetupRanges.useAttrs) {
setupCodeModifies.push([
[`(`],
callExp.start,
callExp.start
], [
[` as typeof __VLS_dollars.$attrs)`],
callExp.end,
callExp.end
]);
}
}
for (const { callExp, exp, arg } of scriptSetupRanges.useCssModule) {
setupCodeModifies.push([
[`(`],
callExp.start,
callExp.start
], [
arg ? [
` as Omit<__VLS_StyleModules, '$style'>[`,
(0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.all),
`])`
] : [
` as __VLS_StyleModules[`,
...(0, wrapWith_1.wrapWith)(exp.start, exp.end, scriptSetup.name, codeFeatures_1.codeFeatures.verification, `'$style'`),
`])`
],
callExp.end,
callExp.end
]);
if (arg) {
setupCodeModifies.push([
[`__VLS_placeholder`],
arg.start,
arg.end
]);
}
}
if (options.vueCompilerOptions.inferTemplateDollarSlots) {
for (const { callExp } of scriptSetupRanges.useSlots) {
setupCodeModifies.push([
[`(`],
callExp.start,
callExp.start
], [
[` as typeof __VLS_dollars.$slots)`],
callExp.end,
callExp.end
]);
}
}
const isTs = options.lang !== 'js' && options.lang !== 'jsx';
for (const { callExp, exp, arg } of scriptSetupRanges.useTemplateRef) {
const templateRefType = arg
? [
`__VLS_TemplateRefs[`,
(0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.all),
`]`
]
: [`unknown`];
if (isTs) {
setupCodeModifies.push([
[
`<`,
...templateRefType,
`>`
],
exp.end,
exp.end
]);
}
else {
setupCodeModifies.push([
[`(`],
callExp.start,
callExp.start
], [
[
` as __VLS_UseTemplateRef<`,
...templateRefType,
`>)`
],
callExp.end,
callExp.end
]);
}
if (arg) {
setupCodeModifies.push([
[`__VLS_placeholder`],
arg.start,
arg.end
]);
}
}
setupCodeModifies = setupCodeModifies.sort((a, b) => a[1] - b[1]);
let nextStart = Math.max(scriptSetupRanges.importSectionEndOffset, scriptSetupRanges.leadingCommentEndOffset);
for (const [codes, start, end] of setupCodeModifies) {
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, nextStart, start, codeFeatures_1.codeFeatures.all);
yield* codes;
nextStart = end;
}
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, nextStart, scriptSetup.content.length, codeFeatures_1.codeFeatures.all);
yield* (0, index_1.generateScriptSectionPartiallyEnding)(scriptSetup.name, scriptSetup.content.length, '#3632/scriptSetup.vue');
yield* generateMacros(options, ctx);
yield* generateDefineProp(options);
if (scriptSetupRanges.defineProps?.typeArg && scriptSetupRanges.withDefaults?.arg) {
// fix https://github.com/vuejs/language-tools/issues/1187
yield `const __VLS_withDefaultsArg = (function <T>(t: T) { return t })(`;
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.withDefaults.arg.start, scriptSetupRanges.withDefaults.arg.end, codeFeatures_1.codeFeatures.navigation);
yield `)${utils_1.endOfLine}`;
}
yield* generateComponentProps(options, ctx, scriptSetup, scriptSetupRanges);
yield* generateModelEmit(scriptSetup, scriptSetupRanges);
const templateCodegenCtx = yield* (0, template_1.generateTemplate)(options, ctx);
yield* (0, componentSelf_1.generateComponentSelf)(options, ctx, templateCodegenCtx);
if (syntax) {
if (!options.vueCompilerOptions.skipTemplateCodegen
&& (scriptSetupRanges.defineSlots
|| options.templateCodegen?.slots.length
|| options.templateCodegen?.dynamicSlots.length)) {
yield `const __VLS_component = `;
yield* (0, component_1.generateComponent)(options, ctx, scriptSetup, scriptSetupRanges);
yield utils_1.endOfLine;
yield `${syntax} `;
yield `{} as ${ctx.localTypes.WithSlots}<typeof __VLS_component, __VLS_Slots>${utils_1.endOfLine}`;
}
else {
yield `${syntax} `;
yield* (0, component_1.generateComponent)(options, ctx, scriptSetup, scriptSetupRanges);
yield utils_1.endOfLine;
}
}
}
function* generateMacros(options, ctx) {
if (options.vueCompilerOptions.target >= 3.3) {
yield `// @ts-ignore${utils_1.newLine}`;
yield `declare const { `;
for (const macro of Object.keys(options.vueCompilerOptions.macros)) {
if (!ctx.bindingNames.has(macro)) {
yield `${macro}, `;
}
}
yield `}: typeof import('${options.vueCompilerOptions.lib}')${utils_1.endOfLine}`;
}
}
function* generateDefineProp(options) {
const definePropProposalA = options.vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition';
const definePropProposalB = options.vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition';
if (definePropProposalA || definePropProposalB) {
yield `type __VLS_PropOptions<T> = Exclude<import('${options.vueCompilerOptions.lib}').Prop<T>, import('${options.vueCompilerOptions.lib}').PropType<T>>${utils_1.endOfLine}`;
if (definePropProposalA) {
yield `declare function defineProp<T>(name: string, options: ({ required: true } | { default: T }) & __VLS_PropOptions<T>): import('${options.vueCompilerOptions.lib}').ComputedRef<T>${utils_1.endOfLine}`;
yield `declare function defineProp<T>(name?: string, options?: __VLS_PropOptions<T>): import('${options.vueCompilerOptions.lib}').ComputedRef<T | undefined>${utils_1.endOfLine}`;
}
if (definePropProposalB) {
yield `declare function defineProp<T>(value: T | (() => T), required?: boolean, options?: __VLS_PropOptions<T>): import('${options.vueCompilerOptions.lib}').ComputedRef<T>${utils_1.endOfLine}`;
yield `declare function defineProp<T>(value: T | (() => T) | undefined, required: true, options?: __VLS_PropOptions<T>): import('${options.vueCompilerOptions.lib}').ComputedRef<T>${utils_1.endOfLine}`;
yield `declare function defineProp<T>(value?: T | (() => T), required?: boolean, options?: __VLS_PropOptions<T>): import('${options.vueCompilerOptions.lib}').ComputedRef<T | undefined>${utils_1.endOfLine}`;
}
}
}
function* generateDefineWithType(scriptSetup, statement, callExp, typeArg, name, defaultName, typeName) {
if (typeArg) {
yield [[
`type ${typeName} = `,
(0, utils_1.generateSfcBlockSection)(scriptSetup, typeArg.start, typeArg.end, codeFeatures_1.codeFeatures.all),
utils_1.endOfLine,
], statement.start, statement.start];
yield [[typeName], typeArg.start, typeArg.end];
}
if (!name) {
if (statement.start === callExp.start && statement.end === callExp.end) {
yield [[`const ${defaultName} = `], callExp.start, callExp.start];
}
else if (typeArg) {
yield [[
`const ${defaultName} = `,
(0, utils_1.generateSfcBlockSection)(scriptSetup, callExp.start, typeArg.start, codeFeatures_1.codeFeatures.all)
], statement.start, typeArg.start];
yield [[
(0, utils_1.generateSfcBlockSection)(scriptSetup, typeArg.end, callExp.end, codeFeatures_1.codeFeatures.all),
utils_1.endOfLine,
(0, utils_1.generateSfcBlockSection)(scriptSetup, statement.start, callExp.start, codeFeatures_1.codeFeatures.all),
defaultName
], typeArg.end, callExp.end];
}
else {
yield [[
`const ${defaultName} = `,
(0, utils_1.generateSfcBlockSection)(scriptSetup, callExp.start, callExp.end, codeFeatures_1.codeFeatures.all),
utils_1.endOfLine,
(0, utils_1.generateSfcBlockSection)(scriptSetup, statement.start, callExp.start, codeFeatures_1.codeFeatures.all),
defaultName
], statement.start, callExp.end];
}
}
}
function* generateComponentProps(options, ctx, scriptSetup, scriptSetupRanges) {
if (scriptSetup.generic) {
yield `const __VLS_fnComponent = (await import('${options.vueCompilerOptions.lib}')).defineComponent({${utils_1.newLine}`;
if (scriptSetupRanges.defineProps?.arg) {
yield `props: `;
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.defineProps.arg.start, scriptSetupRanges.defineProps.arg.end, codeFeatures_1.codeFeatures.navigation);
yield `,${utils_1.newLine}`;
}
yield* (0, component_1.generateEmitsOption)(options, scriptSetupRanges);
yield `})${utils_1.endOfLine}`;
yield `type __VLS_BuiltInPublicProps = ${options.vueCompilerOptions.target >= 3.4
? `import('${options.vueCompilerOptions.lib}').PublicProps`
: options.vueCompilerOptions.target >= 3.0
? `import('${options.vueCompilerOptions.lib}').VNodeProps`
+ ` & import('${options.vueCompilerOptions.lib}').AllowedComponentProps`
+ ` & import('${options.vueCompilerOptions.lib}').ComponentCustomProps`
: `globalThis.JSX.IntrinsicAttributes`}`;
yield utils_1.endOfLine;
yield `type __VLS_OwnProps = `;
yield `${ctx.localTypes.OmitKeepDiscriminatedUnion}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`;
yield utils_1.endOfLine;
}
if (scriptSetupRanges.defineProp.length) {
yield `const __VLS_defaults = {${utils_1.newLine}`;
for (const defineProp of scriptSetupRanges.defineProp) {
if (!defineProp.defaultValue) {
continue;
}
const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp);
if (defineProp.name || defineProp.isModel) {
yield `'${propName}'`;
}
else if (defineProp.localName) {
yield localName;
}
else {
continue;
}
yield `: `;
yield getRangeText(scriptSetup, defineProp.defaultValue);
yield `,${utils_1.newLine}`;
}
yield `}${utils_1.endOfLine}`;
}
yield `type __VLS_PublicProps = `;
if (scriptSetupRanges.defineSlots && options.vueCompilerOptions.jsxSlots) {
if (ctx.generatedPropsType) {
yield ` & `;
}
ctx.generatedPropsType = true;
yield `${ctx.localTypes.PropsChildren}<__VLS_Slots>`;
}
if (scriptSetupRanges.defineProps?.typeArg) {
if (ctx.generatedPropsType) {
yield ` & `;
}
ctx.generatedPropsType = true;
yield `__VLS_Props`;
}
if (scriptSetupRanges.defineProp.length) {
if (ctx.generatedPropsType) {
yield ` & `;
}
ctx.generatedPropsType = true;
yield `{${utils_1.newLine}`;
for (const defineProp of scriptSetupRanges.defineProp) {
const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp);
if (defineProp.comments) {
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, defineProp.comments.start, defineProp.comments.end, codeFeatures_1.codeFeatures.all);
yield utils_1.newLine;
}
if (defineProp.isModel && !defineProp.name) {
yield propName;
}
else if (defineProp.name) {
yield* (0, camelized_1.generateCamelized)(getRangeText(scriptSetup, defineProp.name), scriptSetup.name, defineProp.name.start, codeFeatures_1.codeFeatures.navigation);
}
else if (defineProp.localName) {
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, defineProp.localName.start, defineProp.localName.end, codeFeatures_1.codeFeatures.navigation);
}
else {
continue;
}
yield defineProp.required
? `: `
: `?: `;
yield* generateDefinePropType(scriptSetup, propName, localName, defineProp);
yield `,${utils_1.newLine}`;
if (defineProp.modifierType) {
const modifierName = `${defineProp.name ? propName : 'model'}Modifiers`;
const modifierType = getRangeText(scriptSetup, defineProp.modifierType);
yield `'${modifierName}'?: Partial<Record<${modifierType}, true>>,${utils_1.newLine}`;
}
}
yield `}`;
}
if (!ctx.generatedPropsType) {
yield `{}`;
}
yield utils_1.endOfLine;
}
function* generateModelEmit(scriptSetup, scriptSetupRanges) {
const defineModels = scriptSetupRanges.defineProp.filter(p => p.isModel);
if (defineModels.length) {
yield `type __VLS_ModelEmit = {${utils_1.newLine}`;
for (const defineModel of defineModels) {
const [propName, localName] = getPropAndLocalName(scriptSetup, defineModel);
yield `'update:${propName}': [value: `;
yield* generateDefinePropType(scriptSetup, propName, localName, defineModel);
if (!defineModel.required && !defineModel.defaultValue) {
yield ` | undefined`;
}
yield `]${utils_1.endOfLine}`;
}
yield `}${utils_1.endOfLine}`;
yield `const __VLS_modelEmit = defineEmits<__VLS_ModelEmit>()${utils_1.endOfLine}`;
}
}
function* generateDefinePropType(scriptSetup, propName, localName, defineProp) {
if (defineProp.type) {
// Infer from defineProp<T>
yield getRangeText(scriptSetup, defineProp.type);
}
else if (defineProp.runtimeType && localName) {
// Infer from actual prop declaration code
yield `typeof ${localName}['value']`;
}
else if (defineProp.defaultValue && propName) {
// Infer from defineProp({default: T})
yield `typeof __VLS_defaults['${propName}']`;
}
else {
yield `any`;
}
}
function getPropAndLocalName(scriptSetup, defineProp) {
const localName = defineProp.localName
? getRangeText(scriptSetup, defineProp.localName)
: undefined;
const propName = defineProp.name
? (0, shared_1.camelize)(getRangeText(scriptSetup, defineProp.name).slice(1, -1))
: defineProp.isModel
? 'modelValue'
: localName;
return [propName, localName];
}
function getRangeText(scriptSetup, range) {
return scriptSetup.content.slice(range.start, range.end);
}
//# sourceMappingURL=scriptSetup.js.map

View File

@@ -0,0 +1,2 @@
import type { Code, SfcBlockAttr } from '../../types';
export declare function generateSrc(src: SfcBlockAttr): Generator<Code>;

View File

@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSrc = generateSrc;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
function* generateSrc(src) {
if (src === true) {
return;
}
let { text } = src;
if (text.endsWith('.d.ts')) {
text = text.slice(0, -'.d.ts'.length);
}
else if (text.endsWith('.ts')) {
text = text.slice(0, -'.ts'.length);
}
else if (text.endsWith('.tsx')) {
text = text.slice(0, -'.tsx'.length) + '.jsx';
}
if (!text.endsWith('.js') && !text.endsWith('.jsx')) {
text = text + '.js';
}
yield `export * from `;
yield* (0, utils_1.generateSfcBlockAttrValue)(src, text, {
...codeFeatures_1.codeFeatures.all,
navigation: text === src.text
? true
: {
shouldRename: () => false,
resolveRenameEditText(newName) {
if (newName.endsWith('.jsx') || newName.endsWith('.js')) {
newName = newName.split('.').slice(0, -1).join('.');
}
if (src?.text.endsWith('.d.ts')) {
newName = newName + '.d.ts';
}
else if (src?.text.endsWith('.ts')) {
newName = newName + '.ts';
}
else if (src?.text.endsWith('.tsx')) {
newName = newName + '.tsx';
}
return newName;
},
},
});
yield utils_1.endOfLine;
yield `export { default } from '${text}'${utils_1.endOfLine}`;
}
//# sourceMappingURL=src.js.map

View File

@@ -0,0 +1,7 @@
import type { Code } from '../../types';
import { type TemplateCodegenContext } from '../template/context';
import type { ScriptCodegenContext } from './context';
import type { ScriptCodegenOptions } from './index';
export declare function generateTemplate(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Generator<Code, TemplateCodegenContext>;
export declare function generateTemplateDirectives(options: ScriptCodegenOptions): Generator<Code>;
export declare function getTemplateUsageVars(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Set<string>;

View File

@@ -0,0 +1,148 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplate = generateTemplate;
exports.generateTemplateDirectives = generateTemplateDirectives;
exports.getTemplateUsageVars = getTemplateUsageVars;
const shared_1 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const modules_1 = require("../style/modules");
const scopedClasses_1 = require("../style/scopedClasses");
const context_1 = require("../template/context");
const interpolation_1 = require("../template/interpolation");
const styleScopedClasses_1 = require("../template/styleScopedClasses");
const utils_1 = require("../utils");
function* generateTemplate(options, ctx) {
ctx.generatedTemplate = true;
const templateCodegenCtx = (0, context_1.createTemplateCodegenContext)({
scriptSetupBindingNames: new Set(),
edited: options.edited,
});
yield* generateTemplateCtx(options);
yield* generateTemplateComponents(options);
yield* generateTemplateDirectives(options);
yield* generateTemplateBody(options, templateCodegenCtx);
return templateCodegenCtx;
}
function* generateTemplateCtx(options) {
const exps = [];
exps.push(`{} as InstanceType<__VLS_PickNotAny<typeof __VLS_self, new () => {}>>`);
if (options.vueCompilerOptions.petiteVueExtensions.some(ext => options.fileName.endsWith(ext))) {
exps.push(`globalThis`);
}
if (options.sfc.styles.some(style => style.module)) {
exps.push(`{} as __VLS_StyleModules`);
}
yield `const __VLS_ctx = `;
if (exps.length === 1) {
yield exps[0];
yield `${utils_1.endOfLine}`;
}
else {
yield `{${utils_1.newLine}`;
for (const exp of exps) {
yield `...`;
yield exp;
yield `,${utils_1.newLine}`;
}
yield `}${utils_1.endOfLine}`;
}
}
function* generateTemplateComponents(options) {
const types = [];
if (options.sfc.script && options.scriptRanges?.exportDefault?.componentsOption) {
const { componentsOption } = options.scriptRanges.exportDefault;
yield `const __VLS_componentsOption = `;
yield [
options.sfc.script.content.slice(componentsOption.start, componentsOption.end),
'script',
componentsOption.start,
codeFeatures_1.codeFeatures.navigation,
];
yield utils_1.endOfLine;
types.push(`typeof __VLS_componentsOption`);
}
types.push(`typeof __VLS_ctx`);
yield `type __VLS_LocalComponents =`;
for (const type of types) {
yield ` & `;
yield type;
}
yield utils_1.endOfLine;
yield `let __VLS_components!: __VLS_LocalComponents & __VLS_GlobalComponents${utils_1.endOfLine}`;
}
function* generateTemplateDirectives(options) {
const types = [];
if (options.sfc.script && options.scriptRanges?.exportDefault?.directivesOption) {
const { directivesOption } = options.scriptRanges.exportDefault;
yield `const __VLS_directivesOption = `;
yield [
options.sfc.script.content.slice(directivesOption.start, directivesOption.end),
'script',
directivesOption.start,
codeFeatures_1.codeFeatures.navigation,
];
yield utils_1.endOfLine;
types.push(`typeof __VLS_directivesOption`);
}
types.push(`typeof __VLS_ctx`);
yield `type __VLS_LocalDirectives =`;
for (const type of types) {
yield ` & `;
yield type;
}
yield utils_1.endOfLine;
yield `let __VLS_directives!: __VLS_LocalDirectives & __VLS_GlobalDirectives${utils_1.endOfLine}`;
}
function* generateTemplateBody(options, templateCodegenCtx) {
yield* (0, scopedClasses_1.generateStyleScopedClasses)(options, templateCodegenCtx);
yield* (0, styleScopedClasses_1.generateStyleScopedClassReferences)(templateCodegenCtx, true);
yield* (0, modules_1.generateStyleModules)(options);
yield* generateCssVars(options, templateCodegenCtx);
if (options.templateCodegen) {
yield* options.templateCodegen.codes;
}
else {
yield `// no template${utils_1.newLine}`;
if (!options.scriptSetupRanges?.defineSlots) {
yield `type __VLS_Slots = {}${utils_1.endOfLine}`;
}
yield `type __VLS_InheritedAttrs = {}${utils_1.endOfLine}`;
yield `type __VLS_TemplateRefs = {}${utils_1.endOfLine}`;
yield `type __VLS_RootEl = any${utils_1.endOfLine}`;
}
}
function* generateCssVars(options, ctx) {
if (!options.sfc.styles.length) {
return;
}
yield `// CSS variable injection ${utils_1.newLine}`;
for (const style of options.sfc.styles) {
for (const cssBind of style.cssVars) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, style.name, codeFeatures_1.codeFeatures.all, cssBind.text, cssBind.offset);
yield utils_1.endOfLine;
}
}
yield `// CSS variable injection end ${utils_1.newLine}`;
}
function getTemplateUsageVars(options, ctx) {
const usageVars = new Set();
const components = new Set(options.sfc.template?.ast?.components);
if (options.templateCodegen) {
// fix import components unused report
for (const varName of ctx.bindingNames) {
if (components.has(varName) || components.has((0, shared_1.hyphenateTag)(varName))) {
usageVars.add(varName);
}
}
for (const component of components) {
if (component.includes('.')) {
usageVars.add(component.split('.')[0]);
}
}
for (const [varName] of options.templateCodegen.accessExternalVariables) {
usageVars.add(varName);
}
}
return usageVars;
}
//# sourceMappingURL=template.js.map

View File

@@ -0,0 +1,2 @@
import type { Code } from '../../types';
export declare function generateClassProperty(styleIndex: number, classNameWithDot: string, offset: number, propertyType: string): Generator<Code>;

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateClassProperty = generateClassProperty;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
function* generateClassProperty(styleIndex, classNameWithDot, offset, propertyType) {
yield `${utils_1.newLine} & { `;
yield* (0, wrapWith_1.wrapWith)(offset, offset + classNameWithDot.length, 'style_' + styleIndex, codeFeatures_1.codeFeatures.navigation, `'`, [
classNameWithDot.slice(1),
'style_' + styleIndex,
offset + 1,
utils_1.combineLastMapping
], `'`);
yield `: ${propertyType}`;
yield ` }`;
}
//# sourceMappingURL=classProperty.js.map

View File

@@ -0,0 +1,3 @@
import type { Code } from '../../types';
import type { ScriptCodegenOptions } from '../script';
export declare function generateStyleModules(options: ScriptCodegenOptions): Generator<Code>;

View File

@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleModules = generateStyleModules;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const classProperty_1 = require("./classProperty");
function* generateStyleModules(options) {
const styles = options.sfc.styles.map((style, i) => [style, i]).filter(([style]) => style.module);
if (!styles.length && !options.scriptSetupRanges?.useCssModule.length) {
return;
}
yield `type __VLS_StyleModules = {${utils_1.newLine}`;
for (const [style, i] of styles) {
if (style.module === true) {
yield `$style`;
}
else {
const { text, offset } = style.module;
yield [
text,
'main',
offset,
codeFeatures_1.codeFeatures.withoutHighlight
];
}
yield `: Record<string, string> & __VLS_PrettifyGlobal<{}`;
for (const className of style.classNames) {
yield* (0, classProperty_1.generateClassProperty)(i, className.text, className.offset, 'string');
}
yield `>${utils_1.endOfLine}`;
}
yield `}${utils_1.endOfLine}`;
}
//# sourceMappingURL=modules.js.map

View File

@@ -0,0 +1,4 @@
import type { Code } from '../../types';
import type { ScriptCodegenOptions } from '../script';
import type { TemplateCodegenContext } from '../template/context';
export declare function generateStyleScopedClasses(options: ScriptCodegenOptions, ctx: TemplateCodegenContext): Generator<Code>;

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleScopedClasses = generateStyleScopedClasses;
const utils_1 = require("../utils");
const classProperty_1 = require("./classProperty");
function* generateStyleScopedClasses(options, ctx) {
const option = options.vueCompilerOptions.experimentalResolveStyleCssClasses;
const styles = options.sfc.styles
.map((style, i) => [style, i])
.filter(([style]) => option === 'always' || (option === 'scoped' && style.scoped));
if (!styles.length) {
return;
}
const firstClasses = new Set();
yield `type __VLS_StyleScopedClasses = {}`;
for (const [style, i] of styles) {
for (const className of style.classNames) {
if (firstClasses.has(className.text)) {
ctx.scopedClasses.push({
source: 'style_' + i,
className: className.text.slice(1),
offset: className.offset + 1
});
continue;
}
firstClasses.add(className.text);
yield* (0, classProperty_1.generateClassProperty)(i, className.text, className.offset, 'boolean');
}
}
yield utils_1.endOfLine;
}
//# sourceMappingURL=scopedClasses.js.map

View File

@@ -0,0 +1,172 @@
import type * as CompilerDOM from '@vue/compiler-dom';
import type { Code, VueCodeInformation } from '../../types';
import { InlayHintInfo } from '../inlayHints';
import type { TemplateCodegenOptions } from './index';
export type TemplateCodegenContext = ReturnType<typeof createTemplateCodegenContext>;
/**
* Creates and returns a Context object used for generating type-checkable TS code
* from the template section of a .vue file.
*
* ## Implementation Notes for supporting `@vue-ignore`, `@vue-expect-error`, and `@vue-skip` directives.
*
* Vue language tooling supports a number of directives for suppressing diagnostics within
* Vue templates (https://github.com/vuejs/language-tools/pull/3215)
*
* Here is an overview for how support for how @vue-expect-error is implemented within this file
* (@vue-expect-error is the most complicated directive to support due to its behavior of raising
* a diagnostic when it is annotating a piece of code that doesn't actually have any errors/warning/diagnostics).
*
* Given .vue code:
*
* ```vue
* <script setup lang="ts">
* defineProps<{
* knownProp1: string;
* knownProp2: string;
* knownProp3: string;
* knownProp4_will_trigger_unused_expect_error: string;
* }>();
* </script>
*
* <template>
* {{ knownProp1 }}
* {{ error_unknownProp }} <!-- ERROR: Property 'error_unknownProp' does not exist on type [...] -->
* {{ knownProp2 }}
* <!-- @vue-expect-error This suppresses an Unknown Property Error -->
* {{ suppressed_error_unknownProp }}
* {{ knownProp3 }}
* <!-- @vue-expect-error This will trigger Unused '@ts-expect-error' directive.ts(2578) -->
* {{ knownProp4_will_trigger_unused_expect_error }}
* </template>
* ```
*
* The above code should raise two diagnostics:
*
* 1. Property 'error_unknownProp' does not exist on type [...]
* 2. Unused '@ts-expect-error' directive.ts(2578) -- this is the bottom `@vue-expect-error` directive
* that covers code that doesn't actually raise an error -- note that all `@vue-...` directives
* will ultimately translate into `@ts-...` diagnostics.
*
* The above code will produce the following type-checkable TS code (note: omitting asterisks
* to prevent VSCode syntax double-greying out double-commented code).
*
* ```ts
* ( __VLS_ctx.knownProp1 );
* ( __VLS_ctx.error_unknownProp ); // ERROR: Property 'error_unknownProp' does not exist on type [...]
* ( __VLS_ctx.knownProp2 );
* // @vue-expect-error start
* ( __VLS_ctx.suppressed_error_unknownProp );
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
* ;
* // @vue-expect-error end of INTERPOLATION
* ( __VLS_ctx.knownProp3 );
* // @vue-expect-error start
* ( __VLS_ctx.knownProp4_will_trigger_unused_expect_error );
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
* ;
* // @vue-expect-error end of INTERPOLATION
* ```
*
* In the generated code, there are actually 3 diagnostic errors that'll be raised in the first
* pass on this generated code (but through cleverness described below, not all of them will be
* propagated back to the original .vue file):
*
* 1. Property 'error_unknownProp' does not exist on type [...]
* 2. Unused '@ts-expect-error' directive.ts(2578) from the 1st `@ts-expect-error __VLS_TS_EXPECT_ERROR`
* 3. Unused '@ts-expect-error' directive.ts(2578) from the 2nd `@ts-expect-error __VLS_TS_EXPECT_ERROR`
*
* Be sure to pay careful attention to the mixture of `@vue-expect-error` and `@ts-expect-error`;
* Within the TS file, the only "real" directives recognized by TS are going to be prefixed with `@ts-`;
* any `@vue-` prefixed directives in the comments are only for debugging purposes.
*
* As mentioned above, there are 3 diagnostics errors that'll be generated for the above code, but
* only 2 should be propagated back to the original .vue file.
*
* (The reason we structure things this way is somewhat complicated, but in short it allows us
* to lean on TS as much as possible to generate actual `unused @ts-expect-error directive` errors
* while covering a number of edge cases.)
*
* So, we need a way to dynamically decide whether each of the `@ts-expect-error __VLS_TS_EXPECT_ERROR`
* directives should be reported as an unused directive or not.
*
* To do this, we'll make use of the `shouldReport` callback that'll optionally be provided to the
* `verification` property of the `CodeInformation` object attached to the mapping between source .vue
* and generated .ts code. The `verification` property determines whether "verification" (which includes
* semantic diagnostics) should be performed on the generated .ts code, and `shouldReport`, if provided,
* can be used to determine whether a given diagnostic should be reported back "upwards" to the original
* .vue file or not.
*
* See the comments in the code below for how and where we use this hook to keep track of whether
* an error/diagnostic was encountered for a region of code covered by a `@vue-expect-error` directive,
* and additionally how we use that to determine whether to propagate diagnostics back upward.
*/
export declare function createTemplateCodegenContext(options: Pick<TemplateCodegenOptions, 'scriptSetupBindingNames' | 'edited'>): {
codeFeatures: {
all: VueCodeInformation;
none: VueCodeInformation;
verification: VueCodeInformation;
completion: VueCodeInformation;
additionalCompletion: VueCodeInformation;
withoutCompletion: VueCodeInformation;
navigation: VueCodeInformation;
navigationWithoutRename: VueCodeInformation;
navigationAndCompletion: VueCodeInformation;
navigationAndAdditionalCompletion: VueCodeInformation;
navigationAndVerification: VueCodeInformation;
withoutNavigation: VueCodeInformation;
withoutHighlight: VueCodeInformation;
withoutHighlightAndNavigation: VueCodeInformation;
withoutHighlightAndCompletion: VueCodeInformation;
withoutHighlightAndCompletionAndNavigation: VueCodeInformation;
};
resolveCodeFeatures: (features: VueCodeInformation) => VueCodeInformation;
slots: {
name: string;
offset?: number;
tagRange: [number, number];
nodeLoc: any;
propsVar: string;
}[];
dynamicSlots: {
expVar: string;
propsVar: string;
}[];
dollarVars: Set<string>;
accessExternalVariables: Map<string, Set<number>>;
lastGenericComment: {
content: string;
offset: number;
} | undefined;
blockConditions: string[];
scopedClasses: {
source: string;
className: string;
offset: number;
}[];
emptyClassOffsets: number[];
inlayHints: InlayHintInfo[];
bindingAttrLocs: CompilerDOM.SourceLocation[];
inheritedAttrVars: Set<string>;
templateRefs: Map<string, {
typeExp: string;
offset: number;
}>;
currentComponent: {
ctxVar: string;
used: boolean;
} | undefined;
singleRootElTypes: string[];
singleRootNodes: Set<CompilerDOM.ElementNode | null>;
accessExternalVariable(name: string, offset?: number): void;
hasLocalVariable: (name: string) => boolean;
addLocalVariable: (name: string) => void;
removeLocalVariable: (name: string) => void;
getInternalVariable: () => string;
getHoistVariable: (originalVar: string) => string;
generateHoistVariables: () => Generator<string, void, unknown>;
generateConditionGuards: () => Generator<string, void, unknown>;
ignoreError: () => Generator<Code>;
expectError: (prevNode: CompilerDOM.CommentNode) => Generator<Code>;
resetDirectiveComments: (endStr: string) => Generator<Code>;
generateAutoImportCompletion: () => Generator<Code>;
};

View File

@@ -0,0 +1,293 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTemplateCodegenContext = createTemplateCodegenContext;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
/**
* Creates and returns a Context object used for generating type-checkable TS code
* from the template section of a .vue file.
*
* ## Implementation Notes for supporting `@vue-ignore`, `@vue-expect-error`, and `@vue-skip` directives.
*
* Vue language tooling supports a number of directives for suppressing diagnostics within
* Vue templates (https://github.com/vuejs/language-tools/pull/3215)
*
* Here is an overview for how support for how @vue-expect-error is implemented within this file
* (@vue-expect-error is the most complicated directive to support due to its behavior of raising
* a diagnostic when it is annotating a piece of code that doesn't actually have any errors/warning/diagnostics).
*
* Given .vue code:
*
* ```vue
* <script setup lang="ts">
* defineProps<{
* knownProp1: string;
* knownProp2: string;
* knownProp3: string;
* knownProp4_will_trigger_unused_expect_error: string;
* }>();
* </script>
*
* <template>
* {{ knownProp1 }}
* {{ error_unknownProp }} <!-- ERROR: Property 'error_unknownProp' does not exist on type [...] -->
* {{ knownProp2 }}
* <!-- @vue-expect-error This suppresses an Unknown Property Error -->
* {{ suppressed_error_unknownProp }}
* {{ knownProp3 }}
* <!-- @vue-expect-error This will trigger Unused '@ts-expect-error' directive.ts(2578) -->
* {{ knownProp4_will_trigger_unused_expect_error }}
* </template>
* ```
*
* The above code should raise two diagnostics:
*
* 1. Property 'error_unknownProp' does not exist on type [...]
* 2. Unused '@ts-expect-error' directive.ts(2578) -- this is the bottom `@vue-expect-error` directive
* that covers code that doesn't actually raise an error -- note that all `@vue-...` directives
* will ultimately translate into `@ts-...` diagnostics.
*
* The above code will produce the following type-checkable TS code (note: omitting asterisks
* to prevent VSCode syntax double-greying out double-commented code).
*
* ```ts
* ( __VLS_ctx.knownProp1 );
* ( __VLS_ctx.error_unknownProp ); // ERROR: Property 'error_unknownProp' does not exist on type [...]
* ( __VLS_ctx.knownProp2 );
* // @vue-expect-error start
* ( __VLS_ctx.suppressed_error_unknownProp );
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
* ;
* // @vue-expect-error end of INTERPOLATION
* ( __VLS_ctx.knownProp3 );
* // @vue-expect-error start
* ( __VLS_ctx.knownProp4_will_trigger_unused_expect_error );
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
* ;
* // @vue-expect-error end of INTERPOLATION
* ```
*
* In the generated code, there are actually 3 diagnostic errors that'll be raised in the first
* pass on this generated code (but through cleverness described below, not all of them will be
* propagated back to the original .vue file):
*
* 1. Property 'error_unknownProp' does not exist on type [...]
* 2. Unused '@ts-expect-error' directive.ts(2578) from the 1st `@ts-expect-error __VLS_TS_EXPECT_ERROR`
* 3. Unused '@ts-expect-error' directive.ts(2578) from the 2nd `@ts-expect-error __VLS_TS_EXPECT_ERROR`
*
* Be sure to pay careful attention to the mixture of `@vue-expect-error` and `@ts-expect-error`;
* Within the TS file, the only "real" directives recognized by TS are going to be prefixed with `@ts-`;
* any `@vue-` prefixed directives in the comments are only for debugging purposes.
*
* As mentioned above, there are 3 diagnostics errors that'll be generated for the above code, but
* only 2 should be propagated back to the original .vue file.
*
* (The reason we structure things this way is somewhat complicated, but in short it allows us
* to lean on TS as much as possible to generate actual `unused @ts-expect-error directive` errors
* while covering a number of edge cases.)
*
* So, we need a way to dynamically decide whether each of the `@ts-expect-error __VLS_TS_EXPECT_ERROR`
* directives should be reported as an unused directive or not.
*
* To do this, we'll make use of the `shouldReport` callback that'll optionally be provided to the
* `verification` property of the `CodeInformation` object attached to the mapping between source .vue
* and generated .ts code. The `verification` property determines whether "verification" (which includes
* semantic diagnostics) should be performed on the generated .ts code, and `shouldReport`, if provided,
* can be used to determine whether a given diagnostic should be reported back "upwards" to the original
* .vue file or not.
*
* See the comments in the code below for how and where we use this hook to keep track of whether
* an error/diagnostic was encountered for a region of code covered by a `@vue-expect-error` directive,
* and additionally how we use that to determine whether to propagate diagnostics back upward.
*/
function createTemplateCodegenContext(options) {
let ignoredError = false;
let expectErrorToken;
let lastGenericComment;
let variableId = 0;
function resolveCodeFeatures(features) {
if (features.verification) {
if (ignoredError) {
// We are currently in a region of code covered by a @vue-ignore directive, so don't
// even bother performing any type-checking: set verification to false.
return {
...features,
verification: false,
};
}
if (expectErrorToken) {
// We are currently in a region of code covered by a @vue-expect-error directive. We need to
// keep track of the number of errors encountered within this region so that we can know whether
// we will need to propagate an "unused ts-expect-error" diagnostic back to the original
// .vue file or not.
const token = expectErrorToken;
return {
...features,
verification: {
shouldReport: () => {
token.errors++;
return false;
},
},
};
}
}
return features;
}
const hoistVars = new Map();
const localVars = new Map();
const dollarVars = new Set();
const accessExternalVariables = new Map();
const slots = [];
const dynamicSlots = [];
const blockConditions = [];
const scopedClasses = [];
const emptyClassOffsets = [];
const inlayHints = [];
const bindingAttrLocs = [];
const inheritedAttrVars = new Set();
const templateRefs = new Map();
return {
codeFeatures: new Proxy(codeFeatures_1.codeFeatures, {
get(target, key) {
const data = target[key];
return resolveCodeFeatures(data);
},
}),
resolveCodeFeatures,
slots,
dynamicSlots,
dollarVars,
accessExternalVariables,
lastGenericComment,
blockConditions,
scopedClasses,
emptyClassOffsets,
inlayHints,
bindingAttrLocs,
inheritedAttrVars,
templateRefs,
currentComponent: undefined,
singleRootElTypes: [],
singleRootNodes: new Set(),
accessExternalVariable(name, offset) {
let arr = accessExternalVariables.get(name);
if (!arr) {
accessExternalVariables.set(name, arr = new Set());
}
if (offset !== undefined) {
arr.add(offset);
}
},
hasLocalVariable: (name) => {
return !!localVars.get(name);
},
addLocalVariable: (name) => {
localVars.set(name, (localVars.get(name) ?? 0) + 1);
},
removeLocalVariable: (name) => {
localVars.set(name, localVars.get(name) - 1);
},
getInternalVariable: () => {
return `__VLS_${variableId++}`;
},
getHoistVariable: (originalVar) => {
let name = hoistVars.get(originalVar);
if (name === undefined) {
hoistVars.set(originalVar, name = `__VLS_${variableId++}`);
}
return name;
},
generateHoistVariables: function* () {
// trick to avoid TS 4081 (#5186)
if (hoistVars.size) {
yield `// @ts-ignore${utils_1.newLine}`;
yield `var `;
for (const [originalVar, hoistVar] of hoistVars) {
yield `${hoistVar} = ${originalVar}, `;
}
yield utils_1.endOfLine;
}
},
generateConditionGuards: function* () {
for (const condition of blockConditions) {
yield `if (!${condition}) return${utils_1.endOfLine}`;
}
},
ignoreError: function* () {
if (!ignoredError) {
ignoredError = true;
yield `// @vue-ignore start${utils_1.newLine}`;
}
},
expectError: function* (prevNode) {
if (!expectErrorToken) {
expectErrorToken = {
errors: 0,
node: prevNode,
};
yield `// @vue-expect-error start${utils_1.newLine}`;
}
},
resetDirectiveComments: function* (endStr) {
if (expectErrorToken) {
const token = expectErrorToken;
yield* (0, wrapWith_1.wrapWith)(expectErrorToken.node.loc.start.offset, expectErrorToken.node.loc.end.offset, {
verification: {
// If no errors/warnings/diagnostics were reported within the region of code covered
// by the @vue-expect-error directive, then we should allow any `unused @ts-expect-error`
// diagnostics to be reported upward.
shouldReport: () => token.errors === 0,
},
}, `// @ts-expect-error __VLS_TS_EXPECT_ERROR`);
yield `${utils_1.newLine}${utils_1.endOfLine}`;
expectErrorToken = undefined;
yield `// @vue-expect-error ${endStr}${utils_1.newLine}`;
}
if (ignoredError) {
ignoredError = false;
yield `// @vue-ignore ${endStr}${utils_1.newLine}`;
}
},
generateAutoImportCompletion: function* () {
if (!options.edited) {
return;
}
const all = [...accessExternalVariables.entries()];
if (!all.some(([_, offsets]) => offsets.size)) {
return;
}
yield `// @ts-ignore${utils_1.newLine}`; // #2304
yield `[`;
for (const [varName, offsets] of all) {
for (const offset of offsets) {
if (options.scriptSetupBindingNames.has(varName)) {
// #3409
yield [
varName,
'template',
offset,
{
...codeFeatures_1.codeFeatures.additionalCompletion,
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletionAndNavigation,
},
];
}
else {
yield [
varName,
'template',
offset,
codeFeatures_1.codeFeatures.additionalCompletion,
];
}
yield `,`;
}
offsets.clear();
}
yield `]${utils_1.endOfLine}`;
}
};
}
//# sourceMappingURL=context.js.map

View File

@@ -0,0 +1,6 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateComponent(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, isVForChild: boolean): Generator<Code>;
export declare function generateElement(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, isVForChild: boolean): Generator<Code>;

View File

@@ -0,0 +1,328 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateComponent = generateComponent;
exports.generateElement = generateElement;
const CompilerDOM = require("@vue/compiler-dom");
const shared_1 = require("@vue/shared");
const shared_2 = require("../../utils/shared");
const inlayHints_1 = require("../inlayHints");
const utils_1 = require("../utils");
const camelized_1 = require("../utils/camelized");
const wrapWith_1 = require("../utils/wrapWith");
const elementChildren_1 = require("./elementChildren");
const elementDirectives_1 = require("./elementDirectives");
const elementEvents_1 = require("./elementEvents");
const elementProps_1 = require("./elementProps");
const interpolation_1 = require("./interpolation");
const propertyAccess_1 = require("./propertyAccess");
const styleScopedClasses_1 = require("./styleScopedClasses");
const vSlot_1 = require("./vSlot");
const colonReg = /:/g;
function* generateComponent(options, ctx, node, isVForChild) {
const tagOffsets = [node.loc.start.offset + options.template.content.slice(node.loc.start.offset).indexOf(node.tag)];
if (!node.isSelfClosing && options.template.lang === 'html') {
const endTagOffset = node.loc.start.offset + node.loc.source.lastIndexOf(node.tag);
if (endTagOffset > tagOffsets[0]) {
tagOffsets.push(endTagOffset);
}
}
const failedPropExps = [];
const possibleOriginalNames = getPossibleOriginalComponentNames(node.tag, true);
const matchImportName = possibleOriginalNames.find(name => options.scriptSetupImportComponentNames.has(name));
const componentOriginalVar = matchImportName ?? ctx.getInternalVariable();
const componentFunctionalVar = ctx.getInternalVariable();
const componentVNodeVar = ctx.getInternalVariable();
const componentCtxVar = ctx.getInternalVariable();
const isComponentTag = node.tag.toLowerCase() === 'component';
ctx.currentComponent = {
ctxVar: componentCtxVar,
used: false
};
let props = node.props;
let dynamicTagInfo;
if (isComponentTag) {
for (const prop of node.props) {
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'bind'
&& prop.arg?.loc.source === 'is'
&& prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
if (prop.arg.loc.end.offset === prop.exp.loc.end.offset) {
ctx.inlayHints.push((0, inlayHints_1.createVBindShorthandInlayHintInfo)(prop.exp.loc, 'is'));
}
dynamicTagInfo = {
tag: prop.exp.content,
offsets: [prop.exp.loc.start.offset],
astHolder: prop.exp.loc,
};
props = props.filter(p => p !== prop);
break;
}
}
}
else if (node.tag.includes('.')) {
// namespace tag
dynamicTagInfo = {
tag: node.tag,
offsets: tagOffsets,
astHolder: node.loc,
};
}
if (matchImportName) {
// navigation support
yield `/** @type {[`;
for (const tagOffset of tagOffsets) {
yield `typeof `;
if (componentOriginalVar === node.tag) {
yield [
componentOriginalVar,
'template',
tagOffset,
ctx.codeFeatures.withoutHighlightAndCompletion,
];
}
else {
const shouldCapitalize = matchImportName[0].toUpperCase() === matchImportName[0];
yield* (0, camelized_1.generateCamelized)(shouldCapitalize ? (0, shared_1.capitalize)(node.tag) : node.tag, 'template', tagOffset, {
...ctx.codeFeatures.withoutHighlightAndCompletion,
navigation: {
resolveRenameNewName: camelizeComponentName,
resolveRenameEditText: getTagRenameApply(node.tag),
},
});
}
yield `, `;
}
yield `]} */${utils_1.endOfLine}`;
}
else if (dynamicTagInfo) {
yield `const ${componentOriginalVar} = (`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, dynamicTagInfo.tag, dynamicTagInfo.offsets[0], dynamicTagInfo.astHolder, `(`, `)`);
if (dynamicTagInfo.offsets[1] !== undefined) {
yield `,`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.withoutCompletion, dynamicTagInfo.tag, dynamicTagInfo.offsets[1], dynamicTagInfo.astHolder, `(`, `)`);
}
yield `)${utils_1.endOfLine}`;
}
else if (!isComponentTag) {
yield `const ${componentOriginalVar} = ({} as __VLS_WithComponent<'${getCanonicalComponentName(node.tag)}', __VLS_LocalComponents, `;
if (options.selfComponentName && possibleOriginalNames.includes(options.selfComponentName)) {
yield `typeof __VLS_self & (new () => { `
+ (0, shared_2.getSlotsPropertyName)(options.vueCompilerOptions.target)
+ `: __VLS_Slots }), `;
}
else {
yield `void, `;
}
yield getPossibleOriginalComponentNames(node.tag, false)
.map(name => `'${name}'`)
.join(`, `);
yield `>).`;
yield* generateCanonicalComponentName(node.tag, tagOffsets[0], ctx.codeFeatures.withoutHighlightAndCompletionAndNavigation);
yield `${utils_1.endOfLine}`;
const camelizedTag = (0, shared_1.camelize)(node.tag);
if (utils_1.identifierRegex.test(camelizedTag)) {
// navigation support
yield `/** @type {[`;
for (const tagOffset of tagOffsets) {
for (const shouldCapitalize of (node.tag[0] === node.tag[0].toUpperCase() ? [false] : [true, false])) {
const expectName = shouldCapitalize ? (0, shared_1.capitalize)(camelizedTag) : camelizedTag;
yield `typeof __VLS_components.`;
yield* (0, camelized_1.generateCamelized)(shouldCapitalize ? (0, shared_1.capitalize)(node.tag) : node.tag, 'template', tagOffset, {
navigation: {
resolveRenameNewName: node.tag !== expectName ? camelizeComponentName : undefined,
resolveRenameEditText: getTagRenameApply(node.tag),
},
});
yield `, `;
}
}
yield `]} */${utils_1.endOfLine}`;
// auto import support
if (options.edited) {
yield `// @ts-ignore${utils_1.newLine}`; // #2304
yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(node.tag), 'template', tagOffsets[0], {
completion: {
isAdditional: true,
onlyImport: true,
},
});
yield `${utils_1.endOfLine}`;
}
}
}
else {
yield `const ${componentOriginalVar} = {} as any${utils_1.endOfLine}`;
}
yield `// @ts-ignore${utils_1.newLine}`;
yield `const ${componentFunctionalVar} = __VLS_asFunctionalComponent(${componentOriginalVar}, new ${componentOriginalVar}({${utils_1.newLine}`;
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, props, options.vueCompilerOptions.checkUnknownProps, false);
yield `}))${utils_1.endOfLine}`;
yield `const `;
yield* (0, wrapWith_1.wrapWith)(node.loc.start.offset, node.loc.end.offset, ctx.resolveCodeFeatures({
verification: {
shouldReport(_source, code) {
// https://typescript.tv/errors/#ts6133
return String(code) !== '6133';
},
}
}), componentVNodeVar);
yield ` = ${componentFunctionalVar}`;
yield* generateComponentGeneric(ctx);
yield `(`;
yield* (0, wrapWith_1.wrapWith)(tagOffsets[0], tagOffsets[0] + node.tag.length, ctx.codeFeatures.verification, `{${utils_1.newLine}`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, props, options.vueCompilerOptions.checkUnknownProps, true, failedPropExps), `}`);
yield `, ...__VLS_functionalComponentArgsRest(${componentFunctionalVar}))${utils_1.endOfLine}`;
yield* generateFailedPropExps(options, ctx, failedPropExps);
yield* (0, elementEvents_1.generateElementEvents)(options, ctx, node, componentFunctionalVar, componentVNodeVar, componentCtxVar);
yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node);
const [refName, offset] = yield* generateElementReference(options, ctx, node);
const tag = (0, shared_2.hyphenateTag)(node.tag);
const isRootNode = ctx.singleRootNodes.has(node) && !options.vueCompilerOptions.fallthroughComponentNames.includes(tag);
if (refName || isRootNode) {
const componentInstanceVar = ctx.getInternalVariable();
ctx.currentComponent.used = true;
yield `var ${componentInstanceVar} = {} as (Parameters<NonNullable<typeof ${componentCtxVar}['expose']>>[0] | null)`;
if (isVForChild) {
yield `[]`;
}
yield `${utils_1.endOfLine}`;
if (refName && offset) {
ctx.templateRefs.set(refName, {
typeExp: `typeof ${ctx.getHoistVariable(componentInstanceVar)}`,
offset
});
}
if (isRootNode) {
ctx.singleRootElTypes.push(`NonNullable<typeof ${componentInstanceVar}>['$el']`);
}
}
if (hasVBindAttrs(options, ctx, node)) {
const attrsVar = ctx.getInternalVariable();
yield `let ${attrsVar}!: Parameters<typeof ${componentFunctionalVar}>[0]${utils_1.endOfLine}`;
ctx.inheritedAttrVars.add(attrsVar);
}
(0, styleScopedClasses_1.collectStyleScopedClassReferences)(options, ctx, node);
const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot');
if (slotDir) {
yield* (0, vSlot_1.generateVSlot)(options, ctx, node, slotDir);
}
else {
// #932: reference for default slot
yield* (0, vSlot_1.generateImplicitDefaultSlot)(ctx, node);
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node);
}
if (ctx.currentComponent.used) {
yield `var ${componentCtxVar}!: __VLS_PickFunctionalComponentCtx<typeof ${componentOriginalVar}, typeof ${componentVNodeVar}>${utils_1.endOfLine}`;
}
}
function* generateElement(options, ctx, node, isVForChild) {
const startTagOffset = node.loc.start.offset + options.template.content.slice(node.loc.start.offset).indexOf(node.tag);
const endTagOffset = !node.isSelfClosing && options.template.lang === 'html'
? node.loc.start.offset + node.loc.source.lastIndexOf(node.tag)
: undefined;
const failedPropExps = [];
yield `__VLS_asFunctionalElement(__VLS_intrinsicElements`;
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, node.tag, startTagOffset, ctx.codeFeatures.withoutHighlightAndCompletion);
if (endTagOffset !== undefined) {
yield `, __VLS_intrinsicElements`;
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, node.tag, endTagOffset, ctx.codeFeatures.withoutHighlightAndCompletion);
}
yield `)(`;
yield* (0, wrapWith_1.wrapWith)(startTagOffset, startTagOffset + node.tag.length, ctx.codeFeatures.verification, `{${utils_1.newLine}`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, node.props, options.vueCompilerOptions.checkUnknownProps, true, failedPropExps), `}`);
yield `)${utils_1.endOfLine}`;
yield* generateFailedPropExps(options, ctx, failedPropExps);
yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node);
const [refName, offset] = yield* generateElementReference(options, ctx, node);
if (refName && offset) {
let typeExp = `__VLS_NativeElements['${node.tag}']`;
if (isVForChild) {
typeExp += `[]`;
}
ctx.templateRefs.set(refName, {
typeExp,
offset
});
}
if (ctx.singleRootNodes.has(node)) {
ctx.singleRootElTypes.push(`__VLS_NativeElements['${node.tag}']`);
}
if (hasVBindAttrs(options, ctx, node)) {
ctx.inheritedAttrVars.add(`__VLS_intrinsicElements.${node.tag}`);
}
(0, styleScopedClasses_1.collectStyleScopedClassReferences)(options, ctx, node);
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node);
}
function* generateFailedPropExps(options, ctx, failedPropExps) {
for (const failedExp of failedPropExps) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, failedExp.node.loc.source, failedExp.node.loc.start.offset, failedExp.node.loc, failedExp.prefix, failedExp.suffix);
yield utils_1.endOfLine;
}
}
function getCanonicalComponentName(tagText) {
return utils_1.identifierRegex.test(tagText)
? tagText
: (0, shared_1.capitalize)((0, shared_1.camelize)(tagText.replace(colonReg, '-')));
}
function getPossibleOriginalComponentNames(tagText, deduplicate) {
const name1 = (0, shared_1.capitalize)((0, shared_1.camelize)(tagText));
const name2 = (0, shared_1.camelize)(tagText);
const name3 = tagText;
const names = [name1];
if (!deduplicate || name2 !== name1) {
names.push(name2);
}
if (!deduplicate || name3 !== name2) {
names.push(name3);
}
return names;
}
function* generateCanonicalComponentName(tagText, offset, features) {
if (utils_1.identifierRegex.test(tagText)) {
yield [tagText, 'template', offset, features];
}
else {
yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(tagText.replace(colonReg, '-')), 'template', offset, features);
}
}
function* generateComponentGeneric(ctx) {
if (ctx.lastGenericComment) {
const { content, offset } = ctx.lastGenericComment;
yield* (0, wrapWith_1.wrapWith)(offset, offset + content.length, ctx.codeFeatures.verification, `<`, [
content,
'template',
offset,
ctx.codeFeatures.all
], `>`);
}
ctx.lastGenericComment = undefined;
}
function* generateElementReference(options, ctx, node) {
for (const prop of node.props) {
if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE
&& prop.name === 'ref'
&& prop.value) {
const [content, startOffset] = (0, utils_1.normalizeAttributeValue)(prop.value);
// navigation support for `const foo = ref()`
yield `/** @type {typeof __VLS_ctx`;
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, content, startOffset, ctx.codeFeatures.navigation, prop.value.loc);
yield `} */${utils_1.endOfLine}`;
if (utils_1.identifierRegex.test(content) && !options.templateRefNames.has(content)) {
ctx.accessExternalVariable(content, startOffset);
}
return [content, startOffset];
}
}
return [];
}
function hasVBindAttrs(options, ctx, node) {
return options.vueCompilerOptions.fallthroughAttributes && ((options.inheritAttrs && ctx.singleRootNodes.has(node)) ||
node.props.some(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'bind'
&& prop.exp?.loc.source === '$attrs'));
}
function camelizeComponentName(newName) {
return (0, shared_1.camelize)('-' + newName);
}
function getTagRenameApply(oldName) {
return oldName === (0, shared_2.hyphenateTag)(oldName) ? shared_2.hyphenateTag : undefined;
}
//# sourceMappingURL=element.js.map

View File

@@ -0,0 +1,5 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateElementChildren(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementChildren = generateElementChildren;
const templateChild_1 = require("./templateChild");
function* generateElementChildren(options, ctx, node) {
yield* ctx.resetDirectiveComments('end of element children start');
let prev;
for (const childNode of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, childNode, prev);
prev = childNode;
}
yield* ctx.generateAutoImportCompletion();
}
//# sourceMappingURL=elementChildren.js.map

View File

@@ -0,0 +1,6 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateElementDirectives(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;
export declare function generateModifiers(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, prop: CompilerDOM.DirectiveNode, propertyName?: string): Generator<Code>;

View File

@@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementDirectives = generateElementDirectives;
exports.generateModifiers = generateModifiers;
const CompilerDOM = require("@vue/compiler-dom");
const shared_1 = require("@vue/shared");
const shared_2 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const camelized_1 = require("../utils/camelized");
const stringLiteralKey_1 = require("../utils/stringLiteralKey");
const wrapWith_1 = require("../utils/wrapWith");
const elementProps_1 = require("./elementProps");
const interpolation_1 = require("./interpolation");
const objectProperty_1 = require("./objectProperty");
const builtInDirectives = new Set([
'cloak',
'html',
'memo',
'once',
'show',
'text',
]);
function* generateElementDirectives(options, ctx, node) {
for (const prop of node.props) {
if (prop.type !== CompilerDOM.NodeTypes.DIRECTIVE
|| prop.name === 'slot'
|| prop.name === 'on'
|| prop.name === 'model'
|| prop.name === 'bind'
|| prop.name === 'scope'
|| prop.name === 'data') {
continue;
}
ctx.accessExternalVariable((0, shared_1.camelize)('v-' + prop.name), prop.loc.start.offset);
yield* (0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, ctx.codeFeatures.verification, `__VLS_asFunctionalDirective(`, ...generateIdentifier(options, ctx, prop), `)(null!, { ...__VLS_directiveBindingRestFields, `, ...generateArg(options, ctx, prop), ...generateModifiers(options, ctx, prop), ...generateValue(options, ctx, prop), ` }, null!, null!)`);
yield utils_1.endOfLine;
}
}
function* generateIdentifier(options, ctx, prop) {
const rawName = 'v-' + prop.name;
yield* (0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.start.offset + rawName.length, ctx.codeFeatures.verification, `__VLS_directives.`, ...(0, camelized_1.generateCamelized)(rawName, 'template', prop.loc.start.offset, ctx.resolveCodeFeatures({
...codeFeatures_1.codeFeatures.withoutHighlight,
// fix https://github.com/vuejs/language-tools/issues/1905
...codeFeatures_1.codeFeatures.additionalCompletion,
verification: options.vueCompilerOptions.checkUnknownDirectives && !builtInDirectives.has(prop.name),
navigation: {
resolveRenameNewName: shared_1.camelize,
resolveRenameEditText: getPropRenameApply(prop.name),
},
})));
}
function* generateArg(options, ctx, prop) {
const { arg } = prop;
if (arg?.type !== CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
return;
}
const startOffset = arg.loc.start.offset + arg.loc.source.indexOf(arg.content);
yield* (0, wrapWith_1.wrapWith)(startOffset, startOffset + arg.content.length, ctx.codeFeatures.verification, `arg`);
yield `: `;
if (arg.isStatic) {
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(arg.content, startOffset, ctx.codeFeatures.all);
}
else {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, arg.content, startOffset, arg.loc, `(`, `)`);
}
yield `, `;
}
function* generateModifiers(options, ctx, prop, propertyName = 'modifiers') {
const { modifiers } = prop;
if (!modifiers.length) {
return;
}
const startOffset = modifiers[0].loc.start.offset - 1;
const endOffset = modifiers.at(-1).loc.end.offset;
yield* (0, wrapWith_1.wrapWith)(startOffset, endOffset, ctx.codeFeatures.verification, propertyName);
yield `: { `;
for (const mod of modifiers) {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, mod.content, mod.loc.start.offset, ctx.codeFeatures.withoutHighlightAndNavigation);
yield `: true, `;
}
yield `}, `;
}
function* generateValue(options, ctx, prop) {
const { exp } = prop;
if (exp?.type !== CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
return;
}
yield* (0, wrapWith_1.wrapWith)(exp.loc.start.offset, exp.loc.end.offset, ctx.codeFeatures.verification, `value`);
yield `: `;
yield* (0, elementProps_1.generatePropExp)(options, ctx, prop, exp, ctx.codeFeatures.all);
}
function getPropRenameApply(oldName) {
return oldName === (0, shared_2.hyphenateAttr)(oldName) ? shared_2.hyphenateAttr : undefined;
}
//# sourceMappingURL=elementDirectives.js.map

View File

@@ -0,0 +1,9 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type * as ts from 'typescript';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateElementEvents(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, componentFunctionalVar: string, componentVNodeVar: string, componentCtxVar: string): Generator<Code>;
export declare function generateEventArg(ctx: TemplateCodegenContext, name: string, start: number, directive?: string): Generator<Code>;
export declare function generateEventExpression(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, prop: CompilerDOM.DirectiveNode): Generator<Code>;
export declare function isCompoundExpression(ts: typeof import('typescript'), ast: ts.SourceFile): boolean;

View File

@@ -0,0 +1,139 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementEvents = generateElementEvents;
exports.generateEventArg = generateEventArg;
exports.generateEventExpression = generateEventExpression;
exports.isCompoundExpression = isCompoundExpression;
const CompilerDOM = require("@vue/compiler-dom");
const shared_1 = require("@vue/shared");
const utils_1 = require("../utils");
const camelized_1 = require("../utils/camelized");
const wrapWith_1 = require("../utils/wrapWith");
const interpolation_1 = require("./interpolation");
function* generateElementEvents(options, ctx, node, componentFunctionalVar, componentVNodeVar, componentCtxVar) {
let emitVar;
let eventsVar;
let propsVar;
for (const prop of node.props) {
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'on'
&& prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& prop.arg.isStatic) {
ctx.currentComponent.used = true;
if (!emitVar) {
emitVar = ctx.getInternalVariable();
eventsVar = ctx.getInternalVariable();
propsVar = ctx.getInternalVariable();
yield `let ${emitVar}!: typeof ${componentCtxVar}.emit${utils_1.endOfLine}`;
yield `let ${eventsVar}!: __VLS_NormalizeEmits<typeof ${emitVar}>${utils_1.endOfLine}`;
yield `let ${propsVar}!: __VLS_FunctionalComponentProps<typeof ${componentFunctionalVar}, typeof ${componentVNodeVar}>${utils_1.endOfLine}`;
}
let source = prop.arg.loc.source;
let start = prop.arg.loc.start.offset;
let propPrefix = 'on';
let emitPrefix = '';
if (source.startsWith('vue:')) {
source = source.slice('vue:'.length);
start = start + 'vue:'.length;
propPrefix = 'onVnode';
emitPrefix = 'vnode-';
}
yield `const ${ctx.getInternalVariable()}: __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${eventsVar}, '${(0, shared_1.camelize)(propPrefix + '-' + source)}', '${emitPrefix}${source}', '${(0, shared_1.camelize)(emitPrefix + source)}'> = {${utils_1.newLine}`;
yield* generateEventArg(ctx, source, start, propPrefix);
yield `: `;
yield* generateEventExpression(options, ctx, prop);
yield `}${utils_1.endOfLine}`;
}
}
}
function* generateEventArg(ctx, name, start, directive = 'on') {
const features = {
...ctx.codeFeatures.withoutHighlightAndCompletion,
...ctx.codeFeatures.navigationWithoutRename,
};
if (utils_1.identifierRegex.test((0, shared_1.camelize)(name))) {
yield ['', 'template', start, features];
yield directive;
yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(name), 'template', start, utils_1.combineLastMapping);
}
else {
yield* (0, wrapWith_1.wrapWith)(start, start + name.length, features, `'`, directive, ...(0, camelized_1.generateCamelized)((0, shared_1.capitalize)(name), 'template', start, utils_1.combineLastMapping), `'`);
}
}
function* generateEventExpression(options, ctx, prop) {
if (prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
let prefix = `(`;
let suffix = `)`;
let isFirstMapping = true;
const ast = (0, utils_1.createTsAst)(options.ts, prop.exp, prop.exp.content);
const _isCompoundExpression = isCompoundExpression(options.ts, ast);
if (_isCompoundExpression) {
yield `(...[$event]) => {${utils_1.newLine}`;
ctx.addLocalVariable('$event');
yield* ctx.generateConditionGuards();
prefix = ``;
suffix = ``;
}
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', offset => {
if (_isCompoundExpression && isFirstMapping) {
isFirstMapping = false;
ctx.inlayHints.push({
blockName: 'template',
offset,
setting: 'vue.inlayHints.inlineHandlerLeading',
label: '$event =>',
paddingRight: true,
tooltip: [
'`$event` is a hidden parameter, you can use it in this callback.',
'To hide this hint, set `vue.inlayHints.inlineHandlerLeading` to `false` in IDE settings.',
'[More info](https://github.com/vuejs/language-tools/issues/2445#issuecomment-1444771420)',
].join('\n\n'),
});
}
return ctx.codeFeatures.all;
}, prop.exp.content, prop.exp.loc.start.offset, prop.exp.loc, prefix, suffix);
if (_isCompoundExpression) {
ctx.removeLocalVariable('$event');
yield utils_1.endOfLine;
yield* ctx.generateAutoImportCompletion();
yield `}`;
}
}
else {
yield `() => {}`;
}
}
function isCompoundExpression(ts, ast) {
let result = true;
if (ast.statements.length === 0) {
result = false;
}
else if (ast.statements.length === 1) {
ts.forEachChild(ast, child_1 => {
if (ts.isExpressionStatement(child_1)) {
ts.forEachChild(child_1, child_2 => {
if (ts.isArrowFunction(child_2)) {
result = false;
}
else if (isPropertyAccessOrId(ts, child_2)) {
result = false;
}
});
}
else if (ts.isFunctionDeclaration(child_1)) {
result = false;
}
});
}
return result;
}
function isPropertyAccessOrId(ts, node) {
if (ts.isIdentifier(node)) {
return true;
}
if (ts.isPropertyAccessExpression(node)) {
return isPropertyAccessOrId(ts, node.expression);
}
return false;
}
//# sourceMappingURL=elementEvents.js.map

View File

@@ -0,0 +1,11 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code, VueCodeInformation } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export interface FailedPropExpression {
node: CompilerDOM.SimpleExpressionNode;
prefix: string;
suffix: string;
}
export declare function generateElementProps(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, props: CompilerDOM.ElementNode['props'], strictPropsCheck: boolean, enableCodeFeatures: boolean, failedPropExps?: FailedPropExpression[]): Generator<Code>;
export declare function generatePropExp(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, prop: CompilerDOM.DirectiveNode, exp: CompilerDOM.SimpleExpressionNode | undefined, features: VueCodeInformation, enableCodeFeatures?: boolean): Generator<Code>;

View File

@@ -0,0 +1,284 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementProps = generateElementProps;
exports.generatePropExp = generatePropExp;
const CompilerDOM = require("@vue/compiler-dom");
const shared_1 = require("@vue/shared");
const minimatch_1 = require("minimatch");
const muggle_string_1 = require("muggle-string");
const shared_2 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const inlayHints_1 = require("../inlayHints");
const utils_1 = require("../utils");
const camelized_1 = require("../utils/camelized");
const unicode_1 = require("../utils/unicode");
const wrapWith_1 = require("../utils/wrapWith");
const elementDirectives_1 = require("./elementDirectives");
const elementEvents_1 = require("./elementEvents");
const interpolation_1 = require("./interpolation");
const objectProperty_1 = require("./objectProperty");
function* generateElementProps(options, ctx, node, props, strictPropsCheck, enableCodeFeatures, failedPropExps) {
const isComponent = node.tagType === CompilerDOM.ElementTypes.COMPONENT;
for (const prop of props) {
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'on') {
if (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& !prop.arg.loc.source.startsWith('[')
&& !prop.arg.loc.source.endsWith(']')) {
if (!isComponent) {
yield `...{ `;
yield* (0, elementEvents_1.generateEventArg)(ctx, prop.arg.loc.source, prop.arg.loc.start.offset);
yield `: `;
yield* (0, elementEvents_1.generateEventExpression)(options, ctx, prop);
yield `},`;
}
else {
yield `...{ '${(0, shared_1.camelize)('on-' + prop.arg.loc.source)}': {} as any },`;
}
yield utils_1.newLine;
}
else if (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& prop.arg.loc.source.startsWith('[')
&& prop.arg.loc.source.endsWith(']')) {
failedPropExps?.push({ node: prop.arg, prefix: `(`, suffix: `)` });
failedPropExps?.push({ node: prop.exp, prefix: `() => {`, suffix: `}` });
}
else if (!prop.arg
&& prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
failedPropExps?.push({ node: prop.exp, prefix: `(`, suffix: `)` });
}
}
}
for (const prop of props) {
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& ((prop.name === 'bind' && prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION)
|| prop.name === 'model')
&& (!prop.exp || prop.exp.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION)) {
let propName;
if (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
propName = prop.arg.constType === CompilerDOM.ConstantTypes.CAN_STRINGIFY
? prop.arg.content
: prop.arg.loc.source;
}
else {
propName = getModelPropName(node, options.vueCompilerOptions);
}
if (propName === undefined
|| options.vueCompilerOptions.dataAttributes.some(pattern => (0, minimatch_1.minimatch)(propName, pattern))) {
if (prop.exp && prop.exp.constType !== CompilerDOM.ConstantTypes.CAN_STRINGIFY) {
failedPropExps?.push({ node: prop.exp, prefix: `(`, suffix: `)` });
}
continue;
}
if (prop.name === 'bind'
&& prop.modifiers.some(m => m.content === 'prop' || m.content === 'attr')) {
propName = propName.slice(1);
}
const shouldSpread = propName === 'style' || propName === 'class';
const shouldCamelize = isComponent && getShouldCamelize(options, prop, propName);
const codeInfo = getPropsCodeInfo(ctx, strictPropsCheck, shouldCamelize);
if (shouldSpread) {
yield `...{ `;
}
const codes = [...(0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, ctx.codeFeatures.verification, ...(prop.arg
? (0, objectProperty_1.generateObjectProperty)(options, ctx, propName, prop.arg.loc.start.offset, codeInfo, prop.loc.name_2 ??= {}, shouldCamelize)
: (0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.start.offset + 'v-model'.length, ctx.codeFeatures.withoutHighlightAndCompletion, propName)), `: `, ...generatePropExp(options, ctx, prop, prop.exp, ctx.codeFeatures.all, enableCodeFeatures))];
if (enableCodeFeatures) {
yield* codes;
}
else {
yield (0, muggle_string_1.toString)(codes);
}
if (shouldSpread) {
yield ` }`;
}
yield `,${utils_1.newLine}`;
if (isComponent && prop.name === 'model' && prop.modifiers.length) {
const propertyName = prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
? !prop.arg.isStatic
? `[__VLS_tryAsConstant(\`$\{${prop.arg.content}\}Modifiers\`)]`
: (0, shared_1.camelize)(propName) + `Modifiers`
: `modelModifiers`;
const codes = [...(0, elementDirectives_1.generateModifiers)(options, ctx, prop, propertyName)];
if (enableCodeFeatures) {
yield* codes;
}
else {
yield (0, muggle_string_1.toString)(codes);
}
yield utils_1.newLine;
}
}
else if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE) {
if (options.vueCompilerOptions.dataAttributes.some(pattern => (0, minimatch_1.minimatch)(prop.name, pattern))
// Vue 2 Transition doesn't support "persisted" property but `@vue/compiler-dom` always adds it (#3881)
|| (options.vueCompilerOptions.target < 3
&& prop.name === 'persisted'
&& node.tag.toLowerCase() === 'transition')) {
continue;
}
const shouldSpread = prop.name === 'style' || prop.name === 'class';
const shouldCamelize = isComponent && getShouldCamelize(options, prop, prop.name);
const codeInfo = getPropsCodeInfo(ctx, strictPropsCheck, true);
if (shouldSpread) {
yield `...{ `;
}
const codes = [...(0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, ctx.codeFeatures.verification, ...(0, objectProperty_1.generateObjectProperty)(options, ctx, prop.name, prop.loc.start.offset, codeInfo, prop.loc.name_1 ??= {}, shouldCamelize), `: `, ...(prop.value
? generateAttrValue(prop.value, ctx.codeFeatures.withoutNavigation)
: [`true`]))];
if (enableCodeFeatures) {
yield* codes;
}
else {
yield (0, muggle_string_1.toString)(codes);
}
if (shouldSpread) {
yield ` }`;
}
yield `,${utils_1.newLine}`;
}
else if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'bind'
&& !prop.arg
&& prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
if (prop.exp.loc.source === '$attrs') {
if (enableCodeFeatures) {
ctx.bindingAttrLocs.push(prop.exp.loc);
}
}
else {
const codes = [...(0, wrapWith_1.wrapWith)(prop.exp.loc.start.offset, prop.exp.loc.end.offset, ctx.codeFeatures.verification, `...`, ...generatePropExp(options, ctx, prop, prop.exp, ctx.codeFeatures.all, enableCodeFeatures))];
if (enableCodeFeatures) {
yield* codes;
}
else {
yield (0, muggle_string_1.toString)(codes);
}
yield `,${utils_1.newLine}`;
}
}
}
}
function* generatePropExp(options, ctx, prop, exp, features, enableCodeFeatures = true) {
const isShorthand = prop.arg?.loc.start.offset === prop.exp?.loc.start.offset;
if (isShorthand && features.completion) {
features = {
...features,
completion: undefined,
};
}
if (exp && exp.constType !== CompilerDOM.ConstantTypes.CAN_STRINGIFY) { // style='z-index: 2' will compile to {'z-index':'2'}
if (!isShorthand) { // vue 3.4+
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', features, exp.loc.source, exp.loc.start.offset, exp.loc, `(`, `)`);
}
else {
const propVariableName = (0, shared_1.camelize)(exp.loc.source);
if (utils_1.identifierRegex.test(propVariableName)) {
const isDestructuredProp = options.destructuredPropNames?.has(propVariableName) ?? false;
const isTemplateRef = options.templateRefNames?.has(propVariableName) ?? false;
const codes = (0, camelized_1.generateCamelized)(exp.loc.source, 'template', exp.loc.start.offset, features);
if (ctx.hasLocalVariable(propVariableName) || isDestructuredProp) {
yield* codes;
}
else {
ctx.accessExternalVariable(propVariableName, exp.loc.start.offset);
if (isTemplateRef) {
yield `__VLS_unref(`;
yield* codes;
yield `)`;
}
else {
yield `__VLS_ctx.`;
yield* codes;
}
}
if (enableCodeFeatures) {
ctx.inlayHints.push((0, inlayHints_1.createVBindShorthandInlayHintInfo)(prop.loc, propVariableName));
}
}
}
}
else {
yield `{}`;
}
}
function* generateAttrValue(attrNode, features) {
const quote = attrNode.loc.source.startsWith("'") ? "'" : '"';
yield quote;
let start = attrNode.loc.start.offset;
let content = attrNode.loc.source;
if ((content.startsWith('"') && content.endsWith('"'))
|| (content.startsWith("'") && content.endsWith("'"))) {
start++;
content = content.slice(1, -1);
}
yield* (0, unicode_1.generateUnicode)(content, start, features);
yield quote;
}
function getShouldCamelize(options, prop, propName) {
return (prop.type !== CompilerDOM.NodeTypes.DIRECTIVE
|| !prop.arg
|| (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && prop.arg.isStatic))
&& (0, shared_2.hyphenateAttr)(propName) === propName
&& !options.vueCompilerOptions.htmlAttributes.some(pattern => (0, minimatch_1.minimatch)(propName, pattern));
}
function getPropsCodeInfo(ctx, strictPropsCheck, shouldCamelize) {
return ctx.resolveCodeFeatures({
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletion,
navigation: {
resolveRenameNewName: shared_1.camelize,
resolveRenameEditText: shouldCamelize ? shared_2.hyphenateAttr : undefined,
},
verification: strictPropsCheck || {
shouldReport(_source, code) {
// https://typescript.tv/errors/#ts2353
// https://typescript.tv/errors/#ts2561
if (String(code) === '2353' || String(code) === '2561') {
return false;
}
return true;
},
},
});
}
function getModelPropName(node, vueCompilerOptions) {
for (const modelName in vueCompilerOptions.experimentalModelPropName) {
const tags = vueCompilerOptions.experimentalModelPropName[modelName];
for (const tag in tags) {
if (node.tag === tag || node.tag === (0, shared_2.hyphenateTag)(tag)) {
const val = tags[tag];
if (typeof val === 'object') {
const arr = Array.isArray(val) ? val : [val];
for (const attrs of arr) {
let failed = false;
for (const attr in attrs) {
const attrNode = node.props.find(prop => prop.type === CompilerDOM.NodeTypes.ATTRIBUTE && prop.name === attr);
if (!attrNode || attrNode.value?.content !== attrs[attr]) {
failed = true;
break;
}
}
if (!failed) {
// all match
return modelName || undefined;
}
}
}
}
}
}
for (const modelName in vueCompilerOptions.experimentalModelPropName) {
const tags = vueCompilerOptions.experimentalModelPropName[modelName];
for (const tag in tags) {
if (node.tag === tag || node.tag === (0, shared_2.hyphenateTag)(tag)) {
const attrs = tags[tag];
if (attrs === true) {
return modelName || undefined;
}
}
}
}
return vueCompilerOptions.target < 3 ? 'value' : 'modelValue';
}
//# sourceMappingURL=elementProps.js.map

View File

@@ -0,0 +1,22 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type * as ts from 'typescript';
import type { Code, Sfc, VueCompilerOptions } from '../../types';
import { TemplateCodegenContext } from './context';
export interface TemplateCodegenOptions {
ts: typeof ts;
compilerOptions: ts.CompilerOptions;
vueCompilerOptions: VueCompilerOptions;
template: NonNullable<Sfc['template']>;
edited: boolean;
scriptSetupBindingNames: Set<string>;
scriptSetupImportComponentNames: Set<string>;
destructuredPropNames: Set<string>;
templateRefNames: Set<string>;
hasDefineSlots?: boolean;
slotsAssignName?: string;
propsAssignName?: string;
inheritAttrs: boolean;
selfComponentName?: string;
}
export declare function generateTemplate(options: TemplateCodegenOptions): Generator<Code, TemplateCodegenContext>;
export declare function forEachElementNode(node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode): Generator<CompilerDOM.ElementNode>;

View File

@@ -0,0 +1,151 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplate = generateTemplate;
exports.forEachElementNode = forEachElementNode;
const CompilerDOM = require("@vue/compiler-dom");
const shared_1 = require("../../utils/shared");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
const context_1 = require("./context");
const objectProperty_1 = require("./objectProperty");
const styleScopedClasses_1 = require("./styleScopedClasses");
const templateChild_1 = require("./templateChild");
function* generateTemplate(options) {
const ctx = (0, context_1.createTemplateCodegenContext)(options);
if (options.slotsAssignName) {
ctx.addLocalVariable(options.slotsAssignName);
}
if (options.propsAssignName) {
ctx.addLocalVariable(options.propsAssignName);
}
const slotsPropertyName = (0, shared_1.getSlotsPropertyName)(options.vueCompilerOptions.target);
if (options.vueCompilerOptions.inferTemplateDollarSlots) {
ctx.dollarVars.add(slotsPropertyName);
}
if (options.vueCompilerOptions.inferTemplateDollarAttrs) {
ctx.dollarVars.add('$attrs');
}
if (options.vueCompilerOptions.inferTemplateDollarRefs) {
ctx.dollarVars.add('$refs');
}
if (options.vueCompilerOptions.inferTemplateDollarEl) {
ctx.dollarVars.add('$el');
}
if (options.template.ast) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, options.template.ast, undefined);
}
yield* (0, styleScopedClasses_1.generateStyleScopedClassReferences)(ctx);
yield* ctx.generateAutoImportCompletion();
yield* ctx.generateHoistVariables();
const speicalTypes = [
[slotsPropertyName, yield* generateSlots(options, ctx)],
['$attrs', yield* generateInheritedAttrs(options, ctx)],
['$refs', yield* generateTemplateRefs(options, ctx)],
['$el', yield* generateRootEl(ctx)]
];
yield `var __VLS_dollars!: {${utils_1.newLine}`;
for (const [name, type] of speicalTypes) {
yield `${name}: ${type}${utils_1.endOfLine}`;
}
yield `} & { [K in keyof import('${options.vueCompilerOptions.lib}').ComponentPublicInstance]: unknown }${utils_1.endOfLine}`;
return ctx;
}
function* generateSlots(options, ctx) {
if (!options.hasDefineSlots) {
yield `type __VLS_Slots = {}`;
for (const { expVar, propsVar } of ctx.dynamicSlots) {
yield `${utils_1.newLine}& { [K in NonNullable<typeof ${expVar}>]?: (props: typeof ${propsVar}) => any }`;
}
for (const slot of ctx.slots) {
yield `${utils_1.newLine}& { `;
if (slot.name && slot.offset !== undefined) {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, slot.name, slot.offset, ctx.codeFeatures.withoutHighlightAndCompletion, slot.nodeLoc);
}
else {
yield* (0, wrapWith_1.wrapWith)(slot.tagRange[0], slot.tagRange[1], ctx.codeFeatures.withoutHighlightAndCompletion, `default`);
}
yield `?: (props: typeof ${slot.propsVar}) => any }`;
}
yield `${utils_1.endOfLine}`;
}
return `__VLS_Slots`;
}
function* generateInheritedAttrs(options, ctx) {
yield `type __VLS_InheritedAttrs = {}`;
for (const varName of ctx.inheritedAttrVars) {
yield ` & typeof ${varName}`;
}
yield utils_1.endOfLine;
if (ctx.bindingAttrLocs.length) {
yield `[`;
for (const loc of ctx.bindingAttrLocs) {
yield `__VLS_dollars.`;
yield [
loc.source,
'template',
loc.start.offset,
ctx.codeFeatures.all
];
yield `,`;
}
yield `]${utils_1.endOfLine}`;
}
return `import('${options.vueCompilerOptions.lib}').ComponentPublicInstance['$attrs'] & Partial<__VLS_InheritedAttrs>`;
}
function* generateTemplateRefs(options, ctx) {
yield `type __VLS_TemplateRefs = {${utils_1.newLine}`;
for (const [name, { typeExp, offset }] of ctx.templateRefs) {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, name, offset, ctx.codeFeatures.navigationAndCompletion);
yield `: ${typeExp},${utils_1.newLine}`;
}
yield `}${utils_1.endOfLine}`;
return `__VLS_TemplateRefs`;
}
function* generateRootEl(ctx) {
yield `type __VLS_RootEl = `;
if (ctx.singleRootElTypes.length && !ctx.singleRootNodes.has(null)) {
for (const type of ctx.singleRootElTypes) {
yield `${utils_1.newLine}| ${type}`;
}
}
else {
yield `any`;
}
yield utils_1.endOfLine;
return `__VLS_RootEl`;
}
function* forEachElementNode(node) {
if (node.type === CompilerDOM.NodeTypes.ROOT) {
for (const child of node.children) {
yield* forEachElementNode(child);
}
}
else if (node.type === CompilerDOM.NodeTypes.ELEMENT) {
const patchForNode = (0, templateChild_1.getVForNode)(node);
if (patchForNode) {
yield* forEachElementNode(patchForNode);
}
else {
yield node;
for (const child of node.children) {
yield* forEachElementNode(child);
}
}
}
else if (node.type === CompilerDOM.NodeTypes.IF) {
// v-if / v-else-if / v-else
for (let i = 0; i < node.branches.length; i++) {
const branch = node.branches[i];
for (const childNode of branch.children) {
yield* forEachElementNode(childNode);
}
}
}
else if (node.type === CompilerDOM.NodeTypes.FOR) {
// v-for
for (const child of node.children) {
yield* forEachElementNode(child);
}
}
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,8 @@
import type * as ts from 'typescript';
import type { Code, VueCodeInformation } from '../../types';
import type { TemplateCodegenContext } from './context';
export declare function generateInterpolation(options: {
ts: typeof ts;
destructuredPropNames: Set<string> | undefined;
templateRefNames: Set<string> | undefined;
}, ctx: TemplateCodegenContext, source: string, data: VueCodeInformation | ((offset: number) => VueCodeInformation) | undefined, _code: string, start: number | undefined, astHolder?: any, prefix?: string, suffix?: string): Generator<Code>;

View File

@@ -0,0 +1,225 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateInterpolation = generateInterpolation;
const shared_1 = require("@vue/shared");
const scriptSetupRanges_1 = require("../../parsers/scriptSetupRanges");
const utils_1 = require("../utils");
function* generateInterpolation(options, ctx, source, data, _code, start, astHolder = {}, prefix = '', suffix = '') {
const code = prefix + _code + suffix;
const ast = (0, utils_1.createTsAst)(options.ts, astHolder, code);
for (let [section, offset, type] of forEachInterpolationSegment(options.ts, options.destructuredPropNames, options.templateRefNames, ctx, code, start !== undefined ? start - prefix.length : undefined, ast)) {
if (offset === undefined) {
yield section;
}
else {
offset -= prefix.length;
let addSuffix = '';
const overLength = offset + section.length - _code.length;
if (overLength > 0) {
addSuffix = section.slice(section.length - overLength);
section = section.slice(0, -overLength);
}
if (offset < 0) {
yield section.slice(0, -offset);
section = section.slice(-offset);
offset = 0;
}
const shouldSkip = section.length === 0 && (type === 'startText' || type === 'endText');
if (!shouldSkip) {
if (start !== undefined
&& data) {
yield [
section,
source,
start + offset,
type === 'errorMappingOnly'
? ctx.codeFeatures.verification
: typeof data === 'function' ? data(start + offset) : data,
];
}
else {
yield section;
}
}
yield addSuffix;
}
}
}
;
function* forEachInterpolationSegment(ts, destructuredPropNames, templateRefNames, ctx, code, offset, ast) {
let ctxVars = [];
const varCb = (id, isShorthand) => {
const text = (0, scriptSetupRanges_1.getNodeText)(ts, id, ast);
if (ctx.hasLocalVariable(text)
// https://github.com/vuejs/core/blob/245230e135152900189f13a4281302de45fdcfaa/packages/compiler-core/src/transforms/transformExpression.ts#L342-L352
|| (0, shared_1.isGloballyAllowed)(text)
|| text === 'require'
|| text.startsWith('__VLS_')) {
// localVarOffsets.push(localVar.getStart(ast));
}
else {
ctxVars.push({
text,
isShorthand: isShorthand,
offset: (0, scriptSetupRanges_1.getStartEnd)(ts, id, ast).start,
});
if (destructuredPropNames?.has(text)) {
return;
}
if (offset !== undefined) {
ctx.accessExternalVariable(text, offset + (0, scriptSetupRanges_1.getStartEnd)(ts, id, ast).start);
}
else {
ctx.accessExternalVariable(text);
}
}
};
ts.forEachChild(ast, node => walkIdentifiers(ts, node, ast, varCb, ctx));
ctxVars = ctxVars.sort((a, b) => a.offset - b.offset);
if (ctxVars.length) {
if (ctxVars[0].isShorthand) {
yield [code.slice(0, ctxVars[0].offset + ctxVars[0].text.length), 0];
yield [': ', undefined];
}
else if (ctxVars[0].offset > 0) {
yield [code.slice(0, ctxVars[0].offset), 0, 'startText'];
}
for (let i = 0; i < ctxVars.length - 1; i++) {
const curVar = ctxVars[i];
const nextVar = ctxVars[i + 1];
yield* generateVar(code, ctx.dollarVars, destructuredPropNames, templateRefNames, curVar);
if (nextVar.isShorthand) {
yield [code.slice(curVar.offset + curVar.text.length, nextVar.offset + nextVar.text.length), curVar.offset + curVar.text.length];
yield [': ', undefined];
}
else {
yield [code.slice(curVar.offset + curVar.text.length, nextVar.offset), curVar.offset + curVar.text.length];
}
}
const lastVar = ctxVars.at(-1);
yield* generateVar(code, ctx.dollarVars, destructuredPropNames, templateRefNames, lastVar);
if (lastVar.offset + lastVar.text.length < code.length) {
yield [code.slice(lastVar.offset + lastVar.text.length), lastVar.offset + lastVar.text.length, 'endText'];
}
}
else {
yield [code, 0];
}
}
function* generateVar(code, dollarVars, destructuredPropNames, templateRefNames, curVar) {
// fix https://github.com/vuejs/language-tools/issues/1205
// fix https://github.com/vuejs/language-tools/issues/1264
yield ['', curVar.offset, 'errorMappingOnly'];
const isDestructuredProp = destructuredPropNames?.has(curVar.text) ?? false;
const isTemplateRef = templateRefNames?.has(curVar.text) ?? false;
if (isTemplateRef) {
yield [`__VLS_unref(`, undefined];
yield [code.slice(curVar.offset, curVar.offset + curVar.text.length), curVar.offset];
yield [`)`, undefined];
}
else {
if (dollarVars.has(curVar.text)) {
yield [`__VLS_dollars.`, undefined];
}
else if (!isDestructuredProp) {
yield [`__VLS_ctx.`, undefined];
}
yield [code.slice(curVar.offset, curVar.offset + curVar.text.length), curVar.offset];
}
}
function walkIdentifiers(ts, node, ast, cb, ctx, blockVars = [], isRoot = true) {
if (ts.isIdentifier(node)) {
cb(node, false);
}
else if (ts.isShorthandPropertyAssignment(node)) {
cb(node.name, true);
}
else if (ts.isPropertyAccessExpression(node)) {
walkIdentifiers(ts, node.expression, ast, cb, ctx, blockVars, false);
}
else if (ts.isVariableDeclaration(node)) {
(0, utils_1.collectVars)(ts, node.name, ast, blockVars);
for (const varName of blockVars) {
ctx.addLocalVariable(varName);
}
if (node.initializer) {
walkIdentifiers(ts, node.initializer, ast, cb, ctx, blockVars, false);
}
}
else if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
processFunction(ts, node, ast, cb, ctx);
}
else if (ts.isObjectLiteralExpression(node)) {
for (const prop of node.properties) {
if (ts.isPropertyAssignment(prop)) {
// fix https://github.com/vuejs/language-tools/issues/1176
if (ts.isComputedPropertyName(prop.name)) {
walkIdentifiers(ts, prop.name.expression, ast, cb, ctx, blockVars, false);
}
walkIdentifiers(ts, prop.initializer, ast, cb, ctx, blockVars, false);
}
// fix https://github.com/vuejs/language-tools/issues/1156
else if (ts.isShorthandPropertyAssignment(prop)) {
walkIdentifiers(ts, prop, ast, cb, ctx, blockVars, false);
}
// fix https://github.com/vuejs/language-tools/issues/1148#issuecomment-1094378126
else if (ts.isSpreadAssignment(prop)) {
// TODO: cannot report "Spread types may only be created from object types.ts(2698)"
walkIdentifiers(ts, prop.expression, ast, cb, ctx, blockVars, false);
}
// fix https://github.com/vuejs/language-tools/issues/4604
else if (ts.isFunctionLike(prop) && prop.body) {
processFunction(ts, prop, ast, cb, ctx);
}
}
}
else if (ts.isTypeReferenceNode(node)) {
// fix https://github.com/vuejs/language-tools/issues/1422
ts.forEachChild(node, node => walkIdentifiersInTypeReference(ts, node, cb));
}
else {
const _blockVars = blockVars;
if (ts.isBlock(node)) {
blockVars = [];
}
ts.forEachChild(node, node => walkIdentifiers(ts, node, ast, cb, ctx, blockVars, false));
if (ts.isBlock(node)) {
for (const varName of blockVars) {
ctx.removeLocalVariable(varName);
}
}
blockVars = _blockVars;
}
if (isRoot) {
for (const varName of blockVars) {
ctx.removeLocalVariable(varName);
}
}
}
function processFunction(ts, node, ast, cb, ctx) {
const functionArgs = [];
for (const param of node.parameters) {
(0, utils_1.collectVars)(ts, param.name, ast, functionArgs);
if (param.type) {
walkIdentifiers(ts, param.type, ast, cb, ctx);
}
}
for (const varName of functionArgs) {
ctx.addLocalVariable(varName);
}
if (node.body) {
walkIdentifiers(ts, node.body, ast, cb, ctx);
}
for (const varName of functionArgs) {
ctx.removeLocalVariable(varName);
}
}
function walkIdentifiersInTypeReference(ts, node, cb) {
if (ts.isTypeQueryNode(node) && ts.isIdentifier(node.exprName)) {
cb(node.exprName, false);
}
else {
ts.forEachChild(node, node => walkIdentifiersInTypeReference(ts, node, cb));
}
}
//# sourceMappingURL=interpolation.js.map

View File

@@ -0,0 +1,4 @@
import type { Code, VueCodeInformation } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateObjectProperty(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, code: string, offset: number, features: VueCodeInformation, astHolder?: any, shouldCamelize?: boolean, shouldBeConstant?: boolean): Generator<Code>;

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateObjectProperty = generateObjectProperty;
const shared_1 = require("@vue/shared");
const utils_1 = require("../utils");
const camelized_1 = require("../utils/camelized");
const stringLiteralKey_1 = require("../utils/stringLiteralKey");
const wrapWith_1 = require("../utils/wrapWith");
const interpolation_1 = require("./interpolation");
function* generateObjectProperty(options, ctx, code, offset, features, astHolder, shouldCamelize = false, shouldBeConstant = false) {
if (code.startsWith('[') && code.endsWith(']') && astHolder) {
if (shouldBeConstant) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', features, code.slice(1, -1), offset + 1, astHolder, `[__VLS_tryAsConstant(`, `)]`);
}
else {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', features, code, offset, astHolder);
}
}
else if (shouldCamelize) {
if (utils_1.identifierRegex.test((0, shared_1.camelize)(code))) {
yield* (0, camelized_1.generateCamelized)(code, 'template', offset, features);
}
else {
yield* (0, wrapWith_1.wrapWith)(offset, offset + code.length, features, `'`, ...(0, camelized_1.generateCamelized)(code, 'template', offset, utils_1.combineLastMapping), `'`);
}
}
else {
if (utils_1.identifierRegex.test(code)) {
yield [code, 'template', offset, features];
}
else {
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(code, offset, features);
}
}
}
//# sourceMappingURL=objectProperty.js.map

View File

@@ -0,0 +1,4 @@
import type { Code, VueCodeInformation } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generatePropertyAccess(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, code: string, offset?: number, features?: VueCodeInformation, astHolder?: any): Generator<Code>;

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generatePropertyAccess = generatePropertyAccess;
const utils_1 = require("../utils");
const stringLiteralKey_1 = require("../utils/stringLiteralKey");
const interpolation_1 = require("./interpolation");
function* generatePropertyAccess(options, ctx, code, offset, features, astHolder) {
if (!options.compilerOptions.noPropertyAccessFromIndexSignature && utils_1.identifierRegex.test(code)) {
yield `.`;
yield offset !== undefined && features
? [code, 'template', offset, features]
: code;
}
else if (code.startsWith('[') && code.endsWith(']')) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', features, code, offset, astHolder);
}
else {
yield `[`;
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(code, offset, features);
yield `]`;
}
}
//# sourceMappingURL=propertyAccess.js.map

View File

@@ -0,0 +1,5 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateSlotOutlet(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.SlotOutletNode): Generator<Code>;

View File

@@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSlotOutlet = generateSlotOutlet;
const CompilerDOM = require("@vue/compiler-dom");
const inlayHints_1 = require("../inlayHints");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
const elementChildren_1 = require("./elementChildren");
const elementProps_1 = require("./elementProps");
const interpolation_1 = require("./interpolation");
const propertyAccess_1 = require("./propertyAccess");
function* generateSlotOutlet(options, ctx, node) {
const startTagOffset = node.loc.start.offset + options.template.content.slice(node.loc.start.offset).indexOf(node.tag);
const startTagEndOffset = startTagOffset + node.tag.length;
const propsVar = ctx.getInternalVariable();
const nameProp = node.props.find(prop => {
if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE) {
return prop.name === 'name';
}
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'bind'
&& prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
return prop.arg.content === 'name';
}
});
if (options.hasDefineSlots) {
yield `__VLS_asFunctionalSlot(`;
if (nameProp) {
let codes;
if (nameProp.type === CompilerDOM.NodeTypes.ATTRIBUTE && nameProp.value) {
let { source, start: { offset } } = nameProp.value.loc;
if (source.startsWith('"') || source.startsWith("'")) {
source = source.slice(1, -1);
offset++;
}
codes = (0, propertyAccess_1.generatePropertyAccess)(options, ctx, source, offset, ctx.codeFeatures.navigationAndVerification);
}
else if (nameProp.type === CompilerDOM.NodeTypes.DIRECTIVE
&& nameProp.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
codes = [
`[`,
...(0, elementProps_1.generatePropExp)(options, ctx, nameProp, nameProp.exp, ctx.codeFeatures.all),
`]`
];
}
else {
codes = [`['default']`];
}
yield* (0, wrapWith_1.wrapWith)(nameProp.loc.start.offset, nameProp.loc.end.offset, ctx.codeFeatures.verification, `${options.slotsAssignName ?? '__VLS_slots'}`, ...codes);
}
else {
yield* (0, wrapWith_1.wrapWith)(startTagOffset, startTagEndOffset, ctx.codeFeatures.verification, `${options.slotsAssignName ?? '__VLS_slots'}[`, ...(0, wrapWith_1.wrapWith)(startTagOffset, startTagEndOffset, ctx.codeFeatures.verification, `'default'`), `]`);
}
yield `)(`;
yield* (0, wrapWith_1.wrapWith)(startTagOffset, startTagEndOffset, ctx.codeFeatures.verification, `{${utils_1.newLine}`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, node.props.filter(prop => prop !== nameProp), true, true), `}`);
yield `)${utils_1.endOfLine}`;
}
else {
yield `var ${propsVar} = {${utils_1.newLine}`;
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, node.props.filter(prop => prop !== nameProp), options.vueCompilerOptions.checkUnknownProps, true);
yield `}${utils_1.endOfLine}`;
if (nameProp?.type === CompilerDOM.NodeTypes.ATTRIBUTE
&& nameProp.value) {
ctx.slots.push({
name: nameProp.value.content,
offset: nameProp.loc.start.offset + nameProp.loc.source.indexOf(nameProp.value.content, nameProp.name.length),
tagRange: [startTagOffset, startTagOffset + node.tag.length],
nodeLoc: node.loc,
propsVar: ctx.getHoistVariable(propsVar),
});
}
else if (nameProp?.type === CompilerDOM.NodeTypes.DIRECTIVE
&& nameProp.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const isShortHand = nameProp.arg?.loc.start.offset === nameProp.exp.loc.start.offset;
if (isShortHand) {
ctx.inlayHints.push((0, inlayHints_1.createVBindShorthandInlayHintInfo)(nameProp.exp.loc, 'name'));
}
const expVar = ctx.getInternalVariable();
yield `var ${expVar} = __VLS_tryAsConstant(`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, nameProp.exp.content, nameProp.exp.loc.start.offset, nameProp.exp);
yield `)${utils_1.endOfLine}`;
ctx.dynamicSlots.push({
expVar: ctx.getHoistVariable(expVar),
propsVar: ctx.getHoistVariable(propsVar),
});
}
else {
ctx.slots.push({
name: 'default',
tagRange: [startTagOffset, startTagEndOffset],
nodeLoc: node.loc,
propsVar: ctx.getHoistVariable(propsVar),
});
}
}
yield* ctx.generateAutoImportCompletion();
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node);
}
//# sourceMappingURL=slotOutlet.js.map

View File

@@ -0,0 +1,6 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateStyleScopedClassReferences(ctx: TemplateCodegenContext, withDot?: boolean): Generator<Code>;
export declare function collectStyleScopedClassReferences(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): void;

View File

@@ -0,0 +1,166 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleScopedClassReferences = generateStyleScopedClassReferences;
exports.collectStyleScopedClassReferences = collectStyleScopedClassReferences;
const CompilerDOM = require("@vue/compiler-dom");
const scriptSetupRanges_1 = require("../../parsers/scriptSetupRanges");
const utils_1 = require("../utils");
const escaped_1 = require("../utils/escaped");
const wrapWith_1 = require("../utils/wrapWith");
const classNameEscapeRegex = /([\\'])/;
function* generateStyleScopedClassReferences(ctx, withDot = false) {
for (const offset of ctx.emptyClassOffsets) {
yield `/** @type {__VLS_StyleScopedClasses['`;
yield [
'',
'template',
offset,
ctx.codeFeatures.additionalCompletion,
];
yield `']} */${utils_1.endOfLine}`;
}
for (const { source, className, offset } of ctx.scopedClasses) {
yield `/** @type {__VLS_StyleScopedClasses[`;
yield* (0, wrapWith_1.wrapWith)(offset - (withDot ? 1 : 0), offset + className.length, source, ctx.codeFeatures.navigation, `'`, ...(0, escaped_1.generateEscaped)(className, source, offset, ctx.codeFeatures.navigationAndAdditionalCompletion, classNameEscapeRegex), `'`);
yield `]} */${utils_1.endOfLine}`;
}
}
function collectStyleScopedClassReferences(options, ctx, node) {
for (const prop of node.props) {
if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE
&& prop.name === 'class'
&& prop.value) {
if (options.template.lang === 'pug') {
const getClassOffset = Reflect.get(prop.value.loc.start, 'getClassOffset');
const content = prop.value.loc.source.slice(1, -1);
let startOffset = 1;
for (const className of content.split(' ')) {
if (className) {
ctx.scopedClasses.push({
source: 'template',
className,
offset: getClassOffset(startOffset),
});
}
startOffset += className.length + 1;
}
}
else {
let isWrapped = false;
const [content, startOffset] = (0, utils_1.normalizeAttributeValue)(prop.value);
if (content) {
const classes = collectClasses(content, startOffset + (isWrapped ? 1 : 0));
ctx.scopedClasses.push(...classes);
}
else {
ctx.emptyClassOffsets.push(startOffset);
}
}
}
else if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& prop.arg.content === 'class') {
const content = '`${' + prop.exp.content + '}`';
const startOffset = prop.exp.loc.start.offset - 3;
const { ts } = options;
const ast = ts.createSourceFile('', content, 99);
const literals = [];
ts.forEachChild(ast, node => {
if (!ts.isExpressionStatement(node) ||
!isTemplateExpression(node.expression)) {
return;
}
const expression = node.expression.templateSpans[0].expression;
if (ts.isStringLiteralLike(expression)) {
literals.push(expression);
}
if (ts.isArrayLiteralExpression(expression)) {
walkArrayLiteral(expression);
}
if (ts.isObjectLiteralExpression(expression)) {
walkObjectLiteral(expression);
}
});
for (const literal of literals) {
if (literal.text) {
const classes = collectClasses(literal.text, literal.end - literal.text.length - 1 + startOffset);
ctx.scopedClasses.push(...classes);
}
else {
ctx.emptyClassOffsets.push(literal.end - 1 + startOffset);
}
}
function walkArrayLiteral(node) {
const { elements } = node;
for (const element of elements) {
if (ts.isStringLiteralLike(element)) {
literals.push(element);
}
else if (ts.isObjectLiteralExpression(element)) {
walkObjectLiteral(element);
}
}
}
function walkObjectLiteral(node) {
const { properties } = node;
for (const property of properties) {
if (ts.isPropertyAssignment(property)) {
const { name } = property;
if (ts.isIdentifier(name)) {
walkIdentifier(name);
}
else if (ts.isStringLiteral(name)) {
literals.push(name);
}
else if (ts.isComputedPropertyName(name)) {
const { expression } = name;
if (ts.isStringLiteralLike(expression)) {
literals.push(expression);
}
}
}
else if (ts.isShorthandPropertyAssignment(property)) {
walkIdentifier(property.name);
}
}
}
function walkIdentifier(node) {
const text = (0, scriptSetupRanges_1.getNodeText)(ts, node, ast);
ctx.scopedClasses.push({
source: 'template',
className: text,
offset: node.end - text.length + startOffset
});
}
}
}
}
function collectClasses(content, startOffset = 0) {
const classes = [];
let currentClassName = '';
let offset = 0;
for (const char of (content + ' ')) {
if (char.trim() === '') {
if (currentClassName !== '') {
classes.push({
source: 'template',
className: currentClassName,
offset: offset + startOffset
});
offset += currentClassName.length;
currentClassName = '';
}
offset += char.length;
}
else {
currentClassName += char;
}
}
return classes;
}
// isTemplateExpression is missing in tsc
function isTemplateExpression(node) {
return node.kind === 228;
}
//# sourceMappingURL=styleScopedClasses.js.map

View File

@@ -0,0 +1,7 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateTemplateChild(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode, prevNode: CompilerDOM.TemplateChildNode | undefined, isVForChild?: boolean): Generator<Code>;
export declare function getVForNode(node: CompilerDOM.ElementNode): CompilerDOM.ForNode | undefined;
export declare function parseInterpolationNode(node: CompilerDOM.InterpolationNode, template: string): readonly [string, number];

View File

@@ -0,0 +1,218 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplateChild = generateTemplateChild;
exports.getVForNode = getVForNode;
exports.parseInterpolationNode = parseInterpolationNode;
const CompilerDOM = require("@vue/compiler-dom");
const shared_1 = require("../../utils/shared");
const utils_1 = require("../utils");
const element_1 = require("./element");
const interpolation_1 = require("./interpolation");
const slotOutlet_1 = require("./slotOutlet");
const vFor_1 = require("./vFor");
const vIf_1 = require("./vIf");
const vSlot_1 = require("./vSlot");
const commentDirectiveRegex = /^<!--\s*@vue-(?<name>[-\w]+)\b(?<content>[\s\S]*)-->$/;
// @ts-ignore
const transformContext = {
onError: () => { },
helperString: str => str.toString(),
replaceNode: () => { },
cacheHandlers: false,
prefixIdentifiers: false,
scopes: {
vFor: 0,
vOnce: 0,
vPre: 0,
vSlot: 0,
},
expressionPlugins: ['typescript'],
};
function* generateTemplateChild(options, ctx, node, prevNode, isVForChild = false) {
if (prevNode?.type === CompilerDOM.NodeTypes.COMMENT) {
const match = prevNode.loc.source.match(commentDirectiveRegex);
if (match) {
const { name, content } = match.groups;
switch (name) {
case 'skip': {
yield `// @vue-skip${utils_1.newLine}`;
return;
}
case 'ignore': {
yield* ctx.ignoreError();
break;
}
case 'expect-error': {
yield* ctx.expectError(prevNode);
break;
}
case 'generic': {
const text = content.trim();
if (text.startsWith('{') && text.endsWith('}')) {
ctx.lastGenericComment = {
content: text.slice(1, -1),
offset: prevNode.loc.start.offset + prevNode.loc.source.indexOf('{') + 1,
};
}
break;
}
}
}
}
const cur = node;
if (cur.codegenNode?.type === CompilerDOM.NodeTypes.JS_CACHE_EXPRESSION) {
cur.codegenNode = cur.codegenNode.value;
}
if (node.type === CompilerDOM.NodeTypes.ROOT) {
for (const item of collectSingleRootNodes(options, node.children)) {
ctx.singleRootNodes.add(item);
}
let prev;
for (const childNode of node.children) {
yield* generateTemplateChild(options, ctx, childNode, prev);
prev = childNode;
}
yield* ctx.resetDirectiveComments('end of root');
}
else if (node.type === CompilerDOM.NodeTypes.ELEMENT) {
const vForNode = getVForNode(node);
const vIfNode = getVIfNode(node);
if (vForNode) {
yield* (0, vFor_1.generateVFor)(options, ctx, vForNode);
}
else if (vIfNode) {
yield* (0, vIf_1.generateVIf)(options, ctx, vIfNode);
}
else if (node.tagType === CompilerDOM.ElementTypes.SLOT) {
yield* (0, slotOutlet_1.generateSlotOutlet)(options, ctx, node);
}
else {
const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot');
if (node.tagType === CompilerDOM.ElementTypes.TEMPLATE
&& ctx.currentComponent
&& slotDir) {
yield* (0, vSlot_1.generateVSlot)(options, ctx, node, slotDir);
}
else if (node.tagType === CompilerDOM.ElementTypes.ELEMENT
|| node.tagType === CompilerDOM.ElementTypes.TEMPLATE) {
yield* (0, element_1.generateElement)(options, ctx, node, isVForChild);
}
else {
const { currentComponent } = ctx;
yield* (0, element_1.generateComponent)(options, ctx, node, isVForChild);
ctx.currentComponent = currentComponent;
}
}
}
else if (node.type === CompilerDOM.NodeTypes.TEXT_CALL) {
// {{ var }}
yield* generateTemplateChild(options, ctx, node.content, undefined);
}
else if (node.type === CompilerDOM.NodeTypes.COMPOUND_EXPRESSION) {
// {{ ... }} {{ ... }}
for (const childNode of node.children) {
if (typeof childNode === 'object') {
yield* generateTemplateChild(options, ctx, childNode, undefined);
}
}
}
else if (node.type === CompilerDOM.NodeTypes.INTERPOLATION) {
// {{ ... }}
const [content, start] = parseInterpolationNode(node, options.template.content);
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, content, start, node.content.loc, `(`, `)${utils_1.endOfLine}`);
yield* ctx.resetDirectiveComments('end of INTERPOLATION');
}
else if (node.type === CompilerDOM.NodeTypes.IF) {
// v-if / v-else-if / v-else
yield* (0, vIf_1.generateVIf)(options, ctx, node);
}
else if (node.type === CompilerDOM.NodeTypes.FOR) {
// v-for
yield* (0, vFor_1.generateVFor)(options, ctx, node);
}
else if (node.type === CompilerDOM.NodeTypes.TEXT) {
// not needed progress
}
}
function* collectSingleRootNodes(options, children) {
if (children.length !== 1) {
// "null" is used to determine whether the component is not always has a single root
if (children.length > 1) {
yield null;
}
return;
}
const child = children[0];
if (child.type === CompilerDOM.NodeTypes.IF) {
for (const branch of child.branches) {
yield* collectSingleRootNodes(options, branch.children);
}
return;
}
else if (child.type !== CompilerDOM.NodeTypes.ELEMENT) {
return;
}
yield child;
const tag = (0, shared_1.hyphenateTag)(child.tag);
if (options.vueCompilerOptions.fallthroughComponentNames.includes(tag)) {
yield* collectSingleRootNodes(options, child.children);
}
}
// TODO: track https://github.com/vuejs/vue-next/issues/3498
function getVForNode(node) {
const forDirective = node.props.find((prop) => prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'for');
if (forDirective) {
let forNode;
CompilerDOM.processFor(node, forDirective, transformContext, _forNode => {
forNode = { ..._forNode };
return undefined;
});
if (forNode) {
forNode.children = [{
...node,
props: node.props.filter(prop => prop !== forDirective),
}];
return forNode;
}
}
}
function getVIfNode(node) {
const ifDirective = node.props.find((prop) => prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'if');
if (ifDirective) {
let ifNode;
CompilerDOM.processIf(node, ifDirective, transformContext, _ifNode => {
ifNode = { ..._ifNode };
return undefined;
});
if (ifNode) {
for (const branch of ifNode.branches) {
branch.children = [{
...node,
props: node.props.filter(prop => prop !== ifDirective),
}];
}
return ifNode;
}
}
}
function parseInterpolationNode(node, template) {
let content = node.content.loc.source;
let start = node.content.loc.start.offset;
let leftCharacter;
let rightCharacter;
// fix https://github.com/vuejs/language-tools/issues/1787
while ((leftCharacter = template.slice(start - 1, start)).trim() === '' && leftCharacter.length) {
start--;
content = leftCharacter + content;
}
while ((rightCharacter = template.slice(start + content.length, start + content.length + 1)).trim() === '' && rightCharacter.length) {
content = content + rightCharacter;
}
return [
content,
start,
];
}
//# sourceMappingURL=templateChild.js.map

View File

@@ -0,0 +1,12 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateVFor(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ForNode): Generator<Code>;
export declare function parseVForNode(node: CompilerDOM.ForNode): {
leftExpressionRange: {
start: number;
end: number;
} | undefined;
leftExpressionText: string | undefined;
};

View File

@@ -0,0 +1,85 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVFor = generateVFor;
exports.parseVForNode = parseVForNode;
const CompilerDOM = require("@vue/compiler-dom");
const utils_1 = require("../utils");
const interpolation_1 = require("./interpolation");
const templateChild_1 = require("./templateChild");
function* generateVFor(options, ctx, node) {
const { source } = node.parseResult;
const { leftExpressionRange, leftExpressionText } = parseVForNode(node);
const forBlockVars = [];
yield `for (const [`;
if (leftExpressionRange && leftExpressionText) {
const collectAst = (0, utils_1.createTsAst)(options.ts, node.parseResult, `const [${leftExpressionText}]`);
(0, utils_1.collectVars)(options.ts, collectAst, collectAst, forBlockVars);
yield [
leftExpressionText,
'template',
leftExpressionRange.start,
ctx.codeFeatures.all,
];
}
yield `] of `;
if (source.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
yield `__VLS_getVForSourceType(`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, source.content, source.loc.start.offset, source.loc, `(`, `)`);
yield `!)`; // #3102
}
else {
yield `{} as any`;
}
yield `) {${utils_1.newLine}`;
for (const varName of forBlockVars) {
ctx.addLocalVariable(varName);
}
let isFragment = true;
for (const argument of node.codegenNode?.children.arguments ?? []) {
if (argument.type === CompilerDOM.NodeTypes.JS_FUNCTION_EXPRESSION
&& argument.returns?.type === CompilerDOM.NodeTypes.VNODE_CALL
&& argument.returns?.props?.type === CompilerDOM.NodeTypes.JS_OBJECT_EXPRESSION) {
if (argument.returns.tag !== CompilerDOM.FRAGMENT) {
isFragment = false;
continue;
}
for (const prop of argument.returns.props.properties) {
if (prop.value.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& !prop.value.isStatic) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, prop.value.content, prop.value.loc.start.offset, prop.value.loc, `(`, `)`);
yield utils_1.endOfLine;
}
}
}
}
if (isFragment) {
yield* ctx.resetDirectiveComments('end of v-for start');
}
let prev;
for (const childNode of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, childNode, prev, true);
prev = childNode;
}
for (const varName of forBlockVars) {
ctx.removeLocalVariable(varName);
}
yield* ctx.generateAutoImportCompletion();
yield `}${utils_1.newLine}`;
}
function parseVForNode(node) {
const { value, key, index } = node.parseResult;
const leftExpressionRange = (value || key || index)
? {
start: (value ?? key ?? index).loc.start.offset,
end: (index ?? key ?? value).loc.end.offset,
}
: undefined;
const leftExpressionText = leftExpressionRange
? node.loc.source.slice(leftExpressionRange.start - node.loc.start.offset, leftExpressionRange.end - node.loc.start.offset)
: undefined;
return {
leftExpressionRange,
leftExpressionText,
};
}
//# sourceMappingURL=vFor.js.map

View File

@@ -0,0 +1,5 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateVIf(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.IfNode): Generator<Code>;

View File

@@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVIf = generateVIf;
const CompilerDOM = require("@vue/compiler-dom");
const muggle_string_1 = require("muggle-string");
const utils_1 = require("../utils");
const interpolation_1 = require("./interpolation");
const templateChild_1 = require("./templateChild");
function* generateVIf(options, ctx, node) {
const originalBlockConditionsLength = ctx.blockConditions.length;
for (let i = 0; i < node.branches.length; i++) {
const branch = node.branches[i];
if (i === 0) {
yield `if `;
}
else if (branch.condition) {
yield `else if `;
}
else {
yield `else `;
}
let addedBlockCondition = false;
if (branch.condition?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const codes = [...(0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, branch.condition.content, branch.condition.loc.start.offset, branch.condition.loc, `(`, `)`)];
yield* codes;
ctx.blockConditions.push((0, muggle_string_1.toString)(codes));
addedBlockCondition = true;
yield ` `;
}
yield `{${utils_1.newLine}`;
if (isFragment(node)) {
yield* ctx.resetDirectiveComments('end of v-if start');
}
let prev;
for (const childNode of branch.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, childNode, prev);
prev = childNode;
}
yield* ctx.generateAutoImportCompletion();
yield `}${utils_1.newLine}`;
if (addedBlockCondition) {
ctx.blockConditions[ctx.blockConditions.length - 1] = `!${ctx.blockConditions[ctx.blockConditions.length - 1]}`;
}
}
ctx.blockConditions.length = originalBlockConditionsLength;
}
function isFragment(node) {
return node.codegenNode
&& 'consequent' in node.codegenNode
&& 'tag' in node.codegenNode.consequent
&& node.codegenNode.consequent.tag === CompilerDOM.FRAGMENT;
}
//# sourceMappingURL=vIf.js.map

View File

@@ -0,0 +1,6 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateVSlot(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, slotDir: CompilerDOM.DirectiveNode): Generator<Code>;
export declare function generateImplicitDefaultSlot(ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code, void, any>;

View File

@@ -0,0 +1,93 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVSlot = generateVSlot;
exports.generateImplicitDefaultSlot = generateImplicitDefaultSlot;
const CompilerDOM = require("@vue/compiler-dom");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
const objectProperty_1 = require("./objectProperty");
const templateChild_1 = require("./templateChild");
function* generateVSlot(options, ctx, node, slotDir) {
if (!ctx.currentComponent) {
return;
}
ctx.currentComponent.used = true;
const slotBlockVars = [];
yield `{${utils_1.newLine}`;
yield `const { `;
if (slotDir.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && slotDir.arg.content) {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, slotDir.arg.loc.source, slotDir.arg.loc.start.offset, slotDir.arg.isStatic ? ctx.codeFeatures.withoutHighlight : ctx.codeFeatures.all, slotDir.arg.loc, false, true);
}
else {
yield* (0, wrapWith_1.wrapWith)(slotDir.loc.start.offset, slotDir.loc.start.offset + (slotDir.rawName?.length ?? 0), ctx.codeFeatures.withoutHighlightAndCompletion, `default`);
}
yield `: __VLS_thisSlot } = ${ctx.currentComponent.ctxVar}.slots!${utils_1.endOfLine}`;
if (slotDir.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const slotAst = (0, utils_1.createTsAst)(options.ts, slotDir, `(${slotDir.exp.content}) => {}`);
(0, utils_1.collectVars)(options.ts, slotAst, slotAst, slotBlockVars);
if (!slotDir.exp.content.includes(':')) {
yield `const [`;
yield [
slotDir.exp.content,
'template',
slotDir.exp.loc.start.offset,
ctx.codeFeatures.all,
];
yield `] = __VLS_getSlotParams(__VLS_thisSlot)${utils_1.endOfLine}`;
}
else {
yield `const `;
yield [
slotDir.exp.content,
'template',
slotDir.exp.loc.start.offset,
ctx.codeFeatures.all,
];
yield ` = __VLS_getSlotParam(__VLS_thisSlot)${utils_1.endOfLine}`;
}
}
for (const varName of slotBlockVars) {
ctx.addLocalVariable(varName);
}
yield* ctx.resetDirectiveComments('end of slot children start');
let prev;
for (const childNode of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, childNode, prev);
prev = childNode;
}
for (const varName of slotBlockVars) {
ctx.removeLocalVariable(varName);
}
let isStatic = true;
if (slotDir.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
isStatic = slotDir.arg.isStatic;
}
if (isStatic && !slotDir.arg) {
yield `${ctx.currentComponent.ctxVar}.slots!['`;
yield [
'',
'template',
slotDir.loc.start.offset + (slotDir.loc.source.startsWith('#')
? '#'.length
: slotDir.loc.source.startsWith('v-slot:')
? 'v-slot:'.length
: 0),
ctx.codeFeatures.completion,
];
yield `'/* empty slot name completion */]${utils_1.endOfLine}`;
}
yield* ctx.generateAutoImportCompletion();
yield `}${utils_1.newLine}`;
}
function* generateImplicitDefaultSlot(ctx, node) {
if (!ctx.currentComponent) {
return;
}
if (node.children.length) {
ctx.currentComponent.used = true;
yield `${ctx.currentComponent.ctxVar}.slots!.`;
yield* (0, wrapWith_1.wrapWith)(node.children[0].loc.start.offset, node.children[node.children.length - 1].loc.end.offset, ctx.codeFeatures.navigation, `default`);
yield utils_1.endOfLine;
}
}
//# sourceMappingURL=vSlot.js.map

View File

@@ -0,0 +1,2 @@
import type { Code, VueCodeInformation } from '../../types';
export declare function generateCamelized(code: string, source: string, offset: number, features: VueCodeInformation): Generator<Code>;

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCamelized = generateCamelized;
const shared_1 = require("@vue/shared");
function* generateCamelized(code, source, offset, features) {
const parts = code.split('-');
const startCombineOffset = features.__combineOffset ?? 0;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (part !== '') {
if (i === 0) {
yield [
part,
source,
offset,
features,
];
}
else {
yield [
(0, shared_1.capitalize)(part),
source,
offset,
{ __combineOffset: startCombineOffset + i },
];
}
}
offset += part.length + 1;
}
}
//# sourceMappingURL=camelized.js.map

View File

@@ -0,0 +1,2 @@
import type { Code, VueCodeInformation } from "../../types";
export declare function generateEscaped(text: string, source: string, offset: number, features: VueCodeInformation, escapeTarget: RegExp): Generator<Code>;

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateEscaped = generateEscaped;
function* generateEscaped(text, source, offset, features, escapeTarget) {
const parts = text.split(escapeTarget);
const startCombineOffset = features.__combineOffset ?? 0;
let isEscapeTarget = false;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (isEscapeTarget) {
yield `\\`;
}
yield [
part,
source,
offset,
i === 0 ? features : { __combineOffset: startCombineOffset + i },
];
offset += part.length;
isEscapeTarget = !isEscapeTarget;
}
}
//# sourceMappingURL=escaped.js.map

View File

@@ -0,0 +1,21 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type * as ts from 'typescript';
import type { Code, SfcBlock, SfcBlockAttr, VueCodeInformation } from '../../types';
export declare const newLine = "\n";
export declare const endOfLine = ";\n";
export declare const combineLastMapping: VueCodeInformation;
export declare const identifierRegex: RegExp;
export declare function collectVars(ts: typeof import('typescript'), node: ts.Node, ast: ts.SourceFile, results?: string[]): string[];
export declare function collectIdentifiers(ts: typeof import('typescript'), node: ts.Node, results?: {
id: ts.Identifier;
isRest: boolean;
initializer: ts.Expression | undefined;
}[], isRest?: boolean, initializer?: ts.Expression | undefined): {
id: ts.Identifier;
isRest: boolean;
initializer: ts.Expression | undefined;
}[];
export declare function normalizeAttributeValue(node: CompilerDOM.TextNode): [string, number];
export declare function createTsAst(ts: typeof import('typescript'), astHolder: any, text: string): ts.SourceFile;
export declare function generateSfcBlockSection(block: SfcBlock, start: number, end: number, features: VueCodeInformation): Code;
export declare function generateSfcBlockAttrValue(src: SfcBlockAttr & object, text: string, features: VueCodeInformation): Generator<Code>;

View File

@@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.identifierRegex = exports.combineLastMapping = exports.endOfLine = exports.newLine = void 0;
exports.collectVars = collectVars;
exports.collectIdentifiers = collectIdentifiers;
exports.normalizeAttributeValue = normalizeAttributeValue;
exports.createTsAst = createTsAst;
exports.generateSfcBlockSection = generateSfcBlockSection;
exports.generateSfcBlockAttrValue = generateSfcBlockAttrValue;
const scriptSetupRanges_1 = require("../../parsers/scriptSetupRanges");
exports.newLine = `\n`;
exports.endOfLine = `;${exports.newLine}`;
exports.combineLastMapping = { __combineOffset: 1 };
exports.identifierRegex = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
function collectVars(ts, node, ast, results = []) {
const identifiers = collectIdentifiers(ts, node, []);
for (const { id } of identifiers) {
results.push((0, scriptSetupRanges_1.getNodeText)(ts, id, ast));
}
return results;
}
function collectIdentifiers(ts, node, results = [], isRest = false, initializer = undefined) {
if (ts.isIdentifier(node)) {
results.push({ id: node, isRest, initializer });
}
else if (ts.isObjectBindingPattern(node)) {
for (const el of node.elements) {
collectIdentifiers(ts, el.name, results, !!el.dotDotDotToken, el.initializer);
}
}
else if (ts.isArrayBindingPattern(node)) {
for (const el of node.elements) {
if (ts.isBindingElement(el)) {
collectIdentifiers(ts, el.name, results, !!el.dotDotDotToken);
}
}
}
else {
ts.forEachChild(node, node => collectIdentifiers(ts, node, results, false));
}
return results;
}
function normalizeAttributeValue(node) {
let offset = node.loc.start.offset;
let content = node.loc.source;
if ((content.startsWith(`'`) && content.endsWith(`'`))
|| (content.startsWith(`"`) && content.endsWith(`"`))) {
offset++;
content = content.slice(1, -1);
}
return [content, offset];
}
function createTsAst(ts, astHolder, text) {
if (astHolder.__volar_ast_text !== text) {
astHolder.__volar_ast_text = text;
astHolder.__volar_ast = ts.createSourceFile('/a.ts', text, 99);
}
return astHolder.__volar_ast;
}
function generateSfcBlockSection(block, start, end, features) {
return [
block.content.slice(start, end),
block.name,
start,
features,
];
}
function* generateSfcBlockAttrValue(src, text, features) {
const { offset, quotes } = src;
if (!quotes) {
yield [``, 'main', offset, { verification: true }];
}
yield [
`'${text}'`,
'main',
quotes ? offset - 1 : offset,
features
];
if (!quotes) {
yield [``, 'main', offset + text.length, { __combineOffset: 2 }];
}
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,2 @@
import type { Code, VueCodeInformation } from '../../types';
export declare function generateStringLiteralKey(code: string, offset?: number, info?: VueCodeInformation): Generator<Code>;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStringLiteralKey = generateStringLiteralKey;
const index_1 = require("./index");
const wrapWith_1 = require("./wrapWith");
function* generateStringLiteralKey(code, offset, info) {
if (offset === undefined || !info) {
yield `'${code}'`;
}
else {
yield* (0, wrapWith_1.wrapWith)(offset, offset + code.length, info, `'`, [code, 'template', offset, index_1.combineLastMapping], `'`);
}
}
//# sourceMappingURL=stringLiteralKey.js.map

View File

@@ -0,0 +1,2 @@
import type { Code, VueCodeInformation } from '../../types';
export declare function generateUnicode(code: string, offset: number, info: VueCodeInformation): Generator<Code>;

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateUnicode = generateUnicode;
const wrapWith_1 = require("./wrapWith");
function* generateUnicode(code, offset, info) {
if (needToUnicode(code)) {
yield* (0, wrapWith_1.wrapWith)(offset, offset + code.length, info, toUnicode(code));
}
else {
yield [code, 'template', offset, info];
}
}
function needToUnicode(str) {
return str.includes('\\') || str.includes('\n');
}
function toUnicode(str) {
return str.split('').map(value => {
const temp = value.charCodeAt(0).toString(16).padStart(4, '0');
if (temp.length > 2) {
return '\\u' + temp;
}
return value;
}).join('');
}
//# sourceMappingURL=unicode.js.map

View File

@@ -0,0 +1,3 @@
import type { Code, VueCodeInformation } from "../../types";
export declare function wrapWith(startOffset: number, endOffset: number, features: VueCodeInformation, ...codes: Code[]): Generator<Code>;
export declare function wrapWith(startOffset: number, endOffset: number, source: string, features: VueCodeInformation, ...codes: Code[]): Generator<Code>;

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.wrapWith = wrapWith;
function* wrapWith(startOffset, endOffset, ...args) {
let source = 'template';
let features;
let codes;
if (typeof args[0] === 'string') {
[source, features, ...codes] = args;
}
else {
[features, ...codes] = args;
}
yield ['', source, startOffset, features];
let offset = 1;
for (const code of codes) {
if (typeof code !== 'string') {
offset++;
}
yield code;
}
yield ['', source, endOffset, { __combineOffset: offset }];
}
//# sourceMappingURL=wrapWith.js.map

View File

@@ -0,0 +1,6 @@
import { LanguagePlugin } from '@volar/language-core';
import type * as ts from 'typescript';
import type { VueCompilerOptions } from './types';
import { VueVirtualCode } from './virtualFile/vueFile';
export declare function createVueLanguagePlugin<T>(ts: typeof import('typescript'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, asFileName: (scriptId: T) => string): LanguagePlugin<T, VueVirtualCode>;
export declare function getAllExtensions(options: VueCompilerOptions): string[];

View File

@@ -0,0 +1,122 @@
"use strict";
/// <reference types="@volar/typescript" />
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVueLanguagePlugin = createVueLanguagePlugin;
exports.getAllExtensions = getAllExtensions;
const language_core_1 = require("@volar/language-core");
const CompilerDOM = require("@vue/compiler-dom");
const plugins_1 = require("./plugins");
const CompilerVue2 = require("./utils/vue2TemplateCompiler");
const vueFile_1 = require("./virtualFile/vueFile");
const fileRegistries = [];
function getVueFileRegistry(key, plugins) {
let fileRegistry = fileRegistries.find(r => r.key === key
&& r.plugins.length === plugins.length
&& r.plugins.every(plugin => plugins.includes(plugin)))?.files;
if (!fileRegistry) {
fileRegistry = new Map();
fileRegistries.push({
key: key,
plugins: plugins,
files: fileRegistry,
});
}
return fileRegistry;
}
function getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins) {
const values = [
...Object.keys(vueCompilerOptions)
.sort()
.filter(key => key !== 'plugins')
.map(key => [key, vueCompilerOptions[key]]),
[...new Set(plugins.map(plugin => plugin.requiredCompilerOptions ?? []).flat())]
.sort()
.map(key => [key, compilerOptions[key]]),
];
return JSON.stringify(values);
}
function createVueLanguagePlugin(ts, compilerOptions, vueCompilerOptions, asFileName) {
const pluginContext = {
modules: {
'@vue/compiler-dom': vueCompilerOptions.target < 3
? {
...CompilerDOM,
compile: CompilerVue2.compile,
}
: CompilerDOM,
typescript: ts,
},
compilerOptions,
vueCompilerOptions,
};
const plugins = (0, plugins_1.createPlugins)(pluginContext);
const fileRegistry = getVueFileRegistry(getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins), vueCompilerOptions.plugins);
return {
getLanguageId(scriptId) {
const fileName = asFileName(scriptId);
for (const plugin of plugins) {
const languageId = plugin.getLanguageId?.(fileName);
if (languageId) {
return languageId;
}
}
},
createVirtualCode(scriptId, languageId, snapshot) {
const fileName = asFileName(scriptId);
if (plugins.some(plugin => plugin.isValidFile?.(fileName, languageId))) {
const code = fileRegistry.get(fileName);
if (code) {
code.update(snapshot);
return code;
}
else {
const code = new vueFile_1.VueVirtualCode(fileName, languageId, snapshot, vueCompilerOptions, plugins, ts);
fileRegistry.set(fileName, code);
return code;
}
}
},
updateVirtualCode(_fileId, code, snapshot) {
code.update(snapshot);
return code;
},
typescript: {
extraFileExtensions: getAllExtensions(vueCompilerOptions)
.map(ext => ({
extension: ext.slice(1),
isMixedContent: true,
scriptKind: 7,
})),
getServiceScript(root) {
for (const code of (0, language_core_1.forEachEmbeddedCode)(root)) {
if (/script_(js|jsx|ts|tsx)/.test(code.id)) {
const lang = code.id.slice('script_'.length);
return {
code,
extension: '.' + lang,
scriptKind: lang === 'js' ? ts.ScriptKind.JS
: lang === 'jsx' ? ts.ScriptKind.JSX
: lang === 'tsx' ? ts.ScriptKind.TSX
: ts.ScriptKind.TS,
};
}
}
},
},
};
}
function getAllExtensions(options) {
const result = new Set();
for (const key in options) {
if (key === 'extensions' || key.endsWith('Extensions')) {
const value = options[key];
if (Array.isArray(value) && value.every(v => typeof v === 'string')) {
for (const ext of value) {
result.add(ext);
}
}
}
}
return [...result];
}
//# sourceMappingURL=languagePlugin.js.map

View File

@@ -0,0 +1,23 @@
import type * as ts from 'typescript';
import type { TextRange } from '../types';
export interface ScriptRanges extends ReturnType<typeof parseScriptRanges> {
}
export declare function parseScriptRanges(ts: typeof import('typescript'), ast: ts.SourceFile, hasScriptSetup: boolean, withNode: boolean): {
exportDefault: (TextRange & {
expression: TextRange;
args: TextRange;
argsNode: ts.ObjectLiteralExpression | undefined;
componentsOption: TextRange | undefined;
componentsOptionNode: ts.ObjectLiteralExpression | undefined;
directivesOption: TextRange | undefined;
nameOption: TextRange | undefined;
inheritAttrsOption: string | undefined;
}) | undefined;
classBlockEnd: number | undefined;
bindings: {
range: TextRange;
moduleName?: string;
isDefaultImport?: boolean;
isNamespace?: boolean;
}[];
};

View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseScriptRanges = parseScriptRanges;
const scriptSetupRanges_1 = require("./scriptSetupRanges");
function parseScriptRanges(ts, ast, hasScriptSetup, withNode) {
let exportDefault;
let classBlockEnd;
const bindings = hasScriptSetup ? (0, scriptSetupRanges_1.parseBindingRanges)(ts, ast) : [];
ts.forEachChild(ast, raw => {
if (ts.isExportAssignment(raw)) {
let node = raw;
while (isAsExpression(node.expression) || ts.isParenthesizedExpression(node.expression)) { // fix https://github.com/vuejs/language-tools/issues/1882
node = node.expression;
}
let obj;
if (ts.isObjectLiteralExpression(node.expression)) {
obj = node.expression;
}
else if (ts.isCallExpression(node.expression) && node.expression.arguments.length) {
const arg0 = node.expression.arguments[0];
if (ts.isObjectLiteralExpression(arg0)) {
obj = arg0;
}
}
if (obj) {
let componentsOptionNode;
let directivesOptionNode;
let nameOptionNode;
let inheritAttrsOption;
ts.forEachChild(obj, node => {
if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
const name = (0, scriptSetupRanges_1.getNodeText)(ts, node.name, ast);
if (name === 'components' && ts.isObjectLiteralExpression(node.initializer)) {
componentsOptionNode = node.initializer;
}
else if (name === 'directives' && ts.isObjectLiteralExpression(node.initializer)) {
directivesOptionNode = node.initializer;
}
else if (name === 'name') {
nameOptionNode = node.initializer;
}
else if (name === 'inheritAttrs') {
inheritAttrsOption = (0, scriptSetupRanges_1.getNodeText)(ts, node.initializer, ast);
}
}
});
exportDefault = {
..._getStartEnd(raw),
expression: _getStartEnd(node.expression),
args: _getStartEnd(obj),
argsNode: withNode ? obj : undefined,
componentsOption: componentsOptionNode ? _getStartEnd(componentsOptionNode) : undefined,
componentsOptionNode: withNode ? componentsOptionNode : undefined,
directivesOption: directivesOptionNode ? _getStartEnd(directivesOptionNode) : undefined,
nameOption: nameOptionNode ? _getStartEnd(nameOptionNode) : undefined,
inheritAttrsOption,
};
}
}
if (ts.isClassDeclaration(raw)
&& raw.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)
&& raw.modifiers?.some(mod => mod.kind === ts.SyntaxKind.DefaultKeyword)) {
classBlockEnd = raw.end - 1;
}
});
return {
exportDefault,
classBlockEnd,
bindings,
};
function _getStartEnd(node) {
return (0, scriptSetupRanges_1.getStartEnd)(ts, node, ast);
}
// isAsExpression is missing in tsc
function isAsExpression(node) {
return node.kind === ts.SyntaxKind.AsExpression;
}
}
//# sourceMappingURL=scriptRanges.js.map

View File

@@ -0,0 +1,79 @@
import type * as ts from 'typescript';
import type { TextRange, VueCompilerOptions } from '../types';
type CallExpressionRange = {
callExp: TextRange;
exp: TextRange;
arg?: TextRange;
typeArg?: TextRange;
};
type DefineProp = {
localName?: TextRange;
name?: TextRange;
type?: TextRange;
modifierType?: TextRange;
runtimeType?: TextRange;
defaultValue?: TextRange;
required?: boolean;
isModel?: boolean;
comments?: TextRange;
argNode?: ts.Expression;
};
type DefineProps = CallExpressionRange & {
name?: string;
destructured?: Map<string, ts.Expression | undefined>;
destructuredRest?: string;
statement: TextRange;
argNode?: ts.Expression;
};
type WithDefaults = Omit<CallExpressionRange, 'typeArg'> & {
argNode?: ts.Expression;
};
type DefineEmits = CallExpressionRange & {
name?: string;
hasUnionTypeArg?: boolean;
statement: TextRange;
};
type DefineSlots = CallExpressionRange & {
name?: string;
statement: TextRange;
};
type DefineOptions = {
name?: string;
inheritAttrs?: string;
};
type UseTemplateRef = CallExpressionRange & {
name?: string;
};
export interface ScriptSetupRanges extends ReturnType<typeof parseScriptSetupRanges> {
}
export declare function parseScriptSetupRanges(ts: typeof import('typescript'), ast: ts.SourceFile, vueCompilerOptions: VueCompilerOptions): {
leadingCommentEndOffset: number;
importSectionEndOffset: number;
bindings: {
range: TextRange;
moduleName?: string;
isDefaultImport?: boolean;
isNamespace?: boolean;
}[];
defineProp: DefineProp[];
defineProps: DefineProps | undefined;
withDefaults: WithDefaults | undefined;
defineEmits: DefineEmits | undefined;
defineSlots: DefineSlots | undefined;
defineExpose: CallExpressionRange | undefined;
defineOptions: DefineOptions | undefined;
useAttrs: CallExpressionRange[];
useCssModule: CallExpressionRange[];
useSlots: CallExpressionRange[];
useTemplateRef: UseTemplateRef[];
};
export declare function parseBindingRanges(ts: typeof import('typescript'), ast: ts.SourceFile): {
range: TextRange;
moduleName?: string;
isDefaultImport?: boolean;
isNamespace?: boolean;
}[];
export declare function findBindingVars(ts: typeof import('typescript'), left: ts.BindingName, ast: ts.SourceFile): TextRange[];
export declare function getStartEnd(ts: typeof import('typescript'), node: ts.Node, ast: ts.SourceFile): TextRange;
export declare function getNodeText(ts: typeof import('typescript'), node: ts.Node, ast: ts.SourceFile): string;
export {};

View File

@@ -0,0 +1,440 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseScriptSetupRanges = parseScriptSetupRanges;
exports.parseBindingRanges = parseBindingRanges;
exports.findBindingVars = findBindingVars;
exports.getStartEnd = getStartEnd;
exports.getNodeText = getNodeText;
const utils_1 = require("../codegen/utils");
const tsCheckReg = /^\/\/\s*@ts-(?:no)?check($|\s)/;
function parseScriptSetupRanges(ts, ast, vueCompilerOptions) {
const defineProp = [];
let defineProps;
let withDefaults;
let defineEmits;
let defineSlots;
let defineExpose;
let defineOptions;
const useAttrs = [];
const useCssModule = [];
const useSlots = [];
const useTemplateRef = [];
const definePropProposalA = vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition';
const definePropProposalB = vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition';
const text = ast.text;
const leadingCommentRanges = ts.getLeadingCommentRanges(text, 0)?.reverse() ?? [];
const leadingCommentEndOffset = leadingCommentRanges.find(range => tsCheckReg.test(text.slice(range.pos, range.end)))?.end ?? 0;
let bindings = parseBindingRanges(ts, ast);
let foundNonImportExportNode = false;
let importSectionEndOffset = 0;
ts.forEachChild(ast, node => {
const isTypeExport = (ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node))
&& node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword);
if (!foundNonImportExportNode
&& !ts.isImportDeclaration(node)
&& !isTypeExport
&& !ts.isEmptyStatement(node)
// fix https://github.com/vuejs/language-tools/issues/1223
&& !ts.isImportEqualsDeclaration(node)) {
const commentRanges = ts.getLeadingCommentRanges(text, node.pos);
if (commentRanges?.length) {
const commentRange = commentRanges.sort((a, b) => a.pos - b.pos)[0];
importSectionEndOffset = commentRange.pos;
}
else {
importSectionEndOffset = getStartEnd(ts, node, ast).start;
}
foundNonImportExportNode = true;
}
});
ts.forEachChild(ast, node => visitNode(node, [ast]));
const templateRefNames = new Set(useTemplateRef.map(ref => ref.name));
bindings = bindings.filter(({ range }) => {
const name = text.slice(range.start, range.end);
return !templateRefNames.has(name);
});
return {
leadingCommentEndOffset,
importSectionEndOffset,
bindings,
defineProp,
defineProps,
withDefaults,
defineEmits,
defineSlots,
defineExpose,
defineOptions,
useAttrs,
useCssModule,
useSlots,
useTemplateRef,
};
function visitNode(node, parents) {
const parent = parents[parents.length - 1];
if (ts.isCallExpression(node)
&& ts.isIdentifier(node.expression)) {
const callText = _getNodeText(node.expression);
const isDefineModel = vueCompilerOptions.macros.defineModel.includes(callText);
if (isDefineModel || callText === 'defineProp') {
let localName;
let propName;
let options;
let type;
let modifierType;
let runtimeType;
let defaultValue;
let required = false;
if (ts.isVariableDeclaration(parent) &&
ts.isIdentifier(parent.name)) {
localName = _getStartEnd(parent.name);
}
if (node.typeArguments) {
if (node.typeArguments.length >= 1) {
type = _getStartEnd(node.typeArguments[0]);
}
if (node.typeArguments.length >= 2) {
modifierType = _getStartEnd(node.typeArguments[1]);
}
}
if (isDefineModel) {
if (node.arguments.length >= 2) {
propName = node.arguments[0];
options = node.arguments[1];
}
else if (node.arguments.length >= 1) {
if (ts.isStringLiteralLike(node.arguments[0])) {
propName = node.arguments[0];
}
else {
options = node.arguments[0];
}
}
}
else if (definePropProposalA) {
if (node.arguments.length >= 2) {
options = node.arguments[1];
}
if (node.arguments.length >= 1) {
propName = node.arguments[0];
}
}
else if (definePropProposalB) {
if (node.arguments.length >= 3) {
options = node.arguments[2];
}
if (node.arguments.length >= 2) {
if (node.arguments[1].kind === ts.SyntaxKind.TrueKeyword) {
required = true;
}
}
if (node.arguments.length >= 1) {
defaultValue = _getStartEnd(node.arguments[0]);
}
}
if (options && ts.isObjectLiteralExpression(options)) {
for (const property of options.properties) {
if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) {
continue;
}
const text = _getNodeText(property.name);
if (text === 'type') {
runtimeType = _getStartEnd(property.initializer);
}
else if (text === 'default') {
defaultValue = _getStartEnd(property.initializer);
}
else if (text === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) {
required = true;
}
}
}
let name;
if (propName && ts.isStringLiteralLike(propName)) {
name = _getStartEnd(propName);
}
defineProp.push({
localName,
name,
type,
modifierType,
runtimeType,
defaultValue,
required,
isModel: isDefineModel,
comments: getCommentsRange(ts, node, parents, ast),
argNode: options,
});
}
else if (vueCompilerOptions.macros.defineProps.includes(callText)) {
defineProps = {
...parseCallExpressionAssignment(node, parent),
statement: getStatementRange(ts, parents, node, ast),
argNode: node.arguments[0]
};
if (ts.isVariableDeclaration(parent) && ts.isObjectBindingPattern(parent.name)) {
defineProps.destructured = new Map();
const identifiers = (0, utils_1.collectIdentifiers)(ts, parent.name, []);
for (const { id, isRest, initializer } of identifiers) {
const name = _getNodeText(id);
if (isRest) {
defineProps.destructuredRest = name;
}
else {
defineProps.destructured.set(name, initializer);
}
}
}
else if (ts.isCallExpression(parent)
&& vueCompilerOptions.macros.withDefaults.includes(_getNodeText(parent.expression))) {
const grand = parents.at(-2);
if (grand && ts.isVariableDeclaration(grand)) {
defineProps.name = _getNodeText(grand.name);
}
}
}
else if (vueCompilerOptions.macros.withDefaults.includes(callText)) {
const [, arg] = node.arguments;
withDefaults = {
callExp: _getStartEnd(node),
exp: _getStartEnd(node.expression),
arg: arg ? _getStartEnd(arg) : undefined,
argNode: arg
};
}
else if (vueCompilerOptions.macros.defineEmits.includes(callText)) {
defineEmits = {
...parseCallExpressionAssignment(node, parent),
statement: getStatementRange(ts, parents, node, ast)
};
if (node.typeArguments?.length && ts.isTypeLiteralNode(node.typeArguments[0])) {
for (const member of node.typeArguments[0].members) {
if (ts.isCallSignatureDeclaration(member)) {
const type = member.parameters[0]?.type;
if (type && ts.isUnionTypeNode(type)) {
defineEmits.hasUnionTypeArg = true;
break;
}
}
}
}
}
else if (vueCompilerOptions.macros.defineSlots.includes(callText)) {
defineSlots = {
...parseCallExpressionAssignment(node, parent),
statement: getStatementRange(ts, parents, node, ast)
};
}
else if (vueCompilerOptions.macros.defineExpose.includes(callText)) {
defineExpose = parseCallExpression(node);
}
else if (vueCompilerOptions.macros.defineOptions.includes(callText)
&& node.arguments.length
&& ts.isObjectLiteralExpression(node.arguments[0])) {
defineOptions = {};
const obj = node.arguments[0];
for (const prop of obj.properties) {
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
const name = _getNodeText(prop.name);
if (name === 'inheritAttrs') {
defineOptions.inheritAttrs = _getNodeText(prop.initializer);
}
else if (name === 'name' && ts.isStringLiteral(prop.initializer)) {
defineOptions.name = prop.initializer.text;
}
}
}
}
else if (vueCompilerOptions.composables.useAttrs.includes(callText)) {
useAttrs.push(parseCallExpression(node));
}
else if (vueCompilerOptions.composables.useCssModule.includes(callText)) {
useCssModule.push(parseCallExpression(node));
}
else if (vueCompilerOptions.composables.useSlots.includes(callText)) {
useSlots.push(parseCallExpression(node));
}
else if (vueCompilerOptions.composables.useTemplateRef.includes(callText)
&& !node.typeArguments?.length) {
useTemplateRef.push(parseCallExpressionAssignment(node, parent));
}
}
ts.forEachChild(node, child => {
if (ts.isFunctionLike(node)) {
return;
}
parents.push(node);
visitNode(child, parents);
parents.pop();
});
}
function parseCallExpression(node) {
return {
callExp: _getStartEnd(node),
exp: _getStartEnd(node.expression),
arg: node.arguments.length ? _getStartEnd(node.arguments[0]) : undefined,
typeArg: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
};
}
function parseCallExpressionAssignment(node, parent) {
return {
name: ts.isVariableDeclaration(parent) ? _getNodeText(parent.name) : undefined,
...parseCallExpression(node),
};
}
function _getStartEnd(node) {
return getStartEnd(ts, node, ast);
}
function _getNodeText(node) {
return getNodeText(ts, node, ast);
}
}
function parseBindingRanges(ts, ast) {
const bindings = [];
ts.forEachChild(ast, node => {
if (ts.isVariableStatement(node)) {
for (const decl of node.declarationList.declarations) {
const vars = _findBindingVars(decl.name);
bindings.push(...vars.map(range => ({ range })));
}
}
else if (ts.isFunctionDeclaration(node)) {
if (node.name && ts.isIdentifier(node.name)) {
bindings.push({
range: _getStartEnd(node.name)
});
}
}
else if (ts.isClassDeclaration(node)) {
if (node.name) {
bindings.push({
range: _getStartEnd(node.name)
});
}
}
else if (ts.isEnumDeclaration(node)) {
bindings.push({
range: _getStartEnd(node.name)
});
}
if (ts.isImportDeclaration(node)) {
const moduleName = _getNodeText(node.moduleSpecifier).slice(1, -1);
if (node.importClause && !node.importClause.isTypeOnly) {
const { name, namedBindings } = node.importClause;
if (name) {
bindings.push({
range: _getStartEnd(name),
moduleName,
isDefaultImport: true
});
}
if (namedBindings) {
if (ts.isNamedImports(namedBindings)) {
for (const element of namedBindings.elements) {
if (element.isTypeOnly) {
continue;
}
bindings.push({
range: _getStartEnd(element.name),
moduleName,
isDefaultImport: element.propertyName?.text === 'default'
});
}
}
else {
bindings.push({
range: _getStartEnd(namedBindings.name),
moduleName,
isNamespace: true
});
}
}
}
}
});
return bindings;
function _getStartEnd(node) {
return getStartEnd(ts, node, ast);
}
function _getNodeText(node) {
return getNodeText(ts, node, ast);
}
function _findBindingVars(left) {
return findBindingVars(ts, left, ast);
}
}
function findBindingVars(ts, left, ast) {
const vars = [];
worker(left);
return vars;
function worker(node) {
if (ts.isIdentifier(node)) {
vars.push(getStartEnd(ts, node, ast));
}
// { ? } = ...
// [ ? ] = ...
else if (ts.isObjectBindingPattern(node) || ts.isArrayBindingPattern(node)) {
for (const property of node.elements) {
if (ts.isBindingElement(property)) {
worker(property.name);
}
}
}
// { foo: ? } = ...
else if (ts.isPropertyAssignment(node)) {
worker(node.initializer);
}
// { foo } = ...
else if (ts.isShorthandPropertyAssignment(node)) {
vars.push(getStartEnd(ts, node.name, ast));
}
// { ...? } = ...
// [ ...? ] = ...
else if (ts.isSpreadAssignment(node) || ts.isSpreadElement(node)) {
worker(node.expression);
}
}
}
function getStartEnd(ts, node, ast) {
return {
start: ts.getTokenPosOfNode(node, ast),
end: node.end,
};
}
function getNodeText(ts, node, ast) {
const { start, end } = getStartEnd(ts, node, ast);
return ast.text.slice(start, end);
}
function getStatementRange(ts, parents, node, ast) {
let statementRange;
for (let i = parents.length - 1; i >= 0; i--) {
if (ts.isStatement(parents[i])) {
const statement = parents[i];
ts.forEachChild(statement, child => {
const range = getStartEnd(ts, child, ast);
statementRange ??= range;
statementRange.end = range.end;
});
break;
}
}
if (!statementRange) {
statementRange = getStartEnd(ts, node, ast);
}
return statementRange;
}
function getCommentsRange(ts, node, parents, ast) {
for (let i = parents.length - 1; i >= 0; i--) {
if (ts.isStatement(node)) {
break;
}
node = parents[i];
}
const comments = ts.getLeadingCommentRanges(ast.text, node.pos);
if (comments?.length) {
return {
start: comments[0].pos,
end: comments.at(-1).end,
};
}
}
//# sourceMappingURL=scriptSetupRanges.js.map

View File

@@ -0,0 +1,2 @@
import type { RawVueCompilerOptions } from '../types';
export declare function parseVueCompilerOptions(comments: string[]): RawVueCompilerOptions | undefined;

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseVueCompilerOptions = parseVueCompilerOptions;
const syntaxReg = /^\s*@(?<key>.+?)\s+(?<value>.+?)\s*$/m;
function parseVueCompilerOptions(comments) {
const entries = comments
.map(text => {
try {
const match = text.match(syntaxReg);
if (match) {
const { key, value } = match.groups ?? {};
return [key, JSON.parse(value)];
}
}
catch { }
;
})
.filter(item => !!item);
if (entries.length) {
return Object.fromEntries(entries);
}
}
//# sourceMappingURL=vueCompilerOptions.js.map

View File

@@ -0,0 +1,3 @@
import { VueLanguagePlugin } from './types';
export * from './plugins/shared';
export declare function createPlugins(pluginContext: Parameters<VueLanguagePlugin>[0]): import("./types").VueLanguagePluginReturn[];

83
web-app/node_modules/@vue/language-core/lib/plugins.js generated vendored Normal file
View File

@@ -0,0 +1,83 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPlugins = createPlugins;
const file_html_1 = require("./plugins/file-html");
const file_md_1 = require("./plugins/file-md");
const file_vue_1 = require("./plugins/file-vue");
const vue_root_tags_1 = require("./plugins/vue-root-tags");
const vue_script_js_1 = require("./plugins/vue-script-js");
const vue_sfc_customblocks_1 = require("./plugins/vue-sfc-customblocks");
const vue_sfc_scripts_1 = require("./plugins/vue-sfc-scripts");
const vue_sfc_styles_1 = require("./plugins/vue-sfc-styles");
const vue_sfc_template_1 = require("./plugins/vue-sfc-template");
const vue_template_html_1 = require("./plugins/vue-template-html");
const vue_template_inline_css_1 = require("./plugins/vue-template-inline-css");
const vue_template_inline_ts_1 = require("./plugins/vue-template-inline-ts");
const vue_tsx_1 = require("./plugins/vue-tsx");
const types_1 = require("./types");
__exportStar(require("./plugins/shared"), exports);
function createPlugins(pluginContext) {
const plugins = [
file_vue_1.default,
file_md_1.default,
file_html_1.default,
vue_root_tags_1.default,
vue_script_js_1.default,
vue_template_html_1.default,
vue_template_inline_css_1.default,
vue_template_inline_ts_1.default,
vue_sfc_styles_1.default,
vue_sfc_customblocks_1.default,
vue_sfc_scripts_1.default,
vue_sfc_template_1.default,
vue_tsx_1.default,
...pluginContext.vueCompilerOptions.plugins,
];
const pluginInstances = plugins
.flatMap(plugin => {
try {
const instance = plugin(pluginContext);
const moduleName = plugin.__moduleName;
if (Array.isArray(instance)) {
for (let i = 0; i < instance.length; i++) {
instance[i].name ??= `${moduleName} (${i})`;
}
}
else {
instance.name ??= moduleName;
}
return instance;
}
catch (err) {
console.warn('[Vue] Failed to create plugin', err);
}
})
.filter(plugin => !!plugin)
.sort((a, b) => {
const aOrder = a.order ?? 0;
const bOrder = b.order ?? 0;
return aOrder - bOrder;
});
return pluginInstances.filter(plugin => {
if (!types_1.validVersions.includes(plugin.version)) {
console.warn(`[Vue] Plugin ${plugin.name} is not compatible with the current Vue language tools version. (version: ${plugin.version}, supported versions: ${JSON.stringify(types_1.validVersions)})`);
return false;
}
return true;
});
}
//# sourceMappingURL=plugins.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sfcBlockReg = /\<(script|style)\b([\s\S]*?)\>([\s\S]*?)\<\/\1\>/g;
const langReg = /\blang\s*=\s*(['\"]?)(\S*)\b\1/;
const plugin = ({ vueCompilerOptions }) => {
return {
version: 2.1,
getLanguageId(fileName) {
if (vueCompilerOptions.petiteVueExtensions.some(ext => fileName.endsWith(ext))) {
return 'html';
}
},
isValidFile(_fileName, languageId) {
return languageId === 'html';
},
parseSFC2(fileName, languageId, content) {
if (languageId !== 'html') {
return;
}
let sfc = {
descriptor: {
filename: fileName,
source: content,
comments: [],
template: null,
script: null,
scriptSetup: null,
styles: [],
customBlocks: [],
cssVars: [],
shouldForceReload: () => false,
slotted: false,
},
errors: [],
};
let templateContent = content;
for (const match of content.matchAll(sfcBlockReg)) {
const matchText = match[0];
const tag = match[1];
const attrs = match[2];
const lang = attrs.match(langReg)?.[2];
const content = match[3];
const contentStart = match.index + matchText.indexOf(content);
if (tag === 'style') {
sfc.descriptor.styles.push({
attrs: {},
content,
loc: {
start: { column: -1, line: -1, offset: contentStart },
end: { column: -1, line: -1, offset: contentStart + content.length },
source: content,
},
type: 'style',
lang,
});
}
// ignore `<script src="...">`
else if (tag === 'script' && !attrs.includes('src=')) {
let type = attrs.includes('type=') ? 'scriptSetup' : 'script';
sfc.descriptor[type] = {
attrs: {},
content,
loc: {
start: { column: -1, line: -1, offset: contentStart },
end: { column: -1, line: -1, offset: contentStart + content.length },
source: content,
},
type: 'script',
lang,
};
}
templateContent = templateContent.slice(0, match.index) + ' '.repeat(matchText.length) + templateContent.slice(match.index + matchText.length);
}
sfc.descriptor.template = {
attrs: {},
content: templateContent,
loc: {
start: { column: -1, line: -1, offset: 0 },
end: { column: -1, line: -1, offset: templateContent.length },
source: templateContent,
},
type: 'template',
ast: {},
};
return sfc;
}
};
};
exports.default = plugin;
//# sourceMappingURL=file-html.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const language_core_1 = require("@volar/language-core");
const muggle_string_1 = require("muggle-string");
const buildMappings_1 = require("../utils/buildMappings");
const parseSfc_1 = require("../utils/parseSfc");
const codeblockReg = /(`{3,})[\s\S]+?\1/g;
const inlineCodeblockReg = /`[^\n`]+?`/g;
const latexBlockReg = /(\${2,})[\s\S]+?\1/g;
const scriptSetupReg = /\\\<[\s\S]+?\>\n?/g;
const sfcBlockReg = /\<(script|style)\b[\s\S]*?\>([\s\S]*?)\<\/\1\>/g;
const angleBracketReg = /\<\S*\:\S*\>/g;
const linkReg = /\[[\s\S]*?\]\([\s\S]*?\)/g;
const codeSnippetImportReg = /^\s*<<<\s*.+/gm;
const plugin = ({ vueCompilerOptions }) => {
return {
version: 2.1,
getLanguageId(fileName) {
if (vueCompilerOptions.vitePressExtensions.some(ext => fileName.endsWith(ext))) {
return 'markdown';
}
},
isValidFile(_fileName, languageId) {
return languageId === 'markdown';
},
parseSFC2(_fileName, languageId, content) {
if (languageId !== 'markdown') {
return;
}
content = content
// code block
.replace(codeblockReg, (match, quotes) => quotes + ' '.repeat(match.length - quotes.length * 2) + quotes)
// inline code block
.replace(inlineCodeblockReg, match => `\`${' '.repeat(match.length - 2)}\``)
// latex block
.replace(latexBlockReg, (match, quotes) => quotes + ' '.repeat(match.length - quotes.length * 2) + quotes)
// # \<script setup>
.replace(scriptSetupReg, match => ' '.repeat(match.length))
// <<< https://vitepress.dev/guide/markdown#import-code-snippets
.replace(codeSnippetImportReg, match => ' '.repeat(match.length));
const codes = [];
for (const match of content.matchAll(sfcBlockReg)) {
if (match.index !== undefined) {
const matchText = match[0];
codes.push([matchText, undefined, match.index]);
codes.push('\n\n');
content = content.slice(0, match.index) + ' '.repeat(matchText.length) + content.slice(match.index + matchText.length);
}
}
content = content
// angle bracket: <http://foo.com>
.replace(angleBracketReg, match => ' '.repeat(match.length))
// [foo](http://foo.com)
.replace(linkReg, match => ' '.repeat(match.length));
codes.push('<template>\n');
codes.push([content, undefined, 0]);
codes.push('\n</template>');
const file2VueSourceMap = (0, language_core_1.defaultMapperFactory)((0, buildMappings_1.buildMappings)(codes));
const sfc = (0, parseSfc_1.parse)((0, muggle_string_1.toString)(codes));
if (sfc.descriptor.template) {
sfc.descriptor.template.lang = 'md';
transformRange(sfc.descriptor.template);
}
if (sfc.descriptor.script) {
transformRange(sfc.descriptor.script);
}
if (sfc.descriptor.scriptSetup) {
transformRange(sfc.descriptor.scriptSetup);
}
for (const style of sfc.descriptor.styles) {
transformRange(style);
}
for (const customBlock of sfc.descriptor.customBlocks) {
transformRange(customBlock);
}
return sfc;
function transformRange(block) {
const { start, end } = block.loc;
const startOffset = start.offset;
const endOffset = end.offset;
start.offset = -1;
end.offset = -1;
for (const [offset] of file2VueSourceMap.toSourceLocation(startOffset)) {
start.offset = offset;
break;
}
for (const [offset] of file2VueSourceMap.toSourceLocation(endOffset)) {
end.offset = offset;
break;
}
}
}
};
};
exports.default = plugin;
//# sourceMappingURL=file-md.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const parseSfc_1 = require("../utils/parseSfc");
const plugin = ({ vueCompilerOptions }) => {
return {
version: 2.1,
getLanguageId(fileName) {
if (vueCompilerOptions.extensions.some(ext => fileName.endsWith(ext))) {
return 'vue';
}
},
isValidFile(_fileName, languageId) {
return languageId === 'vue';
},
parseSFC2(_fileName, languageId, content) {
if (languageId !== 'vue') {
return;
}
return (0, parseSfc_1.parse)(content);
},
updateSFC(sfc, change) {
const blocks = [
sfc.descriptor.template,
sfc.descriptor.script,
sfc.descriptor.scriptSetup,
...sfc.descriptor.styles,
...sfc.descriptor.customBlocks,
].filter(block => !!block);
const hitBlock = blocks.find(block => change.start >= block.loc.start.offset && change.end <= block.loc.end.offset);
if (!hitBlock) {
return;
}
const oldContent = hitBlock.content;
const newContent = hitBlock.content =
hitBlock.content.slice(0, change.start - hitBlock.loc.start.offset)
+ change.newText
+ hitBlock.content.slice(change.end - hitBlock.loc.start.offset);
// #3449
const endTagRegex = new RegExp(`</\\s*${hitBlock.type}\\s*>`);
const insertedEndTag = endTagRegex.test(oldContent) !== endTagRegex.test(newContent);
if (insertedEndTag) {
return;
}
const lengthDiff = change.newText.length - (change.end - change.start);
for (const block of blocks) {
if (block.loc.start.offset > change.end) {
block.loc.start.offset += lengthDiff;
}
if (block.loc.end.offset >= change.end) {
block.loc.end.offset += lengthDiff;
}
}
return sfc;
},
};
};
exports.default = plugin;
//# sourceMappingURL=file-vue.js.map

View File

@@ -0,0 +1,2 @@
import type { CodeInformation } from '@volar/language-core';
export declare const allCodeFeatures: CodeInformation;

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.allCodeFeatures = void 0;
exports.allCodeFeatures = {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: true,
};
//# sourceMappingURL=shared.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const muggle_string_1 = require("muggle-string");
const shared_1 = require("./shared");
const plugin = () => {
return {
version: 2.1,
getEmbeddedCodes() {
return [{
id: 'root_tags',
lang: 'vue-root-tags',
}];
},
resolveEmbeddedCode(_fileName, sfc, embeddedFile) {
if (embeddedFile.id === 'root_tags') {
embeddedFile.content.push([sfc.content, undefined, 0, shared_1.allCodeFeatures]);
for (const block of [
sfc.script,
sfc.scriptSetup,
sfc.template,
...sfc.styles,
...sfc.customBlocks,
]) {
if (!block) {
continue;
}
let content = block.content;
if (content.endsWith('\r\n')) {
content = content.slice(0, -2);
}
else if (content.endsWith('\n')) {
content = content.slice(0, -1);
}
const offset = content.lastIndexOf('\n') + 1;
// fix folding range end position failed to mapping
(0, muggle_string_1.replaceSourceRange)(embeddedFile.content, undefined, block.startTagEnd, block.endTagStart, sfc.content.slice(block.startTagEnd, block.startTagEnd + offset), [
'',
undefined,
block.startTagEnd + offset,
{ structure: true },
], sfc.content.slice(block.startTagEnd + offset, block.endTagStart));
}
}
else {
embeddedFile.parentCodeId ??= 'root_tags';
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-root-tags.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const plugin = ({ modules }) => {
return {
version: 2.1,
compileSFCScript(lang, script) {
if (lang === 'js' || lang === 'ts' || lang === 'jsx' || lang === 'tsx') {
const ts = modules.typescript;
return ts.createSourceFile('test.' + lang, script, 99);
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-script-js.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const shared_1 = require("./shared");
const plugin = () => {
return {
version: 2.1,
getEmbeddedCodes(_fileName, sfc) {
return sfc.customBlocks.map((customBlock, i) => ({
id: 'custom_block_' + i,
lang: customBlock.lang,
}));
},
resolveEmbeddedCode(_fileName, sfc, embeddedFile) {
if (embeddedFile.id.startsWith('custom_block_')) {
const index = parseInt(embeddedFile.id.slice('custom_block_'.length));
const customBlock = sfc.customBlocks[index];
embeddedFile.content.push([
customBlock.content,
customBlock.name,
0,
shared_1.allCodeFeatures,
]);
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-sfc-customblocks.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const plugin = () => {
return {
version: 2.1,
getEmbeddedCodes(_fileName, sfc) {
const names = [];
if (sfc.script) {
names.push({ id: 'script_raw', lang: sfc.script.lang });
}
if (sfc.scriptSetup) {
names.push({ id: 'scriptsetup_raw', lang: sfc.scriptSetup.lang });
}
return names;
},
resolveEmbeddedCode(_fileName, sfc, embeddedFile) {
const script = embeddedFile.id === 'script_raw' ? sfc.script
: embeddedFile.id === 'scriptsetup_raw' ? sfc.scriptSetup
: undefined;
if (script) {
embeddedFile.content.push([
script.content,
script.name,
0,
{
structure: true,
format: true,
},
]);
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-sfc-scripts.js.map

View File

@@ -0,0 +1,3 @@
import type { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;

View File

@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const shared_1 = require("./shared");
const plugin = () => {
return {
version: 2.1,
getEmbeddedCodes(_fileName, sfc) {
const result = [];
for (let i = 0; i < sfc.styles.length; i++) {
const style = sfc.styles[i];
if (style) {
result.push({
id: 'style_' + i,
lang: style.lang,
});
if (style.cssVars.length) {
result.push({
id: 'style_' + i + '_inline_ts',
lang: 'ts',
});
}
}
}
return result;
},
resolveEmbeddedCode(_fileName, sfc, embeddedFile) {
if (embeddedFile.id.startsWith('style_')) {
const index = parseInt(embeddedFile.id.split('_')[1]);
const style = sfc.styles[index];
if (embeddedFile.id.endsWith('_inline_ts')) {
embeddedFile.parentCodeId = 'style_' + index;
for (const cssVar of style.cssVars) {
embeddedFile.content.push('(', [
cssVar.text,
style.name,
cssVar.offset,
shared_1.allCodeFeatures,
], ');\n');
}
}
else {
embeddedFile.content.push([
style.content,
style.name,
0,
shared_1.allCodeFeatures,
]);
}
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-sfc-styles.js.map

Some files were not shown because too many files have changed in this diff Show More