613 lines
20 KiB
JavaScript
613 lines
20 KiB
JavaScript
(function() {
|
|
var MarkedYAMLError, nodes, util, _ref, _ref1,
|
|
__hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
|
|
|
MarkedYAMLError = require('./errors').MarkedYAMLError;
|
|
|
|
nodes = require('./nodes');
|
|
|
|
util = require('./util');
|
|
|
|
this.ConstructorError = (function(_super) {
|
|
__extends(ConstructorError, _super);
|
|
|
|
function ConstructorError() {
|
|
_ref = ConstructorError.__super__.constructor.apply(this, arguments);
|
|
return _ref;
|
|
}
|
|
|
|
return ConstructorError;
|
|
|
|
})(MarkedYAMLError);
|
|
|
|
this.BaseConstructor = (function() {
|
|
BaseConstructor.prototype.yaml_constructors = {};
|
|
|
|
BaseConstructor.prototype.yaml_multi_constructors = {};
|
|
|
|
BaseConstructor.add_constructor = function(tag, constructor) {
|
|
if (!this.prototype.hasOwnProperty('yaml_constructors')) {
|
|
this.prototype.yaml_constructors = util.extend({}, this.prototype.yaml_constructors);
|
|
}
|
|
return this.prototype.yaml_constructors[tag] = constructor;
|
|
};
|
|
|
|
BaseConstructor.add_multi_constructor = function(tag_prefix, multi_constructor) {
|
|
if (!this.prototype.hasOwnProperty('yaml_multi_constructors')) {
|
|
this.prototype.yaml_multi_constructors = util.extend({}, this.prototype.yaml_multi_constructors);
|
|
}
|
|
return this.prototype.yaml_multi_constructors[tag_prefix] = multi_constructor;
|
|
};
|
|
|
|
function BaseConstructor() {
|
|
this.constructed_objects = {};
|
|
this.constructing_nodes = [];
|
|
this.deferred_constructors = [];
|
|
}
|
|
|
|
/*
|
|
Are there more documents available?
|
|
*/
|
|
|
|
|
|
BaseConstructor.prototype.check_data = function() {
|
|
return this.check_node();
|
|
};
|
|
|
|
/*
|
|
Construct and return the next document.
|
|
*/
|
|
|
|
|
|
BaseConstructor.prototype.get_data = function() {
|
|
if (this.check_node()) {
|
|
return this.construct_document(this.get_node());
|
|
}
|
|
};
|
|
|
|
/*
|
|
Ensure that the stream contains a single document and construct it.
|
|
*/
|
|
|
|
|
|
BaseConstructor.prototype.get_single_data = function() {
|
|
var node;
|
|
|
|
node = this.get_single_node();
|
|
if (node != null) {
|
|
return this.construct_document(node);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
BaseConstructor.prototype.construct_document = function(node) {
|
|
var data;
|
|
|
|
data = this.construct_object(node);
|
|
while (!util.is_empty(this.deferred_constructors)) {
|
|
this.deferred_constructors.pop()();
|
|
}
|
|
return data;
|
|
};
|
|
|
|
BaseConstructor.prototype.defer = function(f) {
|
|
return this.deferred_constructors.push(f);
|
|
};
|
|
|
|
BaseConstructor.prototype.construct_object = function(node) {
|
|
var constructor, object, tag_prefix, tag_suffix, _ref1;
|
|
|
|
if (node.unique_id in this.constructed_objects) {
|
|
return this.constructed_objects[node.unique_id];
|
|
}
|
|
if (_ref1 = node.unique_id, __indexOf.call(this.constructing_nodes, _ref1) >= 0) {
|
|
throw new exports.ConstructorError(null, null, 'found unconstructable recursive node', node.start_mark);
|
|
}
|
|
this.constructing_nodes.push(node.unique_id);
|
|
constructor = null;
|
|
tag_suffix = null;
|
|
if (node.tag in this.yaml_constructors) {
|
|
constructor = this.yaml_constructors[node.tag];
|
|
} else {
|
|
for (tag_prefix in this.yaml_multi_constructors) {
|
|
if (node.tag.indexOf(tag_prefix === 0)) {
|
|
tag_suffix = node.tag.slice(tag_prefix.length);
|
|
constructor = this.yaml_multi_constructors[tag_prefix];
|
|
break;
|
|
}
|
|
}
|
|
if (constructor == null) {
|
|
if (null in this.yaml_multi_constructors) {
|
|
tag_suffix = node.tag;
|
|
constructor = this.yaml_multi_constructors[null];
|
|
} else if (null in this.yaml_constructors) {
|
|
constructor = this.yaml_constructors[null];
|
|
} else if (node instanceof nodes.ScalarNode) {
|
|
constructor = this.construct_scalar;
|
|
} else if (node instanceof nodes.SequenceNode) {
|
|
constructor = this.construct_sequence;
|
|
} else if (node instanceof nodes.MappingNode) {
|
|
constructor = this.construct_mapping;
|
|
}
|
|
}
|
|
}
|
|
object = constructor.call(this, tag_suffix != null ? tag_suffix : node, node);
|
|
this.constructed_objects[node.unique_id] = object;
|
|
this.constructing_nodes.pop();
|
|
return object;
|
|
};
|
|
|
|
BaseConstructor.prototype.construct_scalar = function(node) {
|
|
if (!(node instanceof nodes.ScalarNode)) {
|
|
throw new exports.ConstructorError(null, null, "expected a scalar node but found " + node.id, node.start_mark);
|
|
}
|
|
return node.value;
|
|
};
|
|
|
|
BaseConstructor.prototype.construct_sequence = function(node) {
|
|
var child, _i, _len, _ref1, _results;
|
|
|
|
if (!(node instanceof nodes.SequenceNode)) {
|
|
throw new exports.ConstructorError(null, null, "expected a sequence node but found " + node.id, node.start_mark);
|
|
}
|
|
_ref1 = node.value;
|
|
_results = [];
|
|
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
|
child = _ref1[_i];
|
|
_results.push(this.construct_object(child));
|
|
}
|
|
return _results;
|
|
};
|
|
|
|
BaseConstructor.prototype.construct_mapping = function(node) {
|
|
var key, key_node, mapping, value, value_node, _i, _len, _ref1, _ref2;
|
|
|
|
if (!(node instanceof nodes.MappingNode)) {
|
|
throw new ConstructorError(null, null, "expected a mapping node but found " + node.id, node.start_mark);
|
|
}
|
|
mapping = {};
|
|
_ref1 = node.value;
|
|
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
|
_ref2 = _ref1[_i], key_node = _ref2[0], value_node = _ref2[1];
|
|
key = this.construct_object(key_node);
|
|
if (typeof key === 'object') {
|
|
throw new exports.ConstructorError('while constructing a mapping', node.start_mark, 'found unhashable key', key_node.start_mark);
|
|
}
|
|
value = this.construct_object(value_node);
|
|
mapping[key] = value;
|
|
}
|
|
return mapping;
|
|
};
|
|
|
|
BaseConstructor.prototype.construct_pairs = function(node) {
|
|
var key, key_node, pairs, value, value_node, _i, _len, _ref1, _ref2;
|
|
|
|
if (!(node instanceof nodes.MappingNode)) {
|
|
throw new exports.ConstructorError(null, null, "expected a mapping node but found " + node.id, node.start_mark);
|
|
}
|
|
pairs = [];
|
|
_ref1 = node.value;
|
|
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
|
_ref2 = _ref1[_i], key_node = _ref2[0], value_node = _ref2[1];
|
|
key = this.construct_object(key_node);
|
|
value = this.construct_object(value_node);
|
|
pairs.push([key, value]);
|
|
}
|
|
return pairs;
|
|
};
|
|
|
|
return BaseConstructor;
|
|
|
|
})();
|
|
|
|
this.Constructor = (function(_super) {
|
|
var BOOL_VALUES, TIMESTAMP_PARTS, TIMESTAMP_REGEX;
|
|
|
|
__extends(Constructor, _super);
|
|
|
|
function Constructor() {
|
|
_ref1 = Constructor.__super__.constructor.apply(this, arguments);
|
|
return _ref1;
|
|
}
|
|
|
|
BOOL_VALUES = {
|
|
on: true,
|
|
off: false,
|
|
"true": true,
|
|
"false": false,
|
|
yes: true,
|
|
no: false
|
|
};
|
|
|
|
TIMESTAMP_REGEX = /^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[\x20\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\.([0-9]*))?(?:[\x20\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?)?$/;
|
|
|
|
TIMESTAMP_PARTS = {
|
|
year: 1,
|
|
month: 2,
|
|
day: 3,
|
|
hour: 4,
|
|
minute: 5,
|
|
second: 6,
|
|
fraction: 7,
|
|
tz: 8,
|
|
tz_sign: 9,
|
|
tz_hour: 10,
|
|
tz_minute: 11
|
|
};
|
|
|
|
Constructor.prototype.yaml_constructors = {};
|
|
|
|
Constructor.prototype.yaml_multi_constructors = {};
|
|
|
|
Constructor.prototype.construct_scalar = function(node) {
|
|
var key_node, value_node, _i, _len, _ref2, _ref3;
|
|
|
|
if (node instanceof nodes.MappingNode) {
|
|
_ref2 = node.value;
|
|
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
|
_ref3 = _ref2[_i], key_node = _ref3[0], value_node = _ref3[1];
|
|
if (key_node.tag === 'tag:yaml.org,2002:value') {
|
|
return this.construct_scalar(value_node);
|
|
}
|
|
}
|
|
}
|
|
return Constructor.__super__.construct_scalar.call(this, node);
|
|
};
|
|
|
|
Constructor.prototype.flatten_mapping = function(node) {
|
|
var index, key_node, merge, submerge, subnode, value, value_node, _i, _j, _len, _len1, _ref2, _ref3;
|
|
|
|
merge = [];
|
|
index = 0;
|
|
while (index < node.value.length) {
|
|
_ref2 = node.value[index], key_node = _ref2[0], value_node = _ref2[1];
|
|
if (key_node.tag === 'tag:yaml.org,2002:merge') {
|
|
node.value.splice(index, 1);
|
|
if (value_node instanceof nodes.MappingNode) {
|
|
this.flatten_mapping(value_node);
|
|
merge = merge.concat(value_node.value);
|
|
} else if (value_node instanceof nodes.SequenceNode) {
|
|
submerge = [];
|
|
_ref3 = value_node.value;
|
|
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
|
subnode = _ref3[_i];
|
|
if (!(subnode instanceof nodes.MappingNode)) {
|
|
throw new exports.ConstructorError('while constructing a mapping', node.start_mark, "expected a mapping for merging, but found " + subnode.id, subnode.start_mark);
|
|
}
|
|
this.flatten_mapping(subnode);
|
|
submerge.push(subnode.value);
|
|
}
|
|
submerge.reverse();
|
|
for (_j = 0, _len1 = submerge.length; _j < _len1; _j++) {
|
|
value = submerge[_j];
|
|
merge = merge.concat(value);
|
|
}
|
|
} else {
|
|
throw new exports.ConstructorError('while constructing a mapping', node.start_mark, "expected a mapping or list of mappings for merging but found " + value_node.id, value_node.start_mark);
|
|
}
|
|
} else if (key_node.tag === 'tag:yaml.org,2002:value') {
|
|
key_node.tag = 'tag:yaml.org,2002:str';
|
|
index++;
|
|
} else {
|
|
index++;
|
|
}
|
|
}
|
|
if (merge.length) {
|
|
return node.value = merge.concat(node.value);
|
|
}
|
|
};
|
|
|
|
Constructor.prototype.construct_mapping = function(node) {
|
|
if (node instanceof nodes.MappingNode) {
|
|
this.flatten_mapping(node);
|
|
}
|
|
return Constructor.__super__.construct_mapping.call(this, node);
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_null = function(node) {
|
|
this.construct_scalar(node);
|
|
return null;
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_bool = function(node) {
|
|
var value;
|
|
|
|
value = this.construct_scalar(node);
|
|
return BOOL_VALUES[value.toLowerCase()];
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_int = function(node) {
|
|
var base, digit, digits, part, sign, value, _i, _len, _ref2;
|
|
|
|
value = this.construct_scalar(node);
|
|
value = value.replace(/_/g, '');
|
|
sign = value[0] === '-' ? -1 : 1;
|
|
if (_ref2 = value[0], __indexOf.call('+-', _ref2) >= 0) {
|
|
value = value.slice(1);
|
|
}
|
|
if (value === '0') {
|
|
return 0;
|
|
} else if (value.indexOf('0b') === 0) {
|
|
return sign * parseInt(value.slice(2), 2);
|
|
} else if (value.indexOf('0x') === 0) {
|
|
return sign * parseInt(value.slice(2), 16);
|
|
} else if (value.indexOf('0o') === 0) {
|
|
return sign * parseInt(value.slice(2), 8);
|
|
} else if (value[0] === '0') {
|
|
return sign * parseInt(value, 8);
|
|
} else if (__indexOf.call(value, ':') >= 0) {
|
|
digits = (function() {
|
|
var _i, _len, _ref3, _results;
|
|
|
|
_ref3 = value.split(/:/g);
|
|
_results = [];
|
|
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
|
part = _ref3[_i];
|
|
_results.push(parseInt(part));
|
|
}
|
|
return _results;
|
|
})();
|
|
digits.reverse();
|
|
base = 1;
|
|
value = 0;
|
|
for (_i = 0, _len = digits.length; _i < _len; _i++) {
|
|
digit = digits[_i];
|
|
value += digit * base;
|
|
base *= 60;
|
|
}
|
|
return sign * value;
|
|
} else {
|
|
return sign * parseInt(value);
|
|
}
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_float = function(node) {
|
|
var base, digit, digits, part, sign, value, _i, _len, _ref2;
|
|
|
|
value = this.construct_scalar(node);
|
|
value = value.replace(/_/g, '').toLowerCase();
|
|
sign = value[0] === '-' ? -1 : 1;
|
|
if (_ref2 = value[0], __indexOf.call('+-', _ref2) >= 0) {
|
|
value = value.slice(1);
|
|
}
|
|
if (value === '.inf') {
|
|
return sign * Infinity;
|
|
} else if (value === '.nan') {
|
|
return NaN;
|
|
} else if (__indexOf.call(value, ':') >= 0) {
|
|
digits = (function() {
|
|
var _i, _len, _ref3, _results;
|
|
|
|
_ref3 = value.split(/:/g);
|
|
_results = [];
|
|
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
|
part = _ref3[_i];
|
|
_results.push(parseFloat(part));
|
|
}
|
|
return _results;
|
|
})();
|
|
digits.reverse();
|
|
base = 1;
|
|
value = 0.0;
|
|
for (_i = 0, _len = digits.length; _i < _len; _i++) {
|
|
digit = digits[_i];
|
|
value += digit * base;
|
|
base *= 60;
|
|
}
|
|
return sign * value;
|
|
} else {
|
|
return sign * parseFloat(value);
|
|
}
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_binary = function(node) {
|
|
var error, value;
|
|
|
|
value = this.construct_scalar(node);
|
|
try {
|
|
if (typeof window !== "undefined" && window !== null) {
|
|
return atob(value);
|
|
}
|
|
return new Buffer(value, 'base64').toString('ascii');
|
|
} catch (_error) {
|
|
error = _error;
|
|
throw new exports.ConstructorError(null, null, "failed to decode base64 data: " + error, node.start_mark);
|
|
}
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_timestamp = function(node) {
|
|
var date, day, fraction, hour, index, key, match, millisecond, minute, month, second, tz_hour, tz_minute, tz_sign, value, values, year;
|
|
|
|
value = this.construct_scalar(node);
|
|
match = node.value.match(TIMESTAMP_REGEX);
|
|
values = {};
|
|
for (key in TIMESTAMP_PARTS) {
|
|
index = TIMESTAMP_PARTS[key];
|
|
values[key] = match[index];
|
|
}
|
|
year = parseInt(values.year);
|
|
month = parseInt(values.month) - 1;
|
|
day = parseInt(values.day);
|
|
if (!values.hour) {
|
|
return new Date(Date.UTC(year, month, day));
|
|
}
|
|
hour = parseInt(values.hour);
|
|
minute = parseInt(values.minute);
|
|
second = parseInt(values.second);
|
|
millisecond = 0;
|
|
if (values.fraction) {
|
|
fraction = values.fraction.slice(0, 6);
|
|
while (fraction.length < 6) {
|
|
fraction += '0';
|
|
}
|
|
fraction = parseInt(fraction);
|
|
millisecond = Math.round(fraction / 1000);
|
|
}
|
|
if (values.tz_sign) {
|
|
tz_sign = values.tz_sign === '-' ? 1 : -1;
|
|
if (tz_hour = parseInt(values.tz_hour)) {
|
|
hour += tz_sign * tz_hour;
|
|
}
|
|
if (tz_minute = parseInt(values.tz_minute)) {
|
|
minute += tz_sign * tz_minute;
|
|
}
|
|
}
|
|
date = new Date(Date.UTC(year, month, day, hour, minute, second, millisecond));
|
|
return date;
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_pair_list = function(type, node) {
|
|
var list,
|
|
_this = this;
|
|
|
|
list = [];
|
|
if (!(node instanceof nodes.SequenceNode)) {
|
|
throw new exports.ConstructorError("while constructing " + type, node.start_mark, "expected a sequence but found " + node.id, node.start_mark);
|
|
}
|
|
this.defer(function() {
|
|
var key, key_node, subnode, value, value_node, _i, _len, _ref2, _ref3, _results;
|
|
|
|
_ref2 = node.value;
|
|
_results = [];
|
|
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
|
subnode = _ref2[_i];
|
|
if (!(subnode instanceof nodes.MappingNode)) {
|
|
throw new exports.ConstructorError("while constructing " + type, node.start_mark, "expected a mapping of length 1 but found " + subnode.id, subnode.start_mark);
|
|
}
|
|
if (subnode.value.length !== 1) {
|
|
throw new exports.ConstructorError("while constructing " + type, node.start_mark, "expected a mapping of length 1 but found " + subnode.id, subnode.start_mark);
|
|
}
|
|
_ref3 = subnode.value[0], key_node = _ref3[0], value_node = _ref3[1];
|
|
key = _this.construct_object(key_node);
|
|
value = _this.construct_object(value_node);
|
|
_results.push(list.push([key, value]));
|
|
}
|
|
return _results;
|
|
});
|
|
return list;
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_omap = function(node) {
|
|
return this.construct_yaml_pair_list('an ordered map', node);
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_pairs = function(node) {
|
|
return this.construct_yaml_pair_list('pairs', node);
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_set = function(node) {
|
|
var data,
|
|
_this = this;
|
|
|
|
data = [];
|
|
this.defer(function() {
|
|
var item, _results;
|
|
|
|
_results = [];
|
|
for (item in _this.construct_mapping(node)) {
|
|
_results.push(data.push(item));
|
|
}
|
|
return _results;
|
|
});
|
|
return data;
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_str = function(node) {
|
|
return this.construct_scalar(node);
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_seq = function(node) {
|
|
var data,
|
|
_this = this;
|
|
|
|
data = [];
|
|
this.defer(function() {
|
|
var item, _i, _len, _ref2, _results;
|
|
|
|
_ref2 = _this.construct_sequence(node);
|
|
_results = [];
|
|
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
|
item = _ref2[_i];
|
|
_results.push(data.push(item));
|
|
}
|
|
return _results;
|
|
});
|
|
return data;
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_map = function(node) {
|
|
var data,
|
|
_this = this;
|
|
|
|
data = {};
|
|
this.defer(function() {
|
|
var key, value, _ref2, _results;
|
|
|
|
_ref2 = _this.construct_mapping(node);
|
|
_results = [];
|
|
for (key in _ref2) {
|
|
value = _ref2[key];
|
|
_results.push(data[key] = value);
|
|
}
|
|
return _results;
|
|
});
|
|
return data;
|
|
};
|
|
|
|
Constructor.prototype.construct_yaml_object = function(node, klass) {
|
|
var data,
|
|
_this = this;
|
|
|
|
data = new klass;
|
|
this.defer(function() {
|
|
var key, value, _ref2, _results;
|
|
|
|
_ref2 = _this.construct_mapping(node, true);
|
|
_results = [];
|
|
for (key in _ref2) {
|
|
value = _ref2[key];
|
|
_results.push(data[key] = value);
|
|
}
|
|
return _results;
|
|
});
|
|
return data;
|
|
};
|
|
|
|
Constructor.prototype.construct_undefined = function(node) {
|
|
throw new exports.ConstructorError(null, null, "could not determine a constructor for the tag " + node.tag, node.start_mark);
|
|
};
|
|
|
|
return Constructor;
|
|
|
|
})(this.BaseConstructor);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:null', this.Constructor.prototype.construct_yaml_null);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:bool', this.Constructor.prototype.construct_yaml_bool);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:int', this.Constructor.prototype.construct_yaml_int);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:float', this.Constructor.prototype.construct_yaml_float);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:binary', this.Constructor.prototype.construct_yaml_binary);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:timestamp', this.Constructor.prototype.construct_yaml_timestamp);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:omap', this.Constructor.prototype.construct_yaml_omap);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:pairs', this.Constructor.prototype.construct_yaml_pairs);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:set', this.Constructor.prototype.construct_yaml_set);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:str', this.Constructor.prototype.construct_yaml_str);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:seq', this.Constructor.prototype.construct_yaml_seq);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:map', this.Constructor.prototype.construct_yaml_map);
|
|
|
|
this.Constructor.add_constructor(null, this.Constructor.prototype.construct_undefined);
|
|
|
|
}).call(this);
|