skypager-project
Version:
skypager project framework
1,531 lines (1,319 loc) • 749 kB
JavaScript
try { require("source-map-support").install(); } catch(error) { }
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmory imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmory exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 85);
/******/ })
/************************************************************************/
/******/ ({
/***/ "../../node_modules/ansi-html-stream/colors.js":
/***/ function(module, exports) {
module.exports.inline = {
resets: { '0': false },
bold: { '1': { style: 'font-weight:bold' } },
underline: { '4': { style: 'text-decoration:underline' } },
foregrounds: {
'30': { style: 'color:#111' } // black
, '31': { style: 'color:#ff7e76' } // red
, '32': { style: 'color:#a4f87b' } // green
, '33': { style: 'color:#f6fcc0' } // yellow
, '34': { style: 'color:#9cd8fb' } // blue
, '35': { style: 'color:#ff85f6' } // magenta
, '36': { style: 'color:#cfd0f8' } // cyan
, '37': { style: 'color:#eee' } // white
, '39': false // default
},
backgrounds: {
'40': { style: 'background-color:#111' } // black
, '41': { style: 'background-color:#ff7e76' } // red
, '42': { style: 'background-color:#a4f87b' } // green
, '43': { style: 'background-color:#f6fcc0' } // yellow
, '44': { style: 'background-color:#9cd8fb' } // blue
, '45': { style: 'background-color:#ff85f6' } // magenta
, '46': { style: 'background-color:#cfd0f8' } // cyan
, '47': { style: 'background-color:#eee' } // white
, '49': false // default
}
};
module.exports.classes = {
resets: { '0': false },
bold: { '1': { 'class': 'ansi-bold' } },
underline: { '4': { 'class': 'ansi-underline' } },
foregrounds: {
'30': { 'class': 'ansi-fg-black' }
, '31': { 'class': 'ansi-fg-red' }
, '32': { 'class': 'ansi-fg-green' }
, '33': { 'class': 'ansi-fg-yellow' }
, '34': { 'class': 'ansi-fg-blue' }
, '35': { 'class': 'ansi-fg-magenta' }
, '36': { 'class': 'ansi-fg-cyan' }
, '37': { 'class': 'ansi-fg-white' }
, '39': false // default
},
backgrounds: {
'40': { 'class': 'ansi-bg-black' }
, '41': { 'class': 'ansi-bg-red' }
, '42': { 'class': 'ansi-bg-green' }
, '43': { 'class': 'ansi-bg-yellow' }
, '44': { 'class': 'ansi-bg-blue' }
, '45': { 'class': 'ansi-bg-magenta' }
, '46': { 'class': 'ansi-bg-cyan' }
, '47': { 'class': 'ansi-bg-white' }
, '49': false // default
}
};
/***/ },
/***/ "../../node_modules/ansi-html-stream/index.js":
/***/ function(module, exports, __webpack_require__) {
var escape = __webpack_require__(60)
, special = __webpack_require__("../../node_modules/special-html/index.js")
, map = __webpack_require__("../../node_modules/map-stream/index.js")
, clone = __webpack_require__(56)
, extend = __webpack_require__(83)
/**
* Returns a through-stream that converts ANSI escape
* code formatting to HTML.
*
* @param options {Object}
* @param options.classes {Boolean} If true, use classes instead of inline styles. Defaults to false.
* @param options.chunked {String} Wrap each chunk in <span class="options.chunked">
* @param options.theme {Object} Override existing styles - see lib/colors.js
*/
function createStream(options) {
var options = options || {}
, colors = __webpack_require__("../../node_modules/ansi-html-stream/colors.js")
, groupStack = [] // Keeps track of opened span types.
, spanStack = [] // Keeps track of opened span markup.
, chunked = options.chunked && escape(options.chunked) || false
, groups
, stream
colors = clone(colors[options.classes ? 'classes' : 'inline'])
colors = extend(colors, options.theme || {})
colors.resets = colors.resets || [{'0':false}]
groups = Object.keys(colors)
groups.forEach(function(group) {
Object.keys(colors[group]).forEach(function(key) {
var text = '<span'
, style = colors[group][key]
if (!style) return
Object.keys(style).forEach(function(attr) {
text += ' ' + attr + '="' + style[attr].replace(/\"/g, '') + '"'
})
text += '>'
colors[group][key] = text
})
})
stream = map(function write(string, next) {
if (chunked) {
string = spanStack.join('') + string
}
string = special(escape(string))
string = string
.replace(/\x1B\[([0-9;]*?\d)m/g, handleANSI) // Handle ANSI colour codes,
.replace(/\x1B\[(?:[0-9;]*?\d)[a-zA-Z]/g, '') // and remove other
.replace(/\x1B\[(?:[suK]|2J|\=\d\d?[h|])/g, '') // ANSI codes
if (chunked) {
spanStack.forEach(function() {
string += '</span>'
})
}
return next(null, string)
})
stream.oldend = stream.end
stream.end = function end(data) {
if (data) this.write(data)
var string = ''
groupStack.forEach(function() {
string += '</span>'
})
this.emit('data', string)
return this.oldend()
};
function handleANSI(fragment, codes) {
var codes = codes.split(';')
, prefix = ''
, suffix = ''
codes.forEach(function(code) {
var group
, style
, stackIndex
for (group in colors) {
if ((style = colors[group][code]) !== undefined) break;
}
if (!style) {
stackIndex = group === 'resets' ? 0 : groupStack.indexOf(group)
spanStack.splice(stackIndex)
groupStack.splice(stackIndex).forEach(function() { prefix += '</span>' })
return
}
stackIndex = groupStack.indexOf(group)
if (stackIndex !== -1) {
spanStack.splice(stackIndex)
groupStack.splice(stackIndex).forEach(function() {
prefix += '</span>'
})
}
groupStack.push(group)
spanStack.push(style)
prefix += style
})
return prefix + suffix
};
return stream
};
module.exports = createStream
module.exports.createStream = module.exports
/***/ },
/***/ "../../node_modules/cli-spinner/index.js":
/***/ function(module, exports, __webpack_require__) {
var readline = __webpack_require__(75);
var defaultSpinnerString = 0;
var defaultSpinnerDelay = 60;
var Spinner = function(textToShow){
this.text = textToShow || '';
this.setSpinnerString(defaultSpinnerString);
this.setSpinnerDelay(defaultSpinnerDelay);
};
Spinner.spinners = [
'|/-\\',
'⠂-–—–-',
'◐◓◑◒',
'◴◷◶◵',
'◰◳◲◱',
'▖▘▝▗',
'■□▪▫',
'▌▀▐▄',
'▉▊▋▌▍▎▏▎▍▌▋▊▉',
'▁▃▄▅▆▇█▇▆▅▄▃',
'←↖↑↗→↘↓↙',
'┤┘┴└├┌┬┐',
'◢◣◤◥',
'.oO°Oo.',
'.oO@*',
'🌍🌎🌏',
'◡◡ ⊙⊙ ◠◠',
'☱☲☴',
'⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏',
'⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓',
'⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆',
'⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋',
'⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉⠁',
'⠈⠉⠋⠓⠒⠐⠐⠒⠖⠦⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈',
'⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈',
'⢄⢂⢁⡁⡈⡐⡠',
'⢹⢺⢼⣸⣇⡧⡗⡏',
'⣾⣽⣻⢿⡿⣟⣯⣷',
'⠁⠂⠄⡀⢀⠠⠐⠈',
'🌑🌒🌓🌔🌕🌝🌖🌗🌘🌚'
];
Spinner.setDefaultSpinnerString = function(value) {
defaultSpinnerString = value;
};
Spinner.setDefaultSpinnerDelay = function(value) {
defaultSpinnerDelay = value;
};
Spinner.prototype.start = function() {
var current = 0;
var self = this;
this.id = setInterval(function() {
var msg = self.text.indexOf('%s') > -1 ? self.text.replace('%s', self.chars[current]) : self.chars[current] + ' ' + self.text;
clearLine();
process.stdout.write(msg);
current = ++current % self.chars.length;
}, this.delay);
};
Spinner.prototype.isSpinning = function() {
return this.id !== undefined;
}
Spinner.prototype.setSpinnerDelay = function(n) {
this.delay = n;
};
Spinner.prototype.setSpinnerString = function(str) {
this.chars = mapToSpinner(str, this.spinners).split('');
};
Spinner.prototype.setSpinnerTitle = function(str) {
this.text = str;
}
Spinner.prototype.stop = function(clear) {
clearInterval(this.id);
this.id = undefined;
if (clear) {
clearLine();
}
};
// Helpers
function isInt(value) {
return (typeof value==='number' && (value%1)===0);
}
function mapToSpinner(value, spinners) {
// Not an integer, return as strng
if (!isInt(value)) {
return value + '';
}
// Check if index is within bounds
value = (value >= Spinner.spinners.length) ? 0 : value;
// If negative, count from the end
value = (value < 0) ? Spinner.spinners.length + value : value;
return Spinner.spinners[value];
}
function clearLine() {
readline.clearLine(process.stdout, 0);
readline.cursorTo(process.stdout, 0);
}
exports.Spinner = Spinner;
/***/ },
/***/ "../../node_modules/cli-table/lib/index.js":
/***/ function(module, exports, __webpack_require__) {
/**
* Module dependencies.
*/
var colors = __webpack_require__(58)
, utils = __webpack_require__("../../node_modules/cli-table/lib/utils.js")
, repeat = utils.repeat
, truncate = utils.truncate
, pad = utils.pad;
/**
* Table constructor
*
* @param {Object} options
* @api public
*/
function Table (options){
this.options = utils.options({
chars: {
'top': '─'
, 'top-mid': '┬'
, 'top-left': '┌'
, 'top-right': '┐'
, 'bottom': '─'
, 'bottom-mid': '┴'
, 'bottom-left': '└'
, 'bottom-right': '┘'
, 'left': '│'
, 'left-mid': '├'
, 'mid': '─'
, 'mid-mid': '┼'
, 'right': '│'
, 'right-mid': '┤'
, 'middle': '│'
}
, truncate: '…'
, colWidths: []
, colAligns: []
, style: {
'padding-left': 1
, 'padding-right': 1
, head: ['red']
, border: ['grey']
, compact : false
}
, head: []
}, options);
};
/**
* Inherit from Array.
*/
Table.prototype.__proto__ = Array.prototype;
/**
* Width getter
*
* @return {Number} width
* @api public
*/
Table.prototype.__defineGetter__('width', function (){
var str = this.toString().split("\n");
if (str.length) return str[0].length;
return 0;
});
/**
* Render to a string.
*
* @return {String} table representation
* @api public
*/
Table.prototype.render
Table.prototype.toString = function (){
var ret = ''
, options = this.options
, style = options.style
, head = options.head
, chars = options.chars
, truncater = options.truncate
, colWidths = options.colWidths || new Array(this.head.length)
, totalWidth = 0;
if (!head.length && !this.length) return '';
if (!colWidths.length){
var all_rows = this.slice(0);
if (head.length) { all_rows = all_rows.concat([head]) };
all_rows.forEach(function(cells){
// horizontal (arrays)
if (typeof cells === 'object' && cells.length) {
extractColumnWidths(cells);
// vertical (objects)
} else {
var header_cell = Object.keys(cells)[0]
, value_cell = cells[header_cell];
colWidths[0] = Math.max(colWidths[0] || 0, get_width(header_cell) || 0);
// cross (objects w/ array values)
if (typeof value_cell === 'object' && value_cell.length) {
extractColumnWidths(value_cell, 1);
} else {
colWidths[1] = Math.max(colWidths[1] || 0, get_width(value_cell) || 0);
}
}
});
};
totalWidth = (colWidths.length == 1 ? colWidths[0] : colWidths.reduce(
function (a, b){
return a + b
})) + colWidths.length + 1;
function extractColumnWidths(arr, offset) {
var offset = offset || 0;
arr.forEach(function(cell, i){
colWidths[i + offset] = Math.max(colWidths[i + offset] || 0, get_width(cell) || 0);
});
};
function get_width(obj) {
return typeof obj == 'object' && obj.width != undefined
? obj.width
: ((typeof obj == 'object' ? utils.strlen(obj.text) : utils.strlen(obj)) + (style['padding-left'] || 0) + (style['padding-right'] || 0))
}
// draws a line
function line (line, left, right, intersection){
var width = 0
, line =
left
+ repeat(line, totalWidth - 2)
+ right;
colWidths.forEach(function (w, i){
if (i == colWidths.length - 1) return;
width += w + 1;
line = line.substr(0, width) + intersection + line.substr(width + 1);
});
return applyStyles(options.style.border, line);
};
// draws the top line
function lineTop (){
var l = line(chars.top
, chars['top-left'] || chars.top
, chars['top-right'] || chars.top
, chars['top-mid']);
if (l)
ret += l + "\n";
};
function generateRow (items, style) {
var cells = []
, max_height = 0;
// prepare vertical and cross table data
if (!Array.isArray(items) && typeof items === "object") {
var key = Object.keys(items)[0]
, value = items[key]
, first_cell_head = true;
if (Array.isArray(value)) {
items = value;
items.unshift(key);
} else {
items = [key, value];
}
}
// transform array of item strings into structure of cells
items.forEach(function (item, i) {
var contents = item.toString().split("\n").reduce(function (memo, l) {
memo.push(string(l, i));
return memo;
}, [])
var height = contents.length;
if (height > max_height) { max_height = height };
cells.push({ contents: contents , height: height });
});
// transform vertical cells into horizontal lines
var lines = new Array(max_height);
cells.forEach(function (cell, i) {
cell.contents.forEach(function (line, j) {
if (!lines[j]) { lines[j] = [] };
if (style || (first_cell_head && i === 0 && options.style.head)) {
line = applyStyles(options.style.head, line)
}
lines[j].push(line);
});
// populate empty lines in cell
for (var j = cell.height, l = max_height; j < l; j++) {
if (!lines[j]) { lines[j] = [] };
lines[j].push(string('', i));
}
});
var ret = "";
lines.forEach(function (line, index) {
if (ret.length > 0) {
ret += "\n" + applyStyles(options.style.border, chars.left);
}
ret += line.join(applyStyles(options.style.border, chars.middle)) + applyStyles(options.style.border, chars.right);
});
return applyStyles(options.style.border, chars.left) + ret;
};
function applyStyles(styles, subject) {
if (!subject)
return '';
styles.forEach(function(style) {
subject = colors[style](subject);
});
return subject;
};
// renders a string, by padding it or truncating it
function string (str, index){
var str = String(typeof str == 'object' && str.text ? str.text : str)
, length = utils.strlen(str)
, width = colWidths[index]
- (style['padding-left'] || 0)
- (style['padding-right'] || 0)
, align = options.colAligns[index] || 'left';
return repeat(' ', style['padding-left'] || 0)
+ (length == width ? str :
(length < width
? pad(str, ( width + (str.length - length) ), ' ', align == 'left' ? 'right' :
(align == 'middle' ? 'both' : 'left'))
: (truncater ? truncate(str, width, truncater) : str))
)
+ repeat(' ', style['padding-right'] || 0);
};
if (head.length){
lineTop();
ret += generateRow(head, style.head) + "\n"
}
if (this.length)
this.forEach(function (cells, i){
if (!head.length && i == 0)
lineTop();
else {
if (!style.compact || i<(!!head.length) ?1:0 || cells.length == 0){
var l = line(chars.mid
, chars['left-mid']
, chars['right-mid']
, chars['mid-mid']);
if (l)
ret += l + "\n"
}
}
if (cells.hasOwnProperty("length") && !cells.length) {
return
} else {
ret += generateRow(cells) + "\n";
};
});
var l = line(chars.bottom
, chars['bottom-left'] || chars.bottom
, chars['bottom-right'] || chars.bottom
, chars['bottom-mid']);
if (l)
ret += l;
else
// trim the last '\n' if we didn't add the bottom decoration
ret = ret.slice(0, -1);
return ret;
};
/**
* Module exports.
*/
module.exports = Table;
module.exports.version = '0.0.1';
/***/ },
/***/ "../../node_modules/cli-table/lib/utils.js":
/***/ function(module, exports) {
/**
* Repeats a string.
*
* @param {String} char(s)
* @param {Number} number of times
* @return {String} repeated string
*/
exports.repeat = function (str, times){
return Array(times + 1).join(str);
};
/**
* Pads a string
*
* @api public
*/
exports.pad = function (str, len, pad, dir) {
if (len + 1 >= str.length)
switch (dir){
case 'left':
str = Array(len + 1 - str.length).join(pad) + str;
break;
case 'both':
var right = Math.ceil((padlen = len - str.length) / 2);
var left = padlen - right;
str = Array(left + 1).join(pad) + str + Array(right + 1).join(pad);
break;
default:
str = str + Array(len + 1 - str.length).join(pad);
};
return str;
};
/**
* Truncates a string
*
* @api public
*/
exports.truncate = function (str, length, chr){
chr = chr || '…';
return str.length >= length ? str.substr(0, length - chr.length) + chr : str;
};
/**
* Copies and merges options with defaults.
*
* @param {Object} defaults
* @param {Object} supplied options
* @return {Object} new (merged) object
*/
function options(defaults, opts) {
for (var p in opts) {
if (opts[p] && opts[p].constructor && opts[p].constructor === Object) {
defaults[p] = defaults[p] || {};
options(defaults[p], opts[p]);
} else {
defaults[p] = opts[p];
}
}
return defaults;
};
exports.options = options;
//
// For consideration of terminal "color" programs like colors.js,
// which can add ANSI escape color codes to strings,
// we destyle the ANSI color escape codes for padding calculations.
//
// see: http://en.wikipedia.org/wiki/ANSI_escape_code
//
exports.strlen = function(str){
var code = /\u001b\[(?:\d*;){0,5}\d*m/g;
var stripped = ("" + str).replace(code,'');
var split = stripped.split("\n");
return split.reduce(function (memo, s) { return (s.length > memo) ? s.length : memo }, 0);
}
/***/ },
/***/ "../../node_modules/figlet/lib/figlet.js":
/***/ function(module, exports, __webpack_require__) {
"use strict";
/*
FIGlet.js (a FIGDriver for FIGlet fonts)
By Patrick Gillespie (patorjk@gmail.com)
Originally Written For: http://patorjk.com/software/taag/
License: MIT (with this header staying intact)
This JavaScript code aims to fully implement the FIGlet spec.
Full FIGlet spec: http://patorjk.com/software/taag/docs/figfont.txt
FIGlet fonts are actually kind of complex, which is why you will see
a lot of code about parsing and interpreting rules. The actual generation
code is pretty simple and is done near the bottom of the code.
*/
"use strict";
var figlet = figlet || (function() {
// ---------------------------------------------------------------------
// Private static variables
var FULL_WIDTH = 0,
FITTING = 1,
SMUSHING = 2,
CONTROLLED_SMUSHING = 3;
// ---------------------------------------------------------------------
// Variable that will hold information about the fonts
var figFonts = {}; // What stores all of the FIGlet font data
var figDefaults = {
font: 'Standard',
fontPath: './fonts'
};
// ---------------------------------------------------------------------
// Private static methods
/*
This method takes in the oldLayout and newLayout data from the FIGfont header file and returns
the layout information.
*/
function getSmushingRules(oldLayout, newLayout) {
var rules = {};
var val, index, len, code;
var codes = [[16384,"vLayout",SMUSHING], [8192,"vLayout",FITTING], [4096, "vRule5", true], [2048, "vRule4", true],
[1024, "vRule3", true], [512, "vRule2", true], [256, "vRule1", true], [128, "hLayout", SMUSHING],
[64, "hLayout", FITTING], [32, "hRule6", true], [16, "hRule5", true], [8, "hRule4", true], [4, "hRule3", true],
[2, "hRule2", true], [1, "hRule1", true]];
val = (newLayout !== null) ? newLayout : oldLayout;
index = 0;
len = codes.length;
while ( index < len ) {
code = codes[index];
if (val >= code[0]) {
val = val - code[0];
rules[code[1]] = (typeof rules[code[1]] === "undefined") ? code[2] : rules[code[1]];
} else if (code[1] !== "vLayout" && code[1] !== "hLayout") {
rules[code[1]] = false;
}
index++;
}
if (typeof rules["hLayout"] === "undefined") {
if (oldLayout === 0) {
rules["hLayout"] = FITTING;
} else if (oldLayout === -1) {
rules["hLayout"] = FULL_WIDTH;
} else {
if (rules["hRule1"] || rules["hRule2"] || rules["hRule3"] || rules["hRule4"] ||rules["hRule5"] || rules["hRule6"] ) {
rules["hLayout"] = CONTROLLED_SMUSHING;
} else {
rules["hLayout"] = SMUSHING;
}
}
} else if (rules["hLayout"] === SMUSHING) {
if (rules["hRule1"] || rules["hRule2"] || rules["hRule3"] || rules["hRule4"] ||rules["hRule5"] || rules["hRule6"] ) {
rules["hLayout"] = CONTROLLED_SMUSHING;
}
}
if (typeof rules["vLayout"] === "undefined") {
if (rules["vRule1"] || rules["vRule2"] || rules["vRule3"] || rules["vRule4"] ||rules["vRule5"] ) {
rules["vLayout"] = CONTROLLED_SMUSHING;
} else {
rules["vLayout"] = FULL_WIDTH;
}
} else if (rules["vLayout"] === SMUSHING) {
if (rules["vRule1"] || rules["vRule2"] || rules["vRule3"] || rules["vRule4"] ||rules["vRule5"] ) {
rules["vLayout"] = CONTROLLED_SMUSHING;
}
}
return rules;
}
/* The [vh]Rule[1-6]_Smush functions return the smushed character OR false if the two characters can't be smushed */
/*
Rule 1: EQUAL CHARACTER SMUSHING (code value 1)
Two sub-characters are smushed into a single sub-character
if they are the same. This rule does not smush
hardblanks. (See rule 6 on hardblanks below)
*/
function hRule1_Smush(ch1, ch2, hardBlank) {
if (ch1 === ch2 && ch1 !== hardBlank) {return ch1;}
return false;
}
/*
Rule 2: UNDERSCORE SMUSHING (code value 2)
An underscore ("_") will be replaced by any of: "|", "/",
"\", "[", "]", "{", "}", "(", ")", "<" or ">".
*/
function hRule2_Smush(ch1, ch2) {
var rule2Str = "|/\\[]{}()<>";
if (ch1 === "_") {
if (rule2Str.indexOf(ch2) !== -1) {return ch2;}
} else if (ch2 === "_") {
if (rule2Str.indexOf(ch1) !== -1) {return ch1;}
}
return false;
}
/*
Rule 3: HIERARCHY SMUSHING (code value 4)
A hierarchy of six classes is used: "|", "/\", "[]", "{}",
"()", and "<>". When two smushing sub-characters are
from different classes, the one from the latter class
will be used.
*/
function hRule3_Smush(ch1, ch2) {
var rule3Classes = "| /\\ [] {} () <>";
var r3_pos1 = rule3Classes.indexOf(ch1);
var r3_pos2 = rule3Classes.indexOf(ch2);
if (r3_pos1 !== -1 && r3_pos2 !== -1) {
if (r3_pos1 !== r3_pos2 && Math.abs(r3_pos1-r3_pos2) !== 1) {
return rule3Classes.substr(Math.max(r3_pos1,r3_pos2), 1);
}
}
return false;
}
/*
Rule 4: OPPOSITE PAIR SMUSHING (code value 8)
Smushes opposing brackets ("[]" or "]["), braces ("{}" or
"}{") and parentheses ("()" or ")(") together, replacing
any such pair with a vertical bar ("|").
*/
function hRule4_Smush(ch1, ch2) {
var rule4Str = "[] {} ()";
var r4_pos1 = rule4Str.indexOf(ch1);
var r4_pos2 = rule4Str.indexOf(ch2);
if (r4_pos1 !== -1 && r4_pos2 !== -1) {
if (Math.abs(r4_pos1-r4_pos2) <= 1) {
return "|";
}
}
return false;
}
/*
Rule 5: BIG X SMUSHING (code value 16)
Smushes "/\" into "|", "\/" into "Y", and "><" into "X".
Note that "<>" is not smushed in any way by this rule.
The name "BIG X" is historical; originally all three pairs
were smushed into "X".
*/
function hRule5_Smush(ch1, ch2) {
var rule5Str = "/\\ \\/ ><";
var rule5Hash = {"0": "|", "3": "Y", "6": "X"};
var r5_pos1 = rule5Str.indexOf(ch1);
var r5_pos2 = rule5Str.indexOf(ch2);
if (r5_pos1 !== -1 && r5_pos2 !== -1) {
if ((r5_pos2-r5_pos1) === 1) {
return rule5Hash[r5_pos1];
}
}
return false;
}
/*
Rule 6: HARDBLANK SMUSHING (code value 32)
Smushes two hardblanks together, replacing them with a
single hardblank. (See "Hardblanks" below.)
*/
function hRule6_Smush(ch1, ch2, hardBlank) {
if (ch1 === hardBlank && ch2 === hardBlank) {
return hardBlank;
}
return false;
}
/*
Rule 1: EQUAL CHARACTER SMUSHING (code value 256)
Same as horizontal smushing rule 1.
*/
function vRule1_Smush(ch1, ch2) {
if (ch1 === ch2) {return ch1;}
return false;
}
/*
Rule 2: UNDERSCORE SMUSHING (code value 512)
Same as horizontal smushing rule 2.
*/
function vRule2_Smush(ch1, ch2) {
var rule2Str = "|/\\[]{}()<>";
if (ch1 === "_") {
if (rule2Str.indexOf(ch2) !== -1) {return ch2;}
} else if (ch2 === "_") {
if (rule2Str.indexOf(ch1) !== -1) {return ch1;}
}
return false;
}
/*
Rule 3: HIERARCHY SMUSHING (code value 1024)
Same as horizontal smushing rule 3.
*/
function vRule3_Smush(ch1, ch2) {
var rule3Classes = "| /\\ [] {} () <>";
var r3_pos1 = rule3Classes.indexOf(ch1);
var r3_pos2 = rule3Classes.indexOf(ch2);
if (r3_pos1 !== -1 && r3_pos2 !== -1) {
if (r3_pos1 !== r3_pos2 && Math.abs(r3_pos1-r3_pos2) !== 1) {
return rule3Classes.substr(Math.max(r3_pos1,r3_pos2), 1);
}
}
return false;
}
/*
Rule 4: HORIZONTAL LINE SMUSHING (code value 2048)
Smushes stacked pairs of "-" and "_", replacing them with
a single "=" sub-character. It does not matter which is
found above the other. Note that vertical smushing rule 1
will smush IDENTICAL pairs of horizontal lines, while this
rule smushes horizontal lines consisting of DIFFERENT
sub-characters.
*/
function vRule4_Smush(ch1, ch2) {
if ( (ch1 === "-" && ch2 === "_") || (ch1 === "_" && ch2 === "-") ) {
return "=";
}
return false;
}
/*
Rule 5: VERTICAL LINE SUPERSMUSHING (code value 4096)
This one rule is different from all others, in that it
"supersmushes" vertical lines consisting of several
vertical bars ("|"). This creates the illusion that
FIGcharacters have slid vertically against each other.
Supersmushing continues until any sub-characters other
than "|" would have to be smushed. Supersmushing can
produce impressive results, but it is seldom possible,
since other sub-characters would usually have to be
considered for smushing as soon as any such stacked
vertical lines are encountered.
*/
function vRule5_Smush(ch1, ch2) {
if ( ch1 === "|" && ch2 === "|" ) {
return "|";
}
return false;
}
/*
Universal smushing simply overrides the sub-character from the
earlier FIGcharacter with the sub-character from the later
FIGcharacter. This produces an "overlapping" effect with some
FIGfonts, wherin the latter FIGcharacter may appear to be "in
front".
*/
function uni_Smush(ch1, ch2, hardBlank) {
if (ch2 === " " || ch2 === "") {
return ch1;
} else if (ch2 === hardBlank && ch1 !== " ") {
return ch1;
} else {
return ch2;
}
}
// --------------------------------------------------------------------------
// main vertical smush routines (excluding rules)
/*
txt1 - A line of text
txt2 - A line of text
opts - FIGlet options array
About: Takes in two lines of text and returns one of the following:
"valid" - These lines can be smushed together given the current smushing rules
"end" - The lines can be smushed, but we're at a stopping point
"invalid" - The two lines cannot be smushed together
*/
function canVerticalSmush(txt1, txt2, opts) {
if (opts.fittingRules.vLayout === FULL_WIDTH) {return "invalid";}
var ii, len = Math.min(txt1.length, txt2.length);
var ch1, ch2, endSmush = false, validSmush;
if (len===0) {return "invalid";}
for (ii = 0; ii < len; ii++) {
ch1 = txt1.substr(ii,1);
ch2 = txt2.substr(ii,1);
if (ch1 !== " " && ch2 !== " ") {
if (opts.fittingRules.vLayout === FITTING) {
return "invalid";
} else if (opts.fittingRules.vLayout === SMUSHING) {
return "end";
} else {
if (vRule5_Smush(ch1,ch2)) {endSmush = endSmush || false; continue;} // rule 5 allow for "super" smushing, but only if we're not already ending this smush
validSmush = false;
validSmush = (opts.fittingRules.vRule1) ? vRule1_Smush(ch1,ch2) : validSmush;
validSmush = (!validSmush && opts.fittingRules.vRule2) ? vRule2_Smush(ch1,ch2) : validSmush;
validSmush = (!validSmush && opts.fittingRules.vRule3) ? vRule3_Smush(ch1,ch2) : validSmush;
validSmush = (!validSmush && opts.fittingRules.vRule4) ? vRule4_Smush(ch1,ch2) : validSmush;
endSmush = true;
if (!validSmush) {return "invalid";}
}
}
}
if (endSmush) {
return "end";
} else {
return "valid";
}
}
function getVerticalSmushDist(lines1, lines2, opts) {
var maxDist = lines1.length;
var len1 = lines1.length;
var len2 = lines2.length;
var subLines1, subLines2, slen;
var curDist = 1;
var ii, ret, result;
while (curDist <= maxDist) {
subLines1 = lines1.slice(Math.max(0,len1-curDist), len1);
subLines2 = lines2.slice(0, Math.min(maxDist, curDist));
slen = subLines2.length;//TODO:check this
result = "";
for (ii = 0; ii < slen; ii++) {
ret = canVerticalSmush(subLines1[ii], subLines2[ii], opts);
if (ret === "end") {
result = ret;
} else if (ret === "invalid") {
result = ret;
break;
} else {
if (result === "") {
result = "valid";
}
}
}
if (result === "invalid") {curDist--;break;}
if (result === "end") {break;}
if (result === "valid") {curDist++;}
}
return Math.min(maxDist,curDist);
}
function verticallySmushLines(line1, line2, opts) {
var ii, len = Math.min(line1.length, line2.length);
var ch1, ch2, result = "", validSmush;
for (ii = 0; ii < len; ii++) {
ch1 = line1.substr(ii,1);
ch2 = line2.substr(ii,1);
if (ch1 !== " " && ch2 !== " ") {
if (opts.fittingRules.vLayout === FITTING) {
result += uni_Smush(ch1,ch2);
} else if (opts.fittingRules.vLayout === SMUSHING) {
result += uni_Smush(ch1,ch2);
} else {
validSmush = (opts.fittingRules.vRule5) ? vRule5_Smush(ch1,ch2) : validSmush;
validSmush = (!validSmush && opts.fittingRules.vRule1) ? vRule1_Smush(ch1,ch2) : validSmush;
validSmush = (!validSmush && opts.fittingRules.vRule2) ? vRule2_Smush(ch1,ch2) : validSmush;
validSmush = (!validSmush && opts.fittingRules.vRule3) ? vRule3_Smush(ch1,ch2) : validSmush;
validSmush = (!validSmush && opts.fittingRules.vRule4) ? vRule4_Smush(ch1,ch2) : validSmush;
result += validSmush;
}
} else {
result += uni_Smush(ch1,ch2);
}
}
return result;
}
function verticalSmush(lines1, lines2, overlap, opts) {
var len1 = lines1.length;
var len2 = lines2.length;
var piece1 = lines1.slice(0, Math.max(0,len1-overlap));
var piece2_1 = lines1.slice(Math.max(0,len1-overlap), len1);
var piece2_2 = lines2.slice(0, Math.min(overlap, len2));
var ii, len, line, piece2 = [], piece3, result = [];
len = piece2_1.length;
for (ii = 0; ii < len; ii++) {
if (ii >= len2) {
line = piece2_1[ii];
} else {
line = verticallySmushLines(piece2_1[ii], piece2_2[ii], opts);
}
piece2.push(line);
}
piece3 = lines2.slice(Math.min(overlap,len2), len2);
return result.concat(piece1,piece2,piece3);
}
function padLines(lines, numSpaces) {
var ii, len = lines.length, padding = "";
for (ii = 0; ii < numSpaces; ii++) {
padding += " ";
}
for (ii = 0; ii < len; ii++) {
lines[ii] += padding;
}
}
function smushVerticalFigLines(output, lines, opts) {
var len1 = output[0].length;
var len2 = lines[0].length;
var overlap;
if (len1 > len2) {
padLines(lines, len1-len2);
} else if (len2 > len1) {
padLines(output, len2-len1);
}
overlap = getVerticalSmushDist(output, lines, opts);
return verticalSmush(output, lines, overlap,opts);
}
// -------------------------------------------------------------------------
// Main horizontal smush routines (excluding rules)
function getHorizontalSmushLength(txt1, txt2, opts) {
if (opts.fittingRules.hLayout === FULL_WIDTH) {return 0;}
var ii, len1 = txt1.length, len2 = txt2.length;
var maxDist = len1;
var curDist = 1;
var breakAfter = false;
var validSmush = false;
var seg1, seg2, ch1, ch2;
if (len1 === 0) {return 0;}
distCal: while (curDist <= maxDist) {
seg1 = txt1.substr(len1-curDist,curDist);
seg2 = txt2.substr(0,Math.min(curDist,len2));
for (ii = 0; ii < Math.min(curDist,len2); ii++) {
ch1 = seg1.substr(ii,1);
ch2 = seg2.substr(ii,1);
if (ch1 !== " " && ch2 !== " " ) {
if (opts.fittingRules.hLayout === FITTING) {
curDist = curDist - 1;
break distCal;
} else if (opts.fittingRules.hLayout === SMUSHING) {
if (ch1 === opts.hardBlank || ch2 === opts.hardBlank) {
curDist = curDist - 1; // universal smushing does not smush hardblanks
}
break distCal;
} else {
breakAfter = true; // we know we need to break, but we need to check if our smushing rules will allow us to smush the overlapped characters
validSmush = false; // the below checks will let us know if we can smush these characters
validSmush = (opts.fittingRules.hRule1) ? hRule1_Smush(ch1,ch2,opts.hardBlank) : validSmush;
validSmush = (!validSmush && opts.fittingRules.hRule2) ? hRule2_Smush(ch1,ch2,opts.hardBlank) : validSmush;
validSmush = (!validSmush && opts.fittingRules.hRule3) ? hRule3_Smush(ch1,ch2,opts.hardBlank) : validSmush;
validSmush = (!validSmush && opts.fittingRules.hRule4) ? hRule4_Smush(ch1,ch2,opts.hardBlank) : validSmush;
validSmush = (!validSmush && opts.fittingRules.hRule5) ? hRule5_Smush(ch1,ch2,opts.hardBlank) : validSmush;
validSmush = (!validSmush && opts.fittingRules.hRule6) ? hRule6_Smush(ch1,ch2,opts.hardBlank) : validSmush;
if (!validSmush) {
curDist = curDist - 1;
break distCal;
}
}
}
}
if (breakAfter) {break;}
curDist++;
}
return Math.min(maxDist,curDist);
}
function horizontalSmush(textBlock1, textBlock2, overlap, opts) {
var ii, jj, ch, outputFig = [],
overlapStart,piece1,piece2,piece3,len1,len2,txt1,txt2;
for (ii = 0; ii < opts.height; ii++) {
txt1 = textBlock1[ii];
txt2 = textBlock2[ii];
len1 = txt1.length;
len2 = txt2.length;
overlapStart = len1-overlap;
piece1 = txt1.substr(0,Math.max(0,overlapStart));
piece2 = "";
// determine overlap piece
var seg1 = txt1.substr(Math.max(0,len1-overlap),overlap);
var seg2 = txt2.substr(0,Math.min(overlap,len2));
for (jj = 0; jj < overlap; jj++) {
var ch1 = (jj < len1) ? seg1.substr(jj,1) : " ";
var ch2 = (jj < len2) ? seg2.substr(jj,1) : " ";
if (ch1 !== " " && ch2 !== " ") {
if (opts.fittingRules.hLayout === FITTING) {
piece2 += uni_Smush(ch1, ch2, opts.hardBlank);
} else if (opts.fittingRules.hLayout === SMUSHING) {
piece2 += uni_Smush(ch1, ch2, opts.hardBlank);
} else {
// Controlled Smushing
var nextCh = "";
nextCh = (!nextCh && opts.fittingRules.hRule1) ? hRule1_Smush(ch1,ch2,opts.hardBlank) : nextCh;
nextCh = (!nextCh && opts.fittingRules.hRule2) ? hRule2_Smush(ch1,ch2,opts.hardBlank) : nextCh;
nextCh = (!nextCh && opts.fittingRules.hRule3) ? hRule3_Smush(ch1,ch2,opts.hardBlank) : nextCh;
nextCh = (!nextCh && opts.fittingRules.hRule4) ? hRule4_Smush(ch1,ch2,opts.hardBlank) : nextCh;
nextCh = (!nextCh && opts.fittingRules.hRule5) ? hRule5_Smush(ch1,ch2,opts.hardBlank) : nextCh;
nextCh = (!nextCh && opts.fittingRules.hRule6) ? hRule6_Smush(ch1,ch2,opts.hardBlank) : nextCh;
nextCh = nextCh || uni_Smush(ch1, ch2, opts.hardBlank);
piece2 += nextCh;
}
} else {
piece2 += uni_Smush(ch1, ch2, opts.hardBlank);
}
}
if (overlap >= len2) {
piece3 = "";
} else {
piece3 = txt2.substr(overlap,Math.max(0,len2-overlap));
}
outputFig[ii] = piece1 + piece2 + piece3;
}
return outputFig;
}
function generateFigTextLine(txt, figChars, opts) {
var charIndex, figChar, overlap = 0, row, outputFigText = [], len=opts.height;
for (row = 0; row < len; row++) {
outputFigText[row] = "";
}
if (opts.printDirection === 1) {
txt = txt.split('').reverse().join('');
}
len=txt.length;
for (charIndex = 0; charIndex < len; charIndex++) {
figChar = figChars[txt.substr(charIndex,1).charCodeAt(0)];
if (figChar) {
if (opts.fittingRules.hLayout !== FULL_WIDTH) {
overlap = 10000;// a value too high to be the overlap
for (row = 0; row < opts.height; row++) {
overlap = Math.min(overlap, getHorizontalSmushLength(outputFigText[row], figChar[row], opts));
}
overlap = (overlap === 10000) ? 0 : overlap;
}
outputFigText = horizontalSmush(outputFigText, figChar, overlap, opts);
}
}
// remove hardblanks
if (opts.showHardBlanks !== true) {
len = outputFigText.length;
for (row = 0; row < len; row++) {
outputFigText[row] = outputFigText[row].replace(new RegExp("\\"+opts.hardBlank,"g")," ");
}
}
return outputFigText;
}
// -------------------------------------------------------------------------
// Parsing and Generation methods
var getHorizontalFittingRules = function(layout, options) {
var props = ["hLayout", "hRule1","hRule2","hRule3","hRule4","hRule5","hRule6"],
params = {}, prop, ii;
if (layout === "default") {
for (ii = 0; ii < props.length; ii++) {
params[props[ii]] = options.fittingRules[props[ii]];
}
} else if (layout === "full") {
params = {"hLayout": FULL_WIDTH,"hRule1":false,"hRule2":false,"hRule3":false,"hRule4":false,"hRule5":false,"hRule6":false};
} else if (layout === "fitted") {
params = {"hLayout": FITTING,"hRule1":false,"hRule2":false,"hRule3":false,"hRule4":false,"hRule5":false,"hRule6":false};
} else if (layout === "controlled smushing") {
params = {"hLayout": CONTROLLED_SMUSHING,"hRule1":true,"hRule2":true,"hRule3":true,"hRule4":true,"hRule5":true,"hRule6":true};
} else if (layout === "universal smushing") {
params = {"hLayout": SMUSHING,"hRule1":false,"hRule2":false,"hRule3":false,"hRule4":false,"hRule5":false,"hRule6":false};
} else {
return;
}
return params;
};
var getVerticalFittingRules = function(layout, options) {
var props = ["vLayout", "vRule1","vRule2","vRule3","vRule4","vRule5"],
params = {}, prop, ii;
if (layout === "default") {
for (ii = 0; ii < props.length; ii++) {
params[props[ii]] = options.fittingRules[props[ii]];
}
} else if (layout === "full") {
params = {"vLayout": FULL_WIDTH,"vRule1":false,"vRule2":false,"vRule3":false,"vRule4":false,"vRule5":false};
} else if (layout === "fitted") {
params = {"vLayout": FITTING,"vRule1":false,"vRule2":false,"vRule3":false,"vRule4":false,"vRule5":false};
} else if (layout === "controlled smushing") {
params = {"vLayout": CONTROLLED_SMUSHING,"vRule1":true,"vRule2":true,"vRule3":true,"vRule4":true,"vRule5":true};
} else if (layout === "universal smushing") {
params = {"vLayout": SMUSHING,"vRule1":false,"vRule2":false,"vRule3":false,"vRule4":false,"vRule5":false};
} else {
return;
}
return params;
};
/*
Generates the ASCII Art
- fontName: Font to use
- option: Options to override the defaults
- txt: The text to make into ASCII Art
*/
var generateText = function(fontName, options, txt) {
txt = txt.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
var lines = txt.split("\n");
var figLines = [];
var ii, len, output;
len = lines.length;
for (ii = 0; ii < len; ii++) {
figLines.push( generateFigTextLine(lines[ii], figFonts[fontName], options) );
}
len = figLines.length;
output = figLines[0];
for (ii = 1; ii < len; ii++) {
output = smushVerticalFigLines(output, figLines[ii], options);
}
return output.join("\n");
};
// -------------------------------------------------------------------------
// Public methods
/*
A short-cut for the figlet.text method
Parameters:
- txt (string): The text to make into ASCII Art
- options (object/string - optional): Options that will override the current font's default options.
If a string is provided instead of an object, it is assumed to be the font name.
* font
* horizontalLayout
* verticalLayout
* showHardBlanks - Wont remove hardblank characters
- next (function): A callback function, it will contained the outputted ASCII Art.
*/
var me = function(txt, options, next) {
me.text(txt, options, next);
};
me.text = function(txt, options, next) {
var fontName = '';
// Validate inputs
txt = txt + '';
if (typeof arguments[1] === 'function') {
next = options;
options = {};
options.font = figDefaults.font; // default font
}
if (typeof options === 'string') {
fontName = options;
options = {};
} else {
options = options || {};
fontName = options.font || figDefaults.font;
}
/*
Load the font. If it loads, it's data will be contained in the figFonts object.
The callback will recieve a fontsOpts object, which contains the default
options of the font (its fitting rules, etc etc).
*/
me.loadFont(fontName, function(err, fontOpts) {
if (err) {
return next(err);
}
next(null, generateText(fontName, _reworkFontOpts(fontOpts, options), txt));
});
};
/*
Synchronous version of figlet.text.
Accepts the same parameters.
*/
me.textSync = function(txt, options) {
var fontName = '';
// Validate inputs
txt = txt + '';
if (typeof options === 'string') {
fontName = options;
options = {};
} else {
options = options || {};
fontName = options.font || figDefaults.font;
}
var fontOpts = _reworkFontOpts(me.loadFontSync(fontName), options);
return generateText(fontName, fontOpts, txt);
};
/*
takes assigned options and merges them with the default options from the choosen font
*/
function _reworkFontOpts(fontOpts, options) {
var myOpts = JSON.parse(JSON.stringify(fontOpts)), // make a copy because we may edit this (see below)
params,
prop;
/*
If the user is chosing to use a specific type of layout (e.g., 'full', 'fitted', etc etc)
Then we need to override the default font options.
*/
if (typeof options.horizontalLayout !== 'undefined') {
params = getH