html_surgeon 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 184ce38f2ca801e35b52003637cdba997487557c
4
+ data.tar.gz: 23741ef09a0cf4e12150171fcbb93417c86ceef2
5
+ SHA512:
6
+ metadata.gz: e567d65954530da7c2f33c562f0890813280b7274d68978d6419552aa933fe49e4cac1d5e5110ac454c99c1393381fade85b73d374750e96e92ebc96f7d8cc38
7
+ data.tar.gz: a25d072d6c15964317a440e5857d24f60ced9ce620b87acfd5f5f48af3b82c507daa8a4edb3c2382fb8078669a6123e2c1d608d3ff34537386ff80ee0a311a25
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.idea
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ before_install: gem install bundler -v 1.10.3
5
+
6
+ addons:
7
+ code_climate:
8
+ repo_token: ecc7b46e36ad6c2bda5d5b91fc86cbf594b8b5903c72a1fa838e53426093280d
9
+
10
+ script: 'bundle exec rake spec'
11
+
12
+ notifications:
13
+ email:
14
+ recipients:
15
+ - eturino@eturino.com
16
+ on_failure: change
17
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in html_surgeon.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'pry'
8
+ gem 'pry-nav'
9
+ gem 'pry-stack_explorer'
10
+ gem 'pry-doc'
11
+ gem 'pry-rescue'
12
+ end
13
+
14
+ gem 'codeclimate-test-reporter', :group => :test, :require => nil
data/README.md ADDED
@@ -0,0 +1,209 @@
1
+ # HtmlSurgeon
2
+
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/html_surgeon.svg)](http://badge.fury.io/rb/html_surgeon)
5
+ [![Build Status](https://travis-ci.org/eturino/html_surgeon.svg?branch=master)](https://travis-ci.org/eturino/html_surgeon)
6
+ [![Code Climate](https://codeclimate.com/github/eturino/html_surgeon.png)](https://codeclimate.com/github/eturino/html_surgeon)
7
+ [![Code Climate Coverage](https://codeclimate.com/github/eturino/html_surgeon/coverage.png)](https://codeclimate.com/github/eturino/html_surgeon)
8
+
9
+ Make specific changes in a HTML string, optionally adding html attributes with the audit trail of the changes. Uses [Nokogiri](http://www.nokogiri.org/).
10
+
11
+ ## Basic Usage
12
+
13
+ First, you create a HtmlSurgeon service instance for the given html fragment
14
+
15
+ ```ruby
16
+ GIVEN_HTML = <<-HTML
17
+ <div>
18
+ <h1>Something</h1>
19
+ <div id="1" class="lol to-be-changed">1</div>
20
+ <span>Other</span>
21
+ <div id="2" class="another to-be-changed">
22
+ <ul>
23
+ <li>1</li>
24
+ <li>2</li>
25
+ </ul>
26
+ </div>
27
+ </div>
28
+ HTML
29
+
30
+ surgeon = HtmlSurgeon.for(GIVEN_HTML)
31
+ ```
32
+
33
+ if you want to add audit attributes in the HTML tags changed, pass the option in the surgeon service creation
34
+
35
+ ```ruby
36
+ surgeon = HtmlSurgeon.for(GIVEN_HTML, audit: true)
37
+ ```
38
+
39
+ with the surgeon service, you can prepare several change sets. A change set is defined by a node set and a list of changes to be applied on each selected node.
40
+
41
+ ```ruby
42
+ change_set = surgeon.css('div.to-be-changed') # => will return a change_set
43
+
44
+ change_set.node_set # => will return a Nokogiri's Node Set with the selected nodes (right now it'll get us div ID 1 and div ID 2.
45
+
46
+ # to prepare a change replace the tag name 'div' for 'article'
47
+ change_set.replace_tag_name('article')
48
+
49
+ # to prepare another change to add a css class in the selected nodes
50
+ change_set.add_css_class('added-class')
51
+
52
+ # we can add a second one
53
+ change_set.add_css_class('another-added-class')
54
+
55
+ ```
56
+
57
+ The changes are not made yet. In order to do it, we call `run` on the change set
58
+
59
+ ```ruby
60
+ change_set.run
61
+
62
+ surgeon.html # => html with the changes applied
63
+ # =>
64
+ # <div>
65
+ # <h1>Something</h1>
66
+ # <article id="1" class="lol to-be-changed added-class another-added-class">1</div>
67
+ # <span>Other</span>
68
+ # <article id="2" class="another to-be-changed added-class another-added-class">
69
+ # <ul>
70
+ # <li>1</li>
71
+ # <li>2</li>
72
+ # </ul>
73
+ # </div>
74
+ # </div>
75
+
76
+
77
+ # original html still in
78
+ surgeon.given_html == GIVEN_HTML # => true
79
+
80
+ # you can review what was changed in the change set
81
+ change_set.changes
82
+ # =>
83
+ # [
84
+ # "replace tag name with article",
85
+ # "add css class added-class",
86
+ # "add css class another-added-class",
87
+ # ]
88
+ ```
89
+
90
+ We can also chain call the changes in a changeset
91
+
92
+ ```ruby
93
+ surgeon = HtmlService.for(GIVEN_HTML)
94
+ surgeon.css('.lol').replace_tag_name('span').add_css_class('hey').run
95
+ surgeon.html # =>
96
+ # <div>
97
+ # <h1>Something</h1>
98
+ # <span id="1" class="lol to-be-changed hey">1</span>
99
+ # <span>Other</span>
100
+ # <div id="2" class="another to-be-changed">
101
+ # <ul>
102
+ # <li>1</li>
103
+ # <li>2</li>
104
+ # </ul>
105
+ # </div>
106
+ # </div>
107
+ ```
108
+
109
+ If we have enabled audit, we'll get the changes applied to an element in an data attribute.
110
+ It will store, in JSON, an array with all the changes.
111
+
112
+ ```ruby
113
+ surgeon = HtmlService.for(GIVEN_HTML)
114
+ surgeon.css('.lol').replace_tag_name('span').add_css_class('hey').run
115
+ surgeon.html # =>
116
+ # <div>
117
+ # <h1>Something</h1>
118
+ # <span id="1" class="lol to-be-changed hey" data-surgeon-audit='[{"change_set":"830e96dc-fa07-40ce-8968-ea5c55ec4b84","changed_at":"2015-07-02T12:52:43.874Z","type":"replace_tag_name","old":"div","new":"span"},{"change_set":"830e96dc-fa07-40ce-8968-ea5c55ec4b84","changed_at":"2015-07-02T12:52:43.874Z","type":"add_css_class","existed_before":false,"class":"hey"}]'>1</span>
119
+ # <span>Other</span>
120
+ # <div id="2" class="another to-be-changed">
121
+ # <ul>
122
+ # <li>1</li>
123
+ # <li>2</li>
124
+ # </ul>
125
+ # </div>
126
+ # </div>#
127
+ ```
128
+
129
+ the attribute's value (formatted) is:
130
+
131
+ ```json
132
+ [
133
+ {
134
+ "change_set":"830e96dc-fa07-40ce-8968-ea5c55ec4b84",
135
+ "changed_at":"2015-07-02T12:52:43.874Z",
136
+ "type":"replace_tag_name",
137
+ "old":"div",
138
+ "new":"span"
139
+ },
140
+ {
141
+ "change_set":"830e96dc-fa07-40ce-8968-ea5c55ec4b84",
142
+ "changed_at":"2015-07-02T12:52:43.874Z",
143
+ "type":"add_css_class",
144
+ "existed_before":false,
145
+ "class":"hey"
146
+ }
147
+ ]
148
+ ```
149
+
150
+ it has a `change_set` with the UUID of the change set, `changed_at` with the moment it was applied, and the rest define the change.
151
+
152
+ ## Selecting the Node Set
153
+
154
+ we use Nokogiri's selections.
155
+
156
+ ### using css
157
+
158
+ ```ruby
159
+ change_set = surgeon.css('div.to-be-changed')
160
+ ```
161
+
162
+ ### using xpath
163
+
164
+ not implemented yet.
165
+
166
+
167
+ ## Available Changes
168
+
169
+ ### Replace Tag Name
170
+
171
+ ```ruby
172
+ surgeon.css('div.to-be-changed').replace_name_tag('article')
173
+ ```
174
+
175
+ ### Add CSS Class
176
+
177
+ ```ruby
178
+ surgeon.css('div.to-be-changed').add_css_class('applied-some-stuff')
179
+ ```
180
+
181
+
182
+
183
+ ## Installation
184
+
185
+ Add this line to your application's Gemfile:
186
+
187
+ ```ruby
188
+ gem 'html_surgeon'
189
+ ```
190
+
191
+ And then execute:
192
+
193
+ $ bundle
194
+
195
+ Or install it yourself as:
196
+
197
+ $ gem install html_surgeon
198
+
199
+
200
+ ## Development
201
+
202
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
203
+
204
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
205
+
206
+ ## Contributing
207
+
208
+ Bug reports and pull requests are welcome on GitHub at https://github.com/eturino/html_surgeon.
209
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ # Default directory to look in is `/specs`
5
+ # Run with `rake spec`
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.rspec_opts = ['--color']
8
+ end
9
+
10
+ task :default => :spec
11
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "html_surgeon"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'html_surgeon/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'html_surgeon'
8
+ spec.version = HtmlSurgeon::VERSION
9
+ spec.authors = ['Eduardo Turiño']
10
+ spec.email = ['eturino@eturino.com']
11
+
12
+ spec.summary = %q{Ruby gem for surgical changes in HTML fragment strings, using Nokogiri, with optional audit trail in html attributes}
13
+ # spec.description = %q{TODO: Write a longer description or delete this line.}
14
+ spec.homepage = 'https://github.com/eturino/html_surgeon'
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ # if spec.respond_to?(:metadata)
19
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
20
+ # else
21
+ # raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
22
+ # end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = 'exe'
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.add_dependency 'nokogiri'
30
+ spec.add_dependency 'activesupport'
31
+ spec.add_dependency 'oj'
32
+ spec.add_dependency 'oj_mimic_json'
33
+ spec.add_development_dependency 'bundler', '~> 1.10'
34
+ spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'rspec'
36
+ end
@@ -0,0 +1,16 @@
1
+ require 'oj_mimic_json'
2
+ require 'nokogiri'
3
+ require 'active_support/all'
4
+ require 'html_surgeon/version'
5
+ require 'html_surgeon/abstract_method_error'
6
+ require 'html_surgeon/service'
7
+ require 'html_surgeon/change_set'
8
+ require 'html_surgeon/change'
9
+ require 'html_surgeon/changes/add_css_class'
10
+ require 'html_surgeon/changes/replace_tag_name'
11
+
12
+ module HtmlSurgeon
13
+ def self.for(html_string, **options)
14
+ Service.new html_string, **options
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module HtmlSurgeon
2
+ class AbstractMethodError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,64 @@
1
+ module HtmlSurgeon
2
+
3
+ class Change
4
+ DATA_CHANGE_AUDIT_ATTRIBUTE = 'data-surgeon-audit'.freeze
5
+
6
+ attr_reader :change_set
7
+
8
+ def initialize(change_set:)
9
+ @change_set = change_set
10
+ end
11
+
12
+ delegate :audit?, to: :change_set
13
+ delegate :uuid, :run_time, to: :change_set, prefix: true
14
+
15
+ def apply(element)
16
+ prepare_audit_change(element) if audit?
17
+
18
+ apply_in element
19
+
20
+ apply_audit_change(element) if audit?
21
+
22
+ self
23
+ end
24
+
25
+ def log
26
+ raise AbstractMethodError, "a lazy developer has not implemented this method in #{self.class}"
27
+ end
28
+
29
+ private
30
+
31
+ def prepare_audit_change(element)
32
+ @audit_data = audit_data(element)
33
+ end
34
+
35
+ def apply_audit_change(element)
36
+ current = current_audit_data(element)
37
+ current << @audit_data
38
+ element[DATA_CHANGE_AUDIT_ATTRIBUTE] = Oj.dump current
39
+ end
40
+
41
+ def current_audit_data(element)
42
+ current = element[DATA_CHANGE_AUDIT_ATTRIBUTE].presence
43
+ return [] unless current
44
+
45
+ Oj.load current
46
+ end
47
+
48
+ def basic_audit_data
49
+ {
50
+ change_set: change_set_uuid,
51
+ changed_at: change_set_run_time
52
+ }
53
+ end
54
+
55
+ def audit_data(element)
56
+ raise AbstractMethodError, "a lazy developer has not implemented this method in #{self.class}"
57
+ end
58
+
59
+ def apply_in(_element)
60
+ raise AbstractMethodError, "a lazy developer has not implemented this method in #{self.class}"
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,52 @@
1
+ module HtmlSurgeon
2
+
3
+ class ChangeSet
4
+ attr_reader :node_set, :base, :change_list, :uuid, :run_time
5
+
6
+ def initialize(node_set, base)
7
+ @node_set = node_set
8
+ @base = base
9
+ @change_list = []
10
+ @uuid = SecureRandom.uuid
11
+ @run_time = nil
12
+ end
13
+
14
+ delegate :audit?, :html, to: :base
15
+
16
+ # TODO: #preview, like run but in another doc, does not change it yet.
17
+
18
+ def run
19
+ @run_time = Time.now.utc
20
+
21
+ node_set.each do |element|
22
+ apply_on_element(element)
23
+ end
24
+
25
+ self
26
+ end
27
+
28
+ def changes
29
+ change_list.map &:log
30
+ end
31
+
32
+ # CHANGES
33
+
34
+ def replace_tag_name(new_tag_name)
35
+ change_list << Changes::ReplaceTagName.new(change_set: self, new_tag_name: new_tag_name)
36
+ self
37
+ end
38
+
39
+ def add_css_class(css_class)
40
+ change_list << Changes::AddCssClass.new(change_set: self, css_class: css_class)
41
+ self
42
+ end
43
+
44
+ private
45
+
46
+ def apply_on_element(element)
47
+ change_list.each do |change|
48
+ change.apply(element)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,40 @@
1
+ module HtmlSurgeon
2
+ module Changes
3
+ class AddCssClass < Change
4
+ attr_reader :css_class
5
+ CLASS_ATTRIBUTE = 'class'.freeze
6
+ CLASS_SEPARATOR = ' '.freeze
7
+
8
+ def initialize(css_class:, **other)
9
+ @css_class = css_class
10
+
11
+ super **other
12
+ end
13
+
14
+ def log
15
+ "add css class #{css_class}"
16
+ end
17
+
18
+ private
19
+ def apply_in(element)
20
+ classes = element_classes element
21
+ classes << css_class
22
+ element.set_attribute(CLASS_ATTRIBUTE, classes.join(CLASS_SEPARATOR))
23
+ end
24
+
25
+ def audit_data(element)
26
+ basic_audit_data.merge type: :add_css_class,
27
+ existed_before: had_class?(element),
28
+ class: css_class
29
+ end
30
+
31
+ def element_classes(element)
32
+ element.get_attribute(CLASS_ATTRIBUTE).to_s.split(CLASS_SEPARATOR)
33
+ end
34
+
35
+ def had_class?(element)
36
+ element_classes(element).include? css_class
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ module HtmlSurgeon
2
+ module Changes
3
+ class ReplaceTagName < Change
4
+ attr_reader :new_tag_name
5
+
6
+ def initialize(new_tag_name:, **other)
7
+ @new_tag_name = new_tag_name
8
+
9
+ super **other
10
+ end
11
+
12
+ def log
13
+ "replace tag name with #{new_tag_name}"
14
+ end
15
+
16
+ private
17
+ def apply_in(element)
18
+ element.name = new_tag_name
19
+ end
20
+
21
+ def audit_data(element)
22
+ basic_audit_data.merge type: :replace_tag_name,
23
+ old: element.name,
24
+ new: new_tag_name
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module HtmlSurgeon
2
+ class Service
3
+ attr_reader :given_html, :options
4
+
5
+ def initialize(html_string, audit: false, **extra_options)
6
+ @given_html = html_string
7
+ @audit = audit
8
+ @options = extra_options.merge audit: audit
9
+ end
10
+
11
+ def html
12
+ @html ||= doc.to_html
13
+ end
14
+
15
+ def audit?
16
+ !!@audit
17
+ end
18
+
19
+ def css(css_selector)
20
+ node_set = doc.css(css_selector)
21
+ ChangeSet.new(node_set, self)
22
+ end
23
+
24
+ private
25
+ def doc
26
+ @doc ||= Nokogiri::HTML.fragment @given_html.dup
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module HtmlSurgeon
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: html_surgeon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eduardo Turiño
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-07-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: oj
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: oj_mimic_json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.10'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.10'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - eturino@eturino.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - README.md
123
+ - Rakefile
124
+ - bin/console
125
+ - bin/setup
126
+ - html_surgeon.gemspec
127
+ - lib/html_surgeon.rb
128
+ - lib/html_surgeon/abstract_method_error.rb
129
+ - lib/html_surgeon/change.rb
130
+ - lib/html_surgeon/change_set.rb
131
+ - lib/html_surgeon/changes/add_css_class.rb
132
+ - lib/html_surgeon/changes/replace_tag_name.rb
133
+ - lib/html_surgeon/service.rb
134
+ - lib/html_surgeon/version.rb
135
+ homepage: https://github.com/eturino/html_surgeon
136
+ licenses: []
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.4.6
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: Ruby gem for surgical changes in HTML fragment strings, using Nokogiri, with
158
+ optional audit trail in html attributes
159
+ test_files: []
160
+ has_rdoc: