nokogiri-styles 0.1.0

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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nokogiri-stykes.gemspec
4
+ gemspec
@@ -0,0 +1,25 @@
1
+ Copyright © 2012, Readmore
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ * Neither the name of Readmore nor the
13
+ names of its contributors may be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL READMORE BE LIABLE FOR ANY
20
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,55 @@
1
+ # nokogiri-styles
2
+
3
+ NokgiriStyles lets you decompose inline CSS styling (the style attribute) in
4
+ HTML elements so you don’t have to bother with regexes and such.
5
+
6
+ ## Usage
7
+
8
+ require 'nokogiri'
9
+ require 'nokogiri-styles'
10
+
11
+ # ...
12
+
13
+ # Get styles
14
+ node['style'] # => 'width: 400px; color: blue'
15
+ node.styles['width'] # => '400px'
16
+ node.styles['color'] # => 'blue'
17
+
18
+ # Update styles
19
+ style = node.styles
20
+ style['width'] = '500px'
21
+ style['height'] = '300px'
22
+ style['color'] = nil
23
+ node.styles = style
24
+ node['style'] # => 'width: 500xp; height: 300px'
25
+
26
+ # Modify classes
27
+ node['class'] # => 'foo bar'
28
+ node.classes # => ['foo', 'bar']
29
+ node.classes = ['foo']
30
+ node['class'] # => 'foo'
31
+
32
+ Note that the `style` attribute is only updated when assigning `.styles`,
33
+ simply doing `node.styles['color'] = 'red'` does not work. Patches welcome.
34
+
35
+ ## Installation
36
+
37
+ Add this line to your application's Gemfile:
38
+
39
+ gem 'nokogiri-styles'
40
+
41
+ And then execute:
42
+
43
+ $ bundle
44
+
45
+ Or install it yourself as:
46
+
47
+ $ gem install nokogiri-styles
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork it
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << 'lib' << 'test'
9
+ test.pattern = 'test/{functional,unit}/test_*.rb'
10
+ end
@@ -0,0 +1,8 @@
1
+ require 'nokogiri-styles/version'
2
+ require 'nokogiri-styles/node_styles'
3
+
4
+ module Nokogiri::XML
5
+ class Node
6
+ include NokogiriStyles::NodeStyles
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ require 'nokogiri-styles/propset'
2
+
3
+ module NokogiriStyles
4
+ module NodeStyles
5
+ def styles
6
+ return NokogiriStyles::Propset.new(self['style'])
7
+ end
8
+
9
+ def styles=(value)
10
+ self['style'] = value.to_s
11
+ end
12
+
13
+ def classes
14
+ return self['class'].split(' ')
15
+ end
16
+
17
+ def classes=(value)
18
+ self['class'] = value.join(' ')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ module NokogiriStyles
2
+ class Propset
3
+ def initialize(style_string)
4
+ @properties = parse_properties(style_string)
5
+ @mapping = make_mapping(@properties)
6
+ end
7
+
8
+ def to_s
9
+ @properties.
10
+ map { |p| [p[:key], p[:value]].join(': ') }.
11
+ join('; ')
12
+ end
13
+
14
+ def [](key)
15
+ property = @mapping[key]
16
+ property.nil? ? nil : property[:value]
17
+ end
18
+
19
+ def []=(key, val)
20
+ return self.delete(key) if val.nil?
21
+ property = @mapping[key]
22
+ if property.nil?
23
+ property = {:key => key}
24
+ @properties << property
25
+ @mapping[key] = property
26
+ end
27
+ @mapping[key][:value] = val
28
+ end
29
+
30
+ def delete(key)
31
+ @mapping.delete(key)
32
+ @properties.reject! { |p| p[:key] == key }
33
+ end
34
+
35
+ private
36
+ def parse_property(property_string)
37
+ parts = property_string.split(':', 2)
38
+ return nil if parts.nil?
39
+ return nil if parts.length != 2
40
+ return nil if parts.any? { |s| s.nil? }
41
+ {:key => parts[0].strip, :value => parts[1].strip}
42
+ end
43
+
44
+ def parse_properties(style_string)
45
+ style_string.
46
+ split(';').
47
+ reject { |s| s.strip.empty? }.
48
+ map { |s| parse_property(s) }.
49
+ reject { |s| s.nil? }
50
+ end
51
+
52
+ def make_mapping(properties)
53
+ properties.reduce({}) do |accum, property|
54
+ accum[property[:key]] = property
55
+ accum
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module NokogiriStyles
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,53 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nokogiri-styles/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Sijmen Mulder']
6
+ gem.email = ['sijmen@readmo.re']
7
+ gem.summary = %q{Basic inline CSS reading and editing for Nokogiri}
8
+ gem.homepage = ''
9
+
10
+ gem.description = <<-EOF
11
+ NokgiriStyles lets you decompose inline CSS styling (the style attribute) in
12
+ HTML elements so you don’t have to bother with regexes and such.
13
+
14
+ Usage:
15
+
16
+ require 'nokogiri'
17
+ require 'nokogiri-styles'
18
+
19
+ # ...
20
+
21
+ # Get styles
22
+ node['style'] # => 'width: 400px; color: blue'
23
+ node.styles['width'] # => '400px'
24
+ node.styles['color'] # => 'blue'
25
+
26
+ # Update styles
27
+ style = node.styles
28
+ style['width'] = '500px'
29
+ style['height'] = '300px'
30
+ style['color'] = nil
31
+ node.styles = style
32
+ node['style'] # => 'width: 500xp; height: 300px'
33
+
34
+ # Modify classes
35
+ node['class'] # => 'foo bar'
36
+ node.classes # => ['foo', 'bar']
37
+ node.classes = ['foo']
38
+ node['class'] # => 'foo'
39
+
40
+ Note that the `style` attribute is only updated when assigning `.styles`,
41
+ simply doing `node.styles['color'] = 'red'` does not work. Patches welcome.
42
+ EOF
43
+
44
+ gem.files = `git ls-files`.split($\)
45
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
46
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
47
+ gem.name = 'nokogiri-styles'
48
+ gem.require_paths = ['lib']
49
+ gem.version = NokogiriStyles::VERSION
50
+
51
+ gem.add_dependency('nokogiri')
52
+ gem.add_development_dependency('test-unit', '2.4.8')
53
+ end
@@ -0,0 +1,36 @@
1
+ require 'test/unit'
2
+ require 'nokogiri-styles/node_styles'
3
+ require 'nokogiri-styles/propset'
4
+
5
+ class MockNode < Hash
6
+ include NokogiriStyles::NodeStyles
7
+ end
8
+
9
+ class MockStyles < String
10
+ end
11
+
12
+ class TestNodeStyles < Test::Unit::TestCase
13
+ def test_classes
14
+ node = MockNode.new
15
+ node['class'] = 'foo bar'
16
+ assert_equal(%w(foo bar), node.classes)
17
+ end
18
+
19
+ def test_set_classes
20
+ node = MockNode.new
21
+ node.classes = %w(foo bar)
22
+ assert_equal('foo bar', node['class'])
23
+ end
24
+
25
+ def test_styles
26
+ node = MockNode.new
27
+ node['style'] = 'width: 2px; height: 4px'
28
+ assert_equal(node.styles.class, NokogiriStyles::Propset)
29
+ end
30
+
31
+ def test_set_styles
32
+ node = MockNode.new
33
+ node.styles = MockStyles.new('width: 2px; height: 4px')
34
+ assert_equal('width: 2px; height: 4px', node['style'])
35
+ end
36
+ end
@@ -0,0 +1,51 @@
1
+ require 'test/unit'
2
+ require 'nokogiri-styles/propset'
3
+
4
+ include NokogiriStyles
5
+
6
+ class TestPropset < Test::Unit::TestCase
7
+ def test_getters
8
+ propset = Propset.new('width: 2px; height: 4px; ')
9
+ assert_equal('2px', propset['width'])
10
+ assert_equal('4px', propset['height'])
11
+ end
12
+
13
+ def test_delete
14
+ propset = Propset.new('width: 2px; height: 4px; height: 3px')
15
+ propset.delete('height')
16
+ propset['width'] = nil
17
+ assert_equal(nil, propset['height'])
18
+ assert_equal(nil, propset['width'])
19
+ end
20
+
21
+ def test_setters
22
+ propset = Propset.new('width: 2px; height: 4px')
23
+ propset['width'] = nil
24
+ propset['height'] = '5px'
25
+ propset['top'] = '1px'
26
+ assert_equal(nil, propset['width'])
27
+ assert_equal('5px', propset['height'])
28
+ assert_equal('1px', propset['top'])
29
+ end
30
+
31
+ def test_duplicate_property
32
+ propset = Propset.new('width: 2px; height: 4px; width: 3px')
33
+ assert_equal('4px', propset['height'])
34
+ assert_equal('3px', propset['width'])
35
+ propset['width'] = '2px'
36
+ assert_equal('2px', propset['width'])
37
+ end
38
+
39
+ def test_to_s
40
+ propset = Propset.new('width: 2px; height: 4px; width: 3px; ')
41
+ propset['height'] = nil
42
+ propset['top'] = '1px'
43
+ propset['width'] = '5px'
44
+ assert_equal('width: 2px; width: 5px; top: 1px', propset.to_s)
45
+ end
46
+
47
+ def test_invalid_property
48
+ propset = Propset.new('width: 2px; height 4px')
49
+ assert_equal('2px', propset['width'])
50
+ end
51
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nokogiri-styles
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sijmen Mulder
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: test-unit
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '='
36
+ - !ruby/object:Gem::Version
37
+ version: 2.4.8
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 2.4.8
46
+ description: ! " NokgiriStyles lets you decompose inline CSS styling (the style
47
+ attribute) in\n HTML elements so you don’t have to bother with regexes and such.\n\n
48
+ \ Usage:\n \n require 'nokogiri'\n require 'nokogiri-styles'\n\n
49
+ \ # ...\n \n # Get styles\n node['style'] # => 'width:
50
+ 400px; color: blue'\n node.styles['width'] # => '400px'\n node.styles['color']
51
+ \ # => 'blue'\n \n # Update styles\n style = node.styles\n style['width']
52
+ \ = '500px'\n style['height'] = '300px'\n style['color'] = nil\n
53
+ \ node.styles = style\n node['style'] # => 'width: 500xp; height:
54
+ 300px'\n\n # Modify classes\n node['class'] # => 'foo bar'\n
55
+ \ node.classes # => ['foo', 'bar']\n node.classes = ['foo']\n
56
+ \ node['class'] # => 'foo'\n\n Note that the `style` attribute
57
+ is only updated when assigning `.styles`,\n simply doing `node.styles['color']
58
+ = 'red'` does not work. Patches welcome.\n"
59
+ email:
60
+ - sijmen@readmo.re
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - LICENSE.md
68
+ - README.md
69
+ - Rakefile
70
+ - lib/nokogiri-styles.rb
71
+ - lib/nokogiri-styles/node_styles.rb
72
+ - lib/nokogiri-styles/propset.rb
73
+ - lib/nokogiri-styles/version.rb
74
+ - nokogiri-styles.gemspec
75
+ - test/unit/test_node_styles.rb
76
+ - test/unit/test_propset.rb
77
+ homepage: ''
78
+ licenses: []
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.24
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Basic inline CSS reading and editing for Nokogiri
101
+ test_files:
102
+ - test/unit/test_node_styles.rb
103
+ - test/unit/test_propset.rb