@volar/vue-language-core
Advanced tools
Comparing version 1.0.16 to 1.0.17
import { Segment } from '@volar/source-map'; | ||
import type { PositionCapabilities, TeleportMappingData } from '@volar/language-core'; | ||
import type { FileRangeCapabilities, MirrorBehaviorCapabilities } from '@volar/language-core'; | ||
import * as SourceMaps from '@volar/source-map'; | ||
@@ -11,6 +11,6 @@ import type * as ts from 'typescript/lib/tsserverlibrary'; | ||
import type { ResolvedVueCompilerOptions } from '../types'; | ||
export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), fileName: string, sfc: Sfc, lang: string, scriptRanges: ScriptRanges | undefined, scriptSetupRanges: ScriptSetupRanges | undefined, cssVars: ReturnType<typeof collectCssVars>, cssModuleClasses: ReturnType<typeof collectStyleCssClasses>, cssScopedClasses: ReturnType<typeof collectStyleCssClasses>, htmlGen: ReturnType<typeof templateGen['generate']> | undefined, compilerOptions: ts.CompilerOptions, vueCompilerOptions: ResolvedVueCompilerOptions, codeGen?: Segment<PositionCapabilities>[], teleports?: SourceMaps.Mapping<TeleportMappingData>[]): { | ||
codeGen: SourceMaps.SegmentWithData<PositionCapabilities>[]; | ||
export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), fileName: string, sfc: Sfc, lang: string, scriptRanges: ScriptRanges | undefined, scriptSetupRanges: ScriptSetupRanges | undefined, cssVars: ReturnType<typeof collectCssVars>, cssModuleClasses: ReturnType<typeof collectStyleCssClasses>, cssScopedClasses: ReturnType<typeof collectStyleCssClasses>, htmlGen: ReturnType<typeof templateGen['generate']> | undefined, compilerOptions: ts.CompilerOptions, vueCompilerOptions: ResolvedVueCompilerOptions, codeGen?: Segment<FileRangeCapabilities>[], mirrorBehaviorMappings?: SourceMaps.Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[]): { | ||
codeGen: SourceMaps.SegmentWithData<FileRangeCapabilities>[]; | ||
extraMappings: SourceMaps.Mapping<any>[]; | ||
teleports: SourceMaps.Mapping<TeleportMappingData>[]; | ||
mirrorBehaviorMappings: SourceMaps.Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[]; | ||
}; |
@@ -8,3 +8,3 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
const transform_1 = require("../utils/transform"); | ||
function generate(ts, fileName, sfc, lang, scriptRanges, scriptSetupRanges, cssVars, cssModuleClasses, cssScopedClasses, htmlGen, compilerOptions, vueCompilerOptions, codeGen = [], teleports = []) { | ||
function generate(ts, fileName, sfc, lang, scriptRanges, scriptSetupRanges, cssVars, cssModuleClasses, cssScopedClasses, htmlGen, compilerOptions, vueCompilerOptions, codeGen = [], mirrorBehaviorMappings = []) { | ||
var _a; | ||
@@ -64,3 +64,3 @@ const bypassDefineComponent = lang === 'js' || lang === 'jsx'; | ||
extraMappings, | ||
teleports, | ||
mirrorBehaviorMappings, | ||
}; | ||
@@ -381,3 +381,3 @@ function writeScriptSetupTypes() { | ||
else { | ||
if (htmlGen === null || htmlGen === void 0 ? void 0 : htmlGen.hasSlot) { | ||
if (!vueCompilerOptions.skipTemplateCodegen && (htmlGen === null || htmlGen === void 0 ? void 0 : htmlGen.hasSlot)) { | ||
usedTypes.WithTemplateSlots = true; | ||
@@ -480,7 +480,7 @@ codeGen.push(`return {} as __VLS_WithTemplateSlots<typeof __VLS_publicComponent, ReturnType<typeof __VLS_template>>;\n`); | ||
codeGen.push(',\n'); | ||
teleports.push({ | ||
mirrorBehaviorMappings.push({ | ||
sourceRange: [scriptStart, scriptEnd], | ||
generatedRange: [templateStart, templateEnd], | ||
data: { | ||
toSourceCapabilities: { | ||
data: [ | ||
{ | ||
definition: true, | ||
@@ -490,3 +490,3 @@ references: true, | ||
}, | ||
toGenedCapabilities: { | ||
{ | ||
definition: true, | ||
@@ -496,3 +496,3 @@ references: true, | ||
}, | ||
}, | ||
], | ||
}); | ||
@@ -499,0 +499,0 @@ } |
@@ -1,8 +0,9 @@ | ||
import { PositionCapabilities } from '@volar/language-core'; | ||
import { FileRangeCapabilities } from '@volar/language-core'; | ||
import * as CompilerDOM from '@vue/compiler-dom'; | ||
import type * as ts from 'typescript/lib/tsserverlibrary'; | ||
import { ResolvedVueCompilerOptions } from '../types'; | ||
export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), vueCompilerOptions: ResolvedVueCompilerOptions, sourceTemplate: string, sourceLang: string, templateAst: CompilerDOM.RootNode, hasScriptSetup: boolean, cssScopedClasses?: string[]): { | ||
codeGen: import("@volar/source-map").SegmentWithData<PositionCapabilities>[]; | ||
formatCodeGen: import("@volar/source-map").SegmentWithData<PositionCapabilities>[]; | ||
cssCodeGen: import("@volar/source-map").SegmentWithData<PositionCapabilities>[]; | ||
export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: ResolvedVueCompilerOptions, sourceTemplate: string, sourceLang: string, templateAst: CompilerDOM.RootNode, hasScriptSetup: boolean, cssScopedClasses?: string[]): { | ||
codeGen: import("@volar/source-map").SegmentWithData<FileRangeCapabilities>[]; | ||
formatCodeGen: import("@volar/source-map").SegmentWithData<FileRangeCapabilities>[]; | ||
cssCodeGen: import("@volar/source-map").SegmentWithData<FileRangeCapabilities>[]; | ||
tagNames: Record<string, number[]>; | ||
@@ -9,0 +10,0 @@ identifiers: Set<string>; |
@@ -24,8 +24,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
const languageModule = { | ||
createSourceFile(fileName, snapshot) { | ||
createFile(fileName, snapshot) { | ||
if (vueCompilerOptions.extensions.some(ext => fileName.endsWith(ext))) { | ||
return new sourceFile_1.VueSourceFile(fileName, snapshot, ts, vueLanguagePlugin); | ||
return new sourceFile_1.VueFile(fileName, snapshot, ts, vueLanguagePlugin); | ||
} | ||
}, | ||
updateSourceFile(sourceFile, snapshot) { | ||
updateFile(sourceFile, snapshot) { | ||
sourceFile.update(snapshot); | ||
@@ -32,0 +32,0 @@ }, |
@@ -1,2 +0,2 @@ | ||
import type { TextRange } from '@volar/language-core'; | ||
import type { TextRange } from '../types'; | ||
import type * as ts from 'typescript/lib/tsserverlibrary'; | ||
@@ -3,0 +3,0 @@ export interface ScriptRanges extends ReturnType<typeof parseScriptRanges> { |
import type * as ts from 'typescript/lib/tsserverlibrary'; | ||
import type { TextRange } from '@volar/language-core'; | ||
import type { TextRange } from '../types'; | ||
export interface ScriptSetupRanges extends ReturnType<typeof parseUnuseScriptSetupRanges> { | ||
@@ -4,0 +4,0 @@ } |
import type * as ts from 'typescript/lib/tsserverlibrary'; | ||
import type { TextRange } from '@volar/language-core'; | ||
import type { TextRange } from '../types'; | ||
export interface ScriptSetupRanges extends ReturnType<typeof parseScriptSetupRanges> { | ||
@@ -4,0 +4,0 @@ } |
@@ -33,3 +33,3 @@ const source_map_1 = require("@volar/source-map"); | ||
codeGen.push('\n</template>'); | ||
const file2VueSourceMap = new source_map_1.SourceMapBase((0, source_map_1.buildMappings)(codeGen)); | ||
const file2VueSourceMap = new source_map_1.SourceMap((0, source_map_1.buildMappings)(codeGen)); | ||
const sfc = (0, parseSfc_1.parse)((0, source_map_1.toString)(codeGen)); | ||
@@ -36,0 +36,0 @@ if (sfc.descriptor.template) { |
import { Sfc, VueLanguagePlugin } from '../types'; | ||
import { TextRange } from '@volar/language-core'; | ||
import { TextRange } from '../types'; | ||
declare const plugin: VueLanguagePlugin; | ||
@@ -4,0 +4,0 @@ export default plugin; |
@@ -13,47 +13,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
const ts = modules.typescript; | ||
const _fileName = (0, reactivity_1.shallowRef)(''); | ||
const _sfc = (0, reactivity_1.shallowRef)({}); | ||
const lang = (0, reactivity_1.computed)(() => { | ||
let lang = !_sfc.value.script && !_sfc.value.scriptSetup ? 'ts' | ||
: _sfc.value.scriptSetup && _sfc.value.scriptSetup.lang !== 'js' ? _sfc.value.scriptSetup.lang | ||
: _sfc.value.script && _sfc.value.script.lang !== 'js' ? _sfc.value.script.lang | ||
: 'js'; | ||
if (vueCompilerOptions.jsxTemplates) { | ||
if (lang === 'js') { | ||
lang = 'jsx'; | ||
} | ||
else if (lang === 'ts') { | ||
lang = 'tsx'; | ||
} | ||
} | ||
return lang; | ||
}); | ||
const cssVars = (0, reactivity_1.computed)(() => collectCssVars(_sfc.value)); | ||
const scriptRanges = (0, reactivity_1.computed)(() => _sfc.value.scriptAst | ||
? (0, scriptRanges_1.parseScriptRanges)(ts, _sfc.value.scriptAst, !!_sfc.value.scriptSetup, false) | ||
: undefined); | ||
const scriptSetupRanges = (0, reactivity_1.computed)(() => _sfc.value.scriptSetupAst | ||
? (0, scriptSetupRanges_1.parseScriptSetupRanges)(ts, _sfc.value.scriptSetupAst) | ||
: undefined); | ||
const cssModuleClasses = (0, reactivity_1.computed)(() => collectStyleCssClasses(_sfc.value, style => !!style.module)); | ||
const cssScopedClasses = (0, reactivity_1.computed)(() => collectStyleCssClasses(_sfc.value, style => { | ||
const setting = vueCompilerOptions.experimentalResolveStyleCssClasses; | ||
return (setting === 'scoped' && style.scoped) || setting === 'always'; | ||
})); | ||
const htmlGen = (0, reactivity_1.computed)(() => { | ||
var _a, _b, _c, _d; | ||
const templateAst = _sfc.value.getTemplateAst(); | ||
if (!templateAst) | ||
return; | ||
return templateGen.generate(ts, vueCompilerOptions, (_b = (_a = _sfc.value.template) === null || _a === void 0 ? void 0 : _a.content) !== null && _b !== void 0 ? _b : '', (_d = (_c = _sfc.value.template) === null || _c === void 0 ? void 0 : _c.lang) !== null && _d !== void 0 ? _d : 'html', templateAst, !!_sfc.value.scriptSetup, Object.values(cssScopedClasses.value).map(style => style.classNames).flat()); | ||
}); | ||
const tsxGen = (0, reactivity_1.computed)(() => (0, script_1.generate)(ts, _fileName.value, _sfc.value, lang.value, scriptRanges.value, scriptSetupRanges.value, cssVars.value, cssModuleClasses.value, cssScopedClasses.value, htmlGen.value, compilerOptions, vueCompilerOptions)); | ||
const instances = new WeakMap(); | ||
return { | ||
version: 1, | ||
getEmbeddedFileNames(fileName, sfc) { | ||
_fileName.value = fileName; | ||
_sfc.value = sfc; | ||
const tsx = useTsx(fileName, sfc); | ||
const fileNames = []; | ||
if (['js', 'ts', 'jsx', 'tsx'].includes(lang.value)) { | ||
fileNames.push(fileName + '.' + lang.value); | ||
if (['js', 'ts', 'jsx', 'tsx'].includes(tsx.lang.value)) { | ||
fileNames.push(fileName + '.' + tsx.lang.value); | ||
} | ||
@@ -68,7 +31,6 @@ if (sfc.template) { | ||
var _a, _b; | ||
_fileName.value = fileName; | ||
_sfc.value = sfc; | ||
const _tsx = useTsx(fileName, sfc); | ||
const suffix = embeddedFile.fileName.replace(fileName, ''); | ||
if (suffix === '.' + lang.value) { | ||
embeddedFile.kind = language_core_1.EmbeddedFileKind.TypeScriptHostFile; | ||
if (suffix === '.' + _tsx.lang.value) { | ||
embeddedFile.kind = language_core_1.FileKind.TypeScriptHostFile; | ||
embeddedFile.capabilities = { | ||
@@ -82,7 +44,7 @@ diagnostic: true, | ||
}; | ||
const tsx = tsxGen.value; | ||
const tsx = _tsx.tsxGen.value; | ||
if (tsx) { | ||
embeddedFile.content = [...tsx.codeGen]; | ||
embeddedFile.extraMappings = [...tsx.extraMappings]; | ||
embeddedFile.teleportMappings = [...tsx.teleports]; | ||
embeddedFile.mirrorBehaviorMappings = [...tsx.mirrorBehaviorMappings]; | ||
} | ||
@@ -100,6 +62,6 @@ } | ||
}; | ||
if (htmlGen.value) { | ||
embeddedFile.content = [...htmlGen.value.formatCodeGen]; | ||
if (_tsx.htmlGen.value) { | ||
embeddedFile.content = [..._tsx.htmlGen.value.formatCodeGen]; | ||
} | ||
for (const cssVar of cssVars.value) { | ||
for (const cssVar of _tsx.cssVars.value) { | ||
embeddedFile.content.push('\n\n'); | ||
@@ -120,4 +82,4 @@ for (const range of cssVar.ranges) { | ||
embeddedFile.parentFileName = fileName + '.template.' + ((_b = sfc.template) === null || _b === void 0 ? void 0 : _b.lang); | ||
if (htmlGen.value) { | ||
embeddedFile.content = [...htmlGen.value.cssCodeGen]; | ||
if (_tsx.htmlGen.value) { | ||
embeddedFile.content = [..._tsx.htmlGen.value.cssCodeGen]; | ||
} | ||
@@ -127,2 +89,51 @@ } | ||
}; | ||
function useTsx(fileName, sfc) { | ||
if (!instances.has(sfc)) { | ||
instances.set(sfc, createTsx(fileName, sfc)); | ||
} | ||
return instances.get(sfc); | ||
} | ||
function createTsx(fileName, _sfc) { | ||
const lang = (0, reactivity_1.computed)(() => { | ||
let lang = !_sfc.script && !_sfc.scriptSetup ? 'ts' | ||
: _sfc.scriptSetup && _sfc.scriptSetup.lang !== 'js' ? _sfc.scriptSetup.lang | ||
: _sfc.script && _sfc.script.lang !== 'js' ? _sfc.script.lang | ||
: 'js'; | ||
if (vueCompilerOptions.jsxTemplates) { | ||
if (lang === 'js') { | ||
lang = 'jsx'; | ||
} | ||
else if (lang === 'ts') { | ||
lang = 'tsx'; | ||
} | ||
} | ||
return lang; | ||
}); | ||
const cssVars = (0, reactivity_1.computed)(() => collectCssVars(_sfc)); | ||
const scriptRanges = (0, reactivity_1.computed)(() => _sfc.scriptAst | ||
? (0, scriptRanges_1.parseScriptRanges)(ts, _sfc.scriptAst, !!_sfc.scriptSetup, false) | ||
: undefined); | ||
const scriptSetupRanges = (0, reactivity_1.computed)(() => _sfc.scriptSetupAst | ||
? (0, scriptSetupRanges_1.parseScriptSetupRanges)(ts, _sfc.scriptSetupAst) | ||
: undefined); | ||
const cssModuleClasses = (0, reactivity_1.computed)(() => collectStyleCssClasses(_sfc, style => !!style.module)); | ||
const cssScopedClasses = (0, reactivity_1.computed)(() => collectStyleCssClasses(_sfc, style => { | ||
const setting = vueCompilerOptions.experimentalResolveStyleCssClasses; | ||
return (setting === 'scoped' && style.scoped) || setting === 'always'; | ||
})); | ||
const htmlGen = (0, reactivity_1.computed)(() => { | ||
var _a, _b, _c, _d; | ||
const templateAst = _sfc.templateAst; | ||
if (!templateAst) | ||
return; | ||
return templateGen.generate(ts, compilerOptions, vueCompilerOptions, (_b = (_a = _sfc.template) === null || _a === void 0 ? void 0 : _a.content) !== null && _b !== void 0 ? _b : '', (_d = (_c = _sfc.template) === null || _c === void 0 ? void 0 : _c.lang) !== null && _d !== void 0 ? _d : 'html', templateAst, !!_sfc.scriptSetup, Object.values(cssScopedClasses.value).map(style => style.classNames).flat()); | ||
}); | ||
const tsxGen = (0, reactivity_1.computed)(() => (0, script_1.generate)(ts, fileName, _sfc, lang.value, scriptRanges.value, scriptSetupRanges.value, cssVars.value, cssModuleClasses.value, cssScopedClasses.value, htmlGen.value, compilerOptions, vueCompilerOptions)); | ||
return { | ||
lang, | ||
tsxGen, | ||
htmlGen, | ||
cssVars, | ||
}; | ||
} | ||
}; | ||
@@ -129,0 +140,0 @@ exports.default = plugin; |
@@ -1,6 +0,6 @@ | ||
import { DocumentCapabilities, EmbeddedFile, EmbeddedFileKind, PositionCapabilities, SourceFile, TeleportMappingData } from '@volar/language-core'; | ||
import { FileCapabilities, VirtualFile, FileKind, FileRangeCapabilities, MirrorBehaviorCapabilities } from '@volar/language-core'; | ||
import { Mapping, Segment } from '@volar/source-map'; | ||
import * as CompilerDom from '@vue/compiler-dom'; | ||
import { SFCParseResult } from '@vue/compiler-sfc'; | ||
import { ComputedRef, Ref } from '@vue/reactivity'; | ||
import { SFCBlock, SFCParseResult, SFCScriptBlock, SFCStyleBlock, SFCTemplateBlock } from '@vue/compiler-sfc'; | ||
import { ComputedRef } from '@vue/reactivity'; | ||
import type * as ts from 'typescript/lib/tsserverlibrary'; | ||
@@ -11,16 +11,15 @@ import { Sfc, SfcBlock, VueLanguagePlugin } from './types'; | ||
parentFileName?: string; | ||
kind: EmbeddedFileKind; | ||
capabilities: DocumentCapabilities; | ||
content: Segment<PositionCapabilities>[]; | ||
extraMappings: Mapping<PositionCapabilities>[]; | ||
teleportMappings: Mapping<TeleportMappingData>[]; | ||
kind: FileKind; | ||
capabilities: FileCapabilities; | ||
content: Segment<FileRangeCapabilities>[]; | ||
extraMappings: Mapping<FileRangeCapabilities>[]; | ||
mirrorBehaviorMappings: Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[]; | ||
constructor(fileName: string); | ||
} | ||
export declare class VueSourceFile implements SourceFile { | ||
export declare class VueFile implements VirtualFile { | ||
fileName: string; | ||
private pscriptSnapshot; | ||
snapshot: ts.IScriptSnapshot; | ||
private ts; | ||
private plugins; | ||
static parsedSfcCache: { | ||
fileName: string; | ||
parsedSfcCache: { | ||
snapshot: ts.IScriptSnapshot; | ||
@@ -30,4 +29,3 @@ sfc: SFCParseResult; | ||
} | undefined; | ||
static compiledSFCTemplateCache: { | ||
fileName: string; | ||
compiledSFCTemplateCache: { | ||
template: string; | ||
@@ -38,4 +36,6 @@ snapshot: ts.IScriptSnapshot; | ||
} | undefined; | ||
static getSFC(plugins: ReturnType<VueLanguagePlugin>[], fileName: string, snapshot: ts.IScriptSnapshot): SFCParseResult | undefined; | ||
static getCompiledSFCTemplate(plugins: ReturnType<VueLanguagePlugin>[], sourceFile: VueSourceFile, newSnapshot: ts.IScriptSnapshot): { | ||
capabilities: FileCapabilities; | ||
kind: FileKind; | ||
mappings: Mapping<FileRangeCapabilities>[]; | ||
get compiledSFCTemplate(): { | ||
errors: CompilerDom.CompilerError[]; | ||
@@ -45,37 +45,31 @@ warnings: CompilerDom.CompilerError[]; | ||
} | undefined; | ||
static current: import("@vue/reactivity").ShallowRef<VueSourceFile>; | ||
static _pluginEmbeddedFiles: ComputedRef<ComputedRef<{ | ||
file: VueEmbeddedFile; | ||
text: string; | ||
mappings: Mapping<PositionCapabilities>[]; | ||
}[]>[]>; | ||
static _allEmbeddeds: ComputedRef<{ | ||
file: VueEmbeddedFile; | ||
text: string; | ||
mappings: Mapping<PositionCapabilities>[]; | ||
}[]>; | ||
static _embeddeds: ComputedRef<EmbeddedFile[]>; | ||
get mainScriptName(): string; | ||
get embeddedFiles(): VirtualFile[]; | ||
sfc: Sfc; | ||
sfcBlocks: ComputedRef<Record<string, SfcBlock>>; | ||
kind: EmbeddedFileKind; | ||
capabilities: DocumentCapabilities; | ||
get mappings(): Mapping<PositionCapabilities>[]; | ||
get text(): string; | ||
get compiledSFCTemplate(): { | ||
_sfcBlocks: ComputedRef<Record<string, SfcBlock>>; | ||
_compiledSfcTemplate: ComputedRef<{ | ||
errors: CompilerDom.CompilerError[]; | ||
warnings: CompilerDom.CompilerError[]; | ||
ast: CompilerDom.RootNode | undefined; | ||
} | undefined; | ||
get tsFileName(): string; | ||
get embeddeds(): EmbeddedFile[]; | ||
_snapshot: Ref<ts.IScriptSnapshot>; | ||
_mappings: ComputedRef<Mapping<PositionCapabilities>[]>; | ||
_allEmbeddeds: import("@vue/reactivity").ShallowRef<{ | ||
} | undefined>; | ||
_pluginEmbeddedFiles: ComputedRef<{ | ||
file: VueEmbeddedFile; | ||
text: string; | ||
mappings: Mapping<PositionCapabilities>[]; | ||
snapshot: ts.IScriptSnapshot; | ||
mappings: Mapping<FileRangeCapabilities>[]; | ||
}[]>[]; | ||
_allEmbeddedFiles: ComputedRef<{ | ||
file: VueEmbeddedFile; | ||
snapshot: ts.IScriptSnapshot; | ||
mappings: Mapping<FileRangeCapabilities>[]; | ||
}[]>; | ||
_embeddeds: import("@vue/reactivity").ShallowRef<EmbeddedFile[]>; | ||
constructor(fileName: string, pscriptSnapshot: ts.IScriptSnapshot, ts: typeof import('typescript/lib/tsserverlibrary'), plugins: ReturnType<VueLanguagePlugin>[]); | ||
update(newScriptSnapshot: ts.IScriptSnapshot, init?: boolean): void; | ||
_embeddedFiles: ComputedRef<VirtualFile[]>; | ||
constructor(fileName: string, snapshot: ts.IScriptSnapshot, ts: typeof import('typescript/lib/tsserverlibrary'), plugins: ReturnType<VueLanguagePlugin>[]); | ||
update(newScriptSnapshot: ts.IScriptSnapshot): void; | ||
parseSfc(): SFCParseResult | undefined; | ||
updateTemplate(block: SFCTemplateBlock | null): void; | ||
updateScript(block: SFCScriptBlock | null): void; | ||
updateScriptSetup(block: SFCScriptBlock | null): void; | ||
updateStyles(blocks: SFCStyleBlock[]): void; | ||
updateCustomBlocks(blocks: SFCBlock[]): void; | ||
updateBlock<T>(oldBlock: T, newBlock: T): void; | ||
} |
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.VueSourceFile = exports.VueEmbeddedFile = void 0; | ||
exports.VueFile = exports.VueEmbeddedFile = void 0; | ||
const language_core_1 = require("@volar/language-core"); | ||
@@ -9,174 +9,58 @@ const source_map_1 = require("@volar/source-map"); | ||
this.fileName = fileName; | ||
this.kind = language_core_1.EmbeddedFileKind.TextFile; | ||
this.kind = language_core_1.FileKind.TextFile; | ||
this.capabilities = {}; | ||
this.content = []; | ||
this.extraMappings = []; | ||
this.teleportMappings = []; | ||
this.mirrorBehaviorMappings = []; | ||
} | ||
} | ||
exports.VueEmbeddedFile = VueEmbeddedFile; | ||
class VueSourceFile { | ||
static getSFC(plugins, fileName, snapshot) { | ||
var _a, _b, _c; | ||
if (((_a = VueSourceFile.parsedSfcCache) === null || _a === void 0 ? void 0 : _a.snapshot) === snapshot) { | ||
return VueSourceFile.parsedSfcCache.sfc; | ||
} | ||
// incremental update | ||
if (((_b = VueSourceFile.parsedSfcCache) === null || _b === void 0 ? void 0 : _b.fileName) === fileName && VueSourceFile.parsedSfcCache.plugin.updateSFC) { | ||
const change = snapshot.getChangeRange(VueSourceFile.parsedSfcCache.snapshot); | ||
if (change) { | ||
const newSfc = VueSourceFile.parsedSfcCache.plugin.updateSFC(VueSourceFile.parsedSfcCache.sfc, { | ||
start: change.span.start, | ||
end: change.span.start + change.span.length, | ||
newText: snapshot.getText(change.span.start, change.span.start + change.newLength), | ||
}); | ||
if (newSfc) { | ||
VueSourceFile.parsedSfcCache.snapshot = snapshot; | ||
VueSourceFile.parsedSfcCache.sfc = newSfc; | ||
return newSfc; | ||
} | ||
} | ||
} | ||
for (const plugin of plugins) { | ||
const sfc = (_c = plugin.parseSFC) === null || _c === void 0 ? void 0 : _c.call(plugin, fileName, snapshot.getText(0, snapshot.getLength())); | ||
if (sfc) { | ||
if (!sfc.errors.length) { | ||
VueSourceFile.parsedSfcCache = { | ||
fileName, | ||
snapshot, | ||
sfc, | ||
plugin, | ||
}; | ||
} | ||
return sfc; | ||
} | ||
} | ||
} | ||
static getCompiledSFCTemplate(plugins, sourceFile, newSnapshot) { | ||
var _a, _b, _c, _d, _e; | ||
if (((_a = VueSourceFile.compiledSFCTemplateCache) === null || _a === void 0 ? void 0 : _a.snapshot) === newSnapshot) { | ||
return { | ||
errors: [], | ||
warnings: [], | ||
ast: VueSourceFile.compiledSFCTemplateCache.result.ast, | ||
}; | ||
} | ||
if (((_b = VueSourceFile.compiledSFCTemplateCache) === null || _b === void 0 ? void 0 : _b.fileName) === sourceFile.fileName | ||
&& VueSourceFile.compiledSFCTemplateCache.template === ((_c = sourceFile.sfc.template) === null || _c === void 0 ? void 0 : _c.content)) { | ||
return { | ||
errors: [], | ||
warnings: [], | ||
ast: VueSourceFile.compiledSFCTemplateCache.result.ast, | ||
}; | ||
} | ||
if (sourceFile.sfc.template) { | ||
// incremental update | ||
if ((_d = VueSourceFile.compiledSFCTemplateCache) === null || _d === void 0 ? void 0 : _d.plugin.updateSFCTemplate) { | ||
const change = newSnapshot.getChangeRange(VueSourceFile.compiledSFCTemplateCache.snapshot); | ||
const templateOffset = sourceFile.sfc.template.startTagEnd; | ||
if (change) { | ||
const newText = newSnapshot.getText(change.span.start, change.span.start + change.newLength); | ||
const newResult = VueSourceFile.compiledSFCTemplateCache.plugin.updateSFCTemplate(VueSourceFile.compiledSFCTemplateCache.result, { | ||
start: change.span.start - templateOffset, | ||
end: change.span.start + change.span.length - templateOffset, | ||
newText, | ||
}); | ||
if (newResult) { | ||
VueSourceFile.compiledSFCTemplateCache.template = sourceFile.sfc.template.content; | ||
VueSourceFile.compiledSFCTemplateCache.snapshot = newSnapshot; | ||
VueSourceFile.compiledSFCTemplateCache.result = newResult; | ||
return { | ||
errors: [], | ||
warnings: [], | ||
ast: newResult.ast, | ||
}; | ||
} | ||
} | ||
} | ||
const errors = []; | ||
const warnings = []; | ||
let options = { | ||
onError: (err) => errors.push(err), | ||
onWarn: (err) => warnings.push(err), | ||
expressionPlugins: ['typescript'], | ||
}; | ||
for (const plugin of plugins) { | ||
if (plugin.resolveTemplateCompilerOptions) { | ||
options = plugin.resolveTemplateCompilerOptions(options); | ||
} | ||
} | ||
for (const plugin of plugins) { | ||
let result; | ||
try { | ||
result = (_e = plugin.compileSFCTemplate) === null || _e === void 0 ? void 0 : _e.call(plugin, sourceFile.sfc.template.lang, sourceFile.sfc.template.content, options); | ||
} | ||
catch (e) { | ||
const err = e; | ||
errors.push(err); | ||
} | ||
if (result || errors.length) { | ||
if (result && !errors.length && !warnings.length) { | ||
VueSourceFile.compiledSFCTemplateCache = { | ||
fileName: sourceFile.fileName, | ||
template: sourceFile.sfc.template.content, | ||
snapshot: newSnapshot, | ||
result: result, | ||
plugin, | ||
}; | ||
} | ||
else { | ||
VueSourceFile.compiledSFCTemplateCache = undefined; | ||
} | ||
return { | ||
errors, | ||
warnings, | ||
ast: result === null || result === void 0 ? void 0 : result.ast, | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
get mappings() { | ||
return this._mappings.value; | ||
} | ||
get text() { | ||
return this._snapshot.value.getText(0, this._snapshot.value.getLength()); | ||
} | ||
class VueFile { | ||
get compiledSFCTemplate() { | ||
return VueSourceFile.getCompiledSFCTemplate(this.plugins, this, this._snapshot.value); | ||
return this._compiledSfcTemplate.value; | ||
} | ||
get tsFileName() { | ||
get mainScriptName() { | ||
var _a, _b; | ||
return (_b = (_a = this._allEmbeddeds.value.find(e => e.file.fileName.replace(this.fileName, '').match(/^\.(js|ts)x?$/))) === null || _a === void 0 ? void 0 : _a.file.fileName) !== null && _b !== void 0 ? _b : ''; | ||
return (_b = (_a = this._allEmbeddedFiles.value.find(e => e.file.fileName.replace(this.fileName, '').match(/^\.(js|ts)x?$/))) === null || _a === void 0 ? void 0 : _a.file.fileName) !== null && _b !== void 0 ? _b : ''; | ||
} | ||
get embeddeds() { | ||
return this._embeddeds.value; | ||
get embeddedFiles() { | ||
return this._embeddedFiles.value; | ||
} | ||
constructor(fileName, pscriptSnapshot, ts, plugins) { | ||
// functions | ||
constructor(fileName, snapshot, ts, plugins) { | ||
this.fileName = fileName; | ||
this.pscriptSnapshot = pscriptSnapshot; | ||
this.snapshot = snapshot; | ||
this.ts = ts; | ||
this.plugins = plugins; | ||
this.sfc = (0, reactivity_1.reactive)({ | ||
template: null, | ||
script: null, | ||
scriptSetup: null, | ||
styles: [], | ||
customBlocks: [], | ||
getTemplateAst: () => { | ||
this.capabilities = { | ||
diagnostic: true, | ||
foldingRange: true, | ||
documentFormatting: true, | ||
documentSymbol: true, | ||
codeAction: true, | ||
inlayHint: true, | ||
}; | ||
this.kind = language_core_1.FileKind.TextFile; | ||
this.mappings = []; | ||
// refs | ||
this.sfc = (0, reactivity_1.reactive)(Object.assign({ template: null, script: null, scriptSetup: null, styles: [], customBlocks: [], templateAst: (0, reactivity_1.computed)(() => { | ||
var _a; | ||
return (_a = this.compiledSFCTemplate) === null || _a === void 0 ? void 0 : _a.ast; | ||
}, | ||
scriptAst: (0, reactivity_1.computed)(() => { | ||
return (_a = this._compiledSfcTemplate.value) === null || _a === void 0 ? void 0 : _a.ast; | ||
}), scriptAst: (0, reactivity_1.computed)(() => { | ||
if (this.sfc.script) { | ||
return this.ts.createSourceFile(this.fileName + '.' + this.sfc.script.lang, this.sfc.script.content, this.ts.ScriptTarget.Latest); | ||
} | ||
}), | ||
scriptSetupAst: (0, reactivity_1.computed)(() => { | ||
}), scriptSetupAst: (0, reactivity_1.computed)(() => { | ||
if (this.sfc.scriptSetup) { | ||
return this.ts.createSourceFile(this.fileName + '.' + this.sfc.scriptSetup.lang, this.sfc.scriptSetup.content, this.ts.ScriptTarget.Latest); | ||
} | ||
}), | ||
}) /* avoid Sfc unwrap in .d.ts by reactive */; | ||
this.sfcBlocks = (0, reactivity_1.computed)(() => { | ||
}) }, { | ||
// backward compatible | ||
getTemplateAst: () => { | ||
var _a; | ||
return (_a = this.compiledSFCTemplate) === null || _a === void 0 ? void 0 : _a.ast; | ||
}, | ||
})) /* avoid Sfc unwrap in .d.ts by reactive */; | ||
// computed | ||
this._sfcBlocks = (0, reactivity_1.computed)(() => { | ||
const blocks = {}; | ||
@@ -200,14 +84,191 @@ if (this.sfc.template) { | ||
}); | ||
this.kind = language_core_1.EmbeddedFileKind.TextFile; | ||
this.capabilities = { | ||
diagnostic: true, | ||
foldingRange: true, | ||
documentFormatting: true, | ||
documentSymbol: true, | ||
codeAction: true, | ||
inlayHint: true, | ||
}; | ||
this._mappings = (0, reactivity_1.computed)(() => [{ | ||
sourceRange: [0, this._snapshot.value.getLength()], | ||
generatedRange: [0, this._snapshot.value.getLength()], | ||
this._compiledSfcTemplate = (0, reactivity_1.computed)(() => { | ||
var _a, _b, _c, _d, _e; | ||
if (((_a = this.compiledSFCTemplateCache) === null || _a === void 0 ? void 0 : _a.template) === ((_b = this.sfc.template) === null || _b === void 0 ? void 0 : _b.content)) { | ||
return { | ||
errors: [], | ||
warnings: [], | ||
ast: (_c = this.compiledSFCTemplateCache) === null || _c === void 0 ? void 0 : _c.result.ast, | ||
}; | ||
} | ||
if (this.sfc.template) { | ||
// incremental update | ||
if ((_d = this.compiledSFCTemplateCache) === null || _d === void 0 ? void 0 : _d.plugin.updateSFCTemplate) { | ||
const change = this.snapshot.getChangeRange(this.compiledSFCTemplateCache.snapshot); | ||
if (change) { | ||
(0, reactivity_1.pauseTracking)(); | ||
const templateOffset = this.sfc.template.startTagEnd; | ||
(0, reactivity_1.resetTracking)(); | ||
const newText = this.snapshot.getText(change.span.start, change.span.start + change.newLength); | ||
const newResult = this.compiledSFCTemplateCache.plugin.updateSFCTemplate(this.compiledSFCTemplateCache.result, { | ||
start: change.span.start - templateOffset, | ||
end: change.span.start + change.span.length - templateOffset, | ||
newText, | ||
}); | ||
if (newResult) { | ||
this.compiledSFCTemplateCache.template = this.sfc.template.content; | ||
this.compiledSFCTemplateCache.snapshot = this.snapshot; | ||
this.compiledSFCTemplateCache.result = newResult; | ||
return { | ||
errors: [], | ||
warnings: [], | ||
ast: newResult.ast, | ||
}; | ||
} | ||
} | ||
} | ||
const errors = []; | ||
const warnings = []; | ||
let options = { | ||
onError: (err) => errors.push(err), | ||
onWarn: (err) => warnings.push(err), | ||
expressionPlugins: ['typescript'], | ||
}; | ||
for (const plugin of this.plugins) { | ||
if (plugin.resolveTemplateCompilerOptions) { | ||
options = plugin.resolveTemplateCompilerOptions(options); | ||
} | ||
} | ||
for (const plugin of this.plugins) { | ||
let result; | ||
try { | ||
result = (_e = plugin.compileSFCTemplate) === null || _e === void 0 ? void 0 : _e.call(plugin, this.sfc.template.lang, this.sfc.template.content, options); | ||
} | ||
catch (e) { | ||
const err = e; | ||
errors.push(err); | ||
} | ||
if (result || errors.length) { | ||
if (result && !errors.length && !warnings.length) { | ||
this.compiledSFCTemplateCache = { | ||
template: this.sfc.template.content, | ||
snapshot: this.snapshot, | ||
result: result, | ||
plugin, | ||
}; | ||
} | ||
else { | ||
this.compiledSFCTemplateCache = undefined; | ||
} | ||
return { | ||
errors, | ||
warnings, | ||
ast: result === null || result === void 0 ? void 0 : result.ast, | ||
}; | ||
} | ||
} | ||
} | ||
}); | ||
this._pluginEmbeddedFiles = this.plugins.map((plugin) => { | ||
const embeddedFiles = {}; | ||
const files = (0, reactivity_1.computed)(() => { | ||
if (plugin.getEmbeddedFileNames) { | ||
const embeddedFileNames = plugin.getEmbeddedFileNames(this.fileName, this.sfc); | ||
for (const oldFileName of Object.keys(embeddedFiles)) { | ||
if (!embeddedFileNames.includes(oldFileName)) { | ||
delete embeddedFiles[oldFileName]; | ||
} | ||
} | ||
for (const embeddedFileName of embeddedFileNames) { | ||
if (!embeddedFiles[embeddedFileName]) { | ||
embeddedFiles[embeddedFileName] = (0, reactivity_1.computed)(() => { | ||
const file = new VueEmbeddedFile(embeddedFileName); | ||
for (const plugin of this.plugins) { | ||
if (plugin.resolveEmbeddedFile) { | ||
plugin.resolveEmbeddedFile(this.fileName, this.sfc, file); | ||
} | ||
} | ||
return file; | ||
}); | ||
} | ||
} | ||
} | ||
return Object.values(embeddedFiles); | ||
}); | ||
return (0, reactivity_1.computed)(() => { | ||
return files.value.map(_file => { | ||
const file = _file.value; | ||
const mappings = [...(0, source_map_1.buildMappings)(file.content), ...file.extraMappings]; | ||
for (const mapping of mappings) { | ||
if (mapping.source !== undefined) { | ||
const block = this._sfcBlocks.value[mapping.source]; | ||
if (block) { | ||
mapping.sourceRange = [ | ||
mapping.sourceRange[0] + block.startTagEnd, | ||
mapping.sourceRange[1] + block.startTagEnd, | ||
]; | ||
mapping.source = undefined; | ||
} | ||
} | ||
} | ||
return { | ||
file, | ||
snapshot: this.ts.ScriptSnapshot.fromString((0, source_map_1.toString)(file.content)), | ||
mappings, | ||
}; | ||
}); | ||
}); | ||
}); | ||
this._allEmbeddedFiles = (0, reactivity_1.computed)(() => { | ||
const all = []; | ||
for (const embeddedFiles of this._pluginEmbeddedFiles) { | ||
for (const embedded of embeddedFiles.value) { | ||
all.push(embedded); | ||
} | ||
} | ||
return all; | ||
}); | ||
this._embeddedFiles = (0, reactivity_1.computed)(() => { | ||
const embeddedFiles = []; | ||
let remain = [...this._allEmbeddedFiles.value]; | ||
while (remain.length) { | ||
const beforeLength = remain.length; | ||
consumeRemain(); | ||
if (beforeLength === remain.length) { | ||
break; | ||
} | ||
} | ||
for (const { file, snapshot, mappings } of remain) { | ||
embeddedFiles.push(Object.assign(Object.assign({}, file), { snapshot, | ||
mappings, embeddedFiles: [] })); | ||
console.error('Unable to resolve embedded: ' + file.parentFileName + ' -> ' + file.fileName); | ||
} | ||
return embeddedFiles; | ||
function consumeRemain() { | ||
for (let i = remain.length - 1; i >= 0; i--) { | ||
const { file, snapshot, mappings } = remain[i]; | ||
if (!file.parentFileName) { | ||
embeddedFiles.push(Object.assign(Object.assign({}, file), { snapshot, | ||
mappings, embeddedFiles: [] })); | ||
remain.splice(i, 1); | ||
} | ||
else { | ||
const parent = findParentStructure(file.parentFileName, embeddedFiles); | ||
if (parent) { | ||
parent.embeddedFiles.push(Object.assign(Object.assign({}, file), { snapshot, | ||
mappings, embeddedFiles: [] })); | ||
remain.splice(i, 1); | ||
} | ||
} | ||
} | ||
} | ||
function findParentStructure(fileName, current) { | ||
for (const child of current) { | ||
if (child.fileName === fileName) { | ||
return child; | ||
} | ||
let parent = findParentStructure(fileName, child.embeddedFiles); | ||
if (parent) { | ||
return parent; | ||
} | ||
} | ||
} | ||
}); | ||
this.update(snapshot); | ||
} | ||
update(newScriptSnapshot) { | ||
this.snapshot = newScriptSnapshot; | ||
this.mappings = [{ | ||
sourceRange: [0, this.snapshot.getLength()], | ||
generatedRange: [0, this.snapshot.getLength()], | ||
data: { | ||
@@ -222,255 +283,166 @@ hover: true, | ||
}, | ||
}]); | ||
this._allEmbeddeds = (0, reactivity_1.shallowRef)([]); | ||
this._embeddeds = (0, reactivity_1.shallowRef)([]); | ||
this._snapshot = (0, reactivity_1.shallowRef)(this.pscriptSnapshot); | ||
this.update(this._snapshot.value, true); | ||
} | ||
update(newScriptSnapshot, init = false) { | ||
const self = this; | ||
if (newScriptSnapshot === this._snapshot.value && !init) { | ||
return; | ||
} | ||
const parsedSfc = VueSourceFile.getSFC(this.plugins, this.fileName, newScriptSnapshot); | ||
this._snapshot.value = newScriptSnapshot; | ||
// TODO: wait for https://github.com/vuejs/core/pull/5912 | ||
}]; | ||
const parsedSfc = this.parseSfc(); | ||
if (parsedSfc) { | ||
updateTemplate(parsedSfc.descriptor.template); | ||
updateScript(parsedSfc.descriptor.script); | ||
updateScriptSetup(parsedSfc.descriptor.scriptSetup); | ||
updateStyles(parsedSfc.descriptor.styles); | ||
updateCustomBlocks(parsedSfc.descriptor.customBlocks); | ||
this.updateTemplate(parsedSfc.descriptor.template); | ||
this.updateScript(parsedSfc.descriptor.script); | ||
this.updateScriptSetup(parsedSfc.descriptor.scriptSetup); | ||
this.updateStyles(parsedSfc.descriptor.styles); | ||
this.updateCustomBlocks(parsedSfc.descriptor.customBlocks); | ||
} | ||
else { | ||
updateTemplate(null); | ||
updateScript(null); | ||
updateScriptSetup(null); | ||
updateStyles([]); | ||
updateCustomBlocks([]); | ||
this.updateTemplate(null); | ||
this.updateScript(null); | ||
this.updateScriptSetup(null); | ||
this.updateStyles([]); | ||
this.updateCustomBlocks([]); | ||
} | ||
VueSourceFile.current.value = this; | ||
this._allEmbeddeds.value = VueSourceFile._allEmbeddeds.value; | ||
this._embeddeds.value = VueSourceFile._embeddeds.value; | ||
function updateTemplate(block) { | ||
var _a; | ||
const newData = block ? { | ||
name: 'template', | ||
start: self._snapshot.value.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + self._snapshot.value.getText(block.loc.end.offset, self._snapshot.value.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'html', | ||
} : null; | ||
if (self.sfc.template && newData) { | ||
updateBlock(self.sfc.template, newData); | ||
} | ||
else { | ||
self.sfc.template = newData; | ||
} | ||
} | ||
function updateScript(block) { | ||
var _a; | ||
const newData = block ? { | ||
name: 'script', | ||
start: self._snapshot.value.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + self._snapshot.value.getText(block.loc.end.offset, self._snapshot.value.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'js', | ||
src: block.src, | ||
} : null; | ||
if (self.sfc.script && newData) { | ||
updateBlock(self.sfc.script, newData); | ||
} | ||
else { | ||
self.sfc.script = newData; | ||
} | ||
} | ||
function updateScriptSetup(block) { | ||
var _a; | ||
const newData = block ? { | ||
name: 'scriptSetup', | ||
start: self._snapshot.value.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + self._snapshot.value.getText(block.loc.end.offset, self._snapshot.value.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'js', | ||
generic: typeof block.attrs.generic === 'string' ? block.attrs.generic : undefined, | ||
genericOffset: typeof block.attrs.generic === 'string' ? newScriptSnapshot.getText(0, newScriptSnapshot.getLength()).substring(0, block.loc.start.offset).lastIndexOf(block.attrs.generic) - block.loc.start.offset : -1, | ||
} : null; | ||
if (self.sfc.scriptSetup && newData) { | ||
updateBlock(self.sfc.scriptSetup, newData); | ||
} | ||
else { | ||
self.sfc.scriptSetup = newData; | ||
} | ||
} | ||
function updateStyles(blocks) { | ||
var _a; | ||
for (let i = 0; i < blocks.length; i++) { | ||
const block = blocks[i]; | ||
const newData = { | ||
name: 'style_' + i, | ||
start: self._snapshot.value.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + self._snapshot.value.getText(block.loc.end.offset, self._snapshot.value.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'css', | ||
module: typeof block.module === 'string' ? block.module : block.module ? '$style' : undefined, | ||
scoped: !!block.scoped, | ||
}; | ||
if (self.sfc.styles.length > i) { | ||
updateBlock(self.sfc.styles[i], newData); | ||
} | ||
parseSfc() { | ||
var _a, _b; | ||
// incremental update | ||
if ((_a = this.parsedSfcCache) === null || _a === void 0 ? void 0 : _a.plugin.updateSFC) { | ||
const change = this.snapshot.getChangeRange(this.parsedSfcCache.snapshot); | ||
if (change) { | ||
const newSfc = this.parsedSfcCache.plugin.updateSFC(this.parsedSfcCache.sfc, { | ||
start: change.span.start, | ||
end: change.span.start + change.span.length, | ||
newText: this.snapshot.getText(change.span.start, change.span.start + change.newLength), | ||
}); | ||
if (newSfc) { | ||
this.parsedSfcCache.snapshot = this.snapshot; | ||
this.parsedSfcCache.sfc = newSfc; | ||
return newSfc; | ||
} | ||
else { | ||
self.sfc.styles.push(newData); | ||
} | ||
} | ||
while (self.sfc.styles.length > blocks.length) { | ||
self.sfc.styles.pop(); | ||
} | ||
} | ||
function updateCustomBlocks(blocks) { | ||
var _a; | ||
for (let i = 0; i < blocks.length; i++) { | ||
const block = blocks[i]; | ||
const newData = { | ||
name: 'customBlock_' + i, | ||
start: self._snapshot.value.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + self._snapshot.value.getText(block.loc.end.offset, self._snapshot.value.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'txt', | ||
type: block.type, | ||
}; | ||
if (self.sfc.customBlocks.length > i) { | ||
updateBlock(self.sfc.customBlocks[i], newData); | ||
for (const plugin of this.plugins) { | ||
const sfc = (_b = plugin.parseSFC) === null || _b === void 0 ? void 0 : _b.call(plugin, this.fileName, this.snapshot.getText(0, this.snapshot.getLength())); | ||
if (sfc) { | ||
if (!sfc.errors.length) { | ||
this.parsedSfcCache = { | ||
snapshot: this.snapshot, | ||
sfc, | ||
plugin, | ||
}; | ||
} | ||
else { | ||
self.sfc.customBlocks.push(newData); | ||
} | ||
return sfc; | ||
} | ||
while (self.sfc.customBlocks.length > blocks.length) { | ||
self.sfc.customBlocks.pop(); | ||
} | ||
} | ||
function updateBlock(oldBlock, newBlock) { | ||
for (let key in newBlock) { | ||
oldBlock[key] = newBlock[key]; | ||
} | ||
} | ||
updateTemplate(block) { | ||
var _a; | ||
const newData = block ? { | ||
name: 'template', | ||
start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'html', | ||
} : null; | ||
if (this.sfc.template && newData) { | ||
this.updateBlock(this.sfc.template, newData); | ||
} | ||
else { | ||
this.sfc.template = newData; | ||
} | ||
} | ||
} | ||
exports.VueSourceFile = VueSourceFile; | ||
VueSourceFile.current = (0, reactivity_1.shallowRef)({}); | ||
VueSourceFile._pluginEmbeddedFiles = (0, reactivity_1.computed)(() => VueSourceFile.current.value.plugins.map(plugin => { | ||
const embeddedFiles = {}; | ||
const files = (0, reactivity_1.computed)(() => { | ||
if (plugin.getEmbeddedFileNames) { | ||
const embeddedFileNames = plugin.getEmbeddedFileNames(VueSourceFile.current.value.fileName, VueSourceFile.current.value.sfc); | ||
for (const oldFileName of Object.keys(embeddedFiles)) { | ||
if (!embeddedFileNames.includes(oldFileName)) { | ||
delete embeddedFiles[oldFileName]; | ||
} | ||
} | ||
for (const embeddedFileName of embeddedFileNames) { | ||
if (!embeddedFiles[embeddedFileName]) { | ||
embeddedFiles[embeddedFileName] = (0, reactivity_1.computed)(() => { | ||
const file = new VueEmbeddedFile(embeddedFileName); | ||
for (const plugin of VueSourceFile.current.value.plugins) { | ||
if (plugin.resolveEmbeddedFile) { | ||
plugin.resolveEmbeddedFile(VueSourceFile.current.value.fileName, VueSourceFile.current.value.sfc, file); | ||
} | ||
} | ||
return file; | ||
}); | ||
} | ||
} | ||
updateScript(block) { | ||
var _a; | ||
const newData = block ? { | ||
name: 'script', | ||
start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'js', | ||
src: block.src, | ||
} : null; | ||
if (this.sfc.script && newData) { | ||
this.updateBlock(this.sfc.script, newData); | ||
} | ||
return Object.values(embeddedFiles); | ||
}); | ||
return (0, reactivity_1.computed)(() => { | ||
return files.value.map(_file => { | ||
const file = _file.value; | ||
const mappings = [...(0, source_map_1.buildMappings)(file.content), ...file.extraMappings]; | ||
for (const mapping of mappings) { | ||
if (mapping.source !== undefined) { | ||
const block = VueSourceFile.current.value.sfcBlocks.value[mapping.source]; | ||
if (block) { | ||
mapping.sourceRange = [ | ||
mapping.sourceRange[0] + block.startTagEnd, | ||
mapping.sourceRange[1] + block.startTagEnd, | ||
]; | ||
mapping.source = undefined; | ||
} | ||
} | ||
} | ||
return { | ||
file, | ||
text: (0, source_map_1.toString)(file.content), | ||
mappings, | ||
}; | ||
}); | ||
}); | ||
})); | ||
VueSourceFile._allEmbeddeds = (0, reactivity_1.computed)(() => { | ||
const all = []; | ||
for (const embeddedFiles of VueSourceFile._pluginEmbeddedFiles.value) { | ||
for (const embedded of embeddedFiles.value) { | ||
all.push(embedded); | ||
else { | ||
this.sfc.script = newData; | ||
} | ||
} | ||
return all; | ||
}); | ||
VueSourceFile._embeddeds = (0, reactivity_1.computed)(() => { | ||
const childs = []; | ||
let remain = [...VueSourceFile._allEmbeddeds.value]; | ||
while (remain.length) { | ||
const beforeLength = remain.length; | ||
consumeRemain(); | ||
if (beforeLength === remain.length) { | ||
break; | ||
updateScriptSetup(block) { | ||
var _a; | ||
const newData = block ? { | ||
name: 'scriptSetup', | ||
start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'js', | ||
generic: typeof block.attrs.generic === 'string' ? block.attrs.generic : undefined, | ||
genericOffset: typeof block.attrs.generic === 'string' ? this.snapshot.getText(0, block.loc.start.offset).lastIndexOf(block.attrs.generic) - block.loc.start.offset : -1, | ||
} : null; | ||
if (this.sfc.scriptSetup && newData) { | ||
this.updateBlock(this.sfc.scriptSetup, newData); | ||
} | ||
else { | ||
this.sfc.scriptSetup = newData; | ||
} | ||
} | ||
for (const { file, text, mappings } of remain) { | ||
childs.push(Object.assign(Object.assign({}, file), { text, | ||
mappings, embeddeds: [] })); | ||
console.error('Unable to resolve embedded: ' + file.parentFileName + ' -> ' + file.fileName); | ||
} | ||
return childs; | ||
function consumeRemain() { | ||
for (let i = remain.length - 1; i >= 0; i--) { | ||
const { file, text, mappings } = remain[i]; | ||
if (!file.parentFileName) { | ||
childs.push(Object.assign(Object.assign({}, file), { text, | ||
mappings, embeddeds: [] })); | ||
remain.splice(i, 1); | ||
updateStyles(blocks) { | ||
var _a; | ||
for (let i = 0; i < blocks.length; i++) { | ||
const block = blocks[i]; | ||
const newData = { | ||
name: 'style_' + i, | ||
start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'css', | ||
module: typeof block.module === 'string' ? block.module : block.module ? '$style' : undefined, | ||
scoped: !!block.scoped, | ||
}; | ||
if (this.sfc.styles.length > i) { | ||
this.updateBlock(this.sfc.styles[i], newData); | ||
} | ||
else { | ||
const parent = findParentStructure(file.parentFileName, childs); | ||
if (parent) { | ||
parent.embeddeds.push(Object.assign(Object.assign({}, file), { text, | ||
mappings, embeddeds: [] })); | ||
remain.splice(i, 1); | ||
} | ||
this.sfc.styles.push(newData); | ||
} | ||
} | ||
while (this.sfc.styles.length > blocks.length) { | ||
this.sfc.styles.pop(); | ||
} | ||
} | ||
function findParentStructure(fileName, strus) { | ||
for (const stru of strus) { | ||
if (stru.fileName === fileName) { | ||
return stru; | ||
updateCustomBlocks(blocks) { | ||
var _a; | ||
for (let i = 0; i < blocks.length; i++) { | ||
const block = blocks[i]; | ||
const newData = { | ||
name: 'customBlock_' + i, | ||
start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<'), | ||
end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1, | ||
startTagEnd: block.loc.start.offset, | ||
endTagStart: block.loc.end.offset, | ||
content: block.content, | ||
lang: (_a = block.lang) !== null && _a !== void 0 ? _a : 'txt', | ||
type: block.type, | ||
}; | ||
if (this.sfc.customBlocks.length > i) { | ||
this.updateBlock(this.sfc.customBlocks[i], newData); | ||
} | ||
let _stru = findParentStructure(fileName, stru.embeddeds); | ||
if (_stru) { | ||
return _stru; | ||
else { | ||
this.sfc.customBlocks.push(newData); | ||
} | ||
} | ||
while (this.sfc.customBlocks.length > blocks.length) { | ||
this.sfc.customBlocks.pop(); | ||
} | ||
} | ||
}); | ||
updateBlock(oldBlock, newBlock) { | ||
for (let key in newBlock) { | ||
oldBlock[key] = newBlock[key]; | ||
} | ||
} | ||
} | ||
exports.VueFile = VueFile; | ||
//# sourceMappingURL=sourceFile.js.map |
@@ -81,5 +81,9 @@ import * as embedded from '@volar/language-core'; | ||
})[]; | ||
getTemplateAst: () => CompilerDom.RootNode | undefined; | ||
templateAst: CompilerDom.RootNode | undefined; | ||
scriptAst: ts.SourceFile | undefined; | ||
scriptSetupAst: ts.SourceFile | undefined; | ||
} | ||
export interface TextRange { | ||
start: number; | ||
end: number; | ||
} |
@@ -9,2 +9,3 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
return ` | ||
// @ts-nocheck | ||
import type { | ||
@@ -110,2 +111,3 @@ FunctionalComponent, | ||
T extends new (...args: any) => { $props: infer Props } ? Props | ||
: T extends (props: infer Props, ...args: any) => any ? Props | ||
: T extends (...args: any) => { props: infer Props } ? Props | ||
@@ -128,3 +130,3 @@ : T extends new (...args: any) => any ? {} | ||
type IntrinsicElements = JSX.IntrinsicElements; | ||
`; | ||
`.trim(); | ||
} | ||
@@ -131,0 +133,0 @@ exports.getTypesCode = getTypesCode; |
@@ -32,3 +32,4 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
function createParsedCommandLineBase(ts, parseConfigHost, content, tsConfigPath, extraFileExtensions, extendsSet) { | ||
let vueOptions = {}; | ||
var _a; | ||
let extendsVueOptions = {}; | ||
const folder = path.dirname(tsConfigPath); | ||
@@ -40,3 +41,3 @@ extendsSet.add(tsConfigPath); | ||
if (!extendsSet.has(extendsPath)) { | ||
vueOptions = createParsedCommandLine(ts, parseConfigHost, extendsPath, extraFileExtensions, extendsSet).vueOptions; | ||
extendsVueOptions = createParsedCommandLine(ts, parseConfigHost, extendsPath, extraFileExtensions, extendsSet).vueOptions; | ||
} | ||
@@ -48,3 +49,13 @@ } | ||
} | ||
return Object.assign(Object.assign({}, content), { vueOptions: Object.assign(Object.assign({}, vueOptions), content.raw.vueCompilerOptions) }); | ||
const vueOptions = Object.assign(Object.assign({}, extendsVueOptions), content.raw.vueCompilerOptions); | ||
vueOptions.hooks = (_a = vueOptions.hooks) === null || _a === void 0 ? void 0 : _a.map(hook => { | ||
try { | ||
hook = require.resolve(hook, { paths: [folder] }); | ||
} | ||
catch (error) { | ||
console.error(error); | ||
} | ||
return hook; | ||
}); | ||
return Object.assign(Object.assign({}, content), { vueOptions }); | ||
} | ||
@@ -51,0 +62,0 @@ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element |
{ | ||
"name": "@volar/vue-language-core", | ||
"version": "1.0.16", | ||
"version": "1.0.17", | ||
"main": "out/index.js", | ||
@@ -16,4 +16,4 @@ "license": "MIT", | ||
"dependencies": { | ||
"@volar/language-core": "1.0.16", | ||
"@volar/source-map": "1.0.16", | ||
"@volar/language-core": "1.0.17", | ||
"@volar/source-map": "1.0.17", | ||
"@vue/compiler-dom": "^3.2.45", | ||
@@ -29,3 +29,3 @@ "@vue/compiler-sfc": "^3.2.45", | ||
}, | ||
"gitHead": "af476047d8859652254ed36f8aee184f1972a97a" | ||
"gitHead": "b66b64f579b5cafee9b8d70aa9f9303f39b6df49" | ||
} |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
235699
5121
6
+ Added@volar/language-core@1.0.17(transitive)
+ Added@volar/source-map@1.0.17(transitive)
- Removed@volar/language-core@1.0.16(transitive)
- Removed@volar/source-map@1.0.16(transitive)
Updated@volar/language-core@1.0.17
Updated@volar/source-map@1.0.17