This commit is contained in:
56
node_modules/yamljs/src/Dumper.coffee
generated
vendored
Normal file
56
node_modules/yamljs/src/Dumper.coffee
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
Utils = require './Utils'
|
||||
Inline = require './Inline'
|
||||
|
||||
# Dumper dumps JavaScript variables to YAML strings.
|
||||
#
|
||||
class Dumper
|
||||
|
||||
# The amount of spaces to use for indentation of nested nodes.
|
||||
@indentation: 4
|
||||
|
||||
|
||||
# Dumps a JavaScript value to YAML.
|
||||
#
|
||||
# @param [Object] input The JavaScript value
|
||||
# @param [Integer] inline The level where you switch to inline YAML
|
||||
# @param [Integer] indent The level of indentation (used internally)
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
|
||||
# @param [Function] objectEncoder A function to serialize custom objects, null otherwise
|
||||
#
|
||||
# @return [String] The YAML representation of the JavaScript value
|
||||
#
|
||||
dump: (input, inline = 0, indent = 0, exceptionOnInvalidType = false, objectEncoder = null) ->
|
||||
output = ''
|
||||
prefix = (if indent then Utils.strRepeat(' ', indent) else '')
|
||||
|
||||
if inline <= 0 or typeof(input) isnt 'object' or input instanceof Date or Utils.isEmpty(input)
|
||||
output += prefix + Inline.dump(input, exceptionOnInvalidType, objectEncoder)
|
||||
|
||||
else
|
||||
if input instanceof Array
|
||||
for value in input
|
||||
willBeInlined = (inline - 1 <= 0 or typeof(value) isnt 'object' or Utils.isEmpty(value))
|
||||
|
||||
output +=
|
||||
prefix +
|
||||
'-' +
|
||||
(if willBeInlined then ' ' else "\n") +
|
||||
@dump(value, inline - 1, (if willBeInlined then 0 else indent + @indentation), exceptionOnInvalidType, objectEncoder) +
|
||||
(if willBeInlined then "\n" else '')
|
||||
|
||||
else
|
||||
for key, value of input
|
||||
willBeInlined = (inline - 1 <= 0 or typeof(value) isnt 'object' or Utils.isEmpty(value))
|
||||
|
||||
output +=
|
||||
prefix +
|
||||
Inline.dump(key, exceptionOnInvalidType, objectEncoder) + ':' +
|
||||
(if willBeInlined then ' ' else "\n") +
|
||||
@dump(value, inline - 1, (if willBeInlined then 0 else indent + @indentation), exceptionOnInvalidType, objectEncoder) +
|
||||
(if willBeInlined then "\n" else '')
|
||||
|
||||
return output
|
||||
|
||||
|
||||
module.exports = Dumper
|
80
node_modules/yamljs/src/Escaper.coffee
generated
vendored
Normal file
80
node_modules/yamljs/src/Escaper.coffee
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
Pattern = require './Pattern'
|
||||
|
||||
# Escaper encapsulates escaping rules for single
|
||||
# and double-quoted YAML strings.
|
||||
class Escaper
|
||||
|
||||
# Mapping arrays for escaping a double quoted string. The backslash is
|
||||
# first to ensure proper escaping.
|
||||
@LIST_ESCAPEES: ['\\', '\\\\', '\\"', '"',
|
||||
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
|
||||
"\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f",
|
||||
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
|
||||
"\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
|
||||
(ch = String.fromCharCode)(0x0085), ch(0x00A0), ch(0x2028), ch(0x2029)]
|
||||
@LIST_ESCAPED: ['\\\\', '\\"', '\\"', '\\"',
|
||||
"\\0", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a",
|
||||
"\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "\\x0e", "\\x0f",
|
||||
"\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17",
|
||||
"\\x18", "\\x19", "\\x1a", "\\e", "\\x1c", "\\x1d", "\\x1e", "\\x1f",
|
||||
"\\N", "\\_", "\\L", "\\P"]
|
||||
|
||||
@MAPPING_ESCAPEES_TO_ESCAPED: do =>
|
||||
mapping = {}
|
||||
for i in [0...@LIST_ESCAPEES.length]
|
||||
mapping[@LIST_ESCAPEES[i]] = @LIST_ESCAPED[i]
|
||||
return mapping
|
||||
|
||||
# Characters that would cause a dumped string to require double quoting.
|
||||
@PATTERN_CHARACTERS_TO_ESCAPE: new Pattern '[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9'
|
||||
|
||||
# Other precompiled patterns
|
||||
@PATTERN_MAPPING_ESCAPEES: new Pattern @LIST_ESCAPEES.join('|').split('\\').join('\\\\')
|
||||
@PATTERN_SINGLE_QUOTING: new Pattern '[\\s\'":{}[\\],&*#?]|^[-?|<>=!%@`]'
|
||||
|
||||
|
||||
|
||||
# Determines if a JavaScript value would require double quoting in YAML.
|
||||
#
|
||||
# @param [String] value A JavaScript value value
|
||||
#
|
||||
# @return [Boolean] true if the value would require double quotes.
|
||||
#
|
||||
@requiresDoubleQuoting: (value) ->
|
||||
return @PATTERN_CHARACTERS_TO_ESCAPE.test value
|
||||
|
||||
|
||||
# Escapes and surrounds a JavaScript value with double quotes.
|
||||
#
|
||||
# @param [String] value A JavaScript value
|
||||
#
|
||||
# @return [String] The quoted, escaped string
|
||||
#
|
||||
@escapeWithDoubleQuotes: (value) ->
|
||||
result = @PATTERN_MAPPING_ESCAPEES.replace value, (str) =>
|
||||
return @MAPPING_ESCAPEES_TO_ESCAPED[str]
|
||||
return '"'+result+'"'
|
||||
|
||||
|
||||
# Determines if a JavaScript value would require single quoting in YAML.
|
||||
#
|
||||
# @param [String] value A JavaScript value
|
||||
#
|
||||
# @return [Boolean] true if the value would require single quotes.
|
||||
#
|
||||
@requiresSingleQuoting: (value) ->
|
||||
return @PATTERN_SINGLE_QUOTING.test value
|
||||
|
||||
|
||||
# Escapes and surrounds a JavaScript value with single quotes.
|
||||
#
|
||||
# @param [String] value A JavaScript value
|
||||
#
|
||||
# @return [String] The quoted, escaped string
|
||||
#
|
||||
@escapeWithSingleQuotes: (value) ->
|
||||
return "'"+value.replace(/'/g, "''")+"'"
|
||||
|
||||
|
||||
module.exports = Escaper
|
12
node_modules/yamljs/src/Exception/DumpException.coffee
generated
vendored
Normal file
12
node_modules/yamljs/src/Exception/DumpException.coffee
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
class DumpException extends Error
|
||||
|
||||
constructor: (@message, @parsedLine, @snippet) ->
|
||||
|
||||
toString: ->
|
||||
if @parsedLine? and @snippet?
|
||||
return '<DumpException> ' + @message + ' (line ' + @parsedLine + ': \'' + @snippet + '\')'
|
||||
else
|
||||
return '<DumpException> ' + @message
|
||||
|
||||
module.exports = DumpException
|
12
node_modules/yamljs/src/Exception/ParseException.coffee
generated
vendored
Normal file
12
node_modules/yamljs/src/Exception/ParseException.coffee
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
class ParseException extends Error
|
||||
|
||||
constructor: (@message, @parsedLine, @snippet) ->
|
||||
|
||||
toString: ->
|
||||
if @parsedLine? and @snippet?
|
||||
return '<ParseException> ' + @message + ' (line ' + @parsedLine + ': \'' + @snippet + '\')'
|
||||
else
|
||||
return '<ParseException> ' + @message
|
||||
|
||||
module.exports = ParseException
|
12
node_modules/yamljs/src/Exception/ParseMore.coffee
generated
vendored
Normal file
12
node_modules/yamljs/src/Exception/ParseMore.coffee
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
class ParseMore extends Error
|
||||
|
||||
constructor: (@message, @parsedLine, @snippet) ->
|
||||
|
||||
toString: ->
|
||||
if @parsedLine? and @snippet?
|
||||
return '<ParseMore> ' + @message + ' (line ' + @parsedLine + ': \'' + @snippet + '\')'
|
||||
else
|
||||
return '<ParseMore> ' + @message
|
||||
|
||||
module.exports = ParseMore
|
488
node_modules/yamljs/src/Inline.coffee
generated
vendored
Normal file
488
node_modules/yamljs/src/Inline.coffee
generated
vendored
Normal file
@@ -0,0 +1,488 @@
|
||||
|
||||
Pattern = require './Pattern'
|
||||
Unescaper = require './Unescaper'
|
||||
Escaper = require './Escaper'
|
||||
Utils = require './Utils'
|
||||
ParseException = require './Exception/ParseException'
|
||||
ParseMore = require './Exception/ParseMore'
|
||||
DumpException = require './Exception/DumpException'
|
||||
|
||||
# Inline YAML parsing and dumping
|
||||
class Inline
|
||||
|
||||
# Quoted string regular expression
|
||||
@REGEX_QUOTED_STRING: '(?:"(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\']*(?:\'\'[^\']*)*)\')'
|
||||
|
||||
# Pre-compiled patterns
|
||||
#
|
||||
@PATTERN_TRAILING_COMMENTS: new Pattern '^\\s*#.*$'
|
||||
@PATTERN_QUOTED_SCALAR: new Pattern '^'+@REGEX_QUOTED_STRING
|
||||
@PATTERN_THOUSAND_NUMERIC_SCALAR: new Pattern '^(-|\\+)?[0-9,]+(\\.[0-9]+)?$'
|
||||
@PATTERN_SCALAR_BY_DELIMITERS: {}
|
||||
|
||||
# Settings
|
||||
@settings: {}
|
||||
|
||||
|
||||
# Configure YAML inline.
|
||||
#
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
|
||||
# @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
|
||||
#
|
||||
@configure: (exceptionOnInvalidType = null, objectDecoder = null) ->
|
||||
# Update settings
|
||||
@settings.exceptionOnInvalidType = exceptionOnInvalidType
|
||||
@settings.objectDecoder = objectDecoder
|
||||
return
|
||||
|
||||
|
||||
# Converts a YAML string to a JavaScript object.
|
||||
#
|
||||
# @param [String] value A YAML string
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
|
||||
# @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
|
||||
#
|
||||
# @return [Object] A JavaScript object representing the YAML string
|
||||
#
|
||||
# @throw [ParseException]
|
||||
#
|
||||
@parse: (value, exceptionOnInvalidType = false, objectDecoder = null) ->
|
||||
# Update settings from last call of Inline.parse()
|
||||
@settings.exceptionOnInvalidType = exceptionOnInvalidType
|
||||
@settings.objectDecoder = objectDecoder
|
||||
|
||||
if not value?
|
||||
return ''
|
||||
|
||||
value = Utils.trim value
|
||||
|
||||
if 0 is value.length
|
||||
return ''
|
||||
|
||||
# Keep a context object to pass through static methods
|
||||
context = {exceptionOnInvalidType, objectDecoder, i: 0}
|
||||
|
||||
switch value.charAt(0)
|
||||
when '['
|
||||
result = @parseSequence value, context
|
||||
++context.i
|
||||
when '{'
|
||||
result = @parseMapping value, context
|
||||
++context.i
|
||||
else
|
||||
result = @parseScalar value, null, ['"', "'"], context
|
||||
|
||||
# Some comments are allowed at the end
|
||||
if @PATTERN_TRAILING_COMMENTS.replace(value[context.i..], '') isnt ''
|
||||
throw new ParseException 'Unexpected characters near "'+value[context.i..]+'".'
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# Dumps a given JavaScript variable to a YAML string.
|
||||
#
|
||||
# @param [Object] value The JavaScript variable to convert
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
|
||||
# @param [Function] objectEncoder A function to serialize custom objects, null otherwise
|
||||
#
|
||||
# @return [String] The YAML string representing the JavaScript object
|
||||
#
|
||||
# @throw [DumpException]
|
||||
#
|
||||
@dump: (value, exceptionOnInvalidType = false, objectEncoder = null) ->
|
||||
if not value?
|
||||
return 'null'
|
||||
type = typeof value
|
||||
if type is 'object'
|
||||
if value instanceof Date
|
||||
return value.toISOString()
|
||||
else if objectEncoder?
|
||||
result = objectEncoder value
|
||||
if typeof result is 'string' or result?
|
||||
return result
|
||||
return @dumpObject value
|
||||
if type is 'boolean'
|
||||
return (if value then 'true' else 'false')
|
||||
if Utils.isDigits(value)
|
||||
return (if type is 'string' then "'"+value+"'" else String(parseInt(value)))
|
||||
if Utils.isNumeric(value)
|
||||
return (if type is 'string' then "'"+value+"'" else String(parseFloat(value)))
|
||||
if type is 'number'
|
||||
return (if value is Infinity then '.Inf' else (if value is -Infinity then '-.Inf' else (if isNaN(value) then '.NaN' else value)))
|
||||
if Escaper.requiresDoubleQuoting value
|
||||
return Escaper.escapeWithDoubleQuotes value
|
||||
if Escaper.requiresSingleQuoting value
|
||||
return Escaper.escapeWithSingleQuotes value
|
||||
if '' is value
|
||||
return '""'
|
||||
if Utils.PATTERN_DATE.test value
|
||||
return "'"+value+"'";
|
||||
if value.toLowerCase() in ['null','~','true','false']
|
||||
return "'"+value+"'"
|
||||
# Default
|
||||
return value;
|
||||
|
||||
|
||||
# Dumps a JavaScript object to a YAML string.
|
||||
#
|
||||
# @param [Object] value The JavaScript object to dump
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
|
||||
# @param [Function] objectEncoder A function do serialize custom objects, null otherwise
|
||||
#
|
||||
# @return string The YAML string representing the JavaScript object
|
||||
#
|
||||
@dumpObject: (value, exceptionOnInvalidType, objectSupport = null) ->
|
||||
# Array
|
||||
if value instanceof Array
|
||||
output = []
|
||||
for val in value
|
||||
output.push @dump val
|
||||
return '['+output.join(', ')+']'
|
||||
|
||||
# Mapping
|
||||
else
|
||||
output = []
|
||||
for key, val of value
|
||||
output.push @dump(key)+': '+@dump(val)
|
||||
return '{'+output.join(', ')+'}'
|
||||
|
||||
|
||||
# Parses a scalar to a YAML string.
|
||||
#
|
||||
# @param [Object] scalar
|
||||
# @param [Array] delimiters
|
||||
# @param [Array] stringDelimiters
|
||||
# @param [Object] context
|
||||
# @param [Boolean] evaluate
|
||||
#
|
||||
# @return [String] A YAML string
|
||||
#
|
||||
# @throw [ParseException] When malformed inline YAML string is parsed
|
||||
#
|
||||
@parseScalar: (scalar, delimiters = null, stringDelimiters = ['"', "'"], context = null, evaluate = true) ->
|
||||
unless context?
|
||||
context = exceptionOnInvalidType: @settings.exceptionOnInvalidType, objectDecoder: @settings.objectDecoder, i: 0
|
||||
{i} = context
|
||||
|
||||
if scalar.charAt(i) in stringDelimiters
|
||||
# Quoted scalar
|
||||
output = @parseQuotedScalar scalar, context
|
||||
{i} = context
|
||||
|
||||
if delimiters?
|
||||
tmp = Utils.ltrim scalar[i..], ' '
|
||||
if not(tmp.charAt(0) in delimiters)
|
||||
throw new ParseException 'Unexpected characters ('+scalar[i..]+').'
|
||||
|
||||
else
|
||||
# "normal" string
|
||||
if not delimiters
|
||||
output = scalar[i..]
|
||||
i += output.length
|
||||
|
||||
# Remove comments
|
||||
strpos = output.indexOf ' #'
|
||||
if strpos isnt -1
|
||||
output = Utils.rtrim output[0...strpos]
|
||||
|
||||
else
|
||||
joinedDelimiters = delimiters.join('|')
|
||||
pattern = @PATTERN_SCALAR_BY_DELIMITERS[joinedDelimiters]
|
||||
unless pattern?
|
||||
pattern = new Pattern '^(.+?)('+joinedDelimiters+')'
|
||||
@PATTERN_SCALAR_BY_DELIMITERS[joinedDelimiters] = pattern
|
||||
if match = pattern.exec scalar[i..]
|
||||
output = match[1]
|
||||
i += output.length
|
||||
else
|
||||
throw new ParseException 'Malformed inline YAML string ('+scalar+').'
|
||||
|
||||
|
||||
if evaluate
|
||||
output = @evaluateScalar output, context
|
||||
|
||||
context.i = i
|
||||
return output
|
||||
|
||||
|
||||
# Parses a quoted scalar to YAML.
|
||||
#
|
||||
# @param [String] scalar
|
||||
# @param [Object] context
|
||||
#
|
||||
# @return [String] A YAML string
|
||||
#
|
||||
# @throw [ParseMore] When malformed inline YAML string is parsed
|
||||
#
|
||||
@parseQuotedScalar: (scalar, context) ->
|
||||
{i} = context
|
||||
|
||||
unless match = @PATTERN_QUOTED_SCALAR.exec scalar[i..]
|
||||
throw new ParseMore 'Malformed inline YAML string ('+scalar[i..]+').'
|
||||
|
||||
output = match[0].substr(1, match[0].length - 2)
|
||||
|
||||
if '"' is scalar.charAt(i)
|
||||
output = Unescaper.unescapeDoubleQuotedString output
|
||||
else
|
||||
output = Unescaper.unescapeSingleQuotedString output
|
||||
|
||||
i += match[0].length
|
||||
|
||||
context.i = i
|
||||
return output
|
||||
|
||||
|
||||
# Parses a sequence to a YAML string.
|
||||
#
|
||||
# @param [String] sequence
|
||||
# @param [Object] context
|
||||
#
|
||||
# @return [String] A YAML string
|
||||
#
|
||||
# @throw [ParseMore] When malformed inline YAML string is parsed
|
||||
#
|
||||
@parseSequence: (sequence, context) ->
|
||||
output = []
|
||||
len = sequence.length
|
||||
{i} = context
|
||||
i += 1
|
||||
|
||||
# [foo, bar, ...]
|
||||
while i < len
|
||||
context.i = i
|
||||
switch sequence.charAt(i)
|
||||
when '['
|
||||
# Nested sequence
|
||||
output.push @parseSequence sequence, context
|
||||
{i} = context
|
||||
when '{'
|
||||
# Nested mapping
|
||||
output.push @parseMapping sequence, context
|
||||
{i} = context
|
||||
when ']'
|
||||
return output
|
||||
when ',', ' ', "\n"
|
||||
# Do nothing
|
||||
else
|
||||
isQuoted = (sequence.charAt(i) in ['"', "'"])
|
||||
value = @parseScalar sequence, [',', ']'], ['"', "'"], context
|
||||
{i} = context
|
||||
|
||||
if not(isQuoted) and typeof(value) is 'string' and (value.indexOf(': ') isnt -1 or value.indexOf(":\n") isnt -1)
|
||||
# Embedded mapping?
|
||||
try
|
||||
value = @parseMapping '{'+value+'}'
|
||||
catch e
|
||||
# No, it's not
|
||||
|
||||
|
||||
output.push value
|
||||
|
||||
--i
|
||||
|
||||
++i
|
||||
|
||||
throw new ParseMore 'Malformed inline YAML string '+sequence
|
||||
|
||||
|
||||
# Parses a mapping to a YAML string.
|
||||
#
|
||||
# @param [String] mapping
|
||||
# @param [Object] context
|
||||
#
|
||||
# @return [String] A YAML string
|
||||
#
|
||||
# @throw [ParseMore] When malformed inline YAML string is parsed
|
||||
#
|
||||
@parseMapping: (mapping, context) ->
|
||||
output = {}
|
||||
len = mapping.length
|
||||
{i} = context
|
||||
i += 1
|
||||
|
||||
# {foo: bar, bar:foo, ...}
|
||||
shouldContinueWhileLoop = false
|
||||
while i < len
|
||||
context.i = i
|
||||
switch mapping.charAt(i)
|
||||
when ' ', ',', "\n"
|
||||
++i
|
||||
context.i = i
|
||||
shouldContinueWhileLoop = true
|
||||
when '}'
|
||||
return output
|
||||
|
||||
if shouldContinueWhileLoop
|
||||
shouldContinueWhileLoop = false
|
||||
continue
|
||||
|
||||
# Key
|
||||
key = @parseScalar mapping, [':', ' ', "\n"], ['"', "'"], context, false
|
||||
{i} = context
|
||||
|
||||
# Value
|
||||
done = false
|
||||
|
||||
while i < len
|
||||
context.i = i
|
||||
switch mapping.charAt(i)
|
||||
when '['
|
||||
# Nested sequence
|
||||
value = @parseSequence mapping, context
|
||||
{i} = context
|
||||
# Spec: Keys MUST be unique; first one wins.
|
||||
# Parser cannot abort this mapping earlier, since lines
|
||||
# are processed sequentially.
|
||||
if output[key] == undefined
|
||||
output[key] = value
|
||||
done = true
|
||||
when '{'
|
||||
# Nested mapping
|
||||
value = @parseMapping mapping, context
|
||||
{i} = context
|
||||
# Spec: Keys MUST be unique; first one wins.
|
||||
# Parser cannot abort this mapping earlier, since lines
|
||||
# are processed sequentially.
|
||||
if output[key] == undefined
|
||||
output[key] = value
|
||||
done = true
|
||||
when ':', ' ', "\n"
|
||||
# Do nothing
|
||||
else
|
||||
value = @parseScalar mapping, [',', '}'], ['"', "'"], context
|
||||
{i} = context
|
||||
# Spec: Keys MUST be unique; first one wins.
|
||||
# Parser cannot abort this mapping earlier, since lines
|
||||
# are processed sequentially.
|
||||
if output[key] == undefined
|
||||
output[key] = value
|
||||
done = true
|
||||
--i
|
||||
|
||||
++i
|
||||
|
||||
if done
|
||||
break
|
||||
|
||||
throw new ParseMore 'Malformed inline YAML string '+mapping
|
||||
|
||||
|
||||
# Evaluates scalars and replaces magic values.
|
||||
#
|
||||
# @param [String] scalar
|
||||
#
|
||||
# @return [String] A YAML string
|
||||
#
|
||||
@evaluateScalar: (scalar, context) ->
|
||||
scalar = Utils.trim(scalar)
|
||||
scalarLower = scalar.toLowerCase()
|
||||
|
||||
switch scalarLower
|
||||
when 'null', '', '~'
|
||||
return null
|
||||
when 'true'
|
||||
return true
|
||||
when 'false'
|
||||
return false
|
||||
when '.inf'
|
||||
return Infinity
|
||||
when '.nan'
|
||||
return NaN
|
||||
when '-.inf'
|
||||
return Infinity
|
||||
else
|
||||
firstChar = scalarLower.charAt(0)
|
||||
switch firstChar
|
||||
when '!'
|
||||
firstSpace = scalar.indexOf(' ')
|
||||
if firstSpace is -1
|
||||
firstWord = scalarLower
|
||||
else
|
||||
firstWord = scalarLower[0...firstSpace]
|
||||
switch firstWord
|
||||
when '!'
|
||||
if firstSpace isnt -1
|
||||
return parseInt @parseScalar(scalar[2..])
|
||||
return null
|
||||
when '!str'
|
||||
return Utils.ltrim scalar[4..]
|
||||
when '!!str'
|
||||
return Utils.ltrim scalar[5..]
|
||||
when '!!int'
|
||||
return parseInt(@parseScalar(scalar[5..]))
|
||||
when '!!bool'
|
||||
return Utils.parseBoolean(@parseScalar(scalar[6..]), false)
|
||||
when '!!float'
|
||||
return parseFloat(@parseScalar(scalar[7..]))
|
||||
when '!!timestamp'
|
||||
return Utils.stringToDate(Utils.ltrim(scalar[11..]))
|
||||
else
|
||||
unless context?
|
||||
context = exceptionOnInvalidType: @settings.exceptionOnInvalidType, objectDecoder: @settings.objectDecoder, i: 0
|
||||
{objectDecoder, exceptionOnInvalidType} = context
|
||||
|
||||
if objectDecoder
|
||||
# If objectDecoder function is given, we can do custom decoding of custom types
|
||||
trimmedScalar = Utils.rtrim scalar
|
||||
firstSpace = trimmedScalar.indexOf(' ')
|
||||
if firstSpace is -1
|
||||
return objectDecoder trimmedScalar, null
|
||||
else
|
||||
subValue = Utils.ltrim trimmedScalar[firstSpace+1..]
|
||||
unless subValue.length > 0
|
||||
subValue = null
|
||||
return objectDecoder trimmedScalar[0...firstSpace], subValue
|
||||
|
||||
if exceptionOnInvalidType
|
||||
throw new ParseException 'Custom object support when parsing a YAML file has been disabled.'
|
||||
|
||||
return null
|
||||
when '0'
|
||||
if '0x' is scalar[0...2]
|
||||
return Utils.hexDec scalar
|
||||
else if Utils.isDigits scalar
|
||||
return Utils.octDec scalar
|
||||
else if Utils.isNumeric scalar
|
||||
return parseFloat scalar
|
||||
else
|
||||
return scalar
|
||||
when '+'
|
||||
if Utils.isDigits scalar
|
||||
raw = scalar
|
||||
cast = parseInt(raw)
|
||||
if raw is String(cast)
|
||||
return cast
|
||||
else
|
||||
return raw
|
||||
else if Utils.isNumeric scalar
|
||||
return parseFloat scalar
|
||||
else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar
|
||||
return parseFloat(scalar.replace(',', ''))
|
||||
return scalar
|
||||
when '-'
|
||||
if Utils.isDigits(scalar[1..])
|
||||
if '0' is scalar.charAt(1)
|
||||
return -Utils.octDec(scalar[1..])
|
||||
else
|
||||
raw = scalar[1..]
|
||||
cast = parseInt(raw)
|
||||
if raw is String(cast)
|
||||
return -cast
|
||||
else
|
||||
return -raw
|
||||
else if Utils.isNumeric scalar
|
||||
return parseFloat scalar
|
||||
else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar
|
||||
return parseFloat(scalar.replace(',', ''))
|
||||
return scalar
|
||||
else
|
||||
if date = Utils.stringToDate(scalar)
|
||||
return date
|
||||
else if Utils.isNumeric(scalar)
|
||||
return parseFloat scalar
|
||||
else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar
|
||||
return parseFloat(scalar.replace(',', ''))
|
||||
return scalar
|
||||
|
||||
module.exports = Inline
|
651
node_modules/yamljs/src/Parser.coffee
generated
vendored
Normal file
651
node_modules/yamljs/src/Parser.coffee
generated
vendored
Normal file
@@ -0,0 +1,651 @@
|
||||
|
||||
Inline = require './Inline'
|
||||
Pattern = require './Pattern'
|
||||
Utils = require './Utils'
|
||||
ParseException = require './Exception/ParseException'
|
||||
ParseMore = require './Exception/ParseMore'
|
||||
|
||||
# Parser parses YAML strings to convert them to JavaScript objects.
|
||||
#
|
||||
class Parser
|
||||
|
||||
# Pre-compiled patterns
|
||||
#
|
||||
PATTERN_FOLDED_SCALAR_ALL: new Pattern '^(?:(?<type>![^\\|>]*)\\s+)?(?<separator>\\||>)(?<modifiers>\\+|\\-|\\d+|\\+\\d+|\\-\\d+|\\d+\\+|\\d+\\-)?(?<comments> +#.*)?$'
|
||||
PATTERN_FOLDED_SCALAR_END: new Pattern '(?<separator>\\||>)(?<modifiers>\\+|\\-|\\d+|\\+\\d+|\\-\\d+|\\d+\\+|\\d+\\-)?(?<comments> +#.*)?$'
|
||||
PATTERN_SEQUENCE_ITEM: new Pattern '^\\-((?<leadspaces>\\s+)(?<value>.+?))?\\s*$'
|
||||
PATTERN_ANCHOR_VALUE: new Pattern '^&(?<ref>[^ ]+) *(?<value>.*)'
|
||||
PATTERN_COMPACT_NOTATION: new Pattern '^(?<key>'+Inline.REGEX_QUOTED_STRING+'|[^ \'"\\{\\[].*?) *\\:(\\s+(?<value>.+?))?\\s*$'
|
||||
PATTERN_MAPPING_ITEM: new Pattern '^(?<key>'+Inline.REGEX_QUOTED_STRING+'|[^ \'"\\[\\{].*?) *\\:(\\s+(?<value>.+?))?\\s*$'
|
||||
PATTERN_DECIMAL: new Pattern '\\d+'
|
||||
PATTERN_INDENT_SPACES: new Pattern '^ +'
|
||||
PATTERN_TRAILING_LINES: new Pattern '(\n*)$'
|
||||
PATTERN_YAML_HEADER: new Pattern '^\\%YAML[: ][\\d\\.]+.*\n', 'm'
|
||||
PATTERN_LEADING_COMMENTS: new Pattern '^(\\#.*?\n)+', 'm'
|
||||
PATTERN_DOCUMENT_MARKER_START: new Pattern '^\\-\\-\\-.*?\n', 'm'
|
||||
PATTERN_DOCUMENT_MARKER_END: new Pattern '^\\.\\.\\.\\s*$', 'm'
|
||||
PATTERN_FOLDED_SCALAR_BY_INDENTATION: {}
|
||||
|
||||
# Context types
|
||||
#
|
||||
CONTEXT_NONE: 0
|
||||
CONTEXT_SEQUENCE: 1
|
||||
CONTEXT_MAPPING: 2
|
||||
|
||||
|
||||
# Constructor
|
||||
#
|
||||
# @param [Integer] offset The offset of YAML document (used for line numbers in error messages)
|
||||
#
|
||||
constructor: (@offset = 0) ->
|
||||
@lines = []
|
||||
@currentLineNb = -1
|
||||
@currentLine = ''
|
||||
@refs = {}
|
||||
|
||||
|
||||
# Parses a YAML string to a JavaScript value.
|
||||
#
|
||||
# @param [String] value A YAML string
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
|
||||
# @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
|
||||
#
|
||||
# @return [Object] A JavaScript value
|
||||
#
|
||||
# @throw [ParseException] If the YAML is not valid
|
||||
#
|
||||
parse: (value, exceptionOnInvalidType = false, objectDecoder = null) ->
|
||||
@currentLineNb = -1
|
||||
@currentLine = ''
|
||||
@lines = @cleanup(value).split "\n"
|
||||
|
||||
data = null
|
||||
context = @CONTEXT_NONE
|
||||
allowOverwrite = false
|
||||
while @moveToNextLine()
|
||||
if @isCurrentLineEmpty()
|
||||
continue
|
||||
|
||||
# Tab?
|
||||
if "\t" is @currentLine[0]
|
||||
throw new ParseException 'A YAML file cannot contain tabs as indentation.', @getRealCurrentLineNb() + 1, @currentLine
|
||||
|
||||
isRef = mergeNode = false
|
||||
if values = @PATTERN_SEQUENCE_ITEM.exec @currentLine
|
||||
if @CONTEXT_MAPPING is context
|
||||
throw new ParseException 'You cannot define a sequence item when in a mapping'
|
||||
context = @CONTEXT_SEQUENCE
|
||||
data ?= []
|
||||
|
||||
if values.value? and matches = @PATTERN_ANCHOR_VALUE.exec values.value
|
||||
isRef = matches.ref
|
||||
values.value = matches.value
|
||||
|
||||
# Array
|
||||
if not(values.value?) or '' is Utils.trim(values.value, ' ') or Utils.ltrim(values.value, ' ').indexOf('#') is 0
|
||||
if @currentLineNb < @lines.length - 1 and not @isNextLineUnIndentedCollection()
|
||||
c = @getRealCurrentLineNb() + 1
|
||||
parser = new Parser c
|
||||
parser.refs = @refs
|
||||
data.push parser.parse(@getNextEmbedBlock(null, true), exceptionOnInvalidType, objectDecoder)
|
||||
else
|
||||
data.push null
|
||||
|
||||
else
|
||||
if values.leadspaces?.length and matches = @PATTERN_COMPACT_NOTATION.exec values.value
|
||||
|
||||
# This is a compact notation element, add to next block and parse
|
||||
c = @getRealCurrentLineNb()
|
||||
parser = new Parser c
|
||||
parser.refs = @refs
|
||||
|
||||
block = values.value
|
||||
indent = @getCurrentLineIndentation()
|
||||
if @isNextLineIndented(false)
|
||||
block += "\n"+@getNextEmbedBlock(indent + values.leadspaces.length + 1, true)
|
||||
|
||||
data.push parser.parse block, exceptionOnInvalidType, objectDecoder
|
||||
|
||||
else
|
||||
data.push @parseValue values.value, exceptionOnInvalidType, objectDecoder
|
||||
|
||||
else if (values = @PATTERN_MAPPING_ITEM.exec @currentLine) and values.key.indexOf(' #') is -1
|
||||
if @CONTEXT_SEQUENCE is context
|
||||
throw new ParseException 'You cannot define a mapping item when in a sequence'
|
||||
context = @CONTEXT_MAPPING
|
||||
data ?= {}
|
||||
|
||||
# Force correct settings
|
||||
Inline.configure exceptionOnInvalidType, objectDecoder
|
||||
try
|
||||
key = Inline.parseScalar values.key
|
||||
catch e
|
||||
e.parsedLine = @getRealCurrentLineNb() + 1
|
||||
e.snippet = @currentLine
|
||||
|
||||
throw e
|
||||
|
||||
if '<<' is key
|
||||
mergeNode = true
|
||||
allowOverwrite = true
|
||||
if values.value?.indexOf('*') is 0
|
||||
refName = values.value[1..]
|
||||
unless @refs[refName]?
|
||||
throw new ParseException 'Reference "'+refName+'" does not exist.', @getRealCurrentLineNb() + 1, @currentLine
|
||||
|
||||
refValue = @refs[refName]
|
||||
|
||||
if typeof refValue isnt 'object'
|
||||
throw new ParseException 'YAML merge keys used with a scalar value instead of an object.', @getRealCurrentLineNb() + 1, @currentLine
|
||||
|
||||
if refValue instanceof Array
|
||||
# Merge array with object
|
||||
for value, i in refValue
|
||||
data[String(i)] ?= value
|
||||
else
|
||||
# Merge objects
|
||||
for key, value of refValue
|
||||
data[key] ?= value
|
||||
|
||||
else
|
||||
if values.value? and values.value isnt ''
|
||||
value = values.value
|
||||
else
|
||||
value = @getNextEmbedBlock()
|
||||
|
||||
c = @getRealCurrentLineNb() + 1
|
||||
parser = new Parser c
|
||||
parser.refs = @refs
|
||||
parsed = parser.parse value, exceptionOnInvalidType
|
||||
|
||||
unless typeof parsed is 'object'
|
||||
throw new ParseException 'YAML merge keys used with a scalar value instead of an object.', @getRealCurrentLineNb() + 1, @currentLine
|
||||
|
||||
if parsed instanceof Array
|
||||
# If the value associated with the merge key is a sequence, then this sequence is expected to contain mapping nodes
|
||||
# and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier
|
||||
# in the sequence override keys specified in later mapping nodes.
|
||||
for parsedItem in parsed
|
||||
unless typeof parsedItem is 'object'
|
||||
throw new ParseException 'Merge items must be objects.', @getRealCurrentLineNb() + 1, parsedItem
|
||||
|
||||
if parsedItem instanceof Array
|
||||
# Merge array with object
|
||||
for value, i in parsedItem
|
||||
k = String(i)
|
||||
unless data.hasOwnProperty(k)
|
||||
data[k] = value
|
||||
else
|
||||
# Merge objects
|
||||
for key, value of parsedItem
|
||||
unless data.hasOwnProperty(key)
|
||||
data[key] = value
|
||||
|
||||
else
|
||||
# If the value associated with the key is a single mapping node, each of its key/value pairs is inserted into the
|
||||
# current mapping, unless the key already exists in it.
|
||||
for key, value of parsed
|
||||
unless data.hasOwnProperty(key)
|
||||
data[key] = value
|
||||
|
||||
else if values.value? and matches = @PATTERN_ANCHOR_VALUE.exec values.value
|
||||
isRef = matches.ref
|
||||
values.value = matches.value
|
||||
|
||||
|
||||
if mergeNode
|
||||
# Merge keys
|
||||
else if not(values.value?) or '' is Utils.trim(values.value, ' ') or Utils.ltrim(values.value, ' ').indexOf('#') is 0
|
||||
# Hash
|
||||
# if next line is less indented or equal, then it means that the current value is null
|
||||
if not(@isNextLineIndented()) and not(@isNextLineUnIndentedCollection())
|
||||
# Spec: Keys MUST be unique; first one wins.
|
||||
# But overwriting is allowed when a merge node is used in current block.
|
||||
if allowOverwrite or data[key] is undefined
|
||||
data[key] = null
|
||||
|
||||
else
|
||||
c = @getRealCurrentLineNb() + 1
|
||||
parser = new Parser c
|
||||
parser.refs = @refs
|
||||
val = parser.parse @getNextEmbedBlock(), exceptionOnInvalidType, objectDecoder
|
||||
|
||||
# Spec: Keys MUST be unique; first one wins.
|
||||
# But overwriting is allowed when a merge node is used in current block.
|
||||
if allowOverwrite or data[key] is undefined
|
||||
data[key] = val
|
||||
|
||||
else
|
||||
val = @parseValue values.value, exceptionOnInvalidType, objectDecoder
|
||||
|
||||
# Spec: Keys MUST be unique; first one wins.
|
||||
# But overwriting is allowed when a merge node is used in current block.
|
||||
if allowOverwrite or data[key] is undefined
|
||||
data[key] = val
|
||||
|
||||
else
|
||||
# 1-liner optionally followed by newline
|
||||
lineCount = @lines.length
|
||||
if 1 is lineCount or (2 is lineCount and Utils.isEmpty(@lines[1]))
|
||||
try
|
||||
value = Inline.parse @lines[0], exceptionOnInvalidType, objectDecoder
|
||||
catch e
|
||||
e.parsedLine = @getRealCurrentLineNb() + 1
|
||||
e.snippet = @currentLine
|
||||
|
||||
throw e
|
||||
|
||||
if typeof value is 'object'
|
||||
if value instanceof Array
|
||||
first = value[0]
|
||||
else
|
||||
for key of value
|
||||
first = value[key]
|
||||
break
|
||||
|
||||
if typeof first is 'string' and first.indexOf('*') is 0
|
||||
data = []
|
||||
for alias in value
|
||||
data.push @refs[alias[1..]]
|
||||
value = data
|
||||
|
||||
return value
|
||||
|
||||
else if Utils.ltrim(value).charAt(0) in ['[', '{']
|
||||
try
|
||||
return Inline.parse value, exceptionOnInvalidType, objectDecoder
|
||||
catch e
|
||||
e.parsedLine = @getRealCurrentLineNb() + 1
|
||||
e.snippet = @currentLine
|
||||
|
||||
throw e
|
||||
|
||||
throw new ParseException 'Unable to parse.', @getRealCurrentLineNb() + 1, @currentLine
|
||||
|
||||
if isRef
|
||||
if data instanceof Array
|
||||
@refs[isRef] = data[data.length-1]
|
||||
else
|
||||
lastKey = null
|
||||
for key of data
|
||||
lastKey = key
|
||||
@refs[isRef] = data[lastKey]
|
||||
|
||||
|
||||
if Utils.isEmpty(data)
|
||||
return null
|
||||
else
|
||||
return data
|
||||
|
||||
|
||||
|
||||
# Returns the current line number (takes the offset into account).
|
||||
#
|
||||
# @return [Integer] The current line number
|
||||
#
|
||||
getRealCurrentLineNb: ->
|
||||
return @currentLineNb + @offset
|
||||
|
||||
|
||||
# Returns the current line indentation.
|
||||
#
|
||||
# @return [Integer] The current line indentation
|
||||
#
|
||||
getCurrentLineIndentation: ->
|
||||
return @currentLine.length - Utils.ltrim(@currentLine, ' ').length
|
||||
|
||||
|
||||
# Returns the next embed block of YAML.
|
||||
#
|
||||
# @param [Integer] indentation The indent level at which the block is to be read, or null for default
|
||||
#
|
||||
# @return [String] A YAML string
|
||||
#
|
||||
# @throw [ParseException] When indentation problem are detected
|
||||
#
|
||||
getNextEmbedBlock: (indentation = null, includeUnindentedCollection = false) ->
|
||||
@moveToNextLine()
|
||||
|
||||
if not indentation?
|
||||
newIndent = @getCurrentLineIndentation()
|
||||
|
||||
unindentedEmbedBlock = @isStringUnIndentedCollectionItem @currentLine
|
||||
|
||||
if not(@isCurrentLineEmpty()) and 0 is newIndent and not(unindentedEmbedBlock)
|
||||
throw new ParseException 'Indentation problem.', @getRealCurrentLineNb() + 1, @currentLine
|
||||
|
||||
else
|
||||
newIndent = indentation
|
||||
|
||||
|
||||
data = [@currentLine[newIndent..]]
|
||||
|
||||
unless includeUnindentedCollection
|
||||
isItUnindentedCollection = @isStringUnIndentedCollectionItem @currentLine
|
||||
|
||||
# Comments must not be removed inside a string block (ie. after a line ending with "|")
|
||||
# They must not be removed inside a sub-embedded block as well
|
||||
removeCommentsPattern = @PATTERN_FOLDED_SCALAR_END
|
||||
removeComments = not removeCommentsPattern.test @currentLine
|
||||
|
||||
while @moveToNextLine()
|
||||
indent = @getCurrentLineIndentation()
|
||||
|
||||
if indent is newIndent
|
||||
removeComments = not removeCommentsPattern.test @currentLine
|
||||
|
||||
if removeComments and @isCurrentLineComment()
|
||||
continue
|
||||
|
||||
if @isCurrentLineBlank()
|
||||
data.push @currentLine[newIndent..]
|
||||
continue
|
||||
|
||||
if isItUnindentedCollection and not @isStringUnIndentedCollectionItem(@currentLine) and indent is newIndent
|
||||
@moveToPreviousLine()
|
||||
break
|
||||
|
||||
if indent >= newIndent
|
||||
data.push @currentLine[newIndent..]
|
||||
else if Utils.ltrim(@currentLine).charAt(0) is '#'
|
||||
# Don't add line with comments
|
||||
else if 0 is indent
|
||||
@moveToPreviousLine()
|
||||
break
|
||||
else
|
||||
throw new ParseException 'Indentation problem.', @getRealCurrentLineNb() + 1, @currentLine
|
||||
|
||||
|
||||
return data.join "\n"
|
||||
|
||||
|
||||
# Moves the parser to the next line.
|
||||
#
|
||||
# @return [Boolean]
|
||||
#
|
||||
moveToNextLine: ->
|
||||
if @currentLineNb >= @lines.length - 1
|
||||
return false
|
||||
|
||||
@currentLine = @lines[++@currentLineNb];
|
||||
|
||||
return true
|
||||
|
||||
|
||||
# Moves the parser to the previous line.
|
||||
#
|
||||
moveToPreviousLine: ->
|
||||
@currentLine = @lines[--@currentLineNb]
|
||||
return
|
||||
|
||||
|
||||
# Parses a YAML value.
|
||||
#
|
||||
# @param [String] value A YAML value
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types false otherwise
|
||||
# @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
|
||||
#
|
||||
# @return [Object] A JavaScript value
|
||||
#
|
||||
# @throw [ParseException] When reference does not exist
|
||||
#
|
||||
parseValue: (value, exceptionOnInvalidType, objectDecoder) ->
|
||||
if 0 is value.indexOf('*')
|
||||
pos = value.indexOf '#'
|
||||
if pos isnt -1
|
||||
value = value.substr(1, pos-2)
|
||||
else
|
||||
value = value[1..]
|
||||
|
||||
if @refs[value] is undefined
|
||||
throw new ParseException 'Reference "'+value+'" does not exist.', @currentLine
|
||||
|
||||
return @refs[value]
|
||||
|
||||
|
||||
if matches = @PATTERN_FOLDED_SCALAR_ALL.exec value
|
||||
modifiers = matches.modifiers ? ''
|
||||
|
||||
foldedIndent = Math.abs(parseInt(modifiers))
|
||||
if isNaN(foldedIndent) then foldedIndent = 0
|
||||
val = @parseFoldedScalar matches.separator, @PATTERN_DECIMAL.replace(modifiers, ''), foldedIndent
|
||||
if matches.type?
|
||||
# Force correct settings
|
||||
Inline.configure exceptionOnInvalidType, objectDecoder
|
||||
return Inline.parseScalar matches.type+' '+val
|
||||
else
|
||||
return val
|
||||
|
||||
# Value can be multiline compact sequence or mapping or string
|
||||
if value.charAt(0) in ['[', '{', '"', "'"]
|
||||
while true
|
||||
try
|
||||
return Inline.parse value, exceptionOnInvalidType, objectDecoder
|
||||
catch e
|
||||
if e instanceof ParseMore and @moveToNextLine()
|
||||
value += "\n" + Utils.trim(@currentLine, ' ')
|
||||
else
|
||||
e.parsedLine = @getRealCurrentLineNb() + 1
|
||||
e.snippet = @currentLine
|
||||
throw e
|
||||
else
|
||||
if @isNextLineIndented()
|
||||
value += "\n" + @getNextEmbedBlock()
|
||||
return Inline.parse value, exceptionOnInvalidType, objectDecoder
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Parses a folded scalar.
|
||||
#
|
||||
# @param [String] separator The separator that was used to begin this folded scalar (| or >)
|
||||
# @param [String] indicator The indicator that was used to begin this folded scalar (+ or -)
|
||||
# @param [Integer] indentation The indentation that was used to begin this folded scalar
|
||||
#
|
||||
# @return [String] The text value
|
||||
#
|
||||
parseFoldedScalar: (separator, indicator = '', indentation = 0) ->
|
||||
notEOF = @moveToNextLine()
|
||||
if not notEOF
|
||||
return ''
|
||||
|
||||
isCurrentLineBlank = @isCurrentLineBlank()
|
||||
text = ''
|
||||
|
||||
# Leading blank lines are consumed before determining indentation
|
||||
while notEOF and isCurrentLineBlank
|
||||
# newline only if not EOF
|
||||
if notEOF = @moveToNextLine()
|
||||
text += "\n"
|
||||
isCurrentLineBlank = @isCurrentLineBlank()
|
||||
|
||||
|
||||
# Determine indentation if not specified
|
||||
if 0 is indentation
|
||||
if matches = @PATTERN_INDENT_SPACES.exec @currentLine
|
||||
indentation = matches[0].length
|
||||
|
||||
|
||||
if indentation > 0
|
||||
pattern = @PATTERN_FOLDED_SCALAR_BY_INDENTATION[indentation]
|
||||
unless pattern?
|
||||
pattern = new Pattern '^ {'+indentation+'}(.*)$'
|
||||
Parser::PATTERN_FOLDED_SCALAR_BY_INDENTATION[indentation] = pattern
|
||||
|
||||
while notEOF and (isCurrentLineBlank or matches = pattern.exec @currentLine)
|
||||
if isCurrentLineBlank
|
||||
text += @currentLine[indentation..]
|
||||
else
|
||||
text += matches[1]
|
||||
|
||||
# newline only if not EOF
|
||||
if notEOF = @moveToNextLine()
|
||||
text += "\n"
|
||||
isCurrentLineBlank = @isCurrentLineBlank()
|
||||
|
||||
else if notEOF
|
||||
text += "\n"
|
||||
|
||||
|
||||
if notEOF
|
||||
@moveToPreviousLine()
|
||||
|
||||
|
||||
# Remove line breaks of each lines except the empty and more indented ones
|
||||
if '>' is separator
|
||||
newText = ''
|
||||
for line in text.split "\n"
|
||||
if line.length is 0 or line.charAt(0) is ' '
|
||||
newText = Utils.rtrim(newText, ' ') + line + "\n"
|
||||
else
|
||||
newText += line + ' '
|
||||
text = newText
|
||||
|
||||
if '+' isnt indicator
|
||||
# Remove any extra space or new line as we are adding them after
|
||||
text = Utils.rtrim(text)
|
||||
|
||||
# Deal with trailing newlines as indicated
|
||||
if '' is indicator
|
||||
text = @PATTERN_TRAILING_LINES.replace text, "\n"
|
||||
else if '-' is indicator
|
||||
text = @PATTERN_TRAILING_LINES.replace text, ''
|
||||
|
||||
return text
|
||||
|
||||
|
||||
# Returns true if the next line is indented.
|
||||
#
|
||||
# @return [Boolean] Returns true if the next line is indented, false otherwise
|
||||
#
|
||||
isNextLineIndented: (ignoreComments = true) ->
|
||||
currentIndentation = @getCurrentLineIndentation()
|
||||
EOF = not @moveToNextLine()
|
||||
|
||||
if ignoreComments
|
||||
while not(EOF) and @isCurrentLineEmpty()
|
||||
EOF = not @moveToNextLine()
|
||||
else
|
||||
while not(EOF) and @isCurrentLineBlank()
|
||||
EOF = not @moveToNextLine()
|
||||
|
||||
if EOF
|
||||
return false
|
||||
|
||||
ret = false
|
||||
if @getCurrentLineIndentation() > currentIndentation
|
||||
ret = true
|
||||
|
||||
@moveToPreviousLine()
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
# Returns true if the current line is blank or if it is a comment line.
|
||||
#
|
||||
# @return [Boolean] Returns true if the current line is empty or if it is a comment line, false otherwise
|
||||
#
|
||||
isCurrentLineEmpty: ->
|
||||
trimmedLine = Utils.trim(@currentLine, ' ')
|
||||
return trimmedLine.length is 0 or trimmedLine.charAt(0) is '#'
|
||||
|
||||
|
||||
# Returns true if the current line is blank.
|
||||
#
|
||||
# @return [Boolean] Returns true if the current line is blank, false otherwise
|
||||
#
|
||||
isCurrentLineBlank: ->
|
||||
return '' is Utils.trim(@currentLine, ' ')
|
||||
|
||||
|
||||
# Returns true if the current line is a comment line.
|
||||
#
|
||||
# @return [Boolean] Returns true if the current line is a comment line, false otherwise
|
||||
#
|
||||
isCurrentLineComment: ->
|
||||
# Checking explicitly the first char of the trim is faster than loops or strpos
|
||||
ltrimmedLine = Utils.ltrim(@currentLine, ' ')
|
||||
|
||||
return ltrimmedLine.charAt(0) is '#'
|
||||
|
||||
|
||||
# Cleanups a YAML string to be parsed.
|
||||
#
|
||||
# @param [String] value The input YAML string
|
||||
#
|
||||
# @return [String] A cleaned up YAML string
|
||||
#
|
||||
cleanup: (value) ->
|
||||
if value.indexOf("\r") isnt -1
|
||||
value = value.split("\r\n").join("\n").split("\r").join("\n")
|
||||
|
||||
# Strip YAML header
|
||||
count = 0
|
||||
[value, count] = @PATTERN_YAML_HEADER.replaceAll value, ''
|
||||
@offset += count
|
||||
|
||||
# Remove leading comments
|
||||
[trimmedValue, count] = @PATTERN_LEADING_COMMENTS.replaceAll value, '', 1
|
||||
if count is 1
|
||||
# Items have been removed, update the offset
|
||||
@offset += Utils.subStrCount(value, "\n") - Utils.subStrCount(trimmedValue, "\n")
|
||||
value = trimmedValue
|
||||
|
||||
# Remove start of the document marker (---)
|
||||
[trimmedValue, count] = @PATTERN_DOCUMENT_MARKER_START.replaceAll value, '', 1
|
||||
if count is 1
|
||||
# Items have been removed, update the offset
|
||||
@offset += Utils.subStrCount(value, "\n") - Utils.subStrCount(trimmedValue, "\n")
|
||||
value = trimmedValue
|
||||
|
||||
# Remove end of the document marker (...)
|
||||
value = @PATTERN_DOCUMENT_MARKER_END.replace value, ''
|
||||
|
||||
# Ensure the block is not indented
|
||||
lines = value.split("\n")
|
||||
smallestIndent = -1
|
||||
for line in lines
|
||||
continue if Utils.trim(line, ' ').length == 0
|
||||
indent = line.length - Utils.ltrim(line).length
|
||||
if smallestIndent is -1 or indent < smallestIndent
|
||||
smallestIndent = indent
|
||||
if smallestIndent > 0
|
||||
for line, i in lines
|
||||
lines[i] = line[smallestIndent..]
|
||||
value = lines.join("\n")
|
||||
|
||||
return value
|
||||
|
||||
|
||||
# Returns true if the next line starts unindented collection
|
||||
#
|
||||
# @return [Boolean] Returns true if the next line starts unindented collection, false otherwise
|
||||
#
|
||||
isNextLineUnIndentedCollection: (currentIndentation = null) ->
|
||||
currentIndentation ?= @getCurrentLineIndentation()
|
||||
notEOF = @moveToNextLine()
|
||||
|
||||
while notEOF and @isCurrentLineEmpty()
|
||||
notEOF = @moveToNextLine()
|
||||
|
||||
if false is notEOF
|
||||
return false
|
||||
|
||||
ret = false
|
||||
if @getCurrentLineIndentation() is currentIndentation and @isStringUnIndentedCollectionItem(@currentLine)
|
||||
ret = true
|
||||
|
||||
@moveToPreviousLine()
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
# Returns true if the string is un-indented collection item
|
||||
#
|
||||
# @return [Boolean] Returns true if the string is un-indented collection item, false otherwise
|
||||
#
|
||||
isStringUnIndentedCollectionItem: ->
|
||||
return @currentLine is '-' or @currentLine[0...2] is '- '
|
||||
|
||||
|
||||
module.exports = Parser
|
144
node_modules/yamljs/src/Pattern.coffee
generated
vendored
Normal file
144
node_modules/yamljs/src/Pattern.coffee
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
# Pattern is a zero-conflict wrapper extending RegExp features
|
||||
# in order to make YAML parsing regex more expressive.
|
||||
#
|
||||
class Pattern
|
||||
|
||||
# @property [RegExp] The RegExp instance
|
||||
regex: null
|
||||
|
||||
# @property [String] The raw regex string
|
||||
rawRegex: null
|
||||
|
||||
# @property [String] The cleaned regex string (used to create the RegExp instance)
|
||||
cleanedRegex: null
|
||||
|
||||
# @property [Object] The dictionary mapping names to capturing bracket numbers
|
||||
mapping: null
|
||||
|
||||
# Constructor
|
||||
#
|
||||
# @param [String] rawRegex The raw regex string defining the pattern
|
||||
#
|
||||
constructor: (rawRegex, modifiers = '') ->
|
||||
cleanedRegex = ''
|
||||
len = rawRegex.length
|
||||
mapping = null
|
||||
|
||||
# Cleanup raw regex and compute mapping
|
||||
capturingBracketNumber = 0
|
||||
i = 0
|
||||
while i < len
|
||||
_char = rawRegex.charAt(i)
|
||||
if _char is '\\'
|
||||
# Ignore next character
|
||||
cleanedRegex += rawRegex[i..i+1]
|
||||
i++
|
||||
else if _char is '('
|
||||
# Increase bracket number, only if it is capturing
|
||||
if i < len - 2
|
||||
part = rawRegex[i..i+2]
|
||||
if part is '(?:'
|
||||
# Non-capturing bracket
|
||||
i += 2
|
||||
cleanedRegex += part
|
||||
else if part is '(?<'
|
||||
# Capturing bracket with possibly a name
|
||||
capturingBracketNumber++
|
||||
i += 2
|
||||
name = ''
|
||||
while i + 1 < len
|
||||
subChar = rawRegex.charAt(i + 1)
|
||||
if subChar is '>'
|
||||
cleanedRegex += '('
|
||||
i++
|
||||
if name.length > 0
|
||||
# Associate a name with a capturing bracket number
|
||||
mapping ?= {}
|
||||
mapping[name] = capturingBracketNumber
|
||||
break
|
||||
else
|
||||
name += subChar
|
||||
|
||||
i++
|
||||
else
|
||||
cleanedRegex += _char
|
||||
capturingBracketNumber++
|
||||
else
|
||||
cleanedRegex += _char
|
||||
else
|
||||
cleanedRegex += _char
|
||||
|
||||
i++
|
||||
|
||||
@rawRegex = rawRegex
|
||||
@cleanedRegex = cleanedRegex
|
||||
@regex = new RegExp @cleanedRegex, 'g'+modifiers.replace('g', '')
|
||||
@mapping = mapping
|
||||
|
||||
|
||||
# Executes the pattern's regex and returns the matching values
|
||||
#
|
||||
# @param [String] str The string to use to execute the pattern
|
||||
#
|
||||
# @return [Array] The matching values extracted from capturing brackets or null if nothing matched
|
||||
#
|
||||
exec: (str) ->
|
||||
@regex.lastIndex = 0
|
||||
matches = @regex.exec str
|
||||
|
||||
if not matches?
|
||||
return null
|
||||
|
||||
if @mapping?
|
||||
for name, index of @mapping
|
||||
matches[name] = matches[index]
|
||||
|
||||
return matches
|
||||
|
||||
|
||||
# Tests the pattern's regex
|
||||
#
|
||||
# @param [String] str The string to use to test the pattern
|
||||
#
|
||||
# @return [Boolean] true if the string matched
|
||||
#
|
||||
test: (str) ->
|
||||
@regex.lastIndex = 0
|
||||
return @regex.test str
|
||||
|
||||
|
||||
# Replaces occurences matching with the pattern's regex with replacement
|
||||
#
|
||||
# @param [String] str The source string to perform replacements
|
||||
# @param [String] replacement The string to use in place of each replaced occurence.
|
||||
#
|
||||
# @return [String] The replaced string
|
||||
#
|
||||
replace: (str, replacement) ->
|
||||
@regex.lastIndex = 0
|
||||
return str.replace @regex, replacement
|
||||
|
||||
|
||||
# Replaces occurences matching with the pattern's regex with replacement and
|
||||
# get both the replaced string and the number of replaced occurences in the string.
|
||||
#
|
||||
# @param [String] str The source string to perform replacements
|
||||
# @param [String] replacement The string to use in place of each replaced occurence.
|
||||
# @param [Integer] limit The maximum number of occurences to replace (0 means infinite number of occurences)
|
||||
#
|
||||
# @return [Array] A destructurable array containing the replaced string and the number of replaced occurences. For instance: ["my replaced string", 2]
|
||||
#
|
||||
replaceAll: (str, replacement, limit = 0) ->
|
||||
@regex.lastIndex = 0
|
||||
count = 0
|
||||
while @regex.test(str) and (limit is 0 or count < limit)
|
||||
@regex.lastIndex = 0
|
||||
str = str.replace @regex, replacement
|
||||
count++
|
||||
|
||||
return [str, count]
|
||||
|
||||
|
||||
module.exports = Pattern
|
||||
|
96
node_modules/yamljs/src/Unescaper.coffee
generated
vendored
Normal file
96
node_modules/yamljs/src/Unescaper.coffee
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
Utils = require './Utils'
|
||||
Pattern = require './Pattern'
|
||||
|
||||
# Unescaper encapsulates unescaping rules for single and double-quoted YAML strings.
|
||||
#
|
||||
class Unescaper
|
||||
|
||||
# Regex fragment that matches an escaped character in
|
||||
# a double quoted string.
|
||||
@PATTERN_ESCAPED_CHARACTER: new Pattern '\\\\([0abt\tnvfre "\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})';
|
||||
|
||||
|
||||
# Unescapes a single quoted string.
|
||||
#
|
||||
# @param [String] value A single quoted string.
|
||||
#
|
||||
# @return [String] The unescaped string.
|
||||
#
|
||||
@unescapeSingleQuotedString: (value) ->
|
||||
return value.replace(/\'\'/g, '\'')
|
||||
|
||||
|
||||
# Unescapes a double quoted string.
|
||||
#
|
||||
# @param [String] value A double quoted string.
|
||||
#
|
||||
# @return [String] The unescaped string.
|
||||
#
|
||||
@unescapeDoubleQuotedString: (value) ->
|
||||
@_unescapeCallback ?= (str) =>
|
||||
return @unescapeCharacter(str)
|
||||
|
||||
# Evaluate the string
|
||||
return @PATTERN_ESCAPED_CHARACTER.replace value, @_unescapeCallback
|
||||
|
||||
|
||||
# Unescapes a character that was found in a double-quoted string
|
||||
#
|
||||
# @param [String] value An escaped character
|
||||
#
|
||||
# @return [String] The unescaped character
|
||||
#
|
||||
@unescapeCharacter: (value) ->
|
||||
ch = String.fromCharCode
|
||||
switch value.charAt(1)
|
||||
when '0'
|
||||
return ch(0)
|
||||
when 'a'
|
||||
return ch(7)
|
||||
when 'b'
|
||||
return ch(8)
|
||||
when 't'
|
||||
return "\t"
|
||||
when "\t"
|
||||
return "\t"
|
||||
when 'n'
|
||||
return "\n"
|
||||
when 'v'
|
||||
return ch(11)
|
||||
when 'f'
|
||||
return ch(12)
|
||||
when 'r'
|
||||
return ch(13)
|
||||
when 'e'
|
||||
return ch(27)
|
||||
when ' '
|
||||
return ' '
|
||||
when '"'
|
||||
return '"'
|
||||
when '/'
|
||||
return '/'
|
||||
when '\\'
|
||||
return '\\'
|
||||
when 'N'
|
||||
# U+0085 NEXT LINE
|
||||
return ch(0x0085)
|
||||
when '_'
|
||||
# U+00A0 NO-BREAK SPACE
|
||||
return ch(0x00A0)
|
||||
when 'L'
|
||||
# U+2028 LINE SEPARATOR
|
||||
return ch(0x2028)
|
||||
when 'P'
|
||||
# U+2029 PARAGRAPH SEPARATOR
|
||||
return ch(0x2029)
|
||||
when 'x'
|
||||
return Utils.utf8chr(Utils.hexDec(value.substr(2, 2)))
|
||||
when 'u'
|
||||
return Utils.utf8chr(Utils.hexDec(value.substr(2, 4)))
|
||||
when 'U'
|
||||
return Utils.utf8chr(Utils.hexDec(value.substr(2, 8)))
|
||||
else
|
||||
return ''
|
||||
|
||||
module.exports = Unescaper
|
349
node_modules/yamljs/src/Utils.coffee
generated
vendored
Normal file
349
node_modules/yamljs/src/Utils.coffee
generated
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
|
||||
Pattern = require './Pattern'
|
||||
|
||||
# A bunch of utility methods
|
||||
#
|
||||
class Utils
|
||||
|
||||
@REGEX_LEFT_TRIM_BY_CHAR: {}
|
||||
@REGEX_RIGHT_TRIM_BY_CHAR: {}
|
||||
@REGEX_SPACES: /\s+/g
|
||||
@REGEX_DIGITS: /^\d+$/
|
||||
@REGEX_OCTAL: /[^0-7]/gi
|
||||
@REGEX_HEXADECIMAL: /[^a-f0-9]/gi
|
||||
|
||||
# Precompiled date pattern
|
||||
@PATTERN_DATE: new Pattern '^'+
|
||||
'(?<year>[0-9][0-9][0-9][0-9])'+
|
||||
'-(?<month>[0-9][0-9]?)'+
|
||||
'-(?<day>[0-9][0-9]?)'+
|
||||
'(?:(?:[Tt]|[ \t]+)'+
|
||||
'(?<hour>[0-9][0-9]?)'+
|
||||
':(?<minute>[0-9][0-9])'+
|
||||
':(?<second>[0-9][0-9])'+
|
||||
'(?:\.(?<fraction>[0-9]*))?'+
|
||||
'(?:[ \t]*(?<tz>Z|(?<tz_sign>[-+])(?<tz_hour>[0-9][0-9]?)'+
|
||||
'(?::(?<tz_minute>[0-9][0-9]))?))?)?'+
|
||||
'$', 'i'
|
||||
|
||||
# Local timezone offset in ms
|
||||
@LOCAL_TIMEZONE_OFFSET: new Date().getTimezoneOffset() * 60 * 1000
|
||||
|
||||
# Trims the given string on both sides
|
||||
#
|
||||
# @param [String] str The string to trim
|
||||
# @param [String] _char The character to use for trimming (default: '\\s')
|
||||
#
|
||||
# @return [String] A trimmed string
|
||||
#
|
||||
@trim: (str, _char = '\\s') ->
|
||||
regexLeft = @REGEX_LEFT_TRIM_BY_CHAR[_char]
|
||||
unless regexLeft?
|
||||
@REGEX_LEFT_TRIM_BY_CHAR[_char] = regexLeft = new RegExp '^'+_char+''+_char+'*'
|
||||
regexLeft.lastIndex = 0
|
||||
regexRight = @REGEX_RIGHT_TRIM_BY_CHAR[_char]
|
||||
unless regexRight?
|
||||
@REGEX_RIGHT_TRIM_BY_CHAR[_char] = regexRight = new RegExp _char+''+_char+'*$'
|
||||
regexRight.lastIndex = 0
|
||||
return str.replace(regexLeft, '').replace(regexRight, '')
|
||||
|
||||
|
||||
# Trims the given string on the left side
|
||||
#
|
||||
# @param [String] str The string to trim
|
||||
# @param [String] _char The character to use for trimming (default: '\\s')
|
||||
#
|
||||
# @return [String] A trimmed string
|
||||
#
|
||||
@ltrim: (str, _char = '\\s') ->
|
||||
regexLeft = @REGEX_LEFT_TRIM_BY_CHAR[_char]
|
||||
unless regexLeft?
|
||||
@REGEX_LEFT_TRIM_BY_CHAR[_char] = regexLeft = new RegExp '^'+_char+''+_char+'*'
|
||||
regexLeft.lastIndex = 0
|
||||
return str.replace(regexLeft, '')
|
||||
|
||||
|
||||
# Trims the given string on the right side
|
||||
#
|
||||
# @param [String] str The string to trim
|
||||
# @param [String] _char The character to use for trimming (default: '\\s')
|
||||
#
|
||||
# @return [String] A trimmed string
|
||||
#
|
||||
@rtrim: (str, _char = '\\s') ->
|
||||
regexRight = @REGEX_RIGHT_TRIM_BY_CHAR[_char]
|
||||
unless regexRight?
|
||||
@REGEX_RIGHT_TRIM_BY_CHAR[_char] = regexRight = new RegExp _char+''+_char+'*$'
|
||||
regexRight.lastIndex = 0
|
||||
return str.replace(regexRight, '')
|
||||
|
||||
|
||||
# Checks if the given value is empty (null, undefined, empty string, string '0', empty Array, empty Object)
|
||||
#
|
||||
# @param [Object] value The value to check
|
||||
#
|
||||
# @return [Boolean] true if the value is empty
|
||||
#
|
||||
@isEmpty: (value) ->
|
||||
return not(value) or value is '' or value is '0' or (value instanceof Array and value.length is 0) or @isEmptyObject(value)
|
||||
|
||||
# Checks if the given value is an empty object
|
||||
#
|
||||
# @param [Object] value The value to check
|
||||
#
|
||||
# @return [Boolean] true if the value is empty and is an object
|
||||
#
|
||||
@isEmptyObject: (value) ->
|
||||
return value instanceof Object and (k for own k of value).length is 0
|
||||
|
||||
# Counts the number of occurences of subString inside string
|
||||
#
|
||||
# @param [String] string The string where to count occurences
|
||||
# @param [String] subString The subString to count
|
||||
# @param [Integer] start The start index
|
||||
# @param [Integer] length The string length until where to count
|
||||
#
|
||||
# @return [Integer] The number of occurences
|
||||
#
|
||||
@subStrCount: (string, subString, start, length) ->
|
||||
c = 0
|
||||
|
||||
string = '' + string
|
||||
subString = '' + subString
|
||||
|
||||
if start?
|
||||
string = string[start..]
|
||||
if length?
|
||||
string = string[0...length]
|
||||
|
||||
len = string.length
|
||||
sublen = subString.length
|
||||
for i in [0...len]
|
||||
if subString is string[i...sublen]
|
||||
c++
|
||||
i += sublen - 1
|
||||
|
||||
return c
|
||||
|
||||
|
||||
# Returns true if input is only composed of digits
|
||||
#
|
||||
# @param [Object] input The value to test
|
||||
#
|
||||
# @return [Boolean] true if input is only composed of digits
|
||||
#
|
||||
@isDigits: (input) ->
|
||||
@REGEX_DIGITS.lastIndex = 0
|
||||
return @REGEX_DIGITS.test input
|
||||
|
||||
|
||||
# Decode octal value
|
||||
#
|
||||
# @param [String] input The value to decode
|
||||
#
|
||||
# @return [Integer] The decoded value
|
||||
#
|
||||
@octDec: (input) ->
|
||||
@REGEX_OCTAL.lastIndex = 0
|
||||
return parseInt((input+'').replace(@REGEX_OCTAL, ''), 8)
|
||||
|
||||
|
||||
# Decode hexadecimal value
|
||||
#
|
||||
# @param [String] input The value to decode
|
||||
#
|
||||
# @return [Integer] The decoded value
|
||||
#
|
||||
@hexDec: (input) ->
|
||||
@REGEX_HEXADECIMAL.lastIndex = 0
|
||||
input = @trim(input)
|
||||
if (input+'')[0...2] is '0x' then input = (input+'')[2..]
|
||||
return parseInt((input+'').replace(@REGEX_HEXADECIMAL, ''), 16)
|
||||
|
||||
|
||||
# Get the UTF-8 character for the given code point.
|
||||
#
|
||||
# @param [Integer] c The unicode code point
|
||||
#
|
||||
# @return [String] The corresponding UTF-8 character
|
||||
#
|
||||
@utf8chr: (c) ->
|
||||
ch = String.fromCharCode
|
||||
if 0x80 > (c %= 0x200000)
|
||||
return ch(c)
|
||||
if 0x800 > c
|
||||
return ch(0xC0 | c>>6) + ch(0x80 | c & 0x3F)
|
||||
if 0x10000 > c
|
||||
return ch(0xE0 | c>>12) + ch(0x80 | c>>6 & 0x3F) + ch(0x80 | c & 0x3F)
|
||||
|
||||
return ch(0xF0 | c>>18) + ch(0x80 | c>>12 & 0x3F) + ch(0x80 | c>>6 & 0x3F) + ch(0x80 | c & 0x3F)
|
||||
|
||||
|
||||
# Returns the boolean value equivalent to the given input
|
||||
#
|
||||
# @param [String|Object] input The input value
|
||||
# @param [Boolean] strict If set to false, accept 'yes' and 'no' as boolean values
|
||||
#
|
||||
# @return [Boolean] the boolean value
|
||||
#
|
||||
@parseBoolean: (input, strict = true) ->
|
||||
if typeof(input) is 'string'
|
||||
lowerInput = input.toLowerCase()
|
||||
if not strict
|
||||
if lowerInput is 'no' then return false
|
||||
if lowerInput is '0' then return false
|
||||
if lowerInput is 'false' then return false
|
||||
if lowerInput is '' then return false
|
||||
return true
|
||||
return !!input
|
||||
|
||||
|
||||
|
||||
# Returns true if input is numeric
|
||||
#
|
||||
# @param [Object] input The value to test
|
||||
#
|
||||
# @return [Boolean] true if input is numeric
|
||||
#
|
||||
@isNumeric: (input) ->
|
||||
@REGEX_SPACES.lastIndex = 0
|
||||
return typeof(input) is 'number' or typeof(input) is 'string' and !isNaN(input) and input.replace(@REGEX_SPACES, '') isnt ''
|
||||
|
||||
|
||||
# Returns a parsed date from the given string
|
||||
#
|
||||
# @param [String] str The date string to parse
|
||||
#
|
||||
# @return [Date] The parsed date or null if parsing failed
|
||||
#
|
||||
@stringToDate: (str) ->
|
||||
unless str?.length
|
||||
return null
|
||||
|
||||
# Perform regular expression pattern
|
||||
info = @PATTERN_DATE.exec str
|
||||
unless info
|
||||
return null
|
||||
|
||||
# Extract year, month, day
|
||||
year = parseInt info.year, 10
|
||||
month = parseInt(info.month, 10) - 1 # In javascript, january is 0, february 1, etc...
|
||||
day = parseInt info.day, 10
|
||||
|
||||
# If no hour is given, return a date with day precision
|
||||
unless info.hour?
|
||||
date = new Date Date.UTC(year, month, day)
|
||||
return date
|
||||
|
||||
# Extract hour, minute, second
|
||||
hour = parseInt info.hour, 10
|
||||
minute = parseInt info.minute, 10
|
||||
second = parseInt info.second, 10
|
||||
|
||||
# Extract fraction, if given
|
||||
if info.fraction?
|
||||
fraction = info.fraction[0...3]
|
||||
while fraction.length < 3
|
||||
fraction += '0'
|
||||
fraction = parseInt fraction, 10
|
||||
else
|
||||
fraction = 0
|
||||
|
||||
# Compute timezone offset if given
|
||||
if info.tz?
|
||||
tz_hour = parseInt info.tz_hour, 10
|
||||
if info.tz_minute?
|
||||
tz_minute = parseInt info.tz_minute, 10
|
||||
else
|
||||
tz_minute = 0
|
||||
|
||||
# Compute timezone delta in ms
|
||||
tz_offset = (tz_hour * 60 + tz_minute) * 60000
|
||||
if '-' is info.tz_sign
|
||||
tz_offset *= -1
|
||||
|
||||
# Compute date
|
||||
date = new Date Date.UTC(year, month, day, hour, minute, second, fraction)
|
||||
if tz_offset
|
||||
date.setTime date.getTime() - tz_offset
|
||||
|
||||
return date
|
||||
|
||||
|
||||
# Repeats the given string a number of times
|
||||
#
|
||||
# @param [String] str The string to repeat
|
||||
# @param [Integer] number The number of times to repeat the string
|
||||
#
|
||||
# @return [String] The repeated string
|
||||
#
|
||||
@strRepeat: (str, number) ->
|
||||
res = ''
|
||||
i = 0
|
||||
while i < number
|
||||
res += str
|
||||
i++
|
||||
return res
|
||||
|
||||
|
||||
# Reads the data from the given file path and returns the result as string
|
||||
#
|
||||
# @param [String] path The path to the file
|
||||
# @param [Function] callback A callback to read file asynchronously (optional)
|
||||
#
|
||||
# @return [String] The resulting data as string
|
||||
#
|
||||
@getStringFromFile: (path, callback = null) ->
|
||||
xhr = null
|
||||
if window?
|
||||
if window.XMLHttpRequest
|
||||
xhr = new XMLHttpRequest()
|
||||
else if window.ActiveXObject
|
||||
for name in ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP", "Microsoft.XMLHTTP"]
|
||||
try
|
||||
xhr = new ActiveXObject(name)
|
||||
|
||||
if xhr?
|
||||
# Browser
|
||||
if callback?
|
||||
# Async
|
||||
xhr.onreadystatechange = ->
|
||||
if xhr.readyState is 4
|
||||
if xhr.status is 200 or xhr.status is 0
|
||||
callback(xhr.responseText)
|
||||
else
|
||||
callback(null)
|
||||
xhr.open 'GET', path, true
|
||||
xhr.send null
|
||||
|
||||
else
|
||||
# Sync
|
||||
xhr.open 'GET', path, false
|
||||
xhr.send null
|
||||
|
||||
if xhr.status is 200 or xhr.status == 0
|
||||
return xhr.responseText
|
||||
|
||||
return null
|
||||
else
|
||||
# Node.js-like
|
||||
req = require
|
||||
fs = req('fs') # Prevent browserify from trying to load 'fs' module
|
||||
if callback?
|
||||
# Async
|
||||
fs.readFile path, (err, data) ->
|
||||
if err
|
||||
callback null
|
||||
else
|
||||
callback String(data)
|
||||
|
||||
else
|
||||
# Sync
|
||||
data = fs.readFileSync path
|
||||
if data?
|
||||
return String(data)
|
||||
return null
|
||||
|
||||
|
||||
|
||||
module.exports = Utils
|
104
node_modules/yamljs/src/Yaml.coffee
generated
vendored
Normal file
104
node_modules/yamljs/src/Yaml.coffee
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
Parser = require './Parser'
|
||||
Dumper = require './Dumper'
|
||||
Utils = require './Utils'
|
||||
|
||||
# Yaml offers convenience methods to load and dump YAML.
|
||||
#
|
||||
class Yaml
|
||||
|
||||
# Parses YAML into a JavaScript object.
|
||||
#
|
||||
# The parse method, when supplied with a YAML string,
|
||||
# will do its best to convert YAML in a file into a JavaScript object.
|
||||
#
|
||||
# Usage:
|
||||
# myObject = Yaml.parse('some: yaml');
|
||||
# console.log(myObject);
|
||||
#
|
||||
# @param [String] input A string containing YAML
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types, false otherwise
|
||||
# @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
|
||||
#
|
||||
# @return [Object] The YAML converted to a JavaScript object
|
||||
#
|
||||
# @throw [ParseException] If the YAML is not valid
|
||||
#
|
||||
@parse: (input, exceptionOnInvalidType = false, objectDecoder = null) ->
|
||||
return new Parser().parse(input, exceptionOnInvalidType, objectDecoder)
|
||||
|
||||
|
||||
# Parses YAML from file path into a JavaScript object.
|
||||
#
|
||||
# The parseFile method, when supplied with a YAML file,
|
||||
# will do its best to convert YAML in a file into a JavaScript object.
|
||||
#
|
||||
# Usage:
|
||||
# myObject = Yaml.parseFile('config.yml');
|
||||
# console.log(myObject);
|
||||
#
|
||||
# @param [String] path A file path pointing to a valid YAML file
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types, false otherwise
|
||||
# @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
|
||||
#
|
||||
# @return [Object] The YAML converted to a JavaScript object or null if the file doesn't exist.
|
||||
#
|
||||
# @throw [ParseException] If the YAML is not valid
|
||||
#
|
||||
@parseFile: (path, callback = null, exceptionOnInvalidType = false, objectDecoder = null) ->
|
||||
if callback?
|
||||
# Async
|
||||
Utils.getStringFromFile path, (input) =>
|
||||
result = null
|
||||
if input?
|
||||
result = @parse input, exceptionOnInvalidType, objectDecoder
|
||||
callback result
|
||||
return
|
||||
else
|
||||
# Sync
|
||||
input = Utils.getStringFromFile path
|
||||
if input?
|
||||
return @parse input, exceptionOnInvalidType, objectDecoder
|
||||
return null
|
||||
|
||||
|
||||
# Dumps a JavaScript object to a YAML string.
|
||||
#
|
||||
# The dump method, when supplied with an object, will do its best
|
||||
# to convert the object into friendly YAML.
|
||||
#
|
||||
# @param [Object] input JavaScript object
|
||||
# @param [Integer] inline The level where you switch to inline YAML
|
||||
# @param [Integer] indent The amount of spaces to use for indentation of nested nodes.
|
||||
# @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
|
||||
# @param [Function] objectEncoder A function to serialize custom objects, null otherwise
|
||||
#
|
||||
# @return [String] A YAML string representing the original JavaScript object
|
||||
#
|
||||
@dump: (input, inline = 2, indent = 4, exceptionOnInvalidType = false, objectEncoder = null) ->
|
||||
yaml = new Dumper()
|
||||
yaml.indentation = indent
|
||||
|
||||
return yaml.dump(input, inline, 0, exceptionOnInvalidType, objectEncoder)
|
||||
|
||||
|
||||
# Alias of dump() method for compatibility reasons.
|
||||
#
|
||||
@stringify: (input, inline, indent, exceptionOnInvalidType, objectEncoder) ->
|
||||
return @dump input, inline, indent, exceptionOnInvalidType, objectEncoder
|
||||
|
||||
|
||||
# Alias of parseFile() method for compatibility reasons.
|
||||
#
|
||||
@load: (path, callback, exceptionOnInvalidType, objectDecoder) ->
|
||||
return @parseFile path, callback, exceptionOnInvalidType, objectDecoder
|
||||
|
||||
|
||||
# Expose YAML namespace to browser
|
||||
window?.YAML = Yaml
|
||||
|
||||
# Not in the browser?
|
||||
unless window?
|
||||
@YAML = Yaml
|
||||
|
||||
module.exports = Yaml
|
Reference in New Issue
Block a user