saxophone 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 57c5242aea2b5daec2f7129d6b12fe56e28e07a8
4
- data.tar.gz: c5f4823813e45c56693feeafbb808253367cf533
2
+ SHA256:
3
+ metadata.gz: 99eb0392977bf92c77b61dd1d79feddde93e8d91b5eea7a76fb03892354ee3b6
4
+ data.tar.gz: 0c2c3c808f9b5c70258238835ee9240b4745876a5948c9fce7879372d4a4077a
5
5
  SHA512:
6
- metadata.gz: 18a39e8330f39c5da059bfcb39f147084d8d707fd6375a9561d4711ce3269dc16a98f860a717d45b181cbd79c555edfc329e7ff80818c0f7e41a65f29a0ce9e6
7
- data.tar.gz: 6d4b5006f62bacf0d51e6300ba146083301fcb3922dd960282216272622a130ce7cd6fac88481ad5149ceedf4f0e69c5538decde24cae5fa16ae7944594a3c7c
6
+ metadata.gz: c40ff56245b84fc4592a949726455feb15c25fe914e93234203976409e8a6b9d47dc6d7b636f29644992e553bb4f88847594890abee24ce88bdeb7de9bf0ca7a
7
+ data.tar.gz: f2d65e68ba0dbf5bb91f97a644d1a4a4a74860186f365dc5f1aa3deb443d8260ec42c7a1fb2f5207f3f24d0ac12a53877f9e76f44d177ca3c3b6f3cfbece8bf4
@@ -0,0 +1,25 @@
1
+ name: build
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
7
+ branches:
8
+ - master
9
+ jobs:
10
+ build:
11
+ if: "!contains(github.event.head_commit.message, '[skip ci]')"
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ ruby: ['2.5', '2.6', '2.7', '3.0']
16
+ handler: ['nokogiri', 'ox', 'oga']
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ bundler-cache: true
23
+ - run: bundle exec rake
24
+ env:
25
+ HANDLER: ${{ matrix.handler }}
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.1
1
+ 3.0.1
data/Gemfile CHANGED
@@ -8,12 +8,12 @@ group :development, :test do
8
8
  gem 'simplecov', require: false, platforms: [:mri]
9
9
  gem 'coveralls', require: false, platforms: [:mri]
10
10
 
11
- gem 'activerecord', '~> 5.0.0'
11
+ gem 'activerecord', '~> 6.0'
12
12
  gem 'nokogiri', '>= 1.8.2'
13
- gem 'ox', '>= 2.1.2', platforms: [:mri, :rbx]
14
- gem 'oga', '>= 0.3.4'
13
+ gem 'ox', '>= 2.10.0'
14
+ gem 'oga', '>= 2.15'
15
15
  end
16
16
 
17
17
  group :test do
18
- gem 'sqlite3'
18
+ gem 'sqlite3', '~> 1.4.2'
19
19
  end
data/README.md CHANGED
@@ -1,6 +1,14 @@
1
- # Saxophone
2
-
3
- A declarative SAX parsing library backed by Nokogiri, Ox or Oga.
1
+ <div align="center">
2
+ <img alt="Saxophone" src="logo.svg" width="400px">
3
+ <br>
4
+ <br>
5
+ <strong>A declarative SAX parsing library backed by Nokogiri, Ox or Oga.</strong>
6
+ <br>
7
+ <br>
8
+ <a href="https://github.com/Absolventa/saxophone/actions/workflows/build.yml">
9
+ <img src="https://github.com/Absolventa/saxophone/actions/workflows/build.yml/badge.svg" alt="Build Status" style="max-width: 100%;">
10
+ </a>
11
+ </div>
4
12
 
5
13
  ## Origins
6
14
 
@@ -37,13 +45,13 @@ gem 'nokogiri', '~> 1.6'
37
45
  To use **Ox** add this line to your Gemfile:
38
46
 
39
47
  ```ruby
40
- gem 'ox', '>= 2.1.2'
48
+ gem 'ox', '>= 2.10.0'
41
49
  ```
42
50
 
43
51
  To use **Oga** add this line to your Gemfile:
44
52
 
45
53
  ```ruby
46
- gem 'oga', '>= 0.2.0'
54
+ gem 'oga', '>= 2.15'
47
55
  ```
48
56
 
49
57
  You can also specify which handler to use manually, like this:
@@ -66,34 +74,42 @@ end
66
74
  class AtomEntry
67
75
  include Saxophone
68
76
  element :title
77
+
69
78
  # The :as argument makes this available through entry.author instead of .name
70
79
  element :name, as: :author
71
80
  element "feedburner:origLink", as: :url
81
+
72
82
  # The :default argument specifies default value for element when it's missing
73
83
  element :summary, class: String, default: "No summary available"
84
+
74
85
  element :content, class: AtomContent
75
86
  element :published
87
+
76
88
  ancestor :ancestor
77
89
  end
78
90
 
79
91
  class Atom
80
92
  include Saxophone
93
+
81
94
  # Use block to modify the returned value
82
95
  # Blocks are working with pretty much everything,
83
96
  # except for `elements` with `class` attribute
84
97
  element :title do |title|
85
98
  title.strip
86
99
  end
100
+
87
101
  # The :with argument means that you only match a link tag
88
102
  # that has an attribute of type: "text/html"
89
103
  element :link, value: :href, as: :url, with: {
90
104
  type: "text/html"
91
105
  }
106
+
92
107
  # The :value argument means that instead of setting the value
93
108
  # to the text between the tag, it sets it to the attribute value of :href
94
109
  element :link, value: :href, as: :feed_url, with: {
95
110
  type: "application/atom+xml"
96
111
  }
112
+
97
113
  elements :entry, as: :entries, class: AtomEntry
98
114
  end
99
115
  ```
@@ -101,7 +117,7 @@ end
101
117
  Then parse any XML with your class:
102
118
 
103
119
  ```ruby
104
- feed = Atom.parse(xml_text)
120
+ feed = Atom.parse(xml)
105
121
 
106
122
  feed.title # Whatever the title of the blog is
107
123
  feed.url # The main URL of the blog
@@ -151,11 +167,11 @@ Multiple elements can be mapped to the same alias:
151
167
  ```ruby
152
168
  class RSSEntry
153
169
  include Saxophone
154
- # ...
155
- element :pubDate, as: :published
156
- element :pubdate, as: :published
157
- element :"dc:date", as: :published
158
- element :"dc:Date", as: :published
170
+
171
+ element :pubDate, as: :published
172
+ element :pubdate, as: :published
173
+ element :"dc:date", as: :published
174
+ element :"dc:Date", as: :published
159
175
  element :"dcterms:created", as: :published
160
176
  end
161
177
  ```
@@ -166,6 +182,25 @@ document determines the value assigned to the alias.
166
182
 
167
183
  If an element is defined in the source but is blank (e.g., `<pubDate></pubDate>`), it is ignored, and non-empty one is picked.
168
184
 
185
+ ## Parsing Errors
186
+ By default, there are no notification or exceptions on parsing errors and warnings. For Nokogiri and Ox, you can
187
+ specify a custom behavior by passing procs that receive a string:
188
+
189
+ ```ruby
190
+ on_error = ->(error_string) { raise error_string }
191
+ on_warning = ->(warning_string) { raise warning_string }
192
+
193
+ feed = Atom.parse(xml, on_error, on_warning)
194
+ ```
195
+
196
+ You can also use a global setting (e.g. in `config/initializers/saxophone.rb` when using Saxophone together
197
+ with Ruby on Rails):
198
+
199
+ ```ruby
200
+ Saxophone.on_error = ->(error_string) { raise error_string }
201
+ Saxophone.on_warning = ->(warning_string) { raise warning_string }
202
+ ```
203
+
169
204
  ## Contributing
170
205
 
171
206
  1. Fork it
@@ -178,7 +213,7 @@ If an element is defined in the source but is blank (e.g., `<pubDate></pubDate>`
178
213
 
179
214
  The MIT License
180
215
 
181
- Copyright (c) 2009-2018:
216
+ Copyright (c) 2009-2020:
182
217
 
183
218
  * [Paul Dix](http://www.pauldix.net)
184
219
  * [Julien Kirch](http://www.archiloque.net)
@@ -125,15 +125,11 @@ module Saxophone
125
125
  end
126
126
 
127
127
  def _error(string)
128
- if @on_error
129
- @on_error.call(string)
130
- end
128
+ @on_error.call(string)
131
129
  end
132
130
 
133
131
  def _warning(string)
134
- if @on_warning
135
- @on_warning.call(string)
136
- end
132
+ @on_warning.call(string)
137
133
  end
138
134
 
139
135
  private
@@ -4,7 +4,7 @@ module Saxophone
4
4
  base.extend(ClassMethods)
5
5
  end
6
6
 
7
- def parse(xml_input, on_error = nil, on_warning = nil)
7
+ def parse(xml_input, on_error = Saxophone.on_error, on_warning = Saxophone.on_warning)
8
8
  handler_klass = Saxophone.const_get("SAX#{Saxophone.handler.capitalize}Handler")
9
9
 
10
10
  handler = handler_klass.new(self, on_error, on_warning)
@@ -15,7 +15,7 @@ module Saxophone
15
15
 
16
16
  module InstanceMethods
17
17
  def initialize(attributes = {})
18
- attributes.each do |name, value|
18
+ attributes&.each do |name, value|
19
19
  send("#{name}=", value)
20
20
  end
21
21
 
@@ -1,3 +1,3 @@
1
1
  module Saxophone
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
data/lib/saxophone.rb CHANGED
@@ -14,6 +14,22 @@ module Saxophone
14
14
  @@handler = handler
15
15
  end
16
16
  end
17
+
18
+ def self.on_error
19
+ @@on_error ||= ->(_) {}
20
+ end
21
+
22
+ def self.on_error=(on_error_proc)
23
+ @@on_error = on_error_proc
24
+ end
25
+
26
+ def self.on_warning
27
+ @@on_warning ||= ->(_) {}
28
+ end
29
+
30
+ def self.on_warning=(on_warning_proc)
31
+ @@on_warning = on_warning_proc
32
+ end
17
33
  end
18
34
 
19
35
  # Try handlers
data/logo.svg ADDED
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg viewBox="0 0 764 245" width="764" height="245" xmlns="http://www.w3.org/2000/svg">
3
+ <g fill="none" fill-rule="evenodd">
4
+ <path d="M157.09 209.91c12.955 0 18.683-3.137 23.592-13.092C182.59 205.41 186.409 208 196.5 208v-6.955c-8.182.137-10.636-3.136-10.636-14.454V151c0-21.955-6.955-29.182-28.773-29.182-15.955 0-22.364 4.637-26.591 18.955l7.227 1.772c3.137-10.5 7.637-13.636 19.364-13.636 16.227 0 21.273 5.182 21.273 22.091v8.455H157.09c-21.682 0-28.636 6-28.636 25.772 0 18.682 6.954 24.682 28.636 24.682Zm0-6.955c-16.226 0-21.135-4.228-21.135-17.728 0-14.59 4.909-18.954 21.136-18.954h21.273v12.136c0 18.682-5.046 24.546-21.273 24.546ZM221.183 208l21.273-35.182L263.864 208h8.454l-25.5-42.136 25.5-42.137h-8.454l-21.41 35.182-21.272-35.182h-8.591l25.636 42.137L212.591 208h8.59Zm103.09 1.91c22.5 0 29.728-10.774 29.728-44.046 0-33.273-7.227-44.046-29.727-44.046s-29.591 10.773-29.591 44.046c0 33.272 7.09 44.045 29.59 44.045Zm0-6.955c-16.772 0-22.09-8.728-22.09-37.091 0-28.364 5.318-37.091 22.09-37.091 16.773 0 22.228 8.727 22.228 37.09 0 28.364-5.455 37.092-22.227 37.092Zm60.546 29.863v-34.5c3.682 8.727 11.727 11.591 22.227 11.591 22.5 0 29.728-10.773 29.728-44.182 0-33.272-7.228-43.909-29.728-43.909-10.227 0-18.272 2.046-22.227 8.455v-6.546h-7.5v109.091h7.5Zm22.227-29.863c-13.363 0-22.227-6-22.227-22.773v-39.818c0-8.864 10.227-11.591 22.227-11.591 16.773 0 22.228 8.727 22.228 36.954 0 28.364-5.455 37.228-22.228 37.228ZM468.41 208v-56.182c0-18.545 4.773-23.045 20.864-23.045 15.954 0 21.136 8.318 21.136 35.318V208h7.5v-43.91c0-32.045-6.954-42.272-28.636-42.272-10.228 0-17.864 2.455-20.864 10.227V98.91h-7.5V208h7.5Zm101.318 1.91c22.5 0 29.728-10.774 29.728-44.046 0-33.273-7.228-44.046-29.728-44.046s-29.59 10.773-29.59 44.046c0 33.272 7.09 44.045 29.59 44.045Zm0-6.955c-16.772 0-22.09-8.728-22.09-37.091 0-28.364 5.318-37.091 22.09-37.091 16.773 0 22.228 8.727 22.228 37.09 0 28.364-5.455 37.092-22.228 37.092Zm61.5 5.045v-56.182c0-18.818 5.591-23.045 24.137-23.045 13.772 0 18.136 5.863 18.136 24.545V208h7.5v-54.682c0-24-6.136-31.5-25.636-31.5-13.228 0-19.228 3-24.137 10.091v-8.182h-7.5V208h7.5Zm102.546 1.91c13.909 0 20.727-3.41 28.363-14.046l-6-4.091c-6.681 8.59-11.863 11.182-22.363 11.182-18.137 0-24.137-8.728-24.41-36.682h54.273c0-33.546-7.227-44.455-29.863-44.455-24.273 0-31.91 10.773-31.91 44.046 0 33.272 7.637 44.045 31.91 44.045Zm22.09-50.455H709.5c.682-23.319 6.955-30.682 24.273-30.682 15.545 0 20.863 7.363 22.09 30.682Z" fill="#000" fill-rule="nonzero"/>
5
+ <path d="M139.791 3.5c-7.052 1.164-11.908 2.19-14.566 3.077-7.587 2.53-12.196 5.953-15.414 8.235-4.983 3.534-8.586 8.8-11.227 13.486-3.3 5.853-5.02 11.347-5.137 17.714-.68 52.755-1.203 125.916-1.203 151.243 0 1.848-.113 3.67-.333 5.458-2.69 21.86-21.324 38.787-43.912 38.787-24.435 0-44.244-19.81-44.244-44.245v-61.562l41.965-21.24.585 75.634" stroke="#0A0909" stroke-width="7"/>
6
+ <path d="m76.021 96.23h34.416m-34.416 17.979h34.416m-34.416 18.109h34.416" stroke="#0A0909" stroke-width="5"/>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,88 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Saxophone global configurations" do
4
+ before(:all) do
5
+ class A
6
+ include Saxophone
7
+ end
8
+ end
9
+
10
+ after(:all) do
11
+ Object.send(:remove_const, :A)
12
+ end
13
+
14
+ describe "handler config" do
15
+ after(:all) do
16
+ Saxophone.handler = :ox # restore default settings
17
+ end
18
+
19
+ context "with handler set to ox" do
20
+ before do
21
+ Saxophone.handler = :ox
22
+ end
23
+
24
+ it "uses ox as handler" do
25
+ expect(Saxophone.handler).to eq :ox
26
+ end
27
+ end
28
+
29
+ context "with handler set to oga" do
30
+ before do
31
+ Saxophone.handler = :oga
32
+ end
33
+
34
+ it "uses oga as handler" do
35
+ expect(Saxophone.handler).to eq :oga
36
+ end
37
+ end
38
+
39
+ context "with handler set to nokogiri" do
40
+ before do
41
+ Saxophone.handler = :nokogiri
42
+ end
43
+
44
+ it "uses nokogiri as handler" do
45
+ expect(Saxophone.handler).to eq :nokogiri
46
+ end
47
+ end
48
+
49
+ context "with handler set to some other value" do
50
+ it "raises error" do
51
+ expect { Saxophone.handler = :not_a_valid_handler }.to raise_error(LoadError)
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "global on_error config" do
57
+ broken_xml = "<top><title>Te & st</title><b>Matched!</b><c>And Again</c></top>"
58
+ xml = "<top><title>Test</title><b>Matched!</b><c>And Again</c></top>"
59
+
60
+ context "not configured" do
61
+ it "does not raise exception on valid xml" do
62
+ expect { A.parse xml }.not_to raise_error
63
+ end
64
+
65
+ it "does not raise exception on broken xml" do
66
+ expect { A.parse broken_xml }.not_to raise_error
67
+ end
68
+ end
69
+
70
+ context "configured to raise exception" do
71
+ before(:all) do
72
+ Saxophone.on_error = ->(error_string) { raise error_string }
73
+ end
74
+
75
+ after(:all) do
76
+ Saxophone.on_error = ->(_) {} # restore default settings
77
+ end
78
+
79
+ it "does not raise exception on valid xml" do
80
+ expect { A.parse xml }.not_to raise_error
81
+ end
82
+
83
+ it "raises exception on broken xml" do
84
+ expect { A.parse broken_xml }.to raise_error(RuntimeError)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -1172,8 +1172,9 @@ describe "Saxophone" do
1172
1172
  describe "with error handling" do
1173
1173
  before do
1174
1174
  @xml = %[
1175
- <item id="1">
1175
+ <item:a:b id="1">
1176
1176
  <title>sweet</title>
1177
+ </idem>
1177
1178
  ]
1178
1179
 
1179
1180
  class ItemElement5
@@ -1190,9 +1191,7 @@ describe "Saxophone" do
1190
1191
  )
1191
1192
  end
1192
1193
 
1193
- it "has error" do
1194
- expect(@errors.uniq.size).to eq(1)
1195
- end
1194
+ it { expect(@errors.uniq.size).to be >= 1 }
1196
1195
 
1197
1196
  it "has no warning" do
1198
1197
  expect(@warnings.uniq.size).to eq(0)
data/spec/spec_helper.rb CHANGED
@@ -1,22 +1,2 @@
1
- begin
2
- require 'simplecov'
3
- require 'coveralls'
4
-
5
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
6
- SimpleCov::Formatter::HTMLFormatter,
7
- Coveralls::SimpleCov::Formatter
8
- ]
9
-
10
- SimpleCov.start do
11
- add_filter '/spec/'
12
- end
13
- rescue LoadError
14
- end
15
-
16
1
  require File.expand_path(File.dirname(__FILE__) + '/../lib/saxophone')
17
2
  Saxophone.handler = ENV['HANDLER'].to_sym if ENV['HANDLER']
18
-
19
- RSpec.configure do |config|
20
- config.run_all_when_everything_filtered = true
21
- config.filter_run :focus
22
- end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saxophone
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Dix
@@ -9,10 +9,10 @@ authors:
9
9
  - Ezekiel Templin
10
10
  - Dmitry Krasnoukhov
11
11
  - Robin Neumann
12
- autorequire:
12
+ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2018-10-19 00:00:00.000000000 Z
15
+ date: 2021-10-27 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rspec
@@ -28,16 +28,16 @@ dependencies:
28
28
  - - "~>"
29
29
  - !ruby/object:Gem::Version
30
30
  version: '3.6'
31
- description:
32
- email:
31
+ description:
32
+ email:
33
33
  executables: []
34
34
  extensions: []
35
35
  extra_rdoc_files: []
36
36
  files:
37
+ - ".github/workflows/build.yml"
37
38
  - ".gitignore"
38
39
  - ".rspec"
39
40
  - ".ruby-version"
40
- - ".travis.yml"
41
41
  - Gemfile
42
42
  - README.md
43
43
  - Rakefile
@@ -56,9 +56,11 @@ files:
56
56
  - lib/saxophone/sax_configure.rb
57
57
  - lib/saxophone/sax_document.rb
58
58
  - lib/saxophone/version.rb
59
+ - logo.svg
59
60
  - saxophone.gemspec
60
61
  - spec/fixtures/atom-content.html
61
62
  - spec/fixtures/atom.xml
63
+ - spec/saxophone/global_config_spec.rb
62
64
  - spec/saxophone/sax_activerecord_spec.rb
63
65
  - spec/saxophone/sax_configure_spec.rb
64
66
  - spec/saxophone/sax_document_spec.rb
@@ -68,7 +70,7 @@ homepage: http://github.com/Absolventa/saxophone
68
70
  licenses:
69
71
  - MIT
70
72
  metadata: {}
71
- post_install_message:
73
+ post_install_message:
72
74
  rdoc_options: []
73
75
  require_paths:
74
76
  - lib
@@ -83,14 +85,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
85
  - !ruby/object:Gem::Version
84
86
  version: '0'
85
87
  requirements: []
86
- rubyforge_project:
87
- rubygems_version: 2.2.2
88
- signing_key:
88
+ rubygems_version: 3.2.15
89
+ signing_key:
89
90
  specification_version: 4
90
91
  summary: Declarative SAX Parsing with Nokogiri, Ox or Oga
91
92
  test_files:
92
93
  - spec/fixtures/atom-content.html
93
94
  - spec/fixtures/atom.xml
95
+ - spec/saxophone/global_config_spec.rb
94
96
  - spec/saxophone/sax_activerecord_spec.rb
95
97
  - spec/saxophone/sax_configure_spec.rb
96
98
  - spec/saxophone/sax_document_spec.rb
data/.travis.yml DELETED
@@ -1,35 +0,0 @@
1
- language: ruby
2
-
3
- rvm:
4
- - 1.9.3
5
- - 2.0
6
- - 2.1
7
- - 2.2
8
- - 2.3
9
- - 2.4
10
- - 2.5
11
- - jruby-1.7
12
- - rbx-2
13
- - ruby-head
14
- - jruby-head
15
-
16
- sudo: false
17
-
18
- env:
19
- matrix:
20
- - HANDLER="nokogiri"
21
- - HANDLER="ox"
22
- - HANDLER="oga"
23
-
24
- matrix:
25
- exclude:
26
- - env: HANDLER="ox"
27
- rvm: jruby-1.7
28
- - env: HANDLER="ox"
29
- rvm: jruby-head
30
- allow_failures:
31
- - env: HANDLER="oga"
32
- rvm: jruby-1.7
33
- - rvm: rbx-2
34
- - rvm: ruby-head
35
- - rvm: jruby-head