markup_attr 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/.rspec +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +131 -0
- data/README.rdoc +105 -0
- data/Rakefile +5 -0
- data/lib/markup_attr.rb +13 -0
- data/lib/markup_attr/active_record.rb +47 -0
- data/lib/markup_attr/markup.rb +28 -0
- data/lib/markup_attr/sanitize.rb +32 -0
- data/lib/markup_attr/version.rb +8 -0
- data/markup_attr.gemspec +31 -0
- data/spec/fixtures/content.markdown +14 -0
- data/spec/fixtures/content.textile +12 -0
- data/spec/markup_attr_spec.rb +105 -0
- data/spec/schema.rb +15 -0
- data/spec/spec_helper.rb +38 -0
- metadata +184 -0
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format documentation
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
markup_attr (0.1.0)
|
5
|
+
actionpack (~> 3.0)
|
6
|
+
activerecord (~> 3.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
RedCloth (4.2.8)
|
12
|
+
actionmailer (3.1.0)
|
13
|
+
actionpack (= 3.1.0)
|
14
|
+
mail (~> 2.3.0)
|
15
|
+
actionpack (3.1.0)
|
16
|
+
activemodel (= 3.1.0)
|
17
|
+
activesupport (= 3.1.0)
|
18
|
+
builder (~> 3.0.0)
|
19
|
+
erubis (~> 2.7.0)
|
20
|
+
i18n (~> 0.6)
|
21
|
+
rack (~> 1.3.2)
|
22
|
+
rack-cache (~> 1.0.3)
|
23
|
+
rack-mount (~> 0.8.2)
|
24
|
+
rack-test (~> 0.6.1)
|
25
|
+
sprockets (~> 2.0.0)
|
26
|
+
activemodel (3.1.0)
|
27
|
+
activesupport (= 3.1.0)
|
28
|
+
bcrypt-ruby (~> 3.0.0)
|
29
|
+
builder (~> 3.0.0)
|
30
|
+
i18n (~> 0.6)
|
31
|
+
activerecord (3.1.0)
|
32
|
+
activemodel (= 3.1.0)
|
33
|
+
activesupport (= 3.1.0)
|
34
|
+
arel (~> 2.2.1)
|
35
|
+
tzinfo (~> 0.3.29)
|
36
|
+
activeresource (3.1.0)
|
37
|
+
activemodel (= 3.1.0)
|
38
|
+
activesupport (= 3.1.0)
|
39
|
+
activesupport (3.1.0)
|
40
|
+
multi_json (~> 1.0)
|
41
|
+
archive-tar-minitar (0.5.2)
|
42
|
+
arel (2.2.1)
|
43
|
+
bcrypt-ruby (3.0.1)
|
44
|
+
builder (3.0.0)
|
45
|
+
columnize (0.3.4)
|
46
|
+
diff-lcs (1.1.3)
|
47
|
+
erubis (2.7.0)
|
48
|
+
hike (1.2.1)
|
49
|
+
i18n (0.6.0)
|
50
|
+
linecache19 (0.5.12)
|
51
|
+
ruby_core_source (>= 0.1.4)
|
52
|
+
mail (2.3.0)
|
53
|
+
i18n (>= 0.4.0)
|
54
|
+
mime-types (~> 1.16)
|
55
|
+
treetop (~> 1.4.8)
|
56
|
+
mime-types (1.16)
|
57
|
+
multi_json (1.0.3)
|
58
|
+
nokogiri (1.5.0)
|
59
|
+
polyglot (0.3.2)
|
60
|
+
rack (1.3.2)
|
61
|
+
rack-cache (1.0.3)
|
62
|
+
rack (>= 0.4)
|
63
|
+
rack-mount (0.8.3)
|
64
|
+
rack (>= 1.0.0)
|
65
|
+
rack-ssl (1.3.2)
|
66
|
+
rack
|
67
|
+
rack-test (0.6.1)
|
68
|
+
rack (>= 1.0)
|
69
|
+
rails (3.1.0)
|
70
|
+
actionmailer (= 3.1.0)
|
71
|
+
actionpack (= 3.1.0)
|
72
|
+
activerecord (= 3.1.0)
|
73
|
+
activeresource (= 3.1.0)
|
74
|
+
activesupport (= 3.1.0)
|
75
|
+
bundler (~> 1.0)
|
76
|
+
railties (= 3.1.0)
|
77
|
+
railties (3.1.0)
|
78
|
+
actionpack (= 3.1.0)
|
79
|
+
activesupport (= 3.1.0)
|
80
|
+
rack-ssl (~> 1.3.2)
|
81
|
+
rake (>= 0.8.7)
|
82
|
+
rdoc (~> 3.4)
|
83
|
+
thor (~> 0.14.6)
|
84
|
+
rake (0.9.2)
|
85
|
+
rdoc (3.9.4)
|
86
|
+
redcarpet (1.17.2)
|
87
|
+
rspec (2.6.0)
|
88
|
+
rspec-core (~> 2.6.0)
|
89
|
+
rspec-expectations (~> 2.6.0)
|
90
|
+
rspec-mocks (~> 2.6.0)
|
91
|
+
rspec-core (2.6.4)
|
92
|
+
rspec-expectations (2.6.0)
|
93
|
+
diff-lcs (~> 1.1.2)
|
94
|
+
rspec-mocks (2.6.0)
|
95
|
+
ruby-debug-base19 (0.11.25)
|
96
|
+
columnize (>= 0.3.1)
|
97
|
+
linecache19 (>= 0.5.11)
|
98
|
+
ruby_core_source (>= 0.1.4)
|
99
|
+
ruby-debug19 (0.11.6)
|
100
|
+
columnize (>= 0.3.1)
|
101
|
+
linecache19 (>= 0.5.11)
|
102
|
+
ruby-debug-base19 (>= 0.11.19)
|
103
|
+
ruby_core_source (0.1.5)
|
104
|
+
archive-tar-minitar (>= 0.5.2)
|
105
|
+
sprockets (2.0.0)
|
106
|
+
hike (~> 1.2)
|
107
|
+
rack (~> 1.0)
|
108
|
+
tilt (!= 1.3.0, ~> 1.1)
|
109
|
+
sqlite3 (1.3.4)
|
110
|
+
swiss_knife (1.0.0)
|
111
|
+
rails (>= 3.0.0)
|
112
|
+
thor (0.14.6)
|
113
|
+
tilt (1.3.3)
|
114
|
+
treetop (1.4.10)
|
115
|
+
polyglot
|
116
|
+
polyglot (>= 0.3.1)
|
117
|
+
tzinfo (0.3.29)
|
118
|
+
|
119
|
+
PLATFORMS
|
120
|
+
ruby
|
121
|
+
|
122
|
+
DEPENDENCIES
|
123
|
+
RedCloth (~> 4.2)
|
124
|
+
markup_attr!
|
125
|
+
nokogiri (~> 1.5)
|
126
|
+
rake
|
127
|
+
redcarpet (~> 1.17)
|
128
|
+
rspec (~> 2.6)
|
129
|
+
ruby-debug19
|
130
|
+
sqlite3 (~> 1.3)
|
131
|
+
swiss_knife (~> 1.0)
|
data/README.rdoc
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
= Markup Attribute
|
2
|
+
|
3
|
+
Markup Attribute is an ActiveRecord plugin that integrates
|
4
|
+
Markdown, Textile and `sanitize` helper method into a single
|
5
|
+
plugin.
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
Install the plugin with
|
10
|
+
|
11
|
+
gem install markup_attr
|
12
|
+
|
13
|
+
Install the markup language you want to use. For Markdown, install it using
|
14
|
+
|
15
|
+
gem install redcarpet
|
16
|
+
|
17
|
+
If you prefer Textile, install it using
|
18
|
+
|
19
|
+
gem install RedCloth
|
20
|
+
|
21
|
+
== Usage
|
22
|
+
|
23
|
+
All you need to do is call the method +markup_attr+ from your model.
|
24
|
+
|
25
|
+
class Post < ActiveRecord::Base
|
26
|
+
markup_attr :content,
|
27
|
+
:format => :markdown,
|
28
|
+
:tags => %w(p a em strong ul li),
|
29
|
+
:attributes => %w(href)
|
30
|
+
end
|
31
|
+
|
32
|
+
The example above expects the table +posts+ to have two columns: +content+
|
33
|
+
and +formatted_content+. This example is also filtering the allowed tags and
|
34
|
+
attributes. If you don't want to limit what will be saved, just go with
|
35
|
+
something like this
|
36
|
+
|
37
|
+
class Post < ActiveRecord::Base
|
38
|
+
markup_attr :content, :format => :textile
|
39
|
+
end
|
40
|
+
|
41
|
+
To save normalized HTML, if you don't want to use Markdown or Textile, set
|
42
|
+
<tt>:format</tt> to <tt>:html</tt>
|
43
|
+
|
44
|
+
class Post < ActiveRecord::Base
|
45
|
+
markup_attr :content, :format => :html
|
46
|
+
end
|
47
|
+
|
48
|
+
If you don't want the content to be sanitized at all, you can set <tt>:sanitize</tt>
|
49
|
+
to +false+. This is specially useful if you're the editor or something like
|
50
|
+
that.
|
51
|
+
|
52
|
+
class Post < ActiveRecord::Base
|
53
|
+
markup_attr :content,
|
54
|
+
:format => :html,
|
55
|
+
:sanitize => false
|
56
|
+
end
|
57
|
+
|
58
|
+
You can instantiate a markup object any time:
|
59
|
+
|
60
|
+
markup = MarkupAttr::Markup.new(:markdown, 'some text')
|
61
|
+
markup = MarkupAttr::Markup.new(:textile, 'some text')
|
62
|
+
puts markup.to_html
|
63
|
+
|
64
|
+
To sanitize a given HTML, use the +html+ method:
|
65
|
+
|
66
|
+
MarkupAttr::Sanitize.html('<script>alert(document.cookie)</script>')
|
67
|
+
|
68
|
+
MarkupAttr::Sanitize.html('<script>alert(document.cookie)</script>',
|
69
|
+
:tags => %w(p a em strong img ul li ol)
|
70
|
+
)
|
71
|
+
|
72
|
+
MarkupAttr::Sanitize.html('<script>alert(document.cookie)</script>',
|
73
|
+
:attributes => %w(href title alt)
|
74
|
+
)
|
75
|
+
|
76
|
+
To remove all tags, use the `strip_tags` method:
|
77
|
+
|
78
|
+
MarkupAttr::Sanitize.strip_tags('<strong>PWNED</strong>')
|
79
|
+
|
80
|
+
== Maintainer
|
81
|
+
|
82
|
+
* Nando Vieira (http://simplesideias.com.br)
|
83
|
+
|
84
|
+
== License
|
85
|
+
|
86
|
+
(The MIT License)
|
87
|
+
|
88
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
89
|
+
a copy of this software and associated documentation files (the
|
90
|
+
'Software'), to deal in the Software without restriction, including
|
91
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
92
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
93
|
+
permit persons to whom the Software is furnished to do so, subject to
|
94
|
+
the following conditions:
|
95
|
+
|
96
|
+
The above copyright notice and this permission notice shall be
|
97
|
+
included in all copies or substantial portions of the Software.
|
98
|
+
|
99
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
100
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
101
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
102
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
103
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
104
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
105
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/lib/markup_attr.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "singleton"
|
2
|
+
require "active_record"
|
3
|
+
require "action_view"
|
4
|
+
|
5
|
+
module MarkupAttr
|
6
|
+
autoload :Markup, "markup_attr/markup"
|
7
|
+
autoload :Sanitize, "markup_attr/sanitize"
|
8
|
+
autoload :Version, "markup_attr/version"
|
9
|
+
|
10
|
+
require "markup_attr/active_record"
|
11
|
+
end
|
12
|
+
|
13
|
+
ActiveRecord::Base.send(:include, MarkupAttr::ActiveRecord)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MarkupAttr
|
2
|
+
module ActiveRecord
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
extend ClassMethods
|
6
|
+
include InstanceMethods
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :markup_attr_options
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def markup_attr(attribute, options = {})
|
16
|
+
self.markup_attr_options ||= {}
|
17
|
+
self.markup_attr_options[attribute] = options.reverse_merge(
|
18
|
+
:sanitize => true,
|
19
|
+
:attributes => %w[title id href alt href],
|
20
|
+
:tags => %w[p ul ol li strong em a code pre]
|
21
|
+
)
|
22
|
+
|
23
|
+
before_save :convert_content_for_markup_attributes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module InstanceMethods
|
28
|
+
private
|
29
|
+
def convert_content_for_markup_attributes
|
30
|
+
self.class.markup_attr_options.each do |attr_name, options|
|
31
|
+
sanitize_markup(attr_name, options.dup)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def sanitize_markup(attr_name, options)
|
36
|
+
return unless __send__("#{attr_name}_changed?") || __send__("formatted_#{attr_name}").blank?
|
37
|
+
|
38
|
+
format = options.delete(:format)
|
39
|
+
|
40
|
+
text = __send__(attr_name).to_s
|
41
|
+
text = MarkupAttr::Markup.new(format, text).to_html unless format == :html
|
42
|
+
text = MarkupAttr::Sanitize.html(text, options) if options[:sanitize]
|
43
|
+
write_attribute("formatted_#{attr_name}", text)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module MarkupAttr
|
2
|
+
class Markup
|
3
|
+
attr_accessor :markup
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :markdown_processor
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(format, text)
|
10
|
+
case format
|
11
|
+
when :markdown
|
12
|
+
@markup = (self.class.markdown_processor || default_markdown_processor).new(text)
|
13
|
+
when :textile
|
14
|
+
@markup = RedCloth.new(text)
|
15
|
+
else
|
16
|
+
raise ArgumentError, "expected format to be :textile or :markdown; received #{format.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_markdown_processor
|
21
|
+
Redcarpet
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_html
|
25
|
+
@markup.to_html
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MarkupAttr
|
2
|
+
# Use ActionView sanitizer class to strip out HTML
|
3
|
+
# in simple contained class.
|
4
|
+
#
|
5
|
+
class Sanitize
|
6
|
+
include Singleton
|
7
|
+
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
8
|
+
include ActionView::Helpers::SanitizeHelper
|
9
|
+
|
10
|
+
# Strip all html.
|
11
|
+
#
|
12
|
+
def self.strip_tags(text)
|
13
|
+
instance.strip_tags(text)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Strip html from text.
|
17
|
+
# You can specify allowed tags and attributes by setting
|
18
|
+
# the options <tt>:tags</tt> and <tt>:attributes</tt>.
|
19
|
+
#
|
20
|
+
# Sanitize.html(text, {
|
21
|
+
# :tags => %w[a li p ul ol code pre em strong],
|
22
|
+
# :attributes => %w[href]
|
23
|
+
# })
|
24
|
+
#
|
25
|
+
# Setting <tt>:tags</tt> and <tt>:attributes</tt>
|
26
|
+
# to +nil+ will accept everything.
|
27
|
+
#
|
28
|
+
def self.html(text, options = {})
|
29
|
+
instance.sanitize(text, options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/markup_attr.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "markup_attr/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "markup_attr"
|
7
|
+
s.version = MarkupAttr::Version::STRING
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Nando Vieira"]
|
10
|
+
s.email = ["fnando.vieira@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/markup_attr"
|
12
|
+
s.summary = "This ActiveRecord plugin saves formatted content (Markdown, Textile, HTML) after normalizing it."
|
13
|
+
s.description = s.summary
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_dependency "activerecord", "~> 3.0"
|
21
|
+
s.add_dependency "actionpack", "~> 3.0"
|
22
|
+
|
23
|
+
s.add_development_dependency "nokogiri", "~> 1.5"
|
24
|
+
s.add_development_dependency "redcarpet" , "~> 1.17"
|
25
|
+
s.add_development_dependency "RedCloth" , "~> 4.2"
|
26
|
+
s.add_development_dependency "rake"
|
27
|
+
s.add_development_dependency "rspec" , "~> 2.6"
|
28
|
+
s.add_development_dependency "sqlite3" , "~> 1.3"
|
29
|
+
s.add_development_dependency "swiss_knife" , "~> 1.0"
|
30
|
+
s.add_development_dependency "ruby-debug19"
|
31
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe MarkupAttr do
|
4
|
+
let(:markdown) { File.read(File.dirname(__FILE__) + "/fixtures/content.markdown") }
|
5
|
+
let(:textile) { File.read(File.dirname(__FILE__) + "/fixtures/content.textile") }
|
6
|
+
|
7
|
+
it "sets class methods" do
|
8
|
+
Post.should respond_to(:markup_attr)
|
9
|
+
Post.should respond_to(:markup_attr_options)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "generates formatted content" do
|
13
|
+
post = create_post
|
14
|
+
post.formatted_content.should_not be_blank
|
15
|
+
post.formatted_excerpt.should_not be_blank
|
16
|
+
end
|
17
|
+
|
18
|
+
it "formats content using markdown" do
|
19
|
+
post = create_post(:content => markdown)
|
20
|
+
text = post.formatted_content
|
21
|
+
|
22
|
+
text.should have_tag("strong", "formatted")
|
23
|
+
text.should have_tag("em", "text")
|
24
|
+
text.should have_tag("a[href='http://example.com']", "http://example.com")
|
25
|
+
text.should have_tag("ul", 1)
|
26
|
+
text.should have_tag("p", 4)
|
27
|
+
|
28
|
+
text.should_not have_tag("h1", "Some title")
|
29
|
+
text.should_not have_tag("script")
|
30
|
+
text.should_not have_tag("a[title=Example]")
|
31
|
+
text.should_not have_tag("img")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "formats content using textile" do
|
35
|
+
post = create_comment(:content => textile)
|
36
|
+
text = post.formatted_content
|
37
|
+
|
38
|
+
text.should have_tag("strong", "formatted")
|
39
|
+
text.should have_tag("em", "text")
|
40
|
+
text.should have_tag("a[href='http://example.com']", "http://example.com")
|
41
|
+
text.should have_tag("ul", 1)
|
42
|
+
text.should have_tag("p", 4)
|
43
|
+
|
44
|
+
text.should_not have_tag("h1", "Some title")
|
45
|
+
text.should_not have_tag("script")
|
46
|
+
text.should_not have_tag("a[title=Example]")
|
47
|
+
text.should_not have_tag("img")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "keeps content when format is :html" do
|
51
|
+
post = create_post(:excerpt => "<p>some text</p>")
|
52
|
+
|
53
|
+
Markdown.stub :new => mock("content").as_null_object
|
54
|
+
Markdown.should_not_receive(:new).with(:html, post.excerpt)
|
55
|
+
|
56
|
+
text = post.formatted_excerpt
|
57
|
+
text.should have_tag("p", /some text/)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "skips parsing when attribute hasn't changed" do
|
61
|
+
post = create_post
|
62
|
+
Markdown.should_not_receive(:new)
|
63
|
+
post.save
|
64
|
+
end
|
65
|
+
|
66
|
+
it "parses content when attribute has changed" do
|
67
|
+
post = create_post
|
68
|
+
post.content = "Check this out: <http://example.com> "
|
69
|
+
post.save
|
70
|
+
post.formatted_content.should have_tag("a[href='http://example.com']", "http://example.com")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "parses content when formatted attribute is blank" do
|
74
|
+
post = create_post
|
75
|
+
post.formatted_content = ""
|
76
|
+
post.save
|
77
|
+
post.formatted_content.should_not be_blank
|
78
|
+
end
|
79
|
+
|
80
|
+
it "skips sanitize" do
|
81
|
+
MarkupAttr::Sanitize.should_not_receive(:html)
|
82
|
+
create_task
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
def create_post(options={})
|
87
|
+
Post.create({
|
88
|
+
:title => "Some title",
|
89
|
+
:content => "some content",
|
90
|
+
:excerpt => "some content"
|
91
|
+
}.merge(options))
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_comment(options={})
|
95
|
+
Comment.create({
|
96
|
+
:content => "some content"
|
97
|
+
}.merge(options))
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_task(options={})
|
101
|
+
Task.create({
|
102
|
+
:content => "some content"
|
103
|
+
}.merge(options))
|
104
|
+
end
|
105
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
create_table :posts do |t|
|
3
|
+
t.string :title
|
4
|
+
t.text :content, :formatted_content
|
5
|
+
t.text :excerpt, :formatted_excerpt
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :comments do |t|
|
9
|
+
t.text :content, :formatted_content
|
10
|
+
end
|
11
|
+
|
12
|
+
create_table :tasks do |t|
|
13
|
+
t.text :content, :formatted_content
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup(:default, :development)
|
3
|
+
Bundler.require
|
4
|
+
|
5
|
+
require "sqlite3"
|
6
|
+
require "redcarpet"
|
7
|
+
require "RedCloth"
|
8
|
+
require "nokogiri"
|
9
|
+
require "swiss_knife/rspec"
|
10
|
+
|
11
|
+
require "markup_attr"
|
12
|
+
|
13
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
14
|
+
|
15
|
+
load("schema.rb")
|
16
|
+
|
17
|
+
class Post < ActiveRecord::Base
|
18
|
+
markup_attr :content,
|
19
|
+
:format => :markdown,
|
20
|
+
:tags => %w[p a em strong ul li],
|
21
|
+
:attributes => %w[href]
|
22
|
+
|
23
|
+
markup_attr :excerpt,
|
24
|
+
:format => :html
|
25
|
+
end
|
26
|
+
|
27
|
+
class Comment < ActiveRecord::Base
|
28
|
+
markup_attr :content,
|
29
|
+
:format => :textile,
|
30
|
+
:tags => %w[p a em strong ul li],
|
31
|
+
:attributes => %w[href]
|
32
|
+
end
|
33
|
+
|
34
|
+
class Task < ActiveRecord::Base
|
35
|
+
markup_attr :content,
|
36
|
+
:format => :textile,
|
37
|
+
:sanitize => false
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: markup_attr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nando Vieira
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-16 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &2154268900 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2154268900
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: actionpack
|
27
|
+
requirement: &2154268400 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2154268400
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: nokogiri
|
38
|
+
requirement: &2154267860 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.5'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2154267860
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: redcarpet
|
49
|
+
requirement: &2154267120 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.17'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2154267120
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: RedCloth
|
60
|
+
requirement: &2154266480 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '4.2'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2154266480
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: &2154266060 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2154266060
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rspec
|
82
|
+
requirement: &2154265500 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '2.6'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *2154265500
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: sqlite3
|
93
|
+
requirement: &2154264960 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '1.3'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *2154264960
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: swiss_knife
|
104
|
+
requirement: &2154264460 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *2154264460
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: ruby-debug19
|
115
|
+
requirement: &2154264040 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *2154264040
|
124
|
+
description: This ActiveRecord plugin saves formatted content (Markdown, Textile,
|
125
|
+
HTML) after normalizing it.
|
126
|
+
email:
|
127
|
+
- fnando.vieira@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- .rspec
|
133
|
+
- Gemfile
|
134
|
+
- Gemfile.lock
|
135
|
+
- README.rdoc
|
136
|
+
- Rakefile
|
137
|
+
- lib/markup_attr.rb
|
138
|
+
- lib/markup_attr/active_record.rb
|
139
|
+
- lib/markup_attr/markup.rb
|
140
|
+
- lib/markup_attr/sanitize.rb
|
141
|
+
- lib/markup_attr/version.rb
|
142
|
+
- markup_attr.gemspec
|
143
|
+
- spec/fixtures/content.markdown
|
144
|
+
- spec/fixtures/content.textile
|
145
|
+
- spec/markup_attr_spec.rb
|
146
|
+
- spec/schema.rb
|
147
|
+
- spec/spec_helper.rb
|
148
|
+
homepage: http://rubygems.org/gems/markup_attr
|
149
|
+
licenses: []
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
none: false
|
156
|
+
requirements:
|
157
|
+
- - ! '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
segments:
|
161
|
+
- 0
|
162
|
+
hash: 1516787436419528243
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
hash: 1516787436419528243
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 1.8.10
|
175
|
+
signing_key:
|
176
|
+
specification_version: 3
|
177
|
+
summary: This ActiveRecord plugin saves formatted content (Markdown, Textile, HTML)
|
178
|
+
after normalizing it.
|
179
|
+
test_files:
|
180
|
+
- spec/fixtures/content.markdown
|
181
|
+
- spec/fixtures/content.textile
|
182
|
+
- spec/markup_attr_spec.rb
|
183
|
+
- spec/schema.rb
|
184
|
+
- spec/spec_helper.rb
|