q1 (2003.08.30) - inputなど空要素の終了タグが出力される点を修正。 - textareaなど空要素ではない要素で、終了タグが出力されないことがある点を修正 - trの終了タグを省略したときに、次のtr要素がtd要素の子になる点を修正。 - 属性値の置換を有効にした。属性値を'@foo'とする方法で、Amrita v1.8.2と互換。 q2 (2003.10.26) - code cleanup - 要素名、属性名をXML互換に近づけた。要素名、属性名に「:」を含められるようにした。 q3 (2003.11.01) - Amrita::NodeArray#to_a()が正しく動かなかったので、each()を追加した。 - 終了タグを省略できるHTML 4.01要素すべてについて、通常の文書で、要素の 親子関係が正しくなるようにした。 q4 (2003.12.17) - Ruby 1.8.1でXMLParserを使うとエラーになる点を修正した q5 (2003.12.19) - テンプレートの属性値置換指定が残ってしまうことがあった点を修正した。 q6 (2004.03.20) - テンプレートの属性値指定を正しく除去するようにした。q5パッチは修正方法が正しくなかった。 diff -Naur amrita-1.0.2.orig/lib/amrita/compiler.rb amrita-1.0.2-cur/lib/amrita/compiler.rb --- amrita-1.0.2.orig/lib/amrita/compiler.rb 2003-01-05 16:54:44.000000000 +0900 +++ amrita-1.0.2-cur/lib/amrita/compiler.rb 2004-03-20 18:27:06.000000000 +0900 @@ -392,7 +392,7 @@ @model_var_name = model_var_name @delete_id = true - @expand_attr = false + @expand_attr = true @symseq = 1 @debug_compiler = false @@ -599,7 +599,7 @@ e2.delete_attr!(:id) end - if e.no_child? and @static_formatter.can_be_single?(e) + if @static_formatter.empty_tag?(e) self << @static_formatter.format_single_tag(e) return end @@ -652,7 +652,7 @@ end end - _if("e.no_child? and #{dynamic_formatter_var_name}.can_be_single?(e)") do + _if("#{dynamic_formatter_var_name}.empty_tag?(e)") do put_src "#{@dynamic_formatter_var_name} << #{@dynamic_formatter_var_name}.format_single_tag(e)" _else do if block_given? @@ -725,7 +725,7 @@ else e.body.compile(self) end - unless e.no_child? and @static_formatter.can_be_single?(e) + unless @static_formatter.empty_tag?(e) self << @static_formatter.format_end_tag(e) end true diff -Naur amrita-1.0.2.orig/lib/amrita/format.rb amrita-1.0.2-cur/lib/amrita/format.rb --- amrita-1.0.2.orig/lib/amrita/format.rb 2003-01-05 16:54:44.000000000 +0900 +++ amrita-1.0.2-cur/lib/amrita/format.rb 2004-03-20 18:27:06.000000000 +0900 @@ -288,8 +288,8 @@ text end - def can_be_single?(element) #:nodoc: - taginfo_of_element(element).can_be_empty + def empty_tag?(element) #:nodoc: + taginfo_of_element(element).empty_tag end def format_attr_of_element(attr, element) @@ -310,7 +310,7 @@ class AsIsFormatter < Formatter def format_element(element, stream=nil, &block) #:nodoc: with_stream(stream) do - if element.no_child? and can_be_single?(element) + if empty_tag?(element) @stream << format_single_tag(element) else @stream << format_start_tag(element) @@ -339,7 +339,7 @@ def format_element(element, stream=nil, &block) #:nodoc: with_stream(stream) do - if element.no_child? and can_be_single?(element) + if empty_tag?(element) @stream << format_single_tag(element) else @stream << format_start_tag(element) @@ -377,7 +377,7 @@ with_stream(stream) do body = element.body pptype = @tagdict.get_tag_info(element.tagname_symbol).pptype - unless element.no_child? and can_be_single?(element) + unless empty_tag?(element) first = format_start_tag(element) last = format_end_tag(element) @@ -462,7 +462,7 @@ class PreFormatter attr_reader :formatter, :expand_attr - def initialize(formatter, expand_attr=false) + def initialize(formatter, expand_attr = true) @formatter = formatter @expand_attr = expand_attr @result_str = "" @@ -484,7 +484,7 @@ when String @result_str << x when NodeArray - x.array.each do |n| + x.each do |n| n.pre_format1(self) end when Node @@ -524,7 +524,7 @@ # # A pre-formatted Node tree will be expanded faster than # original. But, it produces the same output . - def pre_format(formatter, expand_attr=false) + def pre_format(formatter, expand_attr = true) raise "pre_format dose not suport pretty-print" if formatter.kind_of?(PrettyPrintFormatter) prf = PreFormatter.new(formatter, expand_attr) prf.pre_format(self) diff -Naur amrita-1.0.2.orig/lib/amrita/node.rb amrita-1.0.2-cur/lib/amrita/node.rb --- amrita-1.0.2.orig/lib/amrita/node.rb 2002-12-28 16:45:50.000000000 +0900 +++ amrita-1.0.2-cur/lib/amrita/node.rb 2004-03-20 18:27:06.000000000 +0900 @@ -581,11 +581,10 @@ # represents an Array of Node. It is a Node also. class NodeArray include Node - attr_reader :array + def initialize(*elements) if elements.size() == 1 and elements[0].kind_of?(NodeArray) - a = elements[0] - @array = a.array.collect { |n| n.clone } + @array = elements[0].to_a.collect {|n| n.clone} else @array = elements.collect do |a| #raise "can't be a parent of me!" if a.id == self.id # no recusive check because it costs too much @@ -595,7 +594,6 @@ end def ==(x) - return false unless x.kind_of?(NodeArray) case x when NodeArray, Array return false unless x.size() == @array.size() @@ -620,6 +618,14 @@ @array.empty? end + def each + @array.each {|e| yield e} + end + + def to_a + @array + end + def clone NodeArray.new(self) end diff -Naur amrita-1.0.2.orig/lib/amrita/node_expand.rb amrita-1.0.2-cur/lib/amrita/node_expand.rb --- amrita-1.0.2.orig/lib/amrita/node_expand.rb 2002-10-23 22:38:08.000000000 +0900 +++ amrita-1.0.2-cur/lib/amrita/node_expand.rb 2004-03-20 19:06:29.759739496 +0900 @@ -64,7 +64,8 @@ class String #:nodoc: def amrita_expand_element(e, context) ret = e.clone { Amrita::Node::to_node(self) } - context.filter_element(ret) + new_elem = context.filter_element(ret, false) + new_elem.expand_attr!({}, context) end def amrita_expand_node(n, context) @@ -92,10 +93,12 @@ module Amrita module DictionaryData #:nodoc: + # 要素を展開する。 + # e Elementインスタンス def amrita_expand_element(e, context) hid = e.hid new_elem = context.filter_element(e.clone, false) - new_elem.expand_attr!(self, context) if context.expand_attr + new_elem.expand_attr!(self, context) if !hid if hid =~ /^\w+$/ d = amrita_get_data(hid.intern, e, context) new_elem.expand1(d, context) @@ -107,16 +110,8 @@ end end - def amrita_expand_attr(e, context) #:nodoc: - e.attrs.each do |attr| - next if attr.key_symbol == :id - next unless attr.value - if attr.value[0] == ?@ - e[attr.key_symbol] = amrita_get_data(attr.value[1..-1].intern, e, context) - end - end - end - + # 要素以外を展開する + # n Element以外のNodeサブクラスインスタンス def amrita_expand_node(n, context) n.apply_to_children do |child| child.expand1(self, context) @@ -128,6 +123,8 @@ class Hash #:nodoc: include Amrita::DictionaryData + # key id属性値のシンボル + # element Elementオブジェクト def amrita_get_data(key, element, context) if context.hash_key_is_string self[key.to_s] or self[key] @@ -213,7 +210,7 @@ @do_delete_id = @delete_id = true @delete_id_on_copy = true @hash_key_is_string = false - @expand_attr = false + @expand_attr = true end def delete_id=(flag) #:nodoc: @@ -331,6 +328,7 @@ self[attr.key_symbol] = data.amrita_get_data(attr.value[1..-1].intern, self, context) end end + self end def apply_to_children(&block) diff -Naur amrita-1.0.2.orig/lib/amrita/parser.rb amrita-1.0.2-cur/lib/amrita/parser.rb --- amrita-1.0.2.orig/lib/amrita/parser.rb 2002-10-15 16:48:04.000000000 +0900 +++ amrita-1.0.2-cur/lib/amrita/parser.rb 2004-03-20 18:27:06.000000000 +0900 @@ -1,4 +1,6 @@ +# -*- encoding:euc-jp -*- + require 'strscan' require "amrita/node" require "amrita/tag" @@ -67,6 +69,8 @@ [:tag, ret] end + NAME_RE = /([A-Za-z:_][\w.:-]*)/ + def state_text t = @sc.scan(/\A[^<]*/m) if t @@ -92,7 +96,7 @@ raise "can't happen" unless l == 1 @sc.skip(/\A\s+/m) - if t = @sc.scan(/\A[\/\w]+/) + if t = @sc.scan(/\A\/?#{NAME_RE}/) @state = method(:state_space) @tagname = t nil @@ -116,7 +120,7 @@ if @sc.scan(/\A>|\/>/) @state = method(:state_text) generate_tag - elsif t = @sc.scan(/\A[\w-]+/m) + elsif t = @sc.scan(/\A#{NAME_RE}/m) @attrname = t @state = method(:state_attrname) nil @@ -127,7 +131,7 @@ def state_attrname @sc.skip(/\A\s*/m) - if t = @sc.scan(/\A[\w-]+/m) + if t = @sc.scan(/\A#{NAME_RE}/m) @attrname = t @state = method(:state_before_equal) nil @@ -152,7 +156,7 @@ @attrs << [@attrname, nil] @state = method(:state_text) generate_tag - elsif t = @sc.scan(/\A\w+/) + elsif t = @sc.scan(/\A#{NAME_RE}/) @attrs << [@attrname, nil] @attrvalue = "" @attrname = t diff -Naur amrita-1.0.2.orig/lib/amrita/tag.rb amrita-1.0.2-cur/lib/amrita/tag.rb --- amrita-1.0.2.orig/lib/amrita/tag.rb 2002-10-22 17:10:31.000000000 +0900 +++ amrita-1.0.2-cur/lib/amrita/tag.rb 2004-03-20 18:27:06.000000000 +0900 @@ -65,12 +65,12 @@ # If true, it will be printed