Skip to content

Commit 5359d63

Browse files
authored
Merge pull request #354 from HerringtonDarkholme/dev
[RFC] fix #270, support `appendTsSuffixTo` config
2 parents 60f6a42 + 77e0e12 commit 5359d63

16 files changed

Lines changed: 514 additions & 5 deletions

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
"rimraf": "^2.4.2",
6161
"typescript": "^2.0.3",
6262
"typings": "^1.4.0",
63+
"vue": "^2.0.3",
64+
"vue-loader": "^9.7.0",
6365
"webpack": "^1.11.0"
6466
}
6567
}

src/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ const definitionFileRegex = /\.d\.ts$/;
1414
function loader(this: interfaces.Webpack, contents: string) {
1515
this.cacheable && this.cacheable();
1616
const callback = this.async();
17-
const filePath = path.normalize(this.resourcePath);
18-
1917
const options = makeOptions(this);
18+
const rawFilePath = path.normalize(this.resourcePath);
19+
const filePath = utils.appendTsSuffixIfMatch(options.appendTsSuffixTo, rawFilePath);
2020

2121
const { instance, error } = instances.ensureTypeScriptInstance(options, this);
2222

@@ -58,6 +58,7 @@ function makeOptions(loader: interfaces.Webpack) {
5858
configFileName: 'tsconfig.json',
5959
transpileOnly: false,
6060
compilerOptions: {},
61+
appendTsSuffixTo: [],
6162
}, configFileOptions, queryOptions);
6263
options.ignoreDiagnostics = arrify(options.ignoreDiagnostics).map(Number);
6364
options.logLevel = options.logLevel.toUpperCase();

src/instances.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export function ensureTypeScriptInstance(
105105
modifiedFiles: null,
106106
};
107107

108-
const servicesHost = makeServicesHost(scriptRegex, log, loader, instance);
108+
const servicesHost = makeServicesHost(scriptRegex, log, loader, instance, loaderOptions.appendTsSuffixTo);
109109
instance.languageService = compiler.createLanguageService(servicesHost, compiler.createDocumentRegistry());
110110

111111
loader._compiler.plugin("after-compile", afterCompile(instance, configFilePath));

src/interfaces.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export interface Resolve {
8585
/**
8686
* The directory (absolute path) that contains your modules.
8787
* May also be an array of directories.
88-
* This setting should be used to add individual directories to the search path.
88+
* This setting should be used to add individual directories to the search path.
8989
*/
9090
root?: string | string[];
9191
/**
@@ -153,6 +153,7 @@ export interface LoaderOptions {
153153
transpileOnly: boolean;
154154
ignoreDiagnostics: number[];
155155
compilerOptions: typescript.CompilerOptions;
156+
appendTsSuffixTo: RegExp[];
156157
}
157158

158159
export interface TSFile {

src/servicesHost.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ function makeServicesHost(
1313
scriptRegex: RegExp,
1414
log: logger.Logger,
1515
loader: interfaces.Webpack,
16-
instance: interfaces.TSInstance
16+
instance: interfaces.TSInstance,
17+
appendTsSuffixTo: RegExp[]
1718
) {
1819
const { compiler, compilerOptions, files } = instance;
1920

@@ -77,6 +78,7 @@ function makeServicesHost(
7778

7879
try {
7980
resolvedFileName = resolver.resolveSync(path.normalize(path.dirname(containingFile)), moduleName);
81+
resolvedFileName = utils.appendTsSuffixIfMatch(appendTsSuffixTo, resolvedFileName);
8082

8183
if (!resolvedFileName.match(scriptRegex)) {
8284
resolvedFileName = null;

src/utils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,12 @@ export function makeError({ rawMessage, message, location, file }: MakeError): i
7171

7272
return <interfaces.WebpackError> objectAssign(error, { location, file });
7373
}
74+
75+
export function appendTsSuffixIfMatch(patterns: RegExp[], path: string): string {
76+
for (let regexp of patterns) {
77+
if (regexp.test(path)) {
78+
return path + '.ts';
79+
}
80+
}
81+
return path;
82+
}

test/comparison-tests/vue/_FLAKY_

Whitespace-only changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<template><p>Hello from {{msg}}</p></template>
2+
<script>
3+
export default {
4+
data(): Object {
5+
return {
6+
msg: "component"
7+
}
8+
}
9+
}
10+
</script>
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/******/ (function(modules) { // webpackBootstrap
2+
/******/ // The module cache
3+
/******/ var installedModules = {};
4+
5+
/******/ // The require function
6+
/******/ function __webpack_require__(moduleId) {
7+
8+
/******/ // Check if module is in cache
9+
/******/ if(installedModules[moduleId])
10+
/******/ return installedModules[moduleId].exports;
11+
12+
/******/ // Create a new module (and put it into the cache)
13+
/******/ var module = installedModules[moduleId] = {
14+
/******/ exports: {},
15+
/******/ id: moduleId,
16+
/******/ loaded: false
17+
/******/ };
18+
19+
/******/ // Execute the module function
20+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21+
22+
/******/ // Flag the module as loaded
23+
/******/ module.loaded = true;
24+
25+
/******/ // Return the exports of the module
26+
/******/ return module.exports;
27+
/******/ }
28+
29+
30+
/******/ // expose the modules object (__webpack_modules__)
31+
/******/ __webpack_require__.m = modules;
32+
33+
/******/ // expose the module cache
34+
/******/ __webpack_require__.c = installedModules;
35+
36+
/******/ // __webpack_public_path__
37+
/******/ __webpack_require__.p = "";
38+
39+
/******/ // Load entry module and return exports
40+
/******/ return __webpack_require__(0);
41+
/******/ })
42+
/************************************************************************/
43+
/******/ ([
44+
/* 0 */
45+
/***/ function(module, exports, __webpack_require__) {
46+
47+
var __vue_exports__, __vue_options__
48+
49+
/* script */
50+
__vue_exports__ = __webpack_require__(1)
51+
52+
/* template */
53+
var __vue_template__ = __webpack_require__(6)
54+
__vue_options__ = __vue_exports__ = __vue_exports__ || {}
55+
if (
56+
typeof __vue_exports__.default === "object" ||
57+
typeof __vue_exports__.default === "function"
58+
) {
59+
if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")}
60+
__vue_options__ = __vue_exports__ = __vue_exports__.default
61+
}
62+
if (typeof __vue_options__ === "function") {
63+
__vue_options__ = __vue_options__.options
64+
}
65+
__vue_options__.__file = "/ts-loader/.test/vue/index.vue"
66+
__vue_options__.render = __vue_template__.render
67+
__vue_options__.staticRenderFns = __vue_template__.staticRenderFns
68+
69+
/* hot reload */
70+
if (false) {(function () {
71+
var hotAPI = require("vue-hot-reload-api")
72+
hotAPI.install(require("vue"), false)
73+
if (!hotAPI.compatible) return
74+
module.hot.accept()
75+
if (!module.hot.data) {
76+
hotAPI.createRecord("data-v-1e83055b", __vue_options__)
77+
} else {
78+
hotAPI.reload("data-v-1e83055b", __vue_options__)
79+
}
80+
})()}
81+
if (__vue_options__.functional) {console.error("[vue-loader] index.vue: functional components are not supported and should be defined in plain js files using render functions.")}
82+
83+
module.exports = __vue_exports__
84+
85+
86+
/***/ },
87+
/* 1 */
88+
/***/ function(module, exports, __webpack_require__) {
89+
90+
//
91+
"use strict";
92+
var component_vue_1 = __webpack_require__(2);
93+
var helper_1 = __webpack_require__(5);
94+
exports.__esModule = true;
95+
exports["default"] = {
96+
components: { component: component_vue_1["default"] },
97+
data: function () {
98+
return {
99+
msg: "world"
100+
};
101+
},
102+
method: {
103+
myMethod: helper_1.myMethod
104+
}
105+
};
106+
107+
108+
/***/ },
109+
/* 2 */
110+
/***/ function(module, exports, __webpack_require__) {
111+
112+
var __vue_exports__, __vue_options__
113+
114+
/* script */
115+
__vue_exports__ = __webpack_require__(3)
116+
117+
/* template */
118+
var __vue_template__ = __webpack_require__(4)
119+
__vue_options__ = __vue_exports__ = __vue_exports__ || {}
120+
if (
121+
typeof __vue_exports__.default === "object" ||
122+
typeof __vue_exports__.default === "function"
123+
) {
124+
if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")}
125+
__vue_options__ = __vue_exports__ = __vue_exports__.default
126+
}
127+
if (typeof __vue_options__ === "function") {
128+
__vue_options__ = __vue_options__.options
129+
}
130+
__vue_options__.__file = "/ts-loader/.test/vue/component.vue"
131+
__vue_options__.render = __vue_template__.render
132+
__vue_options__.staticRenderFns = __vue_template__.staticRenderFns
133+
134+
/* hot reload */
135+
if (false) {(function () {
136+
var hotAPI = require("vue-hot-reload-api")
137+
hotAPI.install(require("vue"), false)
138+
if (!hotAPI.compatible) return
139+
module.hot.accept()
140+
if (!module.hot.data) {
141+
hotAPI.createRecord("data-v-6043e8f4", __vue_options__)
142+
} else {
143+
hotAPI.reload("data-v-6043e8f4", __vue_options__)
144+
}
145+
})()}
146+
if (__vue_options__.functional) {console.error("[vue-loader] component.vue: functional components are not supported and should be defined in plain js files using render functions.")}
147+
148+
module.exports = __vue_exports__
149+
150+
151+
/***/ },
152+
/* 3 */
153+
/***/ function(module, exports) {
154+
155+
//
156+
"use strict";
157+
exports.__esModule = true;
158+
exports["default"] = {
159+
data: function () {
160+
return {
161+
msg: "component"
162+
};
163+
}
164+
};
165+
166+
167+
/***/ },
168+
/* 4 */
169+
/***/ function(module, exports, __webpack_require__) {
170+
171+
module.exports={render:function (){with(this) {
172+
return _h('p', ["Hello from " + _s(msg)])
173+
}},staticRenderFns: []}
174+
if (false) {
175+
module.hot.accept()
176+
if (module.hot.data) {
177+
require("vue-hot-reload-api").rerender("data-v-6043e8f4", module.exports)
178+
}
179+
}
180+
181+
/***/ },
182+
/* 5 */
183+
/***/ function(module, exports) {
184+
185+
"use strict";
186+
function myMethod() {
187+
console.log('from helper!');
188+
}
189+
exports.myMethod = myMethod;
190+
191+
192+
/***/ },
193+
/* 6 */
194+
/***/ function(module, exports, __webpack_require__) {
195+
196+
module.exports={render:function (){with(this) {
197+
return _h('p', ["hallo " + _s(msg)])
198+
}},staticRenderFns: []}
199+
if (false) {
200+
module.hot.accept()
201+
if (module.hot.data) {
202+
require("vue-hot-reload-api").rerender("data-v-1e83055b", module.exports)
203+
}
204+
}
205+
206+
/***/ }
207+
/******/ ]);

0 commit comments

Comments
 (0)