Skip to content

Commit 032475e

Browse files
cainruspiotr-oles
authored andcommitted
feat: add nativescript-vue-template-compiler support (#354)
* feat: add nativescript-vue-template-compiler support * test: add vue related unit and integrations tests * docs: add information about nativescript-vue-template-compiler support
1 parent 73e3903 commit 032475e

13 files changed

+202
-66
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ new ForkTsCheckerWebpackPlugin({
206206
node doesn't share memory between workers - keep in mind that memory usage will increase. Be aware that in some scenarios increasing workers
207207
number **can increase checking time**. Default: `ForkTsCheckerWebpackPlugin.ONE_CPU`.
208208

209-
- **vue** `boolean`:
210-
If `true`, the linter and compiler will process VueJs single-file-component (.vue) files. See the
209+
- **vue** `boolean | { enabled: boolean, compiler: string }`:
210+
If `true` or `enabled: true`, the linter and compiler will process VueJs single-file-component (.vue) files. See the
211211
[Vue section](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#vue) further down for information on how to correctly setup your project.
212212

213213
- **useTypescriptIncrementalApi** `boolean`:
@@ -408,6 +408,13 @@ new ForkTsCheckerWebpackPlugin({
408408
vue: true
409409
});
410410
```
411+
Optionally change default [vue-template-compiler](https://github.com/vuejs/vue/tree/dev/packages/vue-template-compiler) to [nativescript-vue-template-compiler](https://github.com/nativescript-vue/nativescript-vue/tree/master/packages/nativescript-vue-template-compiler) if you use [nativescript-vue](https://github.com/nativescript-vue/nativescript-vue)
412+
```
413+
new ForkTsCheckerWebpackPlugin({
414+
tslint: true,
415+
vue: { enabled: true, compiler: 'nativescript-vue-template-compiler' }
416+
});
417+
```
411418

412419
2. To activate TypeScript in your `.vue` files, you need to ensure your script tag's language attribute is set
413420
to `ts` or `tsx` (also make sure you include the `.vue` extension in all your import statements as shown below):

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
"vue-class-component": "^6.1.1",
145145
"vue-loader": "^15.2.4",
146146
"vue-template-compiler": "^2.5.16",
147+
"nativescript-vue-template-compiler": "^2.4.0",
147148
"webpack": "^5.0.0-alpha.5"
148149
},
149150
"engines": {

src/ApiIncrementalChecker.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export class ApiIncrementalChecker implements IncrementalCheckerInterface {
5959
linterAutoFix,
6060
createNormalizedMessageFromRuleFailure,
6161
eslinter,
62+
vue,
6263
checkSyntacticErrors = false,
6364
resolveModuleName,
6465
resolveTypeReferenceDirective
@@ -76,6 +77,7 @@ export class ApiIncrementalChecker implements IncrementalCheckerInterface {
7677

7778
this.tsIncrementalCompiler = new CompilerHost(
7879
typescript,
80+
vue,
7981
programConfigFile,
8082
compilerOptions,
8183
checkSyntacticErrors,

src/CompilerHost.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as ts from 'typescript'; // Imported for types alone
33
import { LinkedList } from './LinkedList';
44
import { VueProgram } from './VueProgram';
55
import { ResolveModuleName, ResolveTypeReferenceDirective } from './resolution';
6+
import { VueOptions } from './types/vue-options';
67

78
interface DirectoryWatchDelaySlot {
89
events: { fileName: string }[];
@@ -70,6 +71,7 @@ export class CompilerHost
7071

7172
constructor(
7273
private typescript: typeof ts,
74+
private vueOptions: VueOptions,
7375
programConfigFile: string,
7476
compilerOptions: ts.CompilerOptions,
7577
checkSyntacticErrors: boolean,
@@ -320,7 +322,11 @@ export class CompilerHost
320322

321323
// get typescript contents from Vue file
322324
if (content && VueProgram.isVue(path)) {
323-
const resolved = VueProgram.resolveScriptBlock(this.typescript, content);
325+
const resolved = VueProgram.resolveScriptBlock(
326+
this.typescript,
327+
content,
328+
this.vueOptions.compiler
329+
);
324330
return resolved.content;
325331
}
326332

src/IncrementalChecker.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
IncrementalCheckerParams
3030
} from './IncrementalCheckerInterface';
3131
import { createEslinter } from './createEslinter';
32+
import { VueOptions } from './types/vue-options';
3233

3334
export class IncrementalChecker implements IncrementalCheckerInterface {
3435
// it's shared between compilations
@@ -70,7 +71,7 @@ export class IncrementalChecker implements IncrementalCheckerInterface {
7071
private readonly watchPaths: string[];
7172
private readonly workNumber: number;
7273
private readonly workDivision: number;
73-
private readonly vue: boolean;
74+
private readonly vue: VueOptions;
7475
private readonly checkSyntacticErrors: boolean;
7576
private readonly resolveModuleName: ResolveModuleName | undefined;
7677
private readonly resolveTypeReferenceDirective:
@@ -90,7 +91,7 @@ export class IncrementalChecker implements IncrementalCheckerInterface {
9091
watchPaths,
9192
workNumber = 0,
9293
workDivision = 1,
93-
vue = false,
94+
vue,
9495
checkSyntacticErrors = false,
9596
resolveModuleName,
9697
resolveTypeReferenceDirective
@@ -253,7 +254,7 @@ export class IncrementalChecker implements IncrementalCheckerInterface {
253254

254255
public nextIteration() {
255256
if (!this.watcher) {
256-
const watchExtensions = this.vue
257+
const watchExtensions = this.vue.enabled
257258
? ['.ts', '.tsx', '.vue']
258259
: ['.ts', '.tsx'];
259260
this.watcher = new FilesWatcher(this.watchPaths, watchExtensions);
@@ -285,14 +286,16 @@ export class IncrementalChecker implements IncrementalCheckerInterface {
285286
}
286287
}
287288

288-
this.program = this.vue ? this.loadVueProgram() : this.loadDefaultProgram();
289+
this.program = this.vue.enabled
290+
? this.loadVueProgram(this.vue)
291+
: this.loadDefaultProgram();
289292

290293
if (this.linterConfigFile) {
291294
this.linter = this.createLinter(this.program!);
292295
}
293296
}
294297

295-
private loadVueProgram() {
298+
private loadVueProgram(vueOptions: VueOptions) {
296299
this.programConfig =
297300
this.programConfig ||
298301
VueProgram.loadProgramConfig(
@@ -309,7 +312,8 @@ export class IncrementalChecker implements IncrementalCheckerInterface {
309312
this.watcher!,
310313
this.program!,
311314
this.resolveModuleName,
312-
this.resolveTypeReferenceDirective
315+
this.resolveTypeReferenceDirective,
316+
vueOptions
313317
);
314318
}
315319

src/IncrementalCheckerInterface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CancellationToken } from './CancellationToken';
66
import { NormalizedMessage } from './NormalizedMessage';
77
import { ResolveTypeReferenceDirective, ResolveModuleName } from './resolution';
88
import { createEslinter } from './createEslinter';
9+
import { VueOptions } from './types/vue-options';
910

1011
export interface IncrementalCheckerInterface {
1112
nextIteration(): void;
@@ -40,11 +41,11 @@ export interface ApiIncrementalCheckerParams {
4041
checkSyntacticErrors: boolean;
4142
resolveModuleName: ResolveModuleName | undefined;
4243
resolveTypeReferenceDirective: ResolveTypeReferenceDirective | undefined;
44+
vue: VueOptions;
4345
}
4446

4547
export interface IncrementalCheckerParams extends ApiIncrementalCheckerParams {
4648
watchPaths: string[];
4749
workNumber: number;
4850
workDivision: number;
49-
vue: boolean;
5051
}

src/VueProgram.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
} from './resolution';
1212
// tslint:disable-next-line:no-implicit-dependencies
1313
import * as vueCompiler from 'vue-template-compiler';
14+
import { VueOptions } from './types/vue-options';
1415

1516
interface ResolvedScript {
1617
scriptKind: ts.ScriptKind;
@@ -127,7 +128,10 @@ export class VueProgram {
127128
watcher: FilesWatcher,
128129
oldProgram: ts.Program,
129130
userResolveModuleName: ResolveModuleName | undefined,
130-
userResolveTypeReferenceDirective: ResolveTypeReferenceDirective | undefined
131+
userResolveTypeReferenceDirective:
132+
| ResolveTypeReferenceDirective
133+
| undefined,
134+
vueOptions: VueOptions
131135
) {
132136
const host = typescript.createCompilerHost(programConfig.options);
133137
const realGetSourceFile = host.getSourceFile;
@@ -192,7 +196,11 @@ export class VueProgram {
192196

193197
// get typescript contents from Vue file
194198
if (source && VueProgram.isVue(filePath)) {
195-
const resolved = VueProgram.resolveScriptBlock(typescript, source.text);
199+
const resolved = VueProgram.resolveScriptBlock(
200+
typescript,
201+
source.text,
202+
vueOptions.compiler
203+
);
196204
source = typescript.createSourceFile(
197205
filePath,
198206
resolved.content,
@@ -300,19 +308,20 @@ export class VueProgram {
300308

301309
public static resolveScriptBlock(
302310
typescript: typeof ts,
303-
content: string
311+
content: string,
312+
compiler: string
304313
): ResolvedScript {
305-
// We need to import vue-template-compiler lazily because it cannot be included it
314+
// We need to import template compiler for vue lazily because it cannot be included it
306315
// as direct dependency because it is an optional dependency of fork-ts-checker-webpack-plugin.
307316
// Since its version must not mismatch with user-installed Vue.js,
308-
// we should let the users install vue-template-compiler by themselves.
317+
// we should let the users install template compiler for vue by themselves.
309318
let parser: typeof vueCompiler;
310319
try {
311320
// tslint:disable-next-line
312-
parser = require('vue-template-compiler');
321+
parser = require(compiler);
313322
} catch (err) {
314323
throw new Error(
315-
'When you use `vue` option, make sure to install `vue-template-compiler`.'
324+
'When you use `vue` option, make sure to install `' + compiler + '`.'
316325
);
317326
}
318327

src/index.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
ForkTsCheckerHooks
2424
} from './hooks';
2525
import { RunPayload, RunResult, RUN } from './RpcTypes';
26+
import { VueOptions } from './types/vue-options';
2627

2728
const checkerPluginName = 'fork-ts-checker-webpack-plugin';
2829

@@ -61,7 +62,7 @@ namespace ForkTsCheckerWebpackPlugin {
6162
checkSyntacticErrors: boolean;
6263
memoryLimit: number;
6364
workers: number;
64-
vue: boolean;
65+
vue: boolean | Partial<VueOptions>;
6566
useTypescriptIncrementalApi: boolean;
6667
measureCompilationTime: boolean;
6768
resolveModuleNameModule: string;
@@ -146,7 +147,7 @@ class ForkTsCheckerWebpackPlugin {
146147
private service?: childProcess.ChildProcess;
147148
protected serviceRpc?: RpcProvider;
148149

149-
private vue: boolean;
150+
private vue: VueOptions;
150151

151152
private measureTime: boolean;
152153
private performance: any;
@@ -216,11 +217,11 @@ class ForkTsCheckerWebpackPlugin {
216217
this.tslintAutoFix = tslintAutoFix;
217218
}
218219

219-
this.vue = options.vue === true; // default false
220+
this.vue = ForkTsCheckerWebpackPlugin.prepareVueOptions(options.vue);
220221

221222
this.useTypescriptIncrementalApi =
222223
options.useTypescriptIncrementalApi === undefined
223-
? semver.gte(this.typescriptVersion, '3.0.0') && !this.vue
224+
? semver.gte(this.typescriptVersion, '3.0.0') && !this.vue.enabled
224225
: options.useTypescriptIncrementalApi;
225226

226227
this.measureTime = options.measureCompilationTime === true;
@@ -311,6 +312,23 @@ class ForkTsCheckerWebpackPlugin {
311312
return { eslintVersion, eslintOptions };
312313
}
313314

315+
private static prepareVueOptions(
316+
vueOptions?: boolean | Partial<VueOptions>
317+
): VueOptions {
318+
const defaultVueOptions: VueOptions = {
319+
compiler: 'vue-template-compiler',
320+
enabled: false
321+
};
322+
323+
if (typeof vueOptions === 'boolean') {
324+
return Object.assign(defaultVueOptions, { enabled: vueOptions });
325+
} else if (typeof vueOptions === 'object' && vueOptions !== null) {
326+
return Object.assign(defaultVueOptions, vueOptions);
327+
} else {
328+
return defaultVueOptions;
329+
}
330+
}
331+
314332
private static createFormatter(type: 'default' | 'codeframe', options: any) {
315333
switch (type) {
316334
case 'default':
@@ -655,7 +673,7 @@ class ForkTsCheckerWebpackPlugin {
655673
MEMORY_LIMIT: String(this.memoryLimit),
656674
CHECK_SYNTACTIC_ERRORS: String(this.checkSyntacticErrors),
657675
USE_INCREMENTAL_API: String(this.useTypescriptIncrementalApi === true),
658-
VUE: String(this.vue)
676+
VUE: JSON.stringify(this.vue)
659677
};
660678

661679
if (typeof this.resolveModuleNameModule !== 'undefined') {

src/service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ function createChecker(
8181
eslinter,
8282
checkSyntacticErrors: process.env.CHECK_SYNTACTIC_ERRORS === 'true',
8383
resolveModuleName,
84-
resolveTypeReferenceDirective
84+
resolveTypeReferenceDirective,
85+
vue: JSON.parse(process.env.VUE!)
8586
};
8687

8788
if (useIncrementalApi) {
@@ -94,8 +95,7 @@ function createChecker(
9495
{
9596
watchPaths: process.env.WATCH === '' ? [] : process.env.WATCH!.split('|'),
9697
workNumber: parseInt(process.env.WORK_NUMBER!, 10) || 0,
97-
workDivision: parseInt(process.env.WORK_DIVISION!, 10) || 1,
98-
vue: process.env.VUE === 'true'
98+
workDivision: parseInt(process.env.WORK_DIVISION!, 10) || 1
9999
}
100100
);
101101

src/types/vue-options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface VueOptions {
2+
enabled: boolean;
3+
compiler: string;
4+
}

0 commit comments

Comments
 (0)