eimxml 0.0.2 → 0.0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"
@@ -0,0 +1,7 @@
1
+ class EimXML::Formatter
2
+ class ElementWrapper
3
+ def each(option, &proc)
4
+ contents(option).each(&proc)
5
+ end
6
+ end
7
+ end
@@ -16,32 +16,23 @@ module EimXML
16
16
  module RE
17
17
  EMPTY_ELEMENT = /<([^>]*?)\/>/
18
18
  START_TAG = /<([^>]*?([^\/>]\s*))>/
19
- END_TAG = /<\/(\S+)\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, *space_holders)
24
+ def initialize(src)
25
25
  @scanner = StringScanner.new(src)
26
- @space_holders = []
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(hold_space = false)
38
- @scanner.scan(/\s+/) unless hold_space
29
+ def parse
39
30
  if @scanner.scan(RE::EMPTY_ELEMENT)
40
- parse_empty_element(hold_space)
31
+ parse_empty_element
41
32
  elsif @scanner.scan(RE::START_TAG)
42
- parse_start_tag(hold_space)
33
+ parse_start_tag
43
34
  elsif @scanner.scan(RE::STRING)
44
- parse_string(hold_space)
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 space_holder?(ename)
59
- return true if @space_holders.include?(ename)
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(hold_space)
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(hold_space)
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(hold_space)
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)
@@ -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=nil)
18
+ def initialize(attributes={})
24
19
  super(:html, attributes)
25
20
  end
26
21
 
27
- def to_xml(s="")
28
- s << @prefix << "\n" if @prefix
29
- super(s)
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=nil)
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 STYLE < Simple_; end
43
- class SCRIPT < Simple_; end
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 < Simple_
47
- def initialize(attributes=nil)
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
- hold_space
63
+ add(HIDDEN.new(:name=>name, :value=>token)) if token
50
64
  end
51
65
  end
52
- class FORM < Simple_; end
53
- class H1 < Simple_; end
54
- class H2 < Simple_; end
55
- class H3 < Simple_; end
56
- class H4 < Simple_; end
57
- class H5 < Simple_; end
58
- class H6 < Simple_; end
59
- class P < Simple_; end
60
- class A < Simple_; end
61
- class EM < Simple_; end
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 < Simple_; end
80
+ class LI < PreserveSpace_; end
67
81
  class DL < Simple_; end
68
- class DT < Simple_; end
69
- class DD < Simple_; end
82
+ class DT < PreserveSpace_; end
83
+ class DD < PreserveSpace_; end
70
84
  class TABLE < Simple_; end
71
- class CAPTION < Simple_; end
85
+ class CAPTION < PreserveSpace_; end
72
86
  class TR < Simple_; end
73
- class TH < Simple_; end
74
- class TD < Simple_; end
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=nil, &proc)
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 < Base_
85
- def initialize(name, opt={})
86
- super(:textarea, {:name=>name}.merge(opt))
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 INPUT < Base_
91
- def initialize(type, name, value, opt={})
92
- attr = {:type=>type}
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 HIDDEN < INPUT
100
- def initialize(name, value, opt={})
101
- super(:hidden, name, value, opt)
117
+ class SUBMIT < BUTTON
118
+ def initialize(opt={})
119
+ super(opt.merge(:type=>:submit))
102
120
  end
103
121
  end
104
122
 
105
- class SUBMIT < INPUT
123
+ class HIDDEN < INPUT
106
124
  def initialize(opt={})
107
- opt = opt.dup
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(name, value=nil, opt={})
114
- super(:text, name, value, opt)
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
- constants.each do |c|
119
- v = const_get(c)
120
- if v.is_a?(Class) && /_$/ !~ v.name
121
- DSL.register v
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