feat: init

This commit is contained in:
2026-02-13 22:02:30 +01:00
commit 8f9ff830fb
16711 changed files with 3307340 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
import type { Mapping, VirtualCode } from '@volar/language-core';
import type { Code, Sfc, VueLanguagePluginReturn } from '../types';
export declare class VueEmbeddedCode {
id: string;
lang: string;
content: Code[];
parentCodeId?: string;
linkedCodeMappings: Mapping[];
embeddedCodes: VueEmbeddedCode[];
constructor(id: string, lang: string, content: Code[]);
}
export declare function useEmbeddedCodes(plugins: VueLanguagePluginReturn[], fileName: string, sfc: Sfc): () => VirtualCode[];

View File

@@ -0,0 +1,253 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VueEmbeddedCode = void 0;
exports.useEmbeddedCodes = useEmbeddedCodes;
const alien_signals_1 = require("alien-signals");
const muggle_string_1 = require("muggle-string");
const buildMappings_1 = require("../utils/buildMappings");
class VueEmbeddedCode {
id;
lang;
content;
parentCodeId;
linkedCodeMappings = [];
embeddedCodes = [];
constructor(id, lang, content) {
this.id = id;
this.lang = lang;
this.content = content;
}
}
exports.VueEmbeddedCode = VueEmbeddedCode;
function useEmbeddedCodes(plugins, fileName, sfc) {
const getNameToBlockMap = (0, alien_signals_1.computed)(() => {
const blocks = {};
if (sfc.template) {
blocks[sfc.template.name] = sfc.template;
}
if (sfc.script) {
blocks[sfc.script.name] = sfc.script;
}
if (sfc.scriptSetup) {
blocks[sfc.scriptSetup.name] = sfc.scriptSetup;
}
for (const block of sfc.styles) {
blocks[block.name] = block;
}
for (const block of sfc.customBlocks) {
blocks[block.name] = block;
}
return blocks;
});
const pluginsResult = plugins.map(useEmbeddedCodesForPlugin);
return (0, alien_signals_1.computed)(() => {
const result = [];
const idToCodeMap = new Map();
const virtualCodes = pluginsResult
.map(getPluginResult => getPluginResult())
.flat()
.map(({ code, snapshot, mappings }) => {
const virtualCode = {
id: code.id,
languageId: resolveCommonLanguageId(code.lang),
linkedCodeMappings: code.linkedCodeMappings,
snapshot,
mappings,
embeddedCodes: [],
};
idToCodeMap.set(code.id, virtualCode);
return [code.parentCodeId, virtualCode];
});
for (const [parentCodeId, virtualCode] of virtualCodes) {
if (!parentCodeId) {
result.push(virtualCode);
continue;
}
const parent = idToCodeMap.get(parentCodeId);
if (parent) {
parent.embeddedCodes ??= [];
parent.embeddedCodes.push(virtualCode);
}
else {
result.push(virtualCode);
}
}
return result;
});
function useEmbeddedCodesForPlugin(plugin) {
const getMap = (0, alien_signals_1.computed)(prevMap => {
if (!plugin.getEmbeddedCodes) {
return new Map();
}
const newCodeList = plugin.getEmbeddedCodes(fileName, sfc);
const map = new Map();
for (const { id, lang } of newCodeList) {
const key = id + '__' + lang;
if (prevMap?.has(key)) {
map.set(key, prevMap.get(key));
}
else {
map.set(key, useEmbeddedCode(id, lang));
}
}
return map;
});
return (0, alien_signals_1.computed)(() => {
const result = [];
for (const generate of getMap().values()) {
const { code, snapshot } = generate();
result.push({
code,
snapshot,
mappings: getMappingsForCode(code),
});
}
return result;
});
}
function useEmbeddedCode(id, lang) {
return (0, alien_signals_1.computed)(() => {
const content = [];
const code = new VueEmbeddedCode(id, lang, content);
for (const plugin of plugins) {
if (!plugin.resolveEmbeddedCode) {
continue;
}
try {
plugin.resolveEmbeddedCode(fileName, sfc, code);
}
catch (e) {
console.error(e);
}
}
const newText = (0, muggle_string_1.toString)(code.content);
const changeRanges = new Map();
const snapshot = {
getText: (start, end) => newText.slice(start, end),
getLength: () => newText.length,
getChangeRange(oldSnapshot) {
if (!changeRanges.has(oldSnapshot)) {
changeRanges.set(oldSnapshot, undefined);
const oldText = oldSnapshot.getText(0, oldSnapshot.getLength());
const changeRange = fullDiffTextChangeRange(oldText, newText);
if (changeRange) {
changeRanges.set(oldSnapshot, changeRange);
}
}
return changeRanges.get(oldSnapshot);
},
};
return {
code,
snapshot,
};
});
}
function getMappingsForCode(code) {
const mappings = (0, buildMappings_1.buildMappings)(code.content.map(segment => {
if (typeof segment === 'string') {
return segment;
}
const source = segment[1];
if (source === undefined) {
return segment;
}
const block = getNameToBlockMap()[source];
if (!block) {
return segment;
}
return [
segment[0],
undefined,
segment[2] + block.startTagEnd,
segment[3],
];
}));
const newMappings = [];
const tokenMappings = new Map();
for (let i = 0; i < mappings.length; i++) {
const mapping = mappings[i];
if (mapping.data.__combineToken !== undefined) {
const token = mapping.data.__combineToken;
if (tokenMappings.has(token)) {
const offsetMapping = tokenMappings.get(token);
offsetMapping.sourceOffsets.push(...mapping.sourceOffsets);
offsetMapping.generatedOffsets.push(...mapping.generatedOffsets);
offsetMapping.lengths.push(...mapping.lengths);
}
else {
tokenMappings.set(token, mapping);
newMappings.push(mapping);
}
continue;
}
if (mapping.data.__linkedToken !== undefined) {
const token = mapping.data.__linkedToken;
if (tokenMappings.has(token)) {
const prevMapping = tokenMappings.get(token);
code.linkedCodeMappings.push({
sourceOffsets: [prevMapping.generatedOffsets[0]],
generatedOffsets: [mapping.generatedOffsets[0]],
lengths: [Number(token.description)],
data: undefined,
});
}
else {
tokenMappings.set(token, mapping);
}
continue;
}
newMappings.push(mapping);
}
return newMappings;
}
}
function fullDiffTextChangeRange(oldText, newText) {
for (let start = 0; start < oldText.length && start < newText.length; start++) {
if (oldText[start] !== newText[start]) {
let end = oldText.length;
for (let i = 0; i < oldText.length - start && i < newText.length - start; i++) {
if (oldText[oldText.length - i - 1] !== newText[newText.length - i - 1]) {
break;
}
end--;
}
let length = end - start;
let newLength = length + (newText.length - oldText.length);
if (newLength < 0) {
length -= newLength;
newLength = 0;
}
return {
span: { start, length },
newLength,
};
}
}
}
function resolveCommonLanguageId(lang) {
switch (lang) {
case 'js':
return 'javascript';
case 'cjs':
return 'javascript';
case 'mjs':
return 'javascript';
case 'ts':
return 'typescript';
case 'cts':
return 'typescript';
case 'mts':
return 'typescript';
case 'jsx':
return 'javascriptreact';
case 'tsx':
return 'typescriptreact';
case 'pug':
return 'jade';
case 'md':
return 'markdown';
}
return lang;
}
//# sourceMappingURL=embeddedCodes.js.map

View File

@@ -0,0 +1,24 @@
import type { CodeMapping, VirtualCode } from '@volar/language-core';
import type { SFCParseResult } from '@vue/compiler-sfc';
import type * as ts from 'typescript';
import type { Sfc, VueCompilerOptions, VueLanguagePluginReturn } from '../types';
export declare class VueVirtualCode implements VirtualCode {
fileName: string;
languageId: string;
initSnapshot: ts.IScriptSnapshot;
vueCompilerOptions: VueCompilerOptions;
readonly id = "main";
private _snapshot;
private _parsedSfcResult;
private _ir;
private _embeddedCodes;
private _mappings;
get snapshot(): ts.IScriptSnapshot;
get vueSfc(): SFCParseResult | undefined;
get sfc(): Sfc;
get embeddedCodes(): VirtualCode[];
get mappings(): CodeMapping[];
constructor(fileName: string, languageId: string, initSnapshot: ts.IScriptSnapshot, vueCompilerOptions: VueCompilerOptions, plugins: VueLanguagePluginReturn[], ts: typeof import('typescript'));
update(newSnapshot: ts.IScriptSnapshot): void;
private parseSfc;
}

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VueVirtualCode = void 0;
const alien_signals_1 = require("alien-signals");
const plugins_1 = require("../plugins");
const embeddedCodes_1 = require("./embeddedCodes");
const ir_1 = require("./ir");
class VueVirtualCode {
fileName;
languageId;
initSnapshot;
vueCompilerOptions;
id = 'main';
_snapshot;
_parsedSfcResult;
_ir;
_embeddedCodes;
_mappings;
get snapshot() {
return this._snapshot();
}
get vueSfc() {
return this._parsedSfcResult()?.result;
}
get sfc() {
return this._ir;
}
get embeddedCodes() {
return this._embeddedCodes();
}
get mappings() {
return this._mappings();
}
constructor(fileName, languageId, initSnapshot, vueCompilerOptions, plugins, ts) {
this.fileName = fileName;
this.languageId = languageId;
this.initSnapshot = initSnapshot;
this.vueCompilerOptions = vueCompilerOptions;
this._snapshot = (0, alien_signals_1.signal)(initSnapshot);
this._parsedSfcResult = (0, alien_signals_1.computed)(lastResult => this.parseSfc(plugins, lastResult));
this._ir = (0, ir_1.useIR)(ts, plugins, fileName, this._snapshot, () => this._parsedSfcResult()?.result);
this._embeddedCodes = (0, embeddedCodes_1.useEmbeddedCodes)(plugins, fileName, this._ir);
this._mappings = (0, alien_signals_1.computed)(() => {
return [{
sourceOffsets: [0],
generatedOffsets: [0],
lengths: [this._snapshot().getLength()],
data: plugins_1.allCodeFeatures,
}];
});
}
update(newSnapshot) {
this._snapshot(newSnapshot);
}
parseSfc(plugins, lastResult) {
const snapshot = this.snapshot;
if (lastResult?.plugin.updateSFC && !lastResult.result.errors.length) {
const change = snapshot.getChangeRange(lastResult.snapshot);
if (change) {
const newSfc = lastResult.plugin.updateSFC(lastResult.result, {
start: change.span.start,
end: change.span.start + change.span.length,
newText: snapshot.getText(change.span.start, change.span.start + change.newLength),
});
if (newSfc) {
// force dirty
newSfc.descriptor = JSON.parse(JSON.stringify(newSfc.descriptor));
return {
snapshot,
plugin: lastResult.plugin,
result: newSfc,
};
}
}
}
for (const plugin of plugins) {
const sfc = plugin.parseSFC2?.(this.fileName, this.languageId, snapshot.getText(0, snapshot.getLength()))
?? plugin.parseSFC?.(this.fileName, snapshot.getText(0, snapshot.getLength()));
if (sfc) {
return {
snapshot,
plugin,
result: sfc,
};
}
}
}
}
exports.VueVirtualCode = VueVirtualCode;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,4 @@
import type { SFCParseResult } from '@vue/compiler-sfc';
import type * as ts from 'typescript';
import type { Sfc, VueLanguagePluginReturn } from '../types';
export declare function useIR(ts: typeof import('typescript'), plugins: VueLanguagePluginReturn[], fileName: string, getSnapshot: () => ts.IScriptSnapshot, getParseSfcResult: () => SFCParseResult | undefined): Sfc;

338
node_modules/@vue/language-core/lib/virtualCode/ir.js generated vendored Normal file
View File

@@ -0,0 +1,338 @@
"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.useIR = useIR;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const alien_signals_1 = require("alien-signals");
const signals_1 = require("../utils/signals");
const normalize_1 = require("./normalize");
function useIR(ts, plugins, fileName, getSnapshot, getParseSfcResult) {
const getUntrackedSnapshot = () => {
const pausedSub = (0, alien_signals_1.setActiveSub)(undefined);
const res = getSnapshot();
(0, alien_signals_1.setActiveSub)(pausedSub);
return res;
};
const getContent = (0, alien_signals_1.computed)(() => {
return getSnapshot().getText(0, getSnapshot().getLength());
});
const getComments = (0, signals_1.computedArray)(() => {
return getParseSfcResult()?.descriptor.comments ?? [];
});
const getTemplate = useNullableSfcBlock('template', 'html', (0, alien_signals_1.computed)(() => getParseSfcResult()?.descriptor.template ?? undefined), (_block, base) => {
const getParseTemplateResult = useParseTemplateResult(base);
return mergeObject(base, {
get ast() {
return getParseTemplateResult().result?.ast;
},
get errors() {
return getParseTemplateResult().errors;
},
get warnings() {
return getParseTemplateResult().warnings;
},
});
});
const getScript = useNullableSfcBlock('script', 'js', (0, alien_signals_1.computed)(() => getParseSfcResult()?.descriptor.script ?? undefined), (block, base) => {
const getSrc = useAttrValue('__src', base, block);
const getAst = (0, alien_signals_1.computed)(() => {
for (const plugin of plugins) {
const ast = plugin.compileSFCScript?.(base.lang, base.content);
if (ast) {
return ast;
}
}
return ts.createSourceFile(fileName + '.' + base.lang, '', 99);
});
return mergeObject(base, {
get src() {
return getSrc();
},
get ast() {
return getAst();
},
});
});
const getOriginalScriptSetup = useNullableSfcBlock('scriptSetup', 'js', (0, alien_signals_1.computed)(() => getParseSfcResult()?.descriptor.scriptSetup ?? undefined), (block, base) => {
const getGeneric = useAttrValue('__generic', base, block);
const getAst = (0, alien_signals_1.computed)(() => {
for (const plugin of plugins) {
const ast = plugin.compileSFCScript?.(base.lang, base.content);
if (ast) {
return ast;
}
}
return ts.createSourceFile(fileName + '.' + base.lang, '', 99);
});
return mergeObject(base, {
get generic() {
return getGeneric();
},
get ast() {
return getAst();
},
});
});
const hasScript = (0, alien_signals_1.computed)(() => !!getParseSfcResult()?.descriptor.script);
const hasScriptSetup = (0, alien_signals_1.computed)(() => !!getParseSfcResult()?.descriptor.scriptSetup);
const getScriptSetup = (0, alien_signals_1.computed)(() => {
if (!hasScript() && !hasScriptSetup()) {
// #region monkey fix: https://github.com/vuejs/language-tools/pull/2113
return {
content: '',
lang: 'ts',
name: '',
start: 0,
end: 0,
startTagEnd: 0,
endTagStart: 0,
generic: undefined,
genericOffset: 0,
attrs: {},
ast: ts.createSourceFile('', '', 99, false, ts.ScriptKind.TS),
};
}
return getOriginalScriptSetup();
});
const styles = (0, signals_1.reactiveArray)(() => getParseSfcResult()?.descriptor.styles ?? [], (getBlock, i) => {
const base = useSfcBlock('style_' + i, 'css', getBlock);
const getSrc = useAttrValue('__src', base, getBlock);
const getModule = useAttrValue('__module', base, getBlock);
const getScoped = (0, alien_signals_1.computed)(() => !!getBlock().scoped);
const getIr = (0, alien_signals_1.computed)(() => {
for (const plugin of plugins) {
const ast = plugin.compileSFCStyle?.(base.lang, base.content);
if (ast) {
return ast;
}
}
});
const getImports = (0, signals_1.computedArray)(() => getIr()?.imports ?? [], (oldItem, newItem) => oldItem.text === newItem.text && oldItem.offset === newItem.offset);
const getBindings = (0, signals_1.computedArray)(() => getIr()?.bindings ?? [], (oldItem, newItem) => oldItem.text === newItem.text && oldItem.offset === newItem.offset);
const getClassNames = (0, signals_1.computedArray)(() => getIr()?.classNames ?? [], (oldItem, newItem) => oldItem.text === newItem.text && oldItem.offset === newItem.offset);
return () => mergeObject(base, {
get src() {
return getSrc();
},
get module() {
return getModule();
},
get scoped() {
return getScoped();
},
get imports() {
return getImports();
},
get bindings() {
return getBindings();
},
get classNames() {
return getClassNames();
},
});
});
const customBlocks = (0, signals_1.reactiveArray)(() => getParseSfcResult()?.descriptor.customBlocks ?? [], (getBlock, i) => {
const base = useSfcBlock('custom_block_' + i, 'txt', getBlock);
const getType = (0, alien_signals_1.computed)(() => getBlock().type);
return () => mergeObject(base, {
get type() {
return getType();
},
});
});
return {
get content() {
return getContent();
},
get comments() {
return getComments();
},
get template() {
return getTemplate();
},
get script() {
return getScript();
},
get scriptSetup() {
return getScriptSetup();
},
get styles() {
return styles;
},
get customBlocks() {
return customBlocks;
},
};
function useParseTemplateResult(base) {
return (0, alien_signals_1.computed)(lastResult => {
if (lastResult?.template === base.content) {
return lastResult;
}
// incremental update
if (lastResult?.result && lastResult.plugin?.updateSFCTemplate
&& !lastResult.errors.length
&& !lastResult.warnings.length) {
const change = getUntrackedSnapshot().getChangeRange(lastResult.snapshot);
if (change) {
const pausedSub = (0, alien_signals_1.setActiveSub)(undefined);
const templateOffset = base.startTagEnd;
(0, alien_signals_1.setActiveSub)(pausedSub);
const newText = getUntrackedSnapshot().getText(change.span.start, change.span.start + change.newLength);
const newResult = lastResult.plugin.updateSFCTemplate(lastResult.result, {
start: change.span.start - templateOffset,
end: change.span.start - templateOffset + change.span.length,
newText,
});
if (newResult) {
return {
snapshot: getUntrackedSnapshot(),
template: base.content,
result: newResult,
plugin: lastResult.plugin,
errors: [],
warnings: [],
};
}
}
}
const errors = [];
const warnings = [];
const [nodeTransforms, directiveTransforms] = CompilerDOM.getBaseTransformPreset();
let options = {
onError: err => errors.push(err),
onWarn: err => warnings.push(err),
expressionPlugins: ['typescript'],
nodeTransforms,
directiveTransforms,
};
for (const plugin of plugins) {
if (plugin.resolveTemplateCompilerOptions) {
options = plugin.resolveTemplateCompilerOptions(options);
}
}
for (const plugin of plugins) {
try {
const result = plugin.compileSFCTemplate?.(base.lang, base.content, options);
if (result) {
(0, normalize_1.normalizeTemplateAST)(result.ast);
return {
snapshot: getUntrackedSnapshot(),
template: base.content,
result,
plugin,
errors,
warnings,
};
}
}
catch (e) {
return {
snapshot: getUntrackedSnapshot(),
template: base.content,
plugin,
errors: [e],
warnings,
};
}
}
return {
snapshot: getUntrackedSnapshot(),
template: base.content,
errors,
warnings,
};
});
}
function useNullableSfcBlock(name, defaultLang, getBlock, resolve) {
const hasBlock = (0, alien_signals_1.computed)(() => !!getBlock());
return (0, alien_signals_1.computed)(() => {
if (!hasBlock()) {
return;
}
const _block = (0, alien_signals_1.computed)(() => getBlock());
return resolve(_block, useSfcBlock(name, defaultLang, _block));
});
}
function useSfcBlock(name, defaultLang, getBlock) {
const getLang = (0, alien_signals_1.computed)(() => getBlock().lang ?? defaultLang);
const getAttrs = (0, alien_signals_1.computed)(() => getBlock().attrs); // TODO: computed it
const getContent = (0, alien_signals_1.computed)(() => getBlock().content);
const getStartTagEnd = (0, alien_signals_1.computed)(() => getBlock().loc.start.offset);
const getEndTagStart = (0, alien_signals_1.computed)(() => getBlock().loc.end.offset);
const getStart = (0, alien_signals_1.computed)(() => getUntrackedSnapshot().getText(0, getStartTagEnd()).lastIndexOf('<' + getBlock().type));
const getEnd = (0, alien_signals_1.computed)(() => getEndTagStart()
+ getUntrackedSnapshot().getText(getEndTagStart(), getUntrackedSnapshot().getLength()).indexOf('>') + 1);
return {
name,
get lang() {
return getLang();
},
get attrs() {
return getAttrs();
},
get content() {
return getContent();
},
get startTagEnd() {
return getStartTagEnd();
},
get endTagStart() {
return getEndTagStart();
},
get start() {
return getStart();
},
get end() {
return getEnd();
},
};
}
function useAttrValue(key, base, getBlock) {
return (0, alien_signals_1.computed)(() => {
const val = getBlock()[key];
if (typeof val === 'object') {
return {
...val,
offset: base.start + val.offset,
};
}
return val;
});
}
}
function mergeObject(a, b) {
return Object.defineProperties(a, Object.getOwnPropertyDescriptors(b));
}
//# sourceMappingURL=ir.js.map

View File

@@ -0,0 +1,2 @@
import * as CompilerDOM from '@vue/compiler-dom';
export declare function normalizeTemplateAST(root: CompilerDOM.RootNode): void;

View File

@@ -0,0 +1,205 @@
"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.normalizeTemplateAST = normalizeTemplateAST;
const CompilerDOM = __importStar(require("@vue/compiler-dom"));
const forEachTemplateNode_1 = require("../utils/forEachTemplateNode");
// See https://github.com/vuejs/core/issues/3498
function normalizeTemplateAST(root) {
// @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'],
};
for (const { children, codegenNode, props } of (0, forEachTemplateNode_1.forEachElementNode)(root)) {
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (child.type !== CompilerDOM.NodeTypes.ELEMENT) {
continue;
}
const forNode = getVForNode(child, transformContext);
if (forNode) {
children[i] = forNode;
continue;
}
const ifNode = getVIfNode(child, transformContext);
if (ifNode) {
const normalized = normalizeIfBranch(ifNode, children, i);
children.splice(i, normalized.end - i + 1, normalized.node);
continue;
}
}
// #4539
if (codegenNode
&& 'props' in codegenNode
&& codegenNode.props
&& 'properties' in codegenNode.props) {
for (const p of codegenNode.props.properties) {
if (p.key.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& p.key.content === 'key'
&& !p.key.isHandlerKey
&& !p.key.loc.source
&& p.value.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& p.value.constType === CompilerDOM.ConstantTypes.NOT_CONSTANT) {
const contentBeforeValue = root.loc.source.slice(0, p.value.loc.start.offset);
const argOffset = contentBeforeValue.lastIndexOf('key');
props.push({
type: CompilerDOM.NodeTypes.DIRECTIVE,
name: 'bind',
exp: p.value,
loc: p.loc,
arg: {
...p.key,
loc: {
start: { line: -1, column: -1, offset: argOffset },
end: { line: -1, column: -1, offset: argOffset + 'key'.length },
source: 'key',
},
},
modifiers: [],
});
break;
}
}
}
}
}
function normalizeIfBranch(ifNode, children, start) {
let end = start;
let comments = [];
for (let i = start + 1; i < children.length; i++) {
const sibling = children[i];
if (sibling.type === CompilerDOM.NodeTypes.COMMENT) {
comments.push(sibling);
continue;
}
if (sibling.type === CompilerDOM.NodeTypes.TEXT && !sibling.content.trim()) {
continue;
}
const elseBranch = getVElseDirective(sibling);
if (elseBranch) {
const branchNode = {
...elseBranch.element,
props: elseBranch.element.props.filter(prop => prop !== elseBranch.directive),
};
const branch = createIfBranch(branchNode, elseBranch.directive);
if (comments.length) {
branch.children = [...comments, ...branch.children];
}
ifNode.branches.push(branch);
comments = [];
end = i;
continue;
}
break;
}
return { node: ifNode, end };
}
// source: https://github.com/vuejs/core/blob/25ebe3a42cd80ac0256355c2740a0258cdd7419d/packages/compiler-core/src/transforms/vIf.ts#L207
function createIfBranch(node, dir) {
const isTemplateIf = node.tagType === CompilerDOM.ElementTypes.TEMPLATE;
return {
type: CompilerDOM.NodeTypes.IF_BRANCH,
loc: node.loc,
condition: dir.name === 'else' ? undefined : dir.exp,
children: isTemplateIf && !CompilerDOM.findDir(node, 'for') && !CompilerDOM.findDir(node, 'slot')
? node.children
: [node],
userKey: CompilerDOM.findProp(node, 'key'),
isTemplateIf,
};
}
function getVElseDirective(node) {
if (node.type !== CompilerDOM.NodeTypes.ELEMENT) {
return;
}
const directive = node.props.find((prop) => prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& (prop.name === 'else-if' || prop.name === 'else'));
if (directive) {
return {
element: node,
directive,
};
}
}
function getVForNode(node, transformContext) {
const forDirective = node.props.find((prop) => prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'for');
if (forDirective) {
let forNode;
CompilerDOM.processFor(node, forDirective, transformContext, _forNode => {
forNode = { ..._forNode };
return undefined;
});
if (forNode) {
forNode.children = [{
...node,
props: node.props.filter(prop => prop !== forDirective),
}];
return forNode;
}
}
}
function getVIfNode(node, transformContext) {
const ifDirective = node.props.find((prop) => prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'if');
if (ifDirective) {
let ifNode;
CompilerDOM.processIf(node, ifDirective, transformContext, _ifNode => {
ifNode = { ..._ifNode };
return undefined;
});
if (ifNode) {
for (const branch of ifNode.branches) {
branch.children = [{
...node,
props: node.props.filter(prop => prop !== ifDirective),
}];
}
return ifNode;
}
}
}
//# sourceMappingURL=normalize.js.map