extended_markdownizer 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ docs/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use ruby-1.9.2@markdownizer
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in markdownizer.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ markdownizer (0.3.5)
5
+ activerecord (>= 3.0.3)
6
+ coderay
7
+ rdiscount
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activemodel (3.0.4)
13
+ activesupport (= 3.0.4)
14
+ builder (~> 2.1.2)
15
+ i18n (~> 0.4)
16
+ activerecord (3.0.4)
17
+ activemodel (= 3.0.4)
18
+ activesupport (= 3.0.4)
19
+ arel (~> 2.0.2)
20
+ tzinfo (~> 0.3.23)
21
+ activesupport (3.0.4)
22
+ arel (2.0.8)
23
+ builder (2.1.2)
24
+ coderay (0.9.7)
25
+ diff-lcs (1.1.2)
26
+ git (1.2.5)
27
+ i18n (0.5.0)
28
+ mustache (0.12.0)
29
+ pygments (0.0.1.a)
30
+ rdiscount (1.6.8)
31
+ rocco (0.5)
32
+ mustache
33
+ rdiscount
34
+ rspec (2.5.0)
35
+ rspec-core (~> 2.5.0)
36
+ rspec-expectations (~> 2.5.0)
37
+ rspec-mocks (~> 2.5.0)
38
+ rspec-core (2.5.1)
39
+ rspec-expectations (2.5.0)
40
+ diff-lcs (~> 1.1.2)
41
+ rspec-mocks (2.5.0)
42
+ tzinfo (0.3.24)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ activerecord (>= 3.0.3)
49
+ coderay
50
+ git
51
+ markdownizer!
52
+ pygments
53
+ rdiscount
54
+ rocco
55
+ rspec (~> 2.5.0)
data/Rakefile ADDED
@@ -0,0 +1,65 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ # Bring in Rocco tasks
5
+ require 'rocco/tasks'
6
+ require 'rake/clean'
7
+ Rocco::make 'docs/', 'lib/extended_markdownizer.rb'
8
+
9
+ desc 'Build extended_markdownizer docs'
10
+ task :docs => :rocco
11
+ directory 'docs/'
12
+
13
+ desc 'Build docs and open in browser for the reading'
14
+ task :read => :docs do
15
+ sh 'open docs/lib/rocco.html'
16
+ end
17
+
18
+ # Make index.html a copy of extended_markdownizer.html
19
+ file 'docs/index.html' => ['docs/lib/extended_markdownizer.html'] do |f|
20
+ cp 'docs/lib/extended_markdownizer.html', 'docs/index.html', :preserve => true
21
+ end
22
+ task :docs => 'docs/index.html'
23
+ CLEAN.include 'docs/index.html'
24
+
25
+ # Alias for docs task
26
+ task :doc => :docs
27
+
28
+ # GITHUB PAGES ===============================================================
29
+
30
+ site = 'docs'
31
+ source_branch = 'master'
32
+ deploy_branch = 'gh-pages'
33
+
34
+ desc "generate and deploy website to github user pages"
35
+ multitask :pages do
36
+ puts ">>> Deploying #{deploy_branch} branch to Github Pages <<<"
37
+ require 'git'
38
+ repo = Git.open('.')
39
+ puts "\n>>> Checking out #{deploy_branch} branch <<<\n"
40
+ repo.branch("#{deploy_branch}").checkout
41
+ (Dir["*"] - [site]).each { |f| rm_rf(f) }
42
+ Dir["#{site}/*"].each {|f| mv(f, "index.html")}
43
+ rm_rf(site)
44
+ puts "\n>>> Moving generated site files <<<\n"
45
+ Dir["**/*"].each {|f| repo.add(f) }
46
+ repo.status.deleted.each {|f, s| repo.remove(f)}
47
+ puts "\n>>> Commiting: Site updated at #{Time.now.utc} <<<\n"
48
+ message = ENV["MESSAGE"] || "Site updated at #{Time.now.utc}"
49
+ repo.commit(message)
50
+ puts "\n>>> Pushing generated site to #{deploy_branch} branch <<<\n"
51
+ repo.push
52
+ puts "\n>>> Github Pages deploy complete <<<\n"
53
+ repo.branch("#{source_branch}").checkout
54
+ end
55
+
56
+ # TESTS =====================================================================
57
+
58
+ require 'rspec/core'
59
+ require 'rspec/core/rake_task'
60
+ RSpec::Core::RakeTask.new(:spec) do |spec|
61
+ spec.pattern = FileList['spec/**/*_spec.rb']
62
+ end
63
+
64
+ task :default => :spec
65
+ task :test => [:spec]
data/Readme.md ADDED
@@ -0,0 +1,78 @@
1
+ #Extended Markdownizer
2
+
3
+ A simple gem for Rails 3 to render some ActiveRecord text field as Markdown!
4
+
5
+ Based on [Markdownizer](https://github.com/codegram/markdownizer), by [Txus](https://github.com/txus).
6
+
7
+ It mixes CodeRay and RDiscount to give you awesome code highlighting :)
8
+
9
+ Besides that:
10
+
11
+ * Converts Youtube urls into embedded videos.
12
+ * Converts Vimeo urls into embedded videos.
13
+ * Detects urls and converts into anchors.
14
+
15
+ You can check the generated Rocco documentation on the [project
16
+ page](http://josem.github.com/extended_markdownizer/).
17
+
18
+ ##Install
19
+
20
+ In your Gemfile:
21
+
22
+ gem 'extended_markdownizer'
23
+
24
+ If you want code highlighting, you should run this generator too:
25
+
26
+ rails generate extended_markdownizer:install
27
+
28
+ This will place a extended_markdownizer.css file in your `public/stylesheets` folder.
29
+ You will have to require it manually in your layouts, or through `jammit`, or
30
+ whatever.
31
+
32
+ ## Usage
33
+
34
+ In your model, let's say, Post:
35
+
36
+ class Post < ActiveRecord::Base
37
+ extended_markdownize! :body
38
+ # In this case we want to treat :body as markdown.
39
+ # You can pass an options hash to the code renderer, such as:
40
+ #
41
+ # extended_markdownize! :body, :line_numbers => :table
42
+ #
43
+ end
44
+
45
+ Extended Markdownizer needs an additional field (`:rendered_body`), which you should
46
+ generate in a migration. (If the attribute was `:some_other_field`, it would need
47
+ `:rendered_some_other_field`!) All these fields should have the type `:text`.
48
+
49
+ You save your posts with markdown text like this:
50
+
51
+ Post.create body: """
52
+ # My H1 title
53
+ Markdown is awesome!
54
+ ## Some H2 title...
55
+
56
+ {% code ruby %}
57
+ {% caption 'This caption will become an h5 and also a property of the enclosing div' %}
58
+ {% highlight [1,2,3] %} <- this will highlight lines 1, 2 and 3 (it accepts a Range as well)
59
+
60
+ # All this code will be highlighted properly! :)
61
+ def my_method(*my_args)
62
+ something do
63
+ . . .
64
+ end
65
+ end
66
+
67
+ {% endcode %}
68
+ """
69
+
70
+ And then, in your view you just have to call `<%= raw @post.rendered_body %>` :)
71
+
72
+ ##TODO
73
+ * Update specs
74
+ * Improve docs
75
+
76
+ ## Copyright
77
+ Markdown: Copyright (c) 2011 Codegram. See LICENSE for details.
78
+ Extended Markdown: Copyright (c) 2011 José M. Gilgado
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "extended_markdownizer/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "extended_markdownizer"
7
+ s.version = ExtendedMarkdownizer::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["José M. Gilgado"]
10
+ s.email = ["jm.gilgado@gmail.com"]
11
+ s.homepage = "https://github.com/josem/extended_markdownizer"
12
+ s.summary = %q{Render any text as markdown, with code highlighting and all!}
13
+ s.description = %q{Render any text as markdown, with code highlighting, url detection and conversion of youtube/vimeo urls into embedded videos}
14
+
15
+ s.rubyforge_project = "extended_markdownizer"
16
+
17
+ s.add_runtime_dependency 'activerecord', '>= 3.0.3'
18
+ s.add_runtime_dependency 'rdiscount'
19
+ s.add_runtime_dependency 'coderay'
20
+
21
+ s.add_development_dependency 'rocco'
22
+ s.add_development_dependency 'git'
23
+ s.add_development_dependency 'rspec', '~> 2.5.0'
24
+
25
+ s.files = `git ls-files`.split("\n")
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
28
+ s.require_paths = ["lib"]
29
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'extended_markdownizer'
@@ -0,0 +1,242 @@
1
+ # **ExtendedMarkdownizer** is a simple solution to a simple problem.
2
+ #
3
+ # It is a lightweight Rails 3 gem which enhances any ActiveRecord model with a
4
+ # singleton `markdownize!` method, which makes any text attribute renderable as
5
+ # Markdown. It mixes CodeRay and RDiscount to give you awesome code
6
+ # highlighting, too!
7
+ #
8
+ # If you have any suggestion regarding new features, Check out the [Github repo][gh],
9
+ # fork it and submit a nice pull request :)
10
+ #
11
+
12
+ #### Install ExtendedMarkdownizer
13
+
14
+ # Get ExtendedMarkdownizer in your Rails 3 app through your Gemfile:
15
+ #
16
+ # gem 'extended_markdownizer'
17
+ #
18
+ # If you don't use Bundler, you can alternatively install ExtendedMarkdownizer with
19
+ # Rubygems:
20
+ #
21
+ # gem install extended_markdownizer
22
+ #
23
+ # If you want code highlighting, you should run this generator too:
24
+ #
25
+ # rails generate extended_markdownizer:install
26
+ #
27
+ # This will place a `markdownizer.css` file in your `public/stylesheets`
28
+ # folder. You will have to require it manually in your layouts, or through
29
+ # `jammit`, or whatever.
30
+ #
31
+ # [gh]: http://github.com/josem/markdownizer
32
+
33
+ #### Usage
34
+
35
+ # In your model, let's say, `Post`:
36
+ #
37
+ # class Post < ActiveRecord::Base
38
+ # # In this case we want to treat :body as markdown
39
+ # # This will require `body` and `rendered_body` fields
40
+ # # to exist previously (otherwise it will raise an error).
41
+ # markdownize! :body
42
+ # end
43
+ #
44
+ # Then you can create a `Post` using Markdown syntax, like this:
45
+ #
46
+ # Post.create body: """
47
+ # # My H1 title
48
+ # Markdown is awesome!
49
+ # ## Some H2 title...
50
+ #
51
+ # {% code ruby %}
52
+ #
53
+ # # All this code will be highlighted properly! :)
54
+ # def my_method(*my_args)
55
+ # something do
56
+ # 3 + 4
57
+ # end
58
+ # end
59
+ #
60
+ # {% endcode %}
61
+ # """
62
+ #
63
+ # After that, in your view you just have to call `@post.rendered_body` and,
64
+ # provided you included the generated css in your layout, it will display nice
65
+ # and coloured :)
66
+
67
+ #### Show me the code!
68
+
69
+ # We'll need to include [RDiscount][rd]. This is the Markdown parsing library.
70
+ # Also, [CodeRay][cr] will provide code highlighting. We require `active_record` as
71
+ # well, since we want to extend it with our DSL.
72
+ #
73
+ # [rd]: http://github.com/rtomayko/rdiscount
74
+ # [cr]: http://github.com/rubychan/coderay
75
+ require 'rdiscount'
76
+ require 'coderay'
77
+ require 'active_record' unless defined?(ActiveRecord)
78
+
79
+ module ExtendedMarkdownizer
80
+
81
+ class << self
82
+ # Here we define two helper methods. These will be called from the model to
83
+ # perform the corresponding conversions and parsings.
84
+
85
+ # `ExtendedMarkdownizer.markdown` method converts plain Markdown text to formatted html.
86
+ # To parse the markdown in a coherent hierarchical context, you must provide it
87
+ # with the current hierarchical level of the text to be parsed.
88
+ def markdown(text, hierarchy = 0)
89
+ text.gsub! %r[^(\s*)(#+)(.+)$] do
90
+ $1 << ('#' * hierarchy) << $2 << $3
91
+ end
92
+ text.gsub!("\\#",'#')
93
+ RDiscount.new(text).to_html
94
+ end
95
+
96
+ # `ExtendedMarkdownizer.coderay` method parses a code block delimited from `{% code
97
+ # ruby %}` until `{% endcode %}` and replaces it with appropriate classes for
98
+ # code highlighting. It can take many languages aside from Ruby.
99
+ #
100
+ # With a hash of options you can specify `:line_numbers` (`:table` or `:inline`),
101
+ # and the class of the enclosing div with `:enclosing_class`.
102
+ #
103
+ # It also parses a couple of special idioms:
104
+ #
105
+ # * {% caption 'my caption' %} introduces an h5 before the code and passes
106
+ # the caption to the enclosing div as well.
107
+ #
108
+ # * {% highlight [1,2,3] %} highlights lines 1, 2 and 3. It accepts any
109
+ # Enumerable, so you can also give a Range (1..3).
110
+ #
111
+ def coderay(text, options = {})
112
+ text.gsub(%r[\{% code (\w+?) %\}(.+?)\{% endcode %\}]m) do
113
+ options.delete(:highlight_lines)
114
+ options.delete(:caption)
115
+
116
+ enclosing_class = options[:enclosing_class] || 'markdownizer_code'
117
+
118
+ code, language = $2.strip, $1.strip
119
+
120
+ # Mark comments to avoid conflicts with Header parsing
121
+ code.gsub!(/(#+)/) do
122
+ '\\' + $1
123
+ end
124
+
125
+ code, options, caption = extract_caption_from(code, options)
126
+ code, options = extract_highlights_from(code, options)
127
+
128
+ html_caption = caption ? '<h5>' << caption << '</h5>' : nil
129
+
130
+ "<div class=\"#{enclosing_class}#{caption ? "\" caption=\"#{caption}" : ''}\">" <<
131
+ (html_caption || '') <<
132
+ CodeRay.scan(code, language).div({:css => :class}.merge(options)) <<
133
+ "</div>"
134
+ end
135
+ end
136
+
137
+ # `ExtendedMarkdownizer.urls_into_anchors` method converts the urls in the text into anchors
138
+ def urls_into_anchors(text)
139
+ text.gsub(/^(((http|https):\/\/)?)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/ix) do |url|
140
+ if ($1 != 'http://')
141
+ uri = 'http://' + url
142
+ return "<a target=\"_blank\" href=\"#{uri}\">#{url}</a>"
143
+ else
144
+ return "<a target=\"_blank\" href=\"#{url}\">#{url}</a>"
145
+ end
146
+ end
147
+ end
148
+
149
+ # `ExtendedMarkdownizer.youtube_embedded_videos` method converts the youtube urls into an embedded video
150
+ # Another way to do the same:
151
+ # http://stackoverflow.com/questions/3552228/ruby-on-rails-get-url-string-parameters/3552311#3552311
152
+ def youtube_embedded_videos(text)
153
+ text.gsub(/^(http:\/\/)?(www.)?youtube.com\/watch\?v=([a-zA-Z0-9_]+)(&(.*))?$/ix) do |url|
154
+ iframe = '<iframe width="560" height="349" src="http://www.youtube.com/embed/' + $3.to_s + '?rel=0" frameborder="0" allowfullscreen></iframe>'
155
+ return iframe
156
+ end
157
+ end
158
+
159
+ # `ExtendedMarkdownizer.vimeo_embedded_videos` method converts the vimeo urls into an embedded video
160
+ def vimeo_embedded_videos(text)
161
+ text.gsub(/^(http:\/\/)?(www.)?vimeo.com\/([a-zA-Z0-9_]+)$/ix) do |url|
162
+ iframe = '<iframe src="http://player.vimeo.com/video/'+ $3.to_s + '?byline=0&amp;portrait=0" width="560" height="315" frameborder="0"></iframe>'
163
+ return iframe
164
+ end
165
+ end
166
+
167
+ private
168
+
169
+ def extract_caption_from(code, options)
170
+ caption = nil
171
+ code.gsub!(%r[\{% caption '([^']+)' %\}]) do
172
+ options.merge!({:caption => $1.strip}) if $1
173
+ caption = $1.strip
174
+ ''
175
+ end
176
+ [code.strip, options, caption]
177
+ end
178
+
179
+ # FIXME: Find a safer way to eval code, MY LORD
180
+ def extract_highlights_from(code, options)
181
+ code.gsub!(%r[\{% highlight (.+) %\}]) do
182
+ enumerable = eval($1.strip)
183
+ enumerable = (Enumerable === enumerable)? enumerable : nil
184
+ options.merge!({:highlight_lines => enumerable}) if enumerable
185
+ ''
186
+ end
187
+ [code.strip, options]
188
+ end
189
+
190
+ end
191
+
192
+ #### Public interface
193
+
194
+ # The ExtendedMarkdownizer DSL is the public interface of the gem, and can be called
195
+ # from any ActiveRecord model.
196
+ module DSL
197
+
198
+ # Calling `extended_markdownize! :attribute` (where `:attribute` can be any database
199
+ # attribute with type `text`) will treat this field as Markdown.
200
+ # You can pass an `options` hash for CodeRay. An example option would be:
201
+ #
202
+ # * `:line_numbers => :table` (or `:inline`)
203
+ #
204
+ # You can check other available options in CodeRay's documentation.
205
+ def extended_markdownize! attribute, options = {}
206
+ # Check that both `:attribute` and `:rendered_attribute` columns exist.
207
+ # If they don't, it raises an error indicating that the user should generate
208
+ # a migration.
209
+ unless self.column_names.include?(attribute.to_s) &&
210
+ self.column_names.include?("rendered_#{attribute}")
211
+ raise "#{self.name} doesn't have required attributes :#{attribute} and :rendered_#{attribute}\nPlease generate a migration to add these attributes -- both should have type :text."
212
+ end
213
+
214
+ # The `:hierarchy` option tells ExtendedMarkdownizer the smallest header tag that
215
+ # precedes the Markdown text. If you have a blogpost with an H1 (title) and
216
+ # an H2 (some kind of tagline), then your hierarchy is 2, and the biggest
217
+ # header found the markdown text will be translated directly to an H3. This
218
+ # allows for semantical coherence within the context where the markdown text
219
+ # is to be introduced.
220
+ hierarchy = options.delete(:hierarchy) || 0
221
+
222
+ # Create a `before_save` callback which will convert plain text to
223
+ # Markdownized html every time the model is saved.
224
+ self.before_save :"render_#{attribute}"
225
+
226
+ # Define the converter method, which will assign the rendered html to the
227
+ # `:rendered_attribute` field.
228
+ define_method :"render_#{attribute}" do
229
+ processed_attribute = ExtendedMarkdownizer.youtube_embedded_videos(self.send(attribute))
230
+ processed_attribute = ExtendedMarkdownizer.vimeo_embedded_videos(processed_attribute)
231
+ processed_attribute = ExtendedMarkdownizer.urls_into_anchors(processed_attribute)
232
+ self.send(:"rendered_#{attribute}=", ExtendedMarkdownizer.markdown(ExtendedMarkdownizer.coderay(processed_attribute, options), hierarchy))
233
+ end
234
+ end
235
+ end
236
+
237
+ end
238
+
239
+ # Finally, make our DSL available to any class inheriting from ActiveRecord::Base.
240
+ ActiveRecord::Base.send(:extend, ExtendedMarkdownizer::DSL)
241
+
242
+ # And that's it!
@@ -0,0 +1,3 @@
1
+ module ExtendedMarkdownizer
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,15 @@
1
+ require 'rails/generators'
2
+
3
+ module ExtendedMarkdownizer
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ desc "Copy ExtendedMarkdownizer code highlighting stylesheets"
7
+
8
+ source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
9
+
10
+ def copy_stylesheet_file
11
+ copy_file 'coderay.css', 'public/stylesheets/extended_markdownizer.css'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,131 @@
1
+ .CodeRay {
2
+ background-color: #f8f8f8;
3
+ border: 1px solid silver;
4
+ font-family: 'Courier New', 'Terminal', monospace;
5
+ color: #000;
6
+ }
7
+ .CodeRay pre { margin: 0px }
8
+
9
+ div.CodeRay { }
10
+
11
+ span.CodeRay { white-space: pre; border: 0px; padding: 2px }
12
+
13
+ table.CodeRay { border-collapse: collapse; width: 100%; padding: 2px }
14
+ table.CodeRay td { padding: 2px 4px; vertical-align: top }
15
+
16
+ .CodeRay .line_numbers, .CodeRay .no {
17
+ background-color: #def;
18
+ color: gray;
19
+ text-align: right;
20
+ }
21
+ .CodeRay .line_numbers tt { font-weight: bold }
22
+ .CodeRay .line_numbers .highlighted { color: red }
23
+ .CodeRay .line { display: block; float: left; width: 100%; }
24
+ .CodeRay .no { padding: 0px 4px }
25
+ .CodeRay .code { width: 100% }
26
+
27
+ ol.CodeRay { font-size: 10pt }
28
+ ol.CodeRay li { white-space: pre }
29
+
30
+ .CodeRay .code pre { overflow: auto }
31
+
32
+ .CodeRay .debug { color:white ! important; background:blue ! important; }
33
+
34
+ .CodeRay .af { color:#00C }
35
+ .CodeRay .an { color:#007 }
36
+ .CodeRay .at { color:#f08 }
37
+ .CodeRay .av { color:#700 }
38
+ .CodeRay .aw { color:#C00 }
39
+ .CodeRay .bi { color:#509; font-weight:bold }
40
+ .CodeRay .c { color:#888; }
41
+
42
+ .CodeRay .ch { color:#04D }
43
+ .CodeRay .ch .k { color:#04D }
44
+ .CodeRay .ch .dl { color:#039 }
45
+
46
+ .CodeRay .cl { color:#B06; font-weight:bold }
47
+ .CodeRay .cm { color:#A08; font-weight:bold }
48
+ .CodeRay .co { color:#036; font-weight:bold }
49
+ .CodeRay .cr { color:#0A0 }
50
+ .CodeRay .cv { color:#369 }
51
+ .CodeRay .de { color:#B0B; }
52
+ .CodeRay .df { color:#099; font-weight:bold }
53
+ .CodeRay .di { color:#088; font-weight:bold }
54
+ .CodeRay .dl { color:black }
55
+ .CodeRay .do { color:#970 }
56
+ .CodeRay .dt { color:#34b }
57
+ .CodeRay .ds { color:#D42; font-weight:bold }
58
+ .CodeRay .e { color:#666; font-weight:bold }
59
+ .CodeRay .en { color:#800; font-weight:bold }
60
+ .CodeRay .er { color:#F00; background-color:#FAA }
61
+ .CodeRay .ex { color:#C00; font-weight:bold }
62
+ .CodeRay .fl { color:#60E; font-weight:bold }
63
+ .CodeRay .fu { color:#06B; font-weight:bold }
64
+ .CodeRay .gv { color:#d70; font-weight:bold }
65
+ .CodeRay .hx { color:#058; font-weight:bold }
66
+ .CodeRay .i { color:#00D; font-weight:bold }
67
+ .CodeRay .ic { color:#B44; font-weight:bold }
68
+
69
+ .CodeRay .il { background: #ddd; color: black }
70
+ .CodeRay .il .il { background: #ccc }
71
+ .CodeRay .il .il .il { background: #bbb }
72
+ .CodeRay .il .idl { background: #ddd; font-weight: bold; color: #666 }
73
+ .CodeRay .idl { background-color: #bbb; font-weight: bold; color: #666; }
74
+
75
+ .CodeRay .im { color:#f00; }
76
+ .CodeRay .in { color:#B2B; font-weight:bold }
77
+ .CodeRay .iv { color:#33B }
78
+ .CodeRay .la { color:#970; font-weight:bold }
79
+ .CodeRay .lv { color:#963 }
80
+ .CodeRay .oc { color:#40E; font-weight:bold }
81
+ .CodeRay .of { color:#000; font-weight:bold }
82
+ .CodeRay .op { }
83
+ .CodeRay .pc { color:#038; font-weight:bold }
84
+ .CodeRay .pd { color:#369; font-weight:bold }
85
+ .CodeRay .pp { color:#579; }
86
+ .CodeRay .ps { color:#00C; font-weight:bold }
87
+ .CodeRay .pt { color:#074; font-weight:bold }
88
+ .CodeRay .r, .kw { color:#080; font-weight:bold }
89
+
90
+ .CodeRay .ke { color: #808; }
91
+ .CodeRay .ke .dl { color: #606; }
92
+ .CodeRay .ke .ch { color: #80f; }
93
+ .CodeRay .vl { color: #088; }
94
+
95
+ .CodeRay .rx { background-color:#fff0ff }
96
+ .CodeRay .rx .k { color:#808 }
97
+ .CodeRay .rx .dl { color:#404 }
98
+ .CodeRay .rx .mod { color:#C2C }
99
+ .CodeRay .rx .fu { color:#404; font-weight: bold }
100
+
101
+ .CodeRay .s { background-color:#fff0f0; color: #D20; }
102
+ .CodeRay .s .s { background-color:#ffe0e0 }
103
+ .CodeRay .s .s .s { background-color:#ffd0d0 }
104
+ .CodeRay .s .k { }
105
+ .CodeRay .s .ch { color: #b0b; }
106
+ .CodeRay .s .dl { color: #710; }
107
+
108
+ .CodeRay .sh { background-color:#f0fff0; color:#2B2 }
109
+ .CodeRay .sh .k { }
110
+ .CodeRay .sh .dl { color:#161 }
111
+
112
+ .CodeRay .sy { color:#A60 }
113
+ .CodeRay .sy .k { color:#A60 }
114
+ .CodeRay .sy .dl { color:#630 }
115
+
116
+ .CodeRay .ta { color:#070 }
117
+ .CodeRay .tf { color:#070; font-weight:bold }
118
+ .CodeRay .ts { color:#D70; font-weight:bold }
119
+ .CodeRay .ty { color:#339; font-weight:bold }
120
+ .CodeRay .v { color:#036 }
121
+ .CodeRay .xt { color:#444 }
122
+
123
+ .CodeRay .ins { background: #afa; }
124
+ .CodeRay .del { background: #faa; }
125
+ .CodeRay .chg { color: #aaf; background: #007; }
126
+ .CodeRay .head { color: #f8f; background: #505 }
127
+
128
+ .CodeRay .ins .ins { color: #080; font-weight:bold }
129
+ .CodeRay .del .del { color: #800; font-weight:bold }
130
+ .CodeRay .chg .chg { color: #66f; }
131
+ .CodeRay .head .head { color: #f4f; }
@@ -0,0 +1,230 @@
1
+ require 'spec_helper'
2
+
3
+ describe Markdownizer do
4
+ describe ".markdown(text)" do
5
+ let(:text) { "#My markdown text"}
6
+ context 'when the hierarchy is 0' do
7
+ it 'calls RDiscount to markdownize the text' do
8
+ rdiscount, html_markdown = double(:rdiscount), double(:html_markdown)
9
+
10
+ RDiscount.should_receive(:new).with(text).and_return rdiscount
11
+ rdiscount.should_receive(:to_html).and_return html_markdown
12
+
13
+ subject.markdown(text).should == html_markdown
14
+ end
15
+ end
16
+ context 'when the hierarchy is 2' do
17
+ it "converts all headers into 2 levels deeper" do
18
+ my_text = """
19
+ #This is an H1
20
+ ##This is an H2
21
+ ###This is an H3
22
+ """
23
+ result = double :result, :to_html => true
24
+ RDiscount.should_receive(:new).with do |t|
25
+ t.should =~ /###This is an H1/
26
+ t.should =~ /####This is an H2/
27
+ t.should =~ /#####This is an H3/
28
+ end.and_return result
29
+ subject.markdown(my_text, 2)
30
+ end
31
+ it 'still does not convert anything that is not a header' do
32
+ my_text = """
33
+ #This is an H1
34
+ I am talking about my #method
35
+ {% code ruby %}
36
+ \\#My comment
37
+ {% endcode %}
38
+ ###This is an H3
39
+ """
40
+ result = double :result, :to_html => true
41
+ RDiscount.should_receive(:new).with do |t|
42
+ t.should =~ /###This is an H1/
43
+ t.should =~ /#method/
44
+ t.should_not =~ /###method/
45
+ t.should =~ /#My comment/
46
+ t.should_not =~ /###My comment/
47
+ t.should_not =~ /\\#My comment/
48
+ t.should =~ /#####This is an H3/
49
+ end.and_return result
50
+ subject.markdown(my_text, 2)
51
+ end
52
+ end
53
+ end
54
+ describe ".coderay(text)" do
55
+ let(:text) { """
56
+ #My markdown text
57
+
58
+ {% code ruby %}
59
+ def function(*args)
60
+ puts 'result'
61
+ end
62
+ {% endcode %}
63
+
64
+ """
65
+ }
66
+ let(:text_with_caption) { """
67
+ #My markdown text
68
+
69
+ {% code ruby %}
70
+ {% caption 'This will become an h5' %}
71
+ def function(*args)
72
+ puts 'result'
73
+ end
74
+ {% endcode %}
75
+
76
+ """
77
+ }
78
+ let(:text_with_weird_caption) { """
79
+ #My markdown text
80
+
81
+ {% code ruby %}
82
+ {% caption 'This will become an h5, with some/strange.characters\yo' %}
83
+ def function(*args)
84
+ puts 'result'
85
+ end
86
+ {% endcode %}
87
+
88
+ """
89
+ }
90
+ let(:text_with_array_highlights) { """
91
+ #My markdown text
92
+
93
+ {% code ruby %}
94
+ {% highlight [1,2,3] %}
95
+ def function(*args)
96
+ puts 'result'
97
+ end
98
+ {% endcode %}
99
+
100
+ """
101
+ }
102
+ let(:text_with_range_highlights) { """
103
+ #My markdown text
104
+
105
+ {% code ruby %}
106
+ {% highlight (1..3) %}
107
+ def function(*args)
108
+ puts 'result'
109
+ end
110
+ {% endcode %}
111
+
112
+ """
113
+ }
114
+ let(:text_with_comments) { """
115
+ #My markdown text
116
+
117
+ {% code ruby %}
118
+ #My comment
119
+ # My other comment
120
+ def function(*args)
121
+ puts 'result'
122
+ end
123
+ {% endcode %}
124
+
125
+ """
126
+ }
127
+
128
+ it 'calls CodeRay to parse the code inside {% code ruby %} blocks' do
129
+ scanned_code, html_code = double(:scanned_code), double(:html_code)
130
+
131
+ CodeRay.should_receive(:scan).with("""def function(*args)
132
+ puts 'result'
133
+ end""", 'ruby').and_return scanned_code
134
+
135
+ scanned_code.should_receive(:div).with(:css => :class, :my => :option).and_return 'parsed code'
136
+
137
+ subject.coderay(text, :my => :option).should match('parsed code')
138
+ end
139
+ it 'accepts a caption option inside the code' do
140
+ subject.coderay(text_with_caption).should match('<h5>This will become an h5</h5>')
141
+ end
142
+ it 'accepts a caption with weird chars inside the code' do
143
+ subject.coderay(text_with_weird_caption).should match('<h5>This will become an h5, with some/strange.characters\yo</h5>')
144
+ end
145
+ it 'marks ruby comments to avoid conflicts with Markdown headers' do
146
+ code = ''
147
+ code.stub(:div).and_return ''
148
+ CodeRay.should_receive(:scan).with do |string|
149
+ string.should match(/\\#My comment/)
150
+ string.should match(/\\# My other comment/)
151
+ end.and_return code
152
+ subject.coderay(text_with_comments)
153
+ end
154
+ it 'passes the caption to the div' do
155
+ parsed = double :parsed
156
+ CodeRay.should_receive(:scan).and_return parsed
157
+ parsed.should_receive(:div).with(:css => :class, :caption => 'This will become an h5').and_return 'result'
158
+
159
+ subject.coderay(text_with_caption)
160
+ end
161
+ it 'accepts highlighted lines with an array' do
162
+ parsed = double :parsed
163
+ CodeRay.should_receive(:scan).and_return parsed
164
+ parsed.should_receive(:div).with(:css => :class, :highlight_lines => [1,2,3]).and_return 'result'
165
+
166
+ subject.coderay(text_with_array_highlights)
167
+ end
168
+ it 'accepts highlighted lines with a range' do
169
+ parsed = double :parsed
170
+ CodeRay.should_receive(:scan).and_return parsed
171
+ parsed.should_receive(:div).with(:css => :class, :highlight_lines => (1..3)).and_return 'result'
172
+
173
+ subject.coderay(text_with_range_highlights)
174
+ end
175
+ it 'encloses everything in a nice class' do
176
+ subject.coderay(text_with_caption).should match(/div class=\"markdownizer_code\" caption=\"This will become an h5\"/)
177
+ end
178
+ end
179
+
180
+ describe Markdownizer::DSL do
181
+ it 'integrates with ActiveRecord::Base' do
182
+ (class << ActiveRecord::Base; self; end).ancestors.should include(Markdownizer::DSL)
183
+ end
184
+
185
+ before do
186
+ ActiveRecord::Base.stub(:send)
187
+ @klass = Class.new(ActiveRecord::Base)
188
+ @klass.stub(:column_names) { %{body rendered_body} }
189
+ end
190
+
191
+ describe "#markdownize!(attribute)" do
192
+ context "when either of attribute or rendered_attribute does not exist" do
193
+ it 'raises' do
194
+ expect {
195
+ @klass.markdownize! :some_attribute
196
+ }.to raise_error
197
+ end
198
+ end
199
+ context "otherwise" do
200
+ it 'creates a before_save callback for render_attribute' do
201
+ @klass.should_receive(:before_save).with(:render_body)
202
+ @klass.markdownize! :body
203
+ end
204
+ it 'defines this render_attribute method' do
205
+ klass = Class.new do
206
+ extend Markdownizer::DSL
207
+ def self.column_names
208
+ %{body rendered_body}
209
+ end
210
+ end
211
+
212
+ klass.stub(:before_save)
213
+ klass.markdownize! :body
214
+
215
+ raw_body, raw_body_with_code, final_code = double(:raw_body),
216
+ double(:raw_body_with_code),
217
+ double(:final_code)
218
+
219
+ instance = klass.new
220
+ instance.should_receive(:send).with(:body).and_return raw_body
221
+ Markdownizer.should_receive(:coderay).with(raw_body, {}).and_return raw_body_with_code
222
+ Markdownizer.should_receive(:markdown).with(raw_body_with_code, 0).and_return final_code
223
+
224
+ instance.should_receive(:send).with(:rendered_body=, final_code)
225
+ instance.render_body
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,2 @@
1
+ require 'rspec'
2
+ require 'markdownizer'
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: extended_markdownizer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.2
6
+ platform: ruby
7
+ authors:
8
+ - "Jos\xC3\xA9 M. Gilgado"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-08-07 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 3.0.3
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rdiscount
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: coderay
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: rocco
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: git
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ prerelease: false
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 2.5.0
79
+ type: :development
80
+ version_requirements: *id006
81
+ description: Render any text as markdown, with code highlighting, url detection and conversion of youtube/vimeo urls into embedded videos
82
+ email:
83
+ - jm.gilgado@gmail.com
84
+ executables: []
85
+
86
+ extensions: []
87
+
88
+ extra_rdoc_files: []
89
+
90
+ files:
91
+ - .gemtest
92
+ - .gitignore
93
+ - .rspec
94
+ - .rvmrc
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - Rakefile
98
+ - Readme.md
99
+ - extended_markdownizer.gemspec
100
+ - init.rb
101
+ - lib/extended_markdownizer.rb
102
+ - lib/extended_markdownizer/version.rb
103
+ - lib/generators/extended_markdownizer/install_generator.rb
104
+ - lib/generators/extended_markdownizer/templates/coderay.css
105
+ - spec/extended_markdownizer_spec.rb
106
+ - spec/spec_helper.rb
107
+ homepage: https://github.com/josem/extended_markdownizer
108
+ licenses: []
109
+
110
+ post_install_message:
111
+ rdoc_options: []
112
+
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: "0"
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: "0"
127
+ requirements: []
128
+
129
+ rubyforge_project: extended_markdownizer
130
+ rubygems_version: 1.8.5
131
+ signing_key:
132
+ specification_version: 3
133
+ summary: Render any text as markdown, with code highlighting and all!
134
+ test_files:
135
+ - spec/extended_markdownizer_spec.rb
136
+ - spec/spec_helper.rb