1 |
|
2 |
|
3 |
|
4 |
|
5 | "use strict";
|
6 |
|
7 | const getPaths = require("./getPaths");
|
8 | const forEachBail = require("./forEachBail");
|
9 |
|
10 | module.exports = class SymlinkPlugin {
|
11 | constructor(source, target) {
|
12 | this.source = source;
|
13 | this.target = target;
|
14 | }
|
15 |
|
16 | apply(resolver) {
|
17 | const target = resolver.ensureHook(this.target);
|
18 | const fs = resolver.fileSystem;
|
19 | resolver.getHook(this.source).tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
|
20 | const pathsResult = getPaths(request.path);
|
21 | const pathSeqments = pathsResult.seqments;
|
22 | const paths = pathsResult.paths;
|
23 |
|
24 | let containsSymlink = false;
|
25 | forEachBail.withIndex(paths, (path, idx, callback) => {
|
26 | fs.readlink(path, (err, result) => {
|
27 | if(!err && result) {
|
28 | pathSeqments[idx] = result;
|
29 | containsSymlink = true;
|
30 |
|
31 | if(/^(\/|[a-zA-z]:($|\\))/.test(result))
|
32 | return callback(null, idx);
|
33 | }
|
34 | callback();
|
35 | });
|
36 | }, (err, idx) => {
|
37 | if(!containsSymlink) return callback();
|
38 | const resultSeqments = typeof idx === "number" ? pathSeqments.slice(0, idx + 1) : pathSeqments.slice();
|
39 | const result = resultSeqments.reverse().reduce((a, b) => {
|
40 | return resolver.join(a, b);
|
41 | });
|
42 | const obj = Object.assign({}, request, {
|
43 | path: result
|
44 | });
|
45 | resolver.doResolve(target, obj, "resolved symlink to " + result, resolveContext, callback);
|
46 | });
|
47 | });
|
48 | }
|
49 | };
|