Comparing version 1.0.3 to 2.0.0
@@ -50,3 +50,3 @@ #!/usr/bin/env node | ||
cli.addArgument(['file'], { | ||
help: 'File with YAML document(s)' | ||
help: 'File to read' | ||
}); | ||
@@ -64,7 +64,7 @@ | ||
fs.readFile(options.file, 'utf8', function (err, str) { | ||
var docs = [], out; | ||
fs.readFile(options.file, 'utf8', function (error, input) { | ||
var output, isYaml; | ||
if (err) { | ||
if ('ENOENT' === err.code) { | ||
if (error) { | ||
if ('ENOENT' === error.code) { | ||
console.error('File not found: ' + options.file); | ||
@@ -74,4 +74,7 @@ process.exit(2); | ||
// Fatal fuckup | ||
console.error(options.trace && err.stack || err.message || String(err)); | ||
console.error( | ||
options.trace && error.stack || | ||
error.message || | ||
String(error)); | ||
process.exit(1); | ||
@@ -81,17 +84,46 @@ } | ||
try { | ||
// try load all documents from the file | ||
yaml.loadAll(str, function (doc) { docs.push(doc); }); | ||
out = (1 >= docs.length) ? (docs.shift() || null) : docs; | ||
} catch (err) { | ||
console.error(options.trace && err.stack || err.message || err.toString(options.compact)); | ||
process.exit(1); | ||
output = JSON.parse(input); | ||
isYaml = false; | ||
} catch (error) { | ||
if (error instanceof SyntaxError) { | ||
try { | ||
output = []; | ||
yaml.loadAll(input, function (doc) { output.push(doc); }, {}); | ||
isYaml = true; | ||
if (0 === output.length) { | ||
output = null; | ||
} else if (1 === output.length) { | ||
output = output[0]; | ||
} | ||
} catch (error) { | ||
if (options.trace && error.stack) { | ||
console.error(error.stack); | ||
} else { | ||
console.error(error.toString(options.compact)); | ||
} | ||
process.exit(1); | ||
} | ||
} else { | ||
console.error( | ||
options.trace && error.stack || | ||
error.message || | ||
String(error)); | ||
process.exit(1); | ||
} | ||
} | ||
if (options.json) { | ||
console.log(JSON.stringify(out, null, ' ')); | ||
process.exit(0); | ||
if (isYaml) { | ||
if (options.json) { | ||
console.log(JSON.stringify(output, null, ' ')); | ||
} else { | ||
console.log("\n" + util.inspect(output, false, 10, true) + "\n"); | ||
} | ||
} else { | ||
console.log(yaml.dump(output)); | ||
} | ||
console.log("\n" + util.inspect(out, false, 10, true) + "\n"); | ||
process.exit(0); | ||
}); |
@@ -0,1 +1,9 @@ | ||
2.0.0 / 2013-02-09 | ||
------------------ | ||
* Full rewrite. New architecture. Fast one-stage parsing. | ||
* Changed custom types API. | ||
* Added YAML dumper. | ||
1.0.3 / 2012-11-05 | ||
@@ -2,0 +10,0 @@ ------------------ |
@@ -1,90 +0,33 @@ | ||
/** | ||
* jsyaml | ||
**/ | ||
'use strict'; | ||
var fs = require('fs'); | ||
var _loader = require('./js-yaml/loader'); | ||
var loader = require('./js-yaml/loader'); | ||
var dumper = require('./js-yaml/dumper'); | ||
var jsyaml = module.exports = {}; | ||
function deprecated(name) { | ||
return function () { | ||
throw new Error('Function ' + name + ' is deprecated and cannot be used.'); | ||
}; | ||
} | ||
jsyaml.scan = function scan(stream, callback, Loader) { | ||
Loader = (Loader || _loader.SafeLoader); | ||
module.exports.Type = require('./js-yaml/type'); | ||
module.exports.Schema = require('./js-yaml/schema'); | ||
module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/minimal'); | ||
module.exports.SAFE_SCHEMA = require('./js-yaml/schema/safe'); | ||
module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default'); | ||
module.exports.load = loader.load; | ||
module.exports.loadAll = loader.loadAll; | ||
module.exports.safeLoad = loader.safeLoad; | ||
module.exports.safeLoadAll = loader.safeLoadAll; | ||
module.exports.dump = dumper.dump; | ||
module.exports.safeDump = dumper.safeDump; | ||
module.exports.YAMLException = require('./js-yaml/exception'); | ||
module.exports.scan = deprecated('scan'); | ||
module.exports.parse = deprecated('parse'); | ||
module.exports.compose = deprecated('compose'); | ||
module.exports.addConstructor = deprecated('addConstructor'); | ||
var loader = new Loader(stream); | ||
while (loader.checkToken()) { | ||
callback(loader.getToken()); | ||
} | ||
}; | ||
jsyaml.compose = function compose(stream, Loader) { | ||
Loader = (Loader || _loader.SafeLoader); | ||
var loader = new Loader(stream); | ||
return loader.getSingleNode(); | ||
}; | ||
jsyaml.load = function load(stream, Loader) { | ||
Loader = (Loader || _loader.Loader); | ||
var loader = new Loader(stream); | ||
return loader.getSingleData(); | ||
}; | ||
jsyaml.loadAll = function loadAll(stream, callback, Loader) { | ||
Loader = (Loader || _loader.Loader); | ||
var loader = new Loader(stream); | ||
while (loader.checkData()) { | ||
callback(loader.getData()); | ||
} | ||
}; | ||
jsyaml.safeLoad = function load(stream) { | ||
return jsyaml.load(stream, _loader.SafeLoader); | ||
}; | ||
jsyaml.safeLoadAll = function loadAll(stream, callback) { | ||
jsyaml.loadAll(stream, callback, _loader.SafeLoader); | ||
}; | ||
/** | ||
* jsyaml.addConstructor(tag, constructor[, Loader]) -> Void | ||
* | ||
* Add a constructor for the given tag. | ||
* | ||
* Constructor is a function that accepts a Loader instance | ||
* and a node object and produces the corresponding JavaScript object. | ||
**/ | ||
jsyaml.addConstructor = function addConstructor(tag, constructor, Loader) { | ||
(Loader || _loader.Loader).addConstructor(tag, constructor); | ||
}; | ||
// Register extensions handler | ||
(function () { | ||
var require_handler = function (module, filename) { | ||
var str = fs.readFileSync(filename, 'utf8'); | ||
// fill in documents | ||
module.exports = jsyaml.load(str); | ||
}; | ||
// register require extensions only if we're on node.js | ||
// hack for browserify | ||
if (undefined !== require.extensions) { | ||
require.extensions['.yml'] = require_handler; | ||
require.extensions['.yaml'] = require_handler; | ||
} | ||
}()); | ||
require('./js-yaml/require'); |
'use strict'; | ||
var $$ = module.exports = {}; | ||
var YAMLException = require('./exception'); | ||
// UTILITY METHODS | ||
//////////////////////////////////////////////////////////////////////////////// | ||
var NIL = {}; | ||
// <object> $$.extend(receiver, *sources) | ||
// | ||
// Copy all of the properties in the source objects over to the target object. | ||
// It's in-order, so the last source will override properties of the same name | ||
// in previous arguments. | ||
// | ||
// Example: var o = $$.extend({}, a, b, c); | ||
$$.extend = function extend(receiver) { | ||
var i, l, key, skip = []; | ||
function isNothing(subject) { | ||
return (undefined === subject) || (null === subject); | ||
} | ||
receiver = receiver || {}; | ||
l = arguments.length; | ||
if (!!arguments[l - 1] && !!arguments[l - 1].except) { | ||
skip = arguments[l - 1].except; | ||
l -= 1; | ||
} | ||
function isObject(subject) { | ||
return ('object' === typeof subject) && (null !== subject); | ||
} | ||
for (i = 1; i < l; i += 1) { | ||
if (!!arguments[i] && 'object' === typeof arguments[i]) { | ||
for (key in arguments[i]) { | ||
if (arguments[i].hasOwnProperty(key) && -1 === skip.indexOf(key)) { | ||
receiver[key] = arguments[i][key]; | ||
} | ||
} | ||
} | ||
} | ||
return receiver; | ||
}; | ||
// simple inheritance algorithm | ||
$$.inherits = function inherits(child, parent) { | ||
var InheritanceGlue = function () {}; | ||
InheritanceGlue.prototype = parent.prototype; | ||
child.prototype = new InheritanceGlue(); | ||
// copy parent prototype' methods into child, so mixing made possible | ||
// think of it as of caching of parent's prototype methods in child | ||
$$.extend(child.prototype, parent.prototype, {except: [ | ||
'arguments', 'length', 'name', 'prototype', 'caller' | ||
]}); | ||
// restore constructor | ||
$$.extend(child.prototype, {constructor: child}); | ||
child.__parent__ = parent; | ||
}; | ||
// wrapper for instanceof that allows to check inheritance after $$.inherits | ||
$$.isInstanceOf = function isInstanceOf(obj, klass) { | ||
var parent; | ||
if (obj instanceof klass) { | ||
return true; | ||
function toArray(sequence) { | ||
if (Array.isArray(sequence)) { | ||
return sequence; | ||
} else if (isNothing(sequence)) { | ||
return []; | ||
} else { | ||
return [ sequence ]; | ||
} | ||
} | ||
if (!!obj && !!obj.constructor) { | ||
parent = obj.constructor.__parent__; | ||
return (parent === klass || $$.isInstanceOf(parent, klass)); | ||
} | ||
return false; | ||
}; | ||
// iterates through all object keys-value pairs calling iterator on each one | ||
// example: $$.each(objOrArr, function (val, key) { /* ... */ }); | ||
$$.each = function each(obj, iterator, context) { | ||
var keys, i, l; | ||
if (null === obj || undefined === obj) { | ||
return; | ||
function getSetting(settings, name) { | ||
if (!isNothing(settings) && !isNothing(settings[name])) { | ||
return settings[name]; | ||
} else { | ||
throw new YAMLException('Required "' + name + '" setting is missed.'); | ||
} | ||
} | ||
context = context || iterator; | ||
if (obj.forEach === Array.prototype.forEach) { | ||
obj.forEach(iterator, context); | ||
function getOption(options, name, alternative) { | ||
if (!isNothing(options) && !isNothing(options[name])) { | ||
return options[name]; | ||
} else { | ||
keys = Object.getOwnPropertyNames(obj); | ||
for (i = 0, l = keys.length; i < l; i += 1) { | ||
iterator.call(context, obj[keys[i]], keys[i], obj); | ||
} | ||
return alternative; | ||
} | ||
}; | ||
} | ||
// returns reversed copy of array | ||
$$.reverse = function reverse(arr) { | ||
var result = [], i, l; | ||
for (i = 0, l = arr.length; i < l; i += 1) { | ||
result.unshift(arr[i]); | ||
} | ||
return result; | ||
}; | ||
function extend(target, source) { | ||
var index, length, key, sourceKeys = Object.keys(source); | ||
// Modified from: | ||
// https://raw.github.com/kanaka/noVNC/d890e8640f20fba3215ba7be8e0ff145aeb8c17c/include/base64.js | ||
$$.decodeBase64 = (function () { | ||
var padding = '=', binTable = [ | ||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, | ||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, | ||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | ||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, | ||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | ||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 | ||
]; | ||
return function decode(data) { | ||
var value, code, idx = 0, result = [], leftbits, leftdata; | ||
leftbits = 0; // number of bits decoded, but yet to be appended | ||
leftdata = 0; // bits decoded, but yet to be appended | ||
// Convert one by one. | ||
for (idx = 0; idx < data.length; idx += 1) { | ||
code = data.charCodeAt(idx); | ||
value = binTable[code & 0x7F]; | ||
// Skip LF(NL) || CR | ||
if (0x0A !== code && 0x0D !== code) { | ||
// Fail on illegal characters | ||
if (-1 === value) { | ||
throw new Error("Illegal characters (code=" + code + ") in position " + | ||
idx + ": ordinal not in range(0..128)"); | ||
} | ||
// Collect data into leftdata, update bitcount | ||
leftdata = (leftdata << 6) | value; | ||
leftbits += 6; | ||
// If we have 8 or more bits, append 8 bits to the result | ||
if (leftbits >= 8) { | ||
leftbits -= 8; | ||
// Append if not padding. | ||
if (padding !== data.charAt(idx)) { | ||
result.push((leftdata >> leftbits) & 0xFF); | ||
} | ||
leftdata &= (1 << leftbits) - 1; | ||
} | ||
} | ||
} | ||
// If there are any bits left, the base64 string was corrupted | ||
if (leftbits) { | ||
throw new Error("Corrupted base64 string"); | ||
} | ||
return new Buffer(result); | ||
}; | ||
}()); | ||
// CLASSES | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// Dummy alternative of delayed population based on generators in PyYAML | ||
$$.Populator = function Populator(data, callback, context) { | ||
if (!(this instanceof $$.Populator)) { | ||
return new $$.Populator(data, callback, context); | ||
for (index = 0, length = sourceKeys.length; index < length; index += 1) { | ||
key = sourceKeys[index]; | ||
target[key] = source[key]; | ||
} | ||
this.data = data; | ||
this.execute = function () { | ||
callback.call(context || callback); | ||
}; | ||
}; | ||
return target; | ||
} | ||
// Simple implementation of hashtable | ||
$$.Hash = function Hash(defaultValue) { | ||
var keys, values, index; | ||
function repeat(string, count) { | ||
var result = '', cycle; | ||
if (!(this instanceof $$.Hash)) { | ||
return new $$.Hash(defaultValue); | ||
for (cycle = 0; cycle < count; cycle += 1) { | ||
result += string; | ||
} | ||
index = 0; | ||
keys = []; | ||
values = []; | ||
return result; | ||
} | ||
this.store = function store(key, value) { | ||
var i = keys.indexOf(key); | ||
if (0 <= i) { | ||
values[i] = value; | ||
return; | ||
} | ||
i = index; | ||
index += 1; | ||
keys[i] = key; | ||
values[i] = value; | ||
}; | ||
this.remove = function remove(key) { | ||
var i = keys.indexOf(key); | ||
if (0 <= i) { | ||
delete keys[i]; | ||
delete values[i]; | ||
} | ||
}; | ||
this.hasKey = function hasKey(key) { | ||
return 0 <= keys.indexOf(key); | ||
}; | ||
this.get = function get(key) { | ||
var i = keys.indexOf(key); | ||
return (0 <= i) ? values[i] : defaultValue; | ||
}; | ||
}; | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// vim:ts=2:sw=2 | ||
//////////////////////////////////////////////////////////////////////////////// | ||
module.exports.NIL = NIL; | ||
module.exports.isNothing = isNothing; | ||
module.exports.isObject = isObject; | ||
module.exports.toArray = toArray; | ||
module.exports.getSetting = getSetting; | ||
module.exports.getOption = getOption; | ||
module.exports.repeat = repeat; | ||
module.exports.extend = extend; |
'use strict'; | ||
var $$ = require('./common'); | ||
var _reader = require('./reader'); | ||
var _scanner = require('./scanner'); | ||
var _parser = require('./parser'); | ||
var _composer = require('./composer'); | ||
var _resolver = require('./resolver'); | ||
var _constructor = require('./constructor'); | ||
var common = require('./common'); | ||
var YAMLException = require('./exception'); | ||
var Mark = require('./mark'); | ||
var NIL = common.NIL; | ||
var SAFE_SCHEMA = require('./schema/safe'); | ||
var DEFAULT_SCHEMA = require('./schema/default'); | ||
function BaseLoader(stream) { | ||
_reader.Reader.call(this, stream); | ||
_scanner.Scanner.call(this); | ||
_parser.Parser.call(this); | ||
_composer.Composer.call(this); | ||
_constructor.BaseConstructor.call(this); | ||
_resolver.BaseResolver.call(this); | ||
} | ||
var _hasOwnProperty = Object.prototype.hasOwnProperty; | ||
$$.extend(BaseLoader.prototype, | ||
_reader.Reader.prototype, | ||
_scanner.Scanner.prototype, | ||
_parser.Parser.prototype, | ||
_composer.Composer.prototype, | ||
_constructor.BaseConstructor.prototype, | ||
_resolver.BaseResolver.prototype); | ||
var KIND_STRING = 'string'; | ||
var KIND_ARRAY = 'array'; | ||
var KIND_OBJECT = 'object'; | ||
function SafeLoader(stream) { | ||
_reader.Reader.call(this, stream); | ||
_scanner.Scanner.call(this); | ||
_parser.Parser.call(this); | ||
_composer.Composer.call(this); | ||
_constructor.SafeConstructor.call(this); | ||
_resolver.Resolver.call(this); | ||
} | ||
$$.extend(SafeLoader.prototype, | ||
_reader.Reader.prototype, | ||
_scanner.Scanner.prototype, | ||
_parser.Parser.prototype, | ||
_composer.Composer.prototype, | ||
_constructor.SafeConstructor.prototype, | ||
_resolver.Resolver.prototype); | ||
var CONTEXT_FLOW_IN = 1; | ||
var CONTEXT_FLOW_OUT = 2; | ||
var CONTEXT_BLOCK_IN = 3; | ||
var CONTEXT_BLOCK_OUT = 4; | ||
function Loader(stream) { | ||
_reader.Reader.call(this, stream); | ||
_scanner.Scanner.call(this); | ||
_parser.Parser.call(this); | ||
_composer.Composer.call(this); | ||
_constructor.Constructor.call(this); | ||
_resolver.Resolver.call(this); | ||
var CHOMPING_CLIP = 1; | ||
var CHOMPING_STRIP = 2; | ||
var CHOMPING_KEEP = 3; | ||
var CHAR_TAB = 0x09; /* Tab */ | ||
var CHAR_LINE_FEED = 0x0A; /* LF */ | ||
var CHAR_CARRIAGE_RETURN = 0x0D; /* CR */ | ||
var CHAR_SPACE = 0x20; /* Space */ | ||
var CHAR_EXCLAMATION = 0x21; /* ! */ | ||
var CHAR_DOUBLE_QUOTE = 0x22; /* " */ | ||
var CHAR_SHARP = 0x23; /* # */ | ||
var CHAR_PERCENT = 0x25; /* % */ | ||
var CHAR_AMPERSAND = 0x26; /* & */ | ||
var CHAR_SINGLE_QUOTE = 0x27; /* ' */ | ||
var CHAR_ASTERISK = 0x2A; /* * */ | ||
var CHAR_PLUS = 0x2B; /* + */ | ||
var CHAR_COMMA = 0x2C; /* , */ | ||
var CHAR_MINUS = 0x2D; /* - */ | ||
var CHAR_DOT = 0x2E; /* . */ | ||
var CHAR_SLASH = 0x2F; /* / */ | ||
var CHAR_DIGIT_ZERO = 0x30; /* 0 */ | ||
var CHAR_DIGIT_ONE = 0x31; /* 1 */ | ||
var CHAR_DIGIT_NINE = 0x39; /* 9 */ | ||
var CHAR_COLON = 0x3A; /* : */ | ||
var CHAR_LESS_THAN = 0x3C; /* < */ | ||
var CHAR_GREATER_THAN = 0x3E; /* > */ | ||
var CHAR_QUESTION = 0x3F; /* ? */ | ||
var CHAR_COMMERCIAL_AT = 0x40; /* @ */ | ||
var CHAR_CAPITAL_A = 0x41; /* A */ | ||
var CHAR_CAPITAL_F = 0x46; /* F */ | ||
var CHAR_CAPITAL_L = 0x4C; /* L */ | ||
var CHAR_CAPITAL_N = 0x4E; /* N */ | ||
var CHAR_CAPITAL_P = 0x50; /* P */ | ||
var CHAR_CAPITAL_U = 0x55; /* U */ | ||
var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */ | ||
var CHAR_BACKSLASH = 0x5C; /* \ */ | ||
var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */ | ||
var CHAR_UNDERSCORE = 0x5F; /* _ */ | ||
var CHAR_GRAVE_ACCENT = 0x60; /* ` */ | ||
var CHAR_SMALL_A = 0x61; /* a */ | ||
var CHAR_SMALL_B = 0x62; /* b */ | ||
var CHAR_SMALL_E = 0x65; /* e */ | ||
var CHAR_SMALL_F = 0x66; /* f */ | ||
var CHAR_SMALL_N = 0x6E; /* n */ | ||
var CHAR_SMALL_R = 0x72; /* r */ | ||
var CHAR_SMALL_T = 0x74; /* t */ | ||
var CHAR_SMALL_U = 0x75; /* u */ | ||
var CHAR_SMALL_V = 0x76; /* v */ | ||
var CHAR_SMALL_X = 0x78; /* x */ | ||
var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */ | ||
var CHAR_VERTICAL_LINE = 0x7C; /* | */ | ||
var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */ | ||
var SIMPLE_ESCAPE_SEQUENCES = {}; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_DIGIT_ZERO] = '\x00'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_A] = '\x07'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_B] = '\x08'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_T] = '\x09'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_TAB] = '\x09'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_N] = '\x0A'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_V] = '\x0B'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_F] = '\x0C'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_R] = '\x0D'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SMALL_E] = '\x1B'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SPACE] = ' '; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_DOUBLE_QUOTE] = '\x22'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_SLASH] = '/'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_BACKSLASH] = '\x5C'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_CAPITAL_N] = '\x85'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_UNDERSCORE] = '\xA0'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_CAPITAL_L] = '\u2028'; | ||
SIMPLE_ESCAPE_SEQUENCES[CHAR_CAPITAL_P] = '\u2029'; | ||
var HEXADECIMAL_ESCAPE_SEQUENCES = {}; | ||
HEXADECIMAL_ESCAPE_SEQUENCES[CHAR_SMALL_X] = 2; | ||
HEXADECIMAL_ESCAPE_SEQUENCES[CHAR_SMALL_U] = 4; | ||
HEXADECIMAL_ESCAPE_SEQUENCES[CHAR_CAPITAL_U] = 8; | ||
var PATTERN_NON_PRINTABLE = /[\x00-\x09\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uD800-\uDFFF\uFFFE\uFFFF]/; | ||
var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/; | ||
var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/; | ||
var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i; | ||
var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; | ||
function loadAll(input, output, settings) { | ||
var filename = common.getOption(settings, 'filename', null), | ||
schema = common.getOption(settings, 'schema', DEFAULT_SCHEMA), | ||
resolve = common.getOption(settings, 'resolve', true), | ||
validate = common.getOption(settings, 'validate', true), | ||
strict = common.getOption(settings, 'strict', false), | ||
legacy = common.getOption(settings, 'legacy', false), | ||
directiveHandlers = {}, | ||
implicitTypes = schema.compiledImplicit, | ||
typeMap = schema.compiledTypeMap, | ||
length = input.length, | ||
position = 0, | ||
line = 0, | ||
lineStart = 0, | ||
lineIndent = 0, | ||
character = input.charCodeAt(position), | ||
version, | ||
checkLineBreaks, | ||
tagMap, | ||
anchorMap, | ||
tag, | ||
anchor, | ||
kind, | ||
result; | ||
function generateError(message) { | ||
return new YAMLException( | ||
message, | ||
new Mark(filename, input, position, line, (position - lineStart))); | ||
} | ||
function throwError(message) { | ||
throw generateError(message); | ||
} | ||
function throwWarning(message) { | ||
var error = generateError(message); | ||
if (strict) { | ||
throw error; | ||
} else { | ||
console.warn(error.toString()); | ||
} | ||
} | ||
directiveHandlers['YAML'] = function handleYamlDirective(name, args) { | ||
var match, major, minor; | ||
if (null !== version) { | ||
throwError('duplication of %YAML directive'); | ||
} | ||
if (1 !== args.length) { | ||
throwError('YAML directive accepts exactly one argument'); | ||
} | ||
match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); | ||
if (null === match) { | ||
throwError('ill-formed argument of the YAML directive'); | ||
} | ||
major = parseInt(match[1], 10); | ||
minor = parseInt(match[2], 10); | ||
if (1 !== major) { | ||
throwError('unacceptable YAML version of the document'); | ||
} | ||
version = args[0]; | ||
checkLineBreaks = (minor < 2); | ||
if (1 !== minor && 2 !== minor) { | ||
throwWarning('unsupported YAML version of the document'); | ||
} | ||
}; | ||
directiveHandlers['TAG'] = function handleTagDirective(name, args) { | ||
var handle, prefix; | ||
if (2 !== args.length) { | ||
throwError('TAG directive accepts exactly two arguments'); | ||
} | ||
handle = args[0]; | ||
prefix = args[1]; | ||
if (!PATTERN_TAG_HANDLE.test(handle)) { | ||
throwError('ill-formed tag handle (first argument) of the TAG directive'); | ||
} | ||
if (_hasOwnProperty.call(tagMap, handle)) { | ||
throwError('there is a previously declared suffix for "' + handle + '" tag handle'); | ||
} | ||
if (!PATTERN_TAG_URI.test(prefix)) { | ||
throwError('ill-formed tag prefix (second argument) of the TAG directive'); | ||
} | ||
tagMap[handle] = prefix; | ||
}; | ||
function captureSegment(start, end, checkJson) { | ||
var _position, _length, _character, _result; | ||
if (start < end) { | ||
_result = input.slice(start, end); | ||
if (checkJson && validate) { | ||
for (_position = 0, _length = _result.length; | ||
_position < _length; | ||
_position += 1) { | ||
_character = _result.charCodeAt(_position); | ||
if (!(0x09 === _character || | ||
0x20 <= _character && _character <= 0x10FFFF)) { | ||
throwError('expected valid JSON character'); | ||
} | ||
} | ||
} | ||
result += _result; | ||
} | ||
} | ||
function mergeMappings(destination, source) { | ||
var sourceKeys, key, index, quantity; | ||
if (!common.isObject(source)) { | ||
throwError('cannot merge mappings; the provided source object is unacceptable'); | ||
} | ||
sourceKeys = Object.keys(source); | ||
for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { | ||
key = sourceKeys[index]; | ||
if (!_hasOwnProperty.call(destination, key)) { | ||
destination[key] = source[key]; | ||
} | ||
} | ||
} | ||
function storeMappingPair(_result, keyTag, keyNode, valueNode) { | ||
var index, quantity; | ||
keyNode = String(keyNode); | ||
if (null === _result) { | ||
_result = {}; | ||
} | ||
if ('tag:yaml.org,2002:merge' === keyTag) { | ||
if (Array.isArray(valueNode)) { | ||
for (index = 0, quantity = valueNode.length; index < quantity; index += 1) { | ||
mergeMappings(_result, valueNode[index]); | ||
} | ||
} else { | ||
mergeMappings(_result, valueNode); | ||
} | ||
} else { | ||
_result[keyNode] = valueNode; | ||
} | ||
return _result; | ||
} | ||
function readLineBreak() { | ||
if (CHAR_LINE_FEED === character) { | ||
position += 1; | ||
} else if (CHAR_CARRIAGE_RETURN === character) { | ||
if (CHAR_LINE_FEED === input.charCodeAt(position + 1)) { | ||
position += 2; | ||
} else { | ||
position += 1; | ||
} | ||
} else { | ||
throwError('a line break is expected'); | ||
} | ||
line += 1; | ||
lineStart = position; | ||
character = input.charCodeAt(position); | ||
} | ||
function skipSeparationSpace(allowComments, checkIndent) { | ||
var lineBreaks = 0; | ||
while (position < length) { | ||
while (CHAR_SPACE === character || CHAR_TAB === character) { | ||
character = input.charCodeAt(++position); | ||
} | ||
if (allowComments && CHAR_SHARP === character) { | ||
do { character = input.charCodeAt(++position); } | ||
while (position < length && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character); | ||
} | ||
if (CHAR_LINE_FEED === character || CHAR_CARRIAGE_RETURN === character) { | ||
readLineBreak(); | ||
lineBreaks += 1; | ||
lineIndent = 0; | ||
while (CHAR_SPACE === character) { | ||
lineIndent += 1; | ||
character = input.charCodeAt(++position); | ||
} | ||
if (lineIndent < checkIndent) { | ||
throwWarning('deficient indentation'); | ||
} | ||
} else { | ||
break; | ||
} | ||
} | ||
return lineBreaks; | ||
} | ||
function testDocumentSeparator() { | ||
var _position, _character; | ||
if (position === lineStart && | ||
(CHAR_MINUS === character || CHAR_DOT === character) && | ||
input.charCodeAt(position + 1) === character && | ||
input.charCodeAt(position + 2) === character) { | ||
_position = position + 3; | ||
_character = input.charCodeAt(_position); | ||
if (_position >= length || | ||
CHAR_SPACE === _character || | ||
CHAR_TAB === _character || | ||
CHAR_LINE_FEED === _character || | ||
CHAR_CARRIAGE_RETURN === _character) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
function writeFoldedLines(count) { | ||
if (1 === count) { | ||
result += ' '; | ||
} else if (count > 1) { | ||
result += common.repeat('\n', count - 1); | ||
} | ||
} | ||
function readPlainScalar(nodeIndent, withinFlowCollection) { | ||
var preceding, | ||
following, | ||
captureStart, | ||
captureEnd, | ||
hasPendingContent, | ||
_line, | ||
_lineStart, | ||
_lineIndent, | ||
_kind = kind, | ||
_result = result; | ||
if (CHAR_SPACE === character || | ||
CHAR_TAB === character || | ||
CHAR_LINE_FEED === character || | ||
CHAR_CARRIAGE_RETURN === character || | ||
CHAR_COMMA === character || | ||
CHAR_LEFT_SQUARE_BRACKET === character || | ||
CHAR_RIGHT_SQUARE_BRACKET === character || | ||
CHAR_LEFT_CURLY_BRACKET === character || | ||
CHAR_RIGHT_CURLY_BRACKET === character || | ||
CHAR_SHARP === character || | ||
CHAR_AMPERSAND === character || | ||
CHAR_ASTERISK === character || | ||
CHAR_EXCLAMATION === character || | ||
CHAR_VERTICAL_LINE === character || | ||
CHAR_GREATER_THAN === character || | ||
CHAR_SINGLE_QUOTE === character || | ||
CHAR_DOUBLE_QUOTE === character || | ||
CHAR_PERCENT === character || | ||
CHAR_COMMERCIAL_AT === character || | ||
CHAR_GRAVE_ACCENT === character) { | ||
return false; | ||
} | ||
if (CHAR_QUESTION === character || | ||
CHAR_MINUS === character) { | ||
following = input.charCodeAt(position + 1); | ||
if (CHAR_SPACE === following || | ||
CHAR_TAB === following || | ||
CHAR_LINE_FEED === following || | ||
CHAR_CARRIAGE_RETURN === following || | ||
withinFlowCollection && | ||
(CHAR_COMMA === following || | ||
CHAR_LEFT_SQUARE_BRACKET === following || | ||
CHAR_RIGHT_SQUARE_BRACKET === following || | ||
CHAR_LEFT_CURLY_BRACKET === following || | ||
CHAR_RIGHT_CURLY_BRACKET === following)) { | ||
return false; | ||
} | ||
} | ||
kind = KIND_STRING; | ||
result = ''; | ||
captureStart = captureEnd = position; | ||
hasPendingContent = false; | ||
while (position < length) { | ||
if (CHAR_COLON === character) { | ||
following = input.charCodeAt(position + 1); | ||
if (CHAR_SPACE === following || | ||
CHAR_TAB === following || | ||
CHAR_LINE_FEED === following || | ||
CHAR_CARRIAGE_RETURN === following || | ||
withinFlowCollection && | ||
(CHAR_COMMA === following || | ||
CHAR_LEFT_SQUARE_BRACKET === following || | ||
CHAR_RIGHT_SQUARE_BRACKET === following || | ||
CHAR_LEFT_CURLY_BRACKET === following || | ||
CHAR_RIGHT_CURLY_BRACKET === following)) { | ||
break; | ||
} | ||
} else if (CHAR_SHARP === character) { | ||
preceding = input.charCodeAt(position - 1); | ||
if (CHAR_SPACE === preceding || | ||
CHAR_TAB === preceding || | ||
CHAR_LINE_FEED === preceding || | ||
CHAR_CARRIAGE_RETURN === preceding) { | ||
break; | ||
} | ||
} else if ((position === lineStart && testDocumentSeparator()) || | ||
withinFlowCollection && | ||
(CHAR_COMMA === character || | ||
CHAR_LEFT_SQUARE_BRACKET === character || | ||
CHAR_RIGHT_SQUARE_BRACKET === character || | ||
CHAR_LEFT_CURLY_BRACKET === character || | ||
CHAR_RIGHT_CURLY_BRACKET === character)) { | ||
break; | ||
} else if (CHAR_LINE_FEED === character || | ||
CHAR_CARRIAGE_RETURN === character) { | ||
_line = line; | ||
_lineStart = lineStart; | ||
_lineIndent = lineIndent; | ||
skipSeparationSpace(false, -1); | ||
if (lineIndent >= nodeIndent) { | ||
hasPendingContent = true; | ||
continue; | ||
} else { | ||
position = captureEnd; | ||
line = _line; | ||
lineStart = _lineStart; | ||
lineIndent = _lineIndent; | ||
character = input.charCodeAt(position); | ||
break; | ||
} | ||
} | ||
if (hasPendingContent) { | ||
captureSegment(captureStart, captureEnd, false); | ||
writeFoldedLines(line - _line); | ||
captureStart = captureEnd = position; | ||
hasPendingContent = false; | ||
} | ||
if (CHAR_SPACE !== character && CHAR_TAB !== character) { | ||
captureEnd = position + 1; | ||
} | ||
character = input.charCodeAt(++position); | ||
} | ||
captureSegment(captureStart, captureEnd, false); | ||
if (result) { | ||
return true; | ||
} else { | ||
kind = _kind; | ||
result = _result; | ||
return false; | ||
} | ||
} | ||
function readSingleQuotedScalar(nodeIndent) { | ||
var captureStart, captureEnd; | ||
if (CHAR_SINGLE_QUOTE !== character) { | ||
return false; | ||
} | ||
kind = KIND_STRING; | ||
result = ''; | ||
character = input.charCodeAt(++position); | ||
captureStart = captureEnd = position; | ||
while (position < length) { | ||
if (CHAR_SINGLE_QUOTE === character) { | ||
captureSegment(captureStart, position, true); | ||
character = input.charCodeAt(++position); | ||
if (CHAR_SINGLE_QUOTE === character) { | ||
captureStart = captureEnd = position; | ||
character = input.charCodeAt(++position); | ||
} else { | ||
return true; | ||
} | ||
} else if (CHAR_LINE_FEED === character || | ||
CHAR_CARRIAGE_RETURN === character) { | ||
captureSegment(captureStart, captureEnd, true); | ||
writeFoldedLines(skipSeparationSpace(false, nodeIndent)); | ||
captureStart = captureEnd = position; | ||
character = input.charCodeAt(position); | ||
} else if (position === lineStart && testDocumentSeparator()) { | ||
throwError('unexpected end of the document within a single quoted scalar'); | ||
} else { | ||
character = input.charCodeAt(++position); | ||
captureEnd = position; | ||
} | ||
} | ||
throwError('unexpected end of the stream within a single quoted scalar'); | ||
} | ||
function readDoubleQuotedScalar(nodeIndent) { | ||
var captureStart, | ||
captureEnd, | ||
hexLength, | ||
hexIndex, | ||
hexOffset, | ||
hexResult; | ||
if (CHAR_DOUBLE_QUOTE !== character) { | ||
return false; | ||
} | ||
kind = KIND_STRING; | ||
result = ''; | ||
character = input.charCodeAt(++position); | ||
captureStart = captureEnd = position; | ||
while (position < length) { | ||
if (CHAR_DOUBLE_QUOTE === character) { | ||
captureSegment(captureStart, position, true); | ||
character = input.charCodeAt(++position); | ||
return true; | ||
} else if (CHAR_BACKSLASH === character) { | ||
captureSegment(captureStart, position, true); | ||
character = input.charCodeAt(++position); | ||
if (CHAR_LINE_FEED === character || | ||
CHAR_CARRIAGE_RETURN === character) { | ||
skipSeparationSpace(false, nodeIndent); | ||
} else if (SIMPLE_ESCAPE_SEQUENCES[character]) { | ||
result += SIMPLE_ESCAPE_SEQUENCES[character]; | ||
character = input.charCodeAt(++position); | ||
} else if (HEXADECIMAL_ESCAPE_SEQUENCES[character]) { | ||
hexLength = HEXADECIMAL_ESCAPE_SEQUENCES[character]; | ||
hexResult = 0; | ||
for (hexIndex = 1; hexIndex <= hexLength; hexIndex += 1) { | ||
hexOffset = (hexLength - hexIndex) * 4; | ||
character = input.charCodeAt(++position); | ||
if (CHAR_DIGIT_ZERO <= character && character <= CHAR_DIGIT_NINE) { | ||
hexResult |= (character - CHAR_DIGIT_ZERO) << hexOffset; | ||
} else if (CHAR_CAPITAL_A <= character && character <= CHAR_CAPITAL_F) { | ||
hexResult |= (character - CHAR_CAPITAL_A + 10) << hexOffset; | ||
} else if (CHAR_SMALL_A <= character && character <= CHAR_SMALL_F) { | ||
hexResult |= (character - CHAR_SMALL_A + 10) << hexOffset; | ||
} else { | ||
throwError('expected hexadecimal character'); | ||
} | ||
} | ||
result += String.fromCharCode(hexResult); | ||
character = input.charCodeAt(++position); | ||
} else { | ||
throwError('unknown escape sequence'); | ||
} | ||
captureStart = captureEnd = position; | ||
} else if (CHAR_LINE_FEED === character || | ||
CHAR_CARRIAGE_RETURN === character) { | ||
captureSegment(captureStart, captureEnd, true); | ||
writeFoldedLines(skipSeparationSpace(false, nodeIndent)); | ||
captureStart = captureEnd = position; | ||
character = input.charCodeAt(position); | ||
} else if (position === lineStart && testDocumentSeparator()) { | ||
throwError('unexpected end of the document within a double quoted scalar'); | ||
} else { | ||
character = input.charCodeAt(++position); | ||
captureEnd = position; | ||
} | ||
} | ||
throwError('unexpected end of the stream within a double quoted scalar'); | ||
} | ||
function readFlowCollection(nodeIndent) { | ||
var readNext = true, | ||
_line, | ||
_tag = tag, | ||
_result, | ||
following, | ||
terminator, | ||
isPair, | ||
isExplicitPair, | ||
isMapping, | ||
keyNode, | ||
keyTag, | ||
valueNode; | ||
switch (character) { | ||
case CHAR_LEFT_SQUARE_BRACKET: | ||
terminator = CHAR_RIGHT_SQUARE_BRACKET; | ||
isMapping = false; | ||
_result = []; | ||
break; | ||
case CHAR_LEFT_CURLY_BRACKET: | ||
terminator = CHAR_RIGHT_CURLY_BRACKET; | ||
isMapping = true; | ||
_result = {}; | ||
break; | ||
default: | ||
return false; | ||
} | ||
if (null !== anchor) { | ||
anchorMap[anchor] = _result; | ||
} | ||
character = input.charCodeAt(++position); | ||
while (position < length) { | ||
skipSeparationSpace(true, nodeIndent); | ||
if (character === terminator) { | ||
character = input.charCodeAt(++position); | ||
tag = _tag; | ||
kind = isMapping ? KIND_OBJECT : KIND_ARRAY; | ||
result = _result; | ||
return true; | ||
} else if (!readNext) { | ||
throwError('missed comma between flow collection entries'); | ||
} | ||
keyTag = keyNode = valueNode = null; | ||
isPair = isExplicitPair = false; | ||
if (CHAR_QUESTION === character) { | ||
following = input.charCodeAt(position + 1); | ||
if (CHAR_SPACE === following || | ||
CHAR_TAB === following || | ||
CHAR_LINE_FEED === following || | ||
CHAR_CARRIAGE_RETURN === following) { | ||
isPair = isExplicitPair = true; | ||
position += 1; | ||
character = following; | ||
skipSeparationSpace(true, nodeIndent); | ||
} | ||
} | ||
_line = line; | ||
composeNode(nodeIndent, CONTEXT_FLOW_IN, false, true); | ||
keyTag = tag; | ||
keyNode = result; | ||
if ((isExplicitPair || line === _line) && CHAR_COLON === character) { | ||
isPair = true; | ||
character = input.charCodeAt(++position); | ||
skipSeparationSpace(true, nodeIndent); | ||
composeNode(nodeIndent, CONTEXT_FLOW_IN, false, true); | ||
valueNode = result; | ||
} | ||
if (isMapping) { | ||
storeMappingPair(_result, keyTag, keyNode, valueNode); | ||
} else if (isPair) { | ||
_result.push(storeMappingPair(null, keyTag, keyNode, valueNode)); | ||
} else { | ||
_result.push(keyNode); | ||
} | ||
skipSeparationSpace(true, nodeIndent); | ||
if (CHAR_COMMA === character) { | ||
readNext = true; | ||
character = input.charCodeAt(++position); | ||
} else { | ||
readNext = false; | ||
} | ||
} | ||
throwError('unexpected end of the stream within a flow collection'); | ||
} | ||
function readBlockScalar(nodeIndent) { | ||
var captureStart, | ||
folding, | ||
chomping = CHOMPING_CLIP, | ||
detectedIndent = false, | ||
textIndent = nodeIndent, | ||
emptyLines = -1; | ||
switch (character) { | ||
case CHAR_VERTICAL_LINE: | ||
folding = false; | ||
break; | ||
case CHAR_GREATER_THAN: | ||
folding = true; | ||
break; | ||
default: | ||
return false; | ||
} | ||
kind = KIND_STRING; | ||
result = ''; | ||
while (position < length) { | ||
character = input.charCodeAt(++position); | ||
if (CHAR_PLUS === character || CHAR_MINUS === character) { | ||
if (CHOMPING_CLIP === chomping) { | ||
chomping = (CHAR_PLUS === character) ? CHOMPING_KEEP : CHOMPING_STRIP; | ||
} else { | ||
throwError('repeat of a chomping mode identifier'); | ||
} | ||
} else if (CHAR_DIGIT_ZERO <= character && character <= CHAR_DIGIT_NINE) { | ||
if (CHAR_DIGIT_ZERO === character) { | ||
throwError('bad explicit indentation width of a block scalar; it cannot be less than one'); | ||
} else if (!detectedIndent) { | ||
textIndent = nodeIndent + (character - CHAR_DIGIT_ONE); | ||
detectedIndent = true; | ||
} else { | ||
throwError('repeat of an indentation width identifier'); | ||
} | ||
} else { | ||
break; | ||
} | ||
} | ||
if (CHAR_SPACE === character || CHAR_TAB === character) { | ||
do { character = input.charCodeAt(++position); } | ||
while (CHAR_SPACE === character || CHAR_TAB === character); | ||
if (CHAR_SHARP === character) { | ||
do { character = input.charCodeAt(++position); } | ||
while (position < length && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character); | ||
} | ||
} | ||
while (position < length) { | ||
readLineBreak(); | ||
lineIndent = 0; | ||
while ((!detectedIndent || lineIndent < textIndent) && | ||
(CHAR_SPACE === character)) { | ||
lineIndent += 1; | ||
character = input.charCodeAt(++position); | ||
} | ||
if (!detectedIndent && lineIndent > textIndent) { | ||
textIndent = lineIndent; | ||
} | ||
if (CHAR_LINE_FEED === character || CHAR_CARRIAGE_RETURN === character) { | ||
emptyLines += 1; | ||
continue; | ||
} | ||
// End of the scalar. Perform the chomping. | ||
if (lineIndent < textIndent) { | ||
if (CHOMPING_KEEP === chomping) { | ||
result += common.repeat('\n', emptyLines + 1); | ||
} else if (CHOMPING_CLIP === chomping) { | ||
result += '\n'; | ||
} | ||
break; | ||
} | ||
detectedIndent = true; | ||
if (folding) { | ||
if (CHAR_SPACE === character || CHAR_TAB === character) { | ||
result += common.repeat('\n', emptyLines + 1); | ||
emptyLines = 1; | ||
} else if (0 === emptyLines) { | ||
result += ' '; | ||
emptyLines = 0; | ||
} else { | ||
result += common.repeat('\n', emptyLines); | ||
emptyLines = 0; | ||
} | ||
} else { | ||
result += common.repeat('\n', emptyLines + 1); | ||
emptyLines = 0; | ||
} | ||
captureStart = position; | ||
do { character = input.charCodeAt(++position); } | ||
while (position < length && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character); | ||
captureSegment(captureStart, position, false); | ||
} | ||
return true; | ||
} | ||
function readBlockSequence(nodeIndent) { | ||
var _line, | ||
_tag = tag, | ||
_result = [], | ||
following, | ||
detected = false; | ||
if (null !== anchor) { | ||
anchorMap[anchor] = _result; | ||
} | ||
while (position < length) { | ||
if (CHAR_MINUS !== character) { | ||
break; | ||
} | ||
following = input.charCodeAt(position + 1); | ||
if (CHAR_SPACE !== following && | ||
CHAR_TAB !== following && | ||
CHAR_LINE_FEED !== following && | ||
CHAR_CARRIAGE_RETURN !== following) { | ||
break; | ||
} | ||
detected = true; | ||
position += 1; | ||
character = following; | ||
if (skipSeparationSpace(true, -1)) { | ||
if (lineIndent <= nodeIndent) { | ||
_result.push(null); | ||
continue; | ||
} | ||
} | ||
_line = line; | ||
composeNode(nodeIndent, CONTEXT_BLOCK_IN, false, true); | ||
_result.push(result); | ||
skipSeparationSpace(true, -1); | ||
if ((line === _line || lineIndent > nodeIndent) && position < length) { | ||
throwError('bad indentation of a sequence entry'); | ||
} else if (lineIndent < nodeIndent) { | ||
break; | ||
} | ||
} | ||
if (detected) { | ||
tag = _tag; | ||
kind = KIND_ARRAY; | ||
result = _result; | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
function readBlockMapping(nodeIndent) { | ||
var following, | ||
allowCompact, | ||
_line, | ||
_tag = tag, | ||
_result = {}, | ||
keyTag = null, | ||
keyNode = null, | ||
valueNode = null, | ||
atExplicitKey = false, | ||
detected = false; | ||
if (null !== anchor) { | ||
anchorMap[anchor] = _result; | ||
} | ||
while (position < length) { | ||
following = input.charCodeAt(position + 1); | ||
_line = line; // Save the current line. | ||
if ((CHAR_QUESTION === character || | ||
CHAR_COLON === character) && | ||
(CHAR_SPACE === following || | ||
CHAR_TAB === following || | ||
CHAR_LINE_FEED === following || | ||
CHAR_CARRIAGE_RETURN === following)) { | ||
if (CHAR_QUESTION === character) { | ||
if (atExplicitKey) { | ||
storeMappingPair(_result, keyTag, keyNode, null); | ||
keyTag = keyNode = valueNode = null; | ||
} | ||
detected = true; | ||
atExplicitKey = true; | ||
allowCompact = true; | ||
} else if (atExplicitKey) { | ||
// i.e. CHAR_COLON === character after the explicit key. | ||
atExplicitKey = false; | ||
allowCompact = true; | ||
} else { | ||
throwError('incomplete explicit mapping pair; a key node is missed'); | ||
} | ||
position += 1; | ||
character = following; | ||
} else if (composeNode(nodeIndent, CONTEXT_FLOW_OUT, false, true)) { | ||
if (line === _line) { | ||
// TODO: Remove this cycle when the flow readers will consume | ||
// trailing whitespaces like the block readers. | ||
while (CHAR_SPACE === character || | ||
CHAR_TAB === character) { | ||
character = input.charCodeAt(++position); | ||
} | ||
if (CHAR_COLON === character) { | ||
character = input.charCodeAt(++position); | ||
if (CHAR_SPACE !== character && | ||
CHAR_TAB !== character && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character) { | ||
throwError('a whitespace character is expected after the key-value separator within a block mapping'); | ||
} | ||
if (atExplicitKey) { | ||
storeMappingPair(_result, keyTag, keyNode, null); | ||
keyTag = keyNode = valueNode = null; | ||
} | ||
detected = true; | ||
atExplicitKey = false; | ||
allowCompact = false; | ||
keyTag = tag; | ||
keyNode = result; | ||
} else if (detected) { | ||
throwError('can not read an implicit mapping pair; a colon is missed'); | ||
} else { | ||
tag = _tag; | ||
return true; // Keep the result of `composeNode`. | ||
} | ||
} else if (detected) { | ||
throwError('can not read a block mapping entry; a multiline key may not be an implicit key'); | ||
} else { | ||
tag = _tag; | ||
return true; // Keep the result of `composeNode`. | ||
} | ||
} else { | ||
break; | ||
} | ||
if (line === _line || lineIndent > nodeIndent) { | ||
if (composeNode(nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { | ||
if (atExplicitKey) { | ||
keyNode = result; | ||
} else { | ||
valueNode = result; | ||
} | ||
} | ||
if (!atExplicitKey) { | ||
storeMappingPair(_result, keyTag, keyNode, valueNode); | ||
keyTag = keyNode = valueNode = null; | ||
} | ||
// TODO: It is needed only for flow node readers. It should be removed | ||
// when the flow readers will consume trailing whitespaces as well as | ||
// the block readers. | ||
skipSeparationSpace(true, -1); | ||
} | ||
if (lineIndent > nodeIndent && position < length) { | ||
throwError('bad indentation of a mapping entry'); | ||
} else if (lineIndent < nodeIndent) { | ||
break; | ||
} | ||
} | ||
if (atExplicitKey) { | ||
storeMappingPair(_result, keyTag, keyNode, null); | ||
} | ||
if (detected) { | ||
tag = _tag; | ||
kind = KIND_OBJECT; | ||
result = _result; | ||
} | ||
return detected; | ||
} | ||
function readTagProperty() { | ||
var _position, | ||
isVerbatim = false, | ||
isNamed = false, | ||
tagHandle, | ||
tagName; | ||
if (CHAR_EXCLAMATION !== character) { | ||
return false; | ||
} | ||
if (null !== tag) { | ||
throwError('duplication of a tag property'); | ||
} | ||
character = input.charCodeAt(++position); | ||
if (CHAR_LESS_THAN === character) { | ||
isVerbatim = true; | ||
character = input.charCodeAt(++position); | ||
} else if (CHAR_EXCLAMATION === character) { | ||
isNamed = true; | ||
tagHandle = '!!'; | ||
character = input.charCodeAt(++position); | ||
} else { | ||
tagHandle = '!'; | ||
} | ||
_position = position; | ||
if (isVerbatim) { | ||
do { character = input.charCodeAt(++position); } | ||
while (position < length && CHAR_GREATER_THAN !== character); | ||
if (position < length) { | ||
tagName = input.slice(_position, position); | ||
character = input.charCodeAt(++position); | ||
} else { | ||
throwError('unexpected end of the stream within a verbatim tag'); | ||
} | ||
} else { | ||
while (position < length && | ||
CHAR_SPACE !== character && | ||
CHAR_TAB !== character && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character) { | ||
if (CHAR_EXCLAMATION === character) { | ||
if (!isNamed) { | ||
tagHandle = input.slice(_position - 1, position + 1); | ||
if (validate && !PATTERN_TAG_HANDLE.test(tagHandle)) { | ||
throwError('named tag handle cannot contain such characters'); | ||
} | ||
isNamed = true; | ||
_position = position + 1; | ||
} else { | ||
throwError('tag suffix cannot contain exclamation marks'); | ||
} | ||
} | ||
character = input.charCodeAt(++position); | ||
} | ||
tagName = input.slice(_position, position); | ||
if (validate && PATTERN_FLOW_INDICATORS.test(tagName)) { | ||
throwError('tag suffix cannot contain flow indicator characters'); | ||
} | ||
} | ||
if (validate && tagName && !PATTERN_TAG_URI.test(tagName)) { | ||
throwError('tag name cannot contain such characters: ' + tagName); | ||
} | ||
if (isVerbatim) { | ||
tag = tagName; | ||
} else if (_hasOwnProperty.call(tagMap, tagHandle)) { | ||
tag = tagMap[tagHandle] + tagName; | ||
} else if ('!' === tagHandle) { | ||
tag = '!' + tagName; | ||
} else if ('!!' === tagHandle) { | ||
tag = 'tag:yaml.org,2002:' + tagName; | ||
} else { | ||
throwError('undeclared tag handle "' + tagHandle + '"'); | ||
} | ||
return true; | ||
} | ||
function readAnchorProperty() { | ||
var _position; | ||
if (CHAR_AMPERSAND !== character) { | ||
return false; | ||
} | ||
if (null !== anchor) { | ||
throwError('duplication of an anchor property'); | ||
} | ||
character = input.charCodeAt(++position); | ||
_position = position; | ||
while (position < length && | ||
CHAR_SPACE !== character && | ||
CHAR_TAB !== character && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character && | ||
CHAR_COMMA !== character && | ||
CHAR_LEFT_SQUARE_BRACKET !== character && | ||
CHAR_RIGHT_SQUARE_BRACKET !== character && | ||
CHAR_LEFT_CURLY_BRACKET !== character && | ||
CHAR_RIGHT_CURLY_BRACKET !== character) { | ||
character = input.charCodeAt(++position); | ||
} | ||
if (position === _position) { | ||
throwError('name of an anchor node must contain at least one character'); | ||
} | ||
anchor = input.slice(_position, position); | ||
return true; | ||
} | ||
function readAlias() { | ||
var _position, alias; | ||
if (CHAR_ASTERISK !== character) { | ||
return false; | ||
} | ||
character = input.charCodeAt(++position); | ||
_position = position; | ||
while (position < length && | ||
CHAR_SPACE !== character && | ||
CHAR_TAB !== character && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character && | ||
CHAR_COMMA !== character && | ||
CHAR_LEFT_SQUARE_BRACKET !== character && | ||
CHAR_RIGHT_SQUARE_BRACKET !== character && | ||
CHAR_LEFT_CURLY_BRACKET !== character && | ||
CHAR_RIGHT_CURLY_BRACKET !== character) { | ||
character = input.charCodeAt(++position); | ||
} | ||
if (position === _position) { | ||
throwError('name of an alias node must contain at least one character'); | ||
} | ||
alias = input.slice(_position, position); | ||
if (!anchorMap.hasOwnProperty(alias)) { | ||
throwError('unidentified alias "' + alias + '"'); | ||
} | ||
result = anchorMap[alias]; | ||
skipSeparationSpace(true, -1); | ||
return true; | ||
} | ||
function composeNode(parentIndent, nodeContext, allowToSeek, allowCompact) { | ||
var allowBlockStyles, | ||
allowBlockScalars, | ||
allowBlockCollections, | ||
atNewLine = false, | ||
isIndented = true, | ||
hasContent = false, | ||
typeIndex, | ||
typeQuantity, | ||
type, | ||
typeLoader, | ||
flowIndent, | ||
blockIndent, | ||
_result; | ||
tag = null; | ||
anchor = null; | ||
kind = null; | ||
result = null; | ||
allowBlockStyles = allowBlockScalars = allowBlockCollections = | ||
CONTEXT_BLOCK_OUT === nodeContext || | ||
CONTEXT_BLOCK_IN === nodeContext; | ||
if (allowToSeek) { | ||
if (skipSeparationSpace(true, -1)) { | ||
atNewLine = true; | ||
if (lineIndent === parentIndent) { | ||
isIndented = false; | ||
} else if (lineIndent > parentIndent) { | ||
isIndented = true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
} | ||
if (isIndented) { | ||
while (readTagProperty() || readAnchorProperty()) { | ||
if (skipSeparationSpace(true, -1)) { | ||
atNewLine = true; | ||
if (lineIndent > parentIndent) { | ||
isIndented = true; | ||
allowBlockCollections = allowBlockStyles; | ||
} else if (lineIndent === parentIndent) { | ||
isIndented = false; | ||
allowBlockCollections = allowBlockStyles; | ||
} else { | ||
return true; | ||
} | ||
} else { | ||
allowBlockCollections = false; | ||
} | ||
} | ||
} | ||
if (allowBlockCollections) { | ||
allowBlockCollections = atNewLine || allowCompact; | ||
} | ||
if (isIndented || CONTEXT_BLOCK_OUT === nodeContext) { | ||
if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { | ||
flowIndent = parentIndent; | ||
} else { | ||
flowIndent = parentIndent + 1; | ||
} | ||
blockIndent = position - lineStart; | ||
if (isIndented) { | ||
if (allowBlockCollections && | ||
(readBlockSequence(blockIndent) || | ||
readBlockMapping(blockIndent)) || | ||
readFlowCollection(flowIndent)) { | ||
hasContent = true; | ||
} else { | ||
if ((allowBlockScalars && readBlockScalar(flowIndent)) || | ||
readSingleQuotedScalar(flowIndent) || | ||
readDoubleQuotedScalar(flowIndent)) { | ||
hasContent = true; | ||
} else if (readAlias()) { | ||
hasContent = true; | ||
if (null !== tag || null !== anchor) { | ||
throwError('alias node should not have any properties'); | ||
} | ||
} else if (readPlainScalar(flowIndent, CONTEXT_FLOW_IN === nodeContext)) { | ||
hasContent = true; | ||
if (null === tag) { | ||
tag = '?'; | ||
} | ||
} | ||
if (null !== anchor) { | ||
anchorMap[anchor] = result; | ||
} | ||
} | ||
} else { | ||
hasContent = allowBlockCollections && readBlockSequence(blockIndent); | ||
} | ||
} | ||
if (null !== tag && '!' !== tag) { | ||
if ('?' === tag) { | ||
if (resolve) { | ||
for (typeIndex = 0, typeQuantity = implicitTypes.length; | ||
typeIndex < typeQuantity; | ||
typeIndex += 1) { | ||
type = implicitTypes[typeIndex]; | ||
// Implicit resolving is not allowed for non-scalar types, and '?' | ||
// non-specific tag is only assigned to plain scalars. So, it isn't | ||
// needed to check for 'kind' conformity. | ||
_result = type.loader.resolver(result, false); | ||
if (NIL !== _result) { | ||
tag = type.tag; | ||
result = _result; | ||
break; | ||
} | ||
} | ||
} | ||
} else if (_hasOwnProperty.call(typeMap, tag)) { | ||
typeLoader = typeMap[tag].loader; | ||
if (null !== result && typeLoader.kind !== kind) { | ||
throwError('unacceptable node kind for !<' + tag + '> tag; it should be "' + typeLoader.kind + '", not "' + kind + '"'); | ||
} | ||
if (typeLoader.resolver) { | ||
_result = typeLoader.resolver(result, true); | ||
if (NIL !== _result) { | ||
result = _result; | ||
} else { | ||
throwError('cannot resolve a node with !<' + tag + '> explicit tag'); | ||
} | ||
} | ||
} else { | ||
throwWarning('unknown tag !<' + tag + '>'); | ||
} | ||
} | ||
return null !== tag || null !== anchor || hasContent; | ||
} | ||
function readDocument() { | ||
var documentStart = position, | ||
_position, | ||
directiveName, | ||
directiveArgs, | ||
hasDirectives = false; | ||
version = null; | ||
checkLineBreaks = legacy; | ||
tagMap = {}; | ||
anchorMap = {}; | ||
while (position < length) { | ||
skipSeparationSpace(true, -1); | ||
if (lineIndent > 0 || CHAR_PERCENT !== character) { | ||
break; | ||
} | ||
hasDirectives = true; | ||
character = input.charCodeAt(++position); | ||
_position = position; | ||
while (position < length && | ||
CHAR_SPACE !== character && | ||
CHAR_TAB !== character && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character) { | ||
character = input.charCodeAt(++position); | ||
} | ||
directiveName = input.slice(_position, position); | ||
directiveArgs = []; | ||
if (directiveName.length < 1) { | ||
throwError('directive name must not be less than one character in length'); | ||
} | ||
while (position < length) { | ||
while (CHAR_SPACE === character || CHAR_TAB === character) { | ||
character = input.charCodeAt(++position); | ||
} | ||
if (CHAR_SHARP === character) { | ||
do { character = input.charCodeAt(++position); } | ||
while (position < length && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character); | ||
break; | ||
} | ||
if (CHAR_LINE_FEED === character || CHAR_CARRIAGE_RETURN === character) { | ||
break; | ||
} | ||
_position = position; | ||
while (position < length && | ||
CHAR_SPACE !== character && | ||
CHAR_TAB !== character && | ||
CHAR_LINE_FEED !== character && | ||
CHAR_CARRIAGE_RETURN !== character) { | ||
character = input.charCodeAt(++position); | ||
} | ||
directiveArgs.push(input.slice(_position, position)); | ||
} | ||
if (position < length) { | ||
readLineBreak(); | ||
} | ||
if (_hasOwnProperty.call(directiveHandlers, directiveName)) { | ||
directiveHandlers[directiveName](directiveName, directiveArgs); | ||
} else { | ||
throwWarning('unknown document directive "' + directiveName + '"'); | ||
} | ||
} | ||
skipSeparationSpace(true, -1); | ||
if (0 === lineIndent && | ||
CHAR_MINUS === character && | ||
CHAR_MINUS === input.charCodeAt(position + 1) && | ||
CHAR_MINUS === input.charCodeAt(position + 2)) { | ||
position += 3; | ||
character = input.charCodeAt(position); | ||
skipSeparationSpace(true, -1); | ||
} else if (hasDirectives) { | ||
throwError('directives end mark is expected'); | ||
} | ||
composeNode(lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); | ||
skipSeparationSpace(true, -1); | ||
if (validate && checkLineBreaks && | ||
PATTERN_NON_ASCII_LINE_BREAKS.test(input.slice(documentStart, position))) { | ||
throwWarning('non-ASCII line breaks are interpreted as content'); | ||
} | ||
output(result); | ||
if (position === lineStart && testDocumentSeparator()) { | ||
if (CHAR_DOT === character) { | ||
position += 3; | ||
character = input.charCodeAt(position); | ||
skipSeparationSpace(true, -1); | ||
} | ||
return; | ||
} | ||
if (position < length) { | ||
throwError('end of the stream or a document separator is expected'); | ||
} else { | ||
return; | ||
} | ||
} | ||
if (validate && PATTERN_NON_PRINTABLE.test(input)) { | ||
throwError('the stream contains non-printable characters'); | ||
} | ||
while (CHAR_SPACE === character) { | ||
lineIndent += 1; | ||
character = input.charCodeAt(++position); | ||
} | ||
while (position < length) { | ||
readDocument(); | ||
} | ||
} | ||
$$.extend(Loader.prototype, | ||
_reader.Reader.prototype, | ||
_scanner.Scanner.prototype, | ||
_parser.Parser.prototype, | ||
_composer.Composer.prototype, | ||
_constructor.Constructor.prototype, | ||
_resolver.Resolver.prototype); | ||
function load(input, settings) { | ||
var result = null, received = false; | ||
BaseLoader.addConstructor = function (tag, constructor) { | ||
_constructor.BaseConstructor.addConstructor(tag, constructor); | ||
}; | ||
function callback(data) { | ||
if (!received) { | ||
result = data; | ||
received = true; | ||
} else { | ||
throw new YAMLException('expected a single document in the stream, but found more'); | ||
} | ||
} | ||
loadAll(input, callback, settings); | ||
SafeLoader.addConstructor = function (tag, constructor) { | ||
_constructor.SafeConstructor.addConstructor(tag, constructor); | ||
}; | ||
return result; | ||
} | ||
Loader.addConstructor = function (tag, constructor) { | ||
_constructor.Constructor.addConstructor(tag, constructor); | ||
}; | ||
function safeLoadAll(input, output, settings) { | ||
loadAll(input, output, common.extend({ schema: SAFE_SCHEMA }, settings)); | ||
} | ||
module.exports.BaseLoader = BaseLoader; | ||
module.exports.SafeLoader = SafeLoader; | ||
module.exports.Loader = Loader; | ||
function safeLoad(input, settings) { | ||
return load(input, common.extend({ schema: SAFE_SCHEMA }, settings)); | ||
} | ||
module.exports.loadAll = loadAll; | ||
module.exports.load = load; | ||
module.exports.safeLoadAll = safeLoadAll; | ||
module.exports.safeLoad = safeLoad; |
{ | ||
"name" : "js-yaml", | ||
"version" : "1.0.3", | ||
"description" : "YAML 1.1 Parser", | ||
"keywords" : ["yaml", "parser", "pyyaml"], | ||
"version" : "2.0.0", | ||
"description" : "YAML 1.2 parser and serializer", | ||
"keywords" : ["yaml", "parser", "serializer", "pyyaml"], | ||
"homepage" : "https://github.com/nodeca/js-yaml", | ||
"author" : "Aleksey V Zapparov <ixti@member.fsf.org> (http://www.ixti.net/)", | ||
"author" : { | ||
"name" : "Dervus Grim", | ||
"email" : "dervus@lavabit.com" | ||
}, | ||
"contributors" : [ | ||
{ | ||
"name" : "Aleksey V Zapparov", | ||
"email" : "ixti@member.fsf.org", | ||
"url" : "http://www.ixti.net/" | ||
}, | ||
{ | ||
"name" : "Martin Grenfell", | ||
@@ -26,5 +35,5 @@ "email" : "martin.grenfell@gmail.com>", | ||
"dependencies" : { "argparse": "~ 0.1.3" }, | ||
"devDependencies" : { "vows": "~ 0.6.0" }, | ||
"dependencies" : { "argparse": "~ 0.1.11" }, | ||
"devDependencies" : { "mocha": "*" }, | ||
"engines" : { "node": ">= 0.6.0" } | ||
} |
221
README.md
@@ -1,3 +0,3 @@ | ||
JS-YAML - YAML 1.1 parser for JavaScript | ||
======================================== | ||
JS-YAML - YAML 1.2 parser and serializer for JavaScript | ||
======================================================= | ||
@@ -8,23 +8,24 @@ [![Build Status](https://secure.travis-ci.org/nodeca/js-yaml.png)](http://travis-ci.org/nodeca/js-yaml) | ||
This is a native port of [PyYAML](http://pyyaml.org/), the most advanced YAML parser. | ||
Now you can use all modern YAML feature right in JavaScript. Originally snapshoted | ||
version - PyYAML 3.10 (2011-05-30). | ||
This is an implementation of [YAML](http://yaml.org/), a human friendly data | ||
serialization language. Started as [PyYAML](http://pyyaml.org/) port, it was | ||
completely rewritten from scratch. Now it's very fast, and supports 1.2 spec. | ||
## Breaking changes in 0.3.x -> 1.0.x | ||
- `y`, `yes`, `n`, `no`, `on`, `off` are not converted to Booleans anymore. | ||
Decision to drop support of such "magic" was made after speaking with YAML | ||
core developers: from now on we try to keep as minimal subset of rules as | ||
possible to keep things obvious. Booleans are following YAML 1.2 core schema | ||
now: http://www.yaml.org/spec/1.2/spec.html#id2804923 | ||
- `require('file.yml')` now returns a single document (was array of documents) | ||
and throws an error when file contains multiple documents. That should improve | ||
switching between YAML <-> JSON. So `require('file.yml')` will give the same | ||
result as if it was `require('file.json')` now. | ||
- CLI tool `js-yaml` become part of `js-yaml` again. | ||
Breaking changes in 1.x.x -> 2.0.x | ||
---------------------------------- | ||
If your have not used __custom__ tags or loader classes - no changes needed. Just | ||
upgrade library and enjoy high parse speed. | ||
## Installation | ||
In other case, you should rewrite your tag constructors and custom loader | ||
classes, to conform new schema-based API. See | ||
[examples](https://github.com/nodeca/js-yaml/tree/master/examples) and | ||
[wiki](https://github.com/nodeca/js-yaml/wiki) for details. | ||
Note, that parser internals were completely rewritten. | ||
Installation | ||
------------ | ||
### YAML module for node.js | ||
@@ -45,20 +46,21 @@ | ||
##### Usage | ||
#### Usage | ||
usage: js-yaml [-h] [-v] [-c] [-j] [-t] file | ||
``` | ||
usage: js-yaml [-h] [-v] [-c] [-j] [-t] file | ||
Positional arguments: | ||
file File with YAML document(s) | ||
Positional arguments: | ||
file File with YAML document(s) | ||
Optional arguments: | ||
-h, --help Show this help message and exit. | ||
-v, --version Show program's version number and exit. | ||
-c, --compact Display errors in compact mode | ||
-j, --to-json Output a non-funky boring JSON | ||
-t, --trace Show stack trace on error | ||
Optional arguments: | ||
-h, --help Show this help message and exit. | ||
-v, --version Show program's version number and exit. | ||
-c, --compact Display errors in compact mode | ||
-j, --to-json Output a non-funky boring JSON | ||
-t, --trace Show stack trace on error | ||
``` | ||
### Bundled YAML library for browsers | ||
### bundled YAML library for browser | ||
``` html | ||
@@ -71,15 +73,18 @@ <script src="js-yaml.min.js"></script> | ||
Browser support is still buggy, and mostly done to run online demo. If you | ||
can help to improve browser compatibility and AMD support - rise pull request. | ||
Browser support was done mostly for online demo. If you find eny errors - feel | ||
free to send pull requests with fixes. Also note, that IE and other old browsers | ||
needs [es5-shims](https://github.com/kriskowal/es5-shim) to operate. | ||
**Support of oldIEs** and some other prehistoric browsers is possible using | ||
[es5-shims](https://github.com/kriskowal/es5-shim). Just include shims before | ||
jsyaml to use it with outdated browsers. | ||
API | ||
--- | ||
## API | ||
Here we cover the most 'useful' methods. If you need advanced details (creating | ||
your own tags), see [wiki](https://github.com/nodeca/js-yaml/wiki) and | ||
[examples](https://github.com/nodeca/js-yaml/tree/master/examples) for more | ||
info. | ||
JS-YAML automatically registers handlers for `.yml` and `.yaml` files. You can load them just with `require`. | ||
That's mostly equivalent to calling loadAll() on file handler ang gathering all documents into array. | ||
Just with one string! | ||
In node.js JS-YAML automatically registers handlers for `.yml` and `.yaml` | ||
files. You can load them just with `require`. That's mostly equivalent to | ||
calling `load()` on fetched content of a file. Just with one string! | ||
@@ -90,28 +95,38 @@ ``` javascript | ||
// Get document, or throw exception on error | ||
var doc = require('/home/ixti/example.yml'); | ||
console.log(doc); | ||
try { | ||
var doc = require('/home/ixti/example.yml'); | ||
console.log(doc); | ||
} catch (e) { | ||
console.log(e); | ||
} | ||
``` | ||
### load (string|buffer|file\_resource) | ||
### load (string [ , options ]) | ||
Parses source as single YAML document. Returns JS object or throws exception on error. | ||
Parses `string` as single YAML document. Returns a JavaScript object or throws | ||
`YAMLException` on error. | ||
This function does NOT understands multi-doc sources, it throws exception on those. | ||
NOTE: This function **does not** understands multi-document sources, it throws | ||
exception on those. | ||
options: | ||
- `filename` _(default: null)_ - string to be used as a file path in | ||
error/warning messages. | ||
- `strict` _(default - false)_ makes the loader to throw errors instead of | ||
warnings. | ||
- `schema` _(default: `DEFAULT_SCHEMA`)_ - specifies a schema to use. | ||
### loadAll (string, iterator [ , options ]) | ||
Same as `load()`, but understands multi-document sources and apply `iterator` to | ||
each document. | ||
``` javascript | ||
var yaml = require('js-yaml'); | ||
// pass the string | ||
fs.readFile('/home/ixti/example.yml', 'utf8', function (err, data) { | ||
if (err) { | ||
// handle error | ||
return; | ||
} | ||
try { | ||
console.log( yaml.load(data) ); | ||
} catch(e) { | ||
console.log(e); | ||
} | ||
yaml.loadAll(data, function (doc) { | ||
console.log(doc); | ||
}); | ||
@@ -121,43 +136,59 @@ ``` | ||
### loadAll (string|buffer|file\_resource, iterator) | ||
### safeLoad (string [ , options ]) | ||
Same as `Load`, but understands multi-doc sources and apply iterator to each document. | ||
Same as `load()` but uses `SAFE_SCHEMA` by default - only recommended tags of | ||
YAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`). | ||
``` javascript | ||
var yaml = require('js-yaml'); | ||
// pass the string | ||
fs.readFile('/home/ixti/example.yml', 'utf8', function (err, data) { | ||
if (err) { | ||
// handle error | ||
return; | ||
} | ||
### safeLoadAll (string, iterator [ , options ]) | ||
try { | ||
yaml.loadAll(data, function (doc) { | ||
console.log(doc); | ||
}); | ||
} catch(e) { | ||
console.log(e); | ||
} | ||
}); | ||
``` | ||
Same as `loadAll()` but uses `SAFE_SCHEMA` by default - only recommended tags of | ||
YAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`). | ||
### safeLoad (string|buffer|file\_resource) | ||
### dump (object [ , options ]) | ||
Same as `load()` but uses _safe_ schema - only recommended tags of YAML | ||
specification (no JavaScript-specific tags, e.g. `!!js/regexp`). | ||
Serializes `object` as YAML document. | ||
options: | ||
### safeLoadAll (string|buffer|file\_resource, iterator) | ||
- `indent` _(default: 2)_ - indentation width to use (in spaces). | ||
- `flowLevel` (default: -1) - specifies level of nesting, when to switch from | ||
block to flow style for collections. -1 means block style everwhere | ||
- `styles` - "tag" => "style" map. Each tag may have own set of styles. | ||
- `schema` _(default: `DEFAULT_SCHEMA`)_ specifies a schema to use. | ||
Same as `loadAll()` but uses _safe_ schema - only recommended tags of YAML | ||
specification (no JavaScript-specific tags, e.g. `!!js/regexp`). | ||
styles: | ||
``` none | ||
!!null | ||
"canonical" => "~" | ||
## JavaScript YAML tags scheme | ||
!!int | ||
"binary" => "0b1", "0b101010", "0b1110001111010" | ||
"octal" => "01", "052", "016172" | ||
"decimal" => "1", "42", "7290" | ||
"hexadecimal" => "0x1", "0x2A", "0x1C7A" | ||
!!null, !!bool, !!float | ||
"lowercase" => "null", "true", "false", ".nan", '.inf' | ||
"uppercase" => "NULL", "TRUE", "FALSE", ".NAN", '.INF' | ||
"camelcase" => "Null", "True", "False", ".NaN", '.Inf' | ||
``` | ||
By default, !!int uses `decimal`, and !!null, !!bool, !!float use `lowercase`. | ||
### safeDump (object [ , options ]) | ||
Same as `dump()` but uses `SAFE_SCHEMA` by default - only recommended tags of | ||
YAML specification (no JavaScript-specific tags, e.g. `!!js/regexp`). | ||
Supported YAML types | ||
-------------------- | ||
The list of standard YAML tags and corresponding JavaScipt types. See also | ||
[YAML Tag Discussion](http://pyyaml.org/wiki/YAMLTagDiscussion) and [Yaml Types](http://yaml.org/type/). | ||
[YAML tag discussion](http://pyyaml.org/wiki/YAMLTagDiscussion) and | ||
[YAML types repository](http://yaml.org/type/). | ||
@@ -187,6 +218,10 @@ ``` | ||
### Caveats | ||
## Caveats | ||
Note, that you use arrays or objects as key in JS-YAML. JS do not allows objects | ||
or array as keys, and stringifies them at the moment of adding them. | ||
or array as keys, and stringifies (by calling .toString method) them at the | ||
moment of adding them. | ||
@@ -202,10 +237,20 @@ ``` yaml | ||
=> | ||
``` javascript | ||
{ "": ["baz"], "[object Object]": ["baz", "baz"] } | ||
{ "foo,bar": ["baz"], "[object Object]": ["baz", "baz"] } | ||
``` | ||
Also, reading of properties on implicit block mapping keys is not supported yet. | ||
So, the following YAML document cannot be loaded. | ||
``` yaml | ||
&anchor foo: | ||
foo: bar | ||
*anchor: duplicate key | ||
baz: bat | ||
*anchor: duplicate key | ||
``` | ||
## License | ||
View the [LICENSE](https://github.com/nodeca/js-yaml/blob/master/LICENSE) file (MIT). | ||
View the [LICENSE](https://github.com/nodeca/js-yaml/blob/master/LICENSE) file | ||
(MIT). |
'use strict'; | ||
/*global it */ | ||
var assert = require('assert'); | ||
require('../../lib/js-yaml'); | ||
var Assert = require('assert'); | ||
var source = __dirname + '/data/issue-17.yml'; | ||
it('#17: Non-specific "!" tags should resolve to !!str', function () { | ||
var data = require('./data/issue-17.yml'); | ||
module.exports = require('../helper').issue({ | ||
title: "#17: Non-specific `!` tags should resolve to !!str", | ||
fixed: true, | ||
test: function () { | ||
var str = require(source); | ||
Assert.equal('string', typeof str); | ||
} | ||
assert.equal(typeof data, 'string'); | ||
}); |
'use strict'; | ||
/*global it */ | ||
var assert = require('assert'); | ||
require('../../lib/js-yaml'); | ||
var Assert = require('assert'); | ||
var source = __dirname + '/data/issue-19.yml'; | ||
it('#19: Timestamp parsing is one month off', function () { | ||
var data = require('./data/issue-19.yml'); | ||
module.exports = require('../helper').issue({ | ||
title: "#19: Timestamp parsing is one month off", | ||
fixed: true, | ||
test: function () { | ||
var doc = require(source), expected = Date.UTC(2011, 11, 24); | ||
// JS month starts with 0 (0 => Jan, 1 => Feb, ...) | ||
Assert.equal(doc.xmas.getTime(), expected); | ||
} | ||
// JS month starts with 0 (0 => Jan, 1 => Feb, ...) | ||
assert.equal(data.xmas.getTime(), Date.UTC(2011, 11, 24)); | ||
}); |
'use strict'; | ||
/*global it */ | ||
var assert = require('assert'); | ||
require('../../lib/js-yaml'); | ||
var Assert = require('assert'); | ||
var source = __dirname + '/data/issue-26.yml'; | ||
it('#26: should convert new line into white space', function () { | ||
var data = require('./data/issue-26.yml'); | ||
module.exports = require('../helper').issue({ | ||
title: "#26: should convert new line into white space", | ||
fixed: true, | ||
test: function () { | ||
var doc = require(source); | ||
Assert.equal(doc.test, 'a b c\n'); | ||
} | ||
assert.equal(data.test, 'a b c\n'); | ||
}); |
'use strict'; | ||
/*global it */ | ||
var assert = require('assert'); | ||
require('../../lib/js-yaml'); | ||
var Assert = require('assert'); | ||
var source = __dirname + '/data/issue-33.yml'; | ||
module.exports = require('../helper').issue({ | ||
title: "#33: refactor compact variant of MarkedYAMLError.toString", | ||
fixed: true, | ||
test: function () { | ||
try { | ||
require(source); | ||
} catch (err) { | ||
Assert.equal( | ||
err.toString(true), | ||
'Error on line 1, col 12: expected <block end>, but found undefined' | ||
); | ||
} | ||
} | ||
it('#33: refactor compact variant of MarkedYAMLError.toString', function () { | ||
assert.throws( | ||
function () { require('./data/issue-33.yml'); }, | ||
"require('issue-33.yml') should throw, but it does not"); | ||
}); |
'use strict'; | ||
/*global it */ | ||
var assert = require('assert'); | ||
require('../../lib/js-yaml'); | ||
var Assert = require('assert'); | ||
var source = __dirname + '/data/issue-46.yml'; | ||
it('#46: Timestamps are incorrectly parsed in local time', function () { | ||
var data = require('./data/issue-46.yml'), date1, date2; | ||
date1 = data.date1; // date1: 2010-10-20T20:45:00Z | ||
assert.equal(date1.getUTCFullYear(), 2010, 'year'); | ||
assert.equal(date1.getUTCMonth(), 9, 'month'); | ||
assert.equal(date1.getUTCDate(), 20, 'date'); | ||
assert.equal(date1.getUTCHours(), 20); | ||
assert.equal(date1.getUTCMinutes(), 45); | ||
assert.equal(date1.getUTCSeconds(), 0); | ||
module.exports = require('../helper').issue({ | ||
title: "#46: Timestamps are incorrectly parsed in local time", | ||
fixed: true, | ||
test: function () { | ||
var data = require(source); | ||
var d1 = data.date1; // date1: 2010-10-20T20:45:00Z | ||
Assert.equal(d1.getUTCFullYear(), 2010, 'year'); | ||
Assert.equal(d1.getUTCMonth(), 9, 'month'); | ||
Assert.equal(d1.getUTCDate(), 20, 'date'); | ||
Assert.equal(d1.getUTCHours(), 20); | ||
Assert.equal(d1.getUTCMinutes(), 45); | ||
Assert.equal(d1.getUTCSeconds(), 0); | ||
var d2 = data.date2; // date2: 2010-10-20T20:45:00+0100 | ||
Assert.equal(d2.getUTCFullYear(), 2010, 'year'); | ||
Assert.equal(d2.getUTCMonth(), 9, 'month'); | ||
Assert.equal(d2.getUTCDate(), 20, 'date'); | ||
Assert.equal(d2.getUTCHours(), 19); | ||
Assert.equal(d2.getUTCMinutes(), 45); | ||
Assert.equal(d2.getUTCSeconds(), 0); | ||
} | ||
date2 = data.date2; // date2: 2010-10-20T20:45:00+0100 | ||
assert.equal(date2.getUTCFullYear(), 2010, 'year'); | ||
assert.equal(date2.getUTCMonth(), 9, 'month'); | ||
assert.equal(date2.getUTCDate(), 20, 'date'); | ||
assert.equal(date2.getUTCHours(), 19); | ||
assert.equal(date2.getUTCMinutes(), 45); | ||
assert.equal(date2.getUTCSeconds(), 0); | ||
}); |
'use strict'; | ||
/*global it */ | ||
var assert = require('assert'); | ||
require('../../lib/js-yaml'); | ||
var Assert = require('assert'); | ||
var source = __dirname + '/data/issue-54.yml'; | ||
it("#54: Incorrect utf-8 handling on require('file.yaml')", function () { | ||
var data = require('./data/issue-54.yml'), | ||
expected = '', | ||
index; | ||
// | ||
// document is an array of 40 elements | ||
// each element is a string of 100 `у` (Russian letter) chars | ||
// | ||
for (index = 0; index <= 100; index += 1) { | ||
expected += 'у'; | ||
} | ||
module.exports = require('../helper').issue({ | ||
title: "#54: Incorrect utf-8 handling on require('file.yaml')", | ||
fixed: true, | ||
test: function () { | ||
var data = require(source), expected = '', i; | ||
// | ||
// document is an array of 40 elements | ||
// each element is a string of 100 `у` (Russian letter) chars | ||
// | ||
for (i = 0; i <= 100; i++) { | ||
expected += 'у'; | ||
} | ||
// | ||
// make sure none of the strings were corrupted. | ||
// | ||
for (i = 0; i < 40; i++) { | ||
Assert.equal(data[i], expected, 'Line ' + i + ' is corrupted'); | ||
} | ||
// | ||
// make sure none of the strings were corrupted. | ||
// | ||
for (index = 0; index < 40; index += 1) { | ||
assert.equal(data[index], expected, ('Line ' + index + ' is corrupted')); | ||
} | ||
}); |
'use strict'; | ||
/*global it */ | ||
var assert = require('assert'); | ||
require('../../lib/js-yaml'); | ||
var Assert = require('assert'); | ||
var source = __dirname + '/data/issue-8.yml'; | ||
module.exports = require('../helper').issue({ | ||
title: "#8: Parse failed when no document start present", | ||
fixed: true, | ||
test: function () { | ||
Assert.doesNotThrow(function () { | ||
require(source); | ||
}, TypeError); | ||
} | ||
it('#8: Parse failed when no document start present', function () { | ||
assert.doesNotThrow(function () { | ||
require('./data/issue-8.yml'); | ||
}, TypeError); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
250
9
175032
345
3735
2
Updatedargparse@~ 0.1.11