mush-format
Version:
A javascript library that minifies pretty formatted mushcode.
126 lines (109 loc) • 3.33 kB
JavaScript
const { EventEmitter } = require("events");
const fileType = require("../plugins/core/fileType");
const openFile = require("../plugins/core/open");
const render = require("../plugins/core/render");
const compress = require("../plugins/core/compress");
const pkg = require("../package.json");
/** new MushFormatter() */
class MushFormatter extends EventEmitter {
constructor() {
super();
this.log = [];
this._stack = new Map();
this._stack.set("pre", []);
this._stack.set("open", []);
this._stack.set("render", []);
this._stack.set("compress", []);
this._stack.set("finishing", []);
}
/**
* Register middleware to be used during the formatting process.
* @param {String} step The portion of the formatting process
* where the middleware should fire.
* @param {*} middleware The function to be run against included
* data during a particular step.
*/
use(step, middleware) {
if (typeof middleware !== "function") {
throw new Error("Middleware must be a function.");
}
if (!step) {
throw new Error("Formatting step must be supplied.");
}
const stepValue = this._stack.get(step);
stepValue.push(middleware);
this._stack.set(step, stepValue);
}
/**
* Process data with middleware functions.
* @param {Object} [data = {}] Data passed to the middleware functions
*/
async process(step, data) {
let idx = 0;
const next = async (err, data) => {
if (err) return Promise.reject(err);
if (idx >= this._stack.get(step).length) return Promise.resolve(data);
const layer = this._stack.get(step)[idx++];
try {
data = await layer(data, next);
} catch (error) {
next(error);
}
};
await next(null, data);
}
/**
* Format text.
* @param {String} text The relative file path, url or text string to
* be formatted
*/
async format(text) {
// In the future I might turn this into it's own class.
let data = {
input: text,
type: "",
raw: "",
headers: [],
footers: [],
github: { user: "", repo: "" },
output: "",
cache: new Map(),
emit: (type, data) => this.emit(type, data),
logger: message => this.logger(message),
debug: false
};
// Install the core middleware.
this.use("pre", fileType);
this.use("open", openFile);
this.use("render", render);
this.use("compress", compress);
// I'm passing data around here. There's probably a more elegant
// way to do this.
this.log = [];
this.logger("Begin formatting");
await this.process("pre", data);
await this.process("open", data);
await this.process("render", data);
await this.process("compress", data);
data.log = this.log;
this.emit("done", {
text: data.output,
log: this.log
});
return {
version: this.version(),
text: data.output.trim()
};
}
/**
* Send the current version of the library
*/
version() {
return pkg.version;
}
logger(message) {
const date = new Date();
this.log.push(`[${date.toLocaleString()}] ${message}`);
}
}
module.exports = MushFormatter;