UNPKG

compound-ex4

Version:

Compound-ex4 - MVC framework for NodeJS (ExpressJs 4 version), fork compoundjs(https://github.com/1602/compound)

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