jashkenas--coffeescript/lib/helpers.js

144 lines
4.8 KiB
JavaScript

(function(){
var balanced_string, compact, count, del, extend, flatten, helpers, include, merge, starts;
var __hasProp = Object.prototype.hasOwnProperty;
// This file contains the common helper functions that we'd like to share among
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
// arrays, count characters, that sort of thing.
// Set up exported variables for both **Node.js** and the browser.
if (!((typeof process !== "undefined" && process !== null))) {
this.exports = this;
}
helpers = (exports.helpers = {});
// Does a list include a value?
helpers.include = (include = function include(list, value) {
return list.indexOf(value) >= 0;
});
// Peek at the beginning of a given string to see if it matches a sequence.
helpers.starts = (starts = function starts(string, literal, start) {
return string.substring(start, (start || 0) + literal.length) === literal;
});
// Trim out all falsy values from an array.
helpers.compact = (compact = function compact(array) {
var _a, _b, _c, _d, item;
_a = []; _c = array;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
item = _c[_b];
item ? _a.push(item) : null;
}
return _a;
});
// Count the number of occurences of a character in a string.
helpers.count = (count = function count(string, letter) {
var num, pos;
num = 0;
pos = string.indexOf(letter);
while (pos !== -1) {
num += 1;
pos = string.indexOf(letter, pos + 1);
}
return num;
});
// Merge objects, returning a fresh copy with attributes from both sides.
// Used every time `BaseNode#compile` is called, to allow properties in the
// options hash to propagate down the tree without polluting other branches.
helpers.merge = (merge = function merge(options, overrides) {
var _a, _b, fresh, key, val;
fresh = {};
_a = options;
for (key in _a) { if (__hasProp.call(_a, key)) {
val = _a[key];
(fresh[key] = val);
}}
if (overrides) {
_b = overrides;
for (key in _b) { if (__hasProp.call(_b, key)) {
val = _b[key];
(fresh[key] = val);
}}
}
return fresh;
});
// Extend a source object with the properties of another object (shallow copy).
// We use this to simulate Node's deprecated `process.mixin`
helpers.extend = (extend = function extend(object, properties) {
var _a, _b, key, val;
_a = []; _b = properties;
for (key in _b) { if (__hasProp.call(_b, key)) {
val = _b[key];
_a.push((object[key] = val));
}}
return _a;
});
// Return a completely flattened version of an array. Handy for getting a
// list of `children` from the nodes.
helpers.flatten = (flatten = function flatten(array) {
var _a, _b, _c, item, memo;
memo = [];
_b = array;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
item = _b[_a];
item instanceof Array ? (memo = memo.concat(item)) : memo.push(item);
}
return memo;
});
// Delete a key from an object, returning the value. Useful when a node is
// looking for a particular method in an options hash.
helpers.del = (del = function del(obj, key) {
var val;
val = obj[key];
delete obj[key];
return val;
});
// Matches a balanced group such as a single or double-quoted string. Pass in
// a series of delimiters, all of which must be nested correctly within the
// contents of the string. This method allows us to have strings within
// interpolations within strings, ad infinitum.
helpers.balanced_string = (balanced_string = function balanced_string(str, delimited, options) {
var _a, _b, _c, _d, close, i, levels, open, pair, slash;
options = options || {};
slash = delimited[0][0] === '/';
levels = [];
i = 0;
while (i < str.length) {
if (levels.length && starts(str, '\\', i)) {
i += 1;
} else {
_b = delimited;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
pair = _b[_a];
_d = pair;
open = _d[0];
close = _d[1];
if (levels.length && starts(str, close, i) && levels[levels.length - 1] === pair) {
levels.pop();
i += close.length - 1;
if (!(levels.length)) {
i += 1;
}
break;
} else if (starts(str, open, i)) {
levels.push(pair);
i += open.length - 1;
break;
}
}
}
if (!levels.length || slash && starts(str, '\n', i)) {
break;
}
i += 1;
}
if (levels.length) {
if (slash) {
return false;
}
throw new Error(("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1)));
}
if (!i) {
return false;
} else {
return str.substring(0, i);
}
});
})();