File: /home/frenchy/www/french-american.org/current/node_modules/uglyfly-js/lib/OutputStream.js
/***********************************************************************
Copyright 2014 (c) Saair Quaderi <saair.quaderi@gmail.com>
Copyright 2012-2013 (c) Mihai Bazon <mihai.bazon@gmail.com>
UglyflyJS sourcecode can be found here:
https://github.com/quaderi/uglyflyjs
UglyflyJS (by Saair) is a fork of UglifyJS2 (by Mihai Bazon)
Both libraries are released under the BSD 2-Clause License.
***********************************************************************/
/*globals define, module, require */
((typeof define === "function") ? define :
function () { "use strict"; require('./nd').apply(module, arguments); })(
"OutputStream",
[
"defaults",
"is"
],
function (defaults, is) {
"use strict";
/*jslint plusplus: true*/
function OutputStream(options, warn, croak) {
var indentation = 0,
current_col = 0,
current_line = 1,
current_pos = 0,
OUTPUT = "",
might_need_space = false,
might_need_semicolon = false,
last = null,
stack = [],
maybe_newline,
space,
indent,
with_indent,
newline,
semicolon,
add_mapping;
options = defaults(options, {
indent_start : 0,
indent_level : 4,
quote_keys : false,
space_colon : true,
ascii_only : false,
unescape_regexps : false,
inline_script : false,
width : 80,
max_line_len : 32000,
beautify : false,
source_map : null,
bracketize : false,
semicolons : true,
comments : false,
preserve_line : false,
screw_ie8 : false,
preamble : null,
quote_style : 0
}, croak || true);
function noop() {
return;
}
function to_ascii(str, identifier) {
return str.replace(/[\u0080-\uffff]/g, function (ch) {
var code = ch.charCodeAt(0).toString(16);
if (code.length <= 2 && !identifier) {
while (code.length < 2) {
code = "0" + code;
}
return "\\x" + code;
}
while (code.length < 4) {
code = "0" + code;
}
return "\\u" + code;
});
}
function make_string(str, quote) {
var sqPreference = 0,
use_sq;
str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0\ufeff]/g,
function (s) {
switch (s) {
case "\\":
return "\\\\";
case "\b":
return "\\b";
case "\f":
return "\\f";
case "\n":
return "\\n";
case "\r":
return "\\r";
case "\u2028":
return "\\u2028";
case "\u2029":
return "\\u2029";
case '"':
++sqPreference;
return '"';
case "'":
--sqPreference;
return "'";
case String.fromCharCode(0):
return "\\x00";
case "\ufeff":
return "\\ufeff";
}
return s;
});
if (options.ascii_only) {
str = to_ascii(str);
}
switch (options.quote_style) {
case 1:
use_sq = true;
break;
case 2:
use_sq = false;
break;
case 3:
use_sq = (quote === "'");
break;
default:
use_sq = (sqPreference > 0);
break;
}
str = use_sq ? "'" + str.replace(/\x27/g, "\\'") + "'" : '"' + str.replace(/\x22/g, '\\"') + '"';
return str;
}
function encode_string(str, quote) {
var ret = make_string(str, quote);
if (options.inline_script) {
ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
}
return ret;
}
function make_name(name) {
name = name.toString();
if (options.ascii_only) {
name = to_ascii(name, true);
}
return name;
}
function repeat_string(str, count) {
/*jslint bitwise: true */
var str2 = "";
if (count < 1) {
return "";
}
if (count === 1) {
return str;
}
while (count > 1) {
if (count & 1) {
str2 += str;
}
count >>= 1;
str += str;
}
return str2 + str;
}
function make_indent(back) {
return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
}
/* -----[ beautification/minification ]----- */
function last_char() {
return last.charAt(last.length - 1);
}
function requireSemicolonChars(str) {
switch (str) {
case "(":
case "*":
case "+":
case ",":
case "-":
case ".":
case "/":
case "[":
return true;
}
return false;
}
function print(str) {
var ch,
target_line,
prev,
a,
n;
str = String(str);
ch = str.charAt(0);
if (might_need_semicolon) {
if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
if (options.semicolons || requireSemicolonChars(ch)) {
OUTPUT += ";";
current_col++;
current_pos++;
} else {
OUTPUT += "\n";
current_pos++;
current_line++;
current_col = 0;
}
if (!options.beautify) {
might_need_space = false;
}
}
might_need_semicolon = false;
maybe_newline();
}
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
target_line = stack[stack.length - 1].start.line;
while (current_line < target_line) {
OUTPUT += "\n";
current_pos++;
current_line++;
current_col = 0;
might_need_space = false;
}
}
if (might_need_space) {
prev = last_char();
if ((is.identifier_char(prev) && (is.identifier_char(ch) || ch === "\\")) ||
(/^[\+\-\/]$/.test(ch) && ch === prev)) {
OUTPUT += " ";
current_col++;
current_pos++;
}
might_need_space = false;
}
a = str.split(/\r?\n/);
n = a.length - 1;
current_line += n;
if (n === 0) {
current_col += a[n].length;
} else {
current_col = a[n].length;
}
current_pos += str.length;
last = str;
OUTPUT += str;
}
maybe_newline = function () {
if (options.max_line_len && current_col > options.max_line_len) {
print("\n");
}
};
space = options.beautify ? function () {
print(" ");
} : function () {
might_need_space = true;
};
indent = options.beautify ? function (half) {
if (options.beautify) {
print(make_indent(half ? 0.5 : 0));
}
} : noop;
function next_indent() {
return indentation + options.indent_level;
}
with_indent = options.beautify ? function (col, cont) {
var save_indentation,
ret;
if (col === true) {
col = next_indent();
}
save_indentation = indentation;
indentation = col;
ret = cont();
indentation = save_indentation;
return ret;
} : function (col, cont) {
/*jslint unparam: true */
/*jshint unused: true*/
return cont();
};
newline = options.beautify ? function () {
print("\n");
} : maybe_newline;
semicolon = options.beautify ? function () {
print(";");
} : function () {
might_need_semicolon = true;
};
add_mapping = options.source_map ? function (token, name) {
try {
if (token) {
options.source_map.add(
token.file || "?",
current_line,
current_col,
token.line,
token.col,
(!name && token.type === "name") ? token.value : name
);
}
} catch (ex) {
warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
file: token.file,
line: token.line,
col: token.col,
cline: current_line,
ccol: current_col,
name: name || ""
});
}
} : noop;
if (options.preamble) {
print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
}
function force_semicolon() {
might_need_semicolon = false;
print(";");
}
function with_block(cont) {
var ret;
print("{");
newline();
with_indent(next_indent(), function () {
ret = cont();
});
indent();
print("}");
return ret;
}
function with_parens(cont) {
var ret;
print("(");
//XXX: still nice to have that for argument lists
//ret = with_indent(current_col, cont);
ret = cont();
print(")");
return ret;
}
function with_square(cont) {
var ret;
print("[");
//ret = with_indent(current_col, cont);
ret = cont();
print("]");
return ret;
}
function comma() {
print(",");
space();
}
function colon() {
print(":");
if (options.space_colon) {
space();
}
}
function get() {
return OUTPUT;
}
function current_width() {
return current_col - indentation;
}
function should_break() {
return options.width && (current_width() >= options.width);
}
function print_name(name) {
print(make_name(name));
}
function print_string(str, quote) {
print(encode_string(str, quote));
}
function option(opt) {
return options[opt];
}
function line() {
return current_line;
}
function col() {
return current_col;
}
function pos() {
return current_pos;
}
function push_node(node) {
stack.push(node);
}
function pop_node() {
return stack.pop();
}
function parent(n) {
return stack[stack.length - 2 - (n || 0)];
}
return {
get: get,
toString: get,
indent: indent,
indentation: function () {
return indentation;
},
current_width: current_width,
should_break: should_break,
newline: newline,
print: print,
space: space,
comma: comma,
colon: colon,
last: function () {
return last;
},
semicolon: semicolon,
force_semicolon: force_semicolon,
to_ascii: to_ascii,
print_name: print_name,
print_string: print_string,
next_indent: next_indent,
with_indent: with_indent,
with_block: with_block,
with_parens: with_parens,
with_square: with_square,
add_mapping: add_mapping,
option: option,
line: line,
col: col,
pos: pos,
push_node: push_node,
pop_node: pop_node,
stack: function () {
return stack;
},
parent: parent
};
}
return OutputStream;
}
);