UNPKG

12.2 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13var __importStar = (this && this.__importStar) || function (mod) {
14 if (mod && mod.__esModule) return mod;
15 var result = {};
16 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
17 result["default"] = mod;
18 return result;
19};
20Object.defineProperty(exports, "__esModule", { value: true });
21var fs = __importStar(require("fs"));
22var path = __importStar(require("path"));
23var resolution_1 = require("./resolution");
24var VueProgram = /** @class */ (function () {
25 function VueProgram() {
26 }
27 VueProgram.loadProgramConfig = function (typescript, configFile, compilerOptions) {
28 var extraExtensions = ['vue'];
29 var parseConfigHost = {
30 fileExists: typescript.sys.fileExists,
31 readFile: typescript.sys.readFile,
32 useCaseSensitiveFileNames: typescript.sys.useCaseSensitiveFileNames,
33 readDirectory: function (rootDir, extensions, excludes, includes, depth) {
34 return typescript.sys.readDirectory(rootDir, extensions.concat(extraExtensions), excludes, includes, depth);
35 }
36 };
37 var tsconfig = typescript.readConfigFile(configFile, typescript.sys.readFile).config;
38 tsconfig.compilerOptions = tsconfig.compilerOptions || {};
39 tsconfig.compilerOptions = __assign({}, tsconfig.compilerOptions, compilerOptions);
40 var parsed = typescript.parseJsonConfigFileContent(tsconfig, parseConfigHost, path.dirname(configFile));
41 parsed.options.allowNonTsExtensions = true;
42 return parsed;
43 };
44 /**
45 * Search for default wildcard or wildcard from options, we only search for that in tsconfig CompilerOptions.paths.
46 * The path is resolved with thie given substitution and includes the CompilerOptions.baseUrl (if given).
47 * If no paths given in tsconfig, then the default substitution is '[tsconfig directory]/src'.
48 * (This is a fast, simplified inspiration of what's described here: https://github.com/Microsoft/TypeScript/issues/5039)
49 */
50 VueProgram.resolveNonTsModuleName = function (moduleName, containingFile, basedir, options) {
51 var baseUrl = options.baseUrl ? options.baseUrl : basedir;
52 var discardedSymbols = ['.', '..', '/'];
53 var wildcards = [];
54 if (options.paths) {
55 Object.keys(options.paths).forEach(function (key) {
56 var pathSymbol = key[0];
57 if (discardedSymbols.indexOf(pathSymbol) < 0 &&
58 wildcards.indexOf(pathSymbol) < 0) {
59 wildcards.push(pathSymbol);
60 }
61 });
62 }
63 else {
64 wildcards.push('@');
65 }
66 var isRelative = !path.isAbsolute(moduleName);
67 var correctWildcard;
68 wildcards.forEach(function (wildcard) {
69 if (moduleName.substr(0, 2) === wildcard + "/") {
70 correctWildcard = wildcard;
71 }
72 });
73 if (correctWildcard) {
74 var pattern = options.paths
75 ? options.paths[correctWildcard + "/*"]
76 : undefined;
77 var substitution = pattern
78 ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
79 options.paths[correctWildcard + "/*"][0].replace('*', '')
80 : 'src';
81 moduleName = path.resolve(baseUrl, substitution, moduleName.substr(2));
82 }
83 else if (isRelative) {
84 moduleName = path.resolve(path.dirname(containingFile), moduleName);
85 }
86 return moduleName;
87 };
88 VueProgram.isVue = function (filePath) {
89 return path.extname(filePath) === '.vue';
90 };
91 VueProgram.createProgram = function (typescript, programConfig, basedir, files, oldProgram, userResolveModuleName, userResolveTypeReferenceDirective, vueOptions) {
92 var host = typescript.createCompilerHost(programConfig.options);
93 var realGetSourceFile = host.getSourceFile;
94 var _a = resolution_1.makeResolutionFunctions(userResolveModuleName, userResolveTypeReferenceDirective), resolveModuleName = _a.resolveModuleName, resolveTypeReferenceDirective = _a.resolveTypeReferenceDirective;
95 host.resolveModuleNames = function (moduleNames, containingFile) {
96 return moduleNames.map(function (moduleName) {
97 return resolveModuleName(typescript, moduleName, containingFile, programConfig.options, host).resolvedModule;
98 });
99 };
100 host.resolveTypeReferenceDirectives = function (typeDirectiveNames, containingFile) {
101 return typeDirectiveNames.map(function (typeDirectiveName) {
102 return resolveTypeReferenceDirective(typescript, typeDirectiveName, containingFile, programConfig.options, host).resolvedTypeReferenceDirective;
103 });
104 };
105 // We need a host that can parse Vue SFCs (single file components).
106 host.getSourceFile = function (filePath, languageVersion, onError) {
107 try {
108 var stats = fs.statSync(filePath);
109 files.setMtime(filePath, stats.mtime.valueOf());
110 }
111 catch (e) {
112 // probably file does not exists
113 files.remove(filePath);
114 }
115 // get source file only if there is no source in files register
116 if (!files.has(filePath) || !files.getData(filePath).source) {
117 files.mutateData(filePath, function (data) {
118 data.source = realGetSourceFile(filePath, languageVersion, onError);
119 });
120 }
121 var source = files.getData(filePath).source;
122 // get typescript contents from Vue file
123 if (source && VueProgram.isVue(filePath)) {
124 var resolved = VueProgram.resolveScriptBlock(typescript, source.text, vueOptions.compiler);
125 source = typescript.createSourceFile(filePath, resolved.content, languageVersion, true, resolved.scriptKind);
126 }
127 return source;
128 };
129 // We need a host with special module resolution for Vue files.
130 host.resolveModuleNames = function (moduleNames, containingFile) {
131 var resolvedModules = [];
132 for (var _i = 0, moduleNames_1 = moduleNames; _i < moduleNames_1.length; _i++) {
133 var moduleName = moduleNames_1[_i];
134 // Try to use standard resolution.
135 var resolvedModule = typescript.resolveModuleName(moduleName, containingFile, programConfig.options, {
136 fileExists: function (fileName) {
137 if (fileName.endsWith('.vue.ts')) {
138 return (host.fileExists(fileName.slice(0, -3)) ||
139 host.fileExists(fileName));
140 }
141 else {
142 return host.fileExists(fileName);
143 }
144 },
145 readFile: function (fileName) {
146 // This implementation is not necessary. Just for consistent behavior.
147 if (fileName.endsWith('.vue.ts') && !host.fileExists(fileName)) {
148 return host.readFile(fileName.slice(0, -3));
149 }
150 else {
151 return host.readFile(fileName);
152 }
153 }
154 }).resolvedModule;
155 if (resolvedModule) {
156 if (resolvedModule.resolvedFileName.endsWith('.vue.ts') &&
157 !host.fileExists(resolvedModule.resolvedFileName)) {
158 resolvedModule.resolvedFileName = resolvedModule.resolvedFileName.slice(0, -3);
159 }
160 resolvedModules.push(resolvedModule);
161 }
162 else {
163 // For non-ts extensions.
164 var absolutePath = VueProgram.resolveNonTsModuleName(moduleName, containingFile, basedir, programConfig.options);
165 if (VueProgram.isVue(moduleName)) {
166 resolvedModules.push({
167 resolvedFileName: absolutePath,
168 extension: '.ts'
169 });
170 }
171 else {
172 resolvedModules.push({
173 // If the file does exist, return an empty string (because we assume user has provided a ".d.ts" file for it).
174 resolvedFileName: host.fileExists(absolutePath)
175 ? ''
176 : absolutePath,
177 extension: '.ts'
178 });
179 }
180 }
181 }
182 return resolvedModules;
183 };
184 return typescript.createProgram(programConfig.fileNames, programConfig.options, host, oldProgram // re-use old program
185 );
186 };
187 VueProgram.getScriptKindByLang = function (typescript, lang) {
188 if (lang === 'ts') {
189 return typescript.ScriptKind.TS;
190 }
191 else if (lang === 'tsx') {
192 return typescript.ScriptKind.TSX;
193 }
194 else if (lang === 'jsx') {
195 return typescript.ScriptKind.JSX;
196 }
197 else {
198 // when lang is "js" or no lang specified
199 return typescript.ScriptKind.JS;
200 }
201 };
202 VueProgram.resolveScriptBlock = function (typescript, content, compiler) {
203 // We need to import template compiler for vue lazily because it cannot be included it
204 // as direct dependency because it is an optional dependency of fork-ts-checker-webpack-plugin.
205 // Since its version must not mismatch with user-installed Vue.js,
206 // we should let the users install template compiler for vue by themselves.
207 var parser;
208 try {
209 parser = require(compiler);
210 }
211 catch (err) {
212 throw new Error('When you use `vue` option, make sure to install `' + compiler + '`.');
213 }
214 var script = parser.parseComponent(content, {
215 pad: 'space'
216 }).script;
217 // No <script> block
218 if (!script) {
219 return {
220 scriptKind: typescript.ScriptKind.JS,
221 content: 'export default {};\n'
222 };
223 }
224 var scriptKind = VueProgram.getScriptKindByLang(typescript, script.lang);
225 // There is src attribute
226 if (script.attrs.src) {
227 // import path cannot be end with '.ts[x]'
228 var src = script.attrs.src.replace(/\.tsx?$/i, '');
229 return {
230 scriptKind: scriptKind,
231 // For now, ignore the error when the src file is not found
232 // since it will produce incorrect code location.
233 // It's not a large problem since it's handled on webpack side.
234 content: '// @ts-ignore\n' +
235 ("export { default } from '" + src + "';\n") +
236 '// @ts-ignore\n' +
237 ("export * from '" + src + "';\n")
238 };
239 }
240 // Pad blank lines to retain diagnostics location
241 // We need to prepend `//` for each line to avoid
242 // false positive of no-consecutive-blank-lines TSLint rule
243 var offset = content.slice(0, script.start).split(/\r?\n/g).length;
244 var paddedContent = Array(offset).join('//\n') + script.content.slice(script.start);
245 return {
246 scriptKind: scriptKind,
247 content: paddedContent
248 };
249 };
250 return VueProgram;
251}());
252exports.VueProgram = VueProgram;
253//# sourceMappingURL=VueProgram.js.map
\No newline at end of file