Browse files

Redcarpet 2

  • Loading branch information...
1 parent 9562d1b commit 427146c4b6eb0f58f566a77d17467a67da4f7e3c @vmg vmg committed Jul 22, 2011
@@ -1,61 +1,256 @@
-Ruby + Upskirt = Markdown that doesn't suck
+Redcarpet 2 is written with sugar, spice and everything nice
-Redcarpet is a Ruby wrapper for Upskirt. It is mostly based on Ryan
-Tomayko's RDiscount wrapper, and inspired by Rick Astley wearing a kilt.
+Redcarpet is Ruby library for Markdown processing that smells like
+butterflies and popcorn.
-Redcarpet is powered by the Upskirt library, which can be found at
+Redcarpet used to be a drop-in replacement for Redcloth. This is no longer the
+case since version 2 -- it now has its own API, but retains the old name. Yes,
+that does mean that Redcarpet 2 is not backwards-compatible with the 1.X
+Redcarpet is powered by the Sundown library, which can be found at
-You might want to find out more about Upskirt to see what makes these Ruby
-bindings so awesome.
+You might want to find out more about Sundown to see what makes this Ruby
+library so awesome.
-* Natacha Porté, lady of Markdown
-* Vicent Martí, wannabe
-* With special thanks to Ryan Tomayko
+This library is written by people
+Redcarpet 2 has been rewritten from scratch by Vicent Marti (@tanoku). Why
+are you not following me on Twitter?
-Redcarpet is readily available as a Ruby gem:
+Redcarpet would not be possible without the Sundown library and its authors
+(Natacha Porté, Vicent Martí, and its many awesome contributors).
+You can totally install it as a Gem
+Redcarpet is readily available as a Ruby gem. It will build some native
+extensions, but the parser is standalone and requires no installed libraries.
$ [sudo] gem install redcarpet
-The Redcarpet source (including Upskirt as a submodule) is available at GitHub:
+The Redcarpet source (including Sundown as a submodule) is available at GitHub:
$ git clone git://
+And it's like *really* simple to use
+The core of the Redcarpet library is the `Redcarpet::Markdown` class. Each
+instance of the class is attached to a `Renderer` object; the Markdown class
+performs parsing of a document and uses the attached renderer to generate
+The `Markdown` object is encouraged to be instantiated once with the required
+settings, and reused between parses.
+, extensions={})
+ Initializes a Markdown parser
+ renderer - a renderer object, inheriting from Redcarpet::Render::Base.
+ If the given object has not been instantiated, the library
+ will do it with default arguments.
+ extensions - a hash containing the Markdown extesions which the parser
+ will identify. The following extensions are accepted:
+ :no_intra_emphasis - do not parse emphasis inside of words.
+ Strings such as `foo_bar_baz` will not generate `<em>`
+ tags.
+ :tables - parse tables, PHP-Markdown style
+ :fenced_code_blocks - parse fenced code blocks, PHP-Markdown
+ style .Blocks delimited with 3 or more `~` or backticks
+ will be considered as code, without the need to be
+ indented. An optional language name may be added at the
+ end of the opening fence for the code block
+ :autolink - parse links even when they are not enclosed in
+ `<>` characters. Autolinks for the http, https and ftp
+ protocols will be automatically detected. Email addresses
+ are also handled, and http links without protocol, but
+ starting with `www.`
+ :strikethrough - parse strikethrough, PHP-Markdown style
+ Two `~` characters mark the start of a strikethrough,
+ e.g. `this is ~~good~~ bad`
+ :lax_html_blocks - HTML blocks do not require to be surrounded
+ by an empty line as in the Markdown standard.
+ :space_after_headers - A space is always required between the
+ hash at the beggining of a header and its name, e.g.
+ `#this is my header` would not be a valid header.
+ :superscript - parse superscripts after the `^` character;
+ contiguous superscripts are nested together, and complex
+ values can be enclosed in parenthesis,
+ e.g. `this is the 2^(nd) time`
+ Example:
+ markdown =,
+ :autolink => true, :space_after_headers => true)
+Rendering with the `Markdown` object is done through `Markdown#render`.
+Unlike in the RedCloth API, the text to render is passed as an argument
+and not stored inside the `Markdown` instance, to encourage reusability.
+ Markdown.render(text)
+ Render a Markdown document with the attached renderer
+ text - a Markdown document
+ Example:
+ markdown.render("This is *bongos*, indeed.")
+ #=> "<p>This is <em>bongos</em>, indeed</p>"
+Darling, I packed you a couple renderers for lunch
+Redcarpet comes with two built-in renderers, `Redcarpet::Render::HTML` and
+`Redcarpet::Render::XHTML`, which output HTML and XHTML, respectively. These
+renderers are actually implemented in C, and hence offer a brilliant
+performance, several degrees of magnitude faster than other Ruby Markdown
+The `HTML` renderer has an alternate version, `Redcarpet::Render::HTML_toc`,
+which will output a table of contents in HTML based on the headers of the
+Markdown document.
+Furthermore, the abstract base class `Redcarpet::Render::Base` can be used
+to write a custom renderer purely in Ruby, or extending an existing renderer.
+See the following section for more information.
+And you can even cook your own
+Custom renderers are created by inheriting from an existing renderer. The
+builtin renderers, `HTML` and `XHTML` may be extended as such:
+~~~~~ ruby
+# create a custom renderer that allows highlighting of code blocks
+class HTMLwithAlbino < Redcarpet::Render::HTML
+ def block_code(code, language)
+ Albino.safe_colorize(code, language)
+ end
+markdown =, :fenced_code_blocks => true)
+But new renderers can also be created from scratch (see `lib/render_man.rb` for
+an example implementation of a Manpage renderer)
+~~~~~~ ruby
+class ManPage < Redcarpet::Render::Base
+ # you get the drill -- keep going from here
+The following instance methods may be implemented by the renderer:
+ # Block-level calls
+ # If the return value of the method is `nil`, the block
+ # will be skipped.
+ # If the method for a document element is not implemented,
+ # the block will be skipped.
+ #
+ # Example:
+ #
+ # class RenderWithoutCode < Redcarpet::Render::HTML
+ # def block_code(code, language)
+ # nil
+ # end
+ # end
+ #
+ block_code(code, language)
+ block_quote(quote)
+ block_html(raw_html)
+ header(text, header_level)
+ hrule()
+ list(contents, list_type)
+ list_item(text)
+ paragraph(text)
+ table(header, body)
+ table_row(content)
+ table_cell(content, alignment)
+ # Span-level calls
+ # A return value of `nil` will not output any data
+ # If the method for a document element is not implemented,
+ # the contents of the span will be copied verbatim
+ autolink(link, link_type)
+ codespan(code)
+ double_emphasis(text)
+ emphasis(text)
+ image(link, title, alt_text)
+ linebreak()
+ link(link, title, content)
+ raw_html(raw_html)
+ triple_emphasis(text)
+ strikethrough(text)
+ superscript(text)
+ # Low level rendering
+ entity(text)
+ normal_text(text)
+ # Header of the document
+ # Rendered before any another elements
+ doc_header()
+ # Footer of the document
+ # Rendered after all the other elements
+ doc_footer()
+ # Pre/post-process
+ # Special callback: preprocess or postprocess the whole
+ # document before or after the rendering process begins
+ preprocess(full_document)
+ postprocess(full_document)
+Also, now our Pants are much smarter
-Redcarpet implements the basic protocol popularized by RedCloth:
+Redcarpet 2 comes with a standalone [SmartyPants](
+ implementation. It is fully
+compilant with the original implementation. It is the fastest SmartyPants
+parser there is, with a difference of several orders of magnitude.
-~~~~~~ {ruby}
-require 'redcarpet'
-markdown ="Hello World!")
-puts markdown.to_html
+The SmartyPants parser can be found in `Redcarpet::Render::SmartyPants`. It has
+been implemented as a module, so it can be used standalone or as a mixin.
-[Additional processing options]( can be turned on when creating the
-Redcarpet object:
+When mixed with a Renderer class, it will override the `postprocess` method
+to perform SmartyPants replacements once the rendering is complete
-~~~~~~ {ruby}
-markdown ="Hello World!", :smart, :filter_html)
+~~~~ ruby
+# Mixin
+class HTMLWithPants < Redcarpet::Render::HTML
+ include Redcarpet::Render::SmartyPants
-Note that by default, Redcarpet parses standard Markdown (with no extensions)
-and offers a sane subset of parse options which allow you to modify the rendering
-output and to enable MD extensions on a per-case basis.
+# Standalone
+Redcarpet::Render::SmartyPants.render("<p>Oh SmartyPants, you're so crazy...</p>")
-Redcarpet also offers a wrapper class, `RedcarpetCompat` with the same flags
-and behavior as the RDiscount library, which acts as a drop-in replacement.
+SmartyPants works on top of already-rendered HTML, and will ignore replacements
+inside the content of HTML tags and inside specific HTML blocks such as
+`<code>` or `<pre>`.
+Boring legal stuff
Copyright (c) 2011, Vicent Martí
@@ -70,9 +70,6 @@ task :install => package('.gem') do
sh "gem install #{package('.gem')}"
-desc 'Update the gemspec'
-task :update_gem => file('redcarpet.gemspec')
directory 'pkg/'
file package('.gem') => %w[pkg/ redcarpet.gemspec] + $spec.files do |f|
@@ -91,9 +88,10 @@ def source_version
line.match(/.*VERSION = '(.*)'/)[1]
-file 'redcarpet.gemspec' => FileList['Rakefile','lib/redcarpet.rb'] do |f|
+task :update_gem do
# read spec file and split out manifest section
- spec =
+ GEMFILE = 'redcarpet.gemspec'
+ spec =
head, manifest, tail = spec.split(" # = MANIFEST =\n")
head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
head.sub!(/\.date = '.*'/, ".date = '#{}'")
@@ -107,26 +105,26 @@ file 'redcarpet.gemspec' => FileList['Rakefile','lib/redcarpet.rb'] do |f|
# piece file back together and write...
manifest = " s.files = %w[\n#{files}\n ]\n"
spec = [head,manifest,tail].join(" # = MANIFEST =\n")
-, 'w') { |io| io.write(spec) }
- puts "updated #{}"
+, 'w') { |io| io.write(spec) }
+ puts "updated #{GEMFILE}"
-desc 'Gather required Upskirt sources into extension directory'
-task :gather => 'upskirt/src/markdown.h' do |t|
+desc 'Gather required Sundown sources into extension directory'
+task :gather => 'sundown/src/markdown.h' do |t|
files =
- 'upskirt/src/{markdown,buffer,array,autolink}.h',
- 'upskirt/src/{markdown,buffer,array,autolink}.c',
- 'upskirt/html/{html,html_smartypants}.c',
- 'upskirt/html/html.h',
+ 'sundown/src/{markdown,buffer,array,autolink}.h',
+ 'sundown/src/{markdown,buffer,array,autolink}.c',
+ 'sundown/html/{html,html_smartypants}.c',
+ 'sundown/html/html.h',
cp files, 'ext/redcarpet/',
:preserve => true,
:verbose => true
-file 'upskirt/src/markdown.h' do |t|
- abort "The Upskirt submodule is required."
+file 'sundown/src/markdown.h' do |t|
+ abort "The Sundown submodule is required."
@@ -10,4 +10,4 @@ if ARGV.include?('--help')
require 'redcarpet'
Oops, something went wrong.

0 comments on commit 427146c

Please sign in to comment.