UNPKG

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
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 {};