Skip to content
This repository was archived by the owner on Mar 17, 2021. It is now read-only.

Commit dbcd6cc

Browse files
adriancmirandajoshwiens
authored andcommittedMar 31, 2017
feat: Emit files with relative urls (#135)
* new configuration to emit files with relative URLs * Added support for relativePath option * Changed the 'relativePath' parameter name to 'useRelativePath' * feat: 'useRelativePath' working on dev mode too * style: more readable code * fix: posix on windows
1 parent 5d8f73e commit dbcd6cc

File tree

4 files changed

+215
-160
lines changed

4 files changed

+215
-160
lines changed
 

‎.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1+
# development
12
/node_modules
23
/coverage
4+
*.log
5+
6+
# dotfiles
7+
.*
8+
!.gitignore
9+
*~
10+
*#*

‎README.md

+155-145
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,155 @@
1-
[![npm][npm]][npm-url]
2-
[![node][node]][node-url]
3-
[![deps][deps]][deps-url]
4-
[![tests][tests]][tests-url]
5-
[![coverage][cover]][cover-url]
6-
[![chat][chat]][chat-url]
7-
8-
<div align="center">
9-
<a href="https://github.com/webpack/webpack">
10-
<img width="200" height="200"
11-
src="https://webpack.js.org/assets/icon-square-big.svg">
12-
</a>
13-
<h1>File Loader</h1>
14-
</div>
15-
16-
<h2 align="center">Install</h2>
17-
18-
```bash
19-
npm install --save-dev file-loader
20-
```
21-
22-
<h2 align="center">Usage</h2>
23-
24-
By default the filename of the resulting file is the MD5 hash of the file's contents
25-
with the original extension of the required resource.
26-
27-
``` javascript
28-
var url = require("file-loader!./file.png");
29-
// => emits file.png as file in the output directory and returns the public url
30-
// => returns i. e. "/public-path/0dcbbaa701328a3c262cfd45869e351f.png"
31-
```
32-
33-
By default a file is emitted, however this can be disabled if required (e.g. for server
34-
side packages).
35-
36-
``` javascript
37-
var url = require("file-loader?emitFile=false!./file.png");
38-
// => returns the public url but does NOT emit a file
39-
// => returns i. e. "/public-path/0dcbbaa701328a3c262cfd45869e351f.png"
40-
```
41-
42-
#### Filename templates
43-
44-
You can configure a custom filename template for your file using the query parameter `name`. For instance, to copy a file from your `context` directory into the output directory retaining the full directory structure, you might use `?name=[path][name].[ext]`.
45-
46-
By default, the path and name you specify will output the file in that same directory and will also use that same URL path to access the file.
47-
48-
You can specify custom output and public paths by using the `outputPath` and `publicPath` query name parameters:
49-
50-
```
51-
use: "file-loader?name=[name].[ext]&publicPath=assets/foo/&outputPath=app/images/"
52-
```
53-
54-
#### Filename template placeholders
55-
56-
* `[ext]` the extension of the resource
57-
* `[name]` the basename of the resource
58-
* `[path]` the path of the resource relative to the `context` query parameter or option.
59-
* `[hash]` the hash of the content, `hex`-encoded `md5` by default
60-
* `[<hashType>:hash:<digestType>:<length>]` optionally you can configure
61-
* other `hashType`s, i. e. `sha1`, `md5`, `sha256`, `sha512`
62-
* other `digestType`s, i. e. `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
63-
* and `length` the length in chars
64-
* `[N]` the N-th match obtained from matching the current file name against the query param `regExp`
65-
66-
#### Examples
67-
68-
``` javascript
69-
require("file-loader?name=js/[hash].script.[ext]!./javascript.js");
70-
// => js/0dcbbaa701328a3c262cfd45869e351f.script.js
71-
72-
require("file-loader?name=html-[hash:6].html!./page.html");
73-
// => html-109fa8.html
74-
75-
require("file-loader?name=[hash]!./flash.txt");
76-
// => c31e9820c001c9c4a86bce33ce43b679
77-
78-
require("file-loader?name=[sha512:hash:base64:7].[ext]!./image.png");
79-
// => gdyb21L.png
80-
// use sha512 hash instead of md5 and with only 7 chars of base64
81-
82-
require("file-loader?name=img-[sha512:hash:base64:7].[ext]!./image.jpg");
83-
// => img-VqzT5ZC.jpg
84-
// use custom name, sha512 hash instead of md5 and with only 7 chars of base64
85-
86-
require("file-loader?name=picture.png!./myself.png");
87-
// => picture.png
88-
89-
require("file-loader?name=[path][name].[ext]?[hash]!./dir/file.png")
90-
// => dir/file.png?e43b20c069c4a01867c31e98cbce33c9
91-
```
92-
93-
<h2 align="center">Contributing</h2>
94-
95-
Don't hesitate to create a pull request. Every contribution is appreciated. In development you can start the tests by calling `npm test`.
96-
97-
<h2 align="center">Maintainers</h2>
98-
99-
<table>
100-
<tbody>
101-
<tr>
102-
<td align="center">
103-
<img width="150" height="150"
104-
src="https://avatars.githubusercontent.com/sokra?v=3">
105-
<br />
106-
<a href="https://github.com/">Tobias Koppers</a>
107-
</td>
108-
<td align="center">
109-
<img width="150" height="150"
110-
src="https://avatars.githubusercontent.com/SpaceK33z?v=3">
111-
<br />
112-
<a href="https://github.com/">Kees Kluskens</a>
113-
</td>
114-
<td align="center">
115-
<img width="150" height="150"
116-
src="https://avatars.githubusercontent.com/mobitar?v=3">
117-
<br />
118-
<a href="https://github.com/">Mo Bitar</a>
119-
</td>
120-
</tr>
121-
</tbody>
122-
</table>
123-
124-
125-
<h2 align="center">LICENSE</h2>
126-
127-
MIT
128-
129-
[npm]: https://img.shields.io/npm/v/file-loader.svg
130-
[npm-url]: https://npmjs.com/package/file-loader
131-
132-
[node]: https://img.shields.io/node/v/file-loader.svg
133-
[node-url]: https://nodejs.org
134-
135-
[deps]: https://david-dm.org/webpack-contrib/file-loader.svg
136-
[deps-url]: https://david-dm.org/webpack-contrib/file-loader
137-
138-
[tests]: http://img.shields.io/travis/webpack-contrib/file-loader.svg
139-
[tests-url]: https://travis-ci.org/webpack-contrib/file-loader
140-
141-
[cover]: https://coveralls.io/repos/github/webpack-contrib/file-loader/badge.svg
142-
[cover-url]: https://coveralls.io/github/webpack-contrib/file-loader
143-
144-
[chat]: https://badges.gitter.im/webpack/webpack.svg
145-
[chat-url]: https://gitter.im/webpack/webpack
1+
[![npm][npm]][npm-url]
2+
[![node][node]][node-url]
3+
[![deps][deps]][deps-url]
4+
[![tests][tests]][tests-url]
5+
[![coverage][cover]][cover-url]
6+
[![chat][chat]][chat-url]
7+
8+
<div align="center">
9+
<a href="https://github.com/webpack/webpack">
10+
<img width="200" height="200"
11+
src="https://webpack.js.org/assets/icon-square-big.svg">
12+
</a>
13+
<h1>File Loader</h1>
14+
</div>
15+
16+
<h2 align="center">Install</h2>
17+
18+
```bash
19+
npm install --save-dev file-loader
20+
```
21+
22+
<h2 align="center">Usage</h2>
23+
24+
By default the filename of the resulting file is the MD5 hash of the file's contents
25+
with the original extension of the required resource.
26+
27+
``` javascript
28+
var url = require("file-loader!./file.png");
29+
// => emits file.png as file in the output directory and returns the public url
30+
// => returns i. e. "/public-path/0dcbbaa701328a3c262cfd45869e351f.png"
31+
```
32+
33+
By default a file is emitted, however this can be disabled if required (e.g. for server
34+
side packages).
35+
36+
``` javascript
37+
var url = require("file-loader?emitFile=false!./file.png");
38+
// => returns the public url but does NOT emit a file
39+
// => returns i. e. "/public-path/0dcbbaa701328a3c262cfd45869e351f.png"
40+
```
41+
42+
#### Filename templates
43+
44+
You can configure a custom filename template for your file using the query parameter `name`. For instance, to copy a file from your `context` directory into the output directory retaining the full directory structure, you might use `?name=[path][name].[ext]`.
45+
46+
By default, the path and name you specify will output the file in that same directory and will also use that same URL path to access the file.
47+
48+
You can specify custom output and public paths by using the `outputPath`, `publicPath` and `useRelativePath` query name parameters:
49+
50+
```
51+
use: "file-loader?name=[name].[ext]&publicPath=assets/foo/&outputPath=app/images/"
52+
```
53+
54+
`useRelativePath` should be `true` if you wish to generate relative URL to the each file context
55+
```javascript
56+
{
57+
loader: 'file-loader',
58+
query: {
59+
useRelativePath: process.env.NODE_ENV === "production"
60+
}
61+
}
62+
```
63+
64+
#### Filename template placeholders
65+
66+
* `[ext]` the extension of the resource
67+
* `[name]` the basename of the resource
68+
* `[path]` the path of the resource relative to the `context` query parameter or option.
69+
* `[hash]` the hash of the content, `hex`-encoded `md5` by default
70+
* `[<hashType>:hash:<digestType>:<length>]` optionally you can configure
71+
* other `hashType`s, i. e. `sha1`, `md5`, `sha256`, `sha512`
72+
* other `digestType`s, i. e. `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
73+
* and `length` the length in chars
74+
* `[N]` the N-th match obtained from matching the current file name against the query param `regExp`
75+
76+
#### Examples
77+
78+
``` javascript
79+
require("file-loader?name=js/[hash].script.[ext]!./javascript.js");
80+
// => js/0dcbbaa701328a3c262cfd45869e351f.script.js
81+
82+
require("file-loader?name=html-[hash:6].html!./page.html");
83+
// => html-109fa8.html
84+
85+
require("file-loader?name=[hash]!./flash.txt");
86+
// => c31e9820c001c9c4a86bce33ce43b679
87+
88+
require("file-loader?name=[sha512:hash:base64:7].[ext]!./image.png");
89+
// => gdyb21L.png
90+
// use sha512 hash instead of md5 and with only 7 chars of base64
91+
92+
require("file-loader?name=img-[sha512:hash:base64:7].[ext]!./image.jpg");
93+
// => img-VqzT5ZC.jpg
94+
// use custom name, sha512 hash instead of md5 and with only 7 chars of base64
95+
96+
require("file-loader?name=picture.png!./myself.png");
97+
// => picture.png
98+
99+
require("file-loader?name=[path][name].[ext]?[hash]!./dir/file.png")
100+
// => dir/file.png?e43b20c069c4a01867c31e98cbce33c9
101+
```
102+
103+
<h2 align="center">Contributing</h2>
104+
105+
Don't hesitate to create a pull request. Every contribution is appreciated. In development you can start the tests by calling `npm test`.
106+
107+
<h2 align="center">Maintainers</h2>
108+
109+
<table>
110+
<tbody>
111+
<tr>
112+
<td align="center">
113+
<img width="150" height="150"
114+
src="https://avatars.githubusercontent.com/sokra?v=3">
115+
<br />
116+
<a href="https://github.com/">Tobias Koppers</a>
117+
</td>
118+
<td align="center">
119+
<img width="150" height="150"
120+
src="https://avatars.githubusercontent.com/SpaceK33z?v=3">
121+
<br />
122+
<a href="https://github.com/">Kees Kluskens</a>
123+
</td>
124+
<td align="center">
125+
<img width="150" height="150"
126+
src="https://avatars.githubusercontent.com/mobitar?v=3">
127+
<br />
128+
<a href="https://github.com/">Mo Bitar</a>
129+
</td>
130+
</tr>
131+
</tbody>
132+
</table>
133+
134+
135+
<h2 align="center">LICENSE</h2>
136+
137+
MIT
138+
139+
[npm]: https://img.shields.io/npm/v/file-loader.svg
140+
[npm-url]: https://npmjs.com/package/file-loader
141+
142+
[node]: https://img.shields.io/node/v/file-loader.svg
143+
[node-url]: https://nodejs.org
144+
145+
[deps]: https://david-dm.org/webpack-contrib/file-loader.svg
146+
[deps-url]: https://david-dm.org/webpack-contrib/file-loader
147+
148+
[tests]: http://img.shields.io/travis/webpack-contrib/file-loader.svg
149+
[tests-url]: https://travis-ci.org/webpack-contrib/file-loader
150+
151+
[cover]: https://coveralls.io/repos/github/webpack-contrib/file-loader/badge.svg
152+
[cover-url]: https://coveralls.io/github/webpack-contrib/file-loader
153+
154+
[chat]: https://badges.gitter.im/webpack/webpack.svg
155+
[chat-url]: https://gitter.im/webpack/webpack

‎index.js

+35-14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
MIT License http://www.opensource.org/licenses/mit-license.php
33
Author Tobias Koppers @sokra
44
*/
5+
var path = require("path");
56
var loaderUtils = require("loader-utils");
67

78
module.exports = function(content) {
@@ -11,9 +12,9 @@ module.exports = function(content) {
1112
var query = loaderUtils.getOptions(this) || {};
1213
var configKey = query.config || "fileLoader";
1314
var options = this.options[configKey] || {};
14-
1515
var config = {
1616
publicPath: false,
17+
useRelativePath: false,
1718
name: "[hash].[ext]"
1819
};
1920

@@ -27,29 +28,48 @@ module.exports = function(content) {
2728
config[attr] = query[attr];
2829
});
2930

31+
var context = config.context || this.options.context;
3032
var url = loaderUtils.interpolateName(this, config.name, {
31-
context: config.context || this.options.context,
33+
context: context,
3234
content: content,
3335
regExp: config.regExp
3436
});
3537

36-
var outputPath = url;
37-
38-
var publicPath = "__webpack_public_path__ + " + JSON.stringify(url);
39-
38+
var outputPath = "";
4039
if (config.outputPath) {
41-
// support functions as outputPath to generate them dynamically
42-
outputPath = typeof config.outputPath === "function"
43-
? config.outputPath(url)
44-
: config.outputPath + url
40+
// support functions as outputPath to generate them dynamically
41+
outputPath = (
42+
typeof config.outputPath === "function"
43+
? config.outputPath(url)
44+
: config.outputPath
45+
);
4546
}
4647

48+
var filePath = this.resourcePath;
49+
if (config.useRelativePath) {
50+
var issuerContext = this._module && this._module.issuer && this._module.issuer.context || context;
51+
var relativeUrl = issuerContext && path.relative(issuerContext, filePath).split(path.sep).join("/");
52+
var relativePath = relativeUrl && path.dirname(relativeUrl) + "/";
53+
if (~relativePath.indexOf("../")) {
54+
outputPath = path.posix.join(outputPath, relativePath, url);
55+
} else {
56+
outputPath = relativePath + url;
57+
}
58+
url = relativePath + url;
59+
} else if (outputPath) {
60+
outputPath = outputPath + url;
61+
url = outputPath;
62+
} else {
63+
outputPath = url;
64+
}
65+
66+
var publicPath = "__webpack_public_path__ + " + JSON.stringify(url);
4767
if (config.publicPath) {
4868
// support functions as publicPath to generate them dynamically
4969
publicPath = JSON.stringify(
50-
typeof config.publicPath === "function"
51-
? config.publicPath(url)
52-
: config.publicPath + url
70+
typeof config.publicPath === "function"
71+
? config.publicPath(url)
72+
: config.publicPath + url
5373
);
5474
}
5575

@@ -58,5 +78,6 @@ module.exports = function(content) {
5878
}
5979

6080
return "module.exports = " + publicPath + ";";
61-
}
81+
};
82+
6283
module.exports.raw = true;

‎test/correct-filename.test.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ describe("correct-filename", function() {
6161
test("sntmopgidsdqrofkjywoyldtiij.txt", "/file.txt", "name=[hash:base26].[ext]");
6262
test("sntmopgids.txt", "/file.txt", "name=[hash:base26:10].[ext]");
6363
});
64-
6564
});
6665

6766
describe("publicPath option", function() {
@@ -70,4 +69,21 @@ describe("publicPath option", function() {
7069
'module.exports = "http://cdn/81dc9bdb52d04dc20036dbd8313ed055.txt";'
7170
);
7271
});
72+
});
73+
74+
describe("useRelativePath option", function() {
75+
it("should be supported", function() {
76+
run("/this/is/the/context/file.txt", "useRelativePath=true").result.should.be.eql(
77+
'module.exports = __webpack_public_path__ + \"./81dc9bdb52d04dc20036dbd8313ed055.txt\";'
78+
);
79+
run("/this/is/file.txt", "useRelativePath=true").result.should.be.eql(
80+
'module.exports = __webpack_public_path__ + \"../../81dc9bdb52d04dc20036dbd8313ed055.txt\";'
81+
);
82+
run("/this/file.txt", "context=/this/is/the/&useRelativePath=true").result.should.be.eql(
83+
'module.exports = __webpack_public_path__ + \"../../81dc9bdb52d04dc20036dbd8313ed055.txt\";'
84+
);
85+
run("/this/file.txt", "context=/&useRelativePath=true").result.should.be.eql(
86+
'module.exports = __webpack_public_path__ + \"this/81dc9bdb52d04dc20036dbd8313ed055.txt\";'
87+
);
88+
});
7389
});

0 commit comments

Comments
 (0)
This repository has been archived.