source: frontend/node_modules/pirates/lib/index.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.5 KB
RevLine 
[9af201e]1'use strict';
2
3/* (c) 2015 Ari Porad (@ariporad) <http://ariporad.com>. License: ariporad.mit-license.org */
4const BuiltinModule = require('module');
5const path = require('path');
6
7const nodeModulesRegex = /^(?:.*[\\/])?node_modules(?:[\\/].*)?$/;
8// Guard against poorly-mocked module constructors.
9const Module =
10 module.constructor.length > 1 ? module.constructor : BuiltinModule;
11
12const HOOK_RETURNED_NOTHING_ERROR_MESSAGE =
13 '[Pirates] A hook returned a non-string, or nothing at all! This is a' +
14 ' violation of intergalactic law!\n' +
15 '--------------------\n' +
16 'If you have no idea what this means or what Pirates is, let me explain: ' +
17 'Pirates is a module that makes it easy to implement require hooks. One of' +
18 " the require hooks you're using uses it. One of these require hooks" +
19 " didn't return anything from it's handler, so we don't know what to" +
20 ' do. You might want to debug this.';
21
22/**
23 * @param {string} filename The filename to check.
24 * @param {string[]} exts The extensions to hook. Should start with '.' (ex. ['.js']).
25 * @param {Matcher|null} matcher A matcher function, will be called with path to a file. Should return truthy if the file should be hooked, falsy otherwise.
26 * @param {boolean} ignoreNodeModules Auto-ignore node_modules. Independent of any matcher.
27 */
28function shouldCompile(filename, exts, matcher, ignoreNodeModules) {
29 if (typeof filename !== 'string') {
30 return false;
31 }
32 if (exts.indexOf(path.extname(filename)) === -1) {
33 return false;
34 }
35
36 const resolvedFilename = path.resolve(filename);
37
38 if (ignoreNodeModules && nodeModulesRegex.test(resolvedFilename)) {
39 return false;
40 }
41 if (matcher && typeof matcher === 'function') {
42 return !!matcher(resolvedFilename);
43 }
44
45 return true;
46}
47
48/**
49 * @callback Hook The hook. Accepts the code of the module and the filename.
50 * @param {string} code
51 * @param {string} filename
52 * @returns {string}
53 */
54/**
55 * @callback Matcher A matcher function, will be called with path to a file.
56 *
57 * Should return truthy if the file should be hooked, falsy otherwise.
58 * @param {string} path
59 * @returns {boolean}
60 */
61/**
62 * @callback RevertFunction Reverts the hook when called.
63 * @returns {void}
64 */
65/**
66 * @typedef {object} Options
67 * @property {Matcher|null} [matcher=null] A matcher function, will be called with path to a file.
68 *
69 * Should return truthy if the file should be hooked, falsy otherwise.
70 *
71 * @property {string[]} [extensions=['.js']] The extensions to hook. Should start with '.' (ex. ['.js']).
72 * @property {string[]} [exts=['.js']] The extensions to hook. Should start with '.' (ex. ['.js']).
73 *
74 * @property {string[]} [extension=['.js']] The extensions to hook. Should start with '.' (ex. ['.js']).
75 * @property {string[]} [ext=['.js']] The extensions to hook. Should start with '.' (ex. ['.js']).
76 *
77 * @property {boolean} [ignoreNodeModules=true] Auto-ignore node_modules. Independent of any matcher.
78 */
79
80/**
81 * Add a require hook.
82 *
83 * @param {Hook} hook The hook. Accepts the code of the module and the filename. Required.
84 * @param {Options} [opts] Options
85 * @returns {RevertFunction} The `revert` function. Reverts the hook when called.
86 */
87function addHook(hook, opts = {}) {
88 let reverted = false;
89 const loaders = [];
90 const oldLoaders = [];
91 let exts;
92
93 // We need to do this to fix #15. Basically, if you use a non-standard extension (ie. .jsx), then
94 // We modify the .js loader, then use the modified .js loader for as the base for .jsx.
95 // This prevents that.
96 const originalJSLoader = Module._extensions['.js'];
97
98 const matcher = opts.matcher || null;
99 const ignoreNodeModules = opts.ignoreNodeModules !== false;
100 exts = opts.extensions || opts.exts || opts.extension || opts.ext || ['.js'];
101 if (!Array.isArray(exts)) {
102 exts = [exts];
103 }
104
105 exts.forEach((ext) => {
106 if (typeof ext !== 'string') {
107 throw new TypeError(`Invalid Extension: ${ext}`);
108 }
109 const oldLoader = Module._extensions[ext] || originalJSLoader;
110 oldLoaders[ext] = Module._extensions[ext];
111
112 loaders[ext] = Module._extensions[ext] = function newLoader(mod, filename) {
113 let compile;
114 if (!reverted) {
115 if (shouldCompile(filename, exts, matcher, ignoreNodeModules)) {
116 compile = mod._compile;
117 mod._compile = function _compile(code) {
118 // reset the compile immediately as otherwise we end up having the
119 // compile function being changed even though this loader might be reverted
120 // Not reverting it here leads to long useless compile chains when doing
121 // addHook -> revert -> addHook -> revert -> ...
122 // The compile function is also anyway created new when the loader is called a second time.
123 mod._compile = compile;
124 const newCode = hook(code, filename);
125 if (typeof newCode !== 'string') {
126 throw new Error(HOOK_RETURNED_NOTHING_ERROR_MESSAGE);
127 }
128
129 return mod._compile(newCode, filename);
130 };
131 }
132 }
133
134 oldLoader(mod, filename);
135 };
136 });
137 return function revert() {
138 if (reverted) return;
139 reverted = true;
140
141 exts.forEach((ext) => {
142 // if the current loader for the extension is our loader then unregister it and set the oldLoader again
143 // if not we cannot do anything as we cannot remove a loader from within the loader-chain
144 if (Module._extensions[ext] === loaders[ext]) {
145 if (!oldLoaders[ext]) {
146 delete Module._extensions[ext];
147 } else {
148 Module._extensions[ext] = oldLoaders[ext];
149 }
150 }
151 });
152 };
153}
154
155exports.addHook = addHook;
Note: See TracBrowser for help on using the repository browser.