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 +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
|