Files
op-packages/luci-app-homeproxy-pro/tests/lib/luci-module.js
T

52 lines
1.8 KiB
JavaScript

/*
* SPDX-License-Identifier: GPL-2.0-only
*
* Load a LuCI frontend module outside LuCI.
*
* `'require x as y';` is LuCI's own directive, not JavaScript, so it is
* rewritten into a dependency lookup before the file is evaluated. The
* snapshot renderer and the frontend invariant tests all need this, and there
* is no reason for them to each carry their own copy - the snapshot script had
* one, and the first invariant test copy-pasted it.
*
* `runtime` supplies the `_` / `E` / `L` globals the module expects; the
* defaults are inert, which is enough for the tests that only read the
* module's data (a table, a validator) rather than render it.
*/
'use strict';
const fs = require('fs');
function loadLuciModule(file, deps, runtime) {
let src = fs.readFileSync(file, 'utf8');
src = src.replace(/^'require ([^']+) as (\w+)';$/gm,
(_m, mod, alias) => `const ${alias} = __deps[${JSON.stringify(mod)}];`);
src = src.replace(/^'require ([^']+)';$/gm,
(_m, mod) => `const ${mod.split('.').pop().replace(/[^\w]/g, '_')} = __deps[${JSON.stringify(mod)}];`);
runtime = runtime || {};
const E = runtime.E || (() => null);
const L = runtime.L || {};
/* LuCI's `_()` returns a String object carrying a `format()` method, and
* the form code uses both halves (`_('Expecting: %s').format(x)`). A
* plain-string stand-in throws on the second half, so the default has to
* be a String object too. */
const _ = runtime._ || ((s) => {
const out = new String(s);
out.format = function(...args) {
let i = 0;
return String(this).replace(/%[sdj%]/g, (m) =>
m === '%%' ? '%' : (i < args.length ? String(args[i++]) : m));
};
return out;
});
/* eslint-disable-next-line no-new-func */
const factory = new Function('__deps', '_', 'E', 'L', src);
return factory(deps, _, E, L);
}
module.exports = { loadLuciModule };