markup_mechanic 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.
- data/Gemfile +10 -0
- data/LICENSE +21 -0
- data/README.md +69 -0
- data/Rakefile +150 -0
- data/lib/markup_mechanic.rb +32 -0
- data/lib/markup_mechanic/active_record.rb +4 -0
- data/lib/markup_mechanic/base.rb +18 -0
- data/lib/markup_mechanic/callbacks.rb +5 -0
- data/lib/markup_mechanic/callbacks/before_save.rb +37 -0
- data/lib/markup_mechanic/configuration.rb +23 -0
- data/lib/markup_mechanic/default_adapter.rb +16 -0
- data/lib/markup_mechanic/error.rb +12 -0
- data/lib/markup_mechanic/version.rb +3 -0
- data/markup_mechanic.gemspec +47 -0
- data/test/markup_mechanic_test.rb +11 -0
- data/test/test_helper.rb +9 -0
- metadata +97 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Ryan Heath
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
MarkupMechanic
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Malformed HTML be gone! When you allow users to enter raw HTML into a wide open
|
|
5
|
+
textarea, you're asking for trouble. Missing closing tags and tags closed in the
|
|
6
|
+
wrong order can really make your layouts go bananas. This little library is an
|
|
7
|
+
attempt to repair those issues. Just leave it to the Markup Mechanic (thanks
|
|
8
|
+
to [Chris Scharf](http://github.com/scharfie) for the name).
|
|
9
|
+
|
|
10
|
+
# Installation
|
|
11
|
+
|
|
12
|
+
Just add `gem "markup_mechanic"` to your Gemfile.
|
|
13
|
+
|
|
14
|
+
Note: this gem is designed to use with Rails projects using ActiveRecord.
|
|
15
|
+
|
|
16
|
+
# Usage
|
|
17
|
+
|
|
18
|
+
It's rather simple to use. Once installed, just add one line to your model,
|
|
19
|
+
passing it the columns that you wish to repair.
|
|
20
|
+
|
|
21
|
+
class Article < ActiveRecord::Base
|
|
22
|
+
repair_markup_for :caption, :body
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Each time the record is saved, those columns will run through a parser (or, "mechanic")
|
|
26
|
+
that will repair the invalid HTML.
|
|
27
|
+
|
|
28
|
+
# Custom Mechanic Adapters
|
|
29
|
+
|
|
30
|
+
Under the hood, we're really just relying on the amazing Nokogiri library to do
|
|
31
|
+
the dirty work. That's the default. But if you wanted to customize the behavior of
|
|
32
|
+
the mechanic, you can add your own custom adapter.
|
|
33
|
+
|
|
34
|
+
Two requirements:
|
|
35
|
+
|
|
36
|
+
1. Your class must be initialized to accept an HTML string
|
|
37
|
+
2. Your class must implement a `fix!` instance method
|
|
38
|
+
|
|
39
|
+
For example, in your Rails project, let's say in `config/initializers/markup_mechanic.rb`
|
|
40
|
+
you might do something like this:
|
|
41
|
+
|
|
42
|
+
class MyAwesomeMechanic
|
|
43
|
+
attr_reader :html
|
|
44
|
+
|
|
45
|
+
def initialize(html)
|
|
46
|
+
@html = html
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def fix!
|
|
50
|
+
# do your fancy work here
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
MarkupMechanic.configure do |config|
|
|
55
|
+
config.adapter = MyAwesomeMechanic
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
That's really it. Now the `repair_markup_for` method will run those columns through
|
|
59
|
+
your custom parser instead.
|
|
60
|
+
|
|
61
|
+
# Credits
|
|
62
|
+
|
|
63
|
+
[Chris Scharf](http://github.com/scharfie) for the name and inspiration to package this up as a gem.
|
|
64
|
+
|
|
65
|
+
# License
|
|
66
|
+
|
|
67
|
+
Copyright (c) Ryan Heath
|
|
68
|
+
|
|
69
|
+
Published under the MIT License, see LICENSE
|
data/Rakefile
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'date'
|
|
4
|
+
|
|
5
|
+
#############################################################################
|
|
6
|
+
#
|
|
7
|
+
# Helper functions
|
|
8
|
+
#
|
|
9
|
+
#############################################################################
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def version
|
|
16
|
+
line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
|
|
17
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def date
|
|
21
|
+
Date.today.to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def rubyforge_project
|
|
25
|
+
name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def gemspec_file
|
|
29
|
+
"#{name}.gemspec"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def gem_file
|
|
33
|
+
"#{name}-#{version}.gem"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def replace_header(head, header_name)
|
|
37
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
#############################################################################
|
|
41
|
+
#
|
|
42
|
+
# Standard tasks
|
|
43
|
+
#
|
|
44
|
+
#############################################################################
|
|
45
|
+
|
|
46
|
+
task :default => :test
|
|
47
|
+
|
|
48
|
+
require 'rake/testtask'
|
|
49
|
+
Rake::TestTask.new(:test) do |test|
|
|
50
|
+
test.libs << 'lib' << 'test'
|
|
51
|
+
test.pattern = 'test/**/*_test.rb'
|
|
52
|
+
test.verbose = true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
desc "Generate RCov test coverage and open in your browser"
|
|
56
|
+
task :coverage do
|
|
57
|
+
require 'rcov'
|
|
58
|
+
sh "rm -fr coverage"
|
|
59
|
+
sh "rcov test/*_test.rb"
|
|
60
|
+
sh "open coverage/index.html"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
require 'rake/rdoctask'
|
|
64
|
+
Rake::RDocTask.new do |rdoc|
|
|
65
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
66
|
+
rdoc.title = "#{name} #{version}"
|
|
67
|
+
rdoc.rdoc_files.include('README*')
|
|
68
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
desc "Open an irb session preloaded with this library"
|
|
72
|
+
task :console do
|
|
73
|
+
sh "irb -rubygems -r ./lib/#{name}.rb"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#############################################################################
|
|
77
|
+
#
|
|
78
|
+
# Custom tasks (add your own tasks here)
|
|
79
|
+
#
|
|
80
|
+
#############################################################################
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
#############################################################################
|
|
85
|
+
#
|
|
86
|
+
# Packaging tasks
|
|
87
|
+
#
|
|
88
|
+
#############################################################################
|
|
89
|
+
|
|
90
|
+
desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
|
|
91
|
+
task :release => :build do
|
|
92
|
+
unless `git branch` =~ /^\* master$/
|
|
93
|
+
puts "You must be on the master branch to release!"
|
|
94
|
+
exit!
|
|
95
|
+
end
|
|
96
|
+
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
|
97
|
+
sh "git tag v#{version}"
|
|
98
|
+
sh "git push origin master"
|
|
99
|
+
sh "git push origin v#{version}"
|
|
100
|
+
sh "gem push pkg/#{name}-#{version}.gem"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
desc "Build #{gem_file} into the pkg directory"
|
|
104
|
+
task :build => :gemspec do
|
|
105
|
+
sh "mkdir -p pkg"
|
|
106
|
+
sh "gem build #{gemspec_file}"
|
|
107
|
+
sh "mv #{gem_file} pkg"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
desc "Generate #{gemspec_file}"
|
|
111
|
+
task :gemspec => :validate do
|
|
112
|
+
# read spec file and split out manifest section
|
|
113
|
+
spec = File.read(gemspec_file)
|
|
114
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
|
115
|
+
|
|
116
|
+
# replace name version and date
|
|
117
|
+
replace_header(head, :name)
|
|
118
|
+
replace_header(head, :version)
|
|
119
|
+
replace_header(head, :date)
|
|
120
|
+
#comment this out if your rubyforge_project has a different name
|
|
121
|
+
replace_header(head, :rubyforge_project)
|
|
122
|
+
|
|
123
|
+
# determine file list from git ls-files
|
|
124
|
+
files = `git ls-files`.
|
|
125
|
+
split("\n").
|
|
126
|
+
sort.
|
|
127
|
+
reject { |file| file =~ /^\./ }.
|
|
128
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
|
129
|
+
map { |file| " #{file}" }.
|
|
130
|
+
join("\n")
|
|
131
|
+
|
|
132
|
+
# piece file back together and write
|
|
133
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
|
134
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
|
135
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
|
136
|
+
puts "Updated #{gemspec_file}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
desc "Validate #{gemspec_file}"
|
|
140
|
+
task :validate do
|
|
141
|
+
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
|
142
|
+
unless libfiles.empty?
|
|
143
|
+
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
|
144
|
+
exit!
|
|
145
|
+
end
|
|
146
|
+
unless Dir['VERSION*'].empty?
|
|
147
|
+
puts "A `VERSION` file at root level violates Gem best practices."
|
|
148
|
+
exit!
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'markup_mechanic/error'
|
|
2
|
+
require 'markup_mechanic/default_adapter'
|
|
3
|
+
require 'markup_mechanic/configuration'
|
|
4
|
+
require 'markup_mechanic/callbacks'
|
|
5
|
+
require 'markup_mechanic/base'
|
|
6
|
+
|
|
7
|
+
module MarkupMechanic
|
|
8
|
+
def self.included(base)
|
|
9
|
+
base.extend ClassMethods
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module ClassMethods
|
|
13
|
+
# accepts a list of columns for an ActiveRecord
|
|
14
|
+
# model and fixes the HTML in a before_save callback
|
|
15
|
+
def repair_markup_for(*columns)
|
|
16
|
+
options = columns.extract_options!
|
|
17
|
+
before_save MarkupMechanic::Callbacks::BeforeSave.new(columns, options)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# mixins
|
|
22
|
+
extend Base
|
|
23
|
+
extend Configuration
|
|
24
|
+
|
|
25
|
+
# debug mode sends output to the logs
|
|
26
|
+
def self.debug_mode?
|
|
27
|
+
self.debug_mode
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# hook into ActiveRecord
|
|
32
|
+
require 'markup_mechanic/active_record'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'markup_mechanic/version'
|
|
2
|
+
|
|
3
|
+
module MarkupMechanic
|
|
4
|
+
module Base
|
|
5
|
+
def version
|
|
6
|
+
VERSION
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# wrapper for logging, highlights the section for easier viewing
|
|
10
|
+
def log(message)
|
|
11
|
+
if logger.present? && MarkupMechanic.debug_mode?
|
|
12
|
+
logger.info("--- Markup Mechanic (v#{MarkupMechanic.version}) ---")
|
|
13
|
+
logger.info(message)
|
|
14
|
+
logger.info("----------------------------------------------------")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module MarkupMechanic
|
|
2
|
+
module Callbacks
|
|
3
|
+
# this is the callback that fires on
|
|
4
|
+
# before_save of a model that has the
|
|
5
|
+
# repair_markup_for() call
|
|
6
|
+
class BeforeSave
|
|
7
|
+
attr_accessor :columns, :options, :adapter
|
|
8
|
+
|
|
9
|
+
def initialize(columns, options)
|
|
10
|
+
@columns = columns
|
|
11
|
+
@options = options
|
|
12
|
+
@adapter = MarkupMechanic.adapter
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def before_save(record)
|
|
16
|
+
self.columns.each do |column|
|
|
17
|
+
if record.respond_to?(column) && record.respond_to?("#{column}=")
|
|
18
|
+
MarkupMechanic.log("Repairing #{record.class}::#{column}")
|
|
19
|
+
|
|
20
|
+
# register a new mechanic for this column
|
|
21
|
+
mechanic = self.adapter.new(record.send(column))
|
|
22
|
+
|
|
23
|
+
# since custom adapters are supported, we must ensure that the
|
|
24
|
+
# adapter responds to the `fix!` method, as expected
|
|
25
|
+
raise MarkupMechanic::InvalidAdapterError unless mechanic.respond_to?(:fix!)
|
|
26
|
+
|
|
27
|
+
# repair the HTML
|
|
28
|
+
repaired_html = mechanic.fix!
|
|
29
|
+
|
|
30
|
+
# update the record
|
|
31
|
+
record.send("#{column}=", repaired_html)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module MarkupMechanic
|
|
2
|
+
module Configuration
|
|
3
|
+
attr_accessor :adapter, :logger, :debug_mode
|
|
4
|
+
|
|
5
|
+
# set the defaults when the
|
|
6
|
+
# Configuration module is extended
|
|
7
|
+
def self.extended(base)
|
|
8
|
+
base.reset!
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# convenience method for configuration
|
|
12
|
+
def configure
|
|
13
|
+
yield self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# resets the options to the defaults
|
|
17
|
+
def reset!
|
|
18
|
+
self.adapter = MarkupMechanic::DefaultAdapter
|
|
19
|
+
self.logger = Rails.logger
|
|
20
|
+
self.debug_mode = Rails.env.development?
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module MarkupMechanic
|
|
2
|
+
class DefaultAdapter
|
|
3
|
+
attr_reader :html
|
|
4
|
+
|
|
5
|
+
def initialize(html)
|
|
6
|
+
@html = html.to_s
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# use the magic that is Nokogiri to parse
|
|
10
|
+
# and fix the HTML fragment
|
|
11
|
+
def fix!
|
|
12
|
+
fragment = Nokogiri::HTML.fragment(self.html)
|
|
13
|
+
fragment.to_html
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module MarkupMechanic
|
|
2
|
+
class Error < StandardError; end
|
|
3
|
+
|
|
4
|
+
# raised if the adapter isntance doesn't accept
|
|
5
|
+
# an HTML string on initialization or there's
|
|
6
|
+
# no `fix!` method on the object
|
|
7
|
+
class InvalidAdapterError < Error
|
|
8
|
+
def initialize(message = "needs initialized with a string of HTML, and must respond to a fix! method")
|
|
9
|
+
super(message)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
|
3
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
4
|
+
s.rubygems_version = "1.3.5"
|
|
5
|
+
|
|
6
|
+
s.name = "markup_mechanic"
|
|
7
|
+
s.version = "0.1.0"
|
|
8
|
+
s.date = "2013-06-05"
|
|
9
|
+
s.rubyforge_project = "markup_mechanic"
|
|
10
|
+
|
|
11
|
+
s.summary = "Repairs invalid HTML markup"
|
|
12
|
+
s.description = "For use in Rails projects that will correct invalid HTML entered by users"
|
|
13
|
+
|
|
14
|
+
s.authors = ["Ryan Heath"]
|
|
15
|
+
s.email = "ryan@rpheath.com"
|
|
16
|
+
s.homepage = "http://github.com/rpheath/markup_mechanic"
|
|
17
|
+
|
|
18
|
+
s.require_paths = %w[lib]
|
|
19
|
+
|
|
20
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
21
|
+
s.extra_rdoc_files = %w[README.md LICENSE]
|
|
22
|
+
|
|
23
|
+
s.add_dependency("nokogiri", ["~> 1.5"])
|
|
24
|
+
|
|
25
|
+
# = MANIFEST =
|
|
26
|
+
s.files = %w[
|
|
27
|
+
Gemfile
|
|
28
|
+
LICENSE
|
|
29
|
+
README.md
|
|
30
|
+
Rakefile
|
|
31
|
+
lib/markup_mechanic.rb
|
|
32
|
+
lib/markup_mechanic/active_record.rb
|
|
33
|
+
lib/markup_mechanic/base.rb
|
|
34
|
+
lib/markup_mechanic/callbacks.rb
|
|
35
|
+
lib/markup_mechanic/callbacks/before_save.rb
|
|
36
|
+
lib/markup_mechanic/configuration.rb
|
|
37
|
+
lib/markup_mechanic/default_adapter.rb
|
|
38
|
+
lib/markup_mechanic/error.rb
|
|
39
|
+
lib/markup_mechanic/version.rb
|
|
40
|
+
markup_mechanic.gemspec
|
|
41
|
+
test/markup_mechanic_test.rb
|
|
42
|
+
test/test_helper.rb
|
|
43
|
+
]
|
|
44
|
+
# = MANIFEST =
|
|
45
|
+
|
|
46
|
+
s.test_files = s.files.select { |path| path =~ /^test\/.*_test\.rb/ }
|
|
47
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: markup_mechanic
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 27
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 1
|
|
9
|
+
- 0
|
|
10
|
+
version: 0.1.0
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Ryan Heath
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2013-06-05 00:00:00 -04:00
|
|
19
|
+
default_executable:
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
23
|
+
none: false
|
|
24
|
+
requirements:
|
|
25
|
+
- - ~>
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
hash: 5
|
|
28
|
+
segments:
|
|
29
|
+
- 1
|
|
30
|
+
- 5
|
|
31
|
+
version: "1.5"
|
|
32
|
+
version_requirements: *id001
|
|
33
|
+
name: nokogiri
|
|
34
|
+
prerelease: false
|
|
35
|
+
type: :runtime
|
|
36
|
+
description: For use in Rails projects that will correct invalid HTML entered by users
|
|
37
|
+
email: ryan@rpheath.com
|
|
38
|
+
executables: []
|
|
39
|
+
|
|
40
|
+
extensions: []
|
|
41
|
+
|
|
42
|
+
extra_rdoc_files:
|
|
43
|
+
- README.md
|
|
44
|
+
- LICENSE
|
|
45
|
+
files:
|
|
46
|
+
- Gemfile
|
|
47
|
+
- LICENSE
|
|
48
|
+
- README.md
|
|
49
|
+
- Rakefile
|
|
50
|
+
- lib/markup_mechanic.rb
|
|
51
|
+
- lib/markup_mechanic/active_record.rb
|
|
52
|
+
- lib/markup_mechanic/base.rb
|
|
53
|
+
- lib/markup_mechanic/callbacks.rb
|
|
54
|
+
- lib/markup_mechanic/callbacks/before_save.rb
|
|
55
|
+
- lib/markup_mechanic/configuration.rb
|
|
56
|
+
- lib/markup_mechanic/default_adapter.rb
|
|
57
|
+
- lib/markup_mechanic/error.rb
|
|
58
|
+
- lib/markup_mechanic/version.rb
|
|
59
|
+
- markup_mechanic.gemspec
|
|
60
|
+
- test/markup_mechanic_test.rb
|
|
61
|
+
- test/test_helper.rb
|
|
62
|
+
has_rdoc: true
|
|
63
|
+
homepage: http://github.com/rpheath/markup_mechanic
|
|
64
|
+
licenses: []
|
|
65
|
+
|
|
66
|
+
post_install_message:
|
|
67
|
+
rdoc_options:
|
|
68
|
+
- --charset=UTF-8
|
|
69
|
+
require_paths:
|
|
70
|
+
- lib
|
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
|
+
none: false
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
hash: 3
|
|
77
|
+
segments:
|
|
78
|
+
- 0
|
|
79
|
+
version: "0"
|
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ">="
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
hash: 3
|
|
86
|
+
segments:
|
|
87
|
+
- 0
|
|
88
|
+
version: "0"
|
|
89
|
+
requirements: []
|
|
90
|
+
|
|
91
|
+
rubyforge_project: markup_mechanic
|
|
92
|
+
rubygems_version: 1.6.2
|
|
93
|
+
signing_key:
|
|
94
|
+
specification_version: 2
|
|
95
|
+
summary: Repairs invalid HTML markup
|
|
96
|
+
test_files:
|
|
97
|
+
- test/markup_mechanic_test.rb
|