extended_markdownizer 0.1.2

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/.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