lib/opulent/parser/node.rb in opulent-1.5.5 vs lib/opulent/parser/node.rb in opulent-1.6.0

- old
+ new

@@ -8,87 +8,86 @@ # node [ attributes ] Inline text # # @param parent [Node] Parent node to which we append the node # def node(parent, indent = nil) - if (name = lookahead(:node_lookahead) || lookahead(:shorthand_lookahead)) - return nil if KEYWORDS.include? name[0].to_sym + return unless (name = lookahead(:node_lookahead) || + lookahead(:shorthand_lookahead)) - # Accept either explicit node_name or implicit :div node_name - # with shorthand attributes - if (node_name = accept :node) - node_name = node_name.to_sym - shorthand = shorthand_attributes - elsif (shorthand = shorthand_attributes) - node_name = :div - end + return nil if KEYWORDS.include? name[0].to_sym - # Node creation options - options = {} + # Accept either explicit node_name or implicit :div node_name + # with shorthand attributes + if (node_name = accept :node) + node_name = node_name.to_sym + shorthand = shorthand_attributes + elsif (shorthand = shorthand_attributes) + node_name = :div + end - # Get leading and trailing whitespace - if accept_stripped :leading_whitespace - options[:leading_whitespace] = true - if accept :leading_trailing_whitespace - options[:trailing_whitespace] = true - end - elsif accept_stripped :trailing_whitespace - options[:trailing_whitespace] = true - end + # Node creation options + options = {} - # Get wrapped node attributes - atts = attributes(shorthand) || {} + # Get leading whitespace + options[:leading_whitespace] = accept_stripped(:leading_whitespace) - # Inherit attributes from definition - options[:extension] = extension = extend_attributes + # Get trailing whitespace + options[:trailing_whitespace] = accept_stripped(:trailing_whitespace) - # Get unwrapped node attributes - options[:attributes] = attributes_assignments atts, false + # Get wrapped node attributes + atts = attributes(shorthand) || {} - # Create node - current_node = [:node, node_name, options, [], indent] + # Inherit attributes from definition + options[:extension] = extend_attributes - # Check if the node is explicitly self enclosing - if(close = accept_stripped :self_enclosing) || (!@definitions.keys.include?(node_name) && Settings::SelfEnclosing.include?(node_name)) - current_node[@options][:self_enclosing] = true + # Get unwrapped node attributes + options[:attributes] = attributes_assignments atts, false - unless close.nil? || close.strip.empty? - undo close; error :self_enclosing - end + # Create node + current_node = [:node, node_name, options, [], indent] - # For self enclosing tag error reporting purposes - line = @i - end + # Check for self enclosing tags and definitions + def_check = !@definitions.keys.include?(node_name) && + Settings::SELF_ENCLOSING.include?(node_name) - # Check whether we have explicit inline elements and add them - # with increased base indentation - if (accept :inline_child) - # Inline node element - unless (child_node = node current_node, indent) - error :inline_child - end - else - # Inline text element - text_node = text current_node, indent, false + # Check if the node is explicitly self enclosing + if (close = accept_stripped :self_enclosing) || def_check + current_node[@options][:self_enclosing] = true + + unless close.nil? || close.strip.empty? + undo close + Logger.error :parse, @code, @i, @j, :self_enclosing end + end - # Add the current node to the root - root(current_node, indent) + # Check whether we have explicit inline elements and add them + # with increased base indentation + if accept :inline_child + # Inline node element + Logger.error :parse, + @code, + @i, + @j, + :inline_child unless node current_node, indent + elsif comment current_node, indent + # Accept same line comments + else + # Accept inline text element + text current_node, indent, false + end - # if current_node[@options][:self_enclosing] && current_node[@children].any? - # error :self_enclosing_children, line - # end + # Add the current node to the root + root current_node, indent - # Create a clone of the definition model. Cloning the options is also - # necessary because it's a shallow copy - if @definitions.keys.include?(node_name) - @definition_stack << node_name - parent[@children] << process_definition(node_name, current_node) - @definition_stack.pop - else - parent[@children] << current_node - end + # Create a clone of the definition model. Cloning the options is also + # necessary because it's a shallow copy + if @definitions.keys.include?(node_name) + @definition_stack << node_name + parent[@children] << process_definition(node_name, current_node) + @definition_stack.pop + else + parent[@children] << current_node end end # When entering a definition model, we replace all the node types with their # know definitions at definition call time. @@ -105,17 +104,22 @@ # for the initial call node children and for the model # children process_definition_child model[@options][:call] process_definition_child model - return model + model end + # Process definition children for the current node. + # + # @param node [Node] Callee node + # def process_definition_child(node) node[@children].map! do |child| if child[@type] == :node - if !@definition_stack.include?(child[@value]) && @definitions.keys.include?(child[@value]) + if !@definition_stack.include?(child[@value]) && + @definitions.keys.include?(child[@value]) process_definition child[@value], child else process_definition_child child if child[@children] child end @@ -152,124 +156,138 @@ # # @param atts [Hash] Node attributes # def shorthand_attributes(atts = {}) while (key = accept :shorthand) - key = Settings::Shorthand[key.to_sym] + key = Settings::SHORTHAND[key.to_sym] # Check whether the value is escaped or unescaped escaped = accept(:unescaped_value) ? false : true # Get the attribute value and process it if (value = accept(:node)) - value = [:expression, value.inspect, {escaped: escaped}] + value = [:expression, value.inspect, { escaped: escaped }] elsif (value = accept(:exp_string)) - value = [:expression, value, {escaped: escaped}] + value = [:expression, value, { escaped: escaped }] elsif (value = paranthesis) - value = [:expression, value, {escaped: escaped}] + value = [:expression, value, { escaped: escaped }] else - error :shorthand + Logger.error :parse, @code, @i, @j, :shorthand end # IDs are unique, the rest of the attributes turn into arrays in # order to allow multiple values or identifiers add_attribute(atts, key, value) end - return atts + atts end + # Get element attributes + # + # @atts [Hash] Accumulator for node attributes + # def attributes(atts = {}) wrapped_attributes atts attributes_assignments atts, false - - return atts + atts end - # Check if we match node attributes # # [ assignments ] # # @param as_parameters [Boolean] Accept or reject identifier nodes # def wrapped_attributes(list) if (bracket = accept :brackets) - attributes_assignments list - accept bracket.to_sym, :* + accept_newline + attributes_assignments list, true + accept_newline + + accept_stripped bracket.to_sym, :* end - return list + list end # Check if we match an expression node or # a node node # # [ assignments ] # - # @param parent [Hash] Parent to which we append nodes + # @param list [Hash] Parent to which we append nodes # @param as_parameters [Boolean] Accept or reject identifier nodes # - def attributes_assignments(parent, wrapped = true) - unless wrapped - return parent if lookahead(:assignment_lookahead).nil? + def attributes_assignments(list, wrapped = true) + if wrapped && lookahead(:exp_identifier_stripped_lookahead).nil? || + !wrapped && lookahead(:assignment_lookahead).nil? + return list end - if (argument = accept_stripped :node) - argument = argument.to_sym + return unless (argument = accept_stripped :node) - if accept :assignment - # Check if we have an attribute escape or not - escaped = if accept :assignment_unescaped - false - else - true - end + argument = argument.to_sym - # Get the argument value if we have an assignment - if (value = expression(false, wrapped)) - value[@options][:escaped] = escaped + if accept_stripped :assignment + # Check if we have an attribute escape or not + escaped = if accept :assignment_unescaped + false + else + true + end - # IDs are unique, the rest of the attributes turn into arrays in - # order to allow multiple values or identifiers - add_attribute(parent, argument, value) - else - error :assignments_colon - end + # Get the argument value if we have an assignment + if (value = expression(false, wrapped)) + value[@options][:escaped] = escaped + + # IDs are unique, the rest of the attributes turn into arrays in + # order to allow multiple values or identifiers + add_attribute(list, argument, value) else - parent[argument] = [:expression, "nil", {escaped: false}] unless parent[argument] + Logger.error :parse, @code, @i, @j, :assignments_colon end - - # If our attributes are wrapped, we allow method calls without - # paranthesis, ruby style, therefore we need a terminator to signify - # the expression end. If they are not wrapped (inline), we require - # paranthesis and allow inline calls - if wrapped && accept_stripped(:assignment_terminator) - attributes_assignments parent, wrapped - elsif !wrapped && lookahead(:assignment_lookahead) - attributes_assignments parent, wrapped + else + unless list[argument] + list[argument] = [:expression, 'true', { escaped: false }] end + end - return parent - elsif !parent.empty? - error :assignments_comma + # If our attributes are wrapped, we allow method calls without + # paranthesis, ruby style, therefore we need a terminator to signify + # the expression end. If they are not wrapped (inline), we require + # paranthesis and allow inline calls + if wrapped + # Accept optional comma between attributes + accept_stripped :assignment_terminator + + # Lookahead for attributes on the current line and the next one + if lookahead(:exp_identifier_stripped_lookahead) + attributes_assignments list, wrapped + elsif lookahead_next_line(:exp_identifier_stripped_lookahead) + accept_newline + attributes_assignments list, wrapped + end + elsif !wrapped && lookahead(:assignment_lookahead) + attributes_assignments list, wrapped end + + list end # Extend node attributes with hash from # # +value # +{hash: "value"} # +(paranthesis) # def extend_attributes - if (accept :extend_attributes) - unescaped = accept :unescaped_value + return unless accept :extend_attributes + unescaped = accept :unescaped_value - extension = expression(false, false, false) - extension[@options][:escaped] = false if unescaped + extension = expression(false, false, false) + extension[@options][:escaped] = !unescaped - return extension - end + extension end end end