docomo_css 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -13,6 +13,16 @@ Instead, every element must use its own style attribute, for example
13
13
 
14
14
  docomo_css works around this by inlining all CSS automatically for you.
15
15
 
16
+ Also, docomo does not support styling some elements such as h1, but does if you nest the contents in a span. This library automatically handles transforming
17
+
18
+ <h1>foo</h1>
19
+
20
+ to
21
+
22
+ <h1><span>foo</span></h1>
23
+
24
+ so you don't need to change any styling.
25
+
16
26
  == Install
17
27
 
18
28
  sudo gem install docomo_css
@@ -0,0 +1,118 @@
1
+ require 'docomo_css/stylesheet'
2
+ require 'nokogiri'
3
+ require 'tiny_css'
4
+
5
+ module DocomoCss
6
+ class Filter
7
+ def after(controller)
8
+ return unless controller.response.content_type =~ /application\/xhtml\+xml/
9
+ return unless controller.request.user_agent =~ /docomo/i
10
+ return if docomo_2_0_browser?(controller)
11
+ body = escape_numeric_character_reference controller.response.body
12
+ body = embed_css remove_xml_declare(body)
13
+ controller.response.body = unescape_numeric_character_reference body
14
+ end
15
+
16
+ def embed_css(body)
17
+ doc = Nokogiri::HTML(body)
18
+
19
+ stylesheet_link_node(doc).each do |linknode|
20
+ stylesheet = DocomoCss::Stylesheet.new(linknode['href'])
21
+ next unless stylesheet.valid?
22
+ css = TinyCss.new.read(stylesheet.path)
23
+ embed_pseudo_style(doc, extract_pseudo_style(css))
24
+ embed_style(doc, css)
25
+ end
26
+ xml_declare(doc) + doc.to_xhtml(:indent => 0, :encoding => doc.encoding)
27
+ end
28
+
29
+ def xml_declare(doc)
30
+ <<-XML
31
+ <?xml version="1.0" encoding="#{doc.encoding}"?>
32
+ XML
33
+ end
34
+
35
+ def remove_xml_declare(body)
36
+ body.gsub(%r'<\?xml[^\?]*?\?>', '')
37
+ end
38
+
39
+ def embed_style(doc, css)
40
+ css.style.each do |selector, style|
41
+ stringified_style = stringify_style(style)
42
+ doc.css(selector).each do |element|
43
+ # inject support for unsupported styles
44
+ if /h\d/ =~ element.name
45
+ # font-size needs to be changed in span
46
+ element.children.wrap('<span>')
47
+ element.children.first['style'] = merge_style element['style'], stringified_style
48
+
49
+ # background-color should be changed in div to give 100% width
50
+ div = Nokogiri.make("<div>")
51
+ div['style'] = merge_style element['style'], stringified_style
52
+ element.replace(div)
53
+ div.add_child(element)
54
+ else
55
+ element['style'] = merge_style element['style'], stringified_style
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def stringify_style(style)
62
+ style.map { |k, v| "#{ k }:#{ v }" }.join ';'
63
+ end
64
+
65
+ def merge_style(style, other_style)
66
+ return other_style if style == nil
67
+ style += ";" unless style =~ /;\Z/
68
+ style + other_style
69
+ end
70
+
71
+ def escape_numeric_character_reference(text)
72
+ text.gsub /&#(\d+|x[\da-fA-F]+);/, 'HTMLCSSINLINERESCAPE\1::::::::'
73
+ end
74
+
75
+ def unescape_numeric_character_reference(text)
76
+ text.gsub /HTMLCSSINLINERESCAPE(\d+|x[\da-fA-F]+)::::::::/, '&#\1;'
77
+ end
78
+
79
+ def stylesheet_link_node(document)
80
+ document.xpath '//link[@rel="stylesheet"]'
81
+ end
82
+
83
+ def css_path(stylesheet)
84
+ stylesheet.path
85
+ end
86
+
87
+ def extract_pseudo_style(css)
88
+ pseudo_style = TinyCss.new
89
+ pseudo_selectors(css).each do |v|
90
+ pseudo_style.style[v] = css.style[v]
91
+ css.style.delete(v)
92
+ end
93
+ pseudo_style
94
+ end
95
+
96
+ def embed_pseudo_style(doc, pseudo_style)
97
+ return if pseudo_style.style.keys.empty?
98
+
99
+ raise unless doc.at('/html/head')
100
+ doc.at('/html/head').add_child <<-STYLE
101
+ <style type="text/css">
102
+ #{pseudo_style.write_string}
103
+ </style>
104
+ STYLE
105
+ doc
106
+ end
107
+
108
+ def pseudo_selectors(css)
109
+ css.style.keys.grep(/a:(link|focus|visited)/)
110
+ end
111
+
112
+ private
113
+
114
+ def docomo_2_0_browser?(controller)
115
+ controller.request.user_agent =~ /DoCoMo\/2\.0 [^(]*\(c(\d+);/ && $1.to_i >= 500
116
+ end
117
+ end
118
+ end
@@ -1,5 +1,11 @@
1
+ require 'docomo_css/filter'
2
+
1
3
  class DocomoCss::Railtie < Rails::Railtie
2
4
  initializer "docomo_css.extend.action_controller" do
3
- ActionController::Base.send :include, DocomoCss
5
+ ActionController::Base.class_eval do
6
+ def self.docomo_filter
7
+ after_filter DocomoCss::Filter.new
8
+ end
9
+ end
4
10
  end
5
11
  end
@@ -1,3 +1,3 @@
1
1
  class DocomoCss
2
- Version = "0.3.0"
2
+ Version = "0.4.0"
3
3
  end
data/lib/docomo_css.rb CHANGED
@@ -1,117 +1 @@
1
- require 'nokogiri'
2
- require 'tiny_css'
3
- require 'docomo_css/stylesheet'
4
1
  require 'docomo_css/railtie'
5
-
6
- module DocomoCss
7
-
8
- def self.included(base)
9
- base.extend ClassMethods
10
- end
11
-
12
- module ClassMethods
13
- def docomo_filter
14
- after_filter DocomoCssFilter.new
15
- end
16
- end
17
-
18
- class DocomoCssFilter
19
- def after(controller)
20
- return unless controller.response.content_type =~ /application\/xhtml\+xml/
21
- return unless controller.request.user_agent =~ /docomo/i
22
- return if docomo_2_0_browser?(controller)
23
- body = escape_numeric_character_reference controller.response.body
24
- body = embed_css remove_xml_declare(body)
25
- controller.response.body = unescape_numeric_character_reference body
26
- end
27
-
28
- def embed_css(body)
29
- doc = Nokogiri::HTML(body)
30
-
31
- stylesheet_link_node(doc).each do |linknode|
32
- stylesheet = DocomoCss::Stylesheet.new(linknode['href'])
33
- next unless stylesheet.valid?
34
- css = TinyCss.new.read(stylesheet.path)
35
- embed_pseudo_style(doc, extract_pseudo_style(css))
36
- embed_style(doc, css)
37
- end
38
- xml_declare(doc) + doc.to_xhtml(:indent => 0, :encoding => doc.encoding)
39
- end
40
-
41
- def xml_declare(doc)
42
- <<-XML
43
- <?xml version="1.0" encoding="#{doc.encoding}"?>
44
- XML
45
- end
46
-
47
- def remove_xml_declare(body)
48
- body.gsub(%r'<\?xml[^\?]*?\?>', '')
49
- end
50
-
51
- def embed_style(doc, css)
52
- css.style.each do |selector, style|
53
- stringified_style = stringify_style(style)
54
- doc.css(selector).each do |element|
55
- element['style'] = merge_style element['style'], stringified_style
56
- end
57
- end
58
- end
59
-
60
- def stringify_style(style)
61
- style.map { |k, v| "#{ k }:#{ v }" }.join ';'
62
- end
63
-
64
- def merge_style(style, other_style)
65
- return other_style if style == nil
66
- style += ";" unless style =~ /;\Z/
67
- style + other_style
68
- end
69
-
70
- def escape_numeric_character_reference(text)
71
- text.gsub /&#(\d+|x[\da-fA-F]+);/, 'HTMLCSSINLINERESCAPE\1::::::::'
72
- end
73
-
74
- def unescape_numeric_character_reference(text)
75
- text.gsub /HTMLCSSINLINERESCAPE(\d+|x[\da-fA-F]+)::::::::/, '&#\1;'
76
- end
77
-
78
- def stylesheet_link_node(document)
79
- document.xpath '//link[@rel="stylesheet"]'
80
- end
81
-
82
- def css_path(stylesheet)
83
- stylesheet.path
84
- end
85
-
86
- def extract_pseudo_style(css)
87
- pseudo_style = TinyCss.new
88
- pseudo_selectors(css).each do |v|
89
- pseudo_style.style[v] = css.style[v]
90
- css.style.delete(v)
91
- end
92
- pseudo_style
93
- end
94
-
95
- def embed_pseudo_style(doc, pseudo_style)
96
- return if pseudo_style.style.keys.empty?
97
-
98
- raise unless doc.at('/html/head')
99
- doc.at('/html/head').add_child <<-STYLE
100
- <style type="text/css">
101
- #{pseudo_style.write_string}
102
- </style>
103
- STYLE
104
- doc
105
- end
106
-
107
- def pseudo_selectors(css)
108
- css.style.keys.grep(/a:(link|focus|visited)/)
109
- end
110
-
111
- private
112
-
113
- def docomo_2_0_browser?(controller)
114
- controller.request.user_agent =~ /DoCoMo\/2\.0 [^(]*\(c(\d+);/ && $1.to_i >= 500
115
- end
116
- end
117
- end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docomo_css
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - milk1000cc
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-11-24 00:00:00 +09:00
19
+ date: 2010-12-16 00:00:00 +09:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -47,6 +47,22 @@ dependencies:
47
47
  version: "0"
48
48
  type: :runtime
49
49
  version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rails
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 7
59
+ segments:
60
+ - 3
61
+ - 0
62
+ - 0
63
+ version: 3.0.0
64
+ type: :runtime
65
+ version_requirements: *id003
50
66
  description: Inlines CSS so that you can use external CSS with docomo handsets.
51
67
  email: info@milk1000.cc
52
68
  executables: []
@@ -58,6 +74,7 @@ extra_rdoc_files: []
58
74
  files:
59
75
  - MIT-LICENSE
60
76
  - README.rdoc
77
+ - lib/docomo_css/filter.rb
61
78
  - lib/docomo_css/railtie.rb
62
79
  - lib/docomo_css/stylesheet.rb
63
80
  - lib/docomo_css/version.rb