/**
* Module helpers.
* @module @lumjs/core/modules
*/
const path = require('path');
const {S,isObj} = require('./types');
const replace = require('./strings').replaceItems;
/**
* Get the name of a module.
*
* @param {(object|string)} module - Either a module object, or filename.
* If it is an `object`, it should be a CommonJS `module` object.
* If it is a `string`, it should be the module filename.
* @param {object} [opts] Options.
*
* @param {boolean} [opts.useAuto=true] Enable automatic name cleaning.
* If *basename* mode was **not** used, then once all other rules have been
* applied, strip any leading `.` and `/` characters, and the file extension.
*
* @param {boolean} [opts.basename=false] Use `path.basename()`
* This will strip all parent directories, and the file extension.
* If no other rules are specified in the `opts`, then this will
* be applied automatically as a fallback method. If it is set to
* `true` explicitly, then it will be applied *before* any other options.
*
* @param {object} [opts.replace] Call {@link module:@lumjs/core/strings.replaceItems}
* This uses the default `useAll` values based on the `object` format.
* @param {object} [opts.replaceOne] `replace` but `useAll` set to `false`.
* @param {object} [opts.replaceAll] `replace` but `useAll` set to `true`.
* @param {(string|string[])} [opts.strip] Sub-strings to remove entirely.
* @returns {string} The *name* of a module as per the options set.
* @alias module:@lumjs/core/modules.name
*/
function name(module, opts={})
{
let filename;
if (typeof module === S)
{ // Going to assume a string is the filename.
filename = module;
}
else if (isObj(module) && typeof module.filename === S)
{ // It's a CommonJS module context object.
filename = module.filename;
}
else
{ // Sorry, we don't support that.
throw new TypeError("Unsupported module parameter");
}
const ext = path.extname(filename);
let useFallback = true;
let useAuto = opts.useAuto ?? true;
if (opts.basename)
{ // We want to run the basename sequence first.
filename = path.basename(filename, ext);
useFallback = false;
useAuto = false;
}
if (isObj(opts.replace))
{ // Replacements using replace() or replaceAll() based on parameter format.
useFallback = false;
filename = replace(filename, opts.replace);
}
if (isObj(opts.replaceOne))
{ // Replacements using replace() regardless of parameter format.
useFallback = false;
filename = replace(filename, opts.replaceOne, false);
}
if (isObj(opts.replaceAll))
{ // Replacements using replaceAll() regardless of parameter format.
useFallback = false;
filename = replace(filename, opts.replaceAll, true);
}
if (typeof opts.strip === S)
{ // A prefix. This always uses replace(), never replaceAll().
filename = filename.replace(opts.strip, '');
useFallback = false;
}
else if (Array.isArray(opts.strip))
{ // A list of strings or regexps to strip. Ditto on the use of replace().
for (const strip of opts.strip)
{
filename = filename.replace(strip, '');
}
useFallback = false;
}
if (useFallback)
{ // We're going to use the basename, either as a fallback
filename = path.basename(filename, ext);
useAuto = false;
}
if (useAuto)
{ // A few automatic rules that normally apply if the fallback was not used.
filename = filename
.replace(/^[./]+/, '')
.replace(RegExp(ext+'$'), '');
}
return filename;
}
exports.name = name;