first commit

This commit is contained in:
Artem Anufrij
2026-10-07 18:56:27 +02:00
commit 2a8a60b725
7768 changed files with 1550851 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
import type { VueCodeInformation } from '../types';
export declare const codeFeatures: {
full: VueCodeInformation;
all: VueCodeInformation;
importCompletionOnly: VueCodeInformation;
verification: VueCodeInformation;
completion: VueCodeInformation;
withoutCompletion: VueCodeInformation;
navigation: VueCodeInformation;
navigationWithoutRename: VueCodeInformation;
navigationAndCompletion: VueCodeInformation;
navigationAndVerification: VueCodeInformation;
withoutNavigation: VueCodeInformation;
semanticWithoutHighlight: VueCodeInformation;
withoutHighlight: VueCodeInformation;
withoutHighlightAndCompletion: VueCodeInformation;
withoutSemantic: VueCodeInformation;
structure: VueCodeInformation;
structureAndFormat: VueCodeInformation;
format: VueCodeInformation;
doNotReportTs2339AndTs2551: VueCodeInformation;
doNotReportTs2353AndTs2561: VueCodeInformation;
doNotReportTs6133: VueCodeInformation;
};
/** @deprecated use `codeFeatures.full` instead */
export declare const allCodeFeatures: VueCodeInformation;
+127
View File
@@ -0,0 +1,127 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.allCodeFeatures = exports.codeFeatures = void 0;
exports.codeFeatures = defineCodeFeatures({
full: {
verification: true,
completion: true,
semantic: true,
navigation: true,
structure: true,
format: true,
},
/** @internal */
all: {
verification: true,
completion: true,
semantic: true,
navigation: true,
},
/** @internal */
importCompletionOnly: {
__importCompletion: true,
},
/** @internal */
verification: {
verification: true,
},
/** @internal */
completion: {
completion: true,
},
/** @internal */
withoutCompletion: {
verification: true,
semantic: true,
navigation: true,
},
/** @internal */
navigation: {
navigation: true,
},
/** @internal */
navigationWithoutRename: {
navigation: { shouldRename: () => false },
},
/** @internal */
navigationAndCompletion: {
navigation: true,
completion: true,
},
/** @internal */
navigationAndVerification: {
navigation: true,
verification: true,
},
/** @internal */
withoutNavigation: {
verification: true,
completion: true,
semantic: true,
},
/** @internal */
semanticWithoutHighlight: {
semantic: { shouldHighlight: () => false },
},
/** @internal */
withoutHighlight: {
semantic: { shouldHighlight: () => false },
verification: true,
navigation: true,
completion: true,
},
/** @internal */
withoutHighlightAndCompletion: {
semantic: { shouldHighlight: () => false },
verification: true,
navigation: true,
},
/** @internal */
withoutSemantic: {
verification: true,
navigation: true,
completion: true,
},
/** @internal */
structure: {
structure: true,
},
/** @internal */
structureAndFormat: {
structure: true,
format: true,
},
/** @internal */
format: {
format: true,
},
/** @internal */
doNotReportTs2339AndTs2551: {
verification: {
// https://typescript.tv/errors/#ts2339
// https://typescript.tv/errors/#ts2551
shouldReport: (_source, code) => String(code) !== '2339' && String(code) !== '2551',
},
},
/** @internal */
doNotReportTs2353AndTs2561: {
verification: {
// https://typescript.tv/errors/#ts2353
// https://typescript.tv/errors/#ts2561
shouldReport: (_source, code) => String(code) !== '2353' && String(code) !== '2561',
},
},
/** @internal */
doNotReportTs6133: {
verification: {
// https://typescript.tv/errors/#ts6133
shouldReport: (_source, code) => String(code) !== '6133',
},
},
});
/** @deprecated use `codeFeatures.full` instead */
exports.allCodeFeatures = exports.codeFeatures.full;
function defineCodeFeatures(features) {
return features;
}
//# sourceMappingURL=codeFeatures.js.map
+11
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;
+17
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
+10
View File
@@ -0,0 +1,10 @@
import type { VueCompilerOptions } from '../types';
export declare function getLocalTypesGenerator(vueCompilerOptions: VueCompilerOptions, lang: string): {
generate: () => Generator<string, void, unknown>;
readonly PrettifyLocal: string;
readonly WithDefaults: string;
readonly WithSlots: string;
readonly PropsChildren: string;
readonly TypePropsToOption: string;
readonly OmitIndexSignature: string;
};
+109
View File
@@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLocalTypesGenerator = getLocalTypesGenerator;
const utils_1 = require("./utils");
function getLocalTypesGenerator(vueCompilerOptions, lang) {
const used = new Set();
const isTs = (0, utils_1.isTsLang)(lang);
const WithDefaults = defineHelper(`__VLS_WithDefaults`, () => isTs
? `
type __VLS_WithDefaults<P, D> = {
[K in keyof P & string]: K extends keyof D
? ${PrettifyLocal.name}<P[K] & { default: D[K] }>
: P[K]
};
`.trimStart()
: jsTypedef(`P, D`, `__VLS_WithDefaults`, `{ [K in keyof Pick<P, keyof P>]: K extends keyof D ? ${PrettifyLocal.name}<P[K] & { default: D[K] }> : P[K] }`));
const PrettifyLocal = defineHelper(`__VLS_PrettifyLocal`, () => isTs
? `type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {}${utils_1.endOfLine}`
: jsTypedef(`T`, `__VLS_PrettifyLocal`, `(T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {}`));
const WithSlots = defineHelper(`__VLS_WithSlots`, () => isTs
? `
type __VLS_WithSlots<T, S> = T & {
new(): {
$slots: S;
}
};
`.trimStart()
: jsTypedef(`T, S`, `__VLS_WithSlots`, `T & { new(): { $slots: S; } }`));
const PropsChildren = defineHelper(`__VLS_PropsChildren`, () => isTs
? `
type __VLS_PropsChildren<S> = {
[K in keyof (
boolean extends (
// @ts-ignore
JSX.ElementChildrenAttribute extends never
? true
: false
)
? never
// @ts-ignore
: JSX.ElementChildrenAttribute
)]?: S;
};
`.trimStart()
// The single-line form lets the preceding @ts-ignore cover the whole typedef,
// mirroring the inline @ts-ignore guards of the TS form.
: `// @ts-ignore${utils_1.newLine}/** @template S @typedef {{ [K in keyof (boolean extends (JSX.ElementChildrenAttribute extends never ? true : false) ? never : JSX.ElementChildrenAttribute)]?: S; }} __VLS_PropsChildren */${utils_1.newLine}`);
const TypePropsToOption = defineHelper(`__VLS_TypePropsToOption`, () => isTs
? `
type __VLS_TypePropsToOption<T> = {
[K in keyof T & string]-?: {} extends Pick<T, K>
? { type: import('${vueCompilerOptions.lib}').PropType<Required<T>[K]> }
: { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true }
};
`.trimStart()
: jsTypedef(`T`, `__VLS_TypePropsToOption`, `{ [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 } }`));
const OmitIndexSignature = defineHelper(`__VLS_OmitIndexSignature`, () => isTs
? `type __VLS_OmitIndexSignature<T> = { [K in keyof T as {} extends Record<K, unknown> ? never : K]: T[K]; }${utils_1.endOfLine}`
: jsTypedef(`T`, `__VLS_OmitIndexSignature`, `{ [K in keyof T as {} extends Record<K, unknown> ? never : K]: T[K] }`));
const helpers = {
[PrettifyLocal.name]: PrettifyLocal,
[WithDefaults.name]: WithDefaults,
[WithSlots.name]: WithSlots,
[PropsChildren.name]: PropsChildren,
[TypePropsToOption.name]: TypePropsToOption,
[OmitIndexSignature.name]: OmitIndexSignature,
};
used.clear();
return {
generate,
get PrettifyLocal() {
return PrettifyLocal.name;
},
get WithDefaults() {
return WithDefaults.name;
},
get WithSlots() {
return WithSlots.name;
},
get PropsChildren() {
return PropsChildren.name;
},
get TypePropsToOption() {
return TypePropsToOption.name;
},
get OmitIndexSignature() {
return OmitIndexSignature.name;
},
};
function* generate() {
for (const name of used) {
yield helpers[name].generate();
}
used.clear();
}
function jsTypedef(params, name, body) {
return `/**${utils_1.newLine} * @template ${params}${utils_1.newLine} * @typedef {${body}} ${name}${utils_1.newLine} */${utils_1.newLine}`;
}
function defineHelper(name, generate) {
return {
get name() {
used.add(name);
return name;
},
generate,
};
}
}
//# sourceMappingURL=localTypes.js.map
+75
View File
@@ -0,0 +1,75 @@
declare const raw: {
base: string;
export: string;
components: string;
componentsOption: string;
ctx: string;
defaultModels: string;
defaults: string;
directives: string;
directivesOption: string;
dollars: string;
emit: string;
exposed: string;
intrinsics: string;
modelEmit: string;
props: string;
propsOption: string;
self: string;
setup: string;
slots: string;
src: string;
Emit: string;
EmitProps: string;
GlobalComponents: string;
InheritedAttrs: string;
LocalComponents: string;
LocalDirectives: string;
ModelEmit: string;
ModelProps: string;
Props: string;
PublicProps: string;
RootEl: string;
Slots: string;
StyleModules: string;
StyleScopedClasses: string;
TemplateRefs: string;
asFunctionalComponent0: string;
asFunctionalComponent1: string;
asFunctionalDirective: string;
asFunctionalElement0: string;
asFunctionalElement1: string;
asFunctionalSlot: string;
directiveBindingRestFields: string;
functionalComponentArgsRest: string;
nonNull: string;
omit: string;
tryAsConstant: string;
unwrap: string;
vFor: string;
vSlot: string;
withDotValue: string;
ConstructorOverloads: string;
Elements: string;
EmitsToProps: string;
ExtractComponentContext: string;
ExtractComponentProps: string;
FunctionalComponent: string;
IsAny: string;
IsFunction: string;
NormalizeEmits: string;
OverloadUnion: string;
OverloadUnionInner: string;
PickNotAny: string;
PrettifyGlobal: string;
ResolveDirectives: string;
ResolveEmits: string;
ResolveEvent: string;
ShortEmits: string;
ShortEmitsToObject: string;
SpreadMerge: string;
UnionToIntersection: string;
WithComponent: string;
};
export declare const names: typeof raw;
export {};
+80
View File
@@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.names = void 0;
const raw = {
base: '',
export: '',
components: '',
componentsOption: '',
ctx: '',
defaultModels: '',
defaults: '',
directives: '',
directivesOption: '',
dollars: '',
emit: '',
exposed: '',
intrinsics: '',
modelEmit: '',
props: '',
propsOption: '',
self: '',
setup: '',
slots: '',
src: '',
Emit: '',
EmitProps: '',
GlobalComponents: '',
InheritedAttrs: '',
LocalComponents: '',
LocalDirectives: '',
ModelEmit: '',
ModelProps: '',
Props: '',
PublicProps: '',
RootEl: '',
Slots: '',
StyleModules: '',
StyleScopedClasses: '',
TemplateRefs: '',
// #region template helpers
asFunctionalComponent0: '',
asFunctionalComponent1: '',
asFunctionalDirective: '',
asFunctionalElement0: '',
asFunctionalElement1: '',
asFunctionalSlot: '',
directiveBindingRestFields: '',
functionalComponentArgsRest: '',
nonNull: '',
omit: '',
tryAsConstant: '',
unwrap: '',
vFor: '',
vSlot: '',
withDotValue: '',
ConstructorOverloads: '',
Elements: '',
EmitsToProps: '',
ExtractComponentContext: '',
ExtractComponentProps: '',
FunctionalComponent: '',
IsAny: '',
IsFunction: '',
NormalizeEmits: '',
OverloadUnion: '',
OverloadUnionInner: '',
PickNotAny: '',
PrettifyGlobal: '',
ResolveDirectives: '',
ResolveEmits: '',
ResolveEvent: '',
ShortEmits: '',
ShortEmitsToObject: '',
SpreadMerge: '',
UnionToIntersection: '',
WithComponent: '',
// #endregion
};
exports.names = Object.fromEntries(Object.keys(raw).map(key => [key, `__VLS_${key}`]));
//# sourceMappingURL=names.js.map
+5
View File
@@ -0,0 +1,5 @@
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, IRScriptSetup } from '../../types';
import type { ScriptCodegenContext } from './context';
import type { ScriptCodegenOptions } from './index';
export declare function generateComponent(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: IRScriptSetup, scriptSetupRanges: ScriptSetupRanges): Generator<Code>;
+112
View File
@@ -0,0 +1,112 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateComponent = generateComponent;
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const merge_1 = require("../utils/merge");
function* generateComponent(options, ctx, scriptSetup, scriptSetupRanges) {
yield `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${utils_1.newLine}`;
if (scriptSetupRanges.defineExpose) {
yield `setup: () => ${names_1.names.exposed},${utils_1.newLine}`;
}
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.templateAndStyleTypes.has(names_1.names.TemplateRefs)) {
yield `__typeRefs: ${(0, utils_1.asType)(names_1.names.TemplateRefs, options.scriptLang)},${utils_1.newLine}`;
}
if (options.vueCompilerOptions.target >= 3.5
&& options.vueCompilerOptions.inferComponentDollarEl
&& options.templateAndStyleTypes.has(names_1.names.RootEl)) {
yield `__typeEl: ${(0, utils_1.asType)(names_1.names.RootEl, options.scriptLang)},${utils_1.newLine}`;
}
yield `})`;
}
function* generateEmitsOption(options, scriptSetupRanges) {
const typeCodes = options.vueCompilerOptions.target >= 3.5 && !scriptSetupRanges.defineEmits?.hasUnionTypeArg
? [...generateTypeEmitsOption(scriptSetupRanges)]
: [];
const runtimeCodes = !typeCodes.length
? [...generateRuntimeEmitsOption(options, scriptSetupRanges)]
: [];
if (typeCodes.length) {
yield `__typeEmits: ${(0, utils_1.asType)(typeCodes.join(` & `), options.scriptLang)},${utils_1.newLine}`;
}
else if (runtimeCodes.length) {
yield `emits: `;
yield* (0, merge_1.generateSpreadMerge)(...runtimeCodes);
yield `,${utils_1.newLine}`;
}
}
function* generateTypeEmitsOption(scriptSetupRanges) {
if (scriptSetupRanges.defineModel.length) {
yield names_1.names.ModelEmit;
}
if (scriptSetupRanges.defineEmits?.typeArg) {
yield names_1.names.Emit;
}
}
function* generateRuntimeEmitsOption(options, scriptSetupRanges) {
if (scriptSetupRanges.defineModel.length) {
yield (0, utils_1.asType)(`${names_1.names.NormalizeEmits}<typeof ${names_1.names.modelEmit}>`, options.scriptLang);
}
if (scriptSetupRanges.defineEmits) {
yield (0, utils_1.asType)(`${names_1.names.NormalizeEmits}<typeof ${scriptSetupRanges.defineEmits.name ?? names_1.names.emit}>`, options.scriptLang);
}
}
function* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, hasEmitsOption) {
const typeCodes = options.vueCompilerOptions.target >= 3.5 && !scriptSetupRanges.defineProps?.arg
? [...generateTypePropsOption(options, ctx, hasEmitsOption)]
: [];
const runtimeCodes = scriptSetupRanges.withDefaults || !typeCodes.length
? [...generateRuntimePropsOption(options, ctx, scriptSetup, scriptSetupRanges, hasEmitsOption)]
: [];
if (typeCodes.length) {
if (options.vueCompilerOptions.target >= 3.6 && scriptSetupRanges.withDefaults?.arg) {
yield `__defaults: ${names_1.names.defaults},${utils_1.newLine}`;
}
yield `__typeProps: `;
yield* (0, merge_1.generateSpreadMerge)(...typeCodes);
yield `,${utils_1.newLine}`;
}
if (runtimeCodes.length) {
yield `props: `;
yield* (0, merge_1.generateSpreadMerge)(...runtimeCodes);
yield `,${utils_1.newLine}`;
}
}
function* generateTypePropsOption(options, ctx, hasEmitsOption) {
if (options.templateAndStyleTypes.has(names_1.names.InheritedAttrs)) {
const attrsType = hasEmitsOption
? `Omit<${names_1.names.InheritedAttrs}, keyof ${names_1.names.EmitProps}>`
: names_1.names.InheritedAttrs;
yield (0, utils_1.asType)(attrsType, options.scriptLang);
}
if (ctx.generatedTypes.has(names_1.names.PublicProps)) {
yield (0, utils_1.asType)(names_1.names.PublicProps, options.scriptLang);
}
}
function* generateRuntimePropsOption(options, ctx, scriptSetup, scriptSetupRanges, hasEmitsOption) {
if (options.templateAndStyleTypes.has(names_1.names.InheritedAttrs)) {
const attrsType = hasEmitsOption
? `Omit<${names_1.names.InheritedAttrs}, keyof ${names_1.names.EmitProps}>`
: names_1.names.InheritedAttrs;
const propsType = `${ctx.localTypes.TypePropsToOption}<${names_1.names.PickNotAny}<${ctx.localTypes.OmitIndexSignature}<${attrsType}>, {}>>`;
yield (0, utils_1.asType)(propsType, options.scriptLang);
}
if (ctx.generatedTypes.has(names_1.names.PublicProps) && options.vueCompilerOptions.target < 3.6) {
let propsType = `${ctx.localTypes.TypePropsToOption}<${names_1.names.PublicProps}>`;
if (scriptSetupRanges.withDefaults?.arg) {
propsType = `${ctx.localTypes.WithDefaults}<${propsType}, typeof ${names_1.names.defaults}>`;
}
yield (0, utils_1.asType)(propsType, options.scriptLang);
}
if (scriptSetupRanges.defineProps?.arg) {
const { arg } = scriptSetupRanges.defineProps;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.navigation);
}
}
//# sourceMappingURL=component.js.map
+16
View File
@@ -0,0 +1,16 @@
import type { InlayHintInfo } from '../inlayHints';
import type { ScriptCodegenOptions } from './index';
export type ScriptCodegenContext = ReturnType<typeof createScriptCodegenContext>;
export declare function createScriptCodegenContext(options: ScriptCodegenOptions): {
generatedTypes: Set<string>;
localTypes: {
generate: () => Generator<string, void, unknown>;
readonly PrettifyLocal: string;
readonly WithDefaults: string;
readonly WithSlots: string;
readonly PropsChildren: string;
readonly TypePropsToOption: string;
readonly OmitIndexSignature: string;
};
inlayHints: InlayHintInfo[];
};
+14
View File
@@ -0,0 +1,14 @@
"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, options.scriptLang);
const inlayHints = [];
return {
generatedTypes: new Set(),
localTypes,
inlayHints,
};
}
//# sourceMappingURL=context.js.map
+33
View File
@@ -0,0 +1,33 @@
import type { ScriptRanges } from '../../parsers/scriptRanges';
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, IRScript, IRScriptSetup, VueCompilerOptions } from '../../types';
export interface ScriptCodegenOptions {
vueCompilerOptions: VueCompilerOptions;
script: IRScript | undefined;
scriptSetup: IRScriptSetup | undefined;
fileName: string;
scriptLang: string;
scriptRanges: ScriptRanges | undefined;
scriptSetupRanges: ScriptSetupRanges | undefined;
templateAndStyleTypes: Set<string>;
templateAndStyleCodes: Code[];
setupBindings: Set<string>;
localComponents: Set<string>;
localDirectives: Set<string>;
dotValueBindings: Set<string>;
}
export { generate as generateScript };
declare function generate(options: ScriptCodegenOptions): {
generatedTypes: Set<string>;
localTypes: {
generate: () => Generator<string, void, unknown>;
readonly PrettifyLocal: string;
readonly WithDefaults: string;
readonly WithSlots: string;
readonly PropsChildren: string;
readonly TypePropsToOption: string;
readonly OmitIndexSignature: string;
};
inlayHints: import("../inlayHints").InlayHintInfo[];
codes: Code[];
};
+207
View File
@@ -0,0 +1,207 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateScript = generate;
const path = __importStar(require("path-browserify"));
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const context_1 = require("./context");
const scriptSetup_1 = require("./scriptSetup");
const template_1 = require("./template");
function generate(options) {
const ctx = (0, context_1.createScriptCodegenContext)(options);
const codeGenerator = generateWorker(options, ctx);
return { ...ctx, codes: [...codeGenerator] };
}
function* generateWorker(options, ctx) {
const { script, scriptRanges, scriptSetup, scriptSetupRanges, vueCompilerOptions, fileName } = options;
const exportExpression = (0, utils_1.asType)(`typeof ${names_1.names.export}`, options.scriptLang);
yield* generateGlobalTypesReference(vueCompilerOptions, fileName);
// <script src="">
if (typeof script?.src === 'object') {
let src = script.src.text;
if (src.endsWith('.ts') && !src.endsWith('.d.ts')) {
src = src.slice(0, -'.ts'.length) + '.js';
}
else if (src.endsWith('.tsx')) {
src = src.slice(0, -'.tsx'.length) + '.jsx';
}
yield `import ${names_1.names.src} from `;
const boundary = yield* boundary_1.Boundary.start('main', script.src.offset, script.src.offset + script.src.text.length, {
...codeFeatures_1.codeFeatures.all,
...src !== script.src.text ? codeFeatures_1.codeFeatures.navigationWithoutRename : {},
});
yield `'`;
yield [src.slice(0, script.src.text.length), 'main', script.src.offset, boundary.features];
yield src.slice(script.src.text.length);
yield `'`;
yield boundary.end();
yield utils_1.endOfLine;
yield `export default ${names_1.names.src}${utils_1.endOfLine}`;
yield* (0, template_1.generateTemplate)(options, names_1.names.src);
}
// <script> + <script setup>
else if (script && scriptRanges && scriptSetup && scriptSetupRanges) {
yield* (0, scriptSetup_1.generateScriptSetupImports)(scriptSetup, scriptSetupRanges);
// <script>
let selfType;
const { exportDefault } = scriptRanges;
if (exportDefault) {
yield* generateScriptWithExportDefault(ctx, script, scriptRanges, exportDefault, vueCompilerOptions, selfType = names_1.names.self, exportExpression);
}
else {
yield* (0, utils_1.generateSfcBlockSection)(script, 0, script.content.length, codeFeatures_1.codeFeatures.all);
yield `export default ${exportExpression}${utils_1.endOfLine}`;
}
// <script setup>
yield* generateExportDeclareEqual(scriptSetup, names_1.names.export);
if (scriptSetup.generic) {
yield* (0, scriptSetup_1.generateGeneric)(options, ctx, scriptSetup, scriptSetupRanges, scriptSetup.generic, (0, scriptSetup_1.generateSetupFunction)(options, ctx, scriptSetup, scriptSetupRanges, (0, template_1.generateTemplate)(options, selfType)));
}
else {
yield `await (async () => {${utils_1.newLine}`;
yield* (0, scriptSetup_1.generateSetupFunction)(options, ctx, scriptSetup, scriptSetupRanges, (0, template_1.generateTemplate)(options, selfType), [`return `]);
yield `})()${utils_1.endOfLine}`;
}
}
// only <script setup>
else if (scriptSetup && scriptSetupRanges) {
yield* (0, scriptSetup_1.generateScriptSetupImports)(scriptSetup, scriptSetupRanges);
if (scriptSetup.generic) {
yield* generateExportDeclareEqual(scriptSetup, names_1.names.export);
yield* (0, scriptSetup_1.generateGeneric)(options, ctx, scriptSetup, scriptSetupRanges, scriptSetup.generic, (0, scriptSetup_1.generateSetupFunction)(options, ctx, scriptSetup, scriptSetupRanges, (0, template_1.generateTemplate)(options)));
}
else {
// no script block, generate script setup code at root
yield* (0, scriptSetup_1.generateSetupFunction)(options, ctx, scriptSetup, scriptSetupRanges, (0, template_1.generateTemplate)(options), generateExportDeclareEqual(scriptSetup, names_1.names.export));
}
yield `export default ${exportExpression}${utils_1.endOfLine}`;
}
// only <script>
else if (script && scriptRanges) {
const { exportDefault } = scriptRanges;
if (exportDefault) {
yield* generateScriptWithExportDefault(ctx, script, scriptRanges, exportDefault, vueCompilerOptions, names_1.names.export, exportExpression, (0, template_1.generateTemplate)(options, names_1.names.export));
}
else {
yield* (0, utils_1.generateSfcBlockSection)(script, 0, script.content.length, codeFeatures_1.codeFeatures.all);
yield* generateExportDeclareEqual(script, names_1.names.export);
yield `(await import('${vueCompilerOptions.lib}')).defineComponent({})${utils_1.endOfLine}`;
yield* (0, template_1.generateTemplate)(options, names_1.names.export);
yield `export default ${exportExpression}${utils_1.endOfLine}`;
}
}
yield* ctx.localTypes.generate();
// The <script src> branch never embeds the script setup content, so no
// macro references can appear and the import would be unused.
if (scriptSetup && scriptSetupRanges && typeof script?.src !== 'object') {
yield* (0, scriptSetup_1.generateMacros)(options);
}
}
function* generateScriptWithExportDefault(ctx, script, scriptRanges, exportDefault, vueCompilerOptions, varName, exportExpression, templateGenerator) {
const componentOptions = scriptRanges.exportDefault?.options;
const { expression, isObjectLiteral } = componentOptions ?? exportDefault;
let wrapLeft;
let wrapRight;
if (isObjectLiteral
&& vueCompilerOptions.optionsWrapper.length) {
[wrapLeft, wrapRight] = vueCompilerOptions.optionsWrapper;
ctx.inlayHints.push({
blockName: script.name,
offset: 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: script.name,
offset: expression.end,
setting: 'vue.inlayHints.optionsWrapper',
label: wrapRight || '[Missing optionsWrapper[1]]',
});
}
yield* (0, utils_1.generateSfcBlockSection)(script, 0, expression.start, codeFeatures_1.codeFeatures.all);
yield exportExpression;
yield* (0, utils_1.generateSfcBlockSection)(script, expression.end, exportDefault.end, codeFeatures_1.codeFeatures.all);
yield utils_1.endOfLine;
if (templateGenerator) {
yield* templateGenerator;
}
yield* generateExportDeclareEqual(script, varName);
if (wrapLeft && wrapRight) {
yield wrapLeft;
yield* (0, utils_1.generateSfcBlockSection)(script, expression.start, expression.end, codeFeatures_1.codeFeatures.all);
yield wrapRight;
}
else {
yield* (0, utils_1.generateSfcBlockSection)(script, expression.start, expression.end, codeFeatures_1.codeFeatures.all);
}
yield utils_1.endOfLine;
yield* (0, utils_1.generateSfcBlockSection)(script, exportDefault.end, script.content.length, codeFeatures_1.codeFeatures.all);
}
function* generateGlobalTypesReference({ typesRoot, lib, target, checkUnknownProps }, fileName) {
let typesPath;
if (path.isAbsolute(typesRoot)) {
let relativePath = path.relative(path.dirname(fileName), typesRoot);
if (relativePath !== typesRoot
&& !relativePath.startsWith('./')
&& !relativePath.startsWith('../')) {
relativePath = './' + relativePath;
}
typesPath = relativePath;
}
else {
typesPath = typesRoot;
}
yield `/// <reference types=${JSON.stringify(typesPath + '/template-helpers.d.ts')} />${utils_1.newLine}`;
if (!checkUnknownProps) {
yield `/// <reference types=${JSON.stringify(typesPath + '/props-fallback.d.ts')} />${utils_1.newLine}`;
}
if (lib === 'vue' && target < 3.5) {
yield `/// <reference types=${JSON.stringify(typesPath + '/vue-3.4-shims.d.ts')} />${utils_1.newLine}`;
}
}
function* generateExportDeclareEqual(block, name) {
yield `const `;
const boundary = yield* boundary_1.Boundary.start(block.name, 0, block.content.length, codeFeatures_1.codeFeatures.doNotReportTs6133);
yield name;
yield boundary.end();
yield ` = `;
}
//# sourceMappingURL=index.js.map
+8
View File
@@ -0,0 +1,8 @@
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, IRScriptSetup } from '../../types';
import type { ScriptCodegenContext } from './context';
import type { ScriptCodegenOptions } from './index';
export declare function generateScriptSetupImports(scriptSetup: IRScriptSetup, scriptSetupRanges: ScriptSetupRanges): Generator<Code>;
export declare function generateGeneric(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: IRScriptSetup, scriptSetupRanges: ScriptSetupRanges, generic: NonNullable<IRScriptSetup['generic']>, body: Iterable<Code>): Generator<Code>;
export declare function generateSetupFunction(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: IRScriptSetup, scriptSetupRanges: ScriptSetupRanges, body: Iterable<Code>, output?: Iterable<Code>): Generator<Code>;
export declare function generateMacros(options: ScriptCodegenOptions): Generator<Code>;
+498
View File
@@ -0,0 +1,498 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateScriptSetupImports = generateScriptSetupImports;
exports.generateGeneric = generateGeneric;
exports.generateSetupFunction = generateSetupFunction;
exports.generateMacros = generateMacros;
const shared_1 = require("@vue/shared");
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const camelized_1 = require("../utils/camelized");
const transform_1 = require("../utils/transform");
const component_1 = require("./component");
function* generateScriptSetupImports(scriptSetup, scriptSetupRanges) {
yield [
scriptSetup.content.slice(0, Math.max(scriptSetupRanges.importSectionEndOffset, scriptSetupRanges.leadingCommentEndOffset)),
'scriptSetup',
0,
codeFeatures_1.codeFeatures.all,
];
}
function* generateGeneric(options, ctx, scriptSetup, scriptSetupRanges, generic, body) {
yield `(`;
if (typeof generic === 'object') {
const boundary = yield* boundary_1.Boundary.start('main', generic.offset, generic.offset + generic.text.length, codeFeatures_1.codeFeatures.verification);
yield `<`;
yield [generic.text, 'main', generic.offset, codeFeatures_1.codeFeatures.all];
if (!generic.text.trimEnd().endsWith(`,`)) {
yield `,`;
}
yield `>`;
yield boundary.end();
}
yield `(${utils_1.newLine}`
+ ` ${names_1.names.props}: NonNullable<Awaited<typeof ${names_1.names.setup}>>['props'],${utils_1.newLine}`
+ ` ${names_1.names.ctx}?: ${ctx.localTypes.PrettifyLocal}<Pick<NonNullable<Awaited<typeof ${names_1.names.setup}>>, 'attrs' | 'emit' | 'slots'>>,${utils_1.newLine}`
+ ` ${names_1.names.exposed}?: NonNullable<Awaited<typeof ${names_1.names.setup}>>['expose'],${utils_1.newLine}`
+ ` ${names_1.names.setup} = (async () => {${utils_1.newLine}`;
yield* body;
const propTypes = [];
const emitTypes = [];
const { vueCompilerOptions } = options;
if (ctx.generatedTypes.has(names_1.names.PublicProps)) {
propTypes.push(names_1.names.PublicProps);
}
if (scriptSetupRanges.defineProps?.arg) {
yield `const ${names_1.names.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('${vueCompilerOptions.lib}').${vueCompilerOptions.target >= 3.3 ? `ExtractPublicPropTypes` : `ExtractPropTypes`}<typeof ${names_1.names.propsOption}>`);
}
if (scriptSetupRanges.defineEmits || scriptSetupRanges.defineModel.length) {
propTypes.push(names_1.names.EmitProps);
}
if (options.templateAndStyleTypes.has(names_1.names.InheritedAttrs)) {
propTypes.push(names_1.names.InheritedAttrs);
}
if (scriptSetupRanges.defineEmits) {
emitTypes.push(`typeof ${scriptSetupRanges.defineEmits.name ?? names_1.names.emit}`);
}
if (scriptSetupRanges.defineModel.length) {
emitTypes.push(`typeof ${names_1.names.modelEmit}`);
}
yield `return {} as {${utils_1.newLine}`;
yield ` props: `;
yield vueCompilerOptions.target >= 3.4
? `import('${vueCompilerOptions.lib}').PublicProps`
: vueCompilerOptions.target >= 3
? `import('${vueCompilerOptions.lib}').VNodeProps`
+ ` & import('${vueCompilerOptions.lib}').AllowedComponentProps`
+ ` & import('${vueCompilerOptions.lib}').ComponentCustomProps`
: `globalThis.JSX.IntrinsicAttributes`;
if (propTypes.length) {
yield ` & ${ctx.localTypes.PrettifyLocal}<${propTypes.join(` & `)}>`;
}
yield ` & (typeof globalThis extends { __VLS_PROPS_FALLBACK: infer P } ? P : {})${utils_1.endOfLine}`;
yield ` expose: (exposed: `;
yield scriptSetupRanges.defineExpose
? `import('${vueCompilerOptions.lib}').ShallowUnwrapRef<typeof ${names_1.names.exposed}>`
: `{}`;
if (options.vueCompilerOptions.inferComponentDollarRefs
&& options.templateAndStyleTypes.has(names_1.names.TemplateRefs)) {
yield ` & { $refs: ${names_1.names.TemplateRefs}; }`;
}
if (options.vueCompilerOptions.inferComponentDollarEl
&& options.templateAndStyleTypes.has(names_1.names.RootEl)) {
yield ` & { $el: ${names_1.names.RootEl}; }`;
}
yield `) => void${utils_1.endOfLine}`;
yield ` attrs: any${utils_1.endOfLine}`;
yield ` slots: ${hasSlotsType(options) ? names_1.names.Slots : `{}`}${utils_1.endOfLine}`;
yield ` emit: ${emitTypes.length ? emitTypes.join(` & `) : `{}`}${utils_1.endOfLine}`;
yield `}${utils_1.endOfLine}`;
yield `})(),${utils_1.newLine}`; // __VLS_setup = (async () => {
yield `) => ({} as import('${vueCompilerOptions.lib}').VNode & { __ctx?: NonNullable<Awaited<typeof ${names_1.names.setup}>> }))${utils_1.endOfLine}`;
}
function* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, body, output) {
const transforms = [];
for (const { defaultPropsArg } of scriptSetupRanges.defineModel) {
if (defaultPropsArg) {
transforms.push({
range: [defaultPropsArg.end, defaultPropsArg.end],
*generate() {
yield `: `;
if (scriptSetupRanges.defineProps?.typeArg) {
yield names_1.names.Props;
}
else {
// FIXME: (props: typeof props) => ... would cause TS2502
yield `typeof `;
yield scriptSetupRanges.defineProps?.name ?? names_1.names.props;
}
},
});
}
}
if (scriptSetupRanges.defineProps) {
const { name, statement, callExp, typeArg } = scriptSetupRanges.defineProps;
const _callExp = scriptSetupRanges.withDefaults?.callExp ?? callExp;
transforms.push(...generateDefineWithTypeTransforms(scriptSetup, statement, _callExp, typeArg, name, names_1.names.props, names_1.names.Props));
}
if (scriptSetupRanges.defineEmits) {
const { name, statement, callExp, typeArg } = scriptSetupRanges.defineEmits;
transforms.push(...generateDefineWithTypeTransforms(scriptSetup, statement, callExp, typeArg, name, names_1.names.emit, names_1.names.Emit));
}
if (scriptSetupRanges.defineSlots) {
const { name, statement, callExp, typeArg } = scriptSetupRanges.defineSlots;
transforms.push(...generateDefineWithTypeTransforms(scriptSetup, statement, callExp, typeArg, name, names_1.names.slots, names_1.names.Slots));
if (!name) {
transforms.push((0, transform_1.insert)(statement.end, function* () {
yield `${utils_1.newLine}void ${names_1.names.slots}${utils_1.endOfLine}`;
}));
}
}
if (scriptSetupRanges.defineExpose) {
const { callExp, arg, typeArg } = scriptSetupRanges.defineExpose;
if (typeArg) {
transforms.push((0, transform_1.insert)(callExp.start, function* () {
yield `let ${names_1.names.exposed}!: `;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, typeArg.start, typeArg.end, codeFeatures_1.codeFeatures.all);
yield utils_1.endOfLine;
}), (0, transform_1.replace)(typeArg.start, typeArg.end, function* () {
yield `typeof ${names_1.names.exposed}`;
}));
}
else if (arg) {
transforms.push((0, transform_1.insert)(callExp.start, function* () {
yield `const ${names_1.names.exposed} = `;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.all);
yield utils_1.endOfLine;
}), (0, transform_1.replace)(arg.start, arg.end, function* () {
yield names_1.names.exposed;
}));
}
else {
transforms.push((0, transform_1.insert)(callExp.start, function* () {
yield `const ${names_1.names.exposed} = {}${utils_1.endOfLine}`;
}));
}
}
if (options.vueCompilerOptions.inferTemplateDollarAttrs) {
for (const { callExp } of scriptSetupRanges.useAttrs) {
const type = `typeof ${names_1.names.dollars}.$attrs`;
transforms.push((0, transform_1.insert)(callExp.start, function* () {
yield (0, utils_1.isTsLang)(options.scriptLang) ? `(` : `/** @type {${type}} */ (`;
}), (0, transform_1.insert)(callExp.end, function* () {
yield (0, utils_1.isTsLang)(options.scriptLang) ? ` as ${type})` : `)`;
}));
}
}
for (const { callExp, exp, arg } of scriptSetupRanges.useCssModule) {
const type = options.templateAndStyleTypes.has(names_1.names.StyleModules)
? names_1.names.StyleModules
: `{}`;
if (arg) {
transforms.push((0, transform_1.insert)(callExp.start, function* () {
if ((0, utils_1.isTsLang)(options.scriptLang)) {
yield `(`;
}
else {
yield `/** @type {Omit<${type}, '$style'>[`;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.withoutSemantic);
yield `]} */ (`;
}
}), (0, transform_1.insert)(callExp.end, function* () {
if ((0, utils_1.isTsLang)(options.scriptLang)) {
yield ` as Omit<${type}, '$style'>[`;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.withoutSemantic);
yield `])`;
}
else {
yield `)`;
}
}), (0, transform_1.replace)(arg.start, arg.end, function* () {
yield (0, utils_1.asType)('any', options.scriptLang);
}));
}
else {
transforms.push((0, transform_1.insert)(callExp.start, function* () {
yield (0, utils_1.isTsLang)(options.scriptLang) ? `(` : `/** @type {${type}['$style']} */ (`;
}), (0, transform_1.insert)(callExp.end, function* () {
if ((0, utils_1.isTsLang)(options.scriptLang)) {
yield ` as ${type}[`;
const boundary = yield* boundary_1.Boundary.start(scriptSetup.name, exp.start, exp.end, codeFeatures_1.codeFeatures.verification);
yield `'$style'`;
yield boundary.end();
yield `])`;
}
else {
yield `)`;
}
}));
}
}
if (options.vueCompilerOptions.inferTemplateDollarSlots) {
for (const { callExp } of scriptSetupRanges.useSlots) {
const type = `typeof ${names_1.names.dollars}.$slots`;
transforms.push((0, transform_1.insert)(callExp.start, function* () {
yield (0, utils_1.isTsLang)(options.scriptLang) ? `(` : `/** @type {${type}} */ (`;
}), (0, transform_1.insert)(callExp.end, function* () {
yield (0, utils_1.isTsLang)(options.scriptLang) ? ` as ${type})` : `)`;
}));
}
}
for (const { callExp, arg } of scriptSetupRanges.useTemplateRef) {
transforms.push((0, transform_1.insert)(callExp.start, function* () {
if ((0, utils_1.isTsLang)(options.scriptLang)) {
yield `(`;
return;
}
yield `/** @type {Readonly<import('${options.vueCompilerOptions.lib}').ShallowRef<`;
if (arg) {
yield names_1.names.TemplateRefs;
yield `[`;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.withoutSemantic);
yield `]`;
}
else {
yield `unknown`;
}
yield ` | null>>} */ (`;
}), (0, transform_1.insert)(callExp.end, function* () {
if ((0, utils_1.isTsLang)(options.scriptLang)) {
yield ` as Readonly<import('${options.vueCompilerOptions.lib}').ShallowRef<`;
if (arg) {
yield names_1.names.TemplateRefs;
yield `[`;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, codeFeatures_1.codeFeatures.withoutSemantic);
yield `]`;
}
else {
yield `unknown`;
}
yield ` | null>>)`;
}
else {
yield `)`;
}
}));
if (arg) {
transforms.push((0, transform_1.replace)(arg.start, arg.end, function* () {
yield (0, utils_1.asType)('any', options.scriptLang);
}));
}
}
yield* (0, transform_1.generateCodeWithTransforms)(Math.max(scriptSetupRanges.importSectionEndOffset, scriptSetupRanges.leadingCommentEndOffset), scriptSetup.content.length, transforms, (start, end) => (0, utils_1.generateSfcBlockSection)(scriptSetup, start, end, codeFeatures_1.codeFeatures.all));
yield* generateModels(options, scriptSetup, scriptSetupRanges);
yield* generatePublicProps(options, ctx, scriptSetup, scriptSetupRanges);
yield* body;
if (output) {
if (hasSlotsType(options)) {
yield `const ${names_1.names.base} = `;
yield* (0, component_1.generateComponent)(options, ctx, scriptSetup, scriptSetupRanges);
yield utils_1.endOfLine;
yield* output;
yield (0, utils_1.asType)(`${ctx.localTypes.WithSlots}<typeof ${names_1.names.base}, ${names_1.names.Slots}>`, options.scriptLang);
yield utils_1.endOfLine;
}
else {
yield* output;
yield* (0, component_1.generateComponent)(options, ctx, scriptSetup, scriptSetupRanges);
yield utils_1.endOfLine;
}
}
}
// An `import` (rather than `declare const`) keeps the macros resolvable in JS
// virtual files, where type-only declarations are syntax errors. Imports hoist,
// so this can be emitted after all user content: leading directives stay ahead
// of any statement, and the import-section/content junction stays intact.
function* generateMacros(options) {
if (options.vueCompilerOptions.target >= 3.3) {
const scriptSetup = options.scriptSetup;
const scriptSetupRanges = options.scriptSetupRanges;
if (!scriptSetup || !scriptSetupRanges) {
return;
}
const usedMacros = [];
const add = (canonical, exp) => {
if (exp) {
usedMacros.push({ canonical, alias: getRangeText(scriptSetup, exp) });
}
};
add('defineProps', scriptSetupRanges.defineProps?.exp);
add('defineEmits', scriptSetupRanges.defineEmits?.exp);
add('defineSlots', scriptSetupRanges.defineSlots?.exp);
add('defineExpose', scriptSetupRanges.defineExpose?.exp);
add('withDefaults', scriptSetupRanges.withDefaults?.exp);
if (scriptSetupRanges.defineModel.length) {
usedMacros.push({ canonical: 'defineModel', alias: 'defineModel' });
}
if (scriptSetupRanges.defineOptions) {
usedMacros.push({ canonical: 'defineOptions', alias: 'defineOptions' });
}
const toImport = usedMacros.filter(({ alias }) => !options.setupBindings.has(alias));
if (toImport.length) {
yield `import { `;
for (const { canonical, alias } of toImport) {
yield alias === canonical ? `${canonical}, ` : `${canonical} as ${alias}, `;
}
yield `} from '${options.vueCompilerOptions.lib}'${utils_1.endOfLine}`;
}
}
}
function* generateDefineWithTypeTransforms(scriptSetup, statement, callExp, typeArg, name, defaultName, typeName) {
if (typeArg) {
yield (0, transform_1.insert)(statement.start, function* () {
yield `type ${typeName} = `;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, typeArg.start, typeArg.end, codeFeatures_1.codeFeatures.all);
yield utils_1.endOfLine;
});
yield (0, transform_1.replace)(typeArg.start, typeArg.end, function* () {
yield typeName;
});
}
if (!name) {
if (statement.start === callExp.start && statement.end === callExp.end) {
yield (0, transform_1.insert)(callExp.start, function* () {
yield `const ${defaultName} = `;
});
}
else if (typeArg) {
yield (0, transform_1.replace)(statement.start, typeArg.start, function* () {
yield `const ${defaultName} = `;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, callExp.start, typeArg.start, codeFeatures_1.codeFeatures.all);
});
yield (0, transform_1.replace)(typeArg.end, callExp.end, function* () {
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, typeArg.end, callExp.end, codeFeatures_1.codeFeatures.all);
yield utils_1.endOfLine;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, statement.start, callExp.start, codeFeatures_1.codeFeatures.all);
yield defaultName;
});
}
else {
yield (0, transform_1.replace)(statement.start, callExp.end, function* () {
yield `const ${defaultName} = `;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, callExp.start, callExp.end, codeFeatures_1.codeFeatures.all);
yield utils_1.endOfLine;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, statement.start, callExp.start, codeFeatures_1.codeFeatures.all);
yield defaultName;
});
}
}
else if (!utils_1.identifierRE.test(name)) {
yield (0, transform_1.replace)(statement.start, callExp.start, function* () {
yield `const ${defaultName} = `;
});
yield (0, transform_1.insert)(statement.end, function* () {
yield utils_1.endOfLine;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, statement.start, callExp.start, codeFeatures_1.codeFeatures.all);
yield defaultName;
});
}
}
function* generatePublicProps(options, ctx, scriptSetup, scriptSetupRanges) {
if (scriptSetupRanges.defineProps?.typeArg && scriptSetupRanges.withDefaults?.arg) {
yield `const ${names_1.names.defaults} = `;
yield* (0, utils_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.withDefaults.arg.start, scriptSetupRanges.withDefaults.arg.end, codeFeatures_1.codeFeatures.navigation);
yield utils_1.endOfLine;
yield `void ${names_1.names.defaults}${utils_1.endOfLine}`;
}
const propTypes = [];
if (options.vueCompilerOptions.jsxSlots && hasSlotsType(options)) {
propTypes.push(`${ctx.localTypes.PropsChildren}<${names_1.names.Slots}>`);
}
if (scriptSetupRanges.defineProps?.typeArg) {
propTypes.push(names_1.names.Props);
}
if (scriptSetupRanges.defineModel.length) {
propTypes.push(names_1.names.ModelProps);
}
const target = options.vueCompilerOptions.target;
const used = !!scriptSetup.generic
|| target < 3.6
|| (target >= 3.5 && !scriptSetupRanges.defineProps?.arg);
if (propTypes.length && used) {
yield* (0, utils_1.generateTypeAlias)(names_1.names.PublicProps, options.scriptLang, function* () {
yield propTypes.join(` & `);
});
ctx.generatedTypes.add(names_1.names.PublicProps);
}
}
function hasSlotsType(options) {
return !!(options.scriptSetupRanges?.defineSlots
|| options.templateAndStyleTypes.has(names_1.names.Slots));
}
function* generateModels(options, 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 ${names_1.names.defaultModels}['${propName}']`;
}
else {
modelType = `any`;
}
if (defineModel.defaultValue) {
defaultCodes.push(`'${propName}': ${getRangeText(scriptSetup, defineModel.defaultValue)},${utils_1.newLine}`);
}
propCodes.push(generateModelProp(options, scriptSetup, defineModel, propName, modelType));
emitCodes.push(generateModelEmit(defineModel, propName, modelType));
}
if (defaultCodes.length) {
yield `const ${names_1.names.defaultModels} = {${utils_1.newLine}`;
yield* defaultCodes;
yield `}${utils_1.endOfLine}`;
yield `void ${names_1.names.defaultModels}${utils_1.endOfLine}`;
}
yield* (0, utils_1.generateTypeAlias)(names_1.names.ModelProps, options.scriptLang, function* () {
yield `{${utils_1.newLine}`;
for (const codes of propCodes) {
yield* codes;
}
yield `}`;
});
yield* (0, utils_1.generateTypeAlias)(names_1.names.ModelEmit, options.scriptLang, function* () {
yield `{${utils_1.newLine}`;
for (const codes of emitCodes) {
yield* codes;
}
yield `}`;
});
// avoid `defineModel<...>()` to prevent JS AST issues
yield* (0, utils_1.generateTypedVar)('let', names_1.names.modelEmit, options.scriptLang, function* () {
yield `${names_1.names.ShortEmits}<${names_1.names.ModelEmit}>`;
});
}
function* generateModelProp(options, scriptSetup, defineModel, propName, modelType) {
// In JS the alias body lives inside a JSDoc comment; user comments could
// contain `*/` and terminate it early, so they are dropped.
if (defineModel.comments && (0, utils_1.isTsLang)(options.scriptLang)) {
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
+3
View File
@@ -0,0 +1,3 @@
import type { Code } from '../../types';
import type { ScriptCodegenOptions } from './index';
export declare function generateTemplate(options: ScriptCodegenOptions, selfType?: string): Generator<Code>;
+117
View File
@@ -0,0 +1,117 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplate = generateTemplate;
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const merge_1 = require("../utils/merge");
function* generateTemplate(options, selfType) {
yield* generateTemplateCtx(options, selfType);
yield* generateTemplateComponents(options);
yield* generateTemplateDirectives(options);
yield `void ${names_1.names.ctx}, ${names_1.names.components}, ${names_1.names.intrinsics}, ${names_1.names.directives}${utils_1.endOfLine}`;
for (const name of options.dotValueBindings) {
yield `// @ts-ignore${utils_1.newLine}`;
yield `${names_1.names.withDotValue}(${name}, ${(0, utils_1.getRefBrandArgument)(options.vueCompilerOptions, options.scriptLang)})${utils_1.endOfLine}`;
}
if (options.templateAndStyleCodes.length) {
yield* options.templateAndStyleCodes;
}
}
function* generateTemplateCtx({ vueCompilerOptions, templateAndStyleTypes, scriptSetupRanges, fileName, scriptLang }, selfType) {
const exps = [];
const emitTypes = [];
const propTypes = [];
if (vueCompilerOptions.petiteVueExtensions.some(ext => fileName.endsWith(ext))) {
exps.push(`globalThis`);
}
if (selfType) {
exps.push((0, utils_1.asType)(`InstanceType<${names_1.names.PickNotAny}<typeof ${selfType}, new () => {}>>`, scriptLang));
}
else {
exps.push((0, utils_1.asType)(`import('${vueCompilerOptions.lib}').ComponentPublicInstance`, scriptLang));
}
if (templateAndStyleTypes.has(names_1.names.StyleModules)) {
exps.push((0, utils_1.asType)(names_1.names.StyleModules, scriptLang));
}
if (scriptSetupRanges?.defineEmits) {
emitTypes.push(`typeof ${scriptSetupRanges.defineEmits.name ?? names_1.names.emit}`);
}
if (scriptSetupRanges?.defineModel.length) {
emitTypes.push(`typeof ${names_1.names.modelEmit}`);
}
if (emitTypes.length) {
yield* (0, utils_1.generateTypeAlias)(names_1.names.EmitProps, scriptLang, function* () {
yield `${names_1.names.EmitsToProps}<${names_1.names.NormalizeEmits}<${emitTypes.join(` & `)}>>`;
});
exps.push((0, utils_1.asType)(`{ $emit: ${emitTypes.join(` & `)} }`, scriptLang));
}
if (scriptSetupRanges?.defineProps) {
propTypes.push(`typeof ${scriptSetupRanges.defineProps.name ?? names_1.names.props}`);
}
if (scriptSetupRanges?.defineModel.length) {
propTypes.push(names_1.names.ModelProps);
}
if (emitTypes.length) {
propTypes.push(names_1.names.EmitProps);
}
if (propTypes.length) {
exps.push((0, utils_1.asType)(`{ $props: ${propTypes.join(` & `)} }`, scriptLang));
exps.push((0, utils_1.asType)(propTypes.join(` & `), scriptLang));
}
yield `const ${names_1.names.ctx} = `;
yield* (0, merge_1.generateSpreadMerge)(...exps);
yield utils_1.endOfLine;
}
function* generateTemplateComponents({ vueCompilerOptions, script, scriptRanges, localComponents, scriptLang }) {
const types = [];
if (localComponents.size) {
types.push(generateExposedType(vueCompilerOptions.lib, localComponents));
}
if (script && scriptRanges?.exportDefault?.options?.components) {
const { components } = scriptRanges.exportDefault.options;
yield `const ${names_1.names.componentsOption} = `;
yield* (0, utils_1.generateSfcBlockSection)(script, components.start, components.end, codeFeatures_1.codeFeatures.navigation);
yield utils_1.endOfLine;
types.push(`typeof ${names_1.names.componentsOption}`);
}
yield* (0, utils_1.generateTypeAlias)(names_1.names.LocalComponents, scriptLang, function* () {
yield types.length ? types.join(` & `) : `{}`;
});
yield* (0, utils_1.generateTypeAlias)(names_1.names.GlobalComponents, scriptLang, function* () {
yield vueCompilerOptions.target >= 3.5
? `import('${vueCompilerOptions.lib}').GlobalComponents`
: `import('${vueCompilerOptions.lib}').GlobalComponents & Pick<typeof import('${vueCompilerOptions.lib}'), 'Transition' | 'TransitionGroup' | 'KeepAlive' | 'Suspense' | 'Teleport'>`;
});
yield* (0, utils_1.generateTypedVar)('let', names_1.names.components, scriptLang, function* () {
yield `${names_1.names.LocalComponents} & ${names_1.names.GlobalComponents}`;
});
yield* (0, utils_1.generateTypedVar)('let', names_1.names.intrinsics, scriptLang, function* () {
yield vueCompilerOptions.target >= 3.3
? `import('${vueCompilerOptions.lib}/jsx-runtime').JSX.IntrinsicElements`
: `globalThis.JSX.IntrinsicElements`;
});
}
function* generateTemplateDirectives({ vueCompilerOptions, script, scriptRanges, localDirectives, scriptLang }) {
const types = [];
if (localDirectives.size) {
types.push(generateExposedType(vueCompilerOptions.lib, localDirectives));
}
if (script && scriptRanges?.exportDefault?.options?.directives) {
const { directives } = scriptRanges.exportDefault.options;
yield `const ${names_1.names.directivesOption} = `;
yield* (0, utils_1.generateSfcBlockSection)(script, directives.start, directives.end, codeFeatures_1.codeFeatures.navigation);
yield utils_1.endOfLine;
types.push(`${names_1.names.ResolveDirectives}<typeof ${names_1.names.directivesOption}>`);
}
yield* (0, utils_1.generateTypeAlias)(names_1.names.LocalDirectives, scriptLang, function* () {
yield types.length ? types.join(` & `) : `{}`;
});
yield* (0, utils_1.generateTypedVar)('let', names_1.names.directives, scriptLang, function* () {
yield `${names_1.names.LocalDirectives} & import('${vueCompilerOptions.lib}').GlobalDirectives`;
});
}
function generateExposedType(lib, bindings) {
return `import('${lib}').ShallowUnwrapRef<{\n${[...bindings].map(name => `${name}: typeof ${name};`).join(`\n`)}\n}>`;
}
//# sourceMappingURL=template.js.map
+3
View File
@@ -0,0 +1,3 @@
import type { Code, IRStyle } from '../../types';
export declare function generateClassProperty(source: string, classNameWithDot: string, offset: number, propertyType: string): Generator<Code>;
export declare function generateStyleImports(style: IRStyle): Generator<Code>;
+39
View File
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateClassProperty = generateClassProperty;
exports.generateStyleImports = generateStyleImports;
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
function* generateClassProperty(source, classNameWithDot, offset, propertyType) {
yield `${utils_1.newLine} & { `;
const boundary = yield* boundary_1.Boundary.start(source, offset, offset + classNameWithDot.length, codeFeatures_1.codeFeatures.navigation);
yield `'`;
yield [classNameWithDot.slice(1), source, offset + 1, boundary.features];
yield `'`;
yield boundary.end();
yield `: ${propertyType}`;
yield ` }`;
}
function* generateStyleImports(style) {
if (typeof style.src === 'object') {
yield `${utils_1.newLine} & typeof import(`;
const boundary = yield* boundary_1.Boundary.start('main', style.src.offset, style.src.offset + style.src.text.length, codeFeatures_1.codeFeatures.navigationAndVerification);
yield `'`;
yield [style.src.text, 'main', style.src.offset, boundary.features];
yield `'`;
yield boundary.end();
yield `).default`;
}
for (const { text, offset } of style.imports) {
yield `${utils_1.newLine} & typeof import('`;
yield [
text,
style.name,
offset,
codeFeatures_1.codeFeatures.navigationAndVerification,
];
yield `').default`;
}
}
//# sourceMappingURL=common.js.map
+96
View File
@@ -0,0 +1,96 @@
import type { Code, IRStyle, VueCompilerOptions } from '../../types';
export interface StyleCodegenOptions {
typescript: typeof import('typescript');
vueCompilerOptions: VueCompilerOptions;
styles: readonly IRStyle[];
scriptLang: string;
setupRefs: Set<string>;
setupConsts: Set<string>;
setupBindings: Set<string>;
dotValueBindings: Set<string>;
}
export { generate as generateStyle };
declare function generate(options: StyleCodegenOptions): {
getCommentInfo: () => {
ignoreError?: boolean;
expectError?: {
token: number;
node: import("@vue/compiler-dom").CommentNode;
};
generic?: {
content: string;
offset: number;
};
};
enter: (node: import("@vue/compiler-dom").RootNode | import("@vue/compiler-dom").TemplateChildNode | import("@vue/compiler-dom").SimpleExpressionNode) => boolean;
exit: () => Generator<Code>;
resolveCodeFeatures: (features: import("../../types").VueCodeInformation) => import("../../types").VueCodeInformation;
getInternalVariable: () => string;
scopes: {
has(value: string): boolean;
readonly size: number;
declare(...variables: string[]): void;
end(): Generator<Code, any, any>;
add(value: string): /*elided*/ any;
clear(): void;
delete(value: string): boolean;
forEach(callbackfn: (value: string, value2: string, set: Set<string>) => void, thisArg?: any): void;
[Symbol.iterator](): SetIterator<string>;
entries(): SetIterator<[string, string]>;
keys(): SetIterator<string>;
values(): SetIterator<string>;
readonly [Symbol.toStringTag]: string;
}[];
scope: () => {
has(value: string): boolean;
readonly size: number;
declare(...variables: string[]): void;
end(): Generator<Code, any, any>;
add(value: string): any;
clear(): void;
delete(value: string): boolean;
forEach(callbackfn: (value: string, value2: string, set: Set<string>) => void, thisArg?: any): void;
[Symbol.iterator](): SetIterator<string>;
entries(): SetIterator<[string, string]>;
keys(): SetIterator<string>;
values(): SetIterator<string>;
readonly [Symbol.toStringTag]: string;
};
contextAccesses: Map<string, Map<string, Set<number>>>;
dotValueAccesses: Set<string>;
accessLog: string[];
accessVariable: (source: string, name: string, offset?: number, dotValue?: boolean) => void;
generateAutoImport: () => Generator<Code>;
conditions: {
text: string;
accesses: string[];
}[];
generateConditionGuards: () => Generator<string, void, unknown>;
hoistVars: Map<string, string>;
getHoistVariable: (originalVar: string) => string;
generateHoistVariables: () => Generator<string, void, unknown>;
templateRefs: Map<string, {
typeExp: string;
offset: number;
}[]>;
addTemplateRef: (name: string, typeExp: string, offset: number) => void;
components: (() => string)[];
dollarVars: Set<string>;
inlayHints: import("../inlayHints").InlayHintInfo[];
generatedTypes: Set<string>;
inheritedAttrVars: Set<string>;
singleRootElTypes: Set<string>;
singleRootNodes: Set<import("@vue/compiler-dom").ElementNode | null>;
slots: {
name: string;
offset?: number;
tagRange: [number, number];
propsVar: string;
}[];
dynamicSlots: {
expVar: string;
propsVar: string;
}[];
inVFor: boolean;
codes: Code[];
};
+42
View File
@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyle = generate;
const codeFeatures_1 = require("../codeFeatures");
const modules_1 = require("../style/modules");
const scopedClasses_1 = require("../style/scopedClasses");
const context_1 = require("../template/context");
const interpolation_1 = require("../template/interpolation");
const styleScopedClasses_1 = require("../template/styleScopedClasses");
const utils_1 = require("../utils");
function generate(options) {
// The references registry accumulates across codegen passes; start clean.
for (const style of options.styles) {
styleScopedClasses_1.references.delete(style);
}
const ctx = (0, context_1.createTemplateCodegenContext)();
const codeGenerator = generateWorker(options, ctx);
const codes = [];
for (const code of codeGenerator) {
if (typeof code === 'object') {
code[3] = ctx.resolveCodeFeatures(code[3]);
}
codes.push(code);
}
return { ...ctx, codes };
}
function* generateWorker(options, ctx) {
const scope = ctx.scope();
yield* (0, scopedClasses_1.generateStyleScopedClasses)(options, ctx);
yield* (0, modules_1.generateStyleModules)(options, ctx);
yield* generateCssVars(options, ctx);
yield* scope.end();
}
function* generateCssVars(options, ctx) {
for (const style of options.styles) {
for (const binding of style.bindings) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, style, codeFeatures_1.codeFeatures.all, binding.text, binding.offset, `(`, `)`);
yield utils_1.endOfLine;
}
}
}
//# sourceMappingURL=index.js.map
+4
View File
@@ -0,0 +1,4 @@
import type { Code } from '../../types';
import type { TemplateCodegenContext } from '../template/context';
import type { StyleCodegenOptions } from '.';
export declare function generateStyleModules({ vueCompilerOptions, styles, scriptLang }: StyleCodegenOptions, ctx: TemplateCodegenContext): Generator<Code>;
+63
View File
@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleModules = generateStyleModules;
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const common_1 = require("./common");
function* generateStyleModules({ vueCompilerOptions, styles, scriptLang }, ctx) {
const styleModules = styles.filter(style => style.module);
if (!styleModules.length) {
return;
}
ctx.generatedTypes.add(names_1.names.StyleModules);
yield* (0, utils_1.generateTypeAlias)(names_1.names.StyleModules, scriptLang, function* () {
yield `{${utils_1.newLine}`;
for (const style of styleModules) {
if (style.module === true) {
yield `$style`;
}
else {
const { text, offset } = style.module;
if (!text) {
yield [
`$style`,
'main',
offset,
codeFeatures_1.codeFeatures.verification,
];
}
else if (utils_1.identifierRE.test(text)) {
yield [
text,
'main',
offset,
codeFeatures_1.codeFeatures.navigationAndVerification,
];
}
else {
const boundary = yield* boundary_1.Boundary.start('main', offset, offset + text.length, codeFeatures_1.codeFeatures.navigationAndVerification);
yield `'`;
yield [text, 'main', offset, boundary.features];
yield `'`;
yield boundary.end();
}
}
yield `: `;
if (!vueCompilerOptions.strictCssModules) {
yield `Record<string, string> & `;
}
yield `${names_1.names.PrettifyGlobal}<{}`;
if (vueCompilerOptions.resolveStyleImports) {
yield* (0, common_1.generateStyleImports)(style);
}
for (const className of style.classNames) {
yield* (0, common_1.generateClassProperty)(style.name, className.text, className.offset, 'string');
}
yield `>${utils_1.endOfLine}`;
}
yield `}`;
});
}
//# sourceMappingURL=modules.js.map
+4
View File
@@ -0,0 +1,4 @@
import type { Code } from '../../types';
import type { TemplateCodegenContext } from '../template/context';
import type { StyleCodegenOptions } from '.';
export declare function generateStyleScopedClasses({ vueCompilerOptions, styles, scriptLang }: StyleCodegenOptions, ctx: TemplateCodegenContext): Generator<Code>;
+45
View File
@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStyleScopedClasses = generateStyleScopedClasses;
const names_1 = require("../names");
const styleScopedClasses_1 = require("../template/styleScopedClasses");
const utils_1 = require("../utils");
const common_1 = require("./common");
function* generateStyleScopedClasses({ vueCompilerOptions, styles, scriptLang }, ctx) {
const { resolveStyleClassNames, resolveStyleImports } = vueCompilerOptions;
if (!resolveStyleClassNames) {
return;
}
const scopedStyles = styles.filter(style => resolveStyleClassNames === true || style.scoped);
if (!scopedStyles.length) {
return;
}
ctx.generatedTypes.add(names_1.names.StyleScopedClasses);
const visited = new Set();
const deferredGenerates = [];
yield* (0, utils_1.generateTypeAlias)(names_1.names.StyleScopedClasses, scriptLang, function* () {
yield `{}`;
for (const style of scopedStyles) {
if (resolveStyleImports) {
yield* (0, common_1.generateStyleImports)(style);
}
for (const className of style.classNames) {
if (!visited.has(className.text)) {
visited.add(className.text);
yield* (0, common_1.generateClassProperty)(style.name, className.text, className.offset, 'boolean');
}
else {
deferredGenerates.push((0, styleScopedClasses_1.generateStyleScopedClassReference)(style, className.text.slice(1), className.offset + 1));
}
}
}
});
if ((0, utils_1.isTsLang)(scriptLang)) {
// avoid TS6196: JSDoc refs don't count as usage; JS @typedefs skip the check
yield `void ({} as ${names_1.names.StyleScopedClasses})${utils_1.endOfLine}`;
}
for (const generate of deferredGenerates) {
yield* generate;
}
}
//# sourceMappingURL=scopedClasses.js.map
@@ -0,0 +1,12 @@
import type * as ts from 'typescript';
import type { TemplateCodegenContext } from './context';
export interface DeclarationItem {
id: ts.Identifier;
isShorthand: boolean;
isNarrowing: boolean;
skipped: boolean;
inTypeQuery: boolean;
isNewOperand: boolean;
}
export declare function forEachDeclarations(ts: typeof import('typescript'), node: ts.Node, ast: ts.SourceFile, ctx: TemplateCodegenContext, scope: ReturnType<TemplateCodegenContext['scope']>, inNarrowing: boolean): Generator<DeclarationItem>;
export declare function shouldIdentifierSkipped(ctx: TemplateCodegenContext, text: string): boolean;
@@ -0,0 +1,564 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.forEachDeclarations = forEachDeclarations;
exports.shouldIdentifierSkipped = shouldIdentifierSkipped;
const shared_1 = require("@vue/shared");
const collectBindings_1 = require("../../utils/collectBindings");
const shared_2 = require("../../utils/shared");
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* forEachDeclarations(ts, node, ast, ctx, scope, inNarrowing) {
if (ts.isIdentifier(node)) {
yield {
id: node,
isShorthand: false,
isNarrowing: inNarrowing,
skipped: shouldIdentifierSkipped(ctx, (0, shared_2.getNodeText)(ts, node, ast)),
inTypeQuery: false,
isNewOperand: false,
};
}
else if (ts.isShorthandPropertyAssignment(node)) {
yield {
id: node.name,
isShorthand: true,
isNarrowing: inNarrowing,
skipped: shouldIdentifierSkipped(ctx, (0, shared_2.getNodeText)(ts, node.name, ast)),
inTypeQuery: false,
isNewOperand: false,
};
}
else if (ts.isPropertyAccessExpression(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, true);
}
else if (ts.isElementAccessExpression(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, true);
yield* forEachDeclarations(ts, node.argumentExpression, ast, ctx, scope, false);
}
else if (ts.isCallExpression(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, false);
if (node.typeArguments) {
for (const typeArg of node.typeArguments) {
yield* forEachDeclarationsInTypeNode(ts, typeArg, ast, ctx, scope);
}
}
for (const arg of node.arguments) {
yield* forEachDeclarations(ts, arg, ast, ctx, scope, inNarrowing);
}
}
else if (ts.isNewExpression(node)) {
if (ts.isIdentifier(node.expression)) {
yield {
id: node.expression,
isShorthand: false,
isNarrowing: false,
skipped: shouldIdentifierSkipped(ctx, (0, shared_2.getNodeText)(ts, node.expression, ast)),
inTypeQuery: false,
isNewOperand: true,
};
}
else {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, false);
}
if (node.typeArguments) {
for (const typeArg of node.typeArguments) {
yield* forEachDeclarationsInTypeNode(ts, typeArg, ast, ctx, scope);
}
}
for (const arg of node.arguments ?? []) {
yield* forEachDeclarations(ts, arg, ast, ctx, scope, inNarrowing);
}
}
else if (ts.isTaggedTemplateExpression(node)) {
yield* forEachDeclarations(ts, node.tag, ast, ctx, scope, false);
yield* forEachDeclarations(ts, node.template, ast, ctx, scope, inNarrowing);
}
else if (ts.isParenthesizedExpression(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, inNarrowing);
}
else if (ts.isNonNullExpression(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, inNarrowing);
}
else if (ts.isTypeAssertionExpression(node)) {
yield* forEachDeclarationsInTypeNode(ts, node.type, ast, ctx, scope);
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, inNarrowing);
}
else if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, inNarrowing);
yield* forEachDeclarationsInTypeNode(ts, node.type, ast, ctx, scope);
}
else if (ts.isBinaryExpression(node)) {
const isLogical = node.operatorToken.kind === ts.SyntaxKind.BarBarToken
|| node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|| node.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken;
const isAssignment = node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment
&& node.operatorToken.kind <= ts.SyntaxKind.LastAssignment;
const isEquality = node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken
|| node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken
|| node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken
|| node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken;
const isInstanceof = node.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword;
const isIn = node.operatorToken.kind === ts.SyntaxKind.InKeyword;
if (node.operatorToken.kind === ts.SyntaxKind.CommaToken) {
yield* forEachDeclarations(ts, node.left, ast, ctx, scope, false);
yield* forEachDeclarations(ts, node.right, ast, ctx, scope, inNarrowing);
}
else if (isLogical) {
yield* forEachNarrowedBy(ts, node.left, ast, ctx, scope, function* () {
yield* forEachDeclarations(ts, node.right, ast, ctx, scope, inNarrowing);
});
}
else if (isAssignment) {
yield* forEachDeclarationsInAssignmentTarget(ts, node.left, ast, ctx, scope);
yield* forEachDeclarations(ts, node.right, ast, ctx, scope, false);
}
else {
yield* forEachDeclarations(ts, node.left, ast, ctx, scope, isEquality || isInstanceof);
yield* forEachDeclarations(ts, node.right, ast, ctx, scope, isEquality || isIn);
}
}
else if (ts.isConditionalExpression(node)) {
yield* forEachNarrowedBy(ts, node.condition, ast, ctx, scope, function* () {
yield* forEachDeclarations(ts, node.whenTrue, ast, ctx, scope, false);
yield* forEachDeclarations(ts, node.whenFalse, ast, ctx, scope, false);
});
}
else if (ts.isPrefixUnaryExpression(node)) {
yield* forEachDeclarations(ts, node.operand, ast, ctx, scope, node.operator === ts.SyntaxKind.ExclamationToken
|| node.operator === ts.SyntaxKind.PlusPlusToken
|| node.operator === ts.SyntaxKind.MinusMinusToken);
}
else if (ts.isPostfixUnaryExpression(node)) {
yield* forEachDeclarations(ts, node.operand, ast, ctx, scope, true);
}
else if (isDeleteExpression(ts, node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, true);
}
else if (ts.isTypeOfExpression(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, true);
}
else if (ts.isVariableDeclaration(node)) {
scope.declare(...(0, collectBindings_1.collectBindingNames)(ts, node.name, ast));
yield* forEachDeclarationsInBinding(ts, node, ast, ctx, scope);
}
else if (ts.isArrayBindingPattern(node) || ts.isObjectBindingPattern(node)) {
for (const element of node.elements) {
if (ts.isBindingElement(element)) {
yield* forEachDeclarationsInBinding(ts, element, ast, ctx, scope);
}
}
}
else if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
yield* forEachDeclarationsInFunction(ts, node, ast, ctx);
}
else if (ts.isFunctionDeclaration(node)) {
if (node.name) {
scope.declare((0, shared_2.getNodeText)(ts, node.name, ast));
}
yield* forEachDeclarationsInFunction(ts, node, ast, ctx);
}
else if (ts.isClassDeclaration(node)) {
if (node.name) {
scope.declare((0, shared_2.getNodeText)(ts, node.name, ast));
}
yield* forEachDeclarationsInClass(ts, node, ast, ctx, scope);
}
else if (ts.isClassExpression(node)) {
const classScope = ctx.scope();
if (node.name) {
classScope.declare((0, shared_2.getNodeText)(ts, node.name, ast));
}
yield* forEachDeclarationsInClass(ts, node, ast, ctx, classScope);
classScope.end();
}
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)) {
yield* forEachDeclarations(ts, prop.name.expression, ast, ctx, scope, false);
}
yield* forEachDeclarations(ts, prop.initializer, ast, ctx, scope, false);
}
// fix https://github.com/vuejs/language-tools/issues/1156
else if (ts.isShorthandPropertyAssignment(prop)) {
yield* forEachDeclarations(ts, prop, ast, ctx, scope, false);
}
// fix https://github.com/vuejs/language-tools/issues/1148#issuecomment-1094378126
else if (ts.isSpreadAssignment(prop)) {
// TODO: cannot report "Spread types may only be created from object types.ts(2698)"
yield* forEachDeclarations(ts, prop.expression, ast, ctx, scope, false);
}
// fix https://github.com/vuejs/language-tools/issues/4604
else if (ts.isFunctionLike(prop) && prop.body) {
if (prop.name && ts.isComputedPropertyName(prop.name)) {
yield* forEachDeclarations(ts, prop.name.expression, ast, ctx, scope, false);
}
yield* forEachDeclarationsInFunction(ts, prop, ast, ctx);
}
}
}
// fix https://github.com/vuejs/language-tools/issues/1422
else if (ts.isTypeNode(node)) {
yield* forEachDeclarationsInTypeNode(ts, node, ast, ctx, scope);
}
else if (ts.isBlock(node)) {
const scope = ctx.scope();
predeclareFunctionDeclarations(ts, node.statements, ast, scope);
for (const child of (0, utils_1.forEachNode)(ts, node)) {
yield* forEachDeclarations(ts, child, ast, ctx, scope, false);
}
scope.end();
}
else if (ts.isForOfStatement(node) || ts.isForInStatement(node)) {
const scope = ctx.scope();
const declarations = ts.isVariableDeclarationList(node.initializer) ? node.initializer.declarations : undefined;
if (declarations) {
for (const decl of declarations) {
if (decl.initializer) {
yield* forEachDeclarations(ts, decl.initializer, ast, ctx, scope, false);
}
}
}
else {
yield* forEachDeclarationsInAssignmentTarget(ts, node.initializer, ast, ctx, scope);
}
// The source resolves before the loop bindings are in scope (`for (const x of x)` reads the outer `x`).
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, false);
if (declarations) {
for (const decl of declarations) {
scope.declare(...(0, collectBindings_1.collectBindingNames)(ts, decl.name, ast));
}
}
yield* forEachDeclarations(ts, node.statement, ast, ctx, scope, false);
scope.end();
}
else if (ts.isIfStatement(node)) {
yield* forEachNarrowedBy(ts, node.expression, ast, ctx, scope, function* () {
yield* forEachDeclarations(ts, node.thenStatement, ast, ctx, scope, false);
if (node.elseStatement) {
yield* forEachDeclarations(ts, node.elseStatement, ast, ctx, scope, false);
}
});
}
else if (isWhileStatement(ts, node)) {
yield* forEachNarrowedBy(ts, node.expression, ast, ctx, scope, function* () {
yield* forEachDeclarations(ts, node.statement, ast, ctx, scope, false);
});
}
else if (isDoStatement(ts, node)) {
yield* forEachDeclarations(ts, node.statement, ast, ctx, scope, false);
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, true);
}
else if (ts.isForStatement(node)) {
const scope = ctx.scope();
if (node.initializer) {
if (ts.isVariableDeclarationList(node.initializer)) {
for (const decl of node.initializer.declarations) {
scope.declare(...(0, collectBindings_1.collectBindingNames)(ts, decl.name, ast));
if (decl.initializer) {
yield* forEachDeclarations(ts, decl.initializer, ast, ctx, scope, false);
}
}
}
else {
yield* forEachDeclarations(ts, node.initializer, ast, ctx, scope, false);
}
}
yield* forEachNarrowedBy(ts, node.condition, ast, ctx, scope, function* () {
if (node.incrementor) {
yield* forEachDeclarations(ts, node.incrementor, ast, ctx, scope, false);
}
yield* forEachDeclarations(ts, node.statement, ast, ctx, scope, false);
});
scope.end();
}
else if (ts.isSwitchStatement(node)) {
predeclareFunctionDeclarations(ts, node.caseBlock.clauses.flatMap(clause => [...clause.statements]), ast, scope);
yield* forEachNarrowedBy(ts, node.expression, ast, ctx, scope, function* () {
for (const clause of node.caseBlock.clauses) {
if (ts.isCaseClause(clause)) {
yield* forEachDeclarations(ts, clause.expression, ast, ctx, scope, false);
}
for (const statement of clause.statements) {
yield* forEachDeclarations(ts, statement, ast, ctx, scope, false);
}
}
});
}
else if (ts.isLabeledStatement(node)) {
yield* forEachDeclarations(ts, node.statement, ast, ctx, scope, false);
}
else if (isBreakOrContinueStatement(ts, node)) {
// break/continue labels are not bindings.
}
else if (ts.isMetaProperty(node)) {
// `new.target` / `import.meta` are not bindings.
}
else if (ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) {
yield* forEachDeclarationsInTypeNode(ts, node, ast, ctx, scope);
}
else if (ts.isEnumDeclaration(node)) {
scope.declare((0, shared_2.getNodeText)(ts, node.name, ast));
for (const member of node.members) {
if (member.initializer) {
yield* forEachDeclarations(ts, member.initializer, ast, ctx, scope, false);
}
}
}
else if (ts.isModuleDeclaration(node)) {
if (node.body && ts.isModuleBlock(node.body)) {
const scope = ctx.scope();
predeclareFunctionDeclarations(ts, node.body.statements, ast, scope);
for (const statement of node.body.statements) {
yield* forEachDeclarations(ts, statement, ast, ctx, scope, false);
}
scope.end();
}
else if (node.body && ts.isModuleDeclaration(node.body)) {
yield* forEachDeclarations(ts, node.body, ast, ctx, scope, false);
}
}
else if (ts.isCatchClause(node)) {
const scope = ctx.scope();
if (node.variableDeclaration) {
yield* forEachDeclarations(ts, node.variableDeclaration, ast, ctx, scope, false);
}
if (node.block) {
yield* forEachDeclarations(ts, node.block, ast, ctx, scope, false);
}
scope.end();
}
else if (ts.isSourceFile(node)) {
predeclareFunctionDeclarations(ts, node.statements, ast, scope);
for (const statement of node.statements) {
yield* forEachDeclarations(ts, statement, ast, ctx, scope, inNarrowing);
}
}
else if (ts.isExpressionStatement(node)) {
yield* forEachDeclarations(ts, node.expression, ast, ctx, scope, inNarrowing);
}
else {
for (const child of (0, utils_1.forEachNode)(ts, node)) {
yield* forEachDeclarations(ts, child, ast, ctx, scope, false);
}
}
}
function* forEachNarrowedBy(ts, condition, ast, ctx, scope, body) {
// The condition's declarations come first (narrowing positions), then the body.
if (condition) {
yield* forEachDeclarations(ts, condition, ast, ctx, scope, true);
}
yield* body();
}
function predeclareFunctionDeclarations(ts, statements, ast, scope) {
for (const statement of statements) {
if (ts.isFunctionDeclaration(statement) && statement.name) {
scope.declare((0, shared_2.getNodeText)(ts, statement.name, ast));
}
}
}
function* forEachDeclarationsInAssignmentTarget(ts, node, ast, ctx, scope) {
if (ts.isIdentifier(node)) {
yield {
id: node,
isShorthand: false,
isNarrowing: true,
skipped: shouldIdentifierSkipped(ctx, (0, shared_2.getNodeText)(ts, node, ast)),
inTypeQuery: false,
isNewOperand: false,
};
}
else if (ts.isObjectLiteralExpression(node)) {
for (const prop of node.properties) {
if (ts.isPropertyAssignment(prop)) {
if (ts.isComputedPropertyName(prop.name)) {
yield* forEachDeclarations(ts, prop.name.expression, ast, ctx, scope, false);
}
yield* forEachDeclarationsInAssignmentTarget(ts, prop.initializer, ast, ctx, scope);
}
else if (ts.isShorthandPropertyAssignment(prop)) {
yield {
id: prop.name,
isShorthand: true,
isNarrowing: true,
skipped: shouldIdentifierSkipped(ctx, (0, shared_2.getNodeText)(ts, prop.name, ast)),
inTypeQuery: false,
isNewOperand: false,
};
if (prop.objectAssignmentInitializer) {
yield* forEachDeclarations(ts, prop.objectAssignmentInitializer, ast, ctx, scope, false);
}
}
else if (ts.isSpreadAssignment(prop)) {
yield* forEachDeclarationsInAssignmentTarget(ts, prop.expression, ast, ctx, scope);
}
}
}
else if (ts.isArrayLiteralExpression(node)) {
for (const element of node.elements) {
if (ts.isOmittedExpression(element)) {
continue;
}
else if (ts.isSpreadElement(element)) {
yield* forEachDeclarationsInAssignmentTarget(ts, element.expression, ast, ctx, scope);
}
else if (ts.isBinaryExpression(element)) {
yield* forEachDeclarationsInAssignmentTarget(ts, element.left, ast, ctx, scope);
yield* forEachDeclarations(ts, element.right, ast, ctx, scope, false);
}
else {
yield* forEachDeclarationsInAssignmentTarget(ts, element, ast, ctx, scope);
}
}
}
else if (ts.isParenthesizedExpression(node)) {
yield* forEachDeclarationsInAssignmentTarget(ts, node.expression, ast, ctx, scope);
}
else {
yield* forEachDeclarations(ts, node, ast, ctx, scope, true);
}
}
function* forEachDeclarationsInBinding(ts, node, ast, ctx, scope) {
if ('propertyName' in node && node.propertyName && ts.isComputedPropertyName(node.propertyName)) {
yield* forEachDeclarations(ts, node.propertyName.expression, ast, ctx, scope, true);
}
if (!ts.isIdentifier(node.name)) {
yield* forEachDeclarations(ts, node.name, ast, ctx, scope, false);
}
if ('type' in node && node.type) {
yield* forEachDeclarationsInTypeNode(ts, node.type, ast, ctx, scope);
}
if (node.initializer) {
yield* forEachDeclarations(ts, node.initializer, ast, ctx, scope, false);
}
}
function* forEachDeclarationsInFunction(ts, node, ast, ctx) {
const scope = ctx.scope();
if (ts.isFunctionExpression(node) && node.name) {
scope.declare((0, shared_2.getNodeText)(ts, node.name, ast));
}
for (const param of node.parameters) {
scope.declare(...(0, collectBindings_1.collectBindingNames)(ts, param.name, ast));
}
if (node.typeParameters) {
for (const typeParam of node.typeParameters) {
yield* forEachDeclarationsInTypeNode(ts, typeParam, ast, ctx, scope);
}
}
for (const param of node.parameters) {
yield* forEachDeclarationsInBinding(ts, param, ast, ctx, scope);
}
if (node.type) {
yield* forEachDeclarationsInTypeNode(ts, node.type, ast, ctx, scope);
}
if (node.body) {
yield* forEachDeclarations(ts, node.body, ast, ctx, scope, false);
}
scope.end();
}
function* forEachDeclarationsInClass(ts, node, ast, ctx, scope) {
for (const typeParam of node.typeParameters ?? []) {
yield* forEachDeclarationsInTypeNode(ts, typeParam, ast, ctx, scope);
}
for (const clause of node.heritageClauses ?? []) {
if (clause.token === ts.SyntaxKind.ExtendsKeyword) {
for (const type of clause.types) {
yield* forEachDeclarations(ts, type.expression, ast, ctx, scope, false);
if (type.typeArguments) {
for (const typeArg of type.typeArguments) {
yield* forEachDeclarationsInTypeNode(ts, typeArg, ast, ctx, scope);
}
}
}
}
else {
yield* forEachDeclarationsInTypeNode(ts, clause, ast, ctx, scope);
}
}
for (const member of node.members) {
if (ts.isPropertyDeclaration(member)
|| ts.isMethodDeclaration(member)
|| ts.isGetAccessorDeclaration(member)
|| ts.isSetAccessorDeclaration(member)) {
if (member.name && ts.isComputedPropertyName(member.name)) {
// A computed name in a class property must be an entity name (grammar rule): no `__VLS_unwrap` call allowed.
yield* forEachDeclarations(ts, member.name.expression, ast, ctx, scope, true);
}
}
if (ts.isConstructorDeclaration(member)
|| ts.isMethodDeclaration(member)
|| ts.isGetAccessorDeclaration(member)
|| ts.isSetAccessorDeclaration(member)) {
yield* forEachDeclarationsInFunction(ts, member, ast, ctx);
}
else if (ts.isPropertyDeclaration(member)) {
if (member.type) {
yield* forEachDeclarationsInTypeNode(ts, member.type, ast, ctx, scope);
}
if (member.initializer) {
yield* forEachDeclarations(ts, member.initializer, ast, ctx, scope, false);
}
}
else if (ts.isClassStaticBlockDeclaration(member)) {
const blockScope = ctx.scope();
predeclareFunctionDeclarations(ts, member.body.statements, ast, blockScope);
for (const statement of member.body.statements) {
yield* forEachDeclarations(ts, statement, ast, ctx, blockScope, false);
}
blockScope.end();
}
}
}
function* forEachDeclarationsInTypeNode(ts, node, ast, ctx, scope) {
if (ts.isTypeQueryNode(node)) {
let id = node.exprName;
while (!ts.isIdentifier(id)) {
id = id.left;
}
yield {
id,
isShorthand: false,
isNarrowing: false,
skipped: shouldIdentifierSkipped(ctx, (0, shared_2.getNodeText)(ts, id, ast)),
inTypeQuery: true,
isNewOperand: false,
};
}
else if (ts.isComputedPropertyName(node)) {
// TS1170: a computed name in a type literal must be an entity-name expression (no calls).
for (const item of forEachDeclarations(ts, node.expression, ast, ctx, scope, false)) {
item.inTypeQuery = true;
yield item;
}
}
else {
for (const child of (0, utils_1.forEachNode)(ts, node)) {
yield* forEachDeclarationsInTypeNode(ts, child, ast, ctx, scope);
}
}
}
function shouldIdentifierSkipped(ctx, text) {
return ctx.scopes.some(scope => scope.has(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_');
}
// vue-tsc runs against TypeScript's tsc bundle, which does not include
// type guards that the compiler itself never uses, so check `kind` directly.
function isDeleteExpression(ts, node) {
return node.kind === ts.SyntaxKind.DeleteExpression;
}
function isWhileStatement(ts, node) {
return node.kind === ts.SyntaxKind.WhileStatement;
}
function isDoStatement(ts, node) {
return node.kind === ts.SyntaxKind.DoStatement;
}
function isBreakOrContinueStatement(ts, node) {
return node.kind === ts.SyntaxKind.BreakStatement || node.kind === ts.SyntaxKind.ContinueStatement;
}
//# sourceMappingURL=bindingReferences.js.map
+87
View File
@@ -0,0 +1,87 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code, VueCodeInformation } from '../../types';
import type { InlayHintInfo } from '../inlayHints';
export type TemplateCodegenContext = ReturnType<typeof createTemplateCodegenContext>;
export declare function createTemplateCodegenContext(): {
getCommentInfo: () => {
ignoreError?: boolean;
expectError?: {
token: number;
node: CompilerDOM.CommentNode;
};
generic?: {
content: string;
offset: number;
};
};
enter: (node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode) => boolean;
exit: () => Generator<Code>;
resolveCodeFeatures: (features: VueCodeInformation) => VueCodeInformation;
getInternalVariable: () => string;
scopes: {
has(value: string): boolean;
readonly size: number;
declare(...variables: string[]): void;
end(): Generator<Code, any, any>;
add(value: string): /*elided*/ any;
clear(): void;
delete(value: string): boolean;
forEach(callbackfn: (value: string, value2: string, set: Set<string>) => void, thisArg?: any): void;
[Symbol.iterator](): SetIterator<string>;
entries(): SetIterator<[string, string]>;
keys(): SetIterator<string>;
values(): SetIterator<string>;
readonly [Symbol.toStringTag]: string;
}[];
scope: () => {
has(value: string): boolean;
readonly size: number;
declare(...variables: string[]): void;
end(): Generator<Code, any, any>;
add(value: string): any;
clear(): void;
delete(value: string): boolean;
forEach(callbackfn: (value: string, value2: string, set: Set<string>) => void, thisArg?: any): void;
[Symbol.iterator](): SetIterator<string>;
entries(): SetIterator<[string, string]>;
keys(): SetIterator<string>;
values(): SetIterator<string>;
readonly [Symbol.toStringTag]: string;
};
contextAccesses: Map<string, Map<string, Set<number>>>;
dotValueAccesses: Set<string>;
accessLog: string[];
accessVariable: (source: string, name: string, offset?: number, dotValue?: boolean) => void;
generateAutoImport: () => Generator<Code>;
conditions: {
text: string;
accesses: string[];
}[];
generateConditionGuards: () => Generator<string, void, unknown>;
hoistVars: Map<string, string>;
getHoistVariable: (originalVar: string) => string;
generateHoistVariables: () => Generator<string, void, unknown>;
templateRefs: Map<string, {
typeExp: string;
offset: number;
}[]>;
addTemplateRef: (name: string, typeExp: string, offset: number) => void;
components: (() => string)[];
dollarVars: Set<string>;
inlayHints: InlayHintInfo[];
generatedTypes: Set<string>;
inheritedAttrVars: Set<string>;
singleRootElTypes: Set<string>;
singleRootNodes: Set<CompilerDOM.ElementNode | null>;
slots: {
name: string;
offset?: number;
tagRange: [number, number];
propsVar: string;
}[];
dynamicSlots: {
expVar: string;
propsVar: string;
}[];
inVFor: boolean;
};
+337
View File
@@ -0,0 +1,337 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTemplateCodegenContext = createTemplateCodegenContext;
const language_core_1 = require("@volar/language-core");
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const directiveCommentRE = /^<!--\s*@vue-(?<name>[-\w]+)\b(?<content>[\s\S]*)-->$/;
// Reserved words can never be auto-imported bindings, and emitting them as
// bare array elements is a syntax error (#5267: `[class,]`).
const reservedWords = new Set([
'arguments',
'await',
'break',
'case',
'catch',
'class',
'const',
'continue',
'debugger',
'default',
'delete',
'do',
'else',
'enum',
'eval',
'export',
'extends',
'false',
'finally',
'for',
'function',
'if',
'implements',
'import',
'in',
'instanceof',
'interface',
'let',
'new',
'null',
'package',
'private',
'protected',
'public',
'return',
'static',
'super',
'switch',
'this',
'throw',
'true',
'try',
'typeof',
'var',
'void',
'while',
'with',
'yield',
]);
function createTemplateCodegenContext() {
// directive comments ---------------------------------------------------------
const stack = [];
const commentBuffer = [];
function getCommentInfo() {
return stack[stack.length - 1];
}
function enter(node) {
if (node.type === CompilerDOM.NodeTypes.COMMENT) {
commentBuffer.push(node);
return false;
}
const info = {};
const comments = [...commentBuffer];
commentBuffer.length = 0;
for (const comment of comments) {
const match = comment.loc.source.match(directiveCommentRE);
if (match) {
const { name, content } = match.groups;
switch (name) {
case 'skip': {
return false;
}
case 'ignore': {
info.ignoreError = true;
break;
}
case 'expect-error': {
info.expectError = {
token: 0,
node: comment,
};
break;
}
case 'generic': {
const text = content.trim();
if (text.startsWith('{') && text.endsWith('}')) {
info.generic = {
content: text.slice(1, -1),
offset: comment.loc.start.offset + comment.loc.source.indexOf('{') + 1,
};
}
break;
}
}
}
}
stack.push(info);
return true;
}
function* exit() {
const info = stack.pop();
commentBuffer.length = 0;
if (info.expectError !== undefined) {
const boundary = yield* boundary_1.Boundary.start('template', info.expectError.node.loc.start.offset, info.expectError.node.loc.end.offset, {
verification: {
shouldReport: () => info.expectError.token === 0,
},
});
yield `// @ts-expect-error`;
yield boundary.end();
yield `${utils_1.newLine}${utils_1.endOfLine}`;
}
}
function resolveCodeFeatures(features) {
if (features.verification && stack.length) {
const data = stack[stack.length - 1];
if (data.ignoreError) {
return {
...features,
verification: false,
};
}
if (data.expectError !== undefined) {
return {
...features,
verification: {
shouldReport: (source, code) => {
if ((0, language_core_1.shouldReportDiagnostics)(features, source, code)) {
data.expectError.token++;
}
return false;
},
},
};
}
}
return features;
}
// internal variables ---------------------------------------------------------
let variableId = 0;
function getInternalVariable() {
return `__VLS_${variableId++}`;
}
// scopes ---------------------------------------------------------------------
class Scope extends Set {
declare(...variables) {
for (const name of variables) {
this.add(name);
}
}
end() {
scopes.pop();
return generateAutoImport();
}
}
const scopes = [];
function scope() {
const scope = new Scope();
scopes.push(scope);
return scope;
}
// context accesses -----------------------------------------------------------
const contextAccesses = new Map();
const dotValueAccesses = new Set();
// Ordered log of accessed names; event-handler closures slice from a mark
// to find the names accessed within their body.
const accessLog = [];
function accessVariable(source, name, offset, dotValue = false) {
accessLog.push(name);
let map = contextAccesses.get(name);
if (!map) {
contextAccesses.set(name, map = new Map());
}
let arr = map.get(source);
if (!arr) {
map.set(source, arr = new Set());
}
if (offset !== undefined) {
arr.add(offset);
}
if (dotValue) {
dotValueAccesses.add(name);
}
}
function* generateAutoImport() {
const all = [...contextAccesses.entries()];
if (!all.some(([, offsets]) => offsets.size)) {
return;
}
yield `// @ts-ignore${utils_1.newLine}`; // #2304
yield `[`;
for (const [varName, map] of all) {
for (const [source, offsets] of map) {
if (!reservedWords.has(varName)) {
for (const offset of offsets) {
yield [varName, source, offset, codeFeatures_1.codeFeatures.importCompletionOnly];
yield `,`;
}
}
offsets.clear();
}
}
yield `]${utils_1.endOfLine}`;
}
// conditions -----------------------------------------------------------------
// Active branch conditions with the names each accessed; the guards are
// replayed inside inline-handler closures.
const conditions = [];
function* generateConditionGuards() {
for (const condition of conditions) {
if (condition.accesses.length && condition.accesses.every(name => scopes.some(scope => scope.has(name)))) {
continue;
}
yield `if (!${condition.text}) throw 0${utils_1.endOfLine}`;
}
}
// hoist vars -----------------------------------------------------------------
const hoistVars = new Map();
function getHoistVariable(originalVar) {
let name = hoistVars.get(originalVar);
if (name === undefined) {
hoistVars.set(originalVar, name = `__VLS_${variableId++}`);
}
return name;
}
function* generateHoistVariables() {
// trick to avoid TS 4081 (#5186)
if (hoistVars.size) {
yield `var `;
let first = true;
for (const [originalVar, hoistVar] of hoistVars) {
if (!first) {
yield `, `;
}
first = false;
yield `${hoistVar} = ${originalVar}!`;
}
yield utils_1.endOfLine;
}
}
// template refs --------------------------------------------------------------
const templateRefs = new Map();
function addTemplateRef(name, typeExp, offset) {
let refs = templateRefs.get(name);
if (!refs) {
templateRefs.set(name, refs = []);
}
refs.push({ typeExp, offset });
}
// others ---------------------------------------------------------------------
const components = [];
const dollarVars = new Set();
const inlayHints = [];
const generatedTypes = new Set();
const inheritedAttrVars = new Set();
const singleRootElTypes = new Set();
const singleRootNodes = new Set();
const slots = [];
const dynamicSlots = [];
return {
getCommentInfo,
enter,
exit,
resolveCodeFeatures,
getInternalVariable,
scopes,
scope,
contextAccesses,
dotValueAccesses,
accessLog,
accessVariable,
generateAutoImport,
conditions,
generateConditionGuards,
hoistVars,
getHoistVariable,
generateHoistVariables,
templateRefs,
addTemplateRef,
components,
dollarVars,
inlayHints,
generatedTypes,
inheritedAttrVars,
singleRootElTypes,
singleRootNodes,
slots,
dynamicSlots,
inVFor: false,
};
}
//# sourceMappingURL=context.js.map
+7
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 generateComponent(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;
export declare function generateElement(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;
export declare function generateFragment(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;
+336
View File
@@ -0,0 +1,336 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateComponent = generateComponent;
exports.generateElement = generateElement;
exports.generateFragment = generateFragment;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const shared_1 = require("@vue/shared");
const muggle_string_1 = require("muggle-string");
const shared_2 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const inlayHints_1 = require("../inlayHints");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const camelized_1 = require("../utils/camelized");
const stringLiteralKey_1 = require("../utils/stringLiteralKey");
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 templateChild_1 = require("./templateChild");
const vSlot_1 = require("./vSlot");
function* generateComponent(options, ctx, node) {
let { tag, props } = node;
let [startTagOffset, endTagOffset] = (0, shared_2.getElementTagOffsets)(node, options.template);
let isExpression = false;
let isIsShorthand = false;
if (tag.includes('.')) {
isExpression = true;
}
else if (tag === 'component') {
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) {
isIsShorthand = prop.arg.loc.end.offset === prop.exp.loc.end.offset;
if (isIsShorthand) {
ctx.inlayHints.push((0, inlayHints_1.createVBindShorthandInlayHintInfo)(prop.exp.loc, 'is'));
}
isExpression = true;
tag = prop.exp.content;
startTagOffset = prop.exp.loc.start.offset;
endTagOffset = undefined;
props = props.filter(p => p !== prop);
break;
}
}
}
const componentVar = ctx.getInternalVariable();
if (isExpression) {
yield `const ${componentVar} = `;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, isIsShorthand
? codeFeatures_1.codeFeatures.withoutHighlightAndCompletion
: codeFeatures_1.codeFeatures.all, tag, startTagOffset, `(`, `)`);
if (endTagOffset !== undefined) {
yield ` || `;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.withoutCompletion, tag, endTagOffset, `(`, `)`);
}
yield `${utils_1.endOfLine}`;
}
else {
const originalNames = new Set([
(0, shared_1.capitalize)((0, shared_1.camelize)(tag)),
(0, shared_1.camelize)(tag),
tag,
]);
const matchedImportedComponent = [...originalNames].find(name => options.importedComponents.has(name));
if (matchedImportedComponent) {
// navigation & auto import support
yield `const ${componentVar} = `;
yield* (0, camelized_1.generateCamelized)(matchedImportedComponent[0] + tag.slice(1), 'template', startTagOffset, {
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletion,
...codeFeatures_1.codeFeatures.importCompletionOnly,
});
if (endTagOffset !== undefined) {
yield ` || `;
yield* (0, camelized_1.generateCamelized)(matchedImportedComponent[0] + tag.slice(1), 'template', endTagOffset, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
}
yield utils_1.endOfLine;
}
else {
yield* (0, utils_1.generateTypedVar)('let', componentVar, options.scriptLang, function* () {
yield `${names_1.names.WithComponent}<'${tag}', ${names_1.names.LocalComponents}, ${names_1.names.GlobalComponents}`;
yield originalNames.has(options.componentName)
? `, typeof ${names_1.names.export}`
: `, void`;
for (const name of originalNames) {
yield `, '${name}'`;
}
yield `>[`;
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(tag, startTagOffset, {
...codeFeatures_1.codeFeatures.semanticWithoutHighlight,
...options.vueCompilerOptions.checkUnknownComponents
? codeFeatures_1.codeFeatures.verification
: codeFeatures_1.codeFeatures.doNotReportTs2339AndTs2551,
});
yield `]`;
});
if (utils_1.identifierRE.test((0, shared_1.camelize)(tag))) {
// navigation support
yield `/** @ts-ignore @type {`;
for (const offset of [startTagOffset, endTagOffset]) {
if (offset === undefined) {
continue;
}
yield ` | typeof ${names_1.names.components}.`;
yield* (0, camelized_1.generateCamelized)(tag, 'template', offset, codeFeatures_1.codeFeatures.navigation);
if (tag[0] !== tag[0].toUpperCase()) {
yield ` | typeof ${names_1.names.components}.`;
yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(tag), 'template', offset, codeFeatures_1.codeFeatures.navigation);
}
if (tag.includes('-')) {
yield ` | typeof ${names_1.names.components}[`;
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(tag, offset, codeFeatures_1.codeFeatures.navigation);
yield `]`;
}
}
yield `} */${utils_1.newLine}`;
// auto import support
yield* (0, camelized_1.generateCamelized)(tag, 'template', startTagOffset, codeFeatures_1.codeFeatures.importCompletionOnly);
yield utils_1.endOfLine;
}
}
}
let isCtxVarUsed = false;
let isPropsVarUsed = false;
const getCtxVar = () => (isCtxVarUsed = true, ctxVar);
const getPropsVar = () => (isPropsVarUsed = true, propsVar);
ctx.components.push(getCtxVar);
const functionalVar = ctx.getInternalVariable();
const vnodeVar = ctx.getInternalVariable();
const ctxVar = ctx.getInternalVariable();
const propsVar = ctx.getInternalVariable();
const failedPropExps = [];
const propCodes = [...(0, elementProps_1.generateElementProps)(options, ctx, node, props, options.vueCompilerOptions.checkUnknownProps, failedPropExps)];
const propsStr = (0, muggle_string_1.toString)(propCodes);
yield `// @ts-ignore${utils_1.newLine}`;
yield `const ${functionalVar} = ${options.vueCompilerOptions.checkUnknownProps ? names_1.names.asFunctionalComponent0 : names_1.names.asFunctionalComponent1}(${componentVar}, new ${componentVar}({${utils_1.newLine}`;
yield `// @ts-ignore${utils_1.newLine}`;
yield propsStr
.replace(/\/\/(.*)$/gm, (_, body) => `/*${body.replaceAll('*/', '*\\/')} */`)
.replace(/\n/g, ' ');
yield `}))${utils_1.endOfLine}`;
yield `const `;
const boundary = yield* boundary_1.Boundary.start('template', node.loc.start.offset, node.loc.end.offset, codeFeatures_1.codeFeatures.doNotReportTs6133);
yield vnodeVar;
yield boundary.end();
yield ` = ${functionalVar}`;
const commentInfo = ctx.getCommentInfo();
if (commentInfo.generic) {
const { content, offset } = commentInfo.generic;
const boundary = yield* boundary_1.Boundary.start('template', offset, offset + content.length, codeFeatures_1.codeFeatures.verification);
yield `<`;
yield [content, 'template', offset, codeFeatures_1.codeFeatures.all];
yield `>`;
yield boundary.end();
}
const shouldInheritAttrs = hasVBindAttrs(options, ctx, node);
yield `(`;
const boundary2 = yield* boundary_1.Boundary.start('template', startTagOffset, startTagOffset + tag.length, shouldInheritAttrs && options.vueCompilerOptions.checkRequiredFallthroughAttributes
? {}
: codeFeatures_1.codeFeatures.verification);
yield `{`;
yield [``, 'template', node.loc.start.offset, { __propsCompletion: true }];
yield utils_1.newLine;
yield* propCodes;
yield `}`;
yield boundary2.end();
yield `, ...${names_1.names.functionalComponentArgsRest}(${functionalVar}))${utils_1.endOfLine}`;
yield* generateFailedExpressions(options, ctx, failedPropExps);
yield* (0, elementEvents_1.generateElementEvents)(options, ctx, node, componentVar, getCtxVar, getPropsVar);
yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node);
const templateRef = getTemplateRef(node);
const isSingleRoot = ctx.singleRootNodes.has(node)
&& !options.vueCompilerOptions.fallthroughComponentNames.includes((0, shared_2.hyphenateTag)(tag));
const inferRootEl = ctx.dollarVars.has('$el') || options.vueCompilerOptions.inferComponentDollarEl;
const inferTemplateRefs = options.vueCompilerOptions.inferTemplateDollarRefs
|| options.vueCompilerOptions.inferComponentDollarRefs
|| options.setupRefs.size > 0;
if ((templateRef && inferTemplateRefs) || (isSingleRoot && inferRootEl)) {
const componentInstanceVar = ctx.getInternalVariable();
yield* (0, utils_1.generateTypedVar)('var', componentInstanceVar, options.scriptLang, function* () {
yield `Parameters<NonNullable<typeof ${getCtxVar()}['expose']>>[0]`;
});
if (templateRef && inferTemplateRefs) {
let typeExp = `typeof ${ctx.getHoistVariable(componentInstanceVar)} | null`;
if (ctx.inVFor) {
typeExp = `(${typeExp})[]`;
}
ctx.addTemplateRef(templateRef[0], typeExp, templateRef[1]);
}
if (isSingleRoot && inferRootEl) {
ctx.singleRootElTypes.add(`NonNullable<typeof ${componentInstanceVar}>['$el']`);
}
}
if (shouldInheritAttrs) {
if (options.vueCompilerOptions.checkRequiredFallthroughAttributes) {
const restsVar = ctx.getInternalVariable();
yield `var ${restsVar} = ${names_1.names.omit}(${getPropsVar()}, {\n${propsStr}})${utils_1.endOfLine}`;
ctx.inheritedAttrVars.add(restsVar);
}
else {
ctx.inheritedAttrVars.add(getPropsVar());
}
}
yield* (0, styleScopedClasses_1.generateStyleScopedClassReferences)(options, node);
const slotDir = node.props.find(CompilerDOM.isVSlot);
if (slotDir || node.children.length) {
yield* (0, vSlot_1.generateVSlot)(options, ctx, node, slotDir, getCtxVar());
}
if (isCtxVarUsed) {
yield* (0, utils_1.generateTypedVar)('var', ctxVar, options.scriptLang, function* () {
yield `${names_1.names.ExtractComponentContext}<typeof ${componentVar}, typeof ${vnodeVar}>`;
});
}
if (isPropsVarUsed) {
yield* (0, utils_1.generateTypedVar)('var', propsVar, options.scriptLang, function* () {
yield `${names_1.names.ExtractComponentProps}<typeof ${componentVar}, typeof ${vnodeVar}>`;
});
}
ctx.components.pop();
}
function* generateElement(options, ctx, node) {
const [startTagOffset, endTagOffset] = (0, shared_2.getElementTagOffsets)(node, options.template);
const failedPropExps = [];
yield `${options.vueCompilerOptions.checkUnknownProps ? names_1.names.asFunctionalElement0 : names_1.names.asFunctionalElement1}(${names_1.names.intrinsics}`;
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, node.tag, startTagOffset, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
if (endTagOffset !== undefined) {
yield `, `;
yield names_1.names.intrinsics;
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, node.tag, endTagOffset, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
}
yield `)(`;
const boundary = yield* boundary_1.Boundary.start('template', startTagOffset, startTagOffset + node.tag.length, codeFeatures_1.codeFeatures.verification);
yield `{${utils_1.newLine}`;
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, node.props, options.vueCompilerOptions.checkUnknownProps, failedPropExps);
yield `}`;
yield boundary.end();
yield `)${utils_1.endOfLine}`;
yield* generateFailedExpressions(options, ctx, failedPropExps);
yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node);
const templateRef = getTemplateRef(node);
if (templateRef) {
let typeExp = `${names_1.names.Elements}['${node.tag}']`;
if (ctx.inVFor) {
typeExp += `[]`;
}
ctx.addTemplateRef(templateRef[0], typeExp, templateRef[1]);
}
if (ctx.singleRootNodes.has(node) && (ctx.dollarVars.has('$el') || options.vueCompilerOptions.inferComponentDollarEl)) {
ctx.singleRootElTypes.add(`${names_1.names.Elements}['${node.tag}']`);
}
if (hasVBindAttrs(options, ctx, node)) {
ctx.inheritedAttrVars.add(`${names_1.names.intrinsics}.${node.tag}`);
}
yield* (0, styleScopedClasses_1.generateStyleScopedClassReferences)(options, node);
for (const child of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, child);
}
}
function* generateFragment(options, ctx, node) {
const [startTagOffset] = (0, shared_2.getElementTagOffsets)(node, options.template);
const failedPropExps = [];
// special case for <template v-for="..." :key="..." />
if (node.props.length) {
yield `${options.vueCompilerOptions.checkUnknownProps ? names_1.names.asFunctionalElement0 : names_1.names.asFunctionalElement1}(${names_1.names.intrinsics}.template)(`;
const boundary = yield* boundary_1.Boundary.start('template', startTagOffset, startTagOffset + node.tag.length, codeFeatures_1.codeFeatures.verification);
yield `{${utils_1.newLine}`;
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, node.props, options.vueCompilerOptions.checkUnknownProps, failedPropExps);
yield `}`;
yield boundary.end();
yield `)${utils_1.endOfLine}`;
yield* generateFailedExpressions(options, ctx, failedPropExps);
}
for (const child of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, child);
}
}
function* generateFailedExpressions(options, ctx, failedPropExps) {
for (const { node, prefix, suffix } of failedPropExps) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.all, node.loc.source, node.loc.start.offset, prefix, suffix);
yield utils_1.endOfLine;
}
}
function getTemplateRef(node) {
for (const prop of node.props) {
if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE
&& prop.name === 'ref'
&& prop.value) {
return (0, shared_2.normalizeAttributeValue)(prop.value);
}
}
}
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
@@ -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, asBindingProperty?: boolean): Generator<Code>;
@@ -0,0 +1,162 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementDirectives = generateElementDirectives;
exports.generateModifiers = generateModifiers;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const shared_1 = require("@vue/shared");
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const camelized_1 = require("../utils/camelized");
const stringLiteralKey_1 = require("../utils/stringLiteralKey");
const elementProps_1 = require("./elementProps");
const interpolation_1 = require("./interpolation");
const objectProperty_1 = require("./objectProperty");
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;
}
const boundary = yield* boundary_1.Boundary.start('template', prop.loc.start.offset, prop.loc.end.offset, codeFeatures_1.codeFeatures.verification);
if (options.isVapor && !(0, shared_1.isBuiltInDirective)(prop.name)) {
// vapor custom directives receive a value getter instead of a vdom binding object
yield* generateIdentifier(options, ctx, prop);
yield `(${names_1.names.nonNull}(null), `;
yield* generateValue(options, ctx, prop, false);
yield* generateArg(options, ctx, prop, false);
yield* generateModifiers(options, ctx, prop, 'modifiers', false);
yield `)`;
}
else {
yield `${names_1.names.asFunctionalDirective}(`;
yield* generateIdentifier(options, ctx, prop);
yield `, ${(0, utils_1.asType)(`import('${options.vueCompilerOptions.lib}').ObjectDirective`, options.scriptLang)})(${names_1.names.nonNull}(null), { ...${names_1.names.directiveBindingRestFields}, `;
yield* generateArg(options, ctx, prop);
yield* generateModifiers(options, ctx, prop);
yield* generateValue(options, ctx, prop);
// Vue invokes hooks with all four arguments regardless of the declared
// arity; the padded hook keeps the declared params checked, so the
// synthetic vnode args are `never` to stay assignable to whatever they declare.
yield `},${utils_1.newLine}${names_1.names.nonNull}(null), ${names_1.names.nonNull}(null))`;
}
yield boundary.end();
yield utils_1.endOfLine;
}
}
function* generateIdentifier(options, ctx, prop) {
const rawName = 'v-' + prop.name;
const startOffset = prop.loc.start.offset;
const boundary = yield* boundary_1.Boundary.start('template', startOffset, startOffset + rawName.length, codeFeatures_1.codeFeatures.verification);
yield names_1.names.directives;
yield `.`;
yield* (0, camelized_1.generateCamelized)(rawName, 'template', prop.loc.start.offset, {
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletion,
verification: options.vueCompilerOptions.checkUnknownDirectives && !(0, shared_1.isBuiltInDirective)(prop.name),
});
if (!(0, shared_1.isBuiltInDirective)(prop.name)) {
ctx.accessVariable('template', (0, shared_1.camelize)(rawName), prop.loc.start.offset);
}
yield boundary.end();
}
function* generateArg(options, ctx, prop, asBindingProperty = true) {
const { arg } = prop;
if (arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const startOffset = arg.loc.start.offset + arg.loc.source.indexOf(arg.content);
if (asBindingProperty) {
const boundary = yield* boundary_1.Boundary.start('template', startOffset, startOffset + arg.content.length, codeFeatures_1.codeFeatures.verification);
yield `arg`;
yield boundary.end();
yield `: `;
}
if (arg.isStatic) {
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(arg.content, startOffset, codeFeatures_1.codeFeatures.all);
}
else {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.all, arg.content, startOffset, `(`, `)`);
}
yield `, `;
}
else if (!asBindingProperty) {
yield `undefined, `;
}
}
function* generateModifiers(options, ctx, prop, propertyName = 'modifiers', asBindingProperty = true) {
const { modifiers } = prop;
if (modifiers.length) {
if (asBindingProperty) {
const boundary = yield* boundary_1.Boundary.start('template', modifiers[0].loc.start.offset - 1, modifiers.at(-1).loc.end.offset, codeFeatures_1.codeFeatures.verification);
yield propertyName;
yield boundary.end();
yield `: `;
}
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 `}, `;
}
else if (!asBindingProperty) {
yield `undefined, `;
}
}
function* generateValue(options, ctx, prop, asBindingProperty = true) {
const { exp } = prop;
if (exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const boundary = yield* boundary_1.Boundary.start('template', exp.loc.start.offset, exp.loc.end.offset, codeFeatures_1.codeFeatures.verification);
if (asBindingProperty) {
yield `value`;
yield boundary.end();
yield `: `;
yield* (0, elementProps_1.generatePropExp)(options, ctx, prop, exp);
}
else {
yield `() => `;
yield* (0, elementProps_1.generatePropExp)(options, ctx, prop, exp);
yield boundary.end();
}
yield `, `;
}
else if (!asBindingProperty) {
yield `undefined, `;
}
}
//# sourceMappingURL=elementDirectives.js.map
@@ -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, getCtxVar: () => string, getPropsVar: () => 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;
+273
View File
@@ -0,0 +1,273 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementEvents = generateElementEvents;
exports.generateEventArg = generateEventArg;
exports.generateEventExpression = generateEventExpression;
exports.generateModelEventExpression = generateModelEventExpression;
exports.isCompoundExpression = isCompoundExpression;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const shared_1 = require("@vue/shared");
const utils_1 = require("../../parsers/utils");
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_2 = require("../utils");
const boundary_1 = require("../utils/boundary");
const camelized_1 = require("../utils/camelized");
const interpolation_1 = require("./interpolation");
function* generateElementEvents(options, ctx, node, componentOriginalVar, getCtxVar, getPropsVar) {
const definitions = {};
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))) {
let source = prop.arg?.loc.source ?? 'model-value';
let offset = 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);
offset = offset + 'vue:'.length;
propPrefix = 'onVnode-';
emitPrefix = 'vnode-';
}
const propName = (0, shared_1.camelize)(propPrefix + source);
const emitName = emitPrefix + source;
const key = [
prop.name,
propName,
...prop.modifiers.map(modifier => modifier.content),
].join('+');
definitions[key] ??= {
propPrefix,
emitPrefix,
propName,
emitName,
items: [],
};
definitions[key].items.push({
prop,
source,
offset,
});
}
}
if (!Object.keys(definitions).length) {
return;
}
const emitsVar = ctx.getInternalVariable();
yield* (0, utils_2.generateTypedVar)('let', emitsVar, options.scriptLang, function* () {
yield `${names_1.names.ResolveEmits}<typeof ${componentOriginalVar}, typeof ${getCtxVar()}.emit>`;
});
for (const { propPrefix, emitPrefix, propName, emitName, items } of Object.values(definitions)) {
const eventVar = ctx.getInternalVariable();
const eventType = `${options.vueCompilerOptions.checkUnknownEvents ? '' : 'Record<string, unknown> & '}Partial<${names_1.names.ResolveEvent}<typeof ${getPropsVar()}, typeof ${emitsVar}, '${propName}', '${emitName}', '${(0, shared_1.camelize)(emitName)}'>>`;
if ((0, utils_2.isTsLang)(options.scriptLang)) {
yield `const ${eventVar}: ${eventType} = {${utils_2.newLine}`;
}
else {
yield `/** @type {${eventType}} */${utils_2.newLine}const ${eventVar} = {${utils_2.newLine}`;
}
for (const { prop, source, offset } of items) {
if (prop.name === 'on') {
yield `/** @type {typeof ${emitsVar}.`;
yield* generateEventArg(options, source, offset, emitPrefix.slice(0, -1), codeFeatures_1.codeFeatures.navigation);
yield `} */${utils_2.newLine}`;
}
if (prop.name === 'on') {
yield* generateEventArg(options, source, offset, propPrefix.slice(0, -1));
yield `: `;
yield* generateEventExpression(options, ctx, prop);
}
else {
yield `'${propName}': `;
yield* generateModelEventExpression(options, ctx, prop);
}
yield `,${utils_2.newLine}`;
}
yield `}${utils_2.endOfLine}`;
yield `void ${eventVar}${utils_2.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);
}
const boundary = yield* boundary_1.Boundary.start('template', start, start + name.length, features);
if (utils_2.identifierRE.test((0, shared_1.camelize)(name))) {
yield directive;
yield* (0, camelized_1.generateCamelized)(name, 'template', start, boundary.features);
}
else {
yield `'`;
yield directive;
yield* (0, camelized_1.generateCamelized)(name, 'template', start, boundary.features);
yield `'`;
yield boundary.end();
}
}
function* generateEventExpression(options, ctx, prop) {
if (prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const ast = (0, utils_2.getTypeScriptAST)(options.typescript, options.template, prop.exp.content);
const isCompound = isCompoundExpression(options.typescript, ast);
const interpolation = (0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.all, prop.exp.content, prop.exp.loc.start.offset, isCompound ? `` : `(`, isCompound ? `` : `)`);
if (isCompound) {
const scope = ctx.scope();
scope.declare('$event');
const accessMark = ctx.accessLog.length;
const codes = [];
for (const code of interpolation) {
codes.push(code);
}
yield `// @ts-ignore${utils_2.newLine}`;
yield `(...[$event]) => {${utils_2.newLine}`;
// consume $event to avoid TS6133 when the expression doesn't use it
yield `void $event${utils_2.endOfLine}`;
yield* generateReasserts(options, ctx, accessMark);
yield* ctx.generateConditionGuards();
if (isSingleExpression(options.typescript, ast)) {
yield `return (`;
yield* codes;
yield `)`;
}
else {
yield* codes;
}
yield utils_2.endOfLine;
yield* scope.end();
yield `}`;
ctx.inlayHints.push({
blockName: 'template',
offset: prop.exp.loc.start.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'),
});
}
else {
yield* interpolation;
}
}
else {
yield `() => {}`;
}
}
function* generateModelEventExpression(options, ctx, prop) {
if (prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const accessMark = ctx.accessLog.length;
const codes = [...(0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.verification, prop.exp.content, prop.exp.loc.start.offset, undefined, undefined, true)];
yield `// @ts-ignore${utils_2.newLine}`;
yield `(...[$event]) => {${utils_2.newLine}`;
yield* generateReasserts(options, ctx, accessMark);
yield* ctx.generateConditionGuards();
yield* codes;
yield ` = $event${utils_2.endOfLine}`;
yield `}`;
}
else {
yield `() => {}`;
}
}
// Assertion narrowing does not flow into nested closures for imports and
// `let`/`var` bindings (TS limitation), so re-assert those bindings at closure tops.
function* generateReasserts(options, ctx, accessMark) {
const reasserts = new Set();
const collect = (name) => {
if (options.reassertBindings.has(name) && !ctx.scopes.some(scope => scope.has(name))) {
reasserts.add(name);
}
};
for (const name of ctx.accessLog.slice(accessMark)) {
collect(name);
}
for (const condition of ctx.conditions) {
for (const name of condition.accesses) {
collect(name);
}
}
for (const name of reasserts) {
yield `${names_1.names.withDotValue}(${name}, ${(0, utils_2.getRefBrandArgument)(options.vueCompilerOptions, options.scriptLang)})${utils_2.endOfLine}`;
}
}
function isCompoundExpression(ts, ast) {
if (ast.statements.length === 0) {
return false;
}
if (ast.statements.length === 1 && ast.text[ast.endOfFileToken.pos - 1] !== ';') {
const statement = ast.statements[0];
if (ts.isExpressionStatement(statement)) {
const node = (0, utils_1.getUnwrappedExpression)(ts, statement.expression);
if (ts.isArrowFunction(node)
|| ts.isIdentifier(node)
|| ts.isElementAccessExpression(node)
|| ts.isPropertyAccessExpression(node)) {
return false;
}
}
else if (ts.isFunctionDeclaration(statement)) {
return false;
}
}
return true;
}
function isSingleExpression(ts, ast) {
if (ast.statements.length === 1 && ast.text[ast.endOfFileToken.pos - 1] !== ';') {
const statement = ast.statements[0];
if (ts.isExpressionStatement(statement)) {
return true;
}
}
return false;
}
//# sourceMappingURL=elementEvents.js.map
+11
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 FailedPropExpressions {
node: CompilerDOM.SimpleExpressionNode;
prefix: string;
suffix: string;
}
export declare function generateElementProps(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, props: CompilerDOM.ElementNode['props'], checkUnknownProps: boolean, failedPropExps?: FailedPropExpressions[]): Generator<Code>;
export declare function generatePropExp(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, prop: CompilerDOM.DirectiveNode, exp: CompilerDOM.SimpleExpressionNode | undefined): Generator<Code>;
+280
View File
@@ -0,0 +1,280 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateElementProps = generateElementProps;
exports.generatePropExp = generatePropExp;
const CompilerDOM = __importStar(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 names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const camelized_1 = require("../utils/camelized");
const unicode_1 = require("../utils/unicode");
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, checkUnknownProps, 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)}': ${(0, utils_1.asType)('any', options.scriptLang)} },`;
}
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.isDataAttribute(propName)) {
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 = getShouldCamelize(options, node, prop, propName);
const features = getPropsCodeFeatures(checkUnknownProps);
if (shouldSpread) {
yield `...{ `;
}
const boundary = yield* boundary_1.Boundary.start('template', prop.loc.start.offset, prop.loc.end.offset, codeFeatures_1.codeFeatures.verification);
if (prop.arg) {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, propName, prop.arg.loc.start.offset, features, shouldCamelize);
}
else {
const boundary2 = yield* boundary_1.Boundary.start('template', prop.loc.start.offset, prop.loc.start.offset + 'v-model'.length, codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
yield propName;
yield boundary2.end();
}
yield `: `;
const argLoc = prop.arg?.loc ?? prop.loc;
const boundary3 = yield* boundary_1.Boundary.start('template', argLoc.start.offset, argLoc.end.offset, codeFeatures_1.codeFeatures.verification);
yield* generatePropExp(options, ctx, prop, prop.exp);
yield boundary3.end();
yield boundary.end();
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
? `[${names_1.names.tryAsConstant}(\`\${${prop.arg.content}}Modifiers\`)]`
: (0, shared_1.camelize)(propName) + `Modifiers`
: `modelModifiers`;
yield* (0, elementDirectives_1.generateModifiers)(options, ctx, prop, propertyName);
yield utils_1.newLine;
}
}
else if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE) {
if (options.vueCompilerOptions.isDataAttribute(prop.name)) {
continue;
}
const shouldSpread = prop.name === 'style' || prop.name === 'class';
const shouldCamelize = getShouldCamelize(options, node, prop, prop.name);
const features = getPropsCodeFeatures(checkUnknownProps);
if (shouldSpread) {
yield `...{ `;
}
const boundary = yield* boundary_1.Boundary.start('template', prop.loc.start.offset, prop.loc.end.offset, codeFeatures_1.codeFeatures.verification);
const prefix = options.template.content.slice(prop.loc.start.offset, prop.loc.start.offset + 1);
if (prefix === '.' || prefix === '#') {
// Pug shorthand syntax
for (const char of prop.name) {
yield [char, 'template', prop.loc.start.offset, features];
}
}
else {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, prop.name, prop.loc.start.offset, features, shouldCamelize);
}
yield `: `;
if (prop.name === 'style') {
yield `{}`;
}
else if (prop.value) {
yield* generateAttrValue(prop.value, codeFeatures_1.codeFeatures.withoutNavigation);
}
else {
yield `true`;
}
yield boundary.end();
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') {
failedPropExps?.push({ node: prop.exp, prefix: `(`, suffix: `)` });
}
else {
const boundary = yield* boundary_1.Boundary.start('template', prop.exp.loc.start.offset, prop.exp.loc.end.offset, codeFeatures_1.codeFeatures.verification);
yield `...`;
yield* generatePropExp(options, ctx, prop, prop.exp);
yield boundary.end();
yield `,${utils_1.newLine}`;
}
}
}
}
function* generatePropExp(options, ctx, prop, exp) {
if (!exp) {
yield `{}`;
}
else if (prop.arg?.loc.start.offset !== prop.exp?.loc.start.offset) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.all, exp.loc.source, exp.loc.start.offset, `(`, `)`);
}
else {
const propVariableName = (0, shared_1.camelize)(exp.loc.source);
if (utils_1.identifierRE.test(propVariableName)) {
const codes = (0, camelized_1.generateCamelized)(exp.loc.source, 'template', exp.loc.start.offset, {
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletion,
__shorthandExpression: 'html',
});
yield* (0, interpolation_1.generateIdentifier)(options, ctx, codes, propVariableName, 'template', exp.loc.start.offset, exp.loc.end.offset);
ctx.inlayHints.push((0, inlayHints_1.createVBindShorthandInlayHintInfo)(prop.loc, propVariableName));
}
}
}
function* generateAttrValue(node, features) {
const quote = node.loc.source.startsWith("'") ? "'" : '"';
const [content, offset] = (0, shared_2.normalizeAttributeValue)(node);
yield quote;
yield* (0, unicode_1.generateUnicode)(content, offset, features);
yield quote;
}
function getShouldCamelize(options, node, prop, propName) {
return (node.tagType === CompilerDOM.ElementTypes.COMPONENT
|| node.tagType === CompilerDOM.ElementTypes.SLOT) && (prop.type !== CompilerDOM.NodeTypes.DIRECTIVE
|| prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && prop.arg.isStatic)
&& (0, shared_2.hyphenateAttr)(propName) === propName
&& (node.tagType === CompilerDOM.ElementTypes.SLOT
|| !options.vueCompilerOptions.isHtmlAttribute(propName));
}
function getPropsCodeFeatures(checkUnknownProps) {
return {
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletion,
...checkUnknownProps
? codeFeatures_1.codeFeatures.verification
: codeFeatures_1.codeFeatures.doNotReportTs2353AndTs2561,
__propsCompletion: true,
};
}
function getModelPropName(node, vueCompilerOptions) {
for (const modelName in vueCompilerOptions.experimentalModelPropName) {
const tags = vueCompilerOptions.experimentalModelPropName[modelName];
for (const tag in tags) {
if (node.tag === tag || node.tag === (0, shared_2.hyphenateTag)(tag)) {
const val = tags[tag];
if (typeof val === 'object') {
const arr = Array.isArray(val) ? val : [val];
for (const attrs of arr) {
let failed = false;
for (const attr in attrs) {
const attrNode = node.props.find(prop => prop.type === CompilerDOM.NodeTypes.ATTRIBUTE && prop.name === attr);
if (!attrNode || attrNode.value?.content !== attrs[attr]) {
failed = true;
break;
}
}
if (!failed) {
// all match
return modelName || undefined;
}
}
}
}
}
}
for (const modelName in vueCompilerOptions.experimentalModelPropName) {
const tags = vueCompilerOptions.experimentalModelPropName[modelName];
for (const tag in tags) {
if (node.tag === tag || node.tag === (0, shared_2.hyphenateTag)(tag)) {
const attrs = tags[tag];
if (attrs === true) {
return modelName || undefined;
}
}
}
}
return 'modelValue';
}
//# sourceMappingURL=elementProps.js.map
+105
View File
@@ -0,0 +1,105 @@
import type * as ts from 'typescript';
import type { Code, IRTemplate, VueCompilerOptions } from '../../types';
export interface TemplateCodegenOptions {
typescript: typeof ts;
vueCompilerOptions: VueCompilerOptions;
template: IRTemplate;
isVapor: boolean;
scriptLang: string;
importedComponents: Set<string>;
setupRefs: Set<string>;
setupConsts: Set<string>;
setupBindings: Set<string>;
dotValueBindings: Set<string>;
reassertBindings: Set<string>;
hasDefineSlots?: boolean;
propsAssignName?: string;
slotsAssignName?: string;
inheritAttrs: boolean;
componentName: string;
}
export { generate as generateTemplate };
declare function generate(options: TemplateCodegenOptions): {
getCommentInfo: () => {
ignoreError?: boolean;
expectError?: {
token: number;
node: import("@vue/compiler-dom").CommentNode;
};
generic?: {
content: string;
offset: number;
};
};
enter: (node: import("@vue/compiler-dom").RootNode | import("@vue/compiler-dom").TemplateChildNode | import("@vue/compiler-dom").SimpleExpressionNode) => boolean;
exit: () => Generator<Code>;
resolveCodeFeatures: (features: import("../../types").VueCodeInformation) => import("../../types").VueCodeInformation;
getInternalVariable: () => string;
scopes: {
has(value: string): boolean;
readonly size: number;
declare(...variables: string[]): void;
end(): Generator<Code, any, any>;
add(value: string): /*elided*/ any;
clear(): void;
delete(value: string): boolean;
forEach(callbackfn: (value: string, value2: string, set: Set<string>) => void, thisArg?: any): void;
[Symbol.iterator](): SetIterator<string>;
entries(): SetIterator<[string, string]>;
keys(): SetIterator<string>;
values(): SetIterator<string>;
readonly [Symbol.toStringTag]: string;
}[];
scope: () => {
has(value: string): boolean;
readonly size: number;
declare(...variables: string[]): void;
end(): Generator<Code, any, any>;
add(value: string): any;
clear(): void;
delete(value: string): boolean;
forEach(callbackfn: (value: string, value2: string, set: Set<string>) => void, thisArg?: any): void;
[Symbol.iterator](): SetIterator<string>;
entries(): SetIterator<[string, string]>;
keys(): SetIterator<string>;
values(): SetIterator<string>;
readonly [Symbol.toStringTag]: string;
};
contextAccesses: Map<string, Map<string, Set<number>>>;
dotValueAccesses: Set<string>;
accessLog: string[];
accessVariable: (source: string, name: string, offset?: number, dotValue?: boolean) => void;
generateAutoImport: () => Generator<Code>;
conditions: {
text: string;
accesses: string[];
}[];
generateConditionGuards: () => Generator<string, void, unknown>;
hoistVars: Map<string, string>;
getHoistVariable: (originalVar: string) => string;
generateHoistVariables: () => Generator<string, void, unknown>;
templateRefs: Map<string, {
typeExp: string;
offset: number;
}[]>;
addTemplateRef: (name: string, typeExp: string, offset: number) => void;
components: (() => string)[];
dollarVars: Set<string>;
inlayHints: import("../inlayHints").InlayHintInfo[];
generatedTypes: Set<string>;
inheritedAttrVars: Set<string>;
singleRootElTypes: Set<string>;
singleRootNodes: Set<import("@vue/compiler-dom").ElementNode | null>;
slots: {
name: string;
offset?: number;
tagRange: [number, number];
propsVar: string;
}[];
dynamicSlots: {
expVar: string;
propsVar: string;
}[];
inVFor: boolean;
codes: Code[];
};
+163
View File
@@ -0,0 +1,163 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplate = generate;
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const context_1 = require("./context");
const objectProperty_1 = require("./objectProperty");
const styleScopedClasses_1 = require("./styleScopedClasses");
const templateChild_1 = require("./templateChild");
function generate(options) {
// The references registry accumulates across codegen passes; start clean.
styleScopedClasses_1.references.delete(options.template);
const ctx = (0, context_1.createTemplateCodegenContext)();
const codeGenerator = generateWorker(options, ctx);
const codes = [];
for (const code of codeGenerator) {
if (typeof code === 'object') {
code[3] = ctx.resolveCodeFeatures(code[3]);
}
codes.push(code);
}
return { ...ctx, codes };
}
function* generateWorker(options, ctx) {
const scope = ctx.scope();
const { slotsAssignName, propsAssignName, vueCompilerOptions, template, } = options;
if (slotsAssignName) {
scope.declare(slotsAssignName);
}
if (propsAssignName) {
scope.declare(propsAssignName);
}
if (vueCompilerOptions.inferTemplateDollarSlots) {
ctx.dollarVars.add('$slots');
}
if (vueCompilerOptions.inferTemplateDollarAttrs) {
ctx.dollarVars.add('$attrs');
}
if (vueCompilerOptions.inferTemplateDollarRefs) {
ctx.dollarVars.add('$refs');
}
if (vueCompilerOptions.inferTemplateDollarEl) {
ctx.dollarVars.add('$el');
}
if (template.ast) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, template.ast);
}
yield* ctx.generateHoistVariables();
yield* generateSlotsType(options, ctx);
yield* generateInheritedAttrsType(options, ctx);
yield* generateTemplateRefsType(options, ctx);
yield* generateRootElType(options, ctx);
if (ctx.dollarVars.size) {
yield* (0, utils_1.generateTypedVar)('var', names_1.names.dollars, options.scriptLang, function* () {
yield `{${utils_1.newLine}`;
if (ctx.dollarVars.has('$slots')) {
const type = ctx.generatedTypes.has(names_1.names.Slots) ? names_1.names.Slots : `{}`;
yield `$slots: ${type}${utils_1.endOfLine}`;
}
if (ctx.dollarVars.has('$attrs')) {
yield `$attrs: import('${vueCompilerOptions.lib}').ComponentPublicInstance['$attrs']`;
if (ctx.generatedTypes.has(names_1.names.InheritedAttrs)) {
yield ` & ${names_1.names.InheritedAttrs}`;
}
yield utils_1.endOfLine;
}
if (ctx.dollarVars.has('$refs')) {
const type = ctx.generatedTypes.has(names_1.names.TemplateRefs) ? names_1.names.TemplateRefs : `{}`;
yield `$refs: ${type}${utils_1.endOfLine}`;
}
if (ctx.dollarVars.has('$el')) {
const type = ctx.generatedTypes.has(names_1.names.RootEl) ? names_1.names.RootEl : `any`;
yield `$el: ${type}${utils_1.endOfLine}`;
}
yield `} & { [K in keyof import('${vueCompilerOptions.lib}').ComponentPublicInstance]: unknown }`;
});
}
yield* scope.end();
}
function* generateSlotsType(options, ctx) {
if (options.hasDefineSlots) {
ctx.generatedTypes.add(names_1.names.Slots);
return;
}
if (!ctx.slots.length && !ctx.dynamicSlots.length) {
return;
}
ctx.generatedTypes.add(names_1.names.Slots);
yield* (0, utils_1.generateTypeAlias)(names_1.names.Slots, options.scriptLang, function* () {
yield `{}`;
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 {
const boundary = yield* boundary_1.Boundary.start('template', ...slot.tagRange, codeFeatures_1.codeFeatures.navigation);
yield `default`;
yield boundary.end();
}
yield `?: (props: typeof ${slot.propsVar}) => any }`;
}
});
}
function* generateInheritedAttrsType(options, ctx) {
if (!ctx.inheritedAttrVars.size) {
return;
}
ctx.generatedTypes.add(names_1.names.InheritedAttrs);
const type = [...ctx.inheritedAttrVars].map(name => `typeof ${name}`).join(` & `);
yield* (0, utils_1.generateTypeAlias)(names_1.names.InheritedAttrs, options.scriptLang, function* () {
yield options.vueCompilerOptions.checkRequiredFallthroughAttributes
? type
: `Partial<${type}>`;
});
}
function* generateTemplateRefsType(options, ctx) {
if (!ctx.templateRefs.size
|| !(options.vueCompilerOptions.inferTemplateDollarRefs
|| options.vueCompilerOptions.inferComponentDollarRefs
|| options.setupRefs.size)) {
return;
}
ctx.generatedTypes.add(names_1.names.TemplateRefs);
yield* (0, utils_1.generateTypeAlias)(names_1.names.TemplateRefs, options.scriptLang, function* () {
yield `{}`;
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 `)`;
}
}
});
}
function* generateRootElType(options, ctx) {
if (!ctx.singleRootElTypes.size || ctx.singleRootNodes.has(null)) {
return;
}
ctx.generatedTypes.add(names_1.names.RootEl);
yield* (0, utils_1.generateTypeAlias)(names_1.names.RootEl, options.scriptLang, function* () {
for (const type of ctx.singleRootElTypes) {
yield `${utils_1.newLine}| ${type}`;
}
});
}
//# sourceMappingURL=index.js.map
@@ -0,0 +1,15 @@
import type { Code, IRBlock, VueCodeInformation, VueCompilerOptions } from '../../types';
import type { TemplateCodegenContext } from './context';
export declare function generateInterpolation(options: IdentifierOptions & {
typescript: typeof import('typescript');
}, ctx: TemplateCodegenContext, block: IRBlock, features: VueCodeInformation, code: string, start: number, prefix?: string, suffix?: string, inNarrowing?: boolean): Generator<Code>;
interface IdentifierOptions {
setupRefs: Set<string>;
setupConsts: Set<string>;
setupBindings: Set<string>;
dotValueBindings: Set<string>;
vueCompilerOptions: VueCompilerOptions;
scriptLang: string;
}
export declare function generateIdentifier(options: IdentifierOptions, ctx: TemplateCodegenContext, codes: Iterable<Code>, name: string, source: string, start: number, end: number, isNarrowing?: boolean, inTypeQuery?: boolean, isNewOperand?: boolean): Generator<Code>;
export {};
+138
View File
@@ -0,0 +1,138 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateInterpolation = generateInterpolation;
exports.generateIdentifier = generateIdentifier;
const shared_1 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const bindingReferences_1 = require("./bindingReferences");
function* generateInterpolation(options, ctx, block, features, code, start, prefix = '', suffix = '', inNarrowing = false) {
if (prefix) {
yield prefix;
}
let prevEnd = 0;
for (const [name, offset, isShorthand, isNarrowing, inTypeQuery, isNewOperand] of forEachIdentifiers(options.typescript, ctx, block, code, prefix, suffix, inNarrowing)) {
if (isShorthand) {
yield* generateNonIdentifierCode(code.slice(prevEnd, offset + name.length), block.name, start + prevEnd, features, prevEnd > 0);
yield `: `;
}
else if (prevEnd < offset) {
yield* generateNonIdentifierCode(code.slice(prevEnd, offset), block.name, start + prevEnd, features, prevEnd > 0);
}
const codes = [[
name,
block.name,
start + offset,
isShorthand
? { ...features, __shorthandExpression: 'js' }
: features,
]];
yield* generateIdentifier(options, ctx, codes, name, block.name, start + offset, start + offset + name.length, isNarrowing, inTypeQuery, isNewOperand);
prevEnd = offset + name.length;
}
if (prevEnd < code.length) {
yield* generateNonIdentifierCode(code.slice(prevEnd), block.name, start + prevEnd, features, prevEnd > 0);
}
if (suffix) {
yield suffix;
}
}
/**
* Yield a code chunk, cutting the boundary character off as verification-only.
*
* Adjacent mappings share the boundary offset (closed interval), so both the
* neighbouring token's end and this chunk's start claim the same source offset.
* Downgrading the boundary character to verification-only keeps content-sensitive
* features (rename / navigation) from firing on the neighbouring chunk.
*/
function* generateNonIdentifierCode(code, source, offset, data, shouldCut = true) {
if (!code.length) {
return;
}
if (!shouldCut) {
yield [code, source, offset, data];
return;
}
yield [code.slice(0, 1), source, offset, { verification: data.verification }];
if (code.length > 1) {
yield [code.slice(1), source, offset + 1, data];
}
}
// Access strategy, in precedence order:
// - setup consts → direct reference
// - local-scope / global names → direct reference (the interpolation path
// filters these earlier; the v-bind shorthand path relies on this branch)
// - template refs → direct `.value`
// - dotValue bindings (narrowed at least once anywhere) → `.value` at
// every position; narrowing then works on the `.value` reference chain
// - other bindings → `__VLS_unwrap` (plain reads keep the original type)
// - otherwise → `__VLS_ctx.<name>`
function* generateIdentifier(options, ctx, codes, name, source, start, end, isNarrowing = false, inTypeQuery = false, isNewOperand = false) {
if (options.setupConsts.has(name) || (0, bindingReferences_1.shouldIdentifierSkipped)(ctx, name)) {
yield* codes;
}
else if (options.setupRefs.has(name)) {
yield* codes;
yield `.`;
const boundary = yield* boundary_1.Boundary.start(source, start, end, codeFeatures_1.codeFeatures.verification);
yield `value`;
yield boundary.end();
}
else if (options.setupBindings.has(name)) {
// First pass records narrowing accesses here; the second pass emits from dotValueBindings.
ctx.accessVariable(source, name, start, inTypeQuery || isNarrowing);
if (inTypeQuery || options.dotValueBindings.has(name)) {
yield* codes;
yield `.`;
const boundary = yield* boundary_1.Boundary.start(source, start, end, codeFeatures_1.codeFeatures.verification);
yield `value`;
yield boundary.end();
}
else {
// `new __VLS_unwrap(Foo)()` parses as `new (__VLS_unwrap(Foo)())`,
// whose target lacks a construct signature; keep the operand parenthesized.
if (isNewOperand) {
yield `(`;
}
yield `${names_1.names.unwrap}(`;
yield* codes;
yield `, ${(0, utils_1.getRefBrandArgument)(options.vueCompilerOptions, options.scriptLang)})`;
if (isNewOperand) {
yield `)`;
}
}
}
else {
// #1205, #1264
const boundary = yield* boundary_1.Boundary.start(source, start, end, codeFeatures_1.codeFeatures.verification);
if (ctx.dollarVars.has(name)) {
yield names_1.names.dollars;
}
else {
ctx.accessVariable(source, name, start);
yield names_1.names.ctx;
}
yield `.`;
yield* codes;
yield boundary.end();
}
}
function* forEachIdentifiers(ts, ctx, block, code, prefix, suffix, inNarrowing) {
if (utils_1.identifierRE.test(code) && !(0, bindingReferences_1.shouldIdentifierSkipped)(ctx, code)) {
yield [code, 0, false, inNarrowing, false, false];
return;
}
const scope = ctx.scope();
const ast = (0, utils_1.getTypeScriptAST)(ts, block, prefix + code + suffix);
for (const { id, isShorthand, isNarrowing, skipped, inTypeQuery, isNewOperand } of (0, bindingReferences_1.forEachDeclarations)(ts, ast, ast, ctx, scope, inNarrowing)) {
if (skipped) {
continue;
}
const text = (0, shared_1.getNodeText)(ts, id, ast);
yield [text, (0, shared_1.getStartEnd)(ts, id, ast).start - prefix.length, isShorthand, isNarrowing, inTypeQuery, isNewOperand];
}
scope.end();
}
//# sourceMappingURL=interpolation.js.map
@@ -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>;
+41
View File
@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateObjectProperty = generateObjectProperty;
const shared_1 = require("@vue/shared");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const camelized_1 = require("../utils/camelized");
const stringLiteralKey_1 = require("../utils/stringLiteralKey");
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, options.template, features, code.slice(1, -1), offset + 1, `[${names_1.names.tryAsConstant}(`, `)]`);
}
else {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, features, code, offset);
}
}
else if (shouldCamelize) {
if (utils_1.identifierRE.test((0, shared_1.camelize)(code))) {
yield* (0, camelized_1.generateCamelized)(code, 'template', offset, features);
}
else {
const boundary = yield* boundary_1.Boundary.start('template', offset, offset + code.length, features);
yield `'`;
yield* (0, camelized_1.generateCamelized)(code, 'template', offset, boundary.features);
yield `'`;
yield boundary.end();
}
}
else {
if (utils_1.identifierRE.test(code)) {
yield [code, 'template', offset, features];
}
else {
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(code, offset, features);
}
}
}
//# sourceMappingURL=objectProperty.js.map
@@ -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>;
+21
View File
@@ -0,0 +1,21 @@
"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 (code.startsWith('[') && code.endsWith(']')) {
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, features, code, offset);
}
else if (utils_1.identifierRE.test(code)) {
yield `.`;
yield [code, 'template', offset, features];
}
else {
yield `[`;
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(code, offset, features);
yield `]`;
}
}
//# sourceMappingURL=propertyAccess.js.map
+5
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>;
+144
View File
@@ -0,0 +1,144 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSlotOutlet = generateSlotOutlet;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const shared_1 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const inlayHints_1 = require("../inlayHints");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const elementProps_1 = require("./elementProps");
const interpolation_1 = require("./interpolation");
const propertyAccess_1 = require("./propertyAccess");
const templateChild_1 = require("./templateChild");
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 `${names_1.names.asFunctionalSlot}(`;
if (nameProp) {
let codes;
if (nameProp.type === CompilerDOM.NodeTypes.ATTRIBUTE && nameProp.value) {
const [content, offset] = (0, shared_1.normalizeAttributeValue)(nameProp.value);
codes = (0, propertyAccess_1.generatePropertyAccess)(options, ctx, content, 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']`];
}
const boundary = yield* boundary_1.Boundary.start('template', nameProp.loc.start.offset, nameProp.loc.end.offset, codeFeatures_1.codeFeatures.verification);
yield options.slotsAssignName ?? names_1.names.slots;
yield* codes;
yield boundary.end();
}
else {
const boundary = yield* boundary_1.Boundary.start('template', startTagOffset, startTagEndOffset, codeFeatures_1.codeFeatures.verification);
yield `${options.slotsAssignName ?? names_1.names.slots}[`;
const boundary2 = yield* boundary_1.Boundary.start('template', startTagOffset, startTagEndOffset, codeFeatures_1.codeFeatures.verification);
yield `'default'`;
yield boundary2.end();
yield `]`;
yield boundary.end();
}
yield `)(`;
const boundary = yield* boundary_1.Boundary.start('template', startTagOffset, startTagEndOffset, codeFeatures_1.codeFeatures.verification);
yield `{${utils_1.newLine}`;
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, node.props.filter(prop => prop !== nameProp), true);
yield `}`;
yield boundary.end();
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);
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],
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} = ${names_1.names.tryAsConstant}(`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, isShortHand
? codeFeatures_1.codeFeatures.withoutHighlightAndCompletion
: 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],
propsVar: ctx.getHoistVariable(propsVar),
});
}
}
for (const child of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, child);
}
}
//# sourceMappingURL=slotOutlet.js.map
@@ -0,0 +1,6 @@
import * as CompilerDOM from '@vue/compiler-dom';
import type { Code, IRBlock } from '../../types';
import type { TemplateCodegenOptions } from './index';
export declare const references: WeakMap<IRBlock, [version: string, [className: string, offset: number][]]>;
export declare function generateStyleScopedClassReferences({ template, typescript: ts }: TemplateCodegenOptions, node: CompilerDOM.ElementNode): Generator<Code>;
export declare function generateStyleScopedClassReference(block: IRBlock, className: string, offset: number, fullStart?: number): Generator<Code>;
@@ -0,0 +1,159 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.references = void 0;
exports.generateStyleScopedClassReferences = generateStyleScopedClassReferences;
exports.generateStyleScopedClassReference = generateStyleScopedClassReference;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const shared_1 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const escaped_1 = require("../utils/escaped");
const classNameEscapeRE = /([\\'])/;
// For language-service/lib/plugins/vue-scoped-class-links.ts usage
exports.references = new WeakMap();
function* generateStyleScopedClassReferences({ template, typescript: ts }, node) {
for (const prop of node.props) {
if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE
&& prop.name === 'class'
&& prop.value) {
const [text, start] = (0, shared_1.normalizeAttributeValue)(prop.value);
for (const [className, offset] of forEachClassName(text)) {
yield* generateStyleScopedClassReference(template, className, start + offset);
}
}
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 ast = (0, utils_1.getTypeScriptAST)(ts, template, content);
const literals = [];
for (const node of (0, utils_1.forEachNode)(ts, ast)) {
if (!ts.isExpressionStatement(node)
|| !ts.isParenthesizedExpression(node.expression)) {
continue;
}
const { expression } = node.expression;
if (ts.isStringLiteralLike(expression)) {
literals.push(expression);
}
else if (ts.isArrayLiteralExpression(expression)) {
yield* walkArrayLiteral(expression);
}
else if (ts.isObjectLiteralExpression(expression)) {
yield* walkObjectLiteral(expression);
}
}
for (const literal of literals) {
const start = literal.end - literal.text.length - 1 + startOffset;
for (const [className, offset] of forEachClassName(literal.text)) {
yield* generateStyleScopedClassReference(template, className, start + offset);
}
}
function* walkArrayLiteral(node) {
const { elements } = node;
for (const element of elements) {
if (ts.isStringLiteralLike(element)) {
literals.push(element);
}
else if (ts.isObjectLiteralExpression(element)) {
yield* walkObjectLiteral(element);
}
}
}
function* walkObjectLiteral(node) {
const { properties } = node;
for (const property of properties) {
if (ts.isPropertyAssignment(property)) {
const { name } = property;
if (ts.isIdentifier(name)) {
const text = (0, shared_1.getNodeText)(ts, name, ast);
yield* generateStyleScopedClassReference(template, text, name.end - text.length + startOffset);
}
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)) {
const text = (0, shared_1.getNodeText)(ts, property.name, ast);
yield* generateStyleScopedClassReference(template, text, property.name.end - text.length + startOffset);
}
}
}
}
}
}
function* forEachClassName(content) {
let offset = 0;
for (const className of content.split(' ')) {
yield [className, offset];
offset += className.length + 1;
}
}
function* generateStyleScopedClassReference(block, className, offset, fullStart = offset) {
if (!className) {
yield `/** @type {${names_1.names.StyleScopedClasses}['`;
yield ['', 'template', offset, codeFeatures_1.codeFeatures.completion];
yield `']} */${utils_1.endOfLine}`;
return;
}
const cache = exports.references.get(block);
if (!cache || cache[0] !== block.content) {
const arr = [];
exports.references.set(block, [block.content, arr]);
arr.push([className, offset]);
}
else {
cache[1].push([className, offset]);
}
yield `/** @type {${names_1.names.StyleScopedClasses}[`;
const boundary = yield* boundary_1.Boundary.start(block.name, fullStart, offset + className.length, codeFeatures_1.codeFeatures.navigationAndCompletion);
yield `'`;
yield* (0, escaped_1.generateEscaped)(className, block.name, offset, boundary.features, classNameEscapeRE);
yield `'`;
yield boundary.end();
yield `]} */${utils_1.endOfLine}`;
}
//# sourceMappingURL=styleScopedClasses.js.map
@@ -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 generateTemplateChild(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode, enterNode?: boolean, treatTemplateAsFragment?: boolean): Generator<Code>;
export declare function parseInterpolationNode(node: CompilerDOM.InterpolationNode, template: string): readonly [string, number];
+148
View File
@@ -0,0 +1,148 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTemplateChild = generateTemplateChild;
exports.parseInterpolationNode = parseInterpolationNode;
const CompilerDOM = __importStar(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 interpolation_1 = require("./interpolation");
const slotOutlet_1 = require("./slotOutlet");
const vFor_1 = require("./vFor");
const vIf_1 = require("./vIf");
const vSlot_1 = require("./vSlot");
function* generateTemplateChild(options, ctx, node, enterNode = true, treatTemplateAsFragment = false) {
if (enterNode && !ctx.enter(node)) {
return;
}
if (node.type === CompilerDOM.NodeTypes.ROOT) {
for (const item of collectSingleRootNodes(options, node.children)) {
ctx.singleRootNodes.add(item);
}
for (const child of node.children) {
yield* generateTemplateChild(options, ctx, child);
}
}
else if (node.type === CompilerDOM.NodeTypes.ELEMENT) {
if (node.tagType === CompilerDOM.ElementTypes.SLOT) {
yield* (0, slotOutlet_1.generateSlotOutlet)(options, ctx, node);
}
else {
const slotDir = node.props.find(CompilerDOM.isVSlot);
if (node.tagType === CompilerDOM.ElementTypes.TEMPLATE && ctx.components.length && slotDir) {
yield* (0, vSlot_1.generateVSlot)(options, ctx, node, slotDir, ctx.components.at(-1)());
}
else if (node.tagType === CompilerDOM.ElementTypes.TEMPLATE && treatTemplateAsFragment) {
yield* (0, element_1.generateFragment)(options, ctx, node);
}
else if (node.tagType === CompilerDOM.ElementTypes.COMPONENT) {
yield* (0, element_1.generateComponent)(options, ctx, node);
}
else {
yield* (0, element_1.generateElement)(options, ctx, node);
}
}
}
else if (node.type === CompilerDOM.NodeTypes.COMPOUND_EXPRESSION) {
// {{ ... }} {{ ... }}
for (const child of node.children) {
if (typeof child !== 'object') {
continue;
}
yield* generateTemplateChild(options, ctx, child, false);
}
}
else if (node.type === CompilerDOM.NodeTypes.INTERPOLATION) {
// {{ ... }}
const [content, start] = parseInterpolationNode(node, options.template.content);
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.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);
}
if (enterNode) {
yield* ctx.exit();
}
}
function* collectSingleRootNodes(options, children, treatTemplateAsFragment = false) {
// Exclude the effect of comments on the root node
children = children.filter(node => node.type !== CompilerDOM.NodeTypes.COMMENT);
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, true);
}
return;
}
else if (child.type !== CompilerDOM.NodeTypes.ELEMENT) {
return;
}
if (child.tagType === CompilerDOM.ElementTypes.TEMPLATE && treatTemplateAsFragment) {
yield* collectSingleRootNodes(options, child.children);
return;
}
yield child;
const tag = (0, shared_1.hyphenateTag)(child.tag);
if (options.vueCompilerOptions.fallthroughComponentNames.includes(tag)) {
yield* collectSingleRootNodes(options, child.children);
}
}
function parseInterpolationNode(node, template) {
let start = node.content.loc.start.offset;
let end = node.content.loc.end.offset;
// fix https://github.com/vuejs/language-tools/issues/1787
while (template[start - 1]?.trim() === '') {
start--;
}
while (template[end]?.trim() === '') {
end++;
}
return [template.slice(start, end), start];
}
//# sourceMappingURL=templateChild.js.map
+12
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;
};
+152
View File
@@ -0,0 +1,152 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVFor = generateVFor;
exports.parseVForNode = parseVForNode;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const collectBindings_1 = require("../../utils/collectBindings");
const shared_1 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const interpolation_1 = require("./interpolation");
const templateChild_1 = require("./templateChild");
function* generateVFor(options, ctx, node) {
const { source } = node.parseResult;
const { leftExpressionRange, leftExpressionText } = parseVForNode(node);
const scope = ctx.scope();
let bindingNames = [];
const defaultInitializerRanges = [];
if (leftExpressionRange && leftExpressionText) {
const wrap = `const [`;
const collectAst = (0, utils_1.getTypeScriptAST)(options.typescript, options.template, `${wrap}${leftExpressionText}]`);
bindingNames = (0, collectBindings_1.collectBindingNames)(options.typescript, collectAst, collectAst);
const declaration = collectAst.statements[0].declarationList.declarations[0];
const initializers = [];
collectDefaultInitializers(options.typescript, declaration.name, initializers);
for (const initializer of initializers) {
const { start, end } = (0, shared_1.getStartEnd)(options.typescript, initializer, collectAst);
defaultInitializerRanges.push([start - wrap.length, end - wrap.length]);
}
defaultInitializerRanges.sort((a, b) => a[0] - b[0]);
}
// Evaluate the source before the loop bindings enter scope (`v-for="x in x"` reads the outer `x`);
// destructuring defaults (`{ a, b = a }`) are interpolated after the declaration to see the sibling aliases.
let sourceAlias;
if (source.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
sourceAlias = ctx.getInternalVariable();
// tryAsConstant keeps inline literal sources from widening to `number[]` (#6067).
yield `const ${sourceAlias} = ${names_1.names.tryAsConstant}(`;
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.all, source.content, source.loc.start.offset, `(`, `)`);
yield `)`;
yield utils_1.endOfLine;
}
scope.declare(...bindingNames);
yield `for (const [`;
if (leftExpressionRange && leftExpressionText) {
let lastOffset = 0;
for (const [start, end] of defaultInitializerRanges) {
if (start > lastOffset) {
yield [
leftExpressionText.slice(lastOffset, start),
'template',
leftExpressionRange.start + lastOffset,
codeFeatures_1.codeFeatures.all,
];
}
yield* (0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.all, leftExpressionText.slice(start, end), leftExpressionRange.start + start);
lastOffset = end;
}
if (lastOffset < leftExpressionText.length) {
yield [
leftExpressionText.slice(lastOffset),
'template',
leftExpressionRange.start + lastOffset,
codeFeatures_1.codeFeatures.all,
];
}
}
yield `] of `;
if (sourceAlias !== undefined) {
yield `${names_1.names.vFor}(${names_1.names.nonNull}(`;
yield sourceAlias;
yield `))`; // #3102
}
else {
yield (0, utils_1.asType)('any', options.scriptLang);
}
yield `) {${utils_1.newLine}`;
const { inVFor } = ctx;
ctx.inVFor = true;
for (const child of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, child, false, true);
}
ctx.inVFor = inVFor;
yield* scope.end();
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,
};
}
function collectDefaultInitializers(ts, pattern, out) {
if (ts.isIdentifier(pattern)) {
return;
}
for (const element of pattern.elements) {
if (!ts.isBindingElement(element)) {
continue;
}
if (!ts.isIdentifier(element.name)) {
collectDefaultInitializers(ts, element.name, out);
}
if (element.initializer) {
out.push(element.initializer);
}
}
}
//# sourceMappingURL=vFor.js.map
+5
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>;
+77
View File
@@ -0,0 +1,77 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVIf = generateVIf;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const muggle_string_1 = require("muggle-string");
const codeFeatures_1 = require("../codeFeatures");
const utils_1 = require("../utils");
const interpolation_1 = require("./interpolation");
const templateChild_1 = require("./templateChild");
function* generateVIf(options, ctx, node) {
const originalBlockConditionsLength = ctx.conditions.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 accessMark = ctx.accessLog.length;
const codes = [...(0, interpolation_1.generateInterpolation)(options, ctx, options.template, codeFeatures_1.codeFeatures.all, branch.condition.content, branch.condition.loc.start.offset, `(`, `)`, true)];
yield* codes;
ctx.conditions.push({ text: (0, muggle_string_1.toString)(codes), accesses: ctx.accessLog.slice(accessMark) });
addedBlockCondition = true;
yield ` `;
}
yield `{${utils_1.newLine}`;
for (const child of branch.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, child, i !== 0, true);
}
yield `}${utils_1.newLine}`;
if (addedBlockCondition) {
const condition = ctx.conditions[ctx.conditions.length - 1];
condition.text = `!${condition.text}`;
}
}
ctx.conditions.length = originalBlockConditionsLength;
}
//# sourceMappingURL=vIf.js.map
+5
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, ctxVar: string): Generator<Code>;
+140
View File
@@ -0,0 +1,140 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVSlot = generateVSlot;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const muggle_string_1 = require("muggle-string");
const collectBindings_1 = require("../../utils/collectBindings");
const codeFeatures_1 = require("../codeFeatures");
const names_1 = require("../names");
const utils_1 = require("../utils");
const boundary_1 = require("../utils/boundary");
const interpolation_1 = require("./interpolation");
const objectProperty_1 = require("./objectProperty");
const templateChild_1 = require("./templateChild");
function* generateVSlot(options, ctx, node, slotDir, ctxVar) {
const slotVar = ctx.getInternalVariable();
if (slotDir) {
yield `{${utils_1.newLine}`;
yield `const { `;
if (slotDir.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && slotDir.arg.content) {
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, slotDir.arg.loc.source, slotDir.arg.loc.start.offset, slotDir.arg.isStatic ? codeFeatures_1.codeFeatures.withoutHighlight : codeFeatures_1.codeFeatures.all, false, true);
}
else {
const boundary = yield* boundary_1.Boundary.start('template', slotDir.loc.start.offset, slotDir.loc.start.offset + (slotDir.rawName?.length ?? 0), codeFeatures_1.codeFeatures.withoutHighlightAndCompletion);
yield `default`;
yield boundary.end();
}
}
else {
yield `const { `;
// #932: reference for implicit default slot
const boundary = yield* boundary_1.Boundary.start('template', node.loc.start.offset, node.loc.end.offset, codeFeatures_1.codeFeatures.navigation);
yield `default`;
yield boundary.end();
}
yield `: ${slotVar} } = ${names_1.names.nonNull}(${ctxVar}.slots)${utils_1.endOfLine}`;
const scope = ctx.scope();
if (slotDir?.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const slotAst = (0, utils_1.getTypeScriptAST)(options.typescript, options.template, `(${slotDir.exp.content}) => {}`);
yield* generateSlotParameters(options, ctx, slotAst, slotDir.exp, slotVar);
scope.declare(...(0, collectBindings_1.collectBindingNames)(options.typescript, slotAst, slotAst));
}
for (const child of node.children) {
yield* (0, templateChild_1.generateTemplateChild)(options, ctx, child);
}
yield* scope.end();
if (slotDir) {
let isStatic = true;
if (slotDir.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
isStatic = slotDir.arg.isStatic;
}
yield `}${utils_1.newLine}`;
if (isStatic && !slotDir.arg) {
if (slotDir.loc.source.startsWith('#') || slotDir.loc.source.startsWith('v-slot:')) {
yield `/** @type {NonNullable<typeof ${ctxVar}['slots']>['`;
yield [
'',
'template',
slotDir.loc.start.offset + (slotDir.loc.source.startsWith('#')
? '#'.length
: 'v-slot:'.length),
codeFeatures_1.codeFeatures.completion,
];
yield `']} */${utils_1.endOfLine}`;
}
}
}
}
function* generateSlotParameters(options, ctx, ast, exp, slotVar) {
const { typescript: 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, options.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 `] = ${names_1.names.vSlot}(${names_1.names.nonNull}(${slotVar})`;
if (types.some(t => t)) {
yield `, `;
const boundary = yield* boundary_1.Boundary.start('template', exp.loc.start.offset, exp.loc.end.offset, codeFeatures_1.codeFeatures.verification);
yield `(`;
yield* types.flatMap(type => type ? [`_`, type, `, `] : `_, `);
yield (0, utils_1.isTsLang)(options.scriptLang) ? `) => [] as any` : `) => /** @type {any} */ ([])`;
yield boundary.end();
}
yield `)${utils_1.endOfLine}`;
}
//# sourceMappingURL=vSlot.js.map
+9
View File
@@ -0,0 +1,9 @@
import type { Code, VueCodeInformation } from '../../types';
export declare class Boundary {
private source;
private endOffset;
features: VueCodeInformation;
private constructor();
static start(source: string, start: number, end: number, features: VueCodeInformation): Generator<Code, Boundary>;
end(): Code;
}
+20
View File
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Boundary = void 0;
class Boundary {
constructor(source, endOffset, features) {
this.source = source;
this.endOffset = endOffset;
this.features = features;
}
static *start(source, start, end, features) {
features = { ...features, __combineToken: Symbol() };
yield [``, source, start, features];
return new Boundary(source, end, features);
}
end() {
return [``, this.source, this.endOffset, this.features];
}
}
exports.Boundary = Boundary;
//# sourceMappingURL=boundary.js.map
+2
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>;
+23
View File
@@ -0,0 +1,23 @@
"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('-');
if (!features.__combineToken) {
features = { ...features, __combineToken: Symbol() };
}
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, features];
}
}
offset += part.length + 1;
}
}
//# sourceMappingURL=camelized.js.map
+2
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>;
+20
View File
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateEscaped = generateEscaped;
function* generateEscaped(text, source, offset, features, escapeTarget) {
const parts = text.split(escapeTarget);
if (!features.__combineToken) {
features = { ...features, __combineToken: Symbol() };
}
let isEscapeTarget = false;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (isEscapeTarget) {
yield `\\`;
}
yield [part, source, offset, features];
offset += part.length;
isEscapeTarget = !isEscapeTarget;
}
}
//# sourceMappingURL=escaped.js.map
+13
View File
@@ -0,0 +1,13 @@
import type * as ts from 'typescript';
import type { Code, IRBlock, IRScript, IRScriptSetup, VueCodeInformation, VueCompilerOptions } from '../../types';
export declare const newLine = "\n";
export declare const endOfLine = ";\n";
export declare const identifierRE: RegExp;
export declare function isTsLang(lang: string): boolean;
export declare function asType(type: string, lang: string): string;
export declare function generateTypedVar(kind: 'let' | 'var', name: string, lang: string, type: () => Generator<Code>): Generator<Code>;
export declare function generateTypeAlias(name: string, lang: string, type: () => Generator<Code>): Generator<Code>;
export declare function getRefBrandArgument(vueCompilerOptions: VueCompilerOptions, lang: string): string;
export declare function getTypeScriptAST(ts: typeof import('typescript'), block: IRBlock, text: string): ts.SourceFile;
export declare function generateSfcBlockSection(block: IRScript | IRScriptSetup, start: number, end: number, features: VueCodeInformation): Generator<Code>;
export declare function forEachNode(ts: typeof import('typescript'), node: ts.Node): Generator<ts.Node>;
+109
View File
@@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.identifierRE = exports.endOfLine = exports.newLine = void 0;
exports.isTsLang = isTsLang;
exports.asType = asType;
exports.generateTypedVar = generateTypedVar;
exports.generateTypeAlias = generateTypeAlias;
exports.getRefBrandArgument = getRefBrandArgument;
exports.getTypeScriptAST = getTypeScriptAST;
exports.generateSfcBlockSection = generateSfcBlockSection;
exports.forEachNode = forEachNode;
const codeFeatures_1 = require("../codeFeatures");
exports.newLine = `\n`;
exports.endOfLine = `;${exports.newLine}`;
exports.identifierRE = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
function isTsLang(lang) {
return lang === 'ts' || lang === 'tsx';
}
// `{} as T` in TS; `/** @type {T} */ ({})` in JS. The JSDoc cast keeps the
// same assertion semantics under checkJs, and requires no type-only syntax.
function asType(type, lang) {
return isTsLang(lang) ? `{} as ${type}` : `/** @type {${type}} */ ({})`;
}
// `let name!: T;` in TS; `var name = /** @type {T} */ ({});` in JS.
function* generateTypedVar(kind, name, lang, type) {
if (isTsLang(lang)) {
yield `${kind} ${name}!: `;
yield* type();
yield exports.endOfLine;
}
else {
yield `var ${name} = /** @type {`;
yield* type();
yield `} */ ({})${exports.endOfLine}`;
}
}
// `type name = T;` in TS; `/** @typedef {T} name */;` in JS.
function* generateTypeAlias(name, lang, type) {
if (isTsLang(lang)) {
yield `type ${name} = `;
yield* type();
yield exports.endOfLine;
}
else {
yield `/** @typedef {`;
yield* type();
yield `} ${name} */${exports.endOfLine}`;
}
}
// The phantom argument that carries the component library's `Ref` brand into
// `__VLS_unwrap` / `__VLS_withDotValue`; the helper declarations cannot
// resolve the library import themselves.
function getRefBrandArgument(vueCompilerOptions, lang) {
return asType(`import('${vueCompilerOptions.lib}').Ref<unknown>`, lang);
}
const cacheMaps = new WeakMap();
function getTypeScriptAST(ts, block, text) {
if (!cacheMaps.has(block)) {
cacheMaps.set(block, [block.content, new Map()]);
}
const cacheMap = cacheMaps.get(block);
if (cacheMap[0] !== block.content) {
cacheMap[0] = block.content;
for (const [key, info] of cacheMap[1]) {
if (info[1]) {
info[1] = 0;
}
else {
cacheMap[1].delete(key);
}
}
}
const cache = cacheMap[1].get(text);
if (cache) {
cache[1]++;
return cache[0];
}
const ast = ts.createSourceFile('/dummy.ts', text, 99);
cacheMap[1].set(text, [ast, 1]);
return ast;
}
function* generateSfcBlockSection(block, start, end, features) {
const text = block.content.slice(start, end);
yield [text, block.name, start, features];
// #3632
if ('parseDiagnostics' in block.ast) {
const textEnd = text.trimEnd().length;
for (const diag of block.ast.parseDiagnostics) {
const diagStart = diag.start;
const diagEnd = diag.start + diag.length;
if (diagStart >= textEnd && diagEnd <= end) {
yield `;`;
yield ['', block.name, end, codeFeatures_1.codeFeatures.verification];
yield exports.newLine;
break;
}
}
}
}
function* forEachNode(ts, node) {
const children = [];
ts.forEachChild(node, child => {
children.push(child);
});
for (const child of children) {
yield child;
}
}
//# sourceMappingURL=index.js.map
+3
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>;
+27
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;
}
else {
yield `{${index_1.newLine}`;
for (const code of codes) {
yield `...`;
yield code;
yield `,${index_1.newLine}`;
}
yield `}`;
}
}
//# sourceMappingURL=merge.js.map
@@ -0,0 +1,2 @@
import type { Code, VueCodeInformation } from '../../types';
export declare function generateStringLiteralKey(code: string, offset: number, features: VueCodeInformation): Generator<Code>;
+12
View File
@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateStringLiteralKey = generateStringLiteralKey;
const boundary_1 = require("./boundary");
function* generateStringLiteralKey(code, offset, features) {
const boundary = yield* boundary_1.Boundary.start('template', offset, offset + code.length, features);
yield `'`;
yield [code, 'template', offset, boundary.features];
yield `'`;
yield boundary.end();
}
//# sourceMappingURL=stringLiteralKey.js.map
+8
View File
@@ -0,0 +1,8 @@
import type { Code } from '../../types';
export interface CodeTransform {
range: [start: number, end: number];
generate(): Iterable<Code>;
}
export declare function replace(start: number, end: number, replacement: () => Iterable<Code>): CodeTransform;
export declare function insert(position: number, insertion: () => Iterable<Code>): CodeTransform;
export declare function generateCodeWithTransforms(start: number, end: number, transforms: CodeTransform[], section: (start: number, end: number) => Iterable<Code>): Generator<Code>;
+27
View File
@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.replace = replace;
exports.insert = insert;
exports.generateCodeWithTransforms = generateCodeWithTransforms;
function replace(start, end, replacement) {
return {
range: [start, end],
generate: replacement,
};
}
function insert(position, insertion) {
return {
range: [position, position],
generate: insertion,
};
}
function* generateCodeWithTransforms(start, end, transforms, section) {
const sortedTransforms = transforms.sort((a, b) => a.range[0] - b.range[0]);
for (const { range, generate } of sortedTransforms) {
yield* section(start, range[0]);
yield* generate();
start = range[1];
}
yield* section(start, end);
}
//# sourceMappingURL=transform.js.map
+2
View File
@@ -0,0 +1,2 @@
import type { Code, VueCodeInformation } from '../../types';
export declare function generateUnicode(code: string, offset: number, features: VueCodeInformation): Generator<Code>;
+27
View File
@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateUnicode = generateUnicode;
const boundary_1 = require("./boundary");
function* generateUnicode(code, offset, features) {
if (needToUnicode(code)) {
const boundary = yield* boundary_1.Boundary.start('template', offset, offset + code.length, features);
yield toUnicode(code);
yield boundary.end();
}
else {
yield [code, 'template', offset, features];
}
}
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