apidocCreate = function (opt) {
/*
* this function will create the apidoc from <opt>.dir
*/
let elemCreate;
let module;
let moduleMain;
let readExample;
let tmp;
let toString;
let trimStart;
elemCreate = function (module, prefix, key) {
/*
* this function will create the apidoc-elem in given <module>
*/
let elem;
if (opt.modeNoApidoc) {
return elem;
}
elem = {};
elem.moduleName = prefix.split(".");
// handle case where module is a function
if (elem.moduleName.slice(-1)[0] === key) {
elem.moduleName.pop();
}
elem.moduleName = elem.moduleName.join(".");
elem.id = encodeURIComponent("apidoc.elem." + prefix + "." + key);
elem.typeof = typeof module[key];
elem.name = (
elem.typeof + " <span class=\"apidocSignatureSpan\">"
+ elem.moduleName + ".</span>" + key
);
// handle case where module is a function
elem.name = elem.name.replace(">.<", "><");
if (elem.typeof !== "function") {
return elem;
}
// init source
elem.source = local.stringHtmlSafe(
trimStart(toString(module[key])) || "n/a"
).replace((
/\([\S\s]*?\)/
), function (match0) {
// init signature
elem.signature = match0.replace((
/\u0020*?\/\*[\S\s]*?\*\/\u0020*/g
), "").replace((
/,/g
), ", ").replace((
/\s+/g
), " ");
return elem.signature;
}).replace((
/(\u0020*?\/\*[\S\s]*?\*\/\n)/
), "<span class=\"apidocCodeCommentSpan\">$1</span>").replace((
/^function\u0020\(/
), key + " = function (");
// init example
opt.exampleList.some(function (example) {
example.replace(
new RegExp("((?:\n.*?){8}\\.)(" + key + ")(\\((?:.*?\n){8})"),
function (ignore, match1, match2, match3) {
elem.example = "..." + trimStart(
local.stringHtmlSafe(match1)
+ "<span class=\"apidocCodeKeywordSpan\">"
+ local.stringHtmlSafe(match2)
+ "</span>"
+ local.stringHtmlSafe(match3)
).trimEnd() + "\n...";
return "";
}
);
return elem.example;
});
elem.example = elem.example || "n/a";
return elem;
};
readExample = function (file) {
/*
* this function will read the example from given file
*/
let result;
local.tryCatchOnError(function () {
file = local.path.resolve(opt.dir, file);
console.error("apidocCreate - readExample " + file);
result = "";
result = local.identity(
"\n\n\n\n\n\n\n\n"
// bug-workaround - truncate example to manageable size
+ local.fs.readFileSync(file, "utf8").slice(0, 262144)
+ "\n\n\n\n\n\n\n\n"
).replace((
/\r\n*/g
), "\n");
}, console.error);
return result;
};
toString = function (value) {
/*
* this function will try to return the string form of the value
*/
let result;
local.tryCatchOnError(function () {
result = "";
result = String(value);
}, console.error);
return result;
};
trimStart = function (str) {
/*...
...
local.cliDict._default = function () {
/*
* <moduleDirectory>
* will create apidoc from <moduleDirectory>
*/
// jslint files
process.stdout.write(local.apidocCreate({
dir: process.argv[2],
modulePathList: module.paths
}));
};
// run the cli
if (module === require.main && !globalThis.utility2_rollup) {
...
apidocModuleDictAdd = function (opt, moduleDict) {
/*
* this function will add the modules in <moduleDict> to <opt>.moduleDict
*/
let isModule;
let objectKeys;
let tmp;
objectKeys = function (dict) {
/*
* this function will return a list of the dict's keys, with valid getters
*/
return Object.keys(dict).sort().filter(function (key) {
return local.tryCatchOnError(function () {
return dict[key] || true;
}, local.nop);
});
};
[
"child", "prototype", "grandchild", "prototype"
].forEach(function (elem) {
objectKeys(moduleDict).forEach(function (prefix) {
if (!(
/^\w[\w\-.]*?$/
).test(prefix)) {
return;
}
objectKeys(moduleDict[prefix]).forEach(function (key) {
if (!(
/^\w[\w\-.]*?$/
).test(key) || !moduleDict[prefix][key]) {
return;
}
tmp = (
elem === "prototype"
? {
module: moduleDict[prefix][key].prototype,
name: prefix + "." + key + ".prototype"
}
: {
module: moduleDict[prefix][key],
name: prefix + "." + key
}
);
if (
!tmp.module
|| !(
typeof tmp.module === "function"
|| typeof tmp.module === "object"
)
|| Array.isArray(tmp.module)
|| opt.moduleDict[tmp.name]
|| opt.circularSet.has(tmp.module)
) {
return;
}
isModule = Array.from([
tmp.module,
tmp.module.prototype
]).some(function (dict) {
return objectKeys(dict || {}).some(function (key) {
return typeof dict[key] === "function";
});
});
if (!isModule) {
return;
}
opt.circularSet.add(tmp.module);
opt.moduleDict[tmp.name] = tmp.module;
});
});
});
}
...
opt.circularSet.add(opt.moduleDict[key]);
});
// init circularSet - prototype
opt.circularSet.forEach(function (elem) {
opt.circularSet.add(elem && elem.prototype);
});
// init moduleDict child
local.apidocModuleDictAdd(opt, opt.moduleDict);
// init swgg.apiDict
Object.keys(
(moduleMain.swgg && moduleMain.swgg.apiDict) || {}
).forEach(function (key) {
tmp = "swgg.apiDict";
opt.moduleDict[tmp] = opt.moduleDict[tmp] || {};
tmp = opt.moduleDict[tmp];
...
assertOrThrow = function (passed, msg) {
/*
* this function will throw err.<msg> if <passed> is falsy
*/
if (passed) {
return;
}
throw (
(
msg
&& typeof msg.message === "string"
&& typeof msg.stack === "string"
)
// if msg is err, then leave as is
? msg
: new Error(
typeof msg === "string"
// if msg is a string, then leave as is
? msg
// else JSON.stringify msg
: JSON.stringify(msg, undefined, 4)
)
);
}
...
argList: local.coalesce(commandList[ii][1], "").trim(),
command: [
key
],
description: commandList[ii][2]
};
} catch (ignore) {
local.assertOrThrow(undefined, new Error(
"cliRun - cannot parse comment in COMMAND "
+ key
+ ":\nnew RegExp("
+ JSON.stringify(opt.rgxComment.source)
+ ").exec(" + JSON.stringify(str).replace((
/\\\\/g
), "\u0000").replace((
...
cliRun = function (opt) {
/*
* this function will run cli with given <opt>
*/
local.cliDict._eval = local.cliDict._eval || function () {
/*
* <code>
* will eval <code>
*/
globalThis.local = local;
local.vm.runInThisContext(process.argv[3]);
};
local.cliDict._help = local.cliDict._help || function () {
/*
*
* will print help
*/
let commandList;
let file;
let packageJson;
let str;
let strDict;
commandList = [
{
argList: "<arg2> ...",
description: "usage:",
command: [
"<arg1>"
]
}, {
argList: "'console.log(\"hello world\")'",
description: "example:",
command: [
"--eval"
]
}
];
file = __filename.replace((
/.*\//
), "");
opt = Object.assign({}, opt);
packageJson = require("./package.json");
// validate comment
opt.rgxComment = opt.rgxComment || (
/\)\u0020\{\n(?:|\u0020{4})\/\*\n(?:\u0020|\u0020{5})\*((?:\u0020<[^>]*?>|\u0020\.\.\.)*?)\n(?:\u0020|\u0020{5})\*\u0020
(will\u0020.*?\S)\n(?:\u0020|\u0020{5})\*\/\n(?:\u0020{4}|\u0020{8})\S/
);
strDict = {};
Object.keys(local.cliDict).sort().forEach(function (key, ii) {
if (key[0] === "_" && key !== "_default") {
return;
}
str = String(local.cliDict[key]);
if (key === "_default") {
key = "";
}
strDict[str] = strDict[str] || (ii + 2);
ii = strDict[str];
if (commandList[ii]) {
commandList[ii].command.push(key);
return;
}
try {
commandList[ii] = opt.rgxComment.exec(str);
commandList[ii] = {
argList: local.coalesce(commandList[ii][1], "").trim(),
command: [
key
],
description: commandList[ii][2]
};
} catch (ignore) {
local.assertOrThrow(undefined, new Error(
"cliRun - cannot parse comment in COMMAND "
+ key
+ ":\nnew RegExp("
+ JSON.stringify(opt.rgxComment.source)
+ ").exec(" + JSON.stringify(str).replace((
/\\\\/g
), "\u0000").replace((
/\\n/g
), "\\n\\\n").replace((
/\u0000/g
), "\\\\") + ");"
));
}
});
str = "";
str += packageJson.name + " (" + packageJson.version + ")\n\n";
str += commandList.filter(function (elem) {
return elem;
}).map(function (elem, ii) {
elem.command = elem.command.filter(function (elem) {
return elem;
});
switch (ii) {
case 0:
case 1:
elem.argList = [
elem.argList
];
break;
default:
elem.argList = elem.argList.split(" ");
elem.description = (
"# COMMAND "
+ (elem.command[0] || "<none>") + "\n# "
+ elem.description
);
}
return (
elem.description + "\n " + file
+ " &quo...
...
dir: process.argv[2],
modulePathList: module.paths
}));
};
// run the cli
if (module === require.main && !globalThis.utility2_rollup) {
local.cliRun();
}
}());
}());
...
coalesce = function (...argList) {
/*
* this function will coalesce null, undefined, or "" in <argList>
*/
let arg;
let ii;
ii = 0;
while (ii < argList.length) {
arg = argList[ii];
if (arg !== null && arg !== undefined && arg !== "") {
break;
}
ii += 1;
}
return arg;
}
...
if (commandList[ii]) {
commandList[ii].command.push(key);
return;
}
try {
commandList[ii] = opt.rgxComment.exec(str);
commandList[ii] = {
argList: local.coalesce(commandList[ii][1], "").trim(),
command: [
key
],
description: commandList[ii][2]
};
} catch (ignore) {
local.assertOrThrow(undefined, new Error(
...
fsRmrfSync = function (dir) {
/*
* this function will sync "rm -rf" <dir>
*/
let child_process;
// do nothing if module does not exist
try {
child_process = require("child_process");
} catch (ignore) {
return;
}
child_process.spawnSync("rm", [
"-rf", dir
], {
stdio: [
"ignore", 1, 2
]
});
}
n/a
fsWriteFileWithMkdirpSync = function (file, data) {
/*
* this function will sync write <data> to <file> with "mkdir -p"
*/
let fs;
// do nothing if module does not exist
try {
fs = require("fs");
} catch (ignore) {
return;
}
// try to write file
try {
fs.writeFileSync(file, data);
} catch (ignore) {
// mkdir -p
require("child_process").spawnSync(
"mkdir",
[
"-p", require("path").dirname(file)
],
{
stdio: [
"ignore", 1, 2
]
}
);
// rewrite file
fs.writeFileSync(file, data);
}
}
n/a
functionOrNop = function (fnc) {
/*
* this function will if <fnc> exists,
* return <fnc>,
* else return <nop>
*/
return fnc || local.nop;
}
n/a
identity = function (val) {
/*
* this function will return <val>
*/
return val;
}
...
local.cliDict.help = local.cliDict.help || local.cliDict._help;
local.cliDict._interactive = local.cliDict._interactive || function () {
/*
*
* will start interactive-mode
*/
globalThis.local = local;
local.identity(local.replStart || require("repl").start)({
useGlobal: true
});
};
local.cliDict["--interactive"] = (
local.cliDict["--interactive"]
|| local.cliDict._interactive
);
...
moduleDirname = function (module, pathList) {
/*
* this function will search <pathList> for <module>'s __dirname
*/
let result;
// search process.cwd()
if (!module || module === "." || module.indexOf("/") >= 0) {
return require("path").resolve(process.cwd(), module || "");
}
// search pathList
Array.from([
pathList,
require("module").globalPaths,
[
process.env.HOME + "/node_modules", "/usr/local/lib/node_modules"
]
]).flat().some(function (path) {
try {
result = require("path").resolve(
process.cwd(),
path + "/" + module
);
result = require("fs").statSync(result).isDirectory() && result;
return result;
} catch (ignore) {
result = "";
}
});
return result;
}
...
return match0.replace((
/(.{128}(?:\b|\w+))/g
), "$1\n").trimEnd();
});
return str;
};
// init opt
opt.dir = local.moduleDirname(
opt.dir,
opt.modulePathList || require("module").paths
);
local.objectSetDefault(opt, {
env: {
npm_package_description: ""
},
...
nop = function () {
/*
* this function will do nothing
*/
return;
}
n/a
objectAssignDefault = function (target, source) {
/*
* this function will if items from <target> are null, undefined, or "",
* then overwrite them with items from <source>
*/
target = target || {};
Object.keys(source || {}).forEach(function (key) {
if (
target[key] === null
|| target[key] === undefined
|| target[key] === ""
) {
target[key] = target[key] || source[key];
}
});
return target;
}
n/a
objectSetDefault = function (dict, defaults, depth) {
/*
* this function will recursively set defaults for undefined-items in dict
*/
dict = dict || {};
defaults = defaults || {};
Object.keys(defaults).forEach(function (key) {
let defaults2;
let dict2;
dict2 = dict[key];
// handle misbehaving getter
try {
defaults2 = defaults[key];
} catch (ignore) {}
if (defaults2 === undefined) {
return;
}
// init dict[key] to default value defaults[key]
switch (dict2) {
case "":
case null:
case undefined:
dict[key] = defaults2;
return;
}
// if dict2 and defaults2 are both non-undefined and non-array objects,
// then recurse with dict2 and defaults2
if (
depth > 1
// dict2 is a non-undefined and non-array object
&& typeof dict2 === "object" && dict2 && !Array.isArray(dict2)
// defaults2 is a non-undefined and non-array object
&& typeof defaults2 === "object" && defaults2
&& !Array.isArray(defaults2)
) {
// recurse
local.objectSetDefault(dict2, defaults2, depth - 1);
}
});
return dict;
}
...
// dict2 is a non-undefined and non-array object
&& typeof dict2 === "object" && dict2 && !Array.isArray(dict2)
// defaults2 is a non-undefined and non-array object
&& typeof defaults2 === "object" && defaults2
&& !Array.isArray(defaults2)
) {
// recurse
local.objectSetDefault(dict2, defaults2, depth - 1);
}
});
return dict;
};
local.stringHtmlSafe = function (str) {
/*
...
querySelector = function (selectors) {
/*
* this function will return first dom-elem that match <selectors>
*/
return (
typeof document === "object" && document
&& typeof document.querySelector === "function"
&& document.querySelector(selectors)
) || {};
}
...
local.querySelector = function (selectors) {
/*
* this function will return first dom-elem that match <selectors>
*/
return (
typeof document === "object" && document
&& typeof document.querySelector === "function"
&& document.querySelector(selectors)
) || {};
};
local.querySelectorAll = function (selectors) {
/*
* this function will return dom-elem-list that match <selectors>
*/
return (
...
querySelectorAll = function (selectors) {
/*
* this function will return dom-elem-list that match <selectors>
*/
return (
typeof document === "object" && document
&& typeof document.querySelectorAll === "function"
&& Array.from(document.querySelectorAll(selectors))
) || [];
}
...
local.querySelectorAll = function (selectors) {
/*
* this function will return dom-elem-list that match <selectors>
*/
return (
typeof document === "object" && document
&& typeof document.querySelectorAll === "function"
&& Array.from(document.querySelectorAll(selectors))
) || [];
};
// require builtin
if (!local.isBrowser) {
local.assert = require("assert");
local.buffer = require("buffer");
local.child_process = require("child_process");
...
stringHtmlSafe = function (str) {
/*
* this function will make <str> html-safe
* https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-on-html
*/
return str.replace((
/&/gu
), "&").replace((
/"/gu
), """).replace((
/'/gu
), "'").replace((
/</gu
), "<").replace((
/>/gu
), ">").replace((
/&(amp;|apos;|gt;|lt;|quot;)/igu
), "&$1");
}
...
);
// handle case where module is a function
elem.name = elem.name.replace(">.<", "><");
if (elem.typeof !== "function") {
return elem;
}
// init source
elem.source = local.stringHtmlSafe(
trimStart(toString(module[key])) || "n/a"
).replace((
/\([\S\s]*?\)/
), function (match0) {
// init signature
elem.signature = match0.replace((
/\u0020*?\/\*[\S\s]*?\*\/\u0020*/g
...
templateRender = function (template, dict, opt, ii) {
/*
* this function will render <template> with given <dict>
*/
let argList;
let getVal;
let match;
let renderPartial;
let rgx;
let skip;
let val;
if (dict === null || dict === undefined) {
dict = {};
}
opt = opt || {};
getVal = function (key) {
argList = key.split(" ");
val = dict;
if (argList[0] === "#this/") {
return val;
}
if (argList[0] === "#ii/") {
return ii;
}
// iteratively lookup nested val in dict
argList[0].split(".").forEach(function (key) {
val = val && val[key];
});
return val;
};
renderPartial = function (match0, helper, key, partial) {
switch (helper) {
case "each":
case "eachTrimEndComma":
val = getVal(key);
val = (
Array.isArray(val)
? val.map(function (dict, ii) {
// recurse with partial
return local.templateRender(partial, dict, opt, ii);
}).join("")
: ""
);
// remove trailing-comma from last elem
if (helper === "eachTrimEndComma") {
val = val.trimEnd().replace((
/,$/
), "");
}
return val;
case "if":
partial = partial.split("{{#unless " + key + "}}");
partial = (
getVal(key)
? partial[0]
// handle 'unless' case
: partial.slice(1).join("{{#unless " + key + "}}")
);
// recurse with partial
return local.templateRender(partial, dict, opt);
case "unless":
return (
getVal(key)
? ""
// recurse with partial
: local.templateRender(partial, dict, opt)
);
default:
// recurse with partial
return match0[0] + local.templateRender(match0.slice(1), dict, opt);
}
};
// render partials
rgx = (
/\{\{#(\w+)\u0020([^}]+?)\}\}/g
);
template = template || "";
match = rgx.exec(template);
while (match) {
rgx.lastIndex += 1 - match[0].length;
template = template.replace(
new RegExp(
"\\{\\{#(" + match[1] + ") (" + match[2]
+ ")\\}\\}([\\S\\s]*?)\\{\\{/" + match[1] + " " + match[2]
+ "\\}\\}"
),
renderPartial
);
match = rgx.exec(template);
}
// search for keys in the template
return template.replace((
/\{\{[^}]+?\}\}/g
), function (match0) {
let markdownToHtml;
let notHtmlSafe;
notHtmlSafe = opt.notHtmlSafe;
try {
val = getVal(match0.slice(2, -2));
if (val === undefined) {
return match0;
}
argList.slice(1).forEach(function (fmt, ii, list) {
switch (fmt) {
case "*":
case "+":
case "-":
case "/":
skip = ii + 1;
val = String(
fmt === "*"
? Number(val) * Number(list[skip])
: fmt === "+"
? Number(val) + Number(list[skip])
: fmt === "-"
? Number(val) - Number(list[skip])
: Number(val) / Number(list[skip])
);
break;...
...
case "each":
case "eachTrimEndComma":
val = getVal(key);
val = (
Array.isArray(val)
? val.map(function (dict, ii) {
// recurse with partial
return local.templateRender(partial, dict, opt, ii);
}).join("")
: ""
);
// remove trailing-comma from last elem
if (helper === "eachTrimEndComma") {
val = val.trimEnd().replace((
/,$/
...
tryCatchOnError = function (fnc, onError) {
/*
* this function will run the fnc in a tryCatch block,
* else call onError with errCaught
*/
let result;
// validate onError
local.assertOrThrow(typeof onError === "function", typeof onError);
try {
// reset errCaught
local._debugTryCatchError = null;
result = fnc();
local._debugTryCatchError = null;
return result;
} catch (errCaught) {
// debug errCaught
local._debugTryCatchError = errCaught;
return onError(errCaught);
}
}
...
return elem;
};
readExample = function (file) {
/*
* this function will read the example from given file
*/
let result;
local.tryCatchOnError(function () {
file = local.path.resolve(opt.dir, file);
console.error("apidocCreate - readExample " + file);
result = "";
result = local.identity(
"\n\n\n\n\n\n\n\n"
// bug-workaround - truncate example to manageable size
+ local.fs.readFileSync(file, "utf8").slice(0, 262144)
...
_default = function () {
/*
* <moduleDirectory>
* will create apidoc from <moduleDirectory>
*/
// jslint files
process.stdout.write(local.apidocCreate({
dir: process.argv[2],
modulePathList: module.paths
}));
}
...
local.cliDict._help();
return;
}
if (local.cliDict[process.argv[2]]) {
local.cliDict[process.argv[2]]();
return;
}
local.cliDict._default();
};
local.moduleDirname = function (module, pathList) {
/*
* this function will search <pathList> for <module>'s __dirname
*/
let result;
...