hobo 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/LICENSE.txt +22 -0
  2. data/README.txt +18 -0
  3. data/bin/hobo +81 -0
  4. data/hobo_files/plugin/CHANGES.txt +963 -0
  5. data/hobo_files/plugin/LICENSE.txt +22 -0
  6. data/hobo_files/plugin/README +4 -0
  7. data/hobo_files/plugin/Rakefile +11 -0
  8. data/hobo_files/plugin/generators/hobo/hobo_generator.rb +37 -0
  9. data/hobo_files/plugin/generators/hobo/templates/application.dryml +2 -0
  10. data/hobo_files/plugin/generators/hobo/templates/guest.rb +31 -0
  11. data/hobo_files/plugin/generators/hobo_front_controller/USAGE +11 -0
  12. data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +90 -0
  13. data/hobo_files/plugin/generators/hobo_front_controller/templates/controller.rb +51 -0
  14. data/hobo_files/plugin/generators/hobo_front_controller/templates/functional_test.rb +18 -0
  15. data/hobo_files/plugin/generators/hobo_front_controller/templates/helper.rb +2 -0
  16. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +43 -0
  17. data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +44 -0
  18. data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +18 -0
  19. data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +45 -0
  20. data/hobo_files/plugin/generators/hobo_model/USAGE +26 -0
  21. data/hobo_files/plugin/generators/hobo_model/hobo_model_generator.rb +38 -0
  22. data/hobo_files/plugin/generators/hobo_model/templates/fixtures.yml +11 -0
  23. data/hobo_files/plugin/generators/hobo_model/templates/migration.rb +13 -0
  24. data/hobo_files/plugin/generators/hobo_model/templates/model.rb +24 -0
  25. data/hobo_files/plugin/generators/hobo_model/templates/unit_test.rb +10 -0
  26. data/hobo_files/plugin/generators/hobo_model_controller/USAGE +30 -0
  27. data/hobo_files/plugin/generators/hobo_model_controller/hobo_model_controller_generator.rb +43 -0
  28. data/hobo_files/plugin/generators/hobo_model_controller/templates/controller.rb +5 -0
  29. data/hobo_files/plugin/generators/hobo_model_controller/templates/functional_test.rb +18 -0
  30. data/hobo_files/plugin/generators/hobo_model_controller/templates/helper.rb +2 -0
  31. data/hobo_files/plugin/generators/hobo_model_controller/templates/view.rhtml +2 -0
  32. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +51 -0
  33. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +436 -0
  34. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/default_mapping.rb +11 -0
  35. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/banner.gif +0 -0
  36. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_bodytop.gif +0 -0
  37. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_01.gif +0 -0
  38. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_02.gif +0 -0
  39. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_03.gif +0 -0
  40. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_04.gif +0 -0
  41. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_bottom.gif +0 -0
  42. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_left.gif +0 -0
  43. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_right.gif +0 -0
  44. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_top.gif +0 -0
  45. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_blue.gif +0 -0
  46. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_dblue.gif +0 -0
  47. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_green.gif +0 -0
  48. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_purple.gif +0 -0
  49. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_red.gif +0 -0
  50. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/logo.gif +0 -0
  51. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/spinner.gif +0 -0
  52. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_dblue.gif +0 -0
  53. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_green.gif +0 -0
  54. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_purple.gif +0 -0
  55. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_red.gif +0 -0
  56. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_01.gif +0 -0
  57. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_02.gif +0 -0
  58. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_03.gif +0 -0
  59. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_04.gif +0 -0
  60. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_bottom.gif +0 -0
  61. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_left.gif +0 -0
  62. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_right.gif +0 -0
  63. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_top.gif +0 -0
  64. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +390 -0
  65. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +104 -0
  66. data/hobo_files/plugin/generators/hobo_user_model/USAGE +26 -0
  67. data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +38 -0
  68. data/hobo_files/plugin/generators/hobo_user_model/templates/fixtures.yml +11 -0
  69. data/hobo_files/plugin/generators/hobo_user_model/templates/migration.rb +15 -0
  70. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +58 -0
  71. data/hobo_files/plugin/generators/hobo_user_model/templates/unit_test.rb +10 -0
  72. data/hobo_files/plugin/init.rb +44 -0
  73. data/hobo_files/plugin/lib/action_view_extensions/base.rb +14 -0
  74. data/hobo_files/plugin/lib/active_record/has_many_association.rb +54 -0
  75. data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +22 -0
  76. data/hobo_files/plugin/lib/active_record/table_definition.rb +34 -0
  77. data/hobo_files/plugin/lib/extensions.rb +245 -0
  78. data/hobo_files/plugin/lib/extensions/test_case.rb +130 -0
  79. data/hobo_files/plugin/lib/hobo.rb +353 -0
  80. data/hobo_files/plugin/lib/hobo/HtmlString +3 -0
  81. data/hobo_files/plugin/lib/hobo/authenticated_user.rb +106 -0
  82. data/hobo_files/plugin/lib/hobo/authentication_support.rb +108 -0
  83. data/hobo_files/plugin/lib/hobo/composite_model.rb +66 -0
  84. data/hobo_files/plugin/lib/hobo/controller.rb +134 -0
  85. data/hobo_files/plugin/lib/hobo/controller_helpers.rb +135 -0
  86. data/hobo_files/plugin/lib/hobo/core.rb +475 -0
  87. data/hobo_files/plugin/lib/hobo/define_tags.rb +56 -0
  88. data/hobo_files/plugin/lib/hobo/dryml.rb +161 -0
  89. data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +126 -0
  90. data/hobo_files/plugin/lib/hobo/dryml/tag_module.rb +9 -0
  91. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +57 -0
  92. data/hobo_files/plugin/lib/hobo/dryml/template.rb +586 -0
  93. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +302 -0
  94. data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +19 -0
  95. data/hobo_files/plugin/lib/hobo/generator.rb +25 -0
  96. data/hobo_files/plugin/lib/hobo/html_string.rb +3 -0
  97. data/hobo_files/plugin/lib/hobo/lazy_hash.rb +28 -0
  98. data/hobo_files/plugin/lib/hobo/mapping_tags.rb +262 -0
  99. data/hobo_files/plugin/lib/hobo/markdown_string.rb +7 -0
  100. data/hobo_files/plugin/lib/hobo/model.rb +391 -0
  101. data/hobo_files/plugin/lib/hobo/model_controller.rb +676 -0
  102. data/hobo_files/plugin/lib/hobo/model_queries.rb +92 -0
  103. data/hobo_files/plugin/lib/hobo/model_support.rb +44 -0
  104. data/hobo_files/plugin/lib/hobo/password_string.rb +3 -0
  105. data/hobo_files/plugin/lib/hobo/predicate_dispatch.rb +78 -0
  106. data/hobo_files/plugin/lib/hobo/proc_binding.rb +32 -0
  107. data/hobo_files/plugin/lib/hobo/rapid.rb +447 -0
  108. data/hobo_files/plugin/lib/hobo/static_tags +92 -0
  109. data/hobo_files/plugin/lib/hobo/text.rb +3 -0
  110. data/hobo_files/plugin/lib/hobo/textile_string.rb +13 -0
  111. data/hobo_files/plugin/lib/hobo/undefined.rb +41 -0
  112. data/hobo_files/plugin/lib/hobo/undefined_access_error.rb +5 -0
  113. data/hobo_files/plugin/lib/hobo/where_fragment.rb +23 -0
  114. data/hobo_files/plugin/lib/rexml.rb +345 -0
  115. data/hobo_files/plugin/tags/core.dryml +6 -0
  116. data/hobo_files/plugin/tags/rapid.dryml +177 -0
  117. data/hobo_files/plugin/tags/rapid_editing.dryml +168 -0
  118. data/hobo_files/plugin/tags/rapid_navigation.dryml +95 -0
  119. data/hobo_files/plugin/tags/rapid_pages.dryml +175 -0
  120. data/hobo_files/plugin/tasks/environments.rake +19 -0
  121. data/hobo_files/plugin/tasks/hobo_tasks.rake +4 -0
  122. data/hobo_files/plugin/test/hobo_dryml_template_test.rb +7 -0
  123. data/hobo_files/plugin/test/hobo_test.rb +7 -0
  124. data/hobo_files/plugin/uninstall.rb +1 -0
  125. metadata +206 -0
@@ -0,0 +1,92 @@
1
+ a
2
+ abbr
3
+ acronym
4
+ address
5
+ applet
6
+ area
7
+ b
8
+ base
9
+ basefont
10
+ bdo
11
+ big
12
+ blockquote
13
+ body
14
+ br
15
+ button
16
+ caption
17
+ center
18
+ cite
19
+ code
20
+ col
21
+ colgroup
22
+ dd
23
+ del
24
+ dfn
25
+ dir
26
+ div
27
+ dl
28
+ dt
29
+ em
30
+ embed
31
+ fieldset
32
+ font
33
+ form
34
+ frame
35
+ frameset
36
+ h1
37
+ h2
38
+ h3
39
+ h4
40
+ h5
41
+ h6
42
+ head
43
+ hr
44
+ html
45
+ i
46
+ iframe
47
+ img
48
+ input
49
+ ins
50
+ isindex
51
+ kbd
52
+ label
53
+ legend
54
+ li
55
+ link
56
+ map
57
+ menu
58
+ meta
59
+ noframes
60
+ noscript
61
+ object
62
+ ol
63
+ optgroup
64
+ option
65
+ p
66
+ param
67
+ pre
68
+ q
69
+ s
70
+ samp
71
+ script
72
+ select
73
+ small
74
+ span
75
+ strike
76
+ strong
77
+ style
78
+ sub
79
+ sup
80
+ table
81
+ tbody
82
+ td
83
+ textarea
84
+ tfoot
85
+ th
86
+ thead
87
+ title
88
+ tr
89
+ tt
90
+ u
91
+ ul
92
+ var
@@ -0,0 +1,3 @@
1
+ class Hobo::Text < String
2
+
3
+ end
@@ -0,0 +1,13 @@
1
+ class Hobo::TextileString < String
2
+
3
+ def to_html
4
+ if text.blank?
5
+ ""
6
+ else
7
+ textilized = RedCloth.new(self, [ :hard_breaks ])
8
+ textilized.hard_breaks = true if textilized.respond_to?("hard_breaks=")
9
+ textilized.to_html
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,41 @@
1
+ module Hobo
2
+
3
+ class Undefined
4
+
5
+ def initialize(klass=Object)
6
+ @klass = klass
7
+ end
8
+
9
+ def hobo_undefined?
10
+ true
11
+ end
12
+
13
+ def class
14
+ @klass
15
+ end
16
+
17
+ def is_a?(klass)
18
+ return klass == @klass || klass > @klass
19
+ end
20
+
21
+ def to_s
22
+ "<Hobo::Undefined #{@klass}>"
23
+ end
24
+
25
+ def inspect
26
+ to_s
27
+ end
28
+
29
+ def new_record?
30
+ true
31
+ end
32
+
33
+ def method_missing(name, *args)
34
+ raise UndefinedAccessError.new("call to: #{name}")
35
+ end
36
+
37
+ undef_method :==
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,5 @@
1
+ module Hobo
2
+
3
+ class UndefinedAccessError < RuntimeError; end
4
+
5
+ end
@@ -0,0 +1,23 @@
1
+ module Hobo
2
+
3
+ class WhereFragment
4
+
5
+ def initialize(sql, *params)
6
+ @sql = params.empty? ? sql : ActiveRecord::Base.send(:sanitize_sql, [sql] + params)
7
+ end
8
+
9
+ def &(rhs)
10
+ WhereFragment.new("(#{to_sql}) and (#{rhs.to_sql})")
11
+ end
12
+
13
+ def |(rhs)
14
+ WhereFragment.new("(#{to_sql}) or (#{rhs.to_sql})")
15
+ end
16
+
17
+ def to_sql
18
+ @sql
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,345 @@
1
+ # Hobo needs to process XML as transparently as possibe. In the case of tags
2
+ # that are not defined by hobo (i.e. html tags), they should pass through just
3
+ # as they were in the dryml source. Recontructing the tags from the DOM is not
4
+ # good enough. The extensions to REXML in here allow Hobo to use the original
5
+ # start tag source in the output.
6
+ # There's also some fixes/extras to allow error messages with line numbers.
7
+
8
+ # The main hack is that Element nodes have two instance variables added:
9
+ # @start_tag_source and @source_offset
10
+
11
+ # So cool that Ruby allows us to redfine a method. Such a shame the method
12
+ # happened to be 200 lines long :-(
13
+
14
+ require 'rexml/document'
15
+
16
+ module REXML
17
+ module Parsers
18
+ class BaseParser
19
+ def pull
20
+ if @closed
21
+ x, @closed = @closed, nil
22
+ return [ :end_element, x ]
23
+ end
24
+ return [ :end_document ] if empty?
25
+ return @stack.shift if @stack.size > 0
26
+ @source.read if @source.buffer.size<2
27
+ if @document_status == nil
28
+ @source.consume( /^\s*/um )
29
+ word = @source.match( /(<[^>]*)>/um )
30
+ word = word[1] unless word.nil?
31
+ case word
32
+ when COMMENT_START
33
+ return [ :comment, @source.match( COMMENT_PATTERN, true )[1] ]
34
+ when XMLDECL_START
35
+ results = @source.match( XMLDECL_PATTERN, true )[1]
36
+ version = VERSION.match( results )
37
+ version = version[1] unless version.nil?
38
+ encoding = ENCODING.match(results)
39
+ encoding = encoding[1] unless encoding.nil?
40
+ @source.encoding = encoding
41
+ standalone = STANDALONE.match(results)
42
+ standalone = standalone[1] unless standalone.nil?
43
+ return [ :xmldecl, version, encoding, standalone]
44
+ when INSTRUCTION_START
45
+ return [ :processing_instruction, *@source.match(INSTRUCTION_PATTERN, true)[1,2] ]
46
+ when DOCTYPE_START
47
+ md = @source.match( DOCTYPE_PATTERN, true )
48
+ identity = md[1]
49
+ close = md[2]
50
+ identity =~ IDENTITY
51
+ name = $1
52
+ raise REXML::ParseException("DOCTYPE is missing a name") if name.nil?
53
+ pub_sys = $2.nil? ? nil : $2.strip
54
+ long_name = $3.nil? ? nil : $3.strip
55
+ uri = $4.nil? ? nil : $4.strip
56
+ args = [ :start_doctype, name, pub_sys, long_name, uri ]
57
+ if close == ">"
58
+ @document_status = :after_doctype
59
+ @source.read if @source.buffer.size<2
60
+ md = @source.match(/^\s*/um, true)
61
+ @stack << [ :end_doctype ]
62
+ else
63
+ @document_status = :in_doctype
64
+ end
65
+ return args
66
+ else
67
+ @document_status = :after_doctype
68
+ @source.read if @source.buffer.size<2
69
+ md = @source.match(/\s*/um, true)
70
+ end
71
+ end
72
+ if @document_status == :in_doctype
73
+ md = @source.match(/\s*(.*?>)/um)
74
+ case md[1]
75
+ when SYSTEMENTITY
76
+ match = @source.match( SYSTEMENTITY, true )[1]
77
+ return [ :externalentity, match ]
78
+
79
+ when ELEMENTDECL_START
80
+ return [ :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )[1] ]
81
+
82
+ when ENTITY_START
83
+ match = @source.match( ENTITYDECL, true ).to_a.compact
84
+ match[0] = :entitydecl
85
+ ref = false
86
+ if match[1] == '%'
87
+ ref = true
88
+ match.delete_at 1
89
+ end
90
+ # Now we have to sort out what kind of entity reference this is
91
+ if match[2] == 'SYSTEM'
92
+ # External reference
93
+ match[3] = match[3][1..-2] # PUBID
94
+ match.delete_at(4) if match.size > 4 # Chop out NDATA decl
95
+ # match is [ :entity, name, SYSTEM, pubid(, ndata)? ]
96
+ elsif match[2] == 'PUBLIC'
97
+ # External reference
98
+ match[3] = match[3][1..-2] # PUBID
99
+ match[4] = match[4][1..-2] # HREF
100
+ # match is [ :entity, name, PUBLIC, pubid, href ]
101
+ else
102
+ match[2] = match[2][1..-2]
103
+ match.pop if match.size == 4
104
+ # match is [ :entity, name, value ]
105
+ end
106
+ match << '%' if ref
107
+ return match
108
+ when ATTLISTDECL_START
109
+ md = @source.match( ATTLISTDECL_PATTERN, true )
110
+ raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil?
111
+ element = md[1]
112
+ contents = md[0]
113
+
114
+ pairs = {}
115
+ values = md[0].scan( ATTDEF_RE )
116
+ values.each do |attdef|
117
+ unless attdef[3] == "#IMPLIED"
118
+ attdef.compact!
119
+ val = attdef[3]
120
+ val = attdef[4] if val == "#FIXED "
121
+ pairs[attdef[0]] = val
122
+ end
123
+ end
124
+ return [ :attlistdecl, element, pairs, contents ]
125
+ when NOTATIONDECL_START
126
+ md = nil
127
+ if @source.match( PUBLIC )
128
+ md = @source.match( PUBLIC, true )
129
+ elsif @source.match( SYSTEM )
130
+ md = @source.match( SYSTEM, true )
131
+ else
132
+ raise REXML::ParseException.new( "error parsing notation: no matching pattern", @source )
133
+ end
134
+ return [ :notationdecl, md[1], md[2], md[3] ]
135
+ when CDATA_END
136
+ @document_status = :after_doctype
137
+ @source.match( CDATA_END, true )
138
+ return [ :end_doctype ]
139
+ end
140
+ end
141
+ begin
142
+ if @source.buffer[0] == ?<
143
+ if @source.buffer[1] == ?/
144
+ last_tag, line_no = @tags.pop
145
+ #md = @source.match_to_consume( '>', CLOSE_MATCH)
146
+ md = @source.match( CLOSE_MATCH, true )
147
+ raise REXML::ParseException.new("Missing end tag for "+
148
+ "'#{last_tag}' (line #{line_no}) (got \"#{md[1]}\")",
149
+ @source) unless last_tag == md[1]
150
+ return [ :end_element, last_tag ]
151
+ elsif @source.buffer[1] == ?!
152
+ md = @source.match(/\A(\s*[^>]*>)/um)
153
+ raise REXML::ParseException.new("Malformed node", @source) unless md
154
+ if md[0][2] == ?-
155
+ md = @source.match( COMMENT_PATTERN, true )
156
+ return [ :comment, md[1] ] if md
157
+ else
158
+ md = @source.match( CDATA_PATTERN, true )
159
+ return [ :cdata, md[1] ] if md
160
+ end
161
+ raise REXML::ParseException.new( "Declarations can only occur "+
162
+ "in the doctype declaration.", @source)
163
+ elsif @source.buffer[1] == ??
164
+ md = @source.match( INSTRUCTION_PATTERN, true )
165
+ return [ :processing_instruction, md[1], md[2] ] if md
166
+ raise REXML::ParseException.new( "Bad instruction declaration",
167
+ @source)
168
+ else
169
+ # Get the next tag
170
+ md = @source.match(TAG_MATCH, true)
171
+ raise REXML::ParseException.new("malformed XML: missing tag start", @source) unless md
172
+ attrs = []
173
+ if md[2].size > 0
174
+ attrs = md[2].scan( ATTRIBUTE_PATTERN )
175
+ raise REXML::ParseException.new("error parsing attributes: [#{attrs.join ', '}], excess = \"#$'\"",
176
+ @source) if $' and $'.strip.size > 0
177
+ end
178
+
179
+ if md[4]
180
+ @closed = md[1]
181
+ else
182
+ cl = @source.current_line
183
+ @tags.push([md[1], cl && cl[2]])
184
+ end
185
+ attributes = {}
186
+ attrs.each { |a,b,c| attributes[a] = c }
187
+ return [ :start_element, md[1], attributes, md[0],
188
+ @source.respond_to?(:last_match_offset) && @source.last_match_offset ]
189
+ end
190
+ else
191
+ md = @source.match( TEXT_PATTERN, true )
192
+ if md[0].length == 0
193
+ @source.match( /(\s+)/, true )
194
+ end
195
+ #return [ :text, "" ] if md[0].length == 0
196
+ # unnormalized = Text::unnormalize( md[1], self )
197
+ # return PullEvent.new( :text, md[1], unnormalized )
198
+ return [ :text, md[1] ]
199
+ end
200
+ rescue REXML::ParseException
201
+ raise
202
+ rescue Exception, NameError => error
203
+ raise REXML::ParseException.new( "Exception parsing",
204
+ @source, self, (error ? error : $!) )
205
+ end
206
+ return [ :dummy ]
207
+ end
208
+ end
209
+
210
+ class TreeParser
211
+ def parse
212
+ tag_stack = []
213
+ in_doctype = false
214
+ entities = nil
215
+ begin
216
+ while true
217
+ event = @parser.pull
218
+ case event[0]
219
+ when :end_document
220
+ return
221
+ when :start_element
222
+ tag_stack.push(event[1])
223
+ # find the observers for namespaces
224
+ @build_context = @build_context.add_element( event[1], event[2] )
225
+ @build_context.instance_variable_set("@start_tag_source", event[3])
226
+ @build_context.instance_variable_set("@source_offset", event[4])
227
+ when :end_element
228
+ tag_stack.pop
229
+ @build_context = @build_context.parent
230
+ when :text
231
+ if not in_doctype
232
+ if @build_context[-1].instance_of? Text
233
+ @build_context[-1] << event[1]
234
+ else
235
+ @build_context.add(
236
+ Text.new( event[1], @build_context.whitespace, nil, true )
237
+ ) unless (
238
+ event[1].strip.size==0 and
239
+ @build_context.ignore_whitespace_nodes
240
+ )
241
+ end
242
+ end
243
+ when :comment
244
+ c = Comment.new( event[1] )
245
+ @build_context.add( c )
246
+ when :cdata
247
+ c = CData.new( event[1] )
248
+ @build_context.add( c )
249
+ when :processing_instruction
250
+ @build_context.add( Instruction.new( event[1], event[2] ) )
251
+ when :end_doctype
252
+ in_doctype = false
253
+ entities.each { |k,v| entities[k] = @build_context.entities[k].value }
254
+ @build_context = @build_context.parent
255
+ when :start_doctype
256
+ doctype = DocType.new( event[1..-1], @build_context )
257
+ @build_context = doctype
258
+ entities = {}
259
+ in_doctype = true
260
+ when :attlistdecl
261
+ n = AttlistDecl.new( event[1..-1] )
262
+ @build_context.add( n )
263
+ when :externalentity
264
+ n = ExternalEntity.new( event[1] )
265
+ @build_context.add( n )
266
+ when :elementdecl
267
+ n = ElementDecl.new( event[1] )
268
+ @build_context.add(n)
269
+ when :entitydecl
270
+ entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/
271
+ @build_context.add(Entity.new(event))
272
+ when :notationdecl
273
+ n = NotationDecl.new( *event[1..-1] )
274
+ @build_context.add( n )
275
+ when :xmldecl
276
+ x = XMLDecl.new( event[1], event[2], event[3] )
277
+ @build_context.add( x )
278
+ end
279
+ end
280
+ rescue REXML::Validation::ValidationException
281
+ raise
282
+ rescue
283
+ raise ParseException.new( $!.message, @parser.source, @parser, $! )
284
+ end
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ module Hobo::Dryml
291
+
292
+ class RexSource < REXML::Source
293
+
294
+ def initialize(src)
295
+ super(src)
296
+ @buffer_offset = 0
297
+ end
298
+
299
+ attr_reader :last_match_offset
300
+
301
+ def remember_match(m)
302
+ if m
303
+ @last_match = m
304
+ @last_match_offset = @buffer_offset + m.begin(0)
305
+ @orig[@last_match_offset..@last_match_offset+m[0].length] == @buffer[m.begin(0)..m.end(0)]
306
+ end
307
+ m
308
+ end
309
+
310
+ def advance_buffer(md)
311
+ @buffer = md.post_match
312
+ @buffer_offset += md.end(0)
313
+ end
314
+
315
+ def scan(pattern, cons=false)
316
+ raise '!'
317
+ return nil if @buffer.nil?
318
+ rv = @buffer.scan(pattern)
319
+ if cons and rv.size > 0
320
+ advance_buffer(Regexp.last_match)
321
+ end
322
+ rv
323
+ end
324
+
325
+ def consume( pattern )
326
+ md = remember_match(pattern.match( @buffer ))
327
+ if md
328
+ advance_buffer(md)
329
+ @buffer
330
+ end
331
+ end
332
+
333
+ def match(pattern, cons=false)
334
+ md = remember_match(pattern.match(@buffer))
335
+ advance_buffer(md) if cons and md
336
+ return md
337
+ end
338
+
339
+ def current_line
340
+ pos = last_match_offset
341
+ [0, 0, @orig[0..pos].count("\n") + 1]
342
+ end
343
+
344
+ end
345
+ end