class DOMtempl
Constants
- FRAGMENT
- PRETTIFY
Attributes
vars[RW]
Public Class Methods
new(input, flags = 0)
click to toggle source
# File lib/domtempl.rb, line 11 def initialize(input, flags = 0) @vars = { } @var_iters = { } if (!(flags & FRAGMENT).zero?) @_document = Nokogiri::XML::DocumentFragment.parse(input) else @_document = Nokogiri::HTML(open(input)) end parse() end
Public Instance Methods
assign(path, var)
click to toggle source
# File lib/domtempl.rb, line 342 def assign(path, var) write_var(path, var) end
dump()
click to toggle source
# File lib/domtempl.rb, line 346 def dump() reflow() return @_document.to_html() end
dumpXML()
click to toggle source
# File lib/domtempl.rb, line 355 def dumpXML() reflow() return @_document.toxml() end
error( str)
click to toggle source
# File lib/domtempl.rb, line 24 def error( str) puts "Error:" + str end
expand_path(node, base, path = nil)
click to toggle source
# File lib/domtempl.rb, line 142 def expand_path(node, base, path = nil) if (path == nil) then path = node.get_attribute(base) end top = node.parent while path[0] != '/' top_path = ''; if (!top) then path = '/' + path; break; end if (top.type != Nokogiri::XML::Node::ELEMENT_NODE) top = top.parent next; end if (top.has_attribute?('data-from')) top_path = top.get_attribute('data-from') + '.'; elsif (top.has_attribute?('data-each')) top_path = top.get_attribute('data-each') + '/'; elsif (top.has_attribute?('data-same')) top_path = top.get_attribute('data-same') + '/'; elsif (top.has_attribute?('data-when')) top_path = top.get_attribute('data-when') + '.'; end path = top_path + path; top = top.parent end return path end
out()
click to toggle source
# File lib/domtempl.rb, line 351 def out() print dump() end
outXML()
click to toggle source
# File lib/domtempl.rb, line 360 def outXML() print dumpXML() end
parse()
click to toggle source
# File lib/domtempl.rb, line 338 def parse() parse_vars_node(@_document) end
parse_vars_node(root)
click to toggle source
# File lib/domtempl.rb, line 169 def parse_vars_node(root) for node in root.children if (node.type == Nokogiri::XML::Node::ELEMENT_NODE and node.attributes()) if node.has_attribute?('data-each') @var_iters[ expand_path(node, 'data-each') ] = 0 end if node.has_attribute?('data-same') @var_iters[ expand_path(node, 'data-same') ] += 1 end #for attr in node.get_attributes: # print attr for i in 0..node.attributes.length-1 attr = node.attribute_nodes[i] if (attr.name.include?('data-attr-')) key = attr.name['data-attr'.length..-1] write_var( expand_path(node, '', not(attr.value) ? key : attr.value), node.get_attribute(key).to_s ) end end if node.has_attribute?('data-var') write_var( expand_path(node, 'data-var'), node.inner_text() ) end if node.has_attribute?('data-when') write_var( expand_path(node, 'data-when'), true, 1 ) end end if node.children parse_vars_node(node) end end end
read_var(path)
click to toggle source
# File lib/domtempl.rb, line 28 def read_var(path) if (path[0] == '/') then path = path[1..-1] end walk = path.split(/(\.|\/)/, -1) #, -1, PREG_SPLIT_DELIM_CAPTURE); #puts "let's r-walk [" + path + "] {" #puts walk #puts " } " #puts @vars cpath = '/' ptr = @vars last = walk[ walk.length - 1 ] (0..walk.length-2).step(2).each do |i| step = walk[i] mod = walk[i+1] cpath += step if (ptr[step].nil?) error('undefined array "' + step + '" of path ' + path) return nil; end ptr = ptr[step]; if (mod == '/') n = @var_iters[cpath]; #puts sprintf("Iterator of `%s` is %d", cpath, n) if (ptr[n].nil?) error(('cant iterate through "%d"' % n) + ' of path ' + path); return nil; end ptr = ptr[n]; if (last == '*' and i == walk.length - 3) then return n; end # Hack -- iterator itself if (last == '' and i == walk.length - 3) then break; end end cpath += mod; end if (last == '') return ptr; end if (ptr[last].nil?) error('undefined variable "'+last+'" of path "' + path + '"'); return nil; end return ptr[ last ]; end
reflow()
click to toggle source
# File lib/domtempl.rb, line 326 def reflow() # Reset iteration counters if (@var_iters) for i in @var_iters.keys @var_iters[i] = 0; end end # Reflow all variables replace_vars(@_document); end
replace_vars(root)
click to toggle source
# File lib/domtempl.rb, line 264 def replace_vars(root) for i in 0..root.children.length-1 if i >= root.children.length # because range/xrange doesn't change :(( break end node = root.children[i]; clean = [] if (node.type == Nokogiri::XML::Node::ELEMENT_NODE and node.attributes()) if node.has_attribute?('data-when') if not( read_var(expand_path(node, 'data-when')) ) i -= safe_remove(node); next; end clean.push( 'data-when' ); end if (node.has_attribute?('data-same')) clean.push( 'data-same' ); next; end if (node.has_attribute?('data-each')) clean.push( 'data-each' ); path = expand_path(node, 'data-each'); arr = read_var(path); # Kill marked siblings kill = node.next_sibling; while (kill) _next = kill.next_sibling; if (kill.type == Nokogiri::XML::Node::ELEMENT_NODE and kill.has_attribute('data-same')) safe_remove(kill); end kill = _next; end #print "Cloning time with" #print arr if (arr.length) # Clone new siblings last = nil; (1..arr.length-1).each do |j| #puts sprintf("Doing clone #%d, setting var iter of /%s", j, path); @var_iters[path] = j; nod = safe_clone(node, last); last = nod; nod.remove_attribute('data-each'); nod.set_attribute('data-same', path); replace_vars_node(nod, ['data-same']); end @var_iters[path] = 0; end #print "CLONE COMPLETE" end replace_vars_node( node, clean ); end end end
replace_vars_node(node, clean)
click to toggle source
# File lib/domtempl.rb, line 217 def replace_vars_node(node, clean) stop_here = false; #hack, for speed if (node.attributes) if (node.type == Nokogiri::XML::Node::ELEMENT_NODE) j = -1 #for (j = 0; j < node.get_attributes.length; j++): while j < node.attributes.length - 1 j += 1 attr = node.attribute_nodes[j]; if (attr.name.include?('data-attr-')) key = attr.name['data-attr-'.length..-1] path = expand_path(node, '', (not(attr.value) ? key : attr.value)); val = read_var(path); if (val != false) node.set_attribute(key, val); end clean.push( attr.name ); end end if (node.has_attribute?('data-var')) #print "\nReplacing data-var for `" #print node #puts "` using the path `" + expand_path(node, 'data-var') + "`" clean.push( 'data-var' ) node.inner_html = read_var(expand_path(node, 'data-var')) ; #print "Inner html is now:" + node.toxml() #print "\n" stop_here = true; # do not traverse children of inserted node end end end if (node.children and not(stop_here)) # stop here if 'data-var' was used replace_vars(node); end for attr in clean node.remove_attribute(attr); end end
safe_clone(elem, after = nil)
click to toggle source
# File lib/domtempl.rb, line 382 def safe_clone(elem, after = nil) if after == nil then after = elem; end #print "Must clone " #puts elem #print " after " #puts after #if (elem.cloneNode) orig = elem.previous_sibling; ident = nil; if (orig != nil \ and orig.type == Nokogiri::XML::Node::TEXT_NODE \ and orig.inner_text.strip() == '' #and orig.isWhitespaceInElementContent ) ident = orig.clone(); #print "Found ident (" #print ident.inner_text.length #print ident #print ")" #puts "" end cln = elem.clone(); # Note: because Nokogiri has different DOM-append methods, # we do not need appendChild/insertBefore wraps after.after(cln); if (ident) then cln.before(ident); end return cln; #end #return nil; end
safe_remove(node)
click to toggle source
# File lib/domtempl.rb, line 364 def safe_remove(node) ident = node.previous_sibling; #print "and ws is " #print ident.isWhitespaceInElementContent r = 0; if (ident != nil \ and ident.type == Nokogiri::XML::Node::TEXT_NODE \ and ident.inner_text.strip() == '' #and ident.isWhitespaceInElementContent ) ident.remove(); r = 1; end node.remove() return r end
write_var(path, val, no_overwrite = false)
click to toggle source
# File lib/domtempl.rb, line 83 def write_var(path, val, no_overwrite = false) if (path[0] == '/') then path = path[1..path.length]; end walk = path.split(/(\.|\/)/, -1); #, -1, PREG_SPLIT_DELIM_CAPTURE); cpath = '/'; ptr = @vars; last = walk[ walk.length - 1 ]; #puts "Lets w-walk [ " + path + "] { " #puts walk #puts "}" (0..walk.length-2).step(2).each do |i| step = walk[i] mod = walk[i+1] cpath += step if (mod == '/') n = 0; if (ptr[step].nil? or ptr[step] == true) ptr[step] = [ ] @var_iters[cpath] = 0 else n = @var_iters[cpath] end ptr = ptr[step] if (last == '' and i == walk.length - 3) then break; end if (ptr[n].nil?) ptr[n] = { } end ptr = ptr[n] end if (mod == '.') if (ptr[step].nil? or ptr[step] == true) ptr[step] = { } end ptr = ptr[step] end cpath += mod end if (last == '') #print ptr #if isinstance(ptr, dict) # ptr[ ptr.length ] = val; #else ptr.push( val ); #end return; end if (no_overwrite and not(ptr[last].nil?)) then return; end # puts "Setting [" + last + "]" # puts "in" # puts ptr ptr[ last ] = val; end