lib/wunderbar/node.rb in wunderbar-0.21.4 vs lib/wunderbar/node.rb in wunderbar-0.22.0

- old
+ new

@@ -44,14 +44,21 @@ def walk(result, indent, options) indent += options[:indent] if indent and parent first = true spaced = false + + if preserve_spaces? + options = options.dup + options[:space] = :preserve + end + children.each do |child| next unless child result << '' if (spaced or SpacedNode === child) and not first if String === child + child = child.gsub(/\s+/, ' ') unless options[:space] == :preserve result << child else child.serialize(options, result, indent) end first = false @@ -68,26 +75,28 @@ value=name if value==true line += " #{name}=\"#{value.to_s.gsub(/[&\"<>]/,ESCAPE)}\"" end if children.empty? - if text - if options[:pre] - line += ">#{options[:pre]}#{text}#{options[:post]}</#{name}>" - else - width = options[:width] if name != :pre + if options[:pre] + line += ">#{options[:pre]}#{text}#{options[:post]}</#{name}>" + else + width = options[:width] unless preserve_spaces? + + if text line += ">#{text.to_s.gsub(/[&<>]/,ESCAPE)}</#{name}>" - if indent and width and line.length > width - reflowed = IndentedTextNode.reflow(indent, line, width) - line = reflowed.pop - result.push *reflowed - end + elsif VOID.include? name.to_s + line += "/>" + else + line += "></#{name}>" end - elsif VOID.include? name.to_s - line += "/>" - else - line += "></#{name}>" + + if indent and width and line.length > width + reflowed = IndentedTextNode.reflow(indent, line, width) + line = reflowed.pop + result.push *reflowed + end end elsif CompactNode === self and not CompactNode === parent work = [] walk(work, nil, options) width = options[:width] @@ -111,11 +120,11 @@ tokens.each do |token| if line.length + token.length < width line += ' ' + token else result << line - line = indent.to_s + token + line = indent.to_s + options[:indent] + token end end end else line += ">#{work.join}</#{name}>" @@ -129,10 +138,14 @@ end result << line if parent result end + + def preserve_spaces? + false + end end class CommentNode def initialize(text) @text = text @@ -154,11 +167,17 @@ result << "<!#{@declare} #{@name.to_s}>" result end end - class CDATANode < Node + class PreformattedNode < Node + def preserve_spaces? + true + end + end + + class CDATANode < PreformattedNode def self.normalize(data, indent='') data = data.sub(/\n\s*\Z/, '').sub(/\A\s*\n/, '') unindent = data.sub(/s+\Z/,'').scan(/^ *\S/).map(&:length).min || 0 @@ -175,11 +194,11 @@ children.unshift CDATANode.normalize(@text, tindent).rstrip @text = nil end if @text and @text =~ /[<^>]/ - indent += ' ' if indent + indent += options[:indent] if indent children.unshift @text.gsub(/^/, indent).gsub(/^ +$/,'').rstrip @text = nil super(options.merge(pre: pre, post: post), result, indent) elsif children && children.any? {|node| String===node && node =~ /[<^>]/} super(options.merge(pre: pre, post: post), result, indent) @@ -193,16 +212,22 @@ def initialize(*args) super(nil, *args) end def serialize(options, result, indent) - result << @text.to_s.gsub(/[&<>]/,ESCAPE) + if options[:space] == :preserve + result << @text.to_s.gsub(/[&<>]/,ESCAPE) + else + result << @text.to_s.gsub(/[&<>]/,ESCAPE).gsub(/\s+/, ' ') + end end end class IndentedTextNode < TextNode def self.reflow(indent, line, width) - return [line] if line.include? "\n" or not width + return [line] unless width and indent + line = indent + line.gsub!(/\s+/, ' ').strip + indent += ' ' result = [] while line.length > width split = line.rindex(' ', width) break if not split or split <= indent.to_s.length