extended_markdownizer 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +55 -0
- data/Rakefile +65 -0
- data/Readme.md +78 -0
- data/extended_markdownizer.gemspec +29 -0
- data/init.rb +1 -0
- data/lib/extended_markdownizer.rb +242 -0
- data/lib/extended_markdownizer/version.rb +3 -0
- data/lib/generators/extended_markdownizer/install_generator.rb +15 -0
- data/lib/generators/extended_markdownizer/templates/coderay.css +131 -0
- data/spec/extended_markdownizer_spec.rb +230 -0
- data/spec/spec_helper.rb +2 -0
- metadata +136 -0
data/.gemtest
ADDED
File without changes
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create use ruby-1.9.2@markdownizer
|
data/Gemfile
ADDED
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&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,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
|
data/spec/spec_helper.rb
ADDED
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
|