"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.walkElementNodes = exports.generate = void 0; const language_core_1 = require("@volar/language-core"); const CompilerDOM = require("@vue/compiler-dom"); const shared_1 = require("@vue/shared"); const minimatch_1 = require("minimatch"); const muggle = require("muggle-string"); const shared_2 = require("../utils/shared"); const transform_1 = require("../utils/transform"); const capabilitiesPresets = { all: language_core_1.FileRangeCapabilities.full, allWithHiddenParam: { ...language_core_1.FileRangeCapabilities.full, __hint: { setting: 'vue.inlayHints.inlineHandlerLeading', label: '$event =>', 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'), paddingRight: true, } /* TODO */ }, noDiagnostic: { ...language_core_1.FileRangeCapabilities.full, diagnostic: false }, diagnosticOnly: { diagnostic: true }, tagHover: { hover: true }, event: { hover: true, diagnostic: true }, tagReference: { references: true, definition: true, rename: { normalize: undefined, apply: noEditApply } }, attr: { hover: true, diagnostic: true, references: true, definition: true, rename: true }, attrReference: { references: true, definition: true, rename: true }, slotProp: { references: true, definition: true, rename: true, diagnostic: true }, scopedClassName: { references: true, definition: true, rename: true, completion: true }, slotName: { hover: true, diagnostic: true, references: true, definition: true, completion: true }, slotNameExport: { hover: true, diagnostic: true, references: true, definition: true, /* referencesCodeLens: true */ }, refAttr: { references: true, definition: true, rename: true }, }; const formatBrackets = { normal: ['`${', '}`;'], // fix https://github.com/vuejs/language-tools/issues/3572 params: ['(', ') => {}'], // fix https://github.com/vuejs/language-tools/issues/1210 // fix https://github.com/vuejs/language-tools/issues/2305 curly: ['0 +', '+ 0;'], event: ['() => ', ';'], }; const validTsVarReg = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; const colonReg = /:/g; // @ts-ignore const transformContext = { onError: () => { }, helperString: str => str.toString(), replaceNode: () => { }, cacheHandlers: false, prefixIdentifiers: false, scopes: { vFor: 0, vOnce: 0, vPre: 0, vSlot: 0, }, expressionPlugins: ['typescript'], }; function generate(ts, compilerOptions, vueCompilerOptions, template, shouldGenerateScopedClasses, stylesScopedClasses, hasScriptSetupSlots, slotsAssignName, propsAssignName, codegenStack) { const nativeTags = new Set(vueCompilerOptions.nativeTags); const [codes, codeStacks] = codegenStack ? muggle.track([]) : [[], []]; const [formatCodes, formatCodeStacks] = codegenStack ? muggle.track([]) : [[], []]; const [cssCodes, cssCodeStacks] = codegenStack ? muggle.track([]) : [[], []]; const slots = new Map(); const slotExps = new Map(); const tagNames = collectTagOffsets(); const localVars = new Map(); const tempVars = []; const accessedGlobalVariables = new Set(); const scopedClasses = []; const blockConditions = []; const hasSlotElements = new Set(); const componentCtxVar2EmitEventsVar = new Map(); let hasSlot = false; let elementIndex = 0; let ignoreStart; let expectedErrorStart; let expectedErrorNode; if (slotsAssignName) { localVars.set(slotsAssignName, 1); } if (propsAssignName) { localVars.set(propsAssignName, 1); } generatePreResolveComponents(); if (template.ast) { visitNode(template.ast, undefined, undefined, undefined); } generateStyleScopedClasses(); if (!hasScriptSetupSlots) { codes.push('var __VLS_slots!:', ...createSlotsTypeCode(), ';\n'); } generateAutoImportCompletionCode(); return { codes, codeStacks, formatCodes, formatCodeStacks, cssCodes, cssCodeStacks, tagNames, accessedGlobalVariables, hasSlot, }; function createSlotsTypeCode() { const codes = []; for (const [exp, slot] of slotExps) { hasSlot = true; codes.push(`Partial, (_: typeof ${slot.varName}) => any>> &\n`); } codes.push(`{\n`); for (const [name, slot] of slots) { hasSlot = true; codes.push(...createObjectPropertyCode([ name, 'template', slot.loc, { ...capabilitiesPresets.slotNameExport, referencesCodeLens: true, }, ], slot.nodeLoc)); codes.push(`?(_: typeof ${slot.varName}): any,\n`); } codes.push(`}`); return codes; } function generateStyleScopedClasses() { codes.push(`if (typeof __VLS_styleScopedClasses === 'object' && !Array.isArray(__VLS_styleScopedClasses)) {\n`); for (const { className, offset } of scopedClasses) { codes.push(`__VLS_styleScopedClasses[`); codes.push(...createStringLiteralKeyCode([ className, 'template', offset, { ...capabilitiesPresets.scopedClassName, displayWithLink: stylesScopedClasses.has(className), }, ])); codes.push(`];\n`); } codes.push('}\n'); } function toCanonicalComponentName(tagText) { return validTsVarReg.test(tagText) ? tagText : (0, shared_1.capitalize)((0, shared_1.camelize)(tagText.replace(colonReg, '-'))); } function getPossibleOriginalComponentName(tagText) { return [...new Set([ // order is important: https://github.com/vuejs/language-tools/issues/2010 (0, shared_1.capitalize)((0, shared_1.camelize)(tagText)), (0, shared_1.camelize)(tagText), tagText, ])]; } function generatePreResolveComponents() { codes.push(`let __VLS_resolvedLocalAndGlobalComponents!: {}\n`); for (const tagName in tagNames) { if (nativeTags.has(tagName)) continue; const isNamespacedTag = tagName.indexOf('.') >= 0; if (isNamespacedTag) continue; codes.push(`& __VLS_WithComponent<'${toCanonicalComponentName(tagName)}', typeof __VLS_localComponents, `, // order is important: https://github.com/vuejs/language-tools/issues/2010 `"${(0, shared_1.capitalize)((0, shared_1.camelize)(tagName))}", `, `"${(0, shared_1.camelize)(tagName)}", `, `"${tagName}"`, '>\n'); } codes.push(`;\n`); for (const tagName in tagNames) { const tagOffsets = tagNames[tagName]; const tagRanges = tagOffsets.map(offset => [offset, offset + tagName.length]); const names = nativeTags.has(tagName) ? [tagName] : getPossibleOriginalComponentName(tagName); for (const name of names) { for (const tagRange of tagRanges) { codes.push(nativeTags.has(tagName) ? '__VLS_intrinsicElements' : '__VLS_components', ...createPropertyAccessCode([ name, 'template', tagRange, { ...capabilitiesPresets.tagReference, rename: { normalize: tagName === name ? capabilitiesPresets.tagReference.rename.normalize : camelizeComponentName, apply: getTagRenameApply(tagName), }, ...nativeTags.has(tagName) ? { ...capabilitiesPresets.tagHover, ...capabilitiesPresets.diagnosticOnly, } : {}, }, ]), ';'); } } codes.push('\n'); if (nativeTags.has(tagName)) continue; const isNamespacedTag = tagName.indexOf('.') >= 0; if (isNamespacedTag) continue; codes.push('// @ts-ignore\n', // #2304 '['); const validName = toCanonicalComponentName(tagName); for (const tagRange of tagRanges) { codes.push([ validName, 'template', tagRange, { completion: { additional: true, autoImportOnly: true, }, }, ]); codes.push(','); } codes.push(`];\n`); } } function collectTagOffsets() { const tagOffsetsMap = {}; if (!template.ast) { return tagOffsetsMap; } walkElementNodes(template.ast, node => { if (node.tag === 'slot') { // ignore } else if (node.tag === 'component' || node.tag === 'Component') { for (const prop of node.props) { if (prop.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */ && prop.name === 'is' && prop.value) { const tag = prop.value.content; tagOffsetsMap[tag] ??= []; tagOffsetsMap[tag].push(prop.value.loc.start.offset + prop.value.loc.source.lastIndexOf(tag)); break; } } } else { tagOffsetsMap[node.tag] ??= []; const offsets = tagOffsetsMap[node.tag]; const source = template.content.substring(node.loc.start.offset); const startTagOffset = node.loc.start.offset + source.indexOf(node.tag); offsets.push(startTagOffset); // start tag if (!node.isSelfClosing && template.lang === 'html') { const endTagOffset = node.loc.start.offset + node.loc.source.lastIndexOf(node.tag); if (endTagOffset !== startTagOffset) { offsets.push(endTagOffset); // end tag } } } }); return tagOffsetsMap; } function resolveComment() { if (ignoreStart !== undefined) { for (let i = ignoreStart; i < codes.length; i++) { const code = codes[i]; if (typeof code === 'string') { continue; } const cap = code[3]; if (cap.diagnostic) { code[3] = { ...cap, diagnostic: false, }; } } ignoreStart = undefined; } if (expectedErrorStart !== undefined && expectedErrorStart !== codes.length && expectedErrorNode) { let errors = 0; const suppressError = () => { errors++; return false; }; for (let i = expectedErrorStart; i < codes.length; i++) { const code = codes[i]; if (typeof code === 'string') { continue; } const cap = code[3]; if (cap.diagnostic) { code[3] = { ...cap, diagnostic: { shouldReport: suppressError, }, }; } } codes.push([ '// @ts-expect-error __VLS_TS_EXPECT_ERROR', 'template', [expectedErrorNode.loc.start.offset, expectedErrorNode.loc.end.offset], { diagnostic: { shouldReport: () => errors === 0, }, }, ], '\n;\n'); expectedErrorStart = undefined; expectedErrorNode = undefined; } } function visitNode(node, parentEl, prevNode, componentCtxVar) { resolveComment(); if (prevNode?.type === 3 /* CompilerDOM.NodeTypes.COMMENT */) { const commentText = prevNode.content.trim().split(' ')[0]; if (commentText.match(/^@vue-skip\b[\s\S]*/)) { return; } else if (commentText.match(/^@vue-ignore\b[\s\S]*/)) { ignoreStart = codes.length; } else if (commentText.match(/^@vue-expect-error\b[\s\S]*/)) { expectedErrorStart = codes.length; expectedErrorNode = prevNode; } } if (node.type === 0 /* CompilerDOM.NodeTypes.ROOT */) { let prev; for (const childNode of node.children) { visitNode(childNode, parentEl, prev, componentCtxVar); prev = childNode; } resolveComment(); } else if (node.type === 1 /* CompilerDOM.NodeTypes.ELEMENT */) { const vForNode = getVForNode(node); const vIfNode = getVIfNode(node); if (vForNode) { visitVForNode(vForNode, parentEl, componentCtxVar); } else if (vIfNode) { visitVIfNode(vIfNode, parentEl, componentCtxVar); } else { visitElementNode(node, parentEl, componentCtxVar); } } else if (node.type === 12 /* CompilerDOM.NodeTypes.TEXT_CALL */) { // {{ var }} visitNode(node.content, parentEl, undefined, componentCtxVar); } else if (node.type === 8 /* CompilerDOM.NodeTypes.COMPOUND_EXPRESSION */) { // {{ ... }} {{ ... }} for (const childNode of node.children) { if (typeof childNode === 'object') { visitNode(childNode, parentEl, undefined, componentCtxVar); } } } else if (node.type === 5 /* CompilerDOM.NodeTypes.INTERPOLATION */) { // {{ ... }} let content = node.content.loc.source; let start = node.content.loc.start.offset; let leftCharacter; let rightCharacter; // fix https://github.com/vuejs/language-tools/issues/1787 while ((leftCharacter = template.content.substring(start - 1, start)).trim() === '' && leftCharacter.length) { start--; content = leftCharacter + content; } while ((rightCharacter = template.content.substring(start + content.length, start + content.length + 1)).trim() === '' && rightCharacter.length) { content = content + rightCharacter; } codes.push(...createInterpolationCode(content, node.content.loc, start, capabilitiesPresets.all, '(', ');\n')); const lines = content.split('\n'); formatCodes.push(...createFormatCode(content, start, lines.length <= 1 ? formatBrackets.curly : [ formatBrackets.curly[0], lines[lines.length - 1].trim() === '' ? '' : formatBrackets.curly[1], ])); } else if (node.type === 9 /* CompilerDOM.NodeTypes.IF */) { // v-if / v-else-if / v-else visitVIfNode(node, parentEl, componentCtxVar); } else if (node.type === 11 /* CompilerDOM.NodeTypes.FOR */) { // v-for visitVForNode(node, parentEl, componentCtxVar); } else if (node.type === 2 /* CompilerDOM.NodeTypes.TEXT */) { // not needed progress } } function visitVIfNode(node, parentEl, componentCtxVar) { let originalBlockConditionsLength = blockConditions.length; for (let i = 0; i < node.branches.length; i++) { const branch = node.branches[i]; if (i === 0) codes.push('if'); else if (branch.condition) codes.push('else if'); else codes.push('else'); let addedBlockCondition = false; if (branch.condition?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { codes.push(` `); const beforeCodeLength = codes.length; codes.push(...createInterpolationCode(branch.condition.content, branch.condition.loc, branch.condition.loc.start.offset, capabilitiesPresets.all, '(', ')')); const afterCodeLength = codes.length; formatCodes.push(...createFormatCode(branch.condition.content, branch.condition.loc.start.offset, formatBrackets.normal)); blockConditions.push(muggle.toString(codes.slice(beforeCodeLength, afterCodeLength))); addedBlockCondition = true; } codes.push(` {\n`); let prev; for (const childNode of branch.children) { visitNode(childNode, parentEl, prev, componentCtxVar); prev = childNode; } resolveComment(); generateAutoImportCompletionCode(); codes.push('}\n'); if (addedBlockCondition) { blockConditions[blockConditions.length - 1] = `!(${blockConditions[blockConditions.length - 1]})`; } } blockConditions.length = originalBlockConditionsLength; } function visitVForNode(node, parentEl, componentCtxVar) { const { source, value, key, index } = node.parseResult; const leftExpressionRange = value ? { start: (value ?? key ?? index).loc.start.offset, end: (index ?? key ?? value).loc.end.offset } : undefined; const leftExpressionText = leftExpressionRange ? node.loc.source.substring(leftExpressionRange.start - node.loc.start.offset, leftExpressionRange.end - node.loc.start.offset) : undefined; const forBlockVars = []; codes.push(`for (const [`); if (leftExpressionRange && leftExpressionText) { const collectAst = createTsAst(node.parseResult, `const [${leftExpressionText}]`); (0, transform_1.collectVars)(ts, collectAst, forBlockVars); for (const varName of forBlockVars) localVars.set(varName, (localVars.get(varName) ?? 0) + 1); codes.push([leftExpressionText, 'template', leftExpressionRange.start, capabilitiesPresets.all]); formatCodes.push(...createFormatCode(leftExpressionText, leftExpressionRange.start, formatBrackets.normal)); } codes.push(`] of __VLS_getVForSourceType`); if (source.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { codes.push('(', ...createInterpolationCode(source.content, source.loc, source.loc.start.offset, capabilitiesPresets.all, '(', ')'), '!)', // #3102 ') {\n'); let prev; for (const childNode of node.children) { visitNode(childNode, parentEl, prev, componentCtxVar); prev = childNode; } resolveComment(); generateAutoImportCompletionCode(); codes.push('}\n'); formatCodes.push(...createFormatCode(source.content, source.loc.start.offset, formatBrackets.normal)); } for (const varName of forBlockVars) localVars.set(varName, localVars.get(varName) - 1); } function visitElementNode(node, parentEl, componentCtxVar) { codes.push(`{\n`); const startTagOffset = node.loc.start.offset + template.content.substring(node.loc.start.offset).indexOf(node.tag); let endTagOffset = !node.isSelfClosing && template.lang === 'html' ? node.loc.start.offset + node.loc.source.lastIndexOf(node.tag) : undefined; if (endTagOffset === startTagOffset) { endTagOffset = undefined; } let tag = node.tag; let tagOffsets = endTagOffset !== undefined ? [startTagOffset, endTagOffset] : [startTagOffset]; let props = node.props; const propsFailedExps = []; const isNamespacedTag = tag.indexOf('.') >= 0; const var_originalComponent = `__VLS_${elementIndex++}`; const var_functionalComponent = `__VLS_${elementIndex++}`; const var_componentInstance = `__VLS_${elementIndex++}`; let dynamicTagExp; if (tag === 'slot') { tagOffsets.length = 0; } else if (tag === 'component' || tag === 'Component') { tagOffsets.length = 0; for (const prop of node.props) { if (prop.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */ && prop.name === 'is' && prop.value) { tag = prop.value.content; tagOffsets = [prop.value.loc.start.offset + prop.value.loc.source.lastIndexOf(tag)]; props = props.filter(p => p !== prop); break; } else if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'bind' && prop.arg?.loc.source === 'is' && prop.exp) { dynamicTagExp = prop.exp; props = props.filter(p => p !== prop); break; } } } const isIntrinsicElement = nativeTags.has(tag) && tagOffsets.length; if (isIntrinsicElement) { codes.push('const ', var_originalComponent, ` = __VLS_intrinsicElements[`, ...createStringLiteralKeyCode([ tag, 'template', tagOffsets[0], capabilitiesPresets.diagnosticOnly, ]), '];\n'); } else if (isNamespacedTag) { codes.push(`const ${var_originalComponent} = `, ...createInterpolationCode(tag, node.loc, startTagOffset, capabilitiesPresets.all, '', ''), ';\n'); } else if (dynamicTagExp) { codes.push(`const ${var_originalComponent} = `, ...createInterpolationCode(dynamicTagExp.loc.source, dynamicTagExp.loc, dynamicTagExp.loc.start.offset, capabilitiesPresets.all, '(', ')'), ';\n'); } else { codes.push(`const ${var_originalComponent} = ({} as `); for (const componentName of getPossibleOriginalComponentName(tag)) { codes.push(`'${componentName}' extends keyof typeof __VLS_ctx ? `, `{ '${toCanonicalComponentName(tag)}': typeof __VLS_ctx`, ...createPropertyAccessCode(componentName), ` }: `); } codes.push(`typeof __VLS_resolvedLocalAndGlobalComponents)`, ...(tagOffsets.length ? createPropertyAccessCode([ toCanonicalComponentName(tag), 'template', [tagOffsets[0], tagOffsets[0] + tag.length], capabilitiesPresets.diagnosticOnly, ]) : createPropertyAccessCode(toCanonicalComponentName(tag))), ';\n'); } if (isIntrinsicElement) { codes.push(`const ${var_functionalComponent} = __VLS_elementAsFunctionalComponent(${var_originalComponent});\n`); } else { codes.push(`const ${var_functionalComponent} = __VLS_asFunctionalComponent(`, `${var_originalComponent}, `, `new ${var_originalComponent}({`, ...createPropsCode(node, props, 'extraReferences'), '})', ');\n'); } for (const offset of tagOffsets) { if (isNamespacedTag || dynamicTagExp || isIntrinsicElement) { continue; } const key = toCanonicalComponentName(tag); codes.push(`({} as { ${key}: typeof ${var_originalComponent} }).`); codes.push([ key, 'template', [offset, offset + tag.length], { ...capabilitiesPresets.tagHover, ...capabilitiesPresets.diagnosticOnly, }, ], ';\n'); } if (vueCompilerOptions.strictTemplates) { // with strictTemplates, generate once for props type-checking + instance type codes.push(`const ${var_componentInstance} = ${var_functionalComponent}(`, // diagnostic start tagOffsets.length ? ['', 'template', tagOffsets[0], capabilitiesPresets.diagnosticOnly] : dynamicTagExp ? ['', 'template', startTagOffset, capabilitiesPresets.diagnosticOnly] : '', '{ ', ...createPropsCode(node, props, 'normal', propsFailedExps), '}', // diagnostic end tagOffsets.length ? ['', 'template', tagOffsets[0] + tag.length, capabilitiesPresets.diagnosticOnly] : dynamicTagExp ? ['', 'template', startTagOffset + tag.length, capabilitiesPresets.diagnosticOnly] : '', `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}));\n`); } else { // without strictTemplates, this only for instacne type codes.push(`const ${var_componentInstance} = ${var_functionalComponent}(`, '{ ', ...createPropsCode(node, props, 'extraReferences'), '}', `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}));\n`); // and this for props type-checking codes.push(`({} as (props: __VLS_FunctionalComponentProps & Record) => void)(`, // diagnostic start tagOffsets.length ? ['', 'template', tagOffsets[0], capabilitiesPresets.diagnosticOnly] : dynamicTagExp ? ['', 'template', startTagOffset, capabilitiesPresets.diagnosticOnly] : '', '{ ', ...createPropsCode(node, props, 'normal', propsFailedExps), '}', // diagnostic end tagOffsets.length ? ['', 'template', tagOffsets[0] + tag.length, capabilitiesPresets.diagnosticOnly] : dynamicTagExp ? ['', 'template', startTagOffset + tag.length, capabilitiesPresets.diagnosticOnly] : '', `);\n`); } if (tag !== 'template' && tag !== 'slot') { componentCtxVar = `__VLS_${elementIndex++}`; const componentEventsVar = `__VLS_${elementIndex++}`; codes.push(`const ${componentCtxVar} = __VLS_pickFunctionalComponentCtx(${var_originalComponent}, ${var_componentInstance})!;\n`); codes.push(`let ${componentEventsVar}!: __VLS_NormalizeEmits;\n`); componentCtxVar2EmitEventsVar.set(componentCtxVar, componentEventsVar); parentEl = node; } //#region // fix https://github.com/vuejs/language-tools/issues/1775 for (const failedExp of propsFailedExps) { codes.push(...createInterpolationCode(failedExp.loc.source, failedExp.loc, failedExp.loc.start.offset, capabilitiesPresets.all, '(', ')'), ';\n'); const fb = formatBrackets.normal; if (fb) { formatCodes.push(...createFormatCode(failedExp.loc.source, failedExp.loc.start.offset, fb)); } } generateInlineCss(props); const vScope = props.find(prop => prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && (prop.name === 'scope' || prop.name === 'data')); let inScope = false; let originalConditionsNum = blockConditions.length; if (vScope?.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && vScope.exp) { const scopeVar = `__VLS_${elementIndex++}`; const condition = `__VLS_withScope(__VLS_ctx, ${scopeVar})`; codes.push(`const ${scopeVar} = `); codes.push([ vScope.exp.loc.source, 'template', vScope.exp.loc.start.offset, capabilitiesPresets.all, ]); codes.push(';\n'); codes.push(`if (${condition}) {\n`); blockConditions.push(condition); inScope = true; } generateDirectives(node); generateElReferences(node); // if (shouldGenerateScopedClasses) { generateClassScoped(node); } if (componentCtxVar) { generateEvents(node, var_functionalComponent, var_componentInstance, componentCtxVar); } if (node.tag === 'slot') { generateSlot(node, startTagOffset); } if (inScope) { codes.push('}\n'); blockConditions.length = originalConditionsNum; } //#endregion const slotDir = node.props.find(p => p.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && p.name === 'slot'); if (slotDir && componentCtxVar) { if (parentEl) { hasSlotElements.add(parentEl); } const slotBlockVars = []; codes.push(`{\n`); let hasProps = false; if (slotDir?.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { formatCodes.push(...createFormatCode(slotDir.exp.content, slotDir.exp.loc.start.offset, formatBrackets.params)); const slotAst = createTsAst(slotDir, `(${slotDir.exp.content}) => {}`); (0, transform_1.collectVars)(ts, slotAst, slotBlockVars); hasProps = true; if (slotDir.exp.content.indexOf(':') === -1) { codes.push('const [', [ slotDir.exp.content, 'template', slotDir.exp.loc.start.offset, capabilitiesPresets.all, ], `] = __VLS_getSlotParams(`); } else { codes.push('const ', [ slotDir.exp.content, 'template', slotDir.exp.loc.start.offset, capabilitiesPresets.all, ], ` = __VLS_getSlotParam(`); } } codes.push(['', 'template', (slotDir.arg ?? slotDir).loc.start.offset, capabilitiesPresets.diagnosticOnly], `(${componentCtxVar}.slots!)`, ...((slotDir?.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && slotDir.arg.content) ? createPropertyAccessCode([ slotDir.arg.loc.source, 'template', slotDir.arg.loc.start.offset, slotDir.arg.isStatic ? capabilitiesPresets.slotName : capabilitiesPresets.all ], slotDir.arg.loc) : createPropertyAccessCode([ 'default', 'template', [slotDir.loc.start.offset, slotDir.loc.start.offset + (slotDir.loc.source.startsWith('#') ? '#'.length : slotDir.loc.source.startsWith('v-slot:') ? 'v-slot:'.length : 0)], { ...capabilitiesPresets.slotName, completion: false }, ])), ['', 'template', (slotDir.arg ?? slotDir).loc.end.offset, capabilitiesPresets.diagnosticOnly]); if (hasProps) { codes.push(')'); } codes.push(';\n'); slotBlockVars.forEach(varName => { localVars.set(varName, (localVars.get(varName) ?? 0) + 1); }); let prev; for (const childNode of node.children) { visitNode(childNode, parentEl, prev, componentCtxVar); prev = childNode; } resolveComment(); generateAutoImportCompletionCode(); slotBlockVars.forEach(varName => { localVars.set(varName, localVars.get(varName) - 1); }); let isStatic = true; if (slotDir?.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { isStatic = slotDir.arg.isStatic; } if (isStatic && slotDir && !slotDir.arg) { codes.push(`${componentCtxVar}.slots!['`, [ '', 'template', slotDir.loc.start.offset + (slotDir.loc.source.startsWith('#') ? '#'.length : slotDir.loc.source.startsWith('v-slot:') ? 'v-slot:'.length : 0), { completion: true }, ], `'/* empty slot name completion */]\n`); } codes.push(`}\n`); } else { let prev; for (const childNode of node.children) { visitNode(childNode, parentEl, prev, componentCtxVar); prev = childNode; } resolveComment(); // fix https://github.com/vuejs/language-tools/issues/932 if (!hasSlotElements.has(node) && node.children.length) { codes.push(`(${componentCtxVar}.slots!)`, ...createPropertyAccessCode([ 'default', 'template', [ node.children[0].loc.start.offset, node.children[node.children.length - 1].loc.end.offset, ], { references: true }, ]), ';\n'); } } codes.push(`}\n`); } function generateEvents(node, componentVar, componentInstanceVar, componentCtxVar) { for (const prop of node.props) { if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'on' && prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { const eventsVar = componentCtxVar2EmitEventsVar.get(componentCtxVar); const eventVar = `__VLS_${elementIndex++}`; codes.push(`let ${eventVar} = { '${prop.arg.loc.source}': `, `__VLS_pickEvent(${eventsVar}['${prop.arg.loc.source}'], ({} as __VLS_FunctionalComponentProps)`, ...createPropertyAccessCode([ (0, shared_1.camelize)('on-' + prop.arg.loc.source), // onClickOutside 'template', [prop.arg.loc.start.offset, prop.arg.loc.end.offset], { ...capabilitiesPresets.attrReference, rename: { // @click-outside -> onClickOutside normalize(newName) { return (0, shared_1.camelize)('on-' + newName); }, // onClickOutside -> @click-outside apply(newName) { const hName = (0, shared_2.hyphenateAttr)(newName); if ((0, shared_2.hyphenateAttr)(newName).startsWith('on-')) { return (0, shared_1.camelize)(hName.slice('on-'.length)); } return newName; }, }, }, ]), `) };\n`, `${eventVar} = { `); if (prop.arg.loc.source.startsWith('[') && prop.arg.loc.source.endsWith(']')) { codes.push('[(', ...createInterpolationCode(prop.arg.loc.source.slice(1, -1), prop.arg.loc, prop.arg.loc.start.offset + 1, capabilitiesPresets.all, '', ''), ')!]'); } else { codes.push(...createObjectPropertyCode([ prop.arg.loc.source, 'template', prop.arg.loc.start.offset, capabilitiesPresets.event, ], prop.arg.loc)); } codes.push(`: `); appendExpressionNode(prop); codes.push(` };\n`); } else if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'on' && prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { // for vue 2 nameless event // https://github.com/johnsoncodehk/vue-tsc/issues/67 codes.push(...createInterpolationCode(prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, capabilitiesPresets.all, '$event => {(', ')}'), ';\n'); formatCodes.push(...createFormatCode(prop.exp.content, prop.exp.loc.start.offset, formatBrackets.normal)); } function appendExpressionNode(prop) { if (prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { const ast = createTsAst(prop.exp, prop.exp.content); let isCompoundExpression = true; if (ast.getChildCount() === 2) { // with EOF ast.forEachChild(child_1 => { if (ts.isExpressionStatement(child_1)) { child_1.forEachChild(child_2 => { if (ts.isArrowFunction(child_2)) { isCompoundExpression = false; } else if (ts.isIdentifier(child_2)) { isCompoundExpression = false; } }); } else if (ts.isFunctionDeclaration(child_1)) { isCompoundExpression = false; } }); } let prefix = '('; let suffix = ')'; let isFirstMapping = true; if (isCompoundExpression) { codes.push('$event => {\n'); localVars.set('$event', (localVars.get('$event') ?? 0) + 1); prefix = ''; suffix = ''; for (const blockCondition of blockConditions) { prefix += `if (!(${blockCondition})) return;\n`; } } codes.push(...createInterpolationCode(prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, () => { if (isCompoundExpression && isFirstMapping) { isFirstMapping = false; return capabilitiesPresets.allWithHiddenParam; } return capabilitiesPresets.all; }, prefix, suffix)); if (isCompoundExpression) { localVars.set('$event', localVars.get('$event') - 1); codes.push(';\n'); generateAutoImportCompletionCode(); codes.push('}\n'); } formatCodes.push(...createFormatCode(prop.exp.content, prop.exp.loc.start.offset, isCompoundExpression ? formatBrackets.event : formatBrackets.normal)); } else { codes.push(`() => {}`); } } } } function createPropsCode(node, props, mode, propsFailedExps) { let styleAttrNum = 0; let classAttrNum = 0; if (props.some(prop => prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'bind' && !prop.arg && prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */)) { // fix https://github.com/vuejs/language-tools/issues/2166 styleAttrNum++; classAttrNum++; } const codes = []; let caps_all = capabilitiesPresets.all; let caps_diagnosticOnly = capabilitiesPresets.diagnosticOnly; let caps_attr = capabilitiesPresets.attr; if (mode === 'extraReferences') { caps_all = { references: caps_all.references, rename: caps_all.rename, }; caps_diagnosticOnly = { references: caps_diagnosticOnly.references, rename: caps_diagnosticOnly.rename, }; caps_attr = { references: caps_attr.references, rename: caps_attr.rename, }; } codes.push(`...{ `); for (const prop of props) { if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'on' && prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { codes.push(...createObjectPropertyCode((0, shared_1.camelize)('on-' + prop.arg.loc.source)), ': {} as any, '); } } codes.push(`}, `); const canCamelize = !nativeTags.has(node.tag) || node.tagType === 1 /* CompilerDOM.ElementTypes.COMPONENT */; for (const prop of props) { if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && (prop.name === 'bind' || prop.name === 'model') && (prop.name === 'model' || prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) && (!prop.exp || prop.exp.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */)) { let attrNameText = prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ ? prop.arg.constType === 3 /* CompilerDOM.ConstantTypes.CAN_STRINGIFY */ ? prop.arg.content : prop.arg.loc.source : getModelValuePropName(node, vueCompilerOptions.target, vueCompilerOptions); if (prop.modifiers.some(m => m === 'prop' || m === 'attr')) { attrNameText = attrNameText?.substring(1); } if (attrNameText === undefined || vueCompilerOptions.dataAttributes.some(pattern => (0, minimatch_1.minimatch)(attrNameText, pattern)) || (attrNameText === 'style' && ++styleAttrNum >= 2) || (attrNameText === 'class' && ++classAttrNum >= 2) || (attrNameText === 'name' && node.tag === 'slot') // #2308 ) { if (prop.exp && prop.exp.constType !== 3 /* CompilerDOM.ConstantTypes.CAN_STRINGIFY */) { propsFailedExps?.push(prop.exp); } continue; } let camelized = false; if (canCamelize && (!prop.arg || (prop.arg.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop.arg.isStatic)) // isStatic && (0, shared_2.hyphenateAttr)(attrNameText) === attrNameText && !vueCompilerOptions.htmlAttributes.some(pattern => (0, minimatch_1.minimatch)(attrNameText, pattern))) { attrNameText = (0, shared_1.camelize)(attrNameText); camelized = true; } // camelize name codes.push([ '', 'template', prop.loc.start.offset, caps_diagnosticOnly, ]); if (!prop.arg) { codes.push(...createObjectPropertyCode([ attrNameText, 'template', [prop.loc.start.offset, prop.loc.start.offset + prop.loc.source.indexOf('=')], caps_attr, ], prop.loc.name_1 ?? (prop.loc.name_1 = {}))); } else if (prop.exp?.constType === 3 /* CompilerDOM.ConstantTypes.CAN_STRINGIFY */) { codes.push(...createObjectPropertyCode([ attrNameText, 'template', [prop.arg.loc.start.offset, prop.arg.loc.start.offset + attrNameText.length], // patch style attr, { ...caps_attr, rename: { normalize: shared_1.camelize, apply: camelized ? shared_2.hyphenateAttr : noEditApply, }, }, ], prop.loc.name_2 ?? (prop.loc.name_2 = {}))); } else { codes.push(...createObjectPropertyCode([ attrNameText, 'template', [prop.arg.loc.start.offset, prop.arg.loc.end.offset], { ...caps_attr, rename: { normalize: shared_1.camelize, apply: camelized ? shared_2.hyphenateAttr : noEditApply, }, }, ], prop.loc.name_2 ?? (prop.loc.name_2 = {}))); } codes.push(': ('); if (prop.exp && !(prop.exp.constType === 3 /* CompilerDOM.ConstantTypes.CAN_STRINGIFY */)) { // style='z-index: 2' will compile to {'z-index':'2'} codes.push(...createInterpolationCode(prop.exp.loc.source, prop.exp.loc, prop.exp.loc.start.offset, caps_all, '(', ')')); if (mode === 'normal') { formatCodes.push(...createFormatCode(prop.exp.loc.source, prop.exp.loc.start.offset, formatBrackets.normal)); } } else { codes.push('{}'); } codes.push(')'); codes.push([ '', 'template', prop.loc.end.offset, caps_diagnosticOnly, ]); codes.push(', '); } else if (prop.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */) { let attrNameText = prop.name; if (vueCompilerOptions.dataAttributes.some(pattern => (0, minimatch_1.minimatch)(attrNameText, pattern)) || (attrNameText === 'style' && ++styleAttrNum >= 2) || (attrNameText === 'class' && ++classAttrNum >= 2) || (attrNameText === 'name' && node.tag === 'slot') // #2308 ) { continue; } let camelized = false; if (canCamelize && (0, shared_2.hyphenateAttr)(prop.name) === prop.name && !vueCompilerOptions.htmlAttributes.some(pattern => (0, minimatch_1.minimatch)(attrNameText, pattern))) { attrNameText = (0, shared_1.camelize)(prop.name); camelized = true; } // camelize name codes.push([ '', 'template', prop.loc.start.offset, caps_diagnosticOnly, ]); codes.push(...createObjectPropertyCode([ attrNameText, 'template', [prop.loc.start.offset, prop.loc.start.offset + prop.name.length], { ...caps_attr, rename: { normalize: shared_1.camelize, apply: camelized ? shared_2.hyphenateAttr : noEditApply, }, }, ], prop.loc.name_1 ?? (prop.loc.name_1 = {}))); codes.push(': ('); if (prop.value) { generateAttrValue(prop.value); } else { codes.push('true'); } codes.push(')'); codes.push([ '', 'template', prop.loc.end.offset, caps_diagnosticOnly, ]); codes.push(', '); } else if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'bind' && !prop.arg && prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { codes.push(['', 'template', prop.exp.loc.start.offset, capabilitiesPresets.diagnosticOnly], '...', ...createInterpolationCode(prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, caps_all, '(', ')'), ['', 'template', prop.exp.loc.end.offset, capabilitiesPresets.diagnosticOnly], ', '); if (mode === 'normal') { formatCodes.push(...createFormatCode(prop.exp.content, prop.exp.loc.start.offset, formatBrackets.normal)); } } else { // comment this line to avoid affecting comments in prop expressions // tsCodeGen.addText("/* " + [prop.type, prop.name, prop.arg?.loc.source, prop.exp?.loc.source, prop.loc.source].join(", ") + " */ "); } } return codes; function generateAttrValue(attrNode) { const char = attrNode.loc.source.startsWith("'") ? "'" : '"'; codes.push(char); let start = attrNode.loc.start.offset; let end = attrNode.loc.end.offset; let content = attrNode.loc.source; if ((content.startsWith('"') && content.endsWith('"')) || (content.startsWith("'") && content.endsWith("'"))) { start++; end--; content = content.slice(1, -1); } codes.push([ toUnicodeIfNeed(content), 'template', [start, end], caps_all, ]); codes.push(char); } } function generateInlineCss(props) { for (const prop of props) { if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'bind' && prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop.arg.content === 'style' && prop.exp.constType === 3 /* CompilerDOM.ConstantTypes.CAN_STRINGIFY */) { const endCrt = prop.arg.loc.source[prop.arg.loc.source.length - 1]; // " | ' const start = prop.arg.loc.source.indexOf(endCrt) + 1; const end = prop.arg.loc.source.lastIndexOf(endCrt); const content = prop.arg.loc.source.substring(start, end); cssCodes.push(`x { `); cssCodes.push([ content, 'template', prop.arg.loc.start.offset + start, capabilitiesPresets.all, ]); cssCodes.push(` }\n`); } } } function generateDirectives(node) { for (const prop of node.props) { if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name !== 'slot' && prop.name !== 'on' && prop.name !== 'model' && prop.name !== 'bind' && (prop.name !== 'scope' && prop.name !== 'data')) { accessedGlobalVariables.add((0, shared_1.camelize)('v-' + prop.name)); if (prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && !prop.arg.isStatic) { codes.push(...createInterpolationCode(prop.arg.content, prop.arg.loc, prop.arg.loc.start.offset + prop.arg.loc.source.indexOf(prop.arg.content), capabilitiesPresets.all, '(', ')'), ';\n'); formatCodes.push(...createFormatCode(prop.arg.content, prop.arg.loc.start.offset, formatBrackets.normal)); } codes.push([ '', 'template', prop.loc.start.offset, capabilitiesPresets.diagnosticOnly, ], `__VLS_directiveFunction(__VLS_ctx.`, [ (0, shared_1.camelize)('v-' + prop.name), 'template', [prop.loc.start.offset, prop.loc.start.offset + 'v-'.length + prop.name.length], { ...capabilitiesPresets.noDiagnostic, completion: { // fix https://github.com/vuejs/language-tools/issues/1905 additional: true, }, rename: { normalize: shared_1.camelize, apply: getPropRenameApply(prop.name), }, }, ], ')', '('); if (prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { codes.push(['', 'template', prop.exp.loc.start.offset, capabilitiesPresets.diagnosticOnly], ...createInterpolationCode(prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, capabilitiesPresets.all, '(', ')'), ['', 'template', prop.exp.loc.end.offset, capabilitiesPresets.diagnosticOnly]); formatCodes.push(...createFormatCode(prop.exp.content, prop.exp.loc.start.offset, formatBrackets.normal)); } else { codes.push('undefined'); } codes.push(')', ['', 'template', prop.loc.end.offset, capabilitiesPresets.diagnosticOnly], ';\n'); } } } function generateElReferences(node) { for (const prop of node.props) { if (prop.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */ && prop.name === 'ref' && prop.value) { codes.push('// @ts-ignore\n', ...createInterpolationCode(prop.value.content, prop.value.loc, prop.value.loc.start.offset + 1, capabilitiesPresets.refAttr, '(', ')'), ';\n'); } } } function generateClassScoped(node) { for (const prop of node.props) { if (prop.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */ && prop.name === 'class' && prop.value) { let startOffset = prop.value.loc.start.offset; let tempClassName = ''; for (const char of (prop.value.loc.source + ' ')) { if (char.trim() === '' || char === '"' || char === "'") { if (tempClassName !== '') { scopedClasses.push({ className: tempClassName, offset: startOffset }); startOffset += tempClassName.length; tempClassName = ''; } startOffset += char.length; } else { tempClassName += char; } } } else if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop.arg.content === 'class') { codes.push(`__VLS_styleScopedClasses = (`); codes.push([ prop.exp.content, 'template', prop.exp.loc.start.offset, capabilitiesPresets.scopedClassName, ]); codes.push(`);\n`); } } } function generateSlot(node, startTagOffset) { const varSlot = `__VLS_${elementIndex++}`; const slotNameExpNode = getSlotNameExpNode(); if (hasScriptSetupSlots) { codes.push('__VLS_normalizeSlot(', ['', 'template', node.loc.start.offset, capabilitiesPresets.diagnosticOnly], `${slotsAssignName ?? '__VLS_slots'}[`, ['', 'template', node.loc.start.offset, capabilitiesPresets.diagnosticOnly], slotNameExpNode?.content ?? `('${getSlotName()}' as const)`, ['', 'template', node.loc.end.offset, capabilitiesPresets.diagnosticOnly], ']', ['', 'template', node.loc.end.offset, capabilitiesPresets.diagnosticOnly], ')?.(', ['', 'template', startTagOffset, capabilitiesPresets.diagnosticOnly], '{\n'); } else { codes.push(`var ${varSlot} = {\n`); } for (const prop of node.props) { if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && !prop.arg && prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { codes.push('...', ...createInterpolationCode(prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, capabilitiesPresets.attrReference, '(', ')'), ',\n'); } else if (prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop.arg.content !== 'name') { codes.push(...createObjectPropertyCode([ prop.arg.content, 'template', [prop.arg.loc.start.offset, prop.arg.loc.end.offset], { ...capabilitiesPresets.slotProp, rename: { normalize: shared_1.camelize, apply: getPropRenameApply(prop.arg.content), }, }, ], prop.arg.loc), ': ', ...createInterpolationCode(prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, capabilitiesPresets.attrReference, '(', ')'), ',\n'); } else if (prop.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */ && prop.name !== 'name' // slot name ) { codes.push(...createObjectPropertyCode([ prop.name, 'template', prop.loc.start.offset, { ...capabilitiesPresets.attr, rename: { normalize: shared_1.camelize, apply: getPropRenameApply(prop.name), }, }, ], prop.loc), ': (', prop.value !== undefined ? `"${toUnicodeIfNeed(prop.value.content)}"` : 'true', '),\n'); } } codes.push('}', hasScriptSetupSlots ? ['', 'template', startTagOffset + node.tag.length, capabilitiesPresets.diagnosticOnly] : '', hasScriptSetupSlots ? `);\n` : `;\n`); if (hasScriptSetupSlots) { return; } if (slotNameExpNode) { const varSlotExp = `__VLS_${elementIndex++}`; codes.push(`var ${varSlotExp} = `); if (typeof slotNameExpNode === 'string') { codes.push(slotNameExpNode); } else { codes.push(...createInterpolationCode(slotNameExpNode.content, slotNameExpNode, undefined, undefined, '(', ')')); } codes.push(` as const;\n`); slotExps.set(varSlotExp, { varName: varSlot, }); } else { const slotName = getSlotName(); slots.set(slotName, { varName: varSlot, loc: [startTagOffset, startTagOffset + node.tag.length], nodeLoc: node.loc, }); } function getSlotName() { for (const prop2 of node.props) { if (prop2.name === 'name' && prop2.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */ && prop2.value) { if (prop2.value.content) { return prop2.value.content; } } } return 'default'; } function getSlotNameExpNode() { for (const prop2 of node.props) { if (prop2.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop2.name === 'bind' && prop2.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && prop2.arg.content === 'name') { if (prop2.exp?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) { return prop2.exp; } } } } } function generateAutoImportCompletionCode() { if (!tempVars.length) return; codes.push('// @ts-ignore\n'); // #2304 codes.push('['); for (const _vars of tempVars) { for (const v of _vars) { codes.push([v.text, 'template', v.offset, { completion: { additional: true } }]); codes.push(','); } } codes.push('];\n'); tempVars.length = 0; } // functional like function createFormatCode(mapCode, sourceOffset, formatWrapper) { return [ formatWrapper[0], [mapCode, 'template', sourceOffset, { completion: true /* fix vue-autoinsert-parentheses not working */ }], formatWrapper[1], '\n', ]; } function createObjectPropertyCode(a, astHolder) { const aStr = typeof a === 'string' ? a : a[0]; if (validTsVarReg.test(aStr)) { return [a]; } else if (aStr.startsWith('[') && aStr.endsWith(']') && astHolder) { const range = typeof a === 'object' ? a[2] : undefined; const data = typeof a === 'object' ? a[3] : undefined; return createInterpolationCode(aStr, astHolder, range && typeof range === 'object' ? range[0] : range, data, '', ''); } else { return createStringLiteralKeyCode(a); } } function createInterpolationCode(_code, astHolder, start, data, prefix, suffix) { const code = prefix + _code + suffix; const ast = createTsAst(astHolder, code); const codes = []; const vars = (0, transform_1.walkInterpolationFragment)(ts, code, ast, (frag, fragOffset, isJustForErrorMapping) => { if (fragOffset === undefined) { codes.push(frag); } else { fragOffset -= prefix.length; let addSuffix = ''; const overLength = fragOffset + frag.length - _code.length; if (overLength > 0) { addSuffix = frag.substring(frag.length - overLength); frag = frag.substring(0, frag.length - overLength); } if (fragOffset < 0) { codes.push(frag.substring(0, -fragOffset)); frag = frag.substring(-fragOffset); fragOffset = 0; } if (start !== undefined && data !== undefined) { codes.push([ frag, 'template', start + fragOffset, isJustForErrorMapping ? capabilitiesPresets.diagnosticOnly : typeof data === 'function' ? data() : data, ]); } else { codes.push(frag); } codes.push(addSuffix); } }, localVars, accessedGlobalVariables, vueCompilerOptions); if (start !== undefined) { for (const v of vars) { v.offset = start + v.offset - prefix.length; } if (vars.length) { tempVars.push(vars); } } return codes; } function createTsAst(astHolder, text) { if (astHolder.__volar_ast_text !== text) { astHolder.__volar_ast_text = text; astHolder.__volar_ast = ts.createSourceFile('/a.ts', text, ts.ScriptTarget.ESNext); } return astHolder.__volar_ast; } function createPropertyAccessCode(a, astHolder) { const aStr = typeof a === 'string' ? a : a[0]; if (!compilerOptions.noPropertyAccessFromIndexSignature && validTsVarReg.test(aStr)) { return ['.', a]; } else if (aStr.startsWith('[') && aStr.endsWith(']')) { if (typeof a === 'string' || !astHolder) { return [a]; } else { return createInterpolationCode(a[0], astHolder, typeof a[2] === 'number' ? a[2] : a[2][0], a[3], '', ''); } } else { return ['[', ...createStringLiteralKeyCode(a), ']']; } } function createStringLiteralKeyCode(a) { let codes = ['"', a, '"']; if (typeof a === 'object') { const start = typeof a[2] === 'number' ? a[2] : a[2][0]; const end = typeof a[2] === 'number' ? a[2] : a[2][1]; codes = [ ['', 'template', start, a[3]], ...codes, ['', 'template', end, a[3]], ]; } return codes; } } exports.generate = generate; ; function walkElementNodes(node, cb) { if (node.type === 0 /* CompilerDOM.NodeTypes.ROOT */) { for (const child of node.children) { walkElementNodes(child, cb); } } else if (node.type === 1 /* CompilerDOM.NodeTypes.ELEMENT */) { const patchForNode = getVForNode(node); if (patchForNode) { walkElementNodes(patchForNode, cb); } else { cb(node); for (const child of node.children) { walkElementNodes(child, cb); } } } else if (node.type === 9 /* CompilerDOM.NodeTypes.IF */) { // v-if / v-else-if / v-else for (let i = 0; i < node.branches.length; i++) { const branch = node.branches[i]; for (const childNode of branch.children) { walkElementNodes(childNode, cb); } } } else if (node.type === 11 /* CompilerDOM.NodeTypes.FOR */) { // v-for for (const child of node.children) { walkElementNodes(child, cb); } } } exports.walkElementNodes = walkElementNodes; function toUnicodeIfNeed(str) { if (str.indexOf('\\') === -1 && str.indexOf('\n') === -1) { return str; } return toUnicode(str); } 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(''); } function camelizeComponentName(newName) { return (0, shared_1.camelize)('-' + newName); } function getTagRenameApply(oldName) { return oldName === (0, shared_2.hyphenateTag)(oldName) ? shared_2.hyphenateTag : noEditApply; } function getPropRenameApply(oldName) { return oldName === (0, shared_2.hyphenateAttr)(oldName) ? shared_2.hyphenateAttr : noEditApply; } function noEditApply(n) { return n; } function getModelValuePropName(node, vueVersion, 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 v = tags[tag]; if (typeof v === 'object') { const arr = Array.isArray(v) ? v : [v]; for (const attrs of arr) { let failed = false; for (const attr in attrs) { const attrNode = node.props.find(prop => prop.type === 6 /* 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 vueVersion < 3 ? 'value' : 'modelValue'; } // TODO: track https://github.com/vuejs/vue-next/issues/3498 function getVForNode(node) { const forDirective = node.props.find((prop) => prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'for'); if (forDirective) { let forNode; CompilerDOM.processFor(node, forDirective, transformContext, _forNode => { forNode = { ..._forNode }; return undefined; }); if (forNode) { forNode.children = [{ ...node, props: node.props.filter(prop => prop !== forDirective), }]; return forNode; } } } function getVIfNode(node) { const forDirective = node.props.find((prop) => prop.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */ && prop.name === 'if'); if (forDirective) { let ifNode; CompilerDOM.processIf(node, forDirective, transformContext, _ifNode => { ifNode = { ..._ifNode }; return undefined; }); if (ifNode) { for (const branch of ifNode.branches) { branch.children = [{ ...node, props: node.props.filter(prop => prop !== forDirective), }]; } return ifNode; } } } //# sourceMappingURL=template.js.map