eimxml 0.0.2 → 0.0.3.1
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.
- data/Rakefile +24 -95
- data/Rakefile.utirake +374 -0
- data/lib/eim_xml.rb +95 -220
- data/lib/eim_xml/dsl.rb +105 -0
- data/lib/eim_xml/formatter.rb +123 -0
- data/lib/eim_xml/formatter/element_wrapper.rb +7 -0
- data/lib/eim_xml/parser.rb +12 -40
- data/lib/eim_xml/xhtml.rb +84 -56
- data/lib/eim_xml/xhtml/dsl.rb +18 -0
- data/{test → spec}/assertions_test.rb +1 -0
- data/spec/dsl_spec.rb +217 -0
- data/spec/eim_xml_spec.rb +441 -0
- data/spec/formatter_spec.rb +260 -0
- data/spec/parser_spec.rb +102 -0
- data/spec/xhtml_spec.rb +524 -0
- metadata +52 -38
- data/README +0 -58
- data/test/eim_xml_test.rb +0 -648
- data/test/parser_test.rb +0 -102
- data/test/xhtml_test.rb +0 -340
@@ -0,0 +1,123 @@
|
|
1
|
+
require "eim_xml"
|
2
|
+
|
3
|
+
module EimXML
|
4
|
+
class Formatter
|
5
|
+
attr_reader :out
|
6
|
+
|
7
|
+
def self.write(element, opt={})
|
8
|
+
opt = {:out=>""}.merge(opt)
|
9
|
+
new(opt).write(element)
|
10
|
+
opt[:out]
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(opt)
|
14
|
+
@out = opt[:out]
|
15
|
+
@preservers = opt[:preservers]
|
16
|
+
@preserve_space = false
|
17
|
+
@indent_string = " "
|
18
|
+
@indent_depth = 0
|
19
|
+
@option = opt.dup.tap{|h| [:out, :preservers].each{|k| h.delete(k)}}
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(src)
|
23
|
+
case src
|
24
|
+
when ElementWrapper
|
25
|
+
write_wrapper(src)
|
26
|
+
when Comment
|
27
|
+
write_comment(src)
|
28
|
+
when Element
|
29
|
+
write_element(src)
|
30
|
+
when PCString
|
31
|
+
write_pcstring(src)
|
32
|
+
else
|
33
|
+
write_string(src.to_s)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def indent(&proc)
|
38
|
+
@indent_depth += 1
|
39
|
+
proc.call
|
40
|
+
ensure
|
41
|
+
@indent_depth -= 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def preserve_space_element?(elm)
|
45
|
+
@preservers && @preservers.any? do |e|
|
46
|
+
case e
|
47
|
+
when Symbol
|
48
|
+
e==elm.name
|
49
|
+
when Class
|
50
|
+
e===elm
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def write_indent
|
56
|
+
out << @indent_string*@indent_depth unless @preserve_space
|
57
|
+
end
|
58
|
+
|
59
|
+
def write_newline
|
60
|
+
out << "\n" unless @preserve_space
|
61
|
+
end
|
62
|
+
|
63
|
+
def write_comment(c)
|
64
|
+
write_indent
|
65
|
+
c.write_to(out)
|
66
|
+
write_newline
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_contents_of(elm)
|
70
|
+
flag = @preserve_space
|
71
|
+
@preserve_space = true if preserve_space_element?(elm)
|
72
|
+
write_newline
|
73
|
+
indent do
|
74
|
+
elm.contents.each do |c|
|
75
|
+
write(c)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
write_indent
|
79
|
+
ensure
|
80
|
+
@preserve_space = flag
|
81
|
+
end
|
82
|
+
|
83
|
+
def write_element(elm)
|
84
|
+
write_indent
|
85
|
+
out << "<"
|
86
|
+
elm.name_and_attributes(out)
|
87
|
+
case elm.contents.size
|
88
|
+
when 0
|
89
|
+
out << " />"
|
90
|
+
write_newline
|
91
|
+
else
|
92
|
+
out << ">"
|
93
|
+
write_contents_of(elm)
|
94
|
+
out << "</#{elm.name}>"
|
95
|
+
write_newline
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def write_pcstring(pcs)
|
100
|
+
pcs.encoded_string.each_line do |l|
|
101
|
+
write_indent
|
102
|
+
out << l
|
103
|
+
end
|
104
|
+
write_newline
|
105
|
+
end
|
106
|
+
|
107
|
+
def write_string(str)
|
108
|
+
PCString.encode(str).each_line do |l|
|
109
|
+
write_indent
|
110
|
+
out << l
|
111
|
+
end
|
112
|
+
write_newline
|
113
|
+
end
|
114
|
+
|
115
|
+
def write_wrapper(wrapper)
|
116
|
+
wrapper.each(@option) do |i|
|
117
|
+
write(i)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
require "eim_xml/formatter/element_wrapper"
|
data/lib/eim_xml/parser.rb
CHANGED
@@ -16,32 +16,23 @@ module EimXML
|
|
16
16
|
module RE
|
17
17
|
EMPTY_ELEMENT = /<([^>]*?)\/>/
|
18
18
|
START_TAG = /<([^>]*?([^\/>]\s*))>/
|
19
|
-
END_TAG = /<\/(\S
|
19
|
+
END_TAG = /<\/(\S+?)\s*>/
|
20
20
|
ATTRIBUTE = /\s+([^=\s]+)\s*=\s*('(.*?)'|"(.*?)")/m
|
21
21
|
STRING = /[^<]+/
|
22
22
|
end
|
23
23
|
|
24
|
-
def initialize(src
|
24
|
+
def initialize(src)
|
25
25
|
@scanner = StringScanner.new(src)
|
26
|
-
@
|
27
|
-
@space_holder_res = []
|
28
|
-
space_holders.each do |i|
|
29
|
-
if i.is_a?(Regexp)
|
30
|
-
@space_holder_res << i
|
31
|
-
else
|
32
|
-
@space_holders << i.to_sym
|
33
|
-
end
|
34
|
-
end
|
26
|
+
@scanner.scan(/\s*<\?.*?\?>\s*/)
|
35
27
|
end
|
36
28
|
|
37
|
-
def parse
|
38
|
-
@scanner.scan(/\s+/) unless hold_space
|
29
|
+
def parse
|
39
30
|
if @scanner.scan(RE::EMPTY_ELEMENT)
|
40
|
-
parse_empty_element
|
31
|
+
parse_empty_element
|
41
32
|
elsif @scanner.scan(RE::START_TAG)
|
42
|
-
parse_start_tag
|
33
|
+
parse_start_tag
|
43
34
|
elsif @scanner.scan(RE::STRING)
|
44
|
-
parse_string
|
35
|
+
parse_string
|
45
36
|
else
|
46
37
|
nil
|
47
38
|
end
|
@@ -55,43 +46,26 @@ module EimXML
|
|
55
46
|
end
|
56
47
|
protected :parse_tag
|
57
48
|
|
58
|
-
def
|
59
|
-
|
60
|
-
s = ename.to_s
|
61
|
-
@space_holder_res.each do |re|
|
62
|
-
return true if re=~s
|
63
|
-
end
|
64
|
-
false
|
65
|
-
end
|
66
|
-
|
67
|
-
def parse_empty_element(hold_space)
|
68
|
-
e = parse_tag
|
69
|
-
hold_space = space_holder?(e.name) unless hold_space
|
70
|
-
e.hold_space if hold_space
|
71
|
-
e
|
49
|
+
def parse_empty_element
|
50
|
+
parse_tag
|
72
51
|
end
|
73
52
|
protected :parse_empty_element
|
74
53
|
|
75
|
-
def parse_start_tag
|
54
|
+
def parse_start_tag
|
76
55
|
e = parse_tag
|
77
|
-
hold_space = space_holder?(e.name) unless hold_space
|
78
56
|
|
79
|
-
e.hold_space if hold_space
|
80
|
-
@scanner.scan(/\s*/) unless hold_space
|
81
57
|
until @scanner.scan(RE::END_TAG)
|
82
|
-
c = parse
|
58
|
+
c = parse
|
83
59
|
raise ParseError.new("Syntax error.") unless c
|
84
60
|
e << c
|
85
|
-
@scanner.scan(/\s*/) unless hold_space
|
86
61
|
end
|
87
62
|
raise ParseError.new("End tag mismatched.") unless @scanner[1].to_sym==e.name
|
88
63
|
e
|
89
64
|
end
|
90
65
|
protected :parse_start_tag
|
91
66
|
|
92
|
-
def parse_string
|
67
|
+
def parse_string
|
93
68
|
s = @scanner[0]
|
94
|
-
s = s.strip unless hold_space
|
95
69
|
s = s.gsub(/&(amp|quot|apos|lt|gt);/) do
|
96
70
|
case $1
|
97
71
|
when "amp"
|
@@ -104,8 +78,6 @@ module EimXML
|
|
104
78
|
"<"
|
105
79
|
when "gt"
|
106
80
|
">"
|
107
|
-
else
|
108
|
-
raise "must not happen"
|
109
81
|
end
|
110
82
|
end
|
111
83
|
PCString.new(s)
|
data/lib/eim_xml/xhtml.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
require "eim_xml"
|
2
|
+
require "eim_xml/formatter"
|
2
3
|
|
3
4
|
module EimXML::XHTML
|
4
5
|
module DocType
|
5
6
|
XHTML_MATHML = %[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" "http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd">]
|
6
7
|
end
|
7
8
|
|
8
|
-
class DSL < EimXML::BaseDSL
|
9
|
-
end
|
10
|
-
|
11
|
-
class OpenDSL < EimXML::OpenDSL
|
12
|
-
end
|
13
|
-
|
14
9
|
class Base_ < EimXML::Element
|
15
10
|
end
|
16
11
|
|
@@ -20,106 +15,139 @@ module EimXML::XHTML
|
|
20
15
|
XHTML = "http://www.w3.org/1999/xhtml"
|
21
16
|
end
|
22
17
|
|
23
|
-
def initialize(attributes=
|
18
|
+
def initialize(attributes={})
|
24
19
|
super(:html, attributes)
|
25
20
|
end
|
26
21
|
|
27
|
-
def
|
28
|
-
|
29
|
-
super
|
22
|
+
def write_to(out="")
|
23
|
+
out << @prefix << "\n" if @prefix
|
24
|
+
super
|
30
25
|
end
|
31
26
|
end
|
32
27
|
|
33
28
|
class Simple_ < Base_
|
34
|
-
def initialize(attributes=
|
29
|
+
def initialize(attributes={})
|
35
30
|
super(self.class.name[/.*::(.*)/, 1].downcase.to_sym, attributes)
|
36
31
|
end
|
37
32
|
end
|
38
33
|
|
34
|
+
class PreserveSpace_ < Base_
|
35
|
+
def initialize(name={}, attributes={})
|
36
|
+
if name.is_a?(Hash)
|
37
|
+
super(self.class.name[/.*::(.*)/, 1].downcase.to_sym, name)
|
38
|
+
else
|
39
|
+
super(name, attributes)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
39
44
|
class HEAD < Simple_; end
|
40
45
|
class META < Simple_; end
|
41
46
|
class LINK < Simple_; end
|
42
|
-
class
|
43
|
-
class
|
47
|
+
class IMG < Simple_; end
|
48
|
+
class STYLE < PreserveSpace_; end
|
49
|
+
class SCRIPT < PreserveSpace_; end
|
44
50
|
class TITLE < Simple_; end
|
45
51
|
class BODY < Simple_; end
|
46
|
-
class PRE <
|
47
|
-
|
52
|
+
class PRE < PreserveSpace_; end
|
53
|
+
class FORM < Simple_
|
54
|
+
def initialize(attributes={})
|
55
|
+
if attributes
|
56
|
+
if s = attributes.delete(:session)
|
57
|
+
name = attributes.delete(:session_name) || "token"
|
58
|
+
require "digest/sha1"
|
59
|
+
token = s[name] ||= Digest::SHA1.hexdigest("#{$$}#{Time.now}#{rand}")
|
60
|
+
end
|
61
|
+
end
|
48
62
|
super
|
49
|
-
|
63
|
+
add(HIDDEN.new(:name=>name, :value=>token)) if token
|
50
64
|
end
|
51
65
|
end
|
52
|
-
class
|
53
|
-
class
|
54
|
-
class
|
55
|
-
class
|
56
|
-
class
|
57
|
-
class
|
58
|
-
class
|
59
|
-
class
|
60
|
-
class
|
61
|
-
class
|
62
|
-
class STRONG < Simple_; end
|
66
|
+
class H1 < PreserveSpace_; end
|
67
|
+
class H2 < PreserveSpace_; end
|
68
|
+
class H3 < PreserveSpace_; end
|
69
|
+
class H4 < PreserveSpace_; end
|
70
|
+
class H5 < PreserveSpace_; end
|
71
|
+
class H6 < PreserveSpace_; end
|
72
|
+
class P < PreserveSpace_; end
|
73
|
+
class A < PreserveSpace_; end
|
74
|
+
class EM < PreserveSpace_; end
|
75
|
+
class STRONG < PreserveSpace_; end
|
63
76
|
class DIV < Simple_; end
|
77
|
+
class SPAN < PreserveSpace_; end
|
64
78
|
class UL < Simple_; end
|
65
79
|
class OL < Simple_; end
|
66
|
-
class LI <
|
80
|
+
class LI < PreserveSpace_; end
|
67
81
|
class DL < Simple_; end
|
68
|
-
class DT <
|
69
|
-
class DD <
|
82
|
+
class DT < PreserveSpace_; end
|
83
|
+
class DD < PreserveSpace_; end
|
70
84
|
class TABLE < Simple_; end
|
71
|
-
class CAPTION <
|
85
|
+
class CAPTION < PreserveSpace_; end
|
72
86
|
class TR < Simple_; end
|
73
|
-
class TH <
|
74
|
-
class TD <
|
87
|
+
class TH < PreserveSpace_; end
|
88
|
+
class TD < PreserveSpace_; end
|
89
|
+
class BR < Simple_; end
|
90
|
+
class HR < Simple_; end
|
91
|
+
class SELECT < Simple_; end
|
92
|
+
class OPTION < Simple_; end
|
93
|
+
|
75
94
|
|
76
95
|
module Hn
|
77
|
-
def self.new(level, attr=
|
96
|
+
def self.new(level, attr={}, &proc)
|
78
97
|
raise ArgumentError unless 1<=level && level<=6
|
79
98
|
klass = EimXML::XHTML.const_get("H#{level}")
|
80
99
|
klass.new(attr, &proc)
|
81
100
|
end
|
82
101
|
end
|
83
102
|
|
84
|
-
class TEXTAREA <
|
85
|
-
|
86
|
-
|
103
|
+
class TEXTAREA < PreserveSpace_; end
|
104
|
+
|
105
|
+
class INPUT < Base_
|
106
|
+
def initialize(opt={})
|
107
|
+
super(:input, opt)
|
87
108
|
end
|
88
109
|
end
|
89
110
|
|
90
|
-
class
|
91
|
-
def initialize(
|
92
|
-
|
93
|
-
attr[:name]=name if name
|
94
|
-
attr[:value]=value if value
|
95
|
-
super(:input, attr.merge(opt))
|
111
|
+
class BUTTON < PreserveSpace_
|
112
|
+
def initialize(opt={})
|
113
|
+
super(:button, opt)
|
96
114
|
end
|
97
115
|
end
|
98
116
|
|
99
|
-
class
|
100
|
-
def initialize(
|
101
|
-
super(:
|
117
|
+
class SUBMIT < BUTTON
|
118
|
+
def initialize(opt={})
|
119
|
+
super(opt.merge(:type=>:submit))
|
102
120
|
end
|
103
121
|
end
|
104
122
|
|
105
|
-
class
|
123
|
+
class HIDDEN < INPUT
|
106
124
|
def initialize(opt={})
|
107
|
-
opt
|
108
|
-
super(:submit, opt.delete(:name), opt.delete(:value), opt)
|
125
|
+
super(opt.merge(:type=>:hidden))
|
109
126
|
end
|
110
127
|
end
|
111
128
|
|
112
129
|
class TEXT < INPUT
|
113
|
-
def initialize(
|
114
|
-
super(:text
|
130
|
+
def initialize(opt={})
|
131
|
+
super(opt.merge(:type=>:text))
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class PASSWORD < INPUT
|
136
|
+
def initialize(opt={})
|
137
|
+
super(opt.merge(:type=>:password))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class FILE < INPUT
|
142
|
+
def initialize(opt={})
|
143
|
+
super(opt.merge(:type=>:file))
|
115
144
|
end
|
116
145
|
end
|
117
146
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
OpenDSL.register v
|
147
|
+
PRESERVE_SPACES = [PreserveSpace_]
|
148
|
+
class Formatter < EimXML::Formatter
|
149
|
+
def self.write(element, opt={})
|
150
|
+
EimXML::Formatter.write(element, opt.merge(:preservers=>PRESERVE_SPACES))
|
123
151
|
end
|
124
152
|
end
|
125
153
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "eim_xml/dsl"
|
2
|
+
require "eim_xml/xhtml"
|
3
|
+
|
4
|
+
module EimXML::XHTML
|
5
|
+
class DSL < EimXML::BaseDSL
|
6
|
+
end
|
7
|
+
|
8
|
+
class OpenDSL < EimXML::OpenDSL
|
9
|
+
end
|
10
|
+
|
11
|
+
constants.each do |c|
|
12
|
+
v = const_get(c)
|
13
|
+
if v.is_a?(Class) && /_$/ !~ v.name
|
14
|
+
DSL.register v
|
15
|
+
OpenDSL.register v
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|