├── .gitignore
├── .jshintrc
├── .nvmrc
├── LICENSE
├── codec
├── absolute.js
├── bower-component.js
├── index.js
├── npm-module.js
├── output-relative.js
├── output-root-relative.js
├── project-relative.js
├── project-root-relative.js
├── source-relative.js
├── source-root-relative.js
├── utility
│ ├── enhanced-relative.js
│ ├── get-context-directory.js
│ └── get-output-directory.js
├── webpack-bootstrap.js
└── webpack-protocol.js
├── index.js
├── lib
├── loader.js
├── module-filename-template.js
└── process
│ ├── debug-message.js
│ ├── decode-sources-with.js
│ ├── encode-sources-with.js
│ ├── get-error.js
│ ├── get-field-as-fn.js
│ ├── index.js
│ ├── locate-root-with.js
│ ├── test-codec.js
│ ├── throw-errors.js
│ └── to-reg-exp.js
├── package-lock.json
├── package.json
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /node_modules
3 | /npm-debug.log
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "camelcase": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "forin": false,
7 | "freeze": false,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": "nofunc",
11 | "newcap": true,
12 | "noarg": true,
13 | "noempty": true,
14 | "nonbsp": true,
15 | "nonew": true,
16 | "plusplus": false,
17 | "quotmark": "single",
18 | "undef": true,
19 | "unused": true,
20 | "strict": true,
21 | "maxparams": 20,
22 | "maxdepth": 5,
23 | "maxlen": 120,
24 | "scripturl": true,
25 | "node": true,
26 | "esnext": true,
27 | "jasmine": true
28 | }
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 8.9
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Ben Holloway
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/codec/absolute.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path'),
4 | fs = require('fs');
5 |
6 | /**
7 | * Codec for absolute paths.
8 | * @type {{name:string, decode: function, encode: function, root: function}}
9 | */
10 | module.exports = {
11 | name : 'absolute',
12 | decode: decode,
13 | encode: encode,
14 | root : root
15 | };
16 |
17 | /**
18 | * Decode the given uri.
19 | * Any path with leading slash is tested in an absolute sense.
20 | * @this {{options: object}} A loader or compilation
21 | * @param {string} uri A source uri to decode
22 | * @returns {boolean|string} False where unmatched else the decoded path
23 | */
24 | function decode(uri) {
25 | return path.isAbsolute(uri) && fs.existsSync(uri) && fs.statSync(uri).isFile() && uri;
26 | }
27 |
28 | /**
29 | * Encode the given file path.
30 | * @this {{options: object}} A loader or compilation
31 | * @returns {string} A uri
32 | */
33 | function encode(absolute) {
34 | return absolute;
35 | }
36 |
37 | /**
38 | * The source-map root where relevant.
39 | * @this {{options: object}} A loader or compilation
40 | * @returns {string|undefined} The source-map root applicable to any encoded uri
41 | */
42 | function root() {
43 | }
44 |
--------------------------------------------------------------------------------
/codec/bower-component.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Codec for code generated by the Bower plugin.
5 | * @type {{name:string, decode:function, abstract:boolean}}
6 | */
7 | module.exports = {
8 | name : 'bowerComponent',
9 | decode : decode,
10 | abstract: true
11 | };
12 |
13 | /**
14 | * Validate the given uri (abstract).
15 | * @this {{options: object}} A loader or compilation
16 | * @param {string} uri A source uri to decode
17 | * @returns {boolean|string} False where unmatched else True
18 | */
19 | function decode(uri) {
20 | return /^\/?([\w-]+)\s+\(bower component\)$/.test(uri);
21 | }
22 |
--------------------------------------------------------------------------------
/codec/index.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | require('./webpack-protocol'),
3 | require('./webpack-bootstrap'),
4 | require('./bower-component'),
5 | require('./npm-module'),
6 | /* insert here any additional special character CODECs */
7 | require('./output-relative'),
8 | require('./output-root-relative'),
9 | require('./project-relative'),
10 | require('./project-root-relative'),
11 | require('./source-relative'),
12 | require('./source-root-relative'),
13 | require('./absolute')
14 | ];
15 |
--------------------------------------------------------------------------------
/codec/npm-module.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path'),
4 | fs = require('fs');
5 |
6 | var loaderUtils = require('loader-utils');
7 |
8 | var getContextDirectory = require('./utility/get-context-directory');
9 |
10 | /**
11 | * Codec for relative paths with respect to the context directory.
12 | * @type {{name:string, decode: function}}
13 | */
14 | module.exports = {
15 | name : 'npmModule',
16 | decode: decode
17 | };
18 |
19 | /**
20 | * Decode the given uri.
21 | * Include only module paths containing `~`.
22 | * @this {{options: object}} A loader or compilation
23 | * @param {string} uri A source uri to decode
24 | * @returns {boolean|string} False where unmatched else the decoded path
25 | */
26 | function decode(uri) {
27 | /* jshint validthis:true */
28 | if (/~/.test(uri)) {
29 | var relative = loaderUtils.urlToRequest(uri),
30 | base = getContextDirectory.call(this),
31 | absFile = path.normalize(path.join(base, 'node_modules', relative)),
32 | isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile();
33 | return isValid && absFile;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/codec/output-relative.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path'),
4 | fs = require('fs');
5 |
6 | var getOutputDirectory = require('./utility/get-output-directory');
7 |
8 | /**
9 | * Codec for relative paths with respect to the output directory.
10 | * @type {{name:string, decode: function, encode: function, root: function}}
11 | */
12 | module.exports = {
13 | name : 'outputRelative',
14 | decode: decode,
15 | encode: encode,
16 | root : getOutputDirectory
17 | };
18 |
19 | /**
20 | * Decode the given uri.
21 | * Any path with without leading slash is tested against output directory.
22 | * @this {{options: object}} A loader or compilation
23 | * @param {string} uri A source uri to decode
24 | * @returns {boolean|string} False where unmatched else the decoded path
25 | */
26 | function decode(uri) {
27 | /* jshint validthis:true */
28 | var base = !uri.startsWith('/') && getOutputDirectory.call(this),
29 | absFile = !!base && path.normalize(path.join(base, uri)),
30 | isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile();
31 | return isValid && absFile;
32 | }
33 |
34 | /**
35 | * Encode the given file path.
36 | * @this {{options: object}} A loader or compilation
37 | * @param {string} absolute An absolute file path to encode
38 | * @returns {string} A uri without leading slash
39 | */
40 | function encode(absolute) {
41 | /* jshint validthis:true */
42 | var base = getOutputDirectory.call(this);
43 | if (!base) {
44 | throw new Error('Cannot locate the Webpack output directory');
45 | }
46 | else {
47 | return path.relative(base, absolute);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/codec/output-root-relative.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var relative = require('./output-relative');
4 |
5 | /**
6 | * Codec for relative paths with respect to the output directory.
7 | * @type {{name:string, decode: function, encode: function, root: function}}
8 | */
9 | module.exports = {
10 | name : 'outputRootRelative',
11 | decode: decode,
12 | encode: encode,
13 | root : relative.root
14 | };
15 |
16 | /**
17 | * Decode the given uri.
18 | * Any path with leading slash is tested against output directory.
19 | * @this {{options: object}} A loader or compilation
20 | * @param {string} uri A source uri to decode
21 | * @returns {boolean|string} False where unmatched else the decoded path
22 | */
23 | function decode(uri) {
24 | /* jshint validthis:true */
25 | return uri.startsWith('/') && relative.decode.call(this, uri.slice(1));
26 | }
27 |
28 | /**
29 | * Encode the given file path.
30 | * @this {{options: object}} A loader or compilation
31 | * @param {string} absolute An absolute file path to encode
32 | * @returns {string} A uri with leading slash
33 | */
34 | function encode(absolute) {
35 | /* jshint validthis:true */
36 | return '/' + relative.encode.call(this, absolute);
37 | }
38 |
--------------------------------------------------------------------------------
/codec/project-relative.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path'),
4 | fs = require('fs');
5 |
6 | var getContextDirectory = require('./utility/get-context-directory'),
7 | enhancedRelative = require('./utility/enhanced-relative');
8 |
9 | /**
10 | * Codec for relative paths with respect to the project directory.
11 | * @type {{name:string, decode: function, encode: function, root: function}}
12 | */
13 | module.exports = {
14 | name : 'projectRelative',
15 | decode: decode,
16 | encode: encode,
17 | root : getContextDirectory
18 | };
19 |
20 | /**
21 | * Decode the given uri.
22 | * Any path with without leading slash is tested against project directory.
23 | * @this {{options: object}} A loader or compilation
24 | * @param {string} uri A source uri to decode
25 | * @returns {boolean|string} False where unmatched else the decoded path
26 | */
27 | function decode(uri) {
28 | /* jshint validthis:true */
29 | var base = !uri.startsWith('/') && getContextDirectory.call(this),
30 | absFile = !!base && path.normalize(path.join(base, uri)),
31 | isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile();
32 | return isValid && absFile;
33 | }
34 |
35 | /**
36 | * Encode the given file path.
37 | * @this {{options: object}} A loader or compilation
38 | * @param {string} absolute An absolute file path to encode
39 | * @returns {string} A uri without leading slash
40 | */
41 | function encode(absolute) {
42 | /* jshint validthis:true */
43 | var base = getContextDirectory.call(this);
44 | if (!base) {
45 | throw new Error('Cannot locate the Webpack project directory');
46 | }
47 | else {
48 | return enhancedRelative(base, absolute);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/codec/project-root-relative.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var relative = require('./project-relative');
4 |
5 | /**
6 | * Codec for relative paths with respect to the project directory.
7 | * @type {{name:string, decode: function, encode: function, root: function}}
8 | */
9 | module.exports = {
10 | name : 'projectRootRelative',
11 | decode: decode,
12 | encode: encode,
13 | root : relative.root
14 | };
15 |
16 | /**
17 | * Decode the given uri.
18 | * Any path with leading slash is tested against project directory.
19 | * @this {{options: object}} A loader or compilation
20 | * @param {string} uri A source uri to decode
21 | * @returns {boolean|string} False where unmatched else the decoded path
22 | */
23 | function decode(uri) {
24 | /* jshint validthis:true */
25 | return uri.startsWith('/') && relative.decode.call(this, uri.slice(1));
26 | }
27 |
28 | /**
29 | * Encode the given file path.
30 | * @this {{options: object}} A loader or compilation
31 | * @param {string} absolute An absolute file path to encode
32 | * @returns {string} A uri with leading slash
33 | */
34 | function encode(absolute) {
35 | /* jshint validthis:true */
36 | return '/' + relative.encode.call(this, absolute);
37 | }
38 |
--------------------------------------------------------------------------------
/codec/source-relative.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path'),
4 | fs = require('fs');
5 |
6 | /**
7 | * Codec for relative paths with respect to the source directory.
8 | * @type {{name:string, decode: function, encode: function, root: function}}
9 | */
10 | module.exports = {
11 | name : 'sourceRelative',
12 | decode: decode,
13 | encode: encode,
14 | root : root
15 | };
16 |
17 | /**
18 | * Decode the given uri.
19 | * Any path without leading slash is tested against source directory.
20 | * @this {{options: object}} A loader or compilation
21 | * @param {string} uri A source uri to decode
22 | * @returns {boolean|string} False where unmatched else the decoded path
23 | */
24 | function decode(uri) {
25 | /* jshint validthis:true */
26 | var base = !uri.startsWith('/') && this.context,
27 | absFile = !!base && path.normalize(path.join(base, uri)),
28 | isValid = !!absFile && fs.existsSync(absFile) && fs.statSync(absFile).isFile();
29 | return isValid && absFile;
30 | }
31 |
32 | /**
33 | * Encode the given file path.
34 | * @this {{options: object}} A loader or compilation
35 | * @param {string} absolute An absolute file path to encode
36 | * @returns {string} A uri without leading slash
37 | */
38 | function encode(absolute) {
39 | /* jshint validthis:true */
40 | return path.relative(this.context, absolute);
41 | }
42 |
43 | /**
44 | * The source-map root where relevant.
45 | * @this {{options: object}} A loader or compilation
46 | * @returns {string|undefined} The source-map root applicable to any encoded uri
47 | */
48 | function root() {
49 | /* jshint validthis:true */
50 | return this.context;
51 | }
52 |
--------------------------------------------------------------------------------
/codec/source-root-relative.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var relative = require('./source-relative');
4 |
5 | /**
6 | * Codec for relative paths with respect to the source directory.
7 | * @type {{name:string, decode: function, encode: function, root: function}}
8 | */
9 | module.exports = {
10 | name : 'sourceRootRelative',
11 | decode: decode,
12 | encode: encode,
13 | root : relative.root
14 | };
15 |
16 | /**
17 | * Decode the given uri.
18 | * Any path with leading slash is tested against source directory.
19 | * @this {{options: object}} A loader or compilation
20 | * @param {string} uri A source uri to decode
21 | * @returns {boolean|string} False where unmatched else the decoded path
22 | */
23 | function decode(uri) {
24 | /* jshint validthis:true */
25 | return uri.startsWith('/') && relative.decode.call(this, uri.slice(1));
26 | }
27 |
28 | /**
29 | * Encode the given file path.
30 | * @this {{options: object}} A loader or compilation
31 | * @param {string} absolute An absolute file path to encode
32 | * @returns {string} A uri with leading slash
33 | */
34 | function encode(absolute) {
35 | /* jshint validthis:true */
36 | return '/' + relative.encode.call(this, absolute);
37 | }
38 |
--------------------------------------------------------------------------------
/codec/utility/enhanced-relative.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs'),
4 | path = require('path');
5 |
6 | var cache;
7 |
8 | /**
9 | * Perform path.relative()
but try to detect and correct sym-linked node modules.
10 | * @param {string} from The base path
11 | * @param {string} to The full path
12 | */
13 | function enhancedRelative(from, to) {
14 |
15 | // relative path
16 | var relative = path.relative(from, to);
17 |
18 | // trailing is the relative path portion without any '../'
19 | var trailing = relative.replace(/^\.{2}[\\\/]/, ''),
20 | leading = to.replace(trailing, '');
21 |
22 | // within project is what we want
23 | var isInProject = (relative === trailing);
24 | if (isInProject) {
25 | return relative;
26 | }
27 | // otherwise look at symbolic linked modules
28 | else {
29 | var splitTrailing = trailing.split(/[\\\/]/);
30 |
31 | // ensure failures can retry with fresh cache
32 | for (var i = cache ? 2 : 1, foundPath = false; (i > 0) && !foundPath; i--) {
33 |
34 | // ensure cache
35 | cache = cache || indexLinkedModules(from);
36 |
37 | // take elements from the trailing path and append them the the leading path in an attempt to find a package.json
38 | for (var j = 0; (j < splitTrailing.length) && !foundPath; j++) {
39 |
40 | // find the name of packages in the actual file location
41 | // start at the lowest concrete directory that appears in the relative path
42 | var packagePath = path.join.apply(path, [leading].concat(splitTrailing.slice(0, j + 1))),
43 | packageJsonPath = path.join(packagePath, 'package.json'),
44 | packageName = fs.existsSync(packageJsonPath) && require(packageJsonPath).name;
45 |
46 | // lookup any package name in the cache
47 | var linkedPackagePath = !!packageName && cache[packageName];
48 | if (linkedPackagePath) {
49 |
50 | // the remaining portion of the trailing path, not including the package path
51 | var remainingPath = path.join.apply(path, splitTrailing.slice(j + 1));
52 |
53 | // validate the remaining path in the linked location
54 | // failure implies we will keep trying nested sym-linked packages
55 | var linkedFilePath = path.join(linkedPackagePath, remainingPath),
56 | isValid = !!linkedFilePath && fs.existsSync(linkedFilePath) &&
57 | fs.statSync(linkedFilePath).isFile();
58 |
59 | // path is found where valid
60 | foundPath = isValid && linkedFilePath;
61 | }
62 | }
63 |
64 | // cache cannot be trusted if a file can't be found
65 | // set the cache to false to trigger its rebuild
66 | cache = !!foundPath && cache;
67 | }
68 |
69 | // the relative path should now be within the project
70 | return foundPath ? path.relative(from, foundPath) : relative;
71 | }
72 | }
73 |
74 | module.exports = enhancedRelative;
75 |
76 | /**
77 | * Make a hash of linked modules within the given directory by breadth-first search.
78 | * @param {string} directory A path to start searching
79 | * @returns {object} A collection of sym-linked paths within the project keyed by their package name
80 | */
81 | function indexLinkedModules(directory) {
82 | var buffer = listSymLinkedModules(directory),
83 | hash = {};
84 |
85 | // while there are items in the buffer
86 | while (buffer.length > 0) {
87 | var modulePath = buffer.shift(),
88 | packageJsonPath = path.join(modulePath, 'package.json'),
89 | packageName = fs.existsSync(packageJsonPath) && require(packageJsonPath).name;
90 | if (packageName) {
91 |
92 | // add this path keyed by package name, so long as it doesn't exist at a lower level
93 | hash[packageName] = hash[packageName] || modulePath;
94 |
95 | // detect nested module and push to the buffer (breadth-first)
96 | buffer.push.apply(buffer, listSymLinkedModules(modulePath));
97 | }
98 | }
99 | return hash;
100 |
101 | function listSymLinkedModules(directory) {
102 | var modulesPath = path.join(directory, 'node_modules'),
103 | hasNodeModules = fs.existsSync(modulesPath) && fs.statSync(modulesPath).isDirectory(),
104 | subdirectories = !!hasNodeModules && fs.readdirSync(modulesPath) || [];
105 |
106 | return subdirectories
107 | .map(joinDirectory)
108 | .filter(testIsSymLink);
109 |
110 | function joinDirectory(subdirectory) {
111 | return path.join(modulesPath, subdirectory);
112 | }
113 |
114 | function testIsSymLink(directory) {
115 | return fs.lstatSync(directory).isSymbolicLink(); // must use lstatSync not statSync
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/codec/utility/get-context-directory.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 |
5 | /**
6 | * Infer the compilation context directory from options.
7 | * Relative paths are resolved against process.cwd().
8 | * @this {{options: object}} A loader or compilation
9 | * @returns {string} process.cwd() where not defined else the output path string
10 | */
11 | function getContextDirectory() {
12 | /* jshint validthis:true */
13 | var context = this.options ? this.options.context : null;
14 | return !!context && path.resolve(context) || process.cwd();
15 | }
16 |
17 | module.exports = getContextDirectory;
18 |
--------------------------------------------------------------------------------
/codec/utility/get-output-directory.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path'),
4 | fs = require('fs');
5 |
6 | var getContextDirectory = require('./get-context-directory');
7 |
8 | /**
9 | * Infer the compilation output directory from options.
10 | * Relative paths are resolved against the compilation context (or process.cwd() where not specified).
11 | * @this {{options: object}} A loader or compilation
12 | * @returns {undefined|string} The output path string, where defined
13 | */
14 | function getOutputDirectory() {
15 | /* jshint validthis:true */
16 | var base = this.options && this.options.output ? this.options.output.directory : null,
17 | absBase = !!base && path.resolve(getContextDirectory.call(this), base),
18 | isValid = !!absBase && fs.existsSync(absBase) && fs.statSync(absBase).isDirectory();
19 | return isValid ? absBase : undefined;
20 | }
21 |
22 | module.exports = getOutputDirectory;
23 |
--------------------------------------------------------------------------------
/codec/webpack-bootstrap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Codec for webpack generated bootstrap code.
5 | * @type {{name:string, decode:function, abstract:boolean}}
6 | */
7 | module.exports = {
8 | name : 'webpackBootstrap',
9 | decode : decode,
10 | abstract: true
11 | };
12 |
13 | /**
14 | * Validate the given uri (abstract).
15 | * @this {{options: object}} A loader or compilation
16 | * @param {string} uri A source uri to decode
17 | * @returns {boolean|string} False where unmatched else True
18 | */
19 | function decode(uri) {
20 | return /^webpack\/bootstrap\s+\w{20}$/.test(uri);
21 | }
22 |
--------------------------------------------------------------------------------
/codec/webpack-protocol.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var projectRelative = require('./project-relative');
4 |
5 | /**
6 | * Codec for relative paths with respect to the context directory, preceded by a webpack:// protocol.
7 | * @type {{name:string, decode: function, encode: function, root: function}}
8 | */
9 | module.exports = {
10 | name : 'webpackProtocol',
11 | decode: decode,
12 | encode: encode,
13 | root : root
14 | };
15 |
16 | /**
17 | * Decode the given uri.
18 | * @this {{options: object}} A loader or compilation
19 | * @param {string} uri A source uri to decode
20 | * @returns {boolean|string} False where unmatched else the decoded path
21 | */
22 | function decode(uri) {
23 | /* jshint validthis:true */
24 | var analysis = /^webpack:\/{2}(.*)$/.exec(uri);
25 | return !!analysis && projectRelative.decode.call(this, analysis[1]);
26 | }
27 |
28 | /**
29 | * Encode the given file path.
30 | * @this {{options: object}} A loader or compilation
31 | * @param {string} absolute An absolute file path to encode
32 | * @returns {string} A uri
33 | */
34 | function encode(absolute) {
35 | /* jshint validthis:true */
36 | return 'webpack://' + projectRelative.encode.call(this, absolute);
37 | }
38 |
39 | /**
40 | * The source-map root where relevant.
41 | * @this {{options: object}} A loader or compilation
42 | * @returns {string|undefined} The source-map root applicable to any encoded uri
43 | */
44 | function root() {
45 | }
46 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License http://opensource.org/licenses/MIT
3 | * Author: Ben Holloway @bholloway
4 | */
5 | 'use strict';
6 |
7 | module.exports = Object.assign(require('./lib/loader'), {
8 | moduleFilenameTemplate: require('./lib/module-filename-template'),
9 | codec : require('./codec')
10 | });
--------------------------------------------------------------------------------
/lib/loader.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 |
5 | var loaderUtils = require('loader-utils');
6 |
7 | var process = require('./process');
8 |
9 | /**
10 | * Webpack loader that manipulates the source-map of a preceding loader.
11 | * @this {object} The loader context
12 | * @param {string} content The content
13 | * @param {object} sourceMap The source-map
14 | * @returns {string|String}
15 | */
16 | function loader(content, sourceMap) {
17 | /* jshint validthis:true */
18 |
19 | // loader result is cacheable
20 | this.cacheable();
21 |
22 | // webpack 1: prefer loader query, else options object
23 | // webpack 2: prefer loader options
24 | // webpack 3: deprecate loader.options object
25 | // webpack 4: loader.options no longer defined
26 | var options = Object.assign(
27 | {},
28 | this.options && this.options.adjustSourcemapLoader,
29 | loaderUtils.getOptions(this),
30 | {sep: path.sep}
31 | );
32 |
33 | // process the source-map
34 | var outputMap = process(this, options, sourceMap);
35 |
36 | // need to use callback when there are multiple arguments
37 | this.callback(null, content, outputMap);
38 | }
39 |
40 | module.exports = loader;
41 |
--------------------------------------------------------------------------------
/lib/module-filename-template.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var process = require('./process');
4 |
5 | function moduleFilenameTemplate(options) {
6 | return function templateFn(parameters) {
7 | return process(parameters, options, parameters.resourcePath);
8 | };
9 | }
10 |
11 | module.exports = moduleFilenameTemplate;
--------------------------------------------------------------------------------
/lib/process/debug-message.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var PACKAGE_NAME = require('../../package.json').name,
4 | PADDING = (new Array(11)).join(' ');
5 |
6 | /**
7 | * Format a debug message
8 | * @param {{resourcePath:string, loaders:Array, loaderIndex:number}} context A loader or compilation
9 | * @param {{input:Array., absolute:Array., output:Array., root:string}} info Source-map info
10 | * @returns {string} An encoded debug string
11 | */
12 | function debugMessage(context, info) {
13 | return [
14 | ' ',
15 | PACKAGE_NAME + ':',
16 | ' ' + context.resourcePath,
17 | formatField('@', precedingRequest(context)),
18 | formatField('INPUT', info.input || '(source-map absent)'),
19 | formatField('ABSOLUTE', info.absolute),
20 | formatField('OUTPUT', info.output),
21 | formatField('ROOT', info.root)
22 | ]
23 | .filter(Boolean)
24 | .join('\n');
25 | }
26 |
27 | module.exports = debugMessage;
28 |
29 | /**
30 | * Find the request that precedes this loader in the loader chain
31 | * @param {{loaders:Array, loaderIndex:number}} loader The loader context
32 | * @returns {string} The request of the preceding loader
33 | */
34 | function precedingRequest(loader) {
35 | var isLoader = ('loaderIndex' in loader) && ('loaders' in loader) && Array.isArray(loader.loaders);
36 | if (isLoader) {
37 | var index = loader.loaderIndex + 1;
38 | return (index in loader.loaders) ? loader.loaders[index].request : '(no preceding loader)';
39 | }
40 | }
41 |
42 | /**
43 | * Where the data is truthy then format it with a right-aligned title.
44 | * @param {string} title
45 | * @param {*} data The data to display
46 | * @returns {boolean|string} False where data is falsey, else formatted message
47 | */
48 | function formatField(title, data) {
49 | return !!data && (rightAlign(title) + formatData(data));
50 |
51 | function rightAlign(text) {
52 | return (PADDING + text + ' ').slice(-PADDING.length);
53 | }
54 |
55 | function formatData(data) {
56 | return Array.isArray(data) ? data.join('\n' + PADDING) : data;
57 | }
58 | }
--------------------------------------------------------------------------------
/lib/process/decode-sources-with.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var getFieldAsFn = require('./get-field-as-fn');
4 |
5 | /**
6 | * Create a decoder for input sources using the given codec hash
7 | * @this {object} A loader or compilation
8 | * @param {Array.