hobo 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +22 -0
- data/README.txt +18 -0
- data/bin/hobo +81 -0
- data/hobo_files/plugin/CHANGES.txt +963 -0
- data/hobo_files/plugin/LICENSE.txt +22 -0
- data/hobo_files/plugin/README +4 -0
- data/hobo_files/plugin/Rakefile +11 -0
- data/hobo_files/plugin/generators/hobo/hobo_generator.rb +37 -0
- data/hobo_files/plugin/generators/hobo/templates/application.dryml +2 -0
- data/hobo_files/plugin/generators/hobo/templates/guest.rb +31 -0
- data/hobo_files/plugin/generators/hobo_front_controller/USAGE +11 -0
- data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +90 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/controller.rb +51 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/functional_test.rb +18 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/helper.rb +2 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +43 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +44 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +18 -0
- data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +45 -0
- data/hobo_files/plugin/generators/hobo_model/USAGE +26 -0
- data/hobo_files/plugin/generators/hobo_model/hobo_model_generator.rb +38 -0
- data/hobo_files/plugin/generators/hobo_model/templates/fixtures.yml +11 -0
- data/hobo_files/plugin/generators/hobo_model/templates/migration.rb +13 -0
- data/hobo_files/plugin/generators/hobo_model/templates/model.rb +24 -0
- data/hobo_files/plugin/generators/hobo_model/templates/unit_test.rb +10 -0
- data/hobo_files/plugin/generators/hobo_model_controller/USAGE +30 -0
- data/hobo_files/plugin/generators/hobo_model_controller/hobo_model_controller_generator.rb +43 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/controller.rb +5 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/functional_test.rb +18 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/helper.rb +2 -0
- data/hobo_files/plugin/generators/hobo_model_controller/templates/view.rhtml +2 -0
- data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +51 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +436 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/default_mapping.rb +11 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/banner.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_bodytop.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_01.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_02.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_03.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_04.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_bottom.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_left.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_right.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_top.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_blue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_dblue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_green.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_purple.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_red.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/logo.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/spinner.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_dblue.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_green.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_purple.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_red.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_01.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_02.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_03.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_04.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_bottom.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_left.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_right.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_top.gif +0 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +390 -0
- data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +104 -0
- data/hobo_files/plugin/generators/hobo_user_model/USAGE +26 -0
- data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +38 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/fixtures.yml +11 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/migration.rb +15 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +58 -0
- data/hobo_files/plugin/generators/hobo_user_model/templates/unit_test.rb +10 -0
- data/hobo_files/plugin/init.rb +44 -0
- data/hobo_files/plugin/lib/action_view_extensions/base.rb +14 -0
- data/hobo_files/plugin/lib/active_record/has_many_association.rb +54 -0
- data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +22 -0
- data/hobo_files/plugin/lib/active_record/table_definition.rb +34 -0
- data/hobo_files/plugin/lib/extensions.rb +245 -0
- data/hobo_files/plugin/lib/extensions/test_case.rb +130 -0
- data/hobo_files/plugin/lib/hobo.rb +353 -0
- data/hobo_files/plugin/lib/hobo/HtmlString +3 -0
- data/hobo_files/plugin/lib/hobo/authenticated_user.rb +106 -0
- data/hobo_files/plugin/lib/hobo/authentication_support.rb +108 -0
- data/hobo_files/plugin/lib/hobo/composite_model.rb +66 -0
- data/hobo_files/plugin/lib/hobo/controller.rb +134 -0
- data/hobo_files/plugin/lib/hobo/controller_helpers.rb +135 -0
- data/hobo_files/plugin/lib/hobo/core.rb +475 -0
- data/hobo_files/plugin/lib/hobo/define_tags.rb +56 -0
- data/hobo_files/plugin/lib/hobo/dryml.rb +161 -0
- data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +126 -0
- data/hobo_files/plugin/lib/hobo/dryml/tag_module.rb +9 -0
- data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +57 -0
- data/hobo_files/plugin/lib/hobo/dryml/template.rb +586 -0
- data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +302 -0
- data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +19 -0
- data/hobo_files/plugin/lib/hobo/generator.rb +25 -0
- data/hobo_files/plugin/lib/hobo/html_string.rb +3 -0
- data/hobo_files/plugin/lib/hobo/lazy_hash.rb +28 -0
- data/hobo_files/plugin/lib/hobo/mapping_tags.rb +262 -0
- data/hobo_files/plugin/lib/hobo/markdown_string.rb +7 -0
- data/hobo_files/plugin/lib/hobo/model.rb +391 -0
- data/hobo_files/plugin/lib/hobo/model_controller.rb +676 -0
- data/hobo_files/plugin/lib/hobo/model_queries.rb +92 -0
- data/hobo_files/plugin/lib/hobo/model_support.rb +44 -0
- data/hobo_files/plugin/lib/hobo/password_string.rb +3 -0
- data/hobo_files/plugin/lib/hobo/predicate_dispatch.rb +78 -0
- data/hobo_files/plugin/lib/hobo/proc_binding.rb +32 -0
- data/hobo_files/plugin/lib/hobo/rapid.rb +447 -0
- data/hobo_files/plugin/lib/hobo/static_tags +92 -0
- data/hobo_files/plugin/lib/hobo/text.rb +3 -0
- data/hobo_files/plugin/lib/hobo/textile_string.rb +13 -0
- data/hobo_files/plugin/lib/hobo/undefined.rb +41 -0
- data/hobo_files/plugin/lib/hobo/undefined_access_error.rb +5 -0
- data/hobo_files/plugin/lib/hobo/where_fragment.rb +23 -0
- data/hobo_files/plugin/lib/rexml.rb +345 -0
- data/hobo_files/plugin/tags/core.dryml +6 -0
- data/hobo_files/plugin/tags/rapid.dryml +177 -0
- data/hobo_files/plugin/tags/rapid_editing.dryml +168 -0
- data/hobo_files/plugin/tags/rapid_navigation.dryml +95 -0
- data/hobo_files/plugin/tags/rapid_pages.dryml +175 -0
- data/hobo_files/plugin/tasks/environments.rake +19 -0
- data/hobo_files/plugin/tasks/hobo_tasks.rake +4 -0
- data/hobo_files/plugin/test/hobo_dryml_template_test.rb +7 -0
- data/hobo_files/plugin/test/hobo_test.rb +7 -0
- data/hobo_files/plugin/uninstall.rb +1 -0
- 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,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,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
|