vite-esbuild-typescript-checker
Version:
* Speeds up [TypeScript](https://github.com/Microsoft/TypeScript) type checking * Supports [Vue Single File Component](https://vuejs.org/v2/guide/single-file-components.html) * Displays nice error messages with the [code frame](https://babeljs.io/docs/en/
110 lines (109 loc) • 3.97 kB
JavaScript
import fs from 'fs-extra';
import { createTypeScriptEmbeddedExtension } from './type-script-embedded-extension.js';
import { parse } from '@vue/compiler-sfc';
export function createTypeScriptVueExtension(config) {
function isVueTemplateCompilerV2(compiler) {
return typeof compiler.parseComponent === 'function';
}
function isVueTemplateCompilerV3(compiler) {
return typeof compiler.parse === 'function';
}
function getExtensionByLang(lang) {
if (lang === true) {
return '.js';
}
switch(lang){
case 'ts':
return '.ts';
case 'tsx':
return '.tsx';
case 'js':
case 'jsx':
default:
return '.js';
}
}
function createVueNoScriptEmbeddedSource() {
return {
sourceText: 'export default {};\n',
extension: '.js'
};
}
function createVueSrcScriptEmbeddedSource(src, lang) {
// Import path cannot be end with '.ts[x]'
src = src.replace(/\.tsx?$/i, '');
// For now, ignore the error when the src file is not found since it will produce incorrect code location.
// It's not a large problem since it's handled on webpack side.
const text = [
'// @ts-ignore',
`export { default } from '${src}';`,
'// @ts-ignore',
`export * from '${src}';`
].join('\n');
return {
sourceText: text,
extension: getExtensionByLang(lang)
};
}
function createVueInlineScriptEmbeddedSource(text, lang) {
return {
sourceText: text.indexOf('export default') > -1 ? text : [
text,
'export default {};'
].join('\n'),
extension: getExtensionByLang(lang)
};
}
function getVueEmbeddedSource(fileName) {
if (!fs.existsSync(fileName)) {
return undefined;
}
const vueSourceText = fs.readFileSync(fileName, {
encoding: 'utf-8'
});
let script;
const parsed = parse(vueSourceText);
if (parsed.descriptor && (parsed.descriptor.script || parsed.descriptor.scriptSetup)) {
const scriptV3 = parsed.descriptor.script || parsed.descriptor.scriptSetup;
// map newer version of SFCScriptBlock to the generic one
script = {
content: scriptV3.content,
attrs: scriptV3.attrs,
start: scriptV3.loc.start.offset,
end: scriptV3.loc.end.offset,
lang: scriptV3.lang,
src: scriptV3.src
};
}
if (!script) {
// No <script> block
return createVueNoScriptEmbeddedSource();
} else if (script.attrs.src) {
// <script src="file.ts" /> block
if (typeof script.attrs.src === 'string') {
return createVueSrcScriptEmbeddedSource(script.attrs.src, script.attrs.lang);
}
} else {
// <script lang="ts"></script> block
// pad blank lines to retain diagnostics location
const lineOffset = vueSourceText.slice(0, script.start).split(/\r?\n/g).length;
const paddedSourceText = Array(lineOffset).join('\n') + vueSourceText.slice(script.start, script.end);
return createVueInlineScriptEmbeddedSource(paddedSourceText, script.attrs.lang);
}
}
return createTypeScriptEmbeddedExtension({
embeddedExtensions: [
'.vue'
],
getEmbeddedSource: getVueEmbeddedSource
});
}
let typescriptVueExtension;
export function getVueExtension() {
return typescriptVueExtension;
}
export function initVueExtension(options) {
typescriptVueExtension = createTypeScriptVueExtension(options);
return typescriptVueExtension;
}
export default {};