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