kwartz 3.1.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. data/CHANGES +444 -0
  2. data/README.txt +4 -1
  3. data/bin/kwartz +2 -2
  4. data/doc-api/classes/Kwartz.html +16 -7
  5. data/doc-api/classes/Kwartz/Assertion.html +6 -6
  6. data/doc-api/classes/Kwartz/AssertionError.html +6 -6
  7. data/doc-api/classes/Kwartz/AttrInfo.html +71 -61
  8. data/doc-api/classes/Kwartz/BaseError.html +12 -12
  9. data/doc-api/classes/Kwartz/BaseTranslator.html +104 -74
  10. data/doc-api/classes/Kwartz/CharacterType.html +24 -24
  11. data/doc-api/classes/Kwartz/CommandOptionError.html +7 -7
  12. data/doc-api/classes/Kwartz/CommandOptions.html +50 -50
  13. data/doc-api/classes/Kwartz/Config.html +5 -0
  14. data/doc-api/classes/Kwartz/ConvertError.html +12 -12
  15. data/doc-api/classes/Kwartz/Converter.html +31 -33
  16. data/doc-api/classes/Kwartz/CssStyleParser.html +207 -168
  17. data/doc-api/classes/Kwartz/Defun.html +32 -31
  18. data/doc-api/classes/Kwartz/{HandlerArgument.html → Directive.html} +27 -53
  19. data/doc-api/classes/Kwartz/ElementInfo.html +68 -53
  20. data/doc-api/classes/Kwartz/EperlExpressionParser.html +185 -0
  21. data/doc-api/classes/Kwartz/EperlHandler.html +65 -58
  22. data/doc-api/classes/Kwartz/EperlTranslator.html +14 -7
  23. data/doc-api/classes/Kwartz/ErubisTranslator.html +14 -7
  24. data/doc-api/classes/Kwartz/ErubyTranslator.html +14 -7
  25. data/doc-api/classes/Kwartz/ExpandStatement.html +20 -20
  26. data/doc-api/classes/Kwartz/Expander.html +358 -0
  27. data/doc-api/classes/Kwartz/Handler.html +287 -157
  28. data/doc-api/classes/Kwartz/{StatementHelper.html → HandlerHelper.html} +307 -112
  29. data/doc-api/classes/Kwartz/Helper/ActionViewHelper.html +23 -23
  30. data/doc-api/classes/Kwartz/Helper/RailsTemplate.html +96 -96
  31. data/doc-api/classes/Kwartz/JstlExpressionParser.html +181 -0
  32. data/doc-api/classes/Kwartz/JstlHandler.html +134 -126
  33. data/doc-api/classes/Kwartz/JstlTranslator.html +21 -14
  34. data/doc-api/classes/Kwartz/KwartzError.html +6 -6
  35. data/doc-api/classes/Kwartz/Main.html +4 -4
  36. data/doc-api/classes/Kwartz/NativeExpression.html +19 -19
  37. data/doc-api/classes/Kwartz/NativeStatement.html +24 -24
  38. data/doc-api/classes/Kwartz/Node.html +7 -7
  39. data/doc-api/classes/Kwartz/PIErubisTranslator.html +21 -14
  40. data/doc-api/classes/Kwartz/ParseError.html +6 -6
  41. data/doc-api/classes/Kwartz/PerlExpressionParser.html +185 -0
  42. data/doc-api/classes/Kwartz/PerlHandler.html +353 -0
  43. data/doc-api/classes/Kwartz/PerlTranslator.html +226 -0
  44. data/doc-api/classes/Kwartz/PhpExpressionParser.html +185 -0
  45. data/doc-api/classes/Kwartz/PhpHandler.html +63 -56
  46. data/doc-api/classes/Kwartz/PhpTranslator.html +21 -14
  47. data/doc-api/classes/Kwartz/PresentationLogicParser.html +126 -123
  48. data/doc-api/classes/Kwartz/PrintStatement.html +18 -18
  49. data/doc-api/classes/Kwartz/RailsHandler.html +84 -85
  50. data/doc-api/classes/Kwartz/RailsTranslator.html +13 -6
  51. data/doc-api/classes/Kwartz/RubyExpressionParser.html +180 -0
  52. data/doc-api/classes/Kwartz/RubyHandler.html +73 -69
  53. data/doc-api/classes/Kwartz/RubyStyleParser.html +86 -86
  54. data/doc-api/classes/Kwartz/RubyTranslator.html +28 -21
  55. data/doc-api/classes/Kwartz/Ruleset.html +622 -1
  56. data/doc-api/classes/Kwartz/StrutsTranslator.html +14 -14
  57. data/doc-api/classes/Kwartz/TagInfo.html +52 -27
  58. data/doc-api/classes/Kwartz/TextConverter.html +75 -37
  59. data/doc-api/classes/Kwartz/Translator.html +54 -53
  60. data/doc-api/classes/Kwartz/Util.html +25 -25
  61. data/doc-api/created.rid +1 -1
  62. data/doc-api/files/__/README_txt.html +7 -2
  63. data/doc-api/files/kwartz/assert_rb.html +2 -2
  64. data/doc-api/files/kwartz/binding/eperl_rb.html +2 -2
  65. data/doc-api/files/kwartz/binding/erubis_rb.html +2 -2
  66. data/doc-api/files/kwartz/binding/eruby_rb.html +2 -2
  67. data/doc-api/files/kwartz/binding/jstl_rb.html +2 -2
  68. data/doc-api/files/kwartz/binding/perl_rb.html +115 -0
  69. data/doc-api/files/kwartz/binding/php_rb.html +2 -2
  70. data/doc-api/files/kwartz/binding/pierubis_rb.html +2 -2
  71. data/doc-api/files/kwartz/binding/rails_rb.html +2 -2
  72. data/doc-api/files/kwartz/binding/ruby_rb.html +2 -2
  73. data/doc-api/files/kwartz/binding/struts_rb.html +2 -2
  74. data/doc-api/files/kwartz/config_rb.html +2 -2
  75. data/doc-api/files/kwartz/converter_rb.html +2 -2
  76. data/doc-api/files/kwartz/defun_rb.html +2 -2
  77. data/doc-api/files/kwartz/error_rb.html +2 -2
  78. data/doc-api/files/kwartz/helper/rails_rb.html +2 -2
  79. data/doc-api/files/kwartz/main_rb.html +3 -2
  80. data/doc-api/files/kwartz/node_rb.html +2 -2
  81. data/doc-api/files/kwartz/parser_rb.html +2 -2
  82. data/doc-api/files/kwartz/translator_rb.html +2 -2
  83. data/doc-api/files/kwartz/util/assert-text-equal_rb.html +2 -2
  84. data/doc-api/files/kwartz/util/testcase-helper_rb.html +2 -2
  85. data/doc-api/files/kwartz/util_rb.html +2 -2
  86. data/doc-api/files/kwartz_rb.html +2 -2
  87. data/doc-api/fr_class_index.html +10 -5
  88. data/doc-api/fr_file_index.html +1 -0
  89. data/doc-api/fr_method_index.html +268 -239
  90. data/doc/docstyle.css +9 -3
  91. data/doc/img/fig05.png +0 -0
  92. data/doc/introduction-to-kwartz.html +3040 -0
  93. data/doc/pattern-catalog.html +5 -3
  94. data/doc/reference.html +680 -26
  95. data/doc/users-guide.html +222 -67
  96. data/kwartz.gemspec +4 -4
  97. data/lib/kwartz.rb +3 -3
  98. data/lib/kwartz/assert.rb +2 -2
  99. data/lib/kwartz/binding/eperl.rb +71 -31
  100. data/lib/kwartz/binding/erubis.rb +3 -2
  101. data/lib/kwartz/binding/eruby.rb +3 -2
  102. data/lib/kwartz/binding/jstl.rb +66 -29
  103. data/lib/kwartz/binding/perl.rb +230 -0
  104. data/lib/kwartz/binding/php.rb +69 -29
  105. data/lib/kwartz/binding/pierubis.rb +3 -2
  106. data/lib/kwartz/binding/rails.rb +18 -18
  107. data/lib/kwartz/binding/ruby.rb +74 -42
  108. data/lib/kwartz/binding/struts.rb +22 -21
  109. data/lib/kwartz/config.rb +4 -4
  110. data/lib/kwartz/converter.rb +465 -345
  111. data/lib/kwartz/defun.rb +2 -2
  112. data/lib/kwartz/error.rb +2 -2
  113. data/lib/kwartz/helper/rails.rb +2 -2
  114. data/lib/kwartz/main.rb +5 -4
  115. data/lib/kwartz/node.rb +92 -144
  116. data/lib/kwartz/parser.rb +112 -103
  117. data/lib/kwartz/translator.rb +14 -6
  118. data/lib/kwartz/util.rb +2 -2
  119. data/lib/kwartz/util/assert-text-equal.rb +2 -2
  120. data/lib/kwartz/util/testcase-helper.rb +1 -1
  121. data/test/test-compile.rb +2 -2
  122. data/test/test-compile.yaml +81 -0
  123. data/test/test-converter.rb +4 -8
  124. data/test/test-converter.yaml +152 -3
  125. data/test/test-directives.rb +2 -2
  126. data/test/test-directives.yaml +222 -0
  127. data/test/test-main.rb +6 -4
  128. data/test/test-main.yaml +66 -1
  129. data/test/test-parser.rb +12 -3
  130. data/test/test-parser.yaml +64 -51
  131. data/test/test-rails.rb +2 -2
  132. data/test/test-ruleset.rb +2 -2
  133. data/test/test-ruleset.yaml +465 -4
  134. data/test/test.log +6 -0
  135. data/test/test.rb +2 -2
  136. metadata +116 -106
  137. data/ChangeLog +0 -156
  138. data/doc-api/classes/Kwartz/DocumentRuleset.html +0 -369
  139. data/doc-api/classes/Kwartz/ElementExpander.html +0 -325
  140. data/doc-api/classes/Kwartz/ElementRuleset.html +0 -612
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 128 $
3
- ### $Release: 3.1.2 $
2
+ ### $Rev$
3
+ ### $Release: 3.2.0 $
4
4
  ### copyright(c) 2004-2006 kuwata-lab.com all rights reserved
5
5
  ###
6
6
 
@@ -12,11 +12,45 @@ require 'kwartz/translator'
12
12
  module Kwartz
13
13
 
14
14
 
15
+ module RubyExpressionParser
16
+
17
+
18
+ def parse_expr_str(expr_str, linenum)
19
+ case expr_str
20
+ when /\A(\w+)\z/ # variable
21
+ expr = expr_str
22
+ when /\A(\w+)\.(\w+)\z/ # object.property
23
+ expr = expr_str
24
+ when /\A(\w+)\[('.*?'|".*?"|:\w+)\]\z/ # hash
25
+ expr = expr_str
26
+ when /\A(\w+)\[(\w+)\]\z/ # array or hash
27
+ expr = expr_str
28
+ else
29
+ raise convert_error("'#{expr_str}': invalid expression.", linenum)
30
+ end
31
+ return expr
32
+ end
33
+
34
+
35
+ def parse_expr_str!(expr_str)
36
+ begin
37
+ return parse_expr_str!(expr_str, -1)
38
+ rescue
39
+ return expr_str
40
+ end
41
+ end
42
+
43
+
44
+ end
45
+
46
+
47
+
15
48
 
16
49
  ##
17
50
  ## directive handler for Ruby
18
51
  ##
19
52
  class RubyHandler < Handler
53
+ include RubyExpressionParser
20
54
 
21
55
 
22
56
  RUBY_DIRECTIVE_PATTERN = /\A(\w+)(?:[:\s]\s*(.*))?\z/
@@ -40,24 +74,21 @@ module Kwartz
40
74
  end
41
75
 
42
76
 
43
- def handle(stmt_list, handler_arg)
77
+ def handle(directive, elem_info, stmt_list)
44
78
  ret = super
45
79
  return ret if ret
46
80
 
47
- arg = handler_arg
48
- d_name = arg.directive_name
49
- d_arg = arg.directive_arg
50
- d_str = arg.directive_str
51
- #stag_info = arg.stag_info
52
- #etag_info = arg.etag_info
53
- #cont_stmts = arg.cont_stmts
81
+ d_name = directive.name
82
+ d_arg = directive.arg
83
+ d_str = directive.str
84
+ e = elem_info
54
85
 
55
86
  case d_name
56
87
 
57
88
  when :for, :For, :FOR, :list, :List, :LIST
58
89
  unless d_arg =~ /\A(\w+)(?:,\s*(\w+))?\s+in\s+(.*)\z/ \
59
90
  || d_arg =~ /\A(\w+)(?:,(\w+))?\s*[:=]\s*(.*)\z/
60
- raise convert_error("'#{d_str}': invalid argument.", arg.stag_info.linenum)
91
+ raise convert_error("'#{d_str}': invalid argument.", e.stag_info.linenum)
61
92
  end
62
93
  loopvar = $1 ; loopval = $2 ; looplist = $3
63
94
  is_foreach = d_name == :for || d_name == :For || d_name == :FOR
@@ -71,70 +102,70 @@ module Kwartz
71
102
  code << " #{counter} += 1" if counter
72
103
  code << " #{toggle} = #{counter}%2==0 ? #{@even} : #{@odd}" if toggle
73
104
  if is_foreach
74
- wrap_element_with_native_stmt(stmt_list, arg, code, "end", :foreach)
105
+ wrap_element_with_native_stmt(elem_info, stmt_list, code, "end", :foreach)
75
106
  else
76
- wrap_content_with_native_stmt(stmt_list, arg, code, "end", :foreach)
107
+ wrap_content_with_native_stmt(elem_info, stmt_list, code, "end", :foreach)
77
108
  end
78
109
 
79
110
  when :while
80
- wrap_element_with_native_stmt(stmt_list, arg, "while #{d_arg} do", "end", :while)
111
+ wrap_element_with_native_stmt(elem_info, stmt_list, "while #{d_arg} do", "end", :while)
81
112
  #stmt_list << NativeStatement.new("while #{d_arg} do", :while)
82
- #stmt_list << stag_stmt(arg)
83
- #stmt_list.concat(arg.cont_stmts)
84
- #stmt_list << etag_stmt(arg)
113
+ #stmt_list << stag_stmt(elem_info)
114
+ #stmt_list.concat(e.cont_stmts)
115
+ #stmt_list << etag_stmt(elem_info)
85
116
  #stmt_list << NativeStatement.new("end", :while)
86
117
 
87
118
  when :loop
88
- error_if_empty_tag(arg)
89
- wrap_content_with_native_stmt(stmt_list, arg, "while #{d_arg} do", "end", :while)
90
- #stmt_list << stag_stmt(arg)
119
+ error_if_empty_tag(elem_info, d_str)
120
+ wrap_content_with_native_stmt(elem_info, stmt_list, "while #{d_arg} do", "end", :while)
121
+ #stmt_list << stag_stmt(elem_info)
91
122
  #stmt_list << NativeStatement.new("while #{d_arg} do", :while)
92
- #stmt_list.concat(arg.cont_stmts)
123
+ #stmt_list.concat(e.cont_stmts)
93
124
  #stmt_list << NativeStatement.new("end", :while)
94
- #stmt_list << etag_stmt(arg)
125
+ #stmt_list << etag_stmt(elem_info)
95
126
 
96
127
  when :set
97
- wrap_element_with_native_stmt(stmt_list, arg, d_arg, nil, :set)
128
+ wrap_element_with_native_stmt(elem_info, stmt_list, d_arg, nil, :set)
98
129
  #stmt_list << NativeStatement.new(d_arg, :set)
99
- #stmt_list << stag_stmt(arg)
100
- #stmt_list.concat(arg.cont_stmts)
101
- #stmt_list << etag_stmt(arg)
130
+ #stmt_list << stag_stmt(elem_info)
131
+ #stmt_list.concat(e.cont_stmts)
132
+ #stmt_list << etag_stmt(elem_info)
102
133
 
103
134
  when :if
104
- wrap_element_with_native_stmt(stmt_list, arg, "if #{d_arg} then", "end", :if)
135
+ wrap_element_with_native_stmt(elem_info, stmt_list, "if #{d_arg} then", "end", :if)
105
136
  #stmt_list << NativeStatement.new("if #{d_arg} then", :if)
106
- #stmt_list << stag_stmt(arg)
107
- #stmt_list.concat(arg.cont_stmts)
108
- #stmt_list << etag_stmt(arg)
137
+ #stmt_list << stag_stmt(elem_info)
138
+ #stmt_list.concat(e.cont_stmts)
139
+ #stmt_list << etag_stmt(elem_info)
109
140
  #stmt_list << NativeStatement.new("end", :if)
110
141
 
111
142
  when :elsif, :else
112
- error_when_last_stmt_is_not_if(stmt_list, arg)
143
+ error_when_last_stmt_is_not_if(elem_info, d_str, stmt_list)
113
144
  stmt_list.pop # delete 'end'
114
145
  kind = d_name == :else ? :else : :elseif
115
146
  code = d_name == :else ? "else" : "elsif #{d_arg} then"
116
- wrap_element_with_native_stmt(stmt_list, arg, code, "end", kind)
147
+ wrap_element_with_native_stmt(elem_info, stmt_list, code, "end", kind)
117
148
  #stmt_list << NativeStatement.new(code, kind)
118
- #stmt_list << stag_stmt(arg)
119
- #stmt_list.concat(arg.cont_stmts)
120
- #stmt_list << etag_stmt(arg)
149
+ #stmt_list << stag_stmt(elem_info)
150
+ #stmt_list.concat(e.cont_stmts)
151
+ #stmt_list << etag_stmt(elem_info)
121
152
  #stmt_list << NativeStatement.new("end", kind)
122
153
 
123
154
  when :default, :Default, :DEFAULT
124
- error_if_empty_tag(arg)
125
- expr_code = d_arg
155
+ error_if_empty_tag(elem_info, d_str)
156
+ expr_str = directive.dattr == 'id' ? parse_expr_str(d_arg, e.stag_info.linenum) : d_arg
126
157
  flag_escape = d_name == :default ? nil : (d_name == :Default)
127
- add_native_expr_with_default(stmt_list, arg, expr_code, flag_escape,
128
- "if (#{d_arg}) && !(#{d_arg}).to_s.empty? then",
158
+ add_native_expr_with_default(elem_info, stmt_list, expr_str, flag_escape,
159
+ "if (#{expr_str}) && !(#{d_arg}).to_s.empty? then",
129
160
  "else", "end")
130
- #stmt_list << stag_stmt(arg)
161
+ #stmt_list << stag_stmt(elem_info)
131
162
  #stmt_list << NativeStatement.new_without_newline("if (#{d_arg}) && !(#{d_arg}).to_s.empty? then", :if)
132
163
  #flag_escape = d_name == :default ? nil : (d_name == :Default)
133
164
  #stmt_list << PrintStatement.new([ NativeExpression.new(d_arg, flag_escape) ])
134
165
  #stmt_list << NativeStatement.new_without_newline("else", :else)
135
- #stmt_list.concat(arg.cont_stmts)
166
+ #stmt_list.concat(e.cont_stmts)
136
167
  #stmt_list << NativeStatement.new_without_newline("end", :else)
137
- #stmt_list << etag_stmt(arg)
168
+ #stmt_list << etag_stmt(elem_info)
138
169
 
139
170
  else
140
171
  return false
@@ -154,6 +185,7 @@ module Kwartz
154
185
  ## translator for eRuby
155
186
  ##
156
187
  class RubyTranslator < BaseTranslator
188
+ include RubyExpressionParser
157
189
 
158
190
 
159
191
  def initialize(properties={})
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 111 $
3
- ### $Release: 3.1.2 $
2
+ ### $Rev$
3
+ ### $Release: 3.2.0 $
4
4
  ### copyright(c) 2004-2006 kuwata-lab.com all rights reserved
5
5
  ###
6
6
 
@@ -22,25 +22,26 @@ module Kwartz
22
22
 
23
23
 
24
24
 
25
- def handle(directive_name, directive_arg, directive_str, stag_info, etag_info, cont_stmts, attr_info, append_exprs, stmt_list)
25
+ def handle(directive, elem_info, stmt_list)
26
26
  ret = super
27
27
  return ret if ret
28
28
 
29
- d_name = directive_name
30
- d_arg = directive_arg
31
- d_str = directive_str
29
+ d_name = directive.name
30
+ d_arg = directive.arg
31
+ d_str = directive.str
32
+ e = elem_info
32
33
 
33
- case directive_name
34
+ case d_name
34
35
 
35
36
  when :struts
36
- case tag = stag_info.tagname
37
- when 'input' ; tag = attr_info['type'] || 'text' ; attr_info.delete('type')
37
+ case tag = e.stag_info.tagname
38
+ when 'input' ; tag = e.attr_info['type'] || 'text' ; e.attr_info.delete('type')
38
39
  when 'a' ; tag = 'link'
39
40
  when 'script' ; tag = 'javascript'
40
41
  end
41
- tag == :struts and raise convert_error("#{d_str}: unknown directive.", stag_info.linenum)
42
- return self.handle(tag.intern, d_arg, directive_str, stag_info, etag_info,
43
- cont_stmts, attr_info, append_exprs, stmt_list)
42
+ tag == :struts and raise convert_error("#{d_str}: unknown directive.", e.stag_info.linenum)
43
+ directive.name = tag.intern
44
+ return self.handle(directive, elem_info, stmt_list)
44
45
 
45
46
  else
46
47
  convert_mapping = {
@@ -48,21 +49,21 @@ module Kwartz
48
49
  'class'=>'cssClass'
49
50
  }
50
51
  convert_mapping.each do |html_aname, struts_aname|
51
- next unless attr_info[html_aname]
52
- attr_info[struts_aname] = attr_info[html_aname]
53
- attr_info.delete(html_aname)
52
+ next unless e.attr_info[html_aname]
53
+ e.attr_info[struts_aname] = e.attr_info[html_aname]
54
+ e.attr_info.delete(html_aname)
54
55
  end
55
56
  opts = eval "_evaluate_options(#{d_arg})"
56
57
  opts.each do |name, value|
57
- attr_info[name.to_s] = value.is_a?(Symbol) ? "${#{value}}" : value
58
+ e.attr_info[name.to_s] = value.is_a?(Symbol) ? "${#{value}}" : value
58
59
  end
59
60
  tagname = "html:#{d_name}"
60
- stag_info.tagname = tagname
61
- etag_info.tagname = tagname if etag_info
62
- stag_info.is_empty = true if !etag_info
63
- stmt_list << build_print_stmt(stag_info, attr_info, append_exprs)
61
+ e.stag_info.tagname = tagname
62
+ e.etag_info.tagname = tagname if e.etag_info
63
+ e.stag_info.is_empty = true if !e.etag_info
64
+ stmt_list << build_print_stmt(e.stag_info, e.attr_info, e.append_exprs)
64
65
  stmt_list.concat(cont_stmts)
65
- stmt_list << build_print_stmt(etag_info, nil, nil) if etag_info
66
+ stmt_list << build_print_stmt(e.etag_info, nil, nil) if e.etag_info
66
67
 
67
68
  end #case
68
69
  return true
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 135 $
3
- ### $Release: 3.1.2 $
2
+ ### $Rev$
3
+ ### $Release: 3.2.0 $
4
4
  ### copyright(c) 2004-2006 kuwata-lab.com all rights reserved
5
5
  ###
6
6
 
@@ -20,10 +20,10 @@ module Kwartz
20
20
  PROPERTY_JSTL = 1.2 # jstl version (1.2 or 1.1)
21
21
  #
22
22
  NO_ETAGS = [ 'input', 'img' ,'br', 'hr', 'meta', 'link' ]
23
- #ALLOW_DUPLICATE_ID = false
23
+ ALLOW_DUPLICATE_ID = false # if true then enables to use duplicated id name.
24
24
 
25
25
 
26
26
  end
27
27
 
28
-
28
+
29
29
  end
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 148 $
3
- ### $Release: 3.1.2 $
2
+ ### $Rev$
3
+ ### $Release: 3.2.0 $
4
4
  ### copyright(c) 2004-2006 kuwata-lab.com all rights reserved
5
5
  ###
6
6
 
@@ -83,6 +83,12 @@ module Kwartz
83
83
  end
84
84
 
85
85
 
86
+ def clear_as_dummy_tag # delete <span> tag
87
+ @tagname = nil
88
+ @head_space = @tail_space = nil if @head_space && @tail_space
89
+ end
90
+
91
+
86
92
  def _inspect
87
93
  return [ @prev_text, @head_space, @is_etag, @tagname, @attr_str, @extra_space, @is_empty, @tail_space ]
88
94
  end
@@ -104,20 +110,22 @@ module Kwartz
104
110
  @values[name] = value
105
111
  @spaces[name] = space
106
112
  end
107
- @directive = nil
108
- @linenum = nil
109
113
  end
110
114
  attr_reader :names, :values, :spaces
111
- attr_accessor :directive, :linenum
115
+
116
+
117
+ def has?(name)
118
+ return @values.key?(name)
119
+ end
112
120
 
113
121
 
114
122
  def [](name)
115
- @values[name]
123
+ return @values[name]
116
124
  end
117
125
 
118
126
 
119
127
  def []=(name, value)
120
- @names << name unless @values.key?(name)
128
+ @names << name unless has?(name)
121
129
  @values[name] = value
122
130
  @spaces[name] = ' ' unless @spaces.key?(name)
123
131
  end
@@ -125,15 +133,13 @@ module Kwartz
125
133
 
126
134
  def each
127
135
  @names.each do |name|
128
- space = @spaces[name]
129
- value = @values[name]
130
- yield(space, name, value)
136
+ yield(@spaces[name], name, @values[name])
131
137
  end
132
138
  end
133
139
 
134
140
 
135
141
  def delete(name)
136
- if @values.key?(name)
142
+ if has?(name)
137
143
  @names.delete(name)
138
144
  @values.delete(name)
139
145
  @spaces.delete(name)
@@ -153,55 +159,58 @@ module Kwartz
153
159
  class ElementInfo
154
160
 
155
161
 
156
- def initialize(name, stag_info, etag_info, cont_stmts, attr_info, append_exprs)
157
- @name = name # String
162
+ def initialize(stag_info, etag_info, cont_stmts, attr_info, append_exprs)
158
163
  @stag_info = stag_info # TagInfo
159
164
  @etag_info = etag_info # TagInfo
160
165
  @cont_stmts = cont_stmts # list of Statement
161
166
  @attr_info = attr_info # AttrInfo
162
167
  @append_exprs = append_exprs # list of NativeExpression
163
168
  @logic = [ ExpandStatement.new(:elem, @name) ]
164
- @merged = nil
165
169
  end
166
170
 
167
- attr_accessor :name, :stag_info, :etag_info, :cont_stmts, :attr_info, :append_exprs, :logic
171
+ attr_accessor :stag_info, :etag_info, :cont_stmts, :attr_info, :append_exprs
168
172
  attr_reader :stag_expr, :cont_expr, :etag_expr, :elem_expr
169
-
170
-
171
- def merged?
172
- !@merged.nil?
173
- end
173
+ attr_reader :logic, :before, :after
174
+ attr_accessor :name
175
+ attr_accessor :applied
174
176
 
175
177
 
176
178
  def self.create(values={})
177
- self.new(values[:name], values[:stag], values[:etag], values[:cont], values[:attr], values[:append])
179
+ v = values
180
+ return self.new(v[:name], v[:stag], v[:etag], v[:cont], v[:attr], v[:append])
178
181
  end
179
182
 
180
183
 
181
- def merge(elem_ruleset)
182
- return unless elem_ruleset.name == @name
183
- @merged = elem_ruleset
184
- @stag_expr = _to_native_expr(elem_ruleset.stag)
185
- @cont_expr = _to_native_expr(elem_ruleset.cont || elem_ruleset.value)
186
- @etag_expr = _to_native_expr(elem_ruleset.etag)
187
- @elem_expr = _to_native_expr(elem_ruleset.elem)
184
+ def apply(ruleset)
185
+ r = ruleset
186
+ @stag_expr = _to_native_expr(r.stag) if r.stag
187
+ @cont_expr = _to_native_expr(r.cont) if r.cont
188
+ @etag_expr = _to_native_expr(r.etag) if r.etag
189
+ @elem_expr = _to_native_expr(r.elem) if r.elem
188
190
  if @cont_expr
189
191
  @cont_stmts = [ PrintStatement.new([@cont_expr]) ]
190
192
  @stag_info.tail_space = ''
191
193
  @etag_info.head_space = ''
192
194
  @etag_info.rebuild_tag_text()
193
195
  end
194
- elem_ruleset.remove.each do |aname|
196
+ r.remove.each do |aname|
195
197
  @attr_info.delete(aname)
196
- end if elem_ruleset.remove
197
- elem_ruleset.attrs.each do |aname, avalue|
198
+ end if r.remove
199
+ r.attrs.each do |aname, avalue|
198
200
  @attr_info[aname] = _to_native_expr(avalue)
199
- end if elem_ruleset.attrs
200
- elem_ruleset.append.each do |expr|
201
+ end if r.attrs
202
+ r.append.each do |expr|
201
203
  (@append_exprs ||= []) << _to_native_expr(expr)
202
- end if elem_ruleset.append
203
- @tagname = elem_ruleset.tagname
204
- @logic = elem_ruleset.logic if elem_ruleset.logic
204
+ end if r.append
205
+ @tagname = r.tagname if r.tagname
206
+ @logic = r.logic if r.logic
207
+ (@before ||= []).concat(r.before) if r.before
208
+ (@after ||= []).concat(r.after) if r.after
209
+ end
210
+
211
+
212
+ def dummy_span_tag?(tagname='span')
213
+ return @stag_info.tagname == tagname && @attr_info.empty? && @append_exprs.nil?
205
214
  end
206
215
 
207
216
 
@@ -218,18 +227,9 @@ module Kwartz
218
227
 
219
228
 
220
229
  ##
221
- ## helper module for Converter and Handler
222
230
  ##
223
- ## Handler and Converter class include this module.
224
231
  ##
225
- module ConverterHelper # :nodoc:
226
-
227
-
228
- ## set @despan and @dattr
229
- def include_properties(properties)
230
- @dattr = properties[:dattr] || Config::PROPERTY_DATTR # default: 'kw:d'
231
- @delspan = properties.key?(:delspan) ? properties[:delspan] : Config::PROPERTY_DELSPAN # delete dummy <span> tag or not
232
- end
232
+ module ConvertErrorHelper # :nodoc:
233
233
 
234
234
 
235
235
  ## return ConvertError
@@ -238,25 +238,31 @@ module Kwartz
238
238
  end
239
239
 
240
240
 
241
- ## raise errror if etag_info is null
242
- def error_if_empty_tag(handler_arg)
243
- arg = handler_arg
244
- unless arg.etag_info
245
- d_name = arg.directive_name
246
- d_str = arg.directive_str
247
- msg = "'#{d_str}': #{d_name} directive is not available with empty tag."
248
- raise convert_error(msg, arg.stag_info.linenum)
241
+ end
242
+
243
+
244
+
245
+ ##
246
+ ##
247
+ ##
248
+ module HandlerHelper
249
+ #include ConvertErrorHelper
250
+
251
+
252
+ ## raise error if etag_info is null
253
+ def error_if_empty_tag(elem_info, directive_str)
254
+ unless elem_info.etag_info
255
+ msg = "'#{directive_str}': directive is not available with empty tag."
256
+ raise convert_error(msg, elem_info.stag_info.linenum)
249
257
  end
250
258
  end
251
259
 
252
260
 
253
- def error_when_last_stmt_is_not_if(stmt_list, handler_arg)
261
+ def error_when_last_stmt_is_not_if(elem_info, directive_str, stmt_list)
254
262
  kind = _last_stmt_kind(stmt_list)
255
263
  unless kind == :if || kind == :elseif
256
- d_str = handler_arg.directive_str
257
- linenum = handler_arg.stag_info.linenum
258
- msg = "'#{d_str}': previous statement should be 'if' or 'elsif'."
259
- raise convert_error(msg, linenum)
264
+ msg = "'#{directive_str}': previous statement should be 'if' or 'elsif'."
265
+ raise convert_error(msg, elem_info.stag_info.linenum)
260
266
  end
261
267
  end
262
268
 
@@ -272,13 +278,6 @@ module Kwartz
272
278
  end
273
279
 
274
280
 
275
- end
276
-
277
-
278
-
279
- module StatementHelper
280
-
281
-
282
281
  ## create print statement from text
283
282
  def create_text_print_stmt(text)
284
283
  return PrintStatement.new([text])
@@ -305,8 +304,9 @@ module Kwartz
305
304
  attr_info.each do |space, aname, avalue|
306
305
  sb << "#{space}#{aname}=\""
307
306
  if avalue.is_a?(NativeExpression)
307
+ native_expr = expand_attr_vars_in_native_expr(avalue, attr_info)
308
308
  args << sb # TextExpression.new(sb)
309
- args << avalue
309
+ args << native_expr
310
310
  sb = ''
311
311
  else
312
312
  sb << avalue
@@ -318,7 +318,10 @@ module Kwartz
318
318
  args << sb # TextExpression.new(sb)
319
319
  sb = ''
320
320
  end
321
- args.concat(append_exprs)
321
+ append_exprs.each do |append_expr|
322
+ native_expr = expand_attr_vars_in_native_expr(append_expr, attr_info)
323
+ args << native_expr
324
+ end
322
325
  end
323
326
  sb << "#{t.extra_space}#{t.is_empty ? '/' : ''}>#{t.tail_space}"
324
327
  args << sb # TextExpression.new(sb)
@@ -334,28 +337,67 @@ module Kwartz
334
337
 
335
338
 
336
339
  ## create PrintStatement for NativeExpression
337
- def build_print_expr_stmt(native_expr, stag_info, etag_info)
340
+ def build_print_expr_stmt(native_expr, stag_info, etag_info, attr_info=nil)
338
341
  head_space = (stag_info || etag_info).head_space
339
342
  tail_space = (etag_info || stag_info).tail_space
343
+ native_expr = expand_attr_vars_in_native_expr(native_expr, attr_info) if attr_info
340
344
  args = []
341
- args << head_space if head_space # TexExpression.new(head_space)
345
+ args << head_space if head_space # TextExpression.new(head_space)
342
346
  args << native_expr
343
347
  args << tail_space if tail_space # TextExpression.new(tail_space)
344
348
  return PrintStatement.new(args)
345
349
  end
346
350
 
347
351
 
352
+ ## expand attribute variables (such as '$(rows)' or '$(value)') and return new code
353
+ def expand_attr_vars(code, attr_info)
354
+ new_code = code.gsub(/\$\((\w+(?::\w+)?)\)/) do |m|
355
+ aname = $1
356
+ #unless attrs.key?(aname)
357
+ # raise "#{m}: attribute '#{aname}' expected but not found."
358
+ #end
359
+ avalue = attr_info[aname]
360
+ if avalue.is_a?(NativeExpression)
361
+ raise "#{m}: attribute value of '#{aname}' is NativeExpression object."
362
+ end
363
+ avalue
364
+ end
365
+ return new_code
366
+ end
367
+
368
+
369
+ ## expand attribute variables and return new NativeExpression
370
+ def expand_attr_vars_in_native_expr(native_expr, attr_info)
371
+ code = expand_attr_vars(native_expr.code, attr_info)
372
+ if code != native_expr.code
373
+ native_expr = NativeExpression.new(code, native_expr.escape)
374
+ end
375
+ return native_expr
376
+ end
377
+
378
+
379
+ ## expand attribute variables and return new NativeExpression
380
+ def expand_attr_vars_in_native_stmt(native_stmt, attr_info)
381
+ code = expand_attr_vars(native_stmt.code, attr_info)
382
+ if code != native_stmt.code
383
+ no_newline = native_stmt.no_newline
384
+ native_stmt = NativeStatement.new(code, native_stmt.kind)
385
+ native_stmt.no_newline = no_newline unless no_newline.nil?
386
+ end
387
+ return native_stmt
388
+ end
389
+
390
+
348
391
  ## build print statement of start-tag
349
- def stag_stmt(handler_arg)
350
- arg = handler_arg
351
- return build_print_stmt(arg.stag_info, arg.attr_info, arg.append_exprs)
392
+ def stag_stmt(elem_info)
393
+ e = elem_info
394
+ return build_print_stmt(e.stag_info, e.attr_info, e.append_exprs)
352
395
  end
353
396
 
354
397
 
355
398
  ## build print statemetn of end-tag
356
- def etag_stmt(handler_arg)
357
- arg = handler_arg
358
- return build_print_stmt(arg.etag_info, nil, nil)
399
+ def etag_stmt(elem_info)
400
+ return build_print_stmt(elem_info.etag_info, nil, nil)
359
401
  end
360
402
 
361
403
 
@@ -368,52 +410,50 @@ module Kwartz
368
410
  end
369
411
 
370
412
 
371
- def wrap_element_with_native_stmt(stmt_list, handler_arg, start_code, end_code, kind=nil)
413
+ def wrap_element_with_native_stmt(elem_info, stmt_list, start_code, end_code, kind=nil)
372
414
  add_native_code(stmt_list, start_code, kind)
373
- stmt_list << stag_stmt(handler_arg)
374
- stmt_list.concat(handler_arg.cont_stmts)
375
- stmt_list << etag_stmt(handler_arg)
415
+ stmt_list << stag_stmt(elem_info)
416
+ stmt_list.concat(elem_info.cont_stmts)
417
+ stmt_list << etag_stmt(elem_info)
376
418
  add_native_code(stmt_list, end_code, kind)
377
419
  end
378
420
 
379
421
 
380
- def wrap_content_with_native_stmt(stmt_list, handler_arg, start_code, end_code, kind=nil)
381
- stmt_list << stag_stmt(handler_arg)
422
+ def wrap_content_with_native_stmt(elem_info, stmt_list, start_code, end_code, kind=nil)
423
+ stmt_list << stag_stmt(elem_info)
382
424
  add_native_code(stmt_list, start_code, kind)
383
- stmt_list.concat(handler_arg.cont_stmts)
425
+ stmt_list.concat(elem_info.cont_stmts)
384
426
  add_native_code(stmt_list, end_code, kind)
385
- stmt_list << etag_stmt(handler_arg)
427
+ stmt_list << etag_stmt(elem_info)
386
428
  end
387
429
 
388
430
 
389
- def add_foreach_stmts(stmt_list, handler_arg, foreach_code, endforeach_code,
431
+ def add_foreach_stmts(elem_info, stmt_list, foreach_code, endforeach_code,
390
432
  content_only, counter, toggle, init_code, incr_code, toggle_code)
391
- arg = handler_arg
392
- stmt_list << stag_stmt(arg) if content_only
433
+ stmt_list << stag_stmt(elem_info) if content_only
393
434
  start_code.split(/\n/).each do |code|
394
435
  stmt_list << NativeStatement.new(code, kind)
395
436
  end if start_code
396
- stmt_list << stag_stmt(arg) if !content_only
397
- stmt_list.concat(arg.cont_stmts)
398
- stmt_list << etag_stmt(arg) if !content_only
437
+ stmt_list << stag_stmt(elem_info) if !content_only
438
+ stmt_list.concat(elem_info.cont_stmts)
439
+ stmt_list << etag_stmt(elem_info) if !content_only
399
440
  end_code.split(/\n/).each do |code|
400
441
  stmt_list << NativeStatement.new(code, kind)
401
442
  end
402
- stmt_list << etag_stmt(arg) if content_only
443
+ stmt_list << etag_stmt(elem_info) if content_only
403
444
  end
404
445
 
405
446
 
406
- def add_native_expr_with_default(stmt_list, handler_arg,
447
+ def add_native_expr_with_default(elem_info, stmt_list,
407
448
  expr_code, flag_escape,
408
449
  if_code, else_code, endif_code)
409
- arg = handler_arg
410
- stmt_list << stag_stmt(arg)
450
+ stmt_list << stag_stmt(elem_info)
411
451
  stmt_list << NativeStatement.new_without_newline(if_code, :if)
412
452
  stmt_list << PrintStatement.new([ NativeExpression.new(expr_code, flag_escape) ])
413
453
  stmt_list << NativeStatement.new_without_newline(else_code, :else)
414
- stmt_list.concat(arg.cont_stmts)
454
+ stmt_list.concat(elem_info.cont_stmts)
415
455
  stmt_list << NativeStatement.new_without_newline(endif_code, :else)
416
- stmt_list << etag_stmt(arg)
456
+ stmt_list << etag_stmt(elem_info)
417
457
  end
418
458
 
419
459
 
@@ -426,12 +466,12 @@ module Kwartz
426
466
  ##
427
467
  ## Handler class includes this module.
428
468
  ##
429
- module ElementExpander
469
+ module Expander
430
470
  include Assertion
431
471
 
432
472
 
433
- ## (abstract) get ElementRuleset
434
- def get_element_ruleset(name)
473
+ ## (abstract) get Ruleset
474
+ def get_ruleset(selector)
435
475
  not_implemented
436
476
  end
437
477
 
@@ -444,97 +484,109 @@ module Kwartz
444
484
 
445
485
  ## expand ElementInfo
446
486
  def expand_element_info(elem_info, stmt_list, content_only=false)
447
- #elem_ruleset = @ruleset_table[elem_info.name]
448
- elem_ruleset = get_element_ruleset(elem_info.name)
449
- if elem_ruleset && !elem_info.merged?
450
- elem_info.merge(elem_ruleset)
487
+ expand_statements(elem_info.before, stmt_list, elem_info) if elem_info.before
488
+ stmts = content_only ? [ ExpandStatement.new(:cont) ] : elem_info.logic
489
+ stmts.each do |stmt|
490
+ expand_statement(stmt, stmt_list, elem_info)
451
491
  end
452
- logic = content_only ? [ ExpandStatement.new(:cont, elem_info.name) ] : elem_info.logic
453
- logic.each do |stmt|
492
+ expand_statements(elem_info.after, stmt_list, elem_info) if elem_info.after
493
+ end
494
+
495
+
496
+ ## expand list of ExpandStatement
497
+ def expand_statements(stmts, stmt_list, elem_info)
498
+ stmts.each do |stmt|
454
499
  expand_statement(stmt, stmt_list, elem_info)
455
500
  end
456
- #if content_only
457
- # stmt = ExpandStatement.new(:cont, elem_info.name)
458
- # expand_statement(stmt, stmt_list, elem_info)
459
- #else
460
- # elem_info.logic.each do |stmt|
461
- # expand_statement(stmt, stmt_list, elem_info)
462
- # end
463
- #end
464
501
  end
465
502
 
466
503
 
467
504
  ## expand ExpandStatement
468
505
  def expand_statement(stmt, stmt_list, elem_info)
469
506
 
470
- if stmt.is_a?(ExpandStatement)
471
- e = elem_info
472
-
473
- ## delete dummy '<span>' tag
474
- if @delspan && e.stag_info.tagname == 'span' && e.attr_info.empty? && e.append_exprs.nil?
475
- e.stag_info.tagname = e.etag_info.tagname = nil
507
+ if stmt.is_a?(NativeStatement)
508
+ if elem_info
509
+ native_stmt = expand_attr_vars_in_native_stmt(stmt, elem_info.attr_info)
510
+ else
511
+ native_stmt = stmt
476
512
  end
513
+ stmt_list << native_stmt
514
+ return
515
+ end
477
516
 
478
- case stmt.kind
517
+ if ! stmt.is_a?(ExpandStatement)
518
+ stmt_list << stmt
519
+ return
520
+ end
479
521
 
480
- when :stag
481
- assert unless elem_info
482
- if e.stag_expr
483
- assert unless e.stag_expr.is_a?(NativeExpression)
484
- stmt_list << build_print_expr_stmt(e.stag_expr, e.stag_info, nil)
485
- else
486
- stmt_list << build_print_stmt(e.stag_info, e.attr_info, e.append_exprs)
487
- end
522
+ e = elem_info
488
523
 
489
- when :etag
490
- assert unless elem_info
491
- if e.etag_expr
492
- assert unless e.etag_expr.is_a?(NativeExpression)
493
- stmt_list << build_print_expr_stmt(e.etag_expr, nil, e.etag_info)
494
- elsif e.etag_info # e.etag_info is nil when <br>, <input>, <hr>, <img>, <meta>
495
- stmt_list << build_print_stmt(e.etag_info, nil, nil)
496
- end
524
+ ## remove dummy <span> tag
525
+ if @delspan && elem_info && elem_info.dummy_span_tag?('span')
526
+ #e.stag_info.tagname = e.etag_info.tagname = nil
527
+ e.stag_info.clear_as_dummy_tag()
528
+ e.etag_info.clear_as_dummy_tag()
529
+ end
497
530
 
498
- when :cont
499
- if e.cont_expr
500
- assert unless e.cont_expr.is_a?(NativeExpression)
501
- stmt_list << PrintStatement.new([e.cont_expr])
502
- else
503
- elem_info.cont_stmts.each do |cont_stmt|
504
- expand_statement(cont_stmt, stmt_list, nil)
505
- end
506
- end
531
+ case stmt.kind
507
532
 
508
- when :elem
509
- assert unless elem_info
510
- if e.elem_expr
511
- assert unless e.elem_expr.is_a?(NativeExpression)
512
- stmt_list << build_print_expr_stmt(e.elem_expr, e.stag_info, e.etag_info)
513
- else
514
- stmt.kind = :stag
515
- expand_statement(stmt, stmt_list, elem_info)
516
- stmt.kind = :cont
517
- expand_statement(stmt, stmt_list, elem_info)
518
- stmt.kind = :etag
519
- expand_statement(stmt, stmt_list, elem_info)
520
- stmt.kind = :elem
521
- end
533
+ when :stag
534
+ assert unless elem_info
535
+ if e.stag_expr
536
+ assert unless e.stag_expr.is_a?(NativeExpression)
537
+ stmt_list << build_print_expr_stmt(e.stag_expr, e.stag_info, nil, e.attr_info)
538
+ else
539
+ stmt_list << build_print_stmt(e.stag_info, e.attr_info, e.append_exprs)
540
+ end
541
+
542
+ when :etag
543
+ assert unless elem_info
544
+ if e.etag_expr
545
+ assert unless e.etag_expr.is_a?(NativeExpression)
546
+ stmt_list << build_print_expr_stmt(e.etag_expr, nil, e.etag_info, e.attr_info)
547
+ elsif e.etag_info # e.etag_info is nil when <br>, <input>, <hr>, <img>, <meta>
548
+ stmt_list << build_print_stmt(e.etag_info, nil, nil)
549
+ end
522
550
 
523
- when :element, :content
524
- content_only = stmt.kind == :content
525
- #elem_info = @elements[stmt.name]
526
- elem_info = get_element_info(stmt.name)
527
- unless elem_info
528
- raise convert_error("element '#{stmt.name}' is not found.", nil)
551
+ when :cont
552
+ if e.cont_expr
553
+ assert unless e.cont_expr.is_a?(NativeExpression)
554
+ #stmt_list << PrintStatement.new([e.cont_expr])
555
+ native_expr = expand_attr_vars_in_native_expr(e.cont_expr, e.attr_info)
556
+ stmt_list << PrintStatement.new([native_expr])
557
+ else
558
+ elem_info.cont_stmts.each do |cont_stmt|
559
+ expand_statement(cont_stmt, stmt_list, nil)
529
560
  end
530
- expand_element_info(elem_info, stmt_list, content_only)
561
+ end
531
562
 
563
+ when :elem
564
+ assert unless elem_info
565
+ if e.elem_expr
566
+ assert unless e.elem_expr.is_a?(NativeExpression)
567
+ stmt_list << build_print_expr_stmt(e.elem_expr, e.stag_info, e.etag_info, e.attr_info)
532
568
  else
533
- assert
534
- end #case
569
+ stmt.kind = :stag
570
+ expand_statement(stmt, stmt_list, elem_info)
571
+ stmt.kind = :cont
572
+ expand_statement(stmt, stmt_list, elem_info)
573
+ stmt.kind = :etag
574
+ expand_statement(stmt, stmt_list, elem_info)
575
+ stmt.kind = :elem
576
+ end
577
+
578
+ when :element, :content
579
+ content_only = stmt.kind == :content
580
+ #elem_info = @elements[stmt.name]
581
+ elem_info = get_element_info(stmt.name)
582
+ unless elem_info
583
+ raise convert_error("element '#{stmt.name}' is not found.", nil)
584
+ end
585
+ expand_element_info(elem_info, stmt_list, content_only)
586
+
535
587
  else
536
- stmt_list << stmt
537
- end #if
588
+ assert
589
+ end #case
538
590
  end
539
591
 
540
592
 
@@ -543,27 +595,21 @@ module Kwartz
543
595
 
544
596
 
545
597
  ##
546
- ## argument data for handler
598
+ ## directive
547
599
  ##
548
- class HandlerArgument
549
- include StatementHelper
600
+ class Directive
550
601
 
551
602
 
552
- def initialize(directive_name, directive_arg, directive_str,
553
- stag_info, etag_info, cont_stmts, attr_info, append_exprs)
554
- @directive_name = directive_name
555
- @directive_arg = directive_arg
556
- @directive_str = directive_str
557
- @stag_info = stag_info
558
- @etag_info = etag_info
559
- @cont_stmts = cont_stmts
560
- @attr_info = attr_info
561
- @append_exprs = append_exprs
603
+ def initialize(args={})
604
+ @name = args[:name]
605
+ @arg = args[:arg]
606
+ @dattr = args[:dattr]
607
+ @str = args[:str]
608
+ @linenum = args[:linenum]
562
609
  end
563
610
 
564
611
 
565
- attr_reader :directive_name, :directive_arg, :directive_str
566
- attr_reader :stag_info, :etag_info, :cont_stmts, :attr_info, :append_exprs
612
+ attr_accessor :name, :arg, :dattr, :str, :linenum
567
613
 
568
614
 
569
615
  end
@@ -575,35 +621,47 @@ module Kwartz
575
621
  ##
576
622
  class Handler
577
623
  include Assertion
578
- include ConverterHelper
579
- include StatementHelper
580
- include ElementExpander
624
+ include ConvertErrorHelper
625
+ include HandlerHelper
626
+ include Expander
581
627
 
582
628
 
583
- def initialize(elem_rulesets=[], properties={})
584
- @elem_rulesets = elem_rulesets
585
- #@elem_ruleset_table = elem_rulesets.inject({}) { |table, ruleset| table[ruleset.name] = ruleset; table }
586
- @elem_ruleset_table = {} ; elem_rulesets.each { |ruleset| @elem_ruleset_table[ruleset.name] = ruleset }
629
+ def initialize(rulesets=[], properties={})
630
+ @ruleset_table = {}
631
+ rulesets.each { |ruleset| _register_ruleset(ruleset) }
587
632
  @elem_info_table = {}
588
- include_properties(properties) # @delspan and @dattr
589
- @odd = properties[:odd] || Config::PROPERTY_ODD # "'odd'"
590
- @even = properties[:even] || Config::PROPERTY_EVEN # "'even'"
591
- @filename = nil
633
+ @delspan = properties.fetch(:delspan, Config::PROPERTY_DELSPAN) # delete dummy <span> tag or not
634
+ @odd = properties.fetch(:odd, Config::PROPERTY_ODD) # "'odd'"
635
+ @even = properties.fetch(:even, Config::PROPERTY_EVEN) # "'even'"
592
636
  end
593
637
  attr_reader :odd, :even
594
- attr_accessor :converter, :filename
638
+ attr_accessor :filename
595
639
 
596
640
 
597
- def get_element_ruleset(name) # for ElementExpander module and Converter class
598
- return @elem_ruleset_table[name]
641
+ def _register_ruleset(ruleset)
642
+ ruleset.selectors.each do |selector|
643
+ r = @ruleset_table[selector]
644
+ @ruleset_table[selector] = r ? r.merge(ruleset) : ruleset
645
+ end
599
646
  end
647
+ private :_register_ruleset
648
+
600
649
 
650
+ def get_ruleset(selector) # for Expander module and Converter class
651
+ return @ruleset_table[selector]
652
+ end
601
653
 
602
- def get_element_info(name) # for ElementExpander module
654
+
655
+ def get_element_info(name) # for Expander module
603
656
  return @elem_info_table[name]
604
657
  end
605
658
 
606
659
 
660
+ def register_element_info(name, elem_info)
661
+ @elem_info_table[name] = elem_info
662
+ end
663
+
664
+
607
665
  def _elem_info_table # :nodoc:
608
666
  return @elem_info_table
609
667
  end
@@ -640,97 +698,158 @@ module Kwartz
640
698
  end
641
699
 
642
700
 
643
- ## (abstract) directive format, which is used at has_directive?() method
644
- def directive_format
701
+ ## (abstract) convert universal expression string to native expression string
702
+ def parse_expr_str(expr_str, linenum)
645
703
  not_implemented
646
- #return '%s: %s'
647
704
  end
648
705
 
649
706
 
650
707
  public
651
708
 
652
709
 
710
+ def handle_directives(directive, elem_info, stmt_list)
711
+ e = elem_info
712
+ linenum = elem_info.stag_info.linenum
713
+ append_exprs = nil
714
+
715
+ if directive.dattr == 'id'
716
+ ## nothing
717
+ else
718
+ ## handle 'attr:' and 'append:' directives
719
+ d_str = nil
720
+ directive.str.split(/;/).each do |d_str|
721
+ d_str.strip!
722
+ unless d_str =~ self.directive_pattern # ex. /\A(\w+):\s*(.*)\z/
723
+ raise convert_error("'#{d_str}': invalid directive pattern", linenum)
724
+ end
725
+ d_name = $1.intern # directive name
726
+ d_arg = $2 || '' # directive arg
727
+ case d_name
728
+ when :attr, :Attr, :ATTR
729
+ directive2 = Directive.new(:name=>d_name, :arg=>d_arg, :sr=>d_str)
730
+ handle(directive2, elem_info, stmt_list)
731
+ when :append, :Append, :APPEND
732
+ append_exprs ||= []
733
+ elem_info.append_exprs = append_exprs
734
+ directive2 = Directive.new(:name=>d_name, :arg=>d_arg, :sr=>d_str)
735
+ handle(directive2, elem_info, stmt_list)
736
+ else
737
+ if directive.name
738
+ raise convert_error("'#{d_str}': not available with '#{directive.name}' directive.", linenum)
739
+ end
740
+ directive.name = d_name
741
+ directive.arg = d_arg
742
+ directive.str = d_str
743
+ end #case
744
+ end
745
+ end
746
+
747
+ ## remove dummy <span> tag
748
+ if @delspan && elem_info.dummy_span_tag?('span')
749
+ #e.stag_info.tagname = e.etag_info.tagname = nil
750
+ e.stag_info.clear_as_dummy_tag()
751
+ e.etag_info.clear_as_dummy_tag()
752
+ end
753
+
754
+ ## handle other directives
755
+ if directive.name
756
+ handled = handle(directive, elem_info, stmt_list)
757
+ handled or raise convert_error("'#{directive.str}': unknown directive.", linenum)
758
+ else # for 'attr' and 'append' directive
759
+ assert unless !elem_info.attr_info.empty? || !elem_info.append_exprs.empty?
760
+ stmt_list << stag_stmt(elem_info)
761
+ stmt_list.concat(elem_info.cont_stmts)
762
+ stmt_list << etag_stmt(elem_info) if elem_info.etag_info # when empty-tag
763
+ end
764
+
765
+ end
766
+
767
+
653
768
  ## handle directives ('stag', 'etag', 'elem', 'cont'(='value'))
654
769
  ##
655
770
  ## return true if directive name is one of 'stag', 'etag', 'elem', 'cont', and 'value',
656
771
  ## else return false.
657
- def handle(stmt_list, handler_arg)
658
- arg = handler_arg
659
- d_name = arg.directive_name
660
- d_arg = arg.directive_arg
661
- d_str = arg.directive_str
772
+ def handle(directive, elem_info, stmt_list)
773
+ d_name = directive.name
774
+ d_arg = directive.arg
775
+ d_str = directive.str
776
+ d_attr = directive.dattr
777
+ e = elem_info
778
+ linenum = e.stag_info.linenum
662
779
 
663
780
  case d_name
664
781
 
665
782
  when nil
666
- assert unless !arg.attr_info.empty? || !arg.append_exprs.empty?
667
- stmt_list << stag_stmt(arg)
668
- stmt_list.concat(arg.cont_stmts)
669
- stmt_list << etag_stmt(arg) if arg.etag_info # when empty-tag
783
+ assert false
670
784
 
671
785
  when :dummy
672
786
  # nothing
673
787
 
674
788
  when :id, :mark
675
- unless d_arg =~ /\A(\w+)\z/ || d_arg =~ /\A'(\w+)'\z/
676
- raise convert_error("'#{d_str}': invalid marking name.", arg.stag_info.linenum)
789
+ unless d_arg =~ /\A([-\w]+)\z/ || d_arg =~ /\A'([-\w]+)'\z/
790
+ raise convert_error("'#{d_str}': invalid marking name.", linenum)
677
791
  end
678
792
  name = $1
679
- elem_info = ElementInfo.new(name, arg.stag_info, arg.etag_info, arg.cont_stmts,
680
- arg.attr_info, arg.append_exprs)
681
- if @elem_info_table[name]
682
- #unless Config::ALLOW_DUPLICATE_ID
683
- previous_linenum = @elem_info_table[name].stag_info.linenum
793
+ if get_element_info(name)
794
+ unless Config::ALLOW_DUPLICATE_ID
795
+ previous_linenum = get_element_info(name).stag_info.linenum
684
796
  msg = "'#{d_str}': id '#{name}' is already used at line #{previous_linenum}."
685
- raise convert_error(msg, arg.stag_info.linenum)
686
- #end
687
- else
688
- @elem_info_table[name] = elem_info
797
+ raise convert_error(msg, linenum)
798
+ end
689
799
  end
800
+ ruleset = get_ruleset('#' + name)
801
+ elem_info.apply(ruleset) if ruleset
802
+ register_element_info(name, elem_info)
690
803
  #stmt_list << ExpandStatement.new(:element, name) # lazy expantion
691
804
  expand_element_info(elem_info, stmt_list)
692
805
 
693
806
  when :stag, :Stag, :STAG
694
- error_if_empty_tag(arg)
807
+ error_if_empty_tag(elem_info, d_str)
695
808
  flag_escape = d_name == :stag ? nil : (d_name == :Stag)
696
- expr = NativeExpression.new(d_arg, flag_escape)
697
- stmt_list << build_print_expr_stmt(expr, arg.stag_info, nil)
698
- stmt_list.concat(arg.cont_stmts)
699
- stmt_list << etag_stmt(arg)
809
+ expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
810
+ expr = NativeExpression.new(expr_str, flag_escape)
811
+ stmt_list << build_print_expr_stmt(expr, e.stag_info, nil)
812
+ stmt_list.concat(e.cont_stmts)
813
+ stmt_list << etag_stmt(elem_info)
700
814
 
701
815
  when :etag, :Etag, :ETAG
702
- error_if_empty_tag(arg)
816
+ error_if_empty_tag(elem_info, d_str)
703
817
  flag_escape = d_name == :etag ? nil : (d_name == :Etag)
704
- expr = NativeExpression.new(d_arg, flag_escape)
705
- stmt_list << stag_stmt(arg)
706
- stmt_list.concat(arg.cont_stmts)
707
- stmt_list << build_print_expr_stmt(expr, nil, arg.etag_info)
818
+ expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
819
+ expr = NativeExpression.new(expr_str, flag_escape)
820
+ stmt_list << stag_stmt(elem_info)
821
+ stmt_list.concat(e.cont_stmts)
822
+ stmt_list << build_print_expr_stmt(expr, nil, e.etag_info)
708
823
 
709
824
  when :elem, :Elem, :ELEM
710
825
  flag_escape = d_name == :elem ? nil : (d_name == :Elem)
711
- expr = NativeExpression.new(d_arg, flag_escape)
712
- stmt_list << build_print_expr_stmt(expr, arg.stag_info, arg.etag_info)
826
+ expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
827
+ expr = NativeExpression.new(expr_str, flag_escape)
828
+ stmt_list << build_print_expr_stmt(expr, e.stag_info, e.etag_info)
713
829
 
714
830
  when :cont, :Cont, :CONT, :value, :Value, :VALUE
715
- error_if_empty_tag(arg)
716
- arg.stag_info.tail_space = arg.etag_info.head_space = nil # delete spaces
717
- pargs = build_print_args(arg.stag_info, arg.attr_info, arg.append_exprs)
831
+ error_if_empty_tag(elem_info, directive.str)
832
+ e.stag_info.tail_space = e.etag_info.head_space = nil # delete spaces
833
+ pargs = build_print_args(e.stag_info, e.attr_info, e.append_exprs)
718
834
  flag_escape = (d_name == :cont || d_name == :value) ? nil : (d_name == :Cont || d_name == :Value)
719
- pargs << NativeExpression.new(d_arg, flag_escape)
720
- pargs << arg.etag_info.tag_text if arg.etag_info.tagname
835
+ expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
836
+ pargs << NativeExpression.new(expr_str, flag_escape)
837
+ pargs << e.etag_info.tag_text if e.etag_info.tagname
721
838
  stmt_list << PrintStatement.new(pargs)
722
839
 
723
840
  when :attr, :Attr, :ATTR
724
841
  unless d_arg =~ self.mapping_pattern() # ex. /\A'([-:\w]+)'\s+(.*)\z/
725
- raise convert_error("'#{d_str}': invalid attr pattern.", arg.stag_info.linenum)
842
+ raise convert_error("'#{d_str}': invalid attr pattern.", linenum)
726
843
  end
727
844
  aname = $1; avalue = $2
728
845
  flag_escape = d_name == :attr ? nil : (d_name == :Attr)
729
- arg.attr_info[aname] = NativeExpression.new(avalue, flag_escape)
846
+ expr_str = d_attr == 'id' ? parse_expr_str(avalue, linenum) : avalue
847
+ e.attr_info[aname] = NativeExpression.new(expr_str, flag_escape)
730
848
 
731
849
  when :append, :Append, :APPEND
732
850
  flag_escape = d_name == :append ? nil : (d_name == :Append)
733
- arg.append_exprs << NativeExpression.new(d_arg, flag_escape)
851
+ expr_str = d_attr == 'id' ? parse_expr_str(d_arg, linenum) : d_arg
852
+ e.append_exprs << NativeExpression.new(expr_str, flag_escape)
734
853
 
735
854
  when :replace_element_with_element, :replace_element_with_content,
736
855
  :replace_content_with_element, :replace_content_with_content
@@ -739,35 +858,35 @@ module Kwartz
739
858
  with_content = arr[3] == 'content'
740
859
  name = d_arg
741
860
  #
742
- error_if_empty_tag(arg) if replace_cont
743
- stmt_list << stag_stmt(arg) if replace_cont
861
+ error_if_empty_tag(elem_info, d_str) if replace_cont
862
+ stmt_list << stag_stmt(elem_info) if replace_cont
744
863
  #stmt_list << ExpandStatement.new(:element, name)
745
- elem_info = @elem_info_table[name]
864
+ elem_info2 = @elem_info_table[name]
746
865
  unless elem_info
747
- raise convert_error("'#{d_str}': element '#{name}' not found.", arg.stag_info.linenum)
866
+ raise convert_error("'#{d_str}': element '#{name}' not found.", linenum)
748
867
  end
749
- expand_element_info(elem_info, stmt_list, with_content)
750
- stmt_list << etag_stmt(arg) if replace_cont
868
+ expand_element_info(elem_info2, stmt_list, with_content)
869
+ stmt_list << etag_stmt(elem_info) if replace_cont
751
870
 
752
871
  when :replace_element_with, :replace_content_with, :replace, :placeholder
753
872
  unless d_arg =~ /\A_?(element|content)\(["']?(\w+)["']?\)\z/
754
- raise convert_error("'#{d_str}': invalid #{d_name} format.", stag_info.linenum)
873
+ raise convert_error("'#{d_str}': invalid #{d_name} format.", linenum)
755
874
  end
756
875
  kind = $1
757
876
  name = $2
758
877
  replace_cont = d_name == :replace_content_with || d_name == :placeholder
759
878
  with_content = kind == 'content'
760
879
  #
761
- error_if_empty_tag(arg) if replace_cont
762
- stmt_list << stag_stmt(arg) if replace_cont
880
+ error_if_empty_tag(elem_info, d_str) if replace_cont
881
+ stmt_list << stag_stmt(elem_info) if replace_cont
763
882
  #stmt_list << ExpandStatement.new(:element, name)
764
- elem_info = @elem_info_table[name]
765
- unless elem_info
883
+ elem_info2 = @elem_info_table[name]
884
+ unless elem_info2
766
885
  msg = "'#{d_str}': element '#{name}' not found."
767
- raise convert_error(msg, arg.stag_info.linenum)
886
+ raise convert_error(msg, linenum)
768
887
  end
769
- expand_element_info(elem_info, stmt_list, with_content)
770
- stmt_list << etag_stmt(arg) if replace_cont
888
+ expand_element_info(elem_info2, stmt_list, with_content)
889
+ stmt_list << etag_stmt(elem_info) if replace_cont
771
890
 
772
891
  else
773
892
  return false
@@ -778,6 +897,19 @@ module Kwartz
778
897
  end
779
898
 
780
899
 
900
+ def apply_rulesets(elem_info)
901
+ assert unless !elem_info.applied
902
+ elem_info.applied = true
903
+ tagname = elem_info.stag_info.tagname
904
+ classname = elem_info.attr_info['class']
905
+ #idname = elem_info.name || elem_info.attr_info['id']
906
+ ruleset = nil
907
+ elem_info.apply(ruleset) if ruleset = get_ruleset(tagname)
908
+ elem_info.apply(ruleset) if classname && (ruleset = get_ruleset('.'+classname))
909
+ #elem_info.apply(ruleset) if idname && (ruleset = get_ruleset('#'+idname))
910
+ end
911
+
912
+
781
913
  def extract(elem_name, content_only=false)
782
914
  elem_info = @elem_info_table[elem_name]
783
915
  elem_info or raise convert_error("element '#{elem_name}' not found.", nil)
@@ -809,13 +941,11 @@ module Kwartz
809
941
  ## (abstract) covnert presentation data into list of Statement.
810
942
  ##
811
943
  class Converter
812
- include ConverterHelper
813
- include StatementHelper
944
+ include ConvertErrorHelper
814
945
 
815
946
 
816
947
  def initialize(handler, properties={})
817
948
  @handler = handler
818
- @handler.converter = self
819
949
  end
820
950
 
821
951
  attr_reader :handler #, :dattr, :input
@@ -853,7 +983,7 @@ module Kwartz
853
983
 
854
984
  def initialize(handler, properties={})
855
985
  super
856
- include_properties(properties) # set @delspan and @dattr
986
+ @dattr = properties.fetch(:dattr, Config::PROPERTY_DATTR) # default: 'kw:d'
857
987
  end
858
988
 
859
989
 
@@ -868,18 +998,28 @@ module Kwartz
868
998
  end
869
999
  protected :reset
870
1000
 
1001
+
871
1002
  attr_reader :rest, :linenum
872
1003
 
873
1004
 
874
1005
  def convert(input, filename='')
875
1006
  reset(input, filename)
876
1007
  stmt_list = []
877
- doc_ruleset = @handler.get_element_ruleset('DOCUMENT')
878
- stmt_list += doc_ruleset.begin if doc_ruleset && doc_ruleset.begin
879
- #stmt_list << NativeStatement.new(doc_ruleset.head.chomp, nil) if doc_ruleset && doc_ruleset.head
880
1008
  _convert(stmt_list)
881
- stmt_list += doc_ruleset.end if doc_ruleset && doc_ruleset.end
882
- #stmt_list << NativeStatement.new(doc_ruleset.tail.chomp, nil) if doc_ruleset && doc_ruleset.tail
1009
+ ruleset = @handler.get_ruleset('#DOCUMENT')
1010
+ if ruleset
1011
+ stmt_list2 = []
1012
+ elem_info = nil
1013
+ r = ruleset
1014
+ @handler.expand_statements(r.before, stmt_list2, elem_info) if r.before
1015
+ if r.logic
1016
+ @handler.expand_statements(r.logic, stmt_list2, elem_info)
1017
+ else
1018
+ stmt_list2.concat(stmt_list)
1019
+ end
1020
+ @handler.expand_statements(r.after, stmt_list2, elem_info) if r.after
1021
+ stmt_list = stmt_list2
1022
+ end
883
1023
  return stmt_list
884
1024
  end
885
1025
 
@@ -896,10 +1036,19 @@ module Kwartz
896
1036
  end
897
1037
 
898
1038
 
1039
+ def match_ruleset(taginfo, attr_info)
1040
+ idname = attr_info['id']
1041
+ return true if idname && @handler.get_ruleset("#"+idname)
1042
+ classname = attr_info['class']
1043
+ return true if classname && @handler.get_ruleset("."+classname)
1044
+ return @handler.get_ruleset(taginfo.tagname) ? true : false
1045
+ end
1046
+
1047
+
899
1048
  private
900
1049
 
901
1050
 
902
- def fetch
1051
+ def _fetch
903
1052
  str = @scanner.scan(@@fetch_pattern)
904
1053
  unless str
905
1054
  @rest = @scanner.scan(/.*/m)
@@ -918,11 +1067,11 @@ module Kwartz
918
1067
  start_linenum = @linenum
919
1068
 
920
1069
  ##
921
- while taginfo = fetch()
1070
+ while taginfo = _fetch()
922
1071
  #tag_text, prev_text, head_space, is_etag, tagname, attr_str, extra_space, is_empty, tail_space = taginfo.to_a
923
1072
 
924
1073
  prev_text = taginfo.prev_text
925
- stmt_list << create_text_print_stmt(prev_text) if prev_text && !prev_text.empty?
1074
+ stmt_list << _create_text_print_stmt(prev_text) if prev_text && !prev_text.empty?
926
1075
 
927
1076
  if taginfo.is_etag? # end tag
928
1077
 
@@ -930,36 +1079,49 @@ module Kwartz
930
1079
  etag_info = taginfo
931
1080
  return etag_info
932
1081
  else
933
- stmt_list << create_text_print_stmt(taginfo.tag_text)
1082
+ stmt_list << _create_text_print_stmt(taginfo.tag_text)
934
1083
  end
935
1084
 
936
1085
  elsif taginfo.is_empty? || skip_etag?(taginfo) # empty tag
937
1086
 
938
1087
  attr_info = AttrInfo.new(taginfo.attr_str)
939
- if has_directive?(attr_info, taginfo)
1088
+ directive = _get_directive(attr_info, taginfo)
1089
+ if directive
940
1090
  stag_info = taginfo
941
1091
  etag_info = nil
942
1092
  cont_stmts = []
943
- handle_directive(stag_info, etag_info, cont_stmts, attr_info, stmt_list)
1093
+ elem_info = ElementInfo.new(stag_info, etag_info, cont_stmts, attr_info, nil)
1094
+ @handler.apply_rulesets(elem_info)
1095
+ @handler.handle_directives(directive, elem_info, stmt_list)
944
1096
  else
945
- stmt_list << create_text_print_stmt(taginfo.tag_text)
1097
+ stmt_list << _create_text_print_stmt(taginfo.tag_text)
946
1098
  end
947
1099
 
948
1100
  else # start tag
949
1101
 
950
1102
  attr_info = AttrInfo.new(taginfo.attr_str)
951
- if has_directive?(attr_info, taginfo)
1103
+ directive = _get_directive(attr_info, taginfo)
1104
+ if directive
952
1105
  stag_info = taginfo
953
1106
  cont_stmts = []
954
- etag_info = _convert(cont_stmts, taginfo)
955
- handle_directive(stag_info, etag_info, cont_stmts, attr_info, stmt_list)
1107
+ etag_info = _convert(cont_stmts, stag_info)
1108
+ elem_info = ElementInfo.new(stag_info, etag_info, cont_stmts, attr_info, nil)
1109
+ @handler.apply_rulesets(elem_info)
1110
+ @handler.handle_directives(directive, elem_info, stmt_list)
1111
+ elsif match_ruleset(taginfo, attr_info)
1112
+ stag_info = taginfo
1113
+ cont_stmts = []
1114
+ etag_info = _convert(cont_stmts, stag_info)
1115
+ elem_info = ElementInfo.new(stag_info, etag_info, cont_stmts, attr_info, nil)
1116
+ @handler.apply_rulesets(elem_info)
1117
+ @handler.expand_element_info(elem_info, stmt_list)
956
1118
  elsif taginfo.tagname == start_tagname
957
1119
  stag_info = taginfo
958
- stmt_list << create_text_print_stmt(stag_info.tag_text)
1120
+ stmt_list << _create_text_print_stmt(stag_info.tag_text)
959
1121
  etag_info = _convert(stmt_list, stag_info)
960
- stmt_list << create_text_print_stmt(etag_info.tag_text)
1122
+ stmt_list << _create_text_print_stmt(etag_info.tag_text)
961
1123
  else
962
- stmt_list << create_text_print_stmt(taginfo.tag_text)
1124
+ stmt_list << _create_text_print_stmt(taginfo.tag_text)
963
1125
  end
964
1126
 
965
1127
  end #if
@@ -970,64 +1132,14 @@ module Kwartz
970
1132
  raise convert_error("'<#{start_tagname}>' is not closed.", start_tag_info.linenum)
971
1133
  end
972
1134
 
973
- stmt_list << create_text_print_stmt(@rest) if @rest
1135
+ stmt_list << _create_text_print_stmt(@rest) if @rest && ! @rest.empty?
974
1136
  nil
975
1137
 
976
1138
  end #def
977
1139
 
978
1140
 
979
- def handle_directive(stag_info, etag_info, cont_stmts, attr_info, stmt_list)
980
- directive_name = directive_arg = directive_str = nil
981
- append_exprs = nil
982
-
983
- ## handle 'attr:' and 'append:' directives
984
- d_str = nil
985
- attr_info.directive.split(/;/).each do |d_str|
986
- d_str.strip!
987
- unless d_str =~ @handler.directive_pattern # ex. /\A(\w+):\s*(.*)\z/
988
- raise convert_error("'#{d_str}': invalid directive pattern", stag_info.linenum)
989
- end
990
- d_name = $1.intern # directive name
991
- d_arg = $2 || '' # directive arg
992
- case d_name
993
- when :attr, :Attr, :ATTR
994
- handler_args = HandlerArgument.new(d_name, d_arg, d_str, stag_info, etag_info,
995
- cont_stmts, attr_info, append_exprs)
996
- @handler.handle(stmt_list, handler_args)
997
- when :append, :Append, :APPEND
998
- append_exprs ||= []
999
- handler_args = HandlerArgument.new(d_name, d_arg, d_str, stag_info, etag_info,
1000
- cont_stmts, attr_info, append_exprs)
1001
- @handler.handle(stmt_list, handler_args)
1002
- else
1003
- if directive_name
1004
- raise convert_error("'#{d_str}': not available with '#{directive_name}' directive.", stag_info.linenum)
1005
- end
1006
- directive_name = d_name
1007
- directive_arg = d_arg
1008
- directive_str = d_str
1009
- end #case
1010
- end if attr_info.directive
1011
-
1012
- ## remove dummy <span> tag
1013
- if @delspan && stag_info.tagname == 'span' && attr_info.empty? && append_exprs.nil? && directive_name != :id
1014
- stag_info.tagname = etag_info.tagname = nil
1015
- end
1016
-
1017
- ## handle other directives
1018
- handler_args = HandlerArgument.new(directive_name, directive_arg, directive_str,
1019
- stag_info, etag_info, cont_stmts,
1020
- attr_info, append_exprs)
1021
- ret = @handler.handle(stmt_list, handler_args)
1022
- if directive_name && !ret
1023
- raise convert_error("'#{directive_str}': unknown directive.", stag_info.linenum)
1024
- end
1025
-
1026
- end
1027
-
1028
-
1029
- ## detect whether directive is exist or not
1030
- def has_directive?(attr_info, taginfo)
1141
+ ## get directive object
1142
+ def _get_directive(attr_info, taginfo)
1031
1143
  ## kw:d attribute
1032
1144
  val = attr_info[@dattr] # ex. @dattr == 'kw:d'
1033
1145
  if val && val.is_a?(String) && !val.empty?
@@ -1037,8 +1149,9 @@ module Kwartz
1037
1149
  #return false
1038
1150
  elsif val =~ @handler.directive_pattern() # ex. /\A(\w+):\s*(.*)/
1039
1151
  attr_info.delete(@dattr)
1040
- attr_info.directive = val
1041
- return true
1152
+ #directive = Directive.new(:name=>$1.intern, :arg=>$2, :dattr=>@dattr, :str=>val)
1153
+ directive = Directive.new(:dattr=>@dattr, :str=>val)
1154
+ return directive
1042
1155
  else
1043
1156
  raise convert_error("'#{@dattr}=\"#{val}\"': invalid directive pattern.", taginfo.linenum)
1044
1157
  end
@@ -1047,21 +1160,22 @@ module Kwartz
1047
1160
  val = attr_info['id']
1048
1161
  if val
1049
1162
  case val
1050
- when /\A\w+\z/
1051
- attr_info.directive = @handler.directive_format() % ['mark', val]
1052
- return true
1053
- #when @handler.directive_pattern() # ex. /\A\w+:/
1163
+ when /\A[-\w]+\z/
1164
+ directive = Directive.new(:name=>:mark, :arg=>val, :dattr=>'id', :str=>val)
1165
+ return directive
1166
+ #when @handler.directive_pattern() # ex. /\A(\w+):(.*)/
1054
1167
  # attr_info.delete('id')
1055
- # attr_info.directive = val
1056
- # return true
1057
- when /\A(mark|dummy):(\w+)\z/,
1058
- /\A(replace_(?:element|content)_with_(?:element|content)):(\w+)\z/
1059
- attr_info.directive = @handler.directive_format() % [$1, $2]
1168
+ # directive = Directive.new(:name=>$1.intern, :arg=>$2, :dattr=>'id', :str=>val)
1169
+ # return directive
1170
+ when /\A(mark|dummy):([-\w]+)\z/,
1171
+ /\A(value|stag|cont|etag|elem|default):(.*)\z/i,
1172
+ /\A(replace_[a-z]+_with_[a-z]+):([-\w]+)\z/
1060
1173
  attr_info.delete('id')
1061
- return true
1174
+ directive = Directive.new(:name=>$1.intern, :arg=>$2, :dattr=>'id', :str=>val)
1175
+ return directive
1062
1176
  end
1063
1177
  end
1064
- return false
1178
+ return nil
1065
1179
  end
1066
1180
 
1067
1181
 
@@ -1075,6 +1189,12 @@ module Kwartz
1075
1189
  end
1076
1190
 
1077
1191
 
1192
+ def _create_text_print_stmt(text)
1193
+ return PrintStatement.new([text])
1194
+ #return PritnStatement.new([TextExpression.new(text)])
1195
+ end
1196
+
1197
+
1078
1198
  end #class
1079
1199
  Converter.register_class('text', TextConverter)
1080
1200