@npmstuff/argdown-core
Version:
A pluggable parser for the Argdown argumentation syntax
240 lines • 9.28 kB
JavaScript
import { ArgdownPluginError } from "./ArgdownPluginError";
"use strict";
import { ArgdownTreeWalker } from "./ArgdownTreeWalker";
import { Logger } from "./Logger";
import defaultsDeep from "lodash.defaultsdeep";
import { isString, isFunction, arrayIsEmpty } from "./utils";
export class ArgdownApplication {
constructor(logger) {
this.processors = {};
this.defaultLogger = new Logger();
this.defaultProcesses = {};
this.processors = {};
if (logger && isFunction(logger.log) && isFunction(logger.setLevel)) {
this.logger = logger;
}
else {
this.logger = this.defaultLogger;
this.logger.setLevel("error");
}
}
addPlugin(plugin, processorId) {
if (!processorId) {
processorId = "default";
}
let processor = this.processors[processorId];
if (!processor) {
processor = { plugins: [], walker: null };
this.processors[processorId] = processor;
}
processor.plugins.push(plugin);
if (plugin.tokenListeners || plugin.ruleListeners) {
if (!processor.walker) {
processor.walker = new ArgdownTreeWalker();
}
if (plugin.tokenListeners) {
for (let key of Object.keys(plugin.tokenListeners)) {
processor.walker.addListener(key, plugin.tokenListeners[key]);
}
}
if (plugin.ruleListeners) {
for (let key of Object.keys(plugin.ruleListeners)) {
processor.walker.addListener(key, plugin.ruleListeners[key]);
}
}
}
}
removePlugin(plugin, processorId) {
if (!processorId) {
processorId = "default";
}
let processor = this.processors[processorId];
if (!processor) {
throw new Error(`Could not find processor "${processorId}"`);
}
let index = processor.plugins.indexOf(plugin);
if (index > -1) {
if (plugin.tokenListeners && processor.walker) {
for (let key of Object.keys(plugin.tokenListeners)) {
processor.walker.removeListener(key, plugin.tokenListeners[key]);
}
}
if (plugin.ruleListeners && processor.walker) {
for (let key of Object.keys(plugin.ruleListeners)) {
processor.walker.removeListener(key, plugin.ruleListeners[key]);
}
}
processor.plugins.splice(index, 1);
}
else {
`Could not find plugin "${plugin.name}" in processor "${processorId}"`;
}
}
replacePlugin(oldPluginId, newPlugin, processorId) {
if (!processorId) {
processorId = "default";
}
let processor = this.processors[processorId];
if (!processor) {
throw new Error(`Could not find processor "${processorId}"`);
}
const oldPlugin = this.getPlugin(oldPluginId, processorId);
if (!oldPlugin) {
throw new Error(`Could not find plugin "${oldPluginId}" in processor "${processorId}"`);
}
const plugins = [...processor.plugins];
const pluginIndex = plugins.indexOf(oldPlugin);
plugins[pluginIndex] = newPlugin;
this.removeProcessor(processorId);
for (let plugin of plugins) {
this.addPlugin(plugin, processorId);
}
}
getPlugins(processorId) {
if (!processorId) {
processorId = "default";
}
let processor = this.processors[processorId];
if (processor)
return processor.plugins;
else {
return null;
}
}
getPlugin(name, processorId) {
let plugins = this.getPlugins(processorId);
if (plugins) {
for (let plugin of plugins) {
if (plugin.name == name) {
return plugin;
}
}
}
return null;
}
removeProcessor(processorId) {
let processor = this.processors[processorId];
if (!processor) {
throw new Error(`Could not find processor "${processorId}"`);
}
for (let plugin of processor.plugins) {
this.removePlugin(plugin, processorId);
}
delete this.processors[processorId];
}
run(request, response) {
let processorsToRun = [];
this.logger.setLevel("error");
let resp = response || {};
let req = request;
if (req) {
if (req.logLevel) {
this.logger.setLevel(req.logLevel);
}
if (req.process) {
if (Array.isArray(req.process)) {
processorsToRun = req.process;
}
else if (isString(req.process) &&
req.processes &&
req.processes[req.process]) {
const processObj = req.processes[req.process];
req = defaultsDeep(req, processObj);
if (isString(processObj.process)) {
processorsToRun = this.defaultProcesses[processObj.process];
}
else if (req.process && req.process.constructor === Array) {
processorsToRun = req.process;
}
}
else if (isString(req.process)) {
processorsToRun = this.defaultProcesses[req.process];
}
}
}
if (arrayIsEmpty(processorsToRun)) {
this.logger.log("error", "[ArgdownApplication]: No processors to run.");
return resp;
}
const exceptions = [];
resp.exceptions = exceptions;
for (let processorId of processorsToRun) {
let cancelProcessor = false;
let processor = this.processors[processorId];
if (!processor) {
this.logger.log("error", "[ArgdownApplication]: Processor not found: " + processorId);
continue;
}
this.logger.log("verbose", "[ArgdownApplication]: Running processor: " + processorId);
for (let plugin of processor.plugins) {
if (isFunction(plugin.prepare)) {
this.logger.log("verbose", "[ArgdownApplication]: Preparing plugin: " + plugin.name);
try {
plugin.prepare(req, resp, this.logger);
}
catch (e) {
if (req.throwExceptions) {
throw e;
}
else if (e instanceof ArgdownPluginError) {
e.processor = processorId;
exceptions.push(e);
cancelProcessor = true;
this.logger.log("warning", `[ArgdownApplication]: Processor ${processorId} canceled.`);
break;
}
}
}
}
if (cancelProcessor) {
break;
}
if (resp.ast && processor.walker) {
try {
processor.walker.walk(req, resp, this.logger);
}
catch (e) {
if (req.throwExceptions) {
throw e;
}
else if (e instanceof ArgdownPluginError) {
e.processor = processorId;
exceptions.push(e);
this.logger.log("warning", `[ArgdownApplication]: Processor ${processorId} canceled.`);
break;
}
}
}
for (let plugin of processor.plugins) {
this.logger.log("verbose", "[ArgdownApplication]: Running plugin: " + plugin.name);
if (isFunction(plugin.run)) {
try {
plugin.run(req, resp, this.logger);
}
catch (e) {
if (req.throwExceptions) {
throw e;
}
else if (e instanceof ArgdownPluginError) {
e.processor = processorId;
this.logger.log("warning", `Processor ${processorId} canceled.`);
exceptions.push(e);
break;
}
}
}
}
}
if (req.logExceptions === undefined || req.logExceptions) {
for (let exception of exceptions) {
let msg = exception.stack || exception.message;
if (exception instanceof ArgdownPluginError) {
msg = `[${exception.processor}/${exception.plugin}]: ${msg}`;
}
this.logger.log("error", msg);
}
}
return resp;
}
}
//# sourceMappingURL=ArgdownApplication.js.map