Sort le serveur dans une crate pmoserver

This commit is contained in:
2025-10-06 06:01:41 +02:00
parent 11cfd3e27f
commit 6c13e8cb8e
1229 changed files with 532967 additions and 140 deletions

21
pmoapp/webapp/node_modules/@vue/language-core/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-present Johnson Chu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,13 @@
export * from './lib/codegen/globalTypes';
export * from './lib/codegen/template';
export * from './lib/compilerOptions';
export * from './lib/languagePlugin';
export * from './lib/parsers/scriptSetupRanges';
export * from './lib/plugins';
export * from './lib/types';
export * from './lib/utils/collectBindings';
export * from './lib/utils/parseSfc';
export * from './lib/utils/shared';
export * from './lib/virtualFile/vueFile';
export { tsCodegen } from './lib/plugins/vue-tsx';
export * from '@volar/language-core';

32
pmoapp/webapp/node_modules/@vue/language-core/index.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
"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.tsCodegen = void 0;
__exportStar(require("./lib/codegen/globalTypes"), exports);
__exportStar(require("./lib/codegen/template"), exports);
__exportStar(require("./lib/compilerOptions"), exports);
__exportStar(require("./lib/languagePlugin"), exports);
__exportStar(require("./lib/parsers/scriptSetupRanges"), exports);
__exportStar(require("./lib/plugins"), exports);
__exportStar(require("./lib/types"), exports);
__exportStar(require("./lib/utils/collectBindings"), exports);
__exportStar(require("./lib/utils/parseSfc"), exports);
__exportStar(require("./lib/utils/shared"), exports);
__exportStar(require("./lib/virtualFile/vueFile"), exports);
var vue_tsx_1 = require("./lib/plugins/vue-tsx");
Object.defineProperty(exports, "tsCodegen", { enumerable: true, get: function () { return vue_tsx_1.tsCodegen; } });
__exportStar(require("@volar/language-core"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,90 @@
import type { VueCodeInformation } from '../types';
declare const raw: {
all: {
verification: true;
completion: true;
semantic: true;
navigation: true;
};
verification: {
verification: true;
};
completion: {
completion: true;
};
additionalCompletion: {
completion: {
isAdditional: true;
};
};
withoutCompletion: {
verification: true;
semantic: true;
navigation: true;
};
navigation: {
navigation: true;
};
navigationWithoutRename: {
navigation: {
shouldRename: () => false;
};
};
navigationAndAdditionalCompletion: {
navigation: true;
completion: {
isAdditional: true;
};
};
navigationAndVerification: {
navigation: true;
verification: true;
};
withoutNavigation: {
verification: true;
completion: true;
semantic: true;
};
semanticWithoutHighlight: {
semantic: {
shouldHighlight: () => false;
};
};
withoutHighlight: {
semantic: {
shouldHighlight: () => false;
};
verification: true;
navigation: true;
completion: true;
};
withoutHighlightAndCompletion: {
semantic: {
shouldHighlight: () => false;
};
verification: true;
navigation: true;
};
withoutSemantic: {
verification: true;
navigation: true;
completion: true;
};
doNotReportTs2339AndTs2551: {
verification: {
shouldReport: (_source: string | undefined, code: string | number | undefined) => boolean;
};
};
doNotReportTs2353AndTs2561: {
verification: {
shouldReport: (_source: string | undefined, code: string | number | undefined) => boolean;
};
};
doNotReportTs6133: {
verification: {
shouldReport: (_source: string | undefined, code: string | number | undefined) => boolean;
};
};
};
export declare const codeFeatures: { [K in keyof typeof raw]: VueCodeInformation; };
export {};

View File

@@ -0,0 +1,85 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.codeFeatures = void 0;
const raw = {
all: {
verification: true,
completion: true,
semantic: true,
navigation: true,
},
verification: {
verification: true,
},
completion: {
completion: true,
},
additionalCompletion: {
completion: { isAdditional: true },
},
withoutCompletion: {
verification: true,
semantic: true,
navigation: true,
},
navigation: {
navigation: true,
},
navigationWithoutRename: {
navigation: { shouldRename: () => false },
},
navigationAndAdditionalCompletion: {
navigation: true,
completion: { isAdditional: true },
},
navigationAndVerification: {
navigation: true,
verification: true,
},
withoutNavigation: {
verification: true,
completion: true,
semantic: true,
},
semanticWithoutHighlight: {
semantic: { shouldHighlight: () => false },
},
withoutHighlight: {
semantic: { shouldHighlight: () => false },
verification: true,
navigation: true,
completion: true,
},
withoutHighlightAndCompletion: {
semantic: { shouldHighlight: () => false },
verification: true,
navigation: true,
},
withoutSemantic: {
verification: true,
navigation: true,
completion: true,
},
doNotReportTs2339AndTs2551: {
verification: {
// https://typescript.tv/errors/#ts2339
// https://typescript.tv/errors/#ts2551
shouldReport: (_source, code) => String(code) !== '2339' && String(code) !== '2551',
},
},
doNotReportTs2353AndTs2561: {
verification: {
// https://typescript.tv/errors/#ts2353
// https://typescript.tv/errors/#ts2561
shouldReport: (_source, code) => String(code) !== '2353' && String(code) !== '2561',
},
},
doNotReportTs6133: {
verification: {
// https://typescript.tv/errors/#ts6133
shouldReport: (_source, code) => String(code) !== '6133',
},
},
};
exports.codeFeatures = raw;
//# sourceMappingURL=codeFeatures.js.map

View File

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

View File

@@ -0,0 +1,169 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getGlobalTypesFileName = getGlobalTypesFileName;
exports.generateGlobalTypes = generateGlobalTypes;
function getGlobalTypesFileName(options) {
return [
options.lib,
options.target,
options.checkUnknownProps,
].map(v => (typeof v === 'boolean' ? Number(v) : v)).join('_') + '.d.ts';
}
function generateGlobalTypes(options) {
const { lib, target, checkUnknownProps } = options;
const fnPropsType = `(T extends { $props: infer Props } ? Props : {})${checkUnknownProps ? '' : ' & Record<string, unknown>'}`;
let text = `// @ts-nocheck\nexport {};\n`;
if (target < 3.5) {
text += `
; declare module '${lib}' {
export interface GlobalComponents { }
export interface GlobalDirectives { }
}`;
}
text += `
; declare global {
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 ? { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N3] } :
Self extends object ? { [K in N0]: Self } :
N1 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N1] } :
N2 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N2] } :
N3 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N3] } :
{};
type __VLS_FunctionalComponentCtx<T, K> = __VLS_PickNotAny<'__ctx' extends keyof __VLS_PickNotAny<K, {}>
? K extends { __ctx?: infer Ctx } ? NonNullable<Ctx> : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
>;
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_FunctionalComponent<T> = (props: ${fnPropsType}, ctx?: any) => __VLS_Element & {
__ctx?: {
attrs?: any;
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
emit?: T extends { $emit: infer Emit } ? Emit : {};
props?: ${fnPropsType};
expose?: (exposed: T) => void;
};
};
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,
Emits,
onEvent extends keyof Props,
Event extends keyof Emits,
CamelizedEvent extends keyof Emits,
> = __VLS_IsFunction<Props, onEvent> extends true
? Props
: __VLS_IsFunction<Emits, Event> extends true
? { [K in onEvent]?: Emits[Event] }
: __VLS_IsFunction<Emits, CamelizedEvent> extends true
? { [K in onEvent]?: Emits[CamelizedEvent] }
: Props;
// 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_EmitsToProps<T> = __VLS_PrettifyGlobal<{
[K in string & keyof T as \`on\${Capitalize<K>}\`]?:
(...args: T[K] extends (...args: infer P) => any ? P : T[K] extends null ? any[] : never) => any;
}>;
type __VLS_ResolveEmits<
Comp,
Emits,
TypeEmits = ${target >= 3.6
? `Comp extends { __typeEmits?: infer T } ? unknown extends T ? {} : import('${lib}').ShortEmitsToObject<T> : {}`
: `{}`},
NormalizedEmits = __VLS_NormalizeEmits<Emits> extends infer E ? string extends keyof E ? {} : E : never,
> = __VLS_SpreadMerge<NormalizedEmits, TypeEmits>;
type __VLS_ResolveDirectives<T> = {
[K in keyof T & string as \`v\${Capitalize<K>}\`]: T[K];
};
type __VLS_PrettifyGlobal<T> = { [K in keyof T as K]: T[K]; } & {};
type __VLS_WithDefaultsGlobal<P, D> = {
[K in keyof P as K extends keyof D ? K : never]-?: P[K];
} & {
[K in keyof P as K extends keyof D ? never : K]: P[K];
};
type __VLS_UseTemplateRef<T> = Readonly<import('${lib}').ShallowRef<T | null>>;
type __VLS_ProxyRefs<T> = import('${lib}').ShallowUnwrapRef<T>;
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,
][];
function __VLS_getSlotParameters<S, D extends S>(slot: S, decl?: D):
D extends (...args: infer P) => any ? P : any[];
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_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
T extends new (...args: any) => any ? __VLS_FunctionalComponent<K>
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
: T extends (...args: any) => any ? T
: __VLS_FunctionalComponent<{}>;
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${checkUnknownProps ? '' : ' & 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,10 @@
import type { VueCompilerOptions } from '../types';
export declare function getLocalTypesGenerator(vueCompilerOptions: VueCompilerOptions): {
generate: () => Generator<string, void, unknown>;
readonly PrettifyLocal: string;
readonly WithDefaultsLocal: string;
readonly WithSlots: string;
readonly PropsChildren: string;
readonly TypePropsToOption: string;
readonly OmitIndexSignature: string;
};

View File

@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLocalTypesGenerator = getLocalTypesGenerator;
const utils_1 = require("./utils");
function getLocalTypesGenerator(vueCompilerOptions) {
const used = new Set();
const WithDefaultsLocal = defineHelper(`__VLS_WithDefaultsLocal`, () => `
type __VLS_WithDefaultsLocal<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 as K]: T[K]; } & {}${utils_1.endOfLine}`);
const WithSlots = defineHelper(`__VLS_WithSlots`, () => `
type __VLS_WithSlots<T, S> = T & {
new(): {
$slots: 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`, () => `
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K>
? { type: import('${vueCompilerOptions.lib}').PropType<Required<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,
[WithDefaultsLocal.name]: WithDefaultsLocal,
[WithSlots.name]: WithSlots,
[PropsChildren.name]: PropsChildren,
[TypePropsToOption.name]: TypePropsToOption,
[OmitIndexSignature.name]: OmitIndexSignature,
};
used.clear();
return {
generate,
get PrettifyLocal() {
return PrettifyLocal.name;
},
get WithDefaultsLocal() {
return WithDefaultsLocal.name;
},
get WithSlots() {
return WithSlots.name;
},
get PropsChildren() {
return PropsChildren.name;
},
get TypePropsToOption() {
return TypePropsToOption.name;
},
get OmitIndexSignature() {
return OmitIndexSignature.name;
},
};
function* generate() {
for (const name of used) {
yield helpers[name].generate();
}
used.clear();
}
function defineHelper(name, generate) {
return {
get name() {
used.add(name);
return name;
},
generate,
};
}
}
//# sourceMappingURL=localTypes.js.map

View File

@@ -0,0 +1,5 @@
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>;

View File

@@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateComponent = generateComponent;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const merge_1 = require("../utils/merge");
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}`;
}
const returns = [];
if (ctx.bypassDefineComponent) {
// fill $props
if (scriptSetupRanges.defineProps) {
const name = scriptSetupRanges.defineProps.name ?? `__VLS_props`;
// NOTE: defineProps is inaccurate for $props
returns.push(name, `{} as { $props: Partial<typeof ${name}> }`);
}
// fill $emit
if (scriptSetupRanges.defineEmits) {
returns.push(`{} as { $emit: typeof ${scriptSetupRanges.defineEmits.name ?? `__VLS_emit`} }`);
}
}
if (scriptSetupRanges.defineExpose) {
returns.push(`__VLS_exposed`);
}
if (returns.length) {
yield `setup: () => (`;
yield* (0, merge_1.generateSpreadMerge)(returns);
yield `),${utils_1.newLine}`;
}
if (!ctx.bypassDefineComponent) {
const emitOptionCodes = [...generateEmitsOption(options, scriptSetupRanges)];
yield* emitOptionCodes;
yield* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, !!emitOptionCodes.length);
}
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* generateEmitsOption(options, scriptSetupRanges) {
const optionCodes = [];
const typeOptionCodes = [];
if (scriptSetupRanges.defineModel.length) {
optionCodes.push(`{} as __VLS_NormalizeEmits<typeof __VLS_modelEmit>`);
typeOptionCodes.push(`__VLS_ModelEmit`);
}
if (scriptSetupRanges.defineEmits) {
const { name, typeArg, hasUnionTypeArg } = scriptSetupRanges.defineEmits;
optionCodes.push(`{} as __VLS_NormalizeEmits<typeof ${name ?? '__VLS_emit'}>`);
if (typeArg && !hasUnionTypeArg) {
typeOptionCodes.push(`__VLS_Emit`);
}
else {
typeOptionCodes.length = 0;
}
}
if (options.vueCompilerOptions.target >= 3.5 && typeOptionCodes.length) {
yield `__typeEmits: {} as `;
yield* (0, merge_1.generateIntersectMerge)(typeOptionCodes);
yield `,${utils_1.newLine}`;
}
else if (optionCodes.length) {
yield `emits: `;
yield* (0, merge_1.generateSpreadMerge)(optionCodes);
yield `,${utils_1.newLine}`;
}
}
function* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, hasEmitsOption) {
const getOptionCodes = [];
const typeOptionCodes = [];
if (options.templateCodegen?.inheritedAttrVars.size) {
let attrsType = `__VLS_InheritedAttrs`;
if (hasEmitsOption) {
attrsType = `Omit<${attrsType}, \`on\${string}\`>`;
}
getOptionCodes.push(() => {
const propsType = `__VLS_PickNotAny<${ctx.localTypes.OmitIndexSignature}<${attrsType}>, {}>`;
const optionType = `${ctx.localTypes.TypePropsToOption}<${propsType}>`;
return `{} as ${optionType}`;
});
typeOptionCodes.push(`{} as ${attrsType}`);
}
if (ctx.generatedPropsType) {
if (options.vueCompilerOptions.target < 3.6) {
getOptionCodes.push(() => {
const propsType = `${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`;
return `{} as ` + (scriptSetupRanges.withDefaults?.arg
? `${ctx.localTypes.WithDefaultsLocal}<${propsType}, typeof __VLS_defaults>`
: propsType);
});
}
typeOptionCodes.push(`{} as __VLS_PublicProps`);
}
if (scriptSetupRanges.defineProps?.arg) {
const { arg } = scriptSetupRanges.defineProps;
getOptionCodes.push(() => (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.navigation));
typeOptionCodes.length = 0;
}
const useTypeOption = options.vueCompilerOptions.target >= 3.5 && typeOptionCodes.length;
const useOption = (!useTypeOption || scriptSetupRanges.withDefaults) && getOptionCodes.length;
if (useTypeOption) {
if (options.vueCompilerOptions.target >= 3.6
&& scriptSetupRanges.withDefaults?.arg) {
yield `__defaults: __VLS_defaults,${utils_1.newLine}`;
}
yield `__typeProps: `;
yield* (0, merge_1.generateSpreadMerge)(typeOptionCodes);
yield `,${utils_1.newLine}`;
}
if (useOption) {
yield `props: `;
yield* (0, merge_1.generateSpreadMerge)(getOptionCodes.map(fn => fn()));
yield `,${utils_1.newLine}`;
}
}
//# sourceMappingURL=component.js.map

View File

@@ -0,0 +1,19 @@
import type { InlayHintInfo } from '../inlayHints';
import type { ScriptCodegenOptions } from './index';
export type ScriptCodegenContext = ReturnType<typeof createScriptCodegenContext>;
export declare function createScriptCodegenContext(options: ScriptCodegenOptions): {
generatedTemplate: boolean;
generatedPropsType: boolean;
bypassDefineComponent: boolean;
bindingNames: Set<string>;
localTypes: {
generate: () => Generator<string, void, unknown>;
readonly PrettifyLocal: string;
readonly WithDefaultsLocal: 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.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,39 @@
import type * as ts from 'typescript';
import type { ScriptRanges } from '../../parsers/scriptRanges';
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, Sfc, SfcBlock, VueCompilerOptions } from '../../types';
import type { TemplateCodegenContext } from '../template/context';
export interface ScriptCodegenOptions {
ts: typeof ts;
compilerOptions: ts.CompilerOptions;
vueCompilerOptions: VueCompilerOptions;
sfc: Sfc;
fileName: string;
lang: string;
scriptRanges: ScriptRanges | undefined;
scriptSetupRanges: ScriptSetupRanges | undefined;
templateCodegen: TemplateCodegenContext & {
codes: Code[];
} | undefined;
destructuredPropNames: Set<string>;
templateRefNames: Set<string>;
}
export { generate as generateScript };
declare function generate(options: ScriptCodegenOptions): {
codes: Code[];
generatedTemplate: boolean;
generatedPropsType: boolean;
bypassDefineComponent: boolean;
bindingNames: Set<string>;
localTypes: {
generate: () => Generator<string, void, unknown>;
readonly PrettifyLocal: string;
readonly WithDefaultsLocal: string;
readonly WithSlots: string;
readonly PropsChildren: string;
readonly TypePropsToOption: string;
readonly OmitIndexSignature: string;
};
inlayHints: import("../inlayHints").InlayHintInfo[];
};
export declare function generateConstExport(options: ScriptCodegenOptions, block: SfcBlock): Generator<Code>;

View File

@@ -0,0 +1,134 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateScript = generate;
exports.generateConstExport = generateConstExport;
const path = require("path-browserify");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
const context_1 = require("./context");
const scriptSetup_1 = require("./scriptSetup");
const src_1 = require("./src");
const template_1 = require("./template");
function generate(options) {
const context = (0, context_1.createScriptCodegenContext)(options);
const codegen = generateScript(options, context);
return {
...context,
codes: [...codegen],
};
}
function* generateScript(options, ctx) {
yield* generateGlobalTypesReference(options);
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
yield* (0, scriptSetup_1.generateScriptSetupImports)(options.sfc.scriptSetup, options.scriptSetupRanges);
}
if (options.sfc.script && options.scriptRanges) {
const { exportDefault } = options.scriptRanges;
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
if (exportDefault) {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, exportDefault.start, codeFeatures_1.codeFeatures.all);
yield* (0, scriptSetup_1.generateScriptSetup)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
}
else {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
yield* (0, scriptSetup_1.generateScriptSetup)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
}
}
else if (exportDefault) {
let wrapLeft;
let wrapRight;
if (options.sfc.script.content[exportDefault.expression.start] === '{'
&& options.vueCompilerOptions.optionsWrapper.length) {
[wrapLeft, wrapRight] = options.vueCompilerOptions.optionsWrapper;
ctx.inlayHints.push({
blockName: options.sfc.script.name,
offset: exportDefault.expression.start,
setting: 'vue.inlayHints.optionsWrapper',
label: wrapLeft || '[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: wrapRight || '[Missing optionsWrapper[1]]',
});
}
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, exportDefault.start, codeFeatures_1.codeFeatures.all);
yield* generateConstExport(options, options.sfc.script);
if (wrapLeft) {
yield wrapLeft;
}
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, exportDefault.expression.start, exportDefault.expression.end, codeFeatures_1.codeFeatures.all);
if (wrapRight) {
yield wrapRight;
}
yield utils_1.endOfLine;
}
else {
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, 0, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
yield* generateConstExport(options, options.sfc.script);
yield `(await import('${options.vueCompilerOptions.lib}')).defineComponent({})${utils_1.endOfLine}`;
}
}
else if (options.sfc.scriptSetup && options.scriptSetupRanges) {
yield* (0, scriptSetup_1.generateScriptSetup)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
}
if (!ctx.generatedTemplate) {
yield* (0, template_1.generateTemplate)(options, ctx);
}
yield* generateExportDefault(options);
yield* ctx.localTypes.generate();
}
function* generateGlobalTypesReference(options) {
const globalTypesPath = options.vueCompilerOptions.globalTypesPath(options.fileName);
if (!globalTypesPath) {
yield `/* placeholder */${utils_1.newLine}`;
}
else if (path.isAbsolute(globalTypesPath)) {
let relativePath = path.relative(path.dirname(options.fileName), globalTypesPath);
if (relativePath !== globalTypesPath
&& !relativePath.startsWith('./')
&& !relativePath.startsWith('../')) {
relativePath = './' + relativePath;
}
yield `/// <reference types="${relativePath}" />${utils_1.newLine}`;
}
else {
yield `/// <reference types="${globalTypesPath}" />${utils_1.newLine}`;
}
}
function* generateConstExport(options, block) {
if (options.sfc.script) {
yield* (0, utils_1.generatePartiallyEnding)(options.sfc.script.name, options.scriptRanges?.exportDefault
? options.scriptRanges.exportDefault.start
: options.sfc.script.content.length, '#3632/script.vue');
}
yield `const `;
yield* (0, wrapWith_1.wrapWith)(0, block.content.length, block.name, codeFeatures_1.codeFeatures.verification, `__VLS_export`);
yield ` = `;
}
function* generateExportDefault(options) {
if (options.sfc.script?.src) {
yield* (0, src_1.generateSrc)(options.sfc.script.src);
return;
}
let prefix;
let suffix;
if (options.sfc.script && options.scriptRanges?.exportDefault) {
const { exportDefault } = options.scriptRanges;
prefix = (0, utils_1.generateSfcBlockSection)(options.sfc.script, exportDefault.start, exportDefault.expression.start, codeFeatures_1.codeFeatures.all);
suffix = (0, utils_1.generateSfcBlockSection)(options.sfc.script, exportDefault.expression.end, options.sfc.script.content.length, codeFeatures_1.codeFeatures.all);
}
else {
prefix = `export default `;
suffix = utils_1.endOfLine;
}
yield prefix;
yield `{} as typeof __VLS_export`;
yield suffix;
}
//# 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,459 @@
"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 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) {
yield* (0, index_1.generateConstExport)(options, scriptSetup);
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 propTypes = [];
if (ctx.generatedPropsType) {
propTypes.push(`__VLS_PublicProps`);
}
if (scriptSetupRanges.defineProps?.arg) {
yield `const __VLS_propsOption = `;
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.defineProps.arg.start, scriptSetupRanges.defineProps.arg.end, codeFeatures_1.codeFeatures.navigation);
yield utils_1.endOfLine;
propTypes.push(`import('${options.vueCompilerOptions.lib}').${options.vueCompilerOptions.target >= 3.3 ? `ExtractPublicPropTypes` : `ExtractPropTypes`}<typeof __VLS_propsOption>`);
}
if (scriptSetupRanges.defineEmits || scriptSetupRanges.defineModel.length) {
propTypes.push(`__VLS_EmitProps`);
}
if (options.templateCodegen?.inheritedAttrVars.size) {
propTypes.push(`__VLS_InheritedAttrs`);
}
const emitTypes = [];
if (scriptSetupRanges.defineEmits) {
emitTypes.push(`typeof ${scriptSetupRanges.defineEmits.name ?? '__VLS_emit'}`);
}
if (scriptSetupRanges.defineModel.length) {
emitTypes.push(`typeof __VLS_modelEmit`);
}
yield `return {} as {${utils_1.newLine}`
+ ` props: ${ctx.localTypes.PrettifyLocal}<${propTypes.join(` & `)}> & ${options.vueCompilerOptions.target >= 3.4
? `import('${options.vueCompilerOptions.lib}').PublicProps`
: options.vueCompilerOptions.target >= 3
? `import('${options.vueCompilerOptions.lib}').VNodeProps`
+ ` & import('${options.vueCompilerOptions.lib}').AllowedComponentProps`
+ ` & import('${options.vueCompilerOptions.lib}').ComponentCustomProps`
: `globalThis.JSX.IntrinsicAttributes`}${utils_1.endOfLine}`
+ ` expose: (exposed: ${scriptSetupRanges.defineExpose
? `import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<typeof __VLS_exposed>`
: `{}`}) => void${utils_1.endOfLine}`
+ ` attrs: any${utils_1.endOfLine}`
+ ` slots: __VLS_Slots${utils_1.endOfLine}`
+ ` emit: ${emitTypes.length ? emitTypes.join(` & `) : `{}`}${utils_1.endOfLine}`
+ `}${utils_1.endOfLine}`;
yield `})(),${utils_1.newLine}`; // __VLS_setup = (async () => {
yield `) => ({} as import('${options.vueCompilerOptions.lib}').VNode & { __ctx?: Awaited<typeof __VLS_setup> }))${utils_1.endOfLine}`;
}
else if (!options.sfc.script) {
// no script block, generate script setup code at root
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, 'export default');
}
else {
yield* (0, index_1.generateConstExport)(options, scriptSetup);
yield `await (async () => {${utils_1.newLine}`;
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, 'return');
yield `})()${utils_1.endOfLine}`;
}
}
function* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, syntax) {
let setupCodeModifies = [];
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.withoutSemantic),
`])`,
]
: [
` 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.withoutSemantic),
`]`,
]
: [`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, utils_1.generatePartiallyEnding)(scriptSetup.name, scriptSetup.content.length, '#3632/scriptSetup.vue');
yield* generateMacros(options, ctx);
const hasSlots = !!(scriptSetupRanges.defineSlots
|| options.templateCodegen?.slots.length
|| options.templateCodegen?.dynamicSlots.length);
yield* generateModels(scriptSetup, scriptSetupRanges);
yield* generatePublicProps(options, ctx, scriptSetup, scriptSetupRanges, hasSlots);
yield* (0, template_1.generateTemplate)(options, ctx);
if (syntax) {
const prefix = syntax === 'return'
? [`return `]
: (0, index_1.generateConstExport)(options, scriptSetup);
if (hasSlots) {
yield `const __VLS_base = `;
yield* (0, component_1.generateComponent)(options, ctx, scriptSetup, scriptSetupRanges);
yield utils_1.endOfLine;
yield* prefix;
yield `{} as ${ctx.localTypes.WithSlots}<typeof __VLS_base, __VLS_Slots>${utils_1.endOfLine}`;
}
else {
yield* prefix;
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* 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,
];
}
}
else if (!utils_1.identifierRegex.test(name)) {
yield [[`const ${defaultName} = `], statement.start, callExp.start];
yield [
[
utils_1.endOfLine,
(0, utils_1.generateSfcBlockSection)(scriptSetup, statement.start, callExp.start, codeFeatures_1.codeFeatures.all),
defaultName,
],
statement.end,
statement.end,
];
}
}
function* generatePublicProps(options, ctx, scriptSetup, scriptSetupRanges, hasSlots) {
if (scriptSetupRanges.defineProps?.typeArg && scriptSetupRanges.withDefaults?.arg) {
yield `const __VLS_defaults = `;
yield (0, utils_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.withDefaults.arg.start, scriptSetupRanges.withDefaults.arg.end, codeFeatures_1.codeFeatures.navigation);
yield utils_1.endOfLine;
}
const propTypes = [];
if (options.vueCompilerOptions.jsxSlots && hasSlots) {
propTypes.push(`${ctx.localTypes.PropsChildren}<__VLS_Slots>`);
}
if (scriptSetupRanges.defineProps?.typeArg) {
propTypes.push(`__VLS_Props`);
}
if (scriptSetupRanges.defineModel.length) {
propTypes.push(`__VLS_ModelProps`);
}
if (propTypes.length) {
ctx.generatedPropsType = true;
yield `type __VLS_PublicProps = ${propTypes.join(` & `)}${utils_1.endOfLine}`;
}
}
function* generateModels(scriptSetup, scriptSetupRanges) {
if (!scriptSetupRanges.defineModel.length) {
return;
}
const defaultCodes = [];
const propCodes = [];
const emitCodes = [];
for (const defineModel of scriptSetupRanges.defineModel) {
const propName = defineModel.name
? (0, shared_1.camelize)(getRangeText(scriptSetup, defineModel.name).slice(1, -1))
: 'modelValue';
let modelType;
if (defineModel.type) {
// Infer from defineModel<T>
modelType = getRangeText(scriptSetup, defineModel.type);
}
else if (defineModel.runtimeType && defineModel.localName) {
// Infer from actual prop declaration code
modelType = `typeof ${getRangeText(scriptSetup, defineModel.localName)}['value']`;
}
else if (defineModel.defaultValue && propName) {
// Infer from defineModel({ default: T })
modelType = `typeof __VLS_defaultModels['${propName}']`;
}
else {
modelType = `any`;
}
if (defineModel.defaultValue) {
defaultCodes.push(`'${propName}': ${getRangeText(scriptSetup, defineModel.defaultValue)},${utils_1.newLine}`);
}
propCodes.push(generateModelProp(scriptSetup, defineModel, propName, modelType));
emitCodes.push(generateModelEmit(defineModel, propName, modelType));
}
if (defaultCodes.length) {
yield `const __VLS_defaultModels = {${utils_1.newLine}`;
yield* defaultCodes;
yield `}${utils_1.endOfLine}`;
}
yield `type __VLS_ModelProps = {${utils_1.newLine}`;
for (const codes of propCodes) {
yield* codes;
}
yield `}${utils_1.endOfLine}`;
yield `type __VLS_ModelEmit = {${utils_1.newLine}`;
for (const codes of emitCodes) {
yield* codes;
}
yield `}${utils_1.endOfLine}`;
yield `const __VLS_modelEmit = defineEmits<__VLS_ModelEmit>()${utils_1.endOfLine}`;
}
function* generateModelProp(scriptSetup, defineModel, propName, modelType) {
if (defineModel.comments) {
yield scriptSetup.content.slice(defineModel.comments.start, defineModel.comments.end);
yield utils_1.newLine;
}
if (defineModel.name) {
yield* (0, camelized_1.generateCamelized)(getRangeText(scriptSetup, defineModel.name), scriptSetup.name, defineModel.name.start, codeFeatures_1.codeFeatures.navigation);
}
else {
yield propName;
}
yield defineModel.required ? `: ` : `?: `;
yield modelType;
yield utils_1.endOfLine;
if (defineModel.modifierType) {
const modifierName = `${propName === 'modelValue' ? 'model' : propName}Modifiers`;
const modifierType = getRangeText(scriptSetup, defineModel.modifierType);
yield `'${modifierName}'?: Partial<Record<${modifierType}, true>>${utils_1.endOfLine}`;
}
}
function* generateModelEmit(defineModel, propName, modelType) {
yield `'update:${propName}': [value: `;
yield modelType;
if (!defineModel.required && !defineModel.defaultValue) {
yield ` | undefined`;
}
yield `]${utils_1.endOfLine}`;
}
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,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSrc = generateSrc;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
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, wrapWith_1.wrapWith)(src.offset, src.offset + src.text.length, 'main', {
...codeFeatures_1.codeFeatures.all,
...text !== src.text ? codeFeatures_1.codeFeatures.navigationWithoutRename : {},
}, `'`, [text.slice(0, src.text.length), 'main', src.offset, utils_1.combineLastMapping], text.slice(src.text.length), `'`);
yield utils_1.endOfLine;
yield `export { default } from '${text}'${utils_1.endOfLine}`;
}
//# sourceMappingURL=src.js.map

View File

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

View File

@@ -0,0 +1,169 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplate = generateTemplate;
const shared_1 = require("@vue/shared");
const path = require("path-browserify");
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");
const merge_1 = require("../utils/merge");
function* generateTemplate(options, ctx) {
ctx.generatedTemplate = true;
yield* generateSelf(options);
yield* generateTemplateCtx(options, ctx);
yield* generateTemplateElements();
yield* generateTemplateComponents(options);
yield* generateTemplateDirectives(options);
yield* generateTemplateBody(options, ctx);
}
function* generateSelf(options) {
if (options.sfc.script && options.scriptRanges?.exportDefault) {
yield `const __VLS_self = (await import('${options.vueCompilerOptions.lib}')).defineComponent(`;
const { args } = options.scriptRanges.exportDefault;
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, args.start, args.end, codeFeatures_1.codeFeatures.all);
yield `)${utils_1.endOfLine}`;
}
else if (options.sfc.script?.src) {
yield `let __VLS_self!: typeof import('./${path.basename(options.fileName)}').default${utils_1.endOfLine}`;
}
}
function* generateTemplateCtx(options, ctx) {
const exps = [];
if (options.vueCompilerOptions.petiteVueExtensions.some(ext => options.fileName.endsWith(ext))) {
exps.push(`globalThis`);
}
if (options.sfc.script?.src || options.scriptRanges?.exportDefault) {
exps.push(`{} as InstanceType<__VLS_PickNotAny<typeof __VLS_self, new () => {}>>`);
}
else {
exps.push(`{} as import('${options.vueCompilerOptions.lib}').ComponentPublicInstance`);
}
if (options.sfc.styles.some(style => style.module)) {
exps.push(`{} as __VLS_StyleModules`);
}
const emitTypes = [];
if (options.scriptSetupRanges?.defineEmits) {
const { defineEmits } = options.scriptSetupRanges;
emitTypes.push(`typeof ${defineEmits.name ?? `__VLS_emit`}`);
}
if (options.scriptSetupRanges?.defineModel.length) {
emitTypes.push(`typeof __VLS_modelEmit`);
}
if (emitTypes.length) {
yield `type __VLS_EmitProps = __VLS_EmitsToProps<__VLS_NormalizeEmits<${emitTypes.join(` & `)}>>${utils_1.endOfLine}`;
exps.push(`{} as { $emit: ${emitTypes.join(` & `)} }`);
}
const propTypes = [];
const { defineProps, withDefaults } = options.scriptSetupRanges ?? {};
const props = defineProps?.arg
? `typeof ${defineProps.name ?? `__VLS_props`}`
: defineProps?.typeArg
? withDefaults?.arg
? `__VLS_WithDefaultsGlobal<__VLS_Props, typeof __VLS_defaults>`
: `__VLS_Props`
: undefined;
if (props) {
propTypes.push(props);
}
if (options.scriptSetupRanges?.defineModel.length) {
propTypes.push(`__VLS_ModelProps`);
}
if (emitTypes.length) {
propTypes.push(`__VLS_EmitProps`);
}
if (propTypes.length) {
yield `type __VLS_InternalProps = ${propTypes.join(` & `)}${utils_1.endOfLine}`;
exps.push(`{} as { $props: __VLS_InternalProps }`);
exps.push(`{} as __VLS_InternalProps`);
}
if (options.scriptSetupRanges && ctx.bindingNames.size) {
exps.push(`{} as __VLS_Bindings`);
}
yield `const __VLS_ctx = `;
yield* (0, merge_1.generateSpreadMerge)(exps);
yield utils_1.endOfLine;
}
function* generateTemplateElements() {
yield `let __VLS_elements!: __VLS_IntrinsicElements${utils_1.endOfLine}`;
}
function* generateTemplateComponents(options) {
const types = [`typeof __VLS_ctx`];
if (options.sfc.script && options.scriptRanges?.exportDefault?.componentsOption) {
const { componentsOption } = options.scriptRanges.exportDefault;
yield `const __VLS_componentsOption = `;
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, componentsOption.start, componentsOption.end, codeFeatures_1.codeFeatures.navigation);
yield utils_1.endOfLine;
types.push(`typeof __VLS_componentsOption`);
}
yield `type __VLS_LocalComponents = ${types.join(` & `)}${utils_1.endOfLine}`;
yield `let __VLS_components!: __VLS_LocalComponents & __VLS_GlobalComponents${utils_1.endOfLine}`;
}
function* generateTemplateDirectives(options) {
const types = [`typeof __VLS_ctx`];
if (options.sfc.script && options.scriptRanges?.exportDefault?.directivesOption) {
const { directivesOption } = options.scriptRanges.exportDefault;
yield `const __VLS_directivesOption = `;
yield (0, utils_1.generateSfcBlockSection)(options.sfc.script, directivesOption.start, directivesOption.end, codeFeatures_1.codeFeatures.navigation);
yield utils_1.endOfLine;
types.push(`__VLS_ResolveDirectives<typeof __VLS_directivesOption>`);
}
yield `type __VLS_LocalDirectives = ${types.join(` & `)}${utils_1.endOfLine}`;
yield `let __VLS_directives!: __VLS_LocalDirectives & __VLS_GlobalDirectives${utils_1.endOfLine}`;
}
function* generateTemplateBody(options, ctx) {
const templateCodegenCtx = (0, context_1.createTemplateCodegenContext)({
scriptSetupBindingNames: new Set(),
});
yield* (0, scopedClasses_1.generateStyleScopedClasses)(options, templateCodegenCtx);
yield* (0, styleScopedClasses_1.generateStyleScopedClassReferences)(templateCodegenCtx, true);
yield* (0, modules_1.generateStyleModules)(options);
yield* generateCssVars(options, templateCodegenCtx);
yield* generateBindings(options, ctx, templateCodegenCtx);
if (options.templateCodegen) {
yield* options.templateCodegen.codes;
}
else {
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) {
for (const style of options.sfc.styles) {
for (const binding of style.bindings) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, style.name, codeFeatures_1.codeFeatures.all, binding.text, binding.offset, `(`, `)`);
yield utils_1.endOfLine;
}
}
}
function* generateBindings(options, ctx, templateCodegenCtx) {
if (!options.sfc.scriptSetup || !ctx.bindingNames.size) {
return;
}
const usageVars = new Set([
...options.sfc.template?.ast?.components.flatMap(c => [(0, shared_1.camelize)(c), (0, shared_1.capitalize)((0, shared_1.camelize)(c))]) ?? [],
...options.templateCodegen?.accessExternalVariables.keys() ?? [],
...templateCodegenCtx.accessExternalVariables.keys(),
]);
yield `type __VLS_Bindings = __VLS_ProxyRefs<{${utils_1.newLine}`;
for (const varName of ctx.bindingNames) {
if (!usageVars.has(varName)) {
continue;
}
const token = Symbol(varName.length);
yield ['', undefined, 0, { __linkedToken: token }];
yield `${varName}: typeof `;
yield ['', undefined, 0, { __linkedToken: token }];
yield varName;
yield utils_1.endOfLine;
}
yield `}>${utils_1.endOfLine}`;
}
//# 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,2 @@
import type { Code, Sfc } from '../../types';
export declare function generateStyleImports(style: Sfc['styles'][number]): Generator<Code>;

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleImports = generateStyleImports;
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
function* generateStyleImports(style) {
const features = {
navigation: true,
verification: true,
};
if (typeof style.src === 'object') {
yield `${utils_1.newLine} & typeof import(`;
yield* (0, wrapWith_1.wrapWith)(style.src.offset, style.src.offset + style.src.text.length, 'main', features, `'`, [style.src.text, 'main', style.src.offset, utils_1.combineLastMapping], `'`);
yield `).default`;
}
for (const { text, offset } of style.imports) {
yield `${utils_1.newLine} & typeof import('`;
yield [
text,
style.name,
offset,
features,
];
yield `').default`;
}
}
//# sourceMappingURL=imports.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,42 @@
"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");
const imports_1 = require("./imports");
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.navigation,
];
}
yield `: `;
if (!options.vueCompilerOptions.strictCssModules) {
yield `Record<string, string> & `;
}
yield `__VLS_PrettifyGlobal<{}`;
if (options.vueCompilerOptions.resolveStyleImports) {
yield* (0, imports_1.generateStyleImports)(style);
}
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,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleScopedClasses = generateStyleScopedClasses;
const utils_1 = require("../utils");
const classProperty_1 = require("./classProperty");
const imports_1 = require("./imports");
function* generateStyleScopedClasses(options, ctx) {
const option = options.vueCompilerOptions.resolveStyleClassNames;
const styles = options.sfc.styles
.map((style, i) => [style, i])
.filter(([style]) => option === true || (option === 'scoped' && style.scoped));
if (!styles.length) {
return;
}
const firstClasses = new Set();
yield `type __VLS_StyleScopedClasses = {}`;
for (const [style, i] of styles) {
if (options.vueCompilerOptions.resolveStyleImports) {
yield* (0, imports_1.generateStyleImports)(style);
}
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,163 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code, VueCodeInformation } from '../../types';
import type { 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'>, templateAst?: CompilerDOM.RootNode): {
readonly currentInfo: {
ignoreError?: boolean;
expectError?: {
token: number;
node: CompilerDOM.CommentNode;
};
generic?: {
content: string;
offset: number;
};
};
resolveCodeFeatures: (features: VueCodeInformation) => VueCodeInformation;
inlineTsAsts: Map<string, import("typescript").SourceFile> | undefined;
inVFor: boolean;
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>>;
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>;
addTemplateRef(name: string, typeExp: string, offset: number): void;
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>;
generateAutoImportCompletion(): Generator<Code>;
enter(node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode): boolean;
exit(): Generator<Code>;
};

View File

@@ -0,0 +1,320 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTemplateCodegenContext = createTemplateCodegenContext;
const CompilerDOM = require("@vue/compiler-dom");
const computedSfc_1 = require("../../virtualFile/computedSfc");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
const commentDirectiveRegex = /^<!--\s*@vue-(?<name>[-\w]+)\b(?<content>[\s\S]*)-->$/;
/**
* 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, templateAst) {
let variableId = 0;
function resolveCodeFeatures(features) {
if (features.verification && stack.length) {
const data = stack[stack.length - 1];
if (data.ignoreError) {
// 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 (data.expectError !== undefined) {
// 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.
return {
...features,
verification: {
shouldReport: () => {
data.expectError.token++;
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();
const stack = [];
const commentBuffer = [];
return {
get currentInfo() {
return stack[stack.length - 1];
},
resolveCodeFeatures,
inlineTsAsts: templateAst && computedSfc_1.templateInlineTsAsts.get(templateAst),
inVFor: false,
slots,
dynamicSlots,
dollarVars,
accessExternalVariables,
blockConditions,
scopedClasses,
emptyClassOffsets,
inlayHints,
bindingAttrLocs,
inheritedAttrVars,
templateRefs,
currentComponent: undefined,
singleRootElTypes: [],
singleRootNodes: new Set(),
addTemplateRef(name, typeExp, offset) {
let refs = templateRefs.get(name);
if (!refs) {
templateRefs.set(name, refs = []);
}
refs.push({ typeExp, offset });
},
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() {
// 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() {
for (const condition of blockConditions) {
yield `if (!${condition}) return${utils_1.endOfLine}`;
}
},
*generateAutoImportCompletion() {
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.semanticWithoutHighlight,
},
];
}
else {
yield [
varName,
'template',
offset,
codeFeatures_1.codeFeatures.additionalCompletion,
];
}
yield `,`;
}
offsets.clear();
}
yield `]${utils_1.endOfLine}`;
},
enter(node) {
if (node.type === CompilerDOM.NodeTypes.COMMENT) {
commentBuffer.push(node);
return false;
}
const data = {};
const comments = [...commentBuffer];
commentBuffer.length = 0;
for (const comment of comments) {
const match = comment.loc.source.match(commentDirectiveRegex);
if (match) {
const { name, content } = match.groups;
switch (name) {
case 'skip': {
return false;
}
case 'ignore': {
data.ignoreError = true;
break;
}
case 'expect-error': {
data.expectError = {
token: 0,
node: comment,
};
break;
}
case 'generic': {
const text = content.trim();
if (text.startsWith('{') && text.endsWith('}')) {
data.generic = {
content: text.slice(1, -1),
offset: comment.loc.start.offset + comment.loc.source.indexOf('{') + 1,
};
}
break;
}
}
}
}
stack.push(data);
return true;
},
*exit() {
const data = stack.pop();
commentBuffer.length = 0;
if (data.expectError !== undefined) {
yield* (0, wrapWith_1.wrapWith)(data.expectError.node.loc.start.offset, data.expectError.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: () => data.expectError.token === 0,
},
}, `// @ts-expect-error`);
yield `${utils_1.newLine}${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): Generator<Code>;
export declare function generateElement(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;

View File

@@ -0,0 +1,281 @@
"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 codeFeatures_1 = require("../codeFeatures");
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) {
const tagOffsets = (0, shared_2.getElementTagOffsets)(node, options.template);
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],
};
props = props.filter(p => p !== prop);
break;
}
}
}
else if (node.tag.includes('.')) {
// namespace tag
dynamicTagInfo = {
tag: node.tag,
offsets: tagOffsets,
};
}
if (matchImportName) {
// navigation support
yield `/** @type {[`;
for (const tagOffset of tagOffsets) {
yield `typeof `;
if (componentOriginalVar === node.tag) {
yield [
componentOriginalVar,
'template',
tagOffset,
codeFeatures_1.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, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
}
yield `, `;
}
yield `]} */${utils_1.endOfLine}`;
}
else if (dynamicTagInfo) {
yield `const ${componentOriginalVar} = (`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.all, dynamicTagInfo.tag, dynamicTagInfo.offsets[0], `(`, `)`);
if (dynamicTagInfo.offsets[1] !== undefined) {
yield `,`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.withoutCompletion, dynamicTagInfo.tag, dynamicTagInfo.offsets[1], `(`, `)`);
}
yield `)${utils_1.endOfLine}`;
}
else {
yield `const ${componentOriginalVar} = ({} as __VLS_WithComponent<'${getCanonicalComponentName(node.tag)}', __VLS_LocalComponents, `;
if (options.selfComponentName && possibleOriginalNames.includes(options.selfComponentName)) {
yield `typeof __VLS_export, `;
}
else {
yield `void, `;
}
yield getPossibleOriginalComponentNames(node.tag, false)
.map(name => `'${name}'`)
.join(`, `);
yield `>).`;
yield* generateCanonicalComponentName(node.tag, tagOffsets[0], {
...codeFeatures_1.codeFeatures.semanticWithoutHighlight,
...options.vueCompilerOptions.checkUnknownComponents
? codeFeatures_1.codeFeatures.verification
: codeFeatures_1.codeFeatures.doNotReportTs2339AndTs2551,
});
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])) {
yield `typeof __VLS_components.`;
yield* (0, camelized_1.generateCamelized)(shouldCapitalize ? (0, shared_1.capitalize)(node.tag) : node.tag, 'template', tagOffset, codeFeatures_1.codeFeatures.navigation);
yield `, `;
}
}
yield `]} */${utils_1.endOfLine}`;
// auto import support
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;
}
}
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, codeFeatures_1.codeFeatures.doNotReportTs6133, componentVNodeVar);
yield ` = ${componentFunctionalVar}`;
yield* generateComponentGeneric(ctx);
yield `(`;
yield* (0, wrapWith_1.wrapWith)(tagOffsets[0], tagOffsets[0] + node.tag.length, codeFeatures_1.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, componentOriginalVar, 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 (ctx.inVFor) {
yield `[]`;
}
yield utils_1.endOfLine;
if (refName && offset) {
ctx.addTemplateRef(refName, `typeof ${ctx.getHoistVariable(componentInstanceVar)}`, offset);
}
if (isRootNode) {
ctx.singleRootElTypes.push(`NonNullable<typeof ${componentInstanceVar}>['$el']`);
}
}
if (hasVBindAttrs(options, ctx, node)) {
const attrsVar = ctx.getInternalVariable();
yield `var ${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');
yield* (0, vSlot_1.generateVSlot)(options, ctx, node, slotDir);
if (ctx.currentComponent.used) {
yield `var ${componentCtxVar}!: __VLS_FunctionalComponentCtx<typeof ${componentOriginalVar}, typeof ${componentVNodeVar}>${utils_1.endOfLine}`;
}
}
function* generateElement(options, ctx, node) {
const [startTagOffset, endTagOffset] = (0, shared_2.getElementTagOffsets)(node, options.template);
const failedPropExps = [];
yield `__VLS_asFunctionalElement(__VLS_elements`;
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, node.tag, startTagOffset, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
if (endTagOffset !== undefined) {
yield `, __VLS_elements`;
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, node.tag, endTagOffset, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
}
yield `)(`;
yield* (0, wrapWith_1.wrapWith)(startTagOffset, startTagOffset + node.tag.length, codeFeatures_1.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 (ctx.inVFor) {
typeExp += `[]`;
}
ctx.addTemplateRef(refName, typeExp, offset);
}
if (ctx.singleRootNodes.has(node)) {
ctx.singleRootElTypes.push(`__VLS_NativeElements['${node.tag}']`);
}
if (hasVBindAttrs(options, ctx, node)) {
ctx.inheritedAttrVars.add(`__VLS_elements.${node.tag}`);
}
(0, styleScopedClasses_1.collectStyleScopedClassReferences)(options, ctx, node);
const { currentComponent } = ctx;
ctx.currentComponent = undefined;
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node.children);
ctx.currentComponent = currentComponent;
}
function* generateFailedPropExps(options, ctx, failedPropExps) {
for (const failedExp of failedPropExps) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.all, failedExp.node.loc.source, failedExp.node.loc.start.offset, 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.currentInfo.generic) {
const { content, offset } = ctx.currentInfo.generic;
yield* (0, wrapWith_1.wrapWith)(offset, offset + content.length, codeFeatures_1.codeFeatures.verification, `<`, [
content,
'template',
offset,
codeFeatures_1.codeFeatures.all,
], `>`);
}
}
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, codeFeatures_1.codeFeatures.navigation);
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'));
}
//# sourceMappingURL=element.js.map

View File

@@ -0,0 +1,5 @@
import type * 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, children: (CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode)[], enterNode?: boolean): Generator<Code>;

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementChildren = generateElementChildren;
const templateChild_1 = require("./templateChild");
function* generateElementChildren(options, ctx, children, enterNode = true) {
yield* ctx.generateAutoImportCompletion();
for (const childNode of children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, childNode, enterNode);
}
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,86 @@
"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 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') {
continue;
}
if (!builtInDirectives.has(prop.name)) {
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, codeFeatures_1.codeFeatures.verification, `__VLS_asFunctionalDirective(`, ...generateIdentifier(options, 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, prop) {
const rawName = 'v-' + prop.name;
yield* (0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.start.offset + rawName.length, codeFeatures_1.codeFeatures.verification, `__VLS_directives.`, ...(0, camelized_1.generateCamelized)(rawName, 'template', prop.loc.start.offset, {
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletion,
verification: options.vueCompilerOptions.checkUnknownDirectives && !builtInDirectives.has(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, codeFeatures_1.codeFeatures.verification, `arg`);
yield `: `;
if (arg.isStatic) {
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(arg.content, startOffset, codeFeatures_1.codeFeatures.all);
}
else {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.all, arg.content, startOffset, `(`, `)`);
}
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, codeFeatures_1.codeFeatures.verification, propertyName);
yield `: { `;
for (const mod of modifiers) {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, mod.content, mod.loc.start.offset, codeFeatures_1.codeFeatures.withoutHighlight);
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, codeFeatures_1.codeFeatures.verification, `value`);
yield `: `;
yield* (0, elementProps_1.generatePropExp)(options, ctx, prop, exp);
}
//# sourceMappingURL=elementDirectives.js.map

View File

@@ -0,0 +1,10 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type * as ts from 'typescript';
import type { Code, VueCodeInformation } from '../../types';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateElementEvents(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, componentOriginalVar: string, componentFunctionalVar: string, componentVNodeVar: string, componentCtxVar: string): Generator<Code>;
export declare function generateEventArg(options: TemplateCodegenOptions, name: string, start: number, directive?: string, features?: VueCodeInformation): Generator<Code>;
export declare function generateEventExpression(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, prop: CompilerDOM.DirectiveNode): Generator<Code>;
export declare function generateModelEventExpression(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,175 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementEvents = generateElementEvents;
exports.generateEventArg = generateEventArg;
exports.generateEventExpression = generateEventExpression;
exports.generateModelEventExpression = generateModelEventExpression;
exports.isCompoundExpression = isCompoundExpression;
const CompilerDOM = require("@vue/compiler-dom");
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 interpolation_1 = require("./interpolation");
function* generateElementEvents(options, ctx, node, componentOriginalVar, componentFunctionalVar, componentVNodeVar, componentCtxVar) {
let emitsVar;
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)
|| options.vueCompilerOptions.strictVModel
&& prop.name === 'model'
&& (!prop.arg || prop.arg.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && prop.arg.isStatic))) {
ctx.currentComponent.used = true;
if (!emitsVar) {
emitsVar = ctx.getInternalVariable();
propsVar = ctx.getInternalVariable();
yield `let ${emitsVar}!: __VLS_ResolveEmits<typeof ${componentOriginalVar}, typeof ${componentCtxVar}.emit>${utils_1.endOfLine}`;
yield `let ${propsVar}!: __VLS_FunctionalComponentProps<typeof ${componentFunctionalVar}, typeof ${componentVNodeVar}>${utils_1.endOfLine}`;
}
let source = prop.arg?.loc.source ?? 'model-value';
let start = prop.arg?.loc.start.offset;
let propPrefix = 'on-';
let emitPrefix = '';
if (prop.name === 'model') {
propPrefix = 'onUpdate:';
emitPrefix = 'update:';
}
else if (source.startsWith('vue:')) {
source = source.slice('vue:'.length);
start = start + 'vue:'.length;
propPrefix = 'onVnode-';
emitPrefix = 'vnode-';
}
const propName = (0, shared_1.camelize)(propPrefix + source);
const emitName = emitPrefix + source;
const camelizedEmitName = (0, shared_1.camelize)(emitName);
yield `const ${ctx.getInternalVariable()}: __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${emitsVar}, '${propName}', '${emitName}', '${camelizedEmitName}'> = (${utils_1.newLine}`;
if (prop.name === 'on') {
yield `{ `;
yield* generateEventArg(options, source, start, emitPrefix.slice(0, -1), codeFeatures_1.codeFeatures.navigation);
yield `: {} as any } as typeof ${emitsVar},${utils_1.newLine}`;
}
yield `{ `;
if (prop.name === 'on') {
yield* generateEventArg(options, source, start, propPrefix.slice(0, -1));
yield `: `;
yield* generateEventExpression(options, ctx, prop);
}
else {
yield `'${propName}': `;
yield* generateModelEventExpression(options, ctx, prop);
}
yield `})${utils_1.endOfLine}`;
}
}
}
function* generateEventArg(options, name, start, directive = 'on', features) {
features ??= {
...codeFeatures_1.codeFeatures.semanticWithoutHighlight,
...codeFeatures_1.codeFeatures.navigationWithoutRename,
...options.vueCompilerOptions.checkUnknownEvents
? codeFeatures_1.codeFeatures.verification
: codeFeatures_1.codeFeatures.doNotReportTs2353AndTs2561,
};
if (directive.length) {
name = (0, shared_1.capitalize)(name);
}
if (utils_1.identifierRegex.test((0, shared_1.camelize)(name))) {
yield ['', 'template', start, features];
yield directive;
yield* (0, camelized_1.generateCamelized)(name, 'template', start, utils_1.combineLastMapping);
}
else {
yield* (0, wrapWith_1.wrapWith)(start, start + name.length, features, `'`, directive, ...(0, camelized_1.generateCamelized)(name, 'template', start, utils_1.combineLastMapping), `'`);
}
}
function* generateEventExpression(options, ctx, prop) {
if (prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
let isFirstMapping = true;
const ast = (0, utils_1.createTsAst)(options.ts, ctx.inlineTsAsts, prop.exp.content);
const isCompound = isCompoundExpression(options.ts, ast);
const interpolation = (0, interpolation_1.generateInterpolation)(options, ctx, 'template', offset => {
if (isCompound && 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 codeFeatures_1.codeFeatures.all;
}, prop.exp.content, prop.exp.loc.start.offset, isCompound ? `` : `(`, isCompound ? `` : `)`);
if (isCompound) {
yield `(...[$event]) => {${utils_1.newLine}`;
ctx.addLocalVariable('$event');
yield* ctx.generateConditionGuards();
yield* interpolation;
yield utils_1.endOfLine;
ctx.removeLocalVariable('$event');
yield* ctx.generateAutoImportCompletion();
yield `}`;
}
else {
yield* interpolation;
}
}
else {
yield `() => {}`;
}
}
function* generateModelEventExpression(options, ctx, prop) {
if (prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
yield `(...[$event]) => {${utils_1.newLine}`;
yield* ctx.generateConditionGuards();
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.verification, prop.exp.content, prop.exp.loc.start.offset);
yield ` = $event${utils_1.endOfLine}`;
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 } 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, enableCodeFeatures?: boolean): Generator<Code>;

View File

@@ -0,0 +1,265 @@
"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 muggle_string_1 = require("muggle-string");
const picomatch_1 = require("picomatch");
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)(options, 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, picomatch_1.isMatch)(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 features = getPropsCodeFeatures(strictPropsCheck);
if (shouldSpread) {
yield `...{ `;
}
const codes = [...(0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, codeFeatures_1.codeFeatures.verification, ...(prop.arg
? (0, objectProperty_1.generateObjectProperty)(options, ctx, propName, prop.arg.loc.start.offset, features, shouldCamelize)
: (0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.start.offset + 'v-model'.length, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion, propName)), `: `, ...(0, wrapWith_1.wrapWith)(prop.arg?.loc.start.offset ?? prop.loc.start.offset, prop.arg?.loc.end.offset ?? prop.loc.end.offset, codeFeatures_1.codeFeatures.verification, ...generatePropExp(options, ctx, prop, prop.exp, 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, picomatch_1.isMatch)(prop.name, pattern))) {
continue;
}
const shouldSpread = prop.name === 'style' || prop.name === 'class';
const shouldCamelize = isComponent && getShouldCamelize(options, prop, prop.name);
const features = getPropsCodeFeatures(strictPropsCheck);
if (shouldSpread) {
yield `...{ `;
}
const codes = [...(0, wrapWith_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, codeFeatures_1.codeFeatures.verification, ...(0, objectProperty_1.generateObjectProperty)(options, ctx, prop.name, prop.loc.start.offset, features, shouldCamelize), `: `, ...(prop.value
? generateAttrValue(prop.value, codeFeatures_1.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.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, codeFeatures_1.codeFeatures.verification, `...`, ...generatePropExp(options, ctx, prop, prop.exp, enableCodeFeatures))];
if (enableCodeFeatures) {
yield* codes;
}
else {
yield (0, muggle_string_1.toString)(codes);
}
yield `,${utils_1.newLine}`;
}
}
}
}
function* generatePropExp(options, ctx, prop, exp, enableCodeFeatures = true) {
const isShorthand = prop.arg?.loc.start.offset === prop.exp?.loc.start.offset;
const features = isShorthand
? codeFeatures_1.codeFeatures.withoutHighlightAndCompletion
: codeFeatures_1.codeFeatures.all;
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, `(`, `)`);
}
else {
const propVariableName = (0, shared_1.camelize)(exp.loc.source);
if (utils_1.identifierRegex.test(propVariableName)) {
const isDestructuredProp = options.destructuredPropNames.has(propVariableName);
const isTemplateRef = options.templateRefNames.has(propVariableName);
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, picomatch_1.isMatch)(propName, pattern));
}
function getPropsCodeFeatures(strictPropsCheck) {
return {
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletion,
...strictPropsCheck
? codeFeatures_1.codeFeatures.verification
: codeFeatures_1.codeFeatures.doNotReportTs2353AndTs2561,
};
}
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 'modelValue';
}
//# sourceMappingURL=elementProps.js.map

View File

@@ -0,0 +1,82 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type * as ts from 'typescript';
import type { Code, Sfc, VueCompilerOptions } from '../../types';
export interface TemplateCodegenOptions {
ts: typeof ts;
compilerOptions: ts.CompilerOptions;
vueCompilerOptions: VueCompilerOptions;
template: NonNullable<Sfc['template']>;
scriptSetupBindingNames: Set<string>;
scriptSetupImportComponentNames: Set<string>;
destructuredPropNames: Set<string>;
templateRefNames: Set<string>;
hasDefineSlots?: boolean;
propsAssignName?: string;
slotsAssignName?: string;
inheritAttrs: boolean;
selfComponentName?: string;
}
export { generate as generateTemplate };
declare function generate(options: TemplateCodegenOptions): {
codes: Code[];
currentInfo: {
ignoreError?: boolean;
expectError?: {
token: number;
node: CompilerDOM.CommentNode;
};
generic?: {
content: string;
offset: number;
};
};
resolveCodeFeatures: (features: import("../../types").VueCodeInformation) => import("../../types").VueCodeInformation;
inlineTsAsts: Map<string, ts.SourceFile> | undefined;
inVFor: boolean;
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>>;
blockConditions: string[];
scopedClasses: {
source: string;
className: string;
offset: number;
}[];
emptyClassOffsets: number[];
inlayHints: import("../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>;
addTemplateRef(name: string, typeExp: string, offset: number): void;
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>;
generateAutoImportCompletion(): Generator<Code>;
enter(node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode): boolean;
exit(): Generator<Code>;
};
export declare function forEachElementNode(node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode): Generator<CompilerDOM.ElementNode>;

View File

@@ -0,0 +1,176 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplate = generate;
exports.forEachElementNode = forEachElementNode;
const CompilerDOM = require("@vue/compiler-dom");
const codeFeatures_1 = require("../codeFeatures");
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 generate(options) {
const context = (0, context_1.createTemplateCodegenContext)(options, options.template.ast);
const codegen = generateTemplate(options, context);
const codes = [];
for (const code of codegen) {
if (typeof code === 'object') {
code[3] = context.resolveCodeFeatures(code[3]);
}
codes.push(code);
}
return {
...context,
codes,
};
}
function* generateTemplate(options, ctx) {
if (options.slotsAssignName) {
ctx.addLocalVariable(options.slotsAssignName);
}
if (options.propsAssignName) {
ctx.addLocalVariable(options.propsAssignName);
}
if (options.vueCompilerOptions.inferTemplateDollarSlots) {
ctx.dollarVars.add('$slots');
}
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);
}
yield* (0, styleScopedClasses_1.generateStyleScopedClassReferences)(ctx);
yield* ctx.generateHoistVariables();
const dollarTypes = [
['$slots', yield* generateSlots(options, ctx)],
['$attrs', yield* generateInheritedAttrs(options, ctx)],
['$refs', yield* generateTemplateRefs(options, ctx)],
['$el', yield* generateRootEl(ctx)],
].filter(([name]) => ctx.dollarVars.has(name));
if (dollarTypes.length) {
yield `var __VLS_dollars!: {${utils_1.newLine}`;
for (const [name, type] of dollarTypes) {
yield `${name}: ${type}${utils_1.endOfLine}`;
}
yield `} & { [K in keyof import('${options.vueCompilerOptions.lib}').ComponentPublicInstance]: unknown }${utils_1.endOfLine}`;
}
}
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, codeFeatures_1.codeFeatures.navigation);
}
else {
yield* (0, wrapWith_1.wrapWith)(slot.tagRange[0], slot.tagRange[1], codeFeatures_1.codeFeatures.navigation, `default`);
}
yield `?: (props: typeof ${slot.propsVar}) => any }`;
}
yield utils_1.endOfLine;
}
return `__VLS_Slots`;
}
function* generateInheritedAttrs(options, ctx) {
yield `type __VLS_InheritedAttrs = ${ctx.inheritedAttrVars.size
? `Partial<${[...ctx.inheritedAttrVars].map(name => `typeof ${name}`).join(` & `)}>`
: `{}`}`;
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,
codeFeatures_1.codeFeatures.all,
];
yield `,`;
}
yield `]${utils_1.endOfLine}`;
}
return `import('${options.vueCompilerOptions.lib}').ComponentPublicInstance['$attrs'] & __VLS_InheritedAttrs`;
}
function* generateTemplateRefs(options, ctx) {
yield `type __VLS_TemplateRefs = {}`;
for (const [name, refs] of ctx.templateRefs) {
yield `${utils_1.newLine}& `;
if (refs.length >= 2) {
yield `(`;
}
for (let i = 0; i < refs.length; i++) {
const { typeExp, offset } = refs[i];
if (i) {
yield ` | `;
}
yield `{ `;
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, name, offset, codeFeatures_1.codeFeatures.navigation);
yield `: ${typeExp} }`;
}
if (refs.length >= 2) {
yield `)`;
}
}
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 (const branch of node.branches) {
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,5 @@
import type { Code, VueCodeInformation } from '../../types';
import type { ScriptCodegenOptions } from '../script';
import type { TemplateCodegenContext } from './context';
import type { TemplateCodegenOptions } from './index';
export declare function generateInterpolation(options: TemplateCodegenOptions | ScriptCodegenOptions, ctx: TemplateCodegenContext, source: string, data: VueCodeInformation | ((offset: number) => VueCodeInformation) | undefined, code: string, start: number | undefined, prefix?: string, suffix?: string): Generator<Code>;

View File

@@ -0,0 +1,250 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateInterpolation = generateInterpolation;
const shared_1 = require("@vue/shared");
const collectBindings_1 = require("../../utils/collectBindings");
const shared_2 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
// https://github.com/vuejs/core/blob/fb0c3ca519f1fccf52049cd6b8db3a67a669afe9/packages/compiler-core/src/transforms/transformExpression.ts#L47
const isLiteralWhitelisted = /*@__PURE__*/ (0, shared_1.makeMap)('true,false,null,this');
function* generateInterpolation(options, ctx, source, data, code, start, prefix = '', suffix = '') {
const { ts, destructuredPropNames, templateRefNames, } = options;
for (let [section, offset, type] of forEachInterpolationSegment(ts, ctx.inlineTsAsts, destructuredPropNames, templateRefNames, ctx, code, start, prefix, suffix)) {
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'
? codeFeatures_1.codeFeatures.verification
: typeof data === 'function'
? data(start + offset)
: data,
];
}
else {
yield section;
}
}
yield addSuffix;
}
}
}
function* forEachInterpolationSegment(ts, inlineTsAsts, destructuredPropNames, templateRefNames, ctx, originalCode, start, prefix, suffix) {
const code = prefix + originalCode + suffix;
const offset = start !== undefined ? start - prefix.length : undefined;
let ctxVars = [];
if (utils_1.identifierRegex.test(originalCode) && !shouldIdentifierSkipped(ctx, originalCode, destructuredPropNames)) {
ctxVars.push({
text: originalCode,
offset: prefix.length,
});
}
else {
const ast = (0, utils_1.createTsAst)(ts, inlineTsAsts, code);
const varCb = (id, isShorthand) => {
const text = (0, shared_2.getNodeText)(ts, id, ast);
if (!shouldIdentifierSkipped(ctx, text, destructuredPropNames)) {
ctxVars.push({
text,
offset: (0, shared_2.getStartEnd)(ts, id, ast).start,
isShorthand,
});
}
};
ts.forEachChild(ast, node => walkIdentifiers(ts, node, ast, varCb, ctx, [], true));
}
ctxVars = ctxVars.sort((a, b) => a.offset - b.offset);
if (ctxVars.length) {
for (let i = 0; i < ctxVars.length; i++) {
const lastVar = ctxVars[i - 1];
const curVar = ctxVars[i];
const lastVarEnd = lastVar ? lastVar.offset + lastVar.text.length : 0;
if (curVar.isShorthand) {
yield [code.slice(lastVarEnd, curVar.offset + curVar.text.length), lastVarEnd];
yield [': ', undefined];
}
else {
yield [code.slice(lastVarEnd, curVar.offset), lastVarEnd, i ? undefined : 'startText'];
}
yield* generateVar(templateRefNames, ctx, code, offset, curVar);
}
const lastVar = ctxVars.at(-1);
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(templateRefNames, ctx, code, offset, curVar) {
// fix https://github.com/vuejs/language-tools/issues/1205
// fix https://github.com/vuejs/language-tools/issues/1264
yield ['', curVar.offset, 'errorMappingOnly'];
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 (offset !== undefined) {
ctx.accessExternalVariable(curVar.text, offset + curVar.offset);
}
else {
ctx.accessExternalVariable(curVar.text);
}
if (ctx.dollarVars.has(curVar.text)) {
yield [`__VLS_dollars.`, undefined];
}
else {
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 = false) {
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);
}
else if (ts.isVariableDeclaration(node)) {
const bindingNames = (0, collectBindings_1.collectBindingNames)(ts, node.name, ast);
for (const name of bindingNames) {
ctx.addLocalVariable(name);
blockVars.push(name);
}
walkIdentifiersInBinding(ts, node, ast, cb, ctx, blockVars);
}
else if (ts.isArrayBindingPattern(node) || ts.isObjectBindingPattern(node)) {
for (const element of node.elements) {
if (ts.isBindingElement(element)) {
walkIdentifiersInBinding(ts, element, ast, cb, ctx, blockVars);
}
}
}
else if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
walkIdentifiersInFunction(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);
}
walkIdentifiers(ts, prop.initializer, ast, cb, ctx, blockVars);
}
// fix https://github.com/vuejs/language-tools/issues/1156
else if (ts.isShorthandPropertyAssignment(prop)) {
walkIdentifiers(ts, prop, ast, cb, ctx, blockVars);
}
// 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);
}
// fix https://github.com/vuejs/language-tools/issues/4604
else if (ts.isFunctionLike(prop) && prop.body) {
walkIdentifiersInFunction(ts, prop, ast, cb, ctx);
}
}
}
// fix https://github.com/vuejs/language-tools/issues/1422
else if (ts.isTypeNode(node)) {
walkIdentifiersInTypeNode(ts, node, cb);
}
else {
const _blockVars = blockVars;
if (ts.isBlock(node)) {
blockVars = [];
}
ts.forEachChild(node, node => walkIdentifiers(ts, node, ast, cb, ctx, blockVars));
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 walkIdentifiersInBinding(ts, node, ast, cb, ctx, blockVars) {
if ('type' in node && node.type) {
walkIdentifiersInTypeNode(ts, node.type, cb);
}
if (!ts.isIdentifier(node.name)) {
walkIdentifiers(ts, node.name, ast, cb, ctx, blockVars);
}
if (node.initializer) {
walkIdentifiers(ts, node.initializer, ast, cb, ctx, blockVars);
}
}
function walkIdentifiersInFunction(ts, node, ast, cb, ctx) {
const functionArgs = [];
for (const param of node.parameters) {
functionArgs.push(...(0, collectBindings_1.collectBindingNames)(ts, param.name, ast));
walkIdentifiersInBinding(ts, param, ast, cb, ctx, functionArgs);
}
for (const varName of functionArgs) {
ctx.addLocalVariable(varName);
}
if (node.body) {
walkIdentifiers(ts, node.body, ast, cb, ctx, [], true);
}
for (const varName of functionArgs) {
ctx.removeLocalVariable(varName);
}
}
function walkIdentifiersInTypeNode(ts, node, cb) {
if (ts.isTypeQueryNode(node)) {
let id = node.exprName;
while (!ts.isIdentifier(id)) {
id = id.left;
}
cb(id, false);
}
else {
ts.forEachChild(node, node => walkIdentifiersInTypeNode(ts, node, cb));
}
}
function shouldIdentifierSkipped(ctx, text, destructuredPropNames) {
return ctx.hasLocalVariable(text)
// https://github.com/vuejs/core/blob/245230e135152900189f13a4281302de45fdcfaa/packages/compiler-core/src/transforms/transformExpression.ts#L342-L352
|| (0, shared_1.isGloballyAllowed)(text)
|| isLiteralWhitelisted(text)
|| text === 'require'
|| text.startsWith('__VLS_')
|| destructuredPropNames?.has(text);
}
//# 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, 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, shouldCamelize = false, shouldBeConstant = false) {
if (code.startsWith('[') && code.endsWith(']')) {
if (shouldBeConstant) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', features, code.slice(1, -1), offset + 1, `[__VLS_tryAsConstant(`, `)]`);
}
else {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', features, code, offset);
}
}
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): 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) {
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);
}
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 shared_1 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
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] = (0, shared_1.getElementTagOffsets)(node, options.template);
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.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, codeFeatures_1.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),
`]`,
];
}
else {
codes = [`['default']`];
}
yield* (0, wrapWith_1.wrapWith)(nameProp.loc.start.offset, nameProp.loc.end.offset, codeFeatures_1.codeFeatures.verification, options.slotsAssignName ?? '__VLS_slots', ...codes);
}
else {
yield* (0, wrapWith_1.wrapWith)(startTagOffset, startTagEndOffset, codeFeatures_1.codeFeatures.verification, `${options.slotsAssignName ?? '__VLS_slots'}[`, ...(0, wrapWith_1.wrapWith)(startTagOffset, startTagEndOffset, codeFeatures_1.codeFeatures.verification, `'default'`), `]`);
}
yield `)(`;
yield* (0, wrapWith_1.wrapWith)(startTagOffset, startTagEndOffset, codeFeatures_1.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', codeFeatures_1.codeFeatures.all, nameProp.exp.content, nameProp.exp.loc.start.offset);
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* (0, elementChildren_1.generateElementChildren)(options, ctx, node.children);
}
//# 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,162 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleScopedClassReferences = generateStyleScopedClassReferences;
exports.collectStyleScopedClassReferences = collectStyleScopedClassReferences;
const CompilerDOM = require("@vue/compiler-dom");
const shared_1 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
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,
codeFeatures_1.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, codeFeatures_1.codeFeatures.navigation, `'`, ...(0, escaped_1.generateEscaped)(className, source, offset, codeFeatures_1.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 {
const [content, startOffset] = (0, utils_1.normalizeAttributeValue)(prop.value);
if (content) {
const classes = collectClasses(content, startOffset);
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 - 1;
const { ts } = options;
const ast = ts.createSourceFile('', content, 99);
const literals = [];
ts.forEachChild(ast, node => {
if (!ts.isExpressionStatement(node)
|| !ts.isParenthesizedExpression(node.expression)) {
return;
}
const { expression } = node.expression;
if (ts.isStringLiteralLike(expression)) {
literals.push(expression);
}
else if (ts.isArrayLiteralExpression(expression)) {
walkArrayLiteral(expression);
}
else 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, shared_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;
}
//# 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, enterNode?: 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,186 @@
"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 codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const element_1 = require("./element");
const elementChildren_1 = require("./elementChildren");
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");
// @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, enterNode = true) {
if (enterNode && !ctx.enter(node)) {
return;
}
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);
}
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node.children);
}
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);
}
else {
const { currentComponent } = ctx;
yield* (0, element_1.generateComponent)(options, ctx, node);
ctx.currentComponent = currentComponent;
}
}
}
else if (node.type === CompilerDOM.NodeTypes.TEXT_CALL) {
// {{ var }}
yield* generateTemplateChild(options, ctx, node.content, false);
}
else if (node.type === CompilerDOM.NodeTypes.COMPOUND_EXPRESSION) {
// {{ ... }} {{ ... }}
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node.children.filter(child => typeof child === 'object'), false);
}
else if (node.type === CompilerDOM.NodeTypes.INTERPOLATION) {
// {{ ... }}
const [content, start] = parseInterpolationNode(node, options.template.content);
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.all, content, start, `(`, `)${utils_1.endOfLine}`);
}
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
}
if (enterNode) {
yield* ctx.exit();
}
}
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,82 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVFor = generateVFor;
exports.parseVForNode = parseVForNode;
const CompilerDOM = require("@vue/compiler-dom");
const collectBindings_1 = require("../../utils/collectBindings");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const elementChildren_1 = require("./elementChildren");
const interpolation_1 = require("./interpolation");
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, ctx.inlineTsAsts, `const [${leftExpressionText}]`);
forBlockVars.push(...(0, collectBindings_1.collectBindingNames)(options.ts, collectAst, collectAst));
yield [
leftExpressionText,
'template',
leftExpressionRange.start,
codeFeatures_1.codeFeatures.all,
];
}
yield `] of `;
if (source.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
yield `__VLS_getVForSourceType(`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.all, source.content, source.loc.start.offset, `(`, `)`);
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', codeFeatures_1.codeFeatures.all, prop.value.content, prop.value.loc.start.offset, `(`, `)`);
yield utils_1.endOfLine;
}
}
}
}
const { inVFor } = ctx;
ctx.inVFor = true;
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node.children, isFragment);
ctx.inVFor = inVFor;
for (const varName of forBlockVars) {
ctx.removeLocalVariable(varName);
}
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,46 @@
"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 codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const elementChildren_1 = require("./elementChildren");
const interpolation_1 = require("./interpolation");
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', codeFeatures_1.codeFeatures.all, branch.condition.content, branch.condition.loc.start.offset, `(`, `)`)];
yield* codes;
ctx.blockConditions.push((0, muggle_string_1.toString)(codes));
addedBlockCondition = true;
yield ` `;
}
yield `{${utils_1.newLine}`;
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, branch.children, isFragment(node));
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,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 generateVSlot(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, slotDir: CompilerDOM.DirectiveNode | undefined): Generator<Code>;

View File

@@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVSlot = generateVSlot;
const CompilerDOM = require("@vue/compiler-dom");
const muggle_string_1 = require("muggle-string");
const collectBindings_1 = require("../../utils/collectBindings");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const wrapWith_1 = require("../utils/wrapWith");
const elementChildren_1 = require("./elementChildren");
const interpolation_1 = require("./interpolation");
const objectProperty_1 = require("./objectProperty");
function* generateVSlot(options, ctx, node, slotDir) {
if (!ctx.currentComponent) {
return;
}
const slotBlockVars = [];
const slotVar = ctx.getInternalVariable();
if (slotDir) {
yield `{${utils_1.newLine}`;
}
if (slotDir || node.children.length) {
ctx.currentComponent.used = true;
yield `const { `;
if (slotDir) {
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 ? codeFeatures_1.codeFeatures.withoutHighlight : codeFeatures_1.codeFeatures.all, false, true);
}
else {
yield* (0, wrapWith_1.wrapWith)(slotDir.loc.start.offset, slotDir.loc.start.offset + (slotDir.rawName?.length ?? 0), codeFeatures_1.codeFeatures.withoutHighlightAndCompletion, `default`);
}
}
else {
// #932: reference for implicit default slot
yield* (0, wrapWith_1.wrapWith)(node.loc.start.offset, node.loc.end.offset, codeFeatures_1.codeFeatures.navigation, `default`);
}
yield `: ${slotVar} } = ${ctx.currentComponent.ctxVar}.slots!${utils_1.endOfLine}`;
}
if (slotDir?.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const slotAst = (0, utils_1.createTsAst)(options.ts, ctx.inlineTsAsts, `(${slotDir.exp.content}) => {}`);
slotBlockVars.push(...(0, collectBindings_1.collectBindingNames)(options.ts, slotAst, slotAst));
yield* generateSlotParameters(options, ctx, slotAst, slotDir.exp, slotVar);
}
for (const varName of slotBlockVars) {
ctx.addLocalVariable(varName);
}
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node.children);
for (const varName of slotBlockVars) {
ctx.removeLocalVariable(varName);
}
if (slotDir) {
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),
codeFeatures_1.codeFeatures.completion,
];
yield `'/* empty slot name completion */]${utils_1.endOfLine}`;
}
yield `}${utils_1.newLine}`;
}
}
function* generateSlotParameters(options, ctx, ast, exp, slotVar) {
const { ts } = options;
const statement = ast.statements[0];
if (!statement || !ts.isExpressionStatement(statement) || !ts.isArrowFunction(statement.expression)) {
return;
}
const { expression } = statement;
const startOffset = exp.loc.start.offset - 1;
const types = [];
const interpolation = [...(0, interpolation_1.generateInterpolation)(options, ctx, 'template', codeFeatures_1.codeFeatures.all, ast.text, startOffset)];
(0, muggle_string_1.replaceSourceRange)(interpolation, 'template', startOffset, startOffset + `(`.length);
(0, muggle_string_1.replaceSourceRange)(interpolation, 'template', startOffset + ast.text.length - `) => {}`.length, startOffset + ast.text.length);
for (const { name, type } of expression.parameters) {
if (type) {
types.push([
ast.text.slice(name.end, type.end),
'template',
startOffset + name.end,
codeFeatures_1.codeFeatures.all,
]);
(0, muggle_string_1.replaceSourceRange)(interpolation, 'template', startOffset + name.end, startOffset + type.end);
}
else {
types.push(null);
}
}
yield `const [`;
yield* interpolation;
yield `] = __VLS_getSlotParameters(${slotVar}!`;
if (types.some(t => t)) {
yield `, `;
yield* (0, wrapWith_1.wrapWith)(exp.loc.start.offset, exp.loc.end.offset, codeFeatures_1.codeFeatures.verification, `(`, ...types.flatMap(type => type ? [`_`, type, `, `] : `_, `), `) => [] as any`);
}
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,11 @@
import type * as CompilerDOM from '@vue/compiler-dom';
import type * as ts from 'typescript';
import type { Code, SfcBlock, 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 normalizeAttributeValue(node: CompilerDOM.TextNode): [string, number];
export declare function createTsAst(ts: typeof import('typescript'), inlineTsAsts: Map<string, ts.SourceFile> | undefined, text: string): ts.SourceFile;
export declare function generateSfcBlockSection(block: SfcBlock, start: number, end: number, features: VueCodeInformation): Code;
export declare function generatePartiallyEnding(source: string, end: number, mark: string, delimiter?: string): Generator<Code>;

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.identifierRegex = exports.combineLastMapping = exports.endOfLine = exports.newLine = void 0;
exports.normalizeAttributeValue = normalizeAttributeValue;
exports.createTsAst = createTsAst;
exports.generateSfcBlockSection = generateSfcBlockSection;
exports.generatePartiallyEnding = generatePartiallyEnding;
const codeFeatures_1 = require("../codeFeatures");
exports.newLine = `\n`;
exports.endOfLine = `;${exports.newLine}`;
exports.combineLastMapping = { __combineOffset: 1 };
exports.identifierRegex = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
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, inlineTsAsts, text) {
let ast = inlineTsAsts?.get(text);
if (!ast) {
ast = ts.createSourceFile('/a.ts', text, 99);
inlineTsAsts?.set(text, ast);
}
ast.__volar_used = true;
return ast;
}
function generateSfcBlockSection(block, start, end, features) {
return [
block.content.slice(start, end),
block.name,
start,
features,
];
}
function* generatePartiallyEnding(source, end, mark, delimiter = 'debugger') {
yield delimiter;
yield [``, source, end, codeFeatures_1.codeFeatures.verification];
yield `/* PartiallyEnd: ${mark} */${exports.newLine}`;
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,3 @@
import type { Code } from '../../types';
export declare function generateIntersectMerge(codes: Code[]): Generator<Code>;
export declare function generateSpreadMerge(codes: Code[]): Generator<Code>;

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateIntersectMerge = generateIntersectMerge;
exports.generateSpreadMerge = generateSpreadMerge;
const index_1 = require("./index");
function* generateIntersectMerge(codes) {
yield codes[0];
for (let i = 1; i < codes.length; i++) {
yield ` & `;
yield codes[i];
}
}
function* generateSpreadMerge(codes) {
if (codes.length === 1) {
yield codes[0];
}
else {
yield `{${index_1.newLine}`;
for (const code of codes) {
yield `...`;
yield code;
yield `,${index_1.newLine}`;
}
yield `}`;
}
}
//# sourceMappingURL=merge.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,23 @@
import type * as ts from 'typescript';
import type { RawVueCompilerOptions, VueCompilerOptions, VueLanguagePlugin } from './types';
interface ParseConfigHost extends Omit<ts.ParseConfigHost, 'readDirectory'> {
}
export interface ParsedCommandLine extends Omit<ts.ParsedCommandLine, 'fileNames'> {
vueOptions: VueCompilerOptions;
}
export declare function createParsedCommandLineByJson(ts: typeof import('typescript'), host: ParseConfigHost, rootDir: string, json: any, configFileName?: string): ParsedCommandLine;
export declare function createParsedCommandLine(ts: typeof import('typescript'), host: ParseConfigHost, configFileName: string): ParsedCommandLine;
export declare class CompilerOptionsResolver {
fileExists?: ((path: string) => boolean) | undefined;
options: Omit<RawVueCompilerOptions, 'target' | 'globalTypesPath' | 'plugins'>;
target: number | undefined;
globalTypesPath: string | undefined;
plugins: VueLanguagePlugin[];
constructor(fileExists?: ((path: string) => boolean) | undefined);
addConfig(options: RawVueCompilerOptions, rootDir: string): void;
build(defaults?: VueCompilerOptions): VueCompilerOptions;
private findNodeModulesRoot;
}
export declare function getDefaultCompilerOptions(target?: number, lib?: string, strictTemplates?: boolean): VueCompilerOptions;
export declare function writeGlobalTypes(vueOptions: VueCompilerOptions, writeFile: (fileName: string, data: string) => void): void;
export {};

View File

@@ -0,0 +1,289 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompilerOptionsResolver = void 0;
exports.createParsedCommandLineByJson = createParsedCommandLineByJson;
exports.createParsedCommandLine = createParsedCommandLine;
exports.getDefaultCompilerOptions = getDefaultCompilerOptions;
exports.writeGlobalTypes = writeGlobalTypes;
const shared_1 = require("@vue/shared");
const path_browserify_1 = require("path-browserify");
const globalTypes_1 = require("./codegen/globalTypes");
const shared_2 = require("./utils/shared");
function createParsedCommandLineByJson(ts, host, rootDir, json, configFileName) {
const extendedPaths = new Set();
const proxyHost = {
...host,
readFile(fileName) {
if (!fileName.endsWith('/package.json')) {
extendedPaths.add(fileName);
}
return host.readFile(fileName);
},
readDirectory() {
return [];
},
};
const parsed = ts.parseJsonConfigFileContent(json, proxyHost, rootDir, {}, configFileName);
const resolver = new CompilerOptionsResolver(host.fileExists);
for (const extendPath of [...extendedPaths].reverse()) {
try {
const configFile = ts.readJsonConfigFile(extendPath, host.readFile);
const obj = ts.convertToObject(configFile, []);
const rawOptions = obj?.vueCompilerOptions ?? {};
resolver.addConfig(rawOptions, path_browserify_1.posix.dirname(configFile.fileName));
}
catch { }
}
// ensure the rootDir is added to the config roots
resolver.addConfig({}, rootDir);
return {
...parsed,
vueOptions: resolver.build(),
};
}
function createParsedCommandLine(ts, host, configFileName) {
try {
const extendedPaths = new Set();
const proxyHost = {
...host,
readFile(fileName) {
if (!fileName.endsWith('/package.json')) {
extendedPaths.add(fileName);
}
return host.readFile(fileName);
},
readDirectory() {
return [];
},
};
const config = ts.readJsonConfigFile(configFileName, proxyHost.readFile);
const parsed = ts.parseJsonSourceFileConfigFileContent(config, proxyHost, path_browserify_1.posix.dirname(configFileName), {}, configFileName);
const resolver = new CompilerOptionsResolver(host.fileExists);
for (const extendPath of [...extendedPaths].reverse()) {
try {
const configFile = ts.readJsonConfigFile(extendPath, host.readFile);
const obj = ts.convertToObject(configFile, []);
const rawOptions = obj?.vueCompilerOptions ?? {};
resolver.addConfig(rawOptions, path_browserify_1.posix.dirname(configFile.fileName));
}
catch { }
}
return {
...parsed,
vueOptions: resolver.build(),
};
}
catch { }
return {
options: {},
errors: [],
vueOptions: getDefaultCompilerOptions(),
};
}
class CompilerOptionsResolver {
constructor(fileExists) {
this.fileExists = fileExists;
this.options = {};
this.plugins = [];
}
addConfig(options, rootDir) {
for (const key in options) {
switch (key) {
case 'target':
if (options[key] === 'auto') {
this.target = findVueVersion(rootDir);
}
else {
this.target = options[key];
}
break;
case 'globalTypesPath':
if (options[key] !== undefined) {
this.globalTypesPath = path_browserify_1.posix.join(rootDir, options[key]);
}
break;
case 'plugins':
this.plugins = (options.plugins ?? [])
.flatMap((pluginPath) => {
try {
const resolvedPath = resolvePath(pluginPath, rootDir);
if (resolvedPath) {
const plugin = require(resolvedPath);
plugin.__moduleName = pluginPath;
return plugin;
}
else {
console.warn('[Vue] Load plugin failed:', pluginPath);
}
}
catch (error) {
console.warn('[Vue] Resolve plugin path failed:', pluginPath, error);
}
return [];
});
break;
default:
// @ts-expect-error
this.options[key] = options[key];
break;
}
}
if (options.target === undefined) {
this.target ??= findVueVersion(rootDir);
}
}
build(defaults) {
defaults ??= getDefaultCompilerOptions(this.target, this.options.lib, this.options.strictTemplates);
const resolvedOptions = {
...defaults,
...this.options,
plugins: this.plugins,
macros: {
...defaults.macros,
...this.options.macros,
},
composables: {
...defaults.composables,
...this.options.composables,
},
fallthroughComponentNames: [
...defaults.fallthroughComponentNames,
...this.options.fallthroughComponentNames ?? [],
].map(shared_2.hyphenateTag),
// https://github.com/vuejs/vue-next/blob/master/packages/compiler-dom/src/transforms/vModel.ts#L49-L51
// https://vuejs.org/guide/essentials/forms.html#form-input-bindings
experimentalModelPropName: Object.fromEntries(Object.entries(this.options.experimentalModelPropName ?? defaults.experimentalModelPropName).map(([k, v]) => [(0, shared_1.camelize)(k), v])),
};
if (resolvedOptions.globalTypesPath === shared_1.NOOP) {
if (this.fileExists && this.globalTypesPath === undefined) {
const fileDirToGlobalTypesPath = new Map();
resolvedOptions.globalTypesPath = fileName => {
const fileDir = path_browserify_1.posix.dirname(fileName);
if (fileDirToGlobalTypesPath.has(fileDir)) {
return fileDirToGlobalTypesPath.get(fileDir);
}
const root = this.findNodeModulesRoot(fileDir, resolvedOptions.lib);
const result = root
? path_browserify_1.posix.join(root, 'node_modules', '.vue-global-types', (0, globalTypes_1.getGlobalTypesFileName)(resolvedOptions))
: undefined;
fileDirToGlobalTypesPath.set(fileDir, result);
return result;
};
}
else {
resolvedOptions.globalTypesPath = () => this.globalTypesPath;
}
}
return resolvedOptions;
}
findNodeModulesRoot(dir, lib) {
while (!this.fileExists(path_browserify_1.posix.join(dir, 'node_modules', lib, 'package.json'))) {
const parentDir = path_browserify_1.posix.dirname(dir);
if (dir === parentDir) {
return;
}
dir = parentDir;
}
return dir;
}
}
exports.CompilerOptionsResolver = CompilerOptionsResolver;
function findVueVersion(rootDir) {
const resolvedPath = resolvePath('vue/package.json', rootDir);
if (resolvedPath) {
const vuePackageJson = require(resolvedPath);
const versionNumbers = vuePackageJson.version.split('.');
return Number(versionNumbers[0] + '.' + versionNumbers[1]);
}
else {
// console.warn('Load vue/package.json failed from', folder);
}
}
function resolvePath(scriptPath, root) {
try {
if (require?.resolve) {
return require.resolve(scriptPath, { paths: [root] });
}
else {
// console.warn('failed to resolve path:', scriptPath, 'require.resolve is not supported in web');
}
}
catch {
// console.warn(error);
}
}
function getDefaultCompilerOptions(target = 99, lib = 'vue', strictTemplates = false) {
return {
target,
lib,
globalTypesPath: shared_1.NOOP,
extensions: ['.vue'],
vitePressExtensions: [],
petiteVueExtensions: [],
jsxSlots: false,
strictVModel: strictTemplates,
strictCssModules: false,
checkUnknownProps: strictTemplates,
checkUnknownEvents: strictTemplates,
checkUnknownDirectives: strictTemplates,
checkUnknownComponents: strictTemplates,
inferComponentDollarEl: false,
inferComponentDollarRefs: false,
inferTemplateDollarAttrs: false,
inferTemplateDollarEl: false,
inferTemplateDollarRefs: false,
inferTemplateDollarSlots: false,
skipTemplateCodegen: false,
fallthroughAttributes: false,
resolveStyleImports: false,
resolveStyleClassNames: 'scoped',
fallthroughComponentNames: [
'Transition',
'KeepAlive',
'Teleport',
'Suspense',
],
dataAttributes: [],
htmlAttributes: ['aria-*'],
optionsWrapper: [`(await import('${lib}')).defineComponent(`, `)`],
macros: {
defineProps: ['defineProps'],
defineSlots: ['defineSlots'],
defineEmits: ['defineEmits'],
defineExpose: ['defineExpose'],
defineModel: ['defineModel'],
defineOptions: ['defineOptions'],
withDefaults: ['withDefaults'],
},
composables: {
useAttrs: ['useAttrs'],
useCssModule: ['useCssModule'],
useSlots: ['useSlots'],
useTemplateRef: ['useTemplateRef', 'templateRef'],
},
plugins: [],
experimentalModelPropName: {
'': {
input: true,
},
value: {
input: { type: 'text' },
textarea: true,
select: true,
},
},
};
}
function writeGlobalTypes(vueOptions, writeFile) {
const writed = new Set();
const { globalTypesPath } = vueOptions;
vueOptions.globalTypesPath = (fileName) => {
const result = globalTypesPath(fileName);
if (result && !writed.has(result)) {
writed.add(result);
writeFile(result, (0, globalTypes_1.generateGlobalTypes)(vueOptions));
}
return result;
};
}
//# sourceMappingURL=compilerOptions.js.map

View File

@@ -0,0 +1,6 @@
import { type 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,114 @@
"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 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': 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) {
return [
...new Set([
'extensions',
'vitePressExtensions',
'petiteVueExtensions',
].flatMap(key => options[key])),
];
}
//# sourceMappingURL=languagePlugin.js.map

View File

@@ -0,0 +1,22 @@
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): {
exportDefault: (TextRange & {
expression: TextRange;
args: TextRange;
argsNode: ts.ObjectLiteralExpression;
componentsOption: TextRange | undefined;
componentsOptionNode: ts.ObjectLiteralExpression | undefined;
directivesOption: TextRange | undefined;
nameOption: TextRange | undefined;
inheritAttrsOption: string | undefined;
}) | undefined;
bindings: {
range: TextRange;
moduleName?: string;
isDefaultImport?: boolean;
isNamespace?: boolean;
}[];
};

View File

@@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseScriptRanges = parseScriptRanges;
const shared_1 = require("../utils/shared");
const utils_1 = require("./utils");
function parseScriptRanges(ts, ast, hasScriptSetup) {
let exportDefault;
const bindings = hasScriptSetup ? (0, utils_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 = _getNodeText(node.name);
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 = _getNodeText(node.initializer);
}
}
});
exportDefault = {
..._getStartEnd(raw),
expression: _getStartEnd(node.expression),
args: _getStartEnd(obj),
argsNode: obj,
componentsOption: componentsOptionNode ? _getStartEnd(componentsOptionNode) : undefined,
componentsOptionNode,
directivesOption: directivesOptionNode ? _getStartEnd(directivesOptionNode) : undefined,
nameOption: nameOptionNode ? _getStartEnd(nameOptionNode) : undefined,
inheritAttrsOption,
};
const comment = (0, utils_1.getClosestMultiLineCommentRange)(ts, raw, [], ast);
if (comment) {
exportDefault.start = comment.start;
}
}
}
});
return {
exportDefault,
bindings,
};
function _getStartEnd(node) {
return (0, shared_1.getStartEnd)(ts, node, ast);
}
function _getNodeText(node) {
return (0, shared_1.getNodeText)(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,69 @@
import type * as ts from 'typescript';
import type { TextRange, VueCompilerOptions } from '../types';
type CallExpressionRange = {
callExp: TextRange;
exp: TextRange;
arg?: TextRange;
typeArg?: TextRange;
};
type DefineModel = {
localName?: TextRange;
name?: TextRange;
type?: TextRange;
modifierType?: TextRange;
runtimeType?: TextRange;
defaultValue?: TextRange;
required?: 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;
}[];
defineModel: DefineModel[];
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 {};

View File

@@ -0,0 +1,284 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseScriptSetupRanges = parseScriptSetupRanges;
const collectBindings_1 = require("../utils/collectBindings");
const shared_1 = require("../utils/shared");
const utils_1 = require("./utils");
const tsCheckReg = /^\/\/\s*@ts-(?:no)?check(?:$|\s)/;
function parseScriptSetupRanges(ts, ast, vueCompilerOptions) {
const defineModel = [];
let defineProps;
let withDefaults;
let defineEmits;
let defineSlots;
let defineExpose;
let defineOptions;
const useAttrs = [];
const useCssModule = [];
const useSlots = [];
const useTemplateRef = [];
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 = (0, utils_1.parseBindingRanges)(ts, ast);
let foundNonImportExportNode = false;
let importSectionEndOffset = 0;
ts.forEachChild(ast, node => {
if (foundNonImportExportNode
|| ts.isImportDeclaration(node)
|| ts.isExportDeclaration(node)
|| ts.isEmptyStatement(node)
// fix https://github.com/vuejs/language-tools/issues/1223
|| ts.isImportEqualsDeclaration(node)) {
return;
}
if ((ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node))
&& node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)) {
return;
}
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 = (0, shared_1.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,
defineModel,
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);
if (vueCompilerOptions.macros.defineModel.includes(callText)) {
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 (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];
}
}
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);
}
defineModel.push({
localName,
name,
type,
modifierType,
runtimeType,
defaultValue,
required,
comments: (0, utils_1.getClosestMultiLineCommentRange)(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, collectBindings_1.collectBindingIdentifiers)(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) && ts.isIdentifier(parent.name)
? _getNodeText(parent.name)
: undefined,
...parseCallExpression(node),
};
}
function _getStartEnd(node) {
return (0, shared_1.getStartEnd)(ts, node, ast);
}
function _getNodeText(node) {
return (0, shared_1.getNodeText)(ts, node, ast);
}
}
function getStatementRange(ts, parents, node, ast) {
let statementRange;
for (let i = parents.length - 1; i >= 0; i--) {
const statement = parents[i];
if (ts.isStatement(statement)) {
ts.forEachChild(statement, child => {
const range = (0, shared_1.getStartEnd)(ts, child, ast);
statementRange ??= range;
statementRange.end = range.end;
});
break;
}
}
if (!statementRange) {
statementRange = (0, shared_1.getStartEnd)(ts, node, ast);
}
return statementRange;
}
//# sourceMappingURL=scriptSetupRanges.js.map

View File

@@ -0,0 +1,12 @@
import type * as ts from 'typescript';
import type { TextRange } from '../types';
export declare function parseBindingRanges(ts: typeof import('typescript'), ast: ts.SourceFile): {
range: TextRange;
moduleName?: string;
isDefaultImport?: boolean;
isNamespace?: boolean;
}[];
export declare function getClosestMultiLineCommentRange(ts: typeof import('typescript'), node: ts.Node, parents: ts.Node[], ast: ts.SourceFile): {
start: number;
end: number;
} | undefined;

View File

@@ -0,0 +1,95 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseBindingRanges = parseBindingRanges;
exports.getClosestMultiLineCommentRange = getClosestMultiLineCommentRange;
const collectBindings_1 = require("../utils/collectBindings");
const shared_1 = require("../utils/shared");
function parseBindingRanges(ts, ast) {
const bindings = [];
ts.forEachChild(ast, node => {
if (ts.isVariableStatement(node)) {
for (const decl of node.declarationList.declarations) {
const ranges = (0, collectBindings_1.collectBindingRanges)(ts, decl.name, ast);
bindings.push(...ranges.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 (0, shared_1.getStartEnd)(ts, node, ast);
}
function _getNodeText(node) {
return (0, shared_1.getNodeText)(ts, node, ast);
}
}
function getClosestMultiLineCommentRange(ts, node, parents, ast) {
for (let i = parents.length - 1; i >= 0; i--) {
if (ts.isStatement(node)) {
break;
}
node = parents[i];
}
const comment = ts.getLeadingCommentRanges(ast.text, node.pos)
?.reverse()
.find(range => range.kind === 3);
if (comment) {
return {
start: comment.pos,
end: comment.end,
};
}
}
//# sourceMappingURL=utils.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,22 @@
"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 { type VueLanguagePlugin } from './types';
export * from './plugins/shared';
export declare function createPlugins(pluginContext: Parameters<VueLanguagePlugin>[0]): import("./types").VueLanguagePluginReturn[];

View File

@@ -0,0 +1,85 @@
"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_style_css_1 = require("./plugins/vue-style-css");
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_style_css_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,91 @@
"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.2,
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,93 @@
"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 frontmatterReg = /^---[\s\S]*?\n---(?:\r?\n|$)/;
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 angleBracketReg = /<\S*:\S*>/g;
const linkReg = /\[[\s\S]*?\]\([\s\S]*?\)/g;
const sfcBlockReg = /<(script|style)\b[\s\S]*?>([\s\S]*?)<\/\1>/g;
const codeSnippetImportReg = /^\s*<<<\s*.+/gm;
const plugin = ({ vueCompilerOptions }) => {
return {
version: 2.2,
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
// frontmatter
.replace(frontmatterReg, match => ' '.repeat(match.length))
// 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))
// angle bracket: <http://foo.com>
.replace(angleBracketReg, match => ' '.repeat(match.length))
// [foo](http://foo.com)
.replace(linkReg, match => ' '.repeat(match.length));
const codes = [];
for (const match of content.matchAll(sfcBlockReg)) {
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);
}
codes.push('<template>\n');
codes.push([content, undefined, 0]);
codes.push('\n</template>');
const mappings = (0, buildMappings_1.buildMappings)(codes);
const mapper = new language_core_1.SourceMap(mappings);
const sfc = (0, parseSfc_1.parse)((0, muggle_string_1.toString)(codes));
for (const block of [
sfc.descriptor.template,
sfc.descriptor.script,
sfc.descriptor.scriptSetup,
...sfc.descriptor.styles,
...sfc.descriptor.customBlocks,
]) {
if (block) {
transformRange(block);
}
}
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 mapper.toSourceLocation(startOffset)) {
start.offset = offset;
break;
}
for (const [offset] of mapper.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,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const parseSfc_1 = require("../utils/parseSfc");
const plugin = ({ vueCompilerOptions }) => {
return {
version: 2.2,
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;
}
const sfc = (0, parseSfc_1.parse)(content);
for (const error of sfc.errors) {
// Handle 'Element is missing end tag.' error, see #4893
if ('code' in error && error.code === 24 && sfc.descriptor.template
&& error.loc?.start.line === sfc.descriptor.template.loc.start.line) {
const template = sfc.descriptor.template;
const templateText = template.content;
const endTagOffset = templateText.lastIndexOf('<');
const endTagText = templateText.slice(endTagOffset).trimEnd();
if ('</template>'.startsWith(endTagText)) {
sfc.descriptor.template.loc.end.offset = template.loc.start.offset + endTagOffset;
template.content = templateText.slice(0, endTagOffset);
}
}
}
return sfc;
},
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;

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