class BlueCloth

Bluecloth is a Ruby implementation of Markdown, a text-to-HTML conversion tool.

Authors

Contributors

This product includes software developed by David Loren Parsons <www.pell.portland.or.us/~orc>.

Version

2.1.0

Revision

$Revision: 34dd000f535c $

License

Copyright © 2004-2011, Michael Granger All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Constants

DEFAULT_OPTIONS

The defaults for all supported options.

INSPECT_TEXT_LENGTH

The number of characters of the original markdown source to include in the output of inspect

MKD_1_COMPAT

MarkdownTest 1.0 Compatibility Mode

Create links for inline URIs

MKD_CDATA

Generate code for xml ![CDATA]

MKD_EMBED

MKD_NOLINKS|MKD_NOIMAGE|MKD_TAGTEXT

MKD_EXTRA_FOOTNOTE

Markdown-extra Footnotes

MKD_NOALPHALIST

Forbid alphabetic lists

MKD_NODIVQUOTE

Forbid '>%class%' blocks

MKD_NODLIST

Forbid definition lists

MKD_NOHEADER

don't process header blocks

MKD_NOHTML

Escape all opening angle brackets in the input text instead of allowing block-level HTML

MKD_NOIMAGE

Do not process `![]' and remove IMG tags from the output.

Do not process `[]' and remove A tags from the output.

MKD_NOPANTS

Do not do Smartypants-style mangling of quotes, dashes, or ellipses.

MKD_NORELAXED

Relaxed emphasis – emphasis happens everywhere

MKD_NOSTRIKETHROUGH

forbid ~~strikethrough~~

MKD_NOSUPERSCRIPT

Don't use superscript extension

MKD_NOTABLES

disallow tables

MKD_NO_EXT

don't allow pseudo-protocols

Be paranoid about link protocols

MKD_STRICT

disable SUPERSCRIPT, RELAXED_EMPHASIS

MKD_TABSTOP

Expand tabs to 4 spaces

MKD_TAGTEXT

process text inside an html tag; no <em>, no <bold>, no html or [] expansion

MKD_TOC

do table-of-contents processing

REVISION

Version control revision

VERSION

Release Version

Attributes

options[R]

The options hash that describes the options in effect when the object was created

text[R]

The original Markdown text the object was constructed with

Public Class Methods

discount_version → string click to toggle source

Return the version string of the Discount library BlueCloth was built on.

static VALUE
bluecloth_s_discount_version( VALUE klass ) {
        return rb_str_new2( markdown_version );
}
flags_from_opthash( opthash={} ) click to toggle source

Convert the specified opthash into a flags bitmask. If it's already a Fixnum (e.g., if someone passed in an ORed flags argument instead of an opthash), just return it as-is.

# File lib/bluecloth.rb, line 103
def self::flags_from_opthash( opthash={} )
        return opthash if opthash.is_a?( Integer )

        # Support BlueCloth1-style options
        if opthash == :filter_html || opthash == [:filter_html]
                opthash = { :escape_html => true }
        elsif opthash == :filter_styles
                opthash = {}
        elsif !opthash.is_a?( Hash )
                raise ArgumentError, "option %p not supported" % [ opthash ]
        end

        flags = 0

        if   opthash[:remove_links]     then flags |= MKD_NOLINKS;         end
        if   opthash[:remove_images]    then flags |= MKD_NOIMAGE;         end
        if ! opthash[:smartypants]      then flags |= MKD_NOPANTS;         end
        if   opthash[:escape_html]      then flags |= MKD_NOHTML;          end
        if   opthash[:strict_mode]      then flags |= MKD_STRICT;          end
        if   opthash[:tagtext_mode]     then flags |= MKD_TAGTEXT;         end
        if ! opthash[:pseudoprotocols]  then flags |= MKD_NO_EXT;          end
        if   opthash[:xml_cdata]        then flags |= MKD_CDATA;           end
        if ! opthash[:superscript]      then flags |= MKD_NOSUPERSCRIPT;   end
        if ! opthash[:relaxed]          then flags |= MKD_NORELAXED;       end
        if ! opthash[:tables]           then flags |= MKD_NOTABLES;        end
        if ! opthash[:strikethrough]    then flags |= MKD_NOSTRIKETHROUGH; end
        if   opthash[:header_labels]    then flags |= MKD_TOC;             end
        if   opthash[:mdtest_1_compat]  then flags |= MKD_1_COMPAT;        end
        if   opthash[:auto_links]       then flags |= MKD_AUTOLINK;        end
        if   opthash[:safe_links]       then flags |= MKD_SAFELINK;        end
        if ! opthash[:pandoc_headers]   then flags |= MKD_NOHEADER;        end
        if   opthash[:expand_tabs]      then flags |= MKD_TABSTOP;         end
        if ! opthash[:divquotes]        then flags |= MKD_NODIVQUOTE;      end
        if ! opthash[:alphalists]       then flags |= MKD_NOALPHALIST;     end
        if ! opthash[:definition_lists] then flags |= MKD_NODLIST;         end
        if   opthash[:footnotes]        then flags |= MKD_EXTRA_FOOTNOTE;  end

        return flags
end
new( string='', options=DEFAULT_OPTIONS ) → object click to toggle source

Create a new BlueCloth object that will process the given string. The options argument is a Hash that can be used to control the generated markup, and to enable/disable extensions. The supported options are:

:remove_links

Ignore links in Markdown, and escape A tags in the output. Defaults to false.

:remove_images

Ignore images in Markdown, and escape IMG tags in the output. Defaults to false.

:smartypants

Do Smartypants-style mangling of quotes, dashes, or ellipses. Defaults to true.

:pseudoprotocols

Support Discount's pseudo-protocol links. Defaults to false.

:pandoc_headers

Support the extraction of Pandoc headers, which can be fetched as a Hash via the header method. Defaults to false.

:header_labels

Generate ID attributes for all headers. Defaults to false.

:escape_html

Escape all HTML in the input string. Defaults to false.

:strict_mode

Disables Discount's relaxed emphasis (ignores underscores in the middle of words) and superscript notation. Defaults to true.

static VALUE
bluecloth_initialize( int argc, VALUE *argv, VALUE self ) {
        if ( !bluecloth_check_ptr(self) ) {
                MMIOT *document;
                VALUE text, optflags, fullhash, opthash = Qnil;
                int flags = 0;
                VALUE utf8text = Qnil;

                rb_scan_args( argc, argv, "02", &text, &opthash );

                /* Default empty string and options */
                if ( argc == 0 ) {
                        text = rb_str_new( "", 0 );
                }

                /* One arg could be either the text or the opthash, so shift the args if appropriate */
                else if ( argc == 1 && (TYPE(text) == T_HASH || TYPE(text) == T_FIXNUM) ) {
                        opthash = text;
                        text = rb_str_new( "", 0 );
                }
                else {
                        text = rb_obj_dup( rb_obj_as_string(text) );
                }

                /* Merge the options hash with the defaults and turn it into a flags int */
                if ( NIL_P(opthash) ) opthash = rb_hash_new();
                optflags = rb_funcall( bluecloth_cBlueCloth, rb_intern("flags_from_opthash"), 1, opthash );
                fullhash = rb_funcall( bluecloth_cBlueCloth, rb_intern("opthash_from_flags"), 1, optflags );

                flags = NUM2INT( optflags );

#ifdef M17N_SUPPORTED
                bluecloth_debug( "Bytes before utf8ification: %s",
                        RSTRING_PTR(rb_funcall(text, rb_intern("dump"), 0, Qnil)) );
                utf8text = rb_str_export_to_enc( rb_str_dup(text), rb_utf8_encoding() );
                DATA_PTR( self ) = document = bluecloth_alloc( utf8text, flags );
#else
                DATA_PTR( self ) = document = bluecloth_alloc( text, flags );
#endif /* M17N_SUPPORTED */

                if ( !mkd_compile(document, flags) )
                        rb_raise( rb_eRuntimeError, "Failed to compile markdown" );

                OBJ_FREEZE( text );
                rb_iv_set( self, "@text", text );
                OBJ_FREEZE( fullhash );
                rb_iv_set( self, "@options", fullhash );

                OBJ_INFECT( self, text );
        }

        return self;
}
opthash_from_flags( flags=0 ) click to toggle source

Returns a Hash that reflects the settings from the specified flags Integer.

# File lib/bluecloth.rb, line 145
def self::opthash_from_flags( flags=0 )
        flags = flags.to_i

        opthash = {}
        if  ( flags & MKD_NOLINKS         ).nonzero? then opthash[:remove_links]     = true; end
        if  ( flags & MKD_NOIMAGE         ).nonzero? then opthash[:remove_images]    = true; end
        if !( flags & MKD_NOPANTS         ).nonzero? then opthash[:smartypants]      = true; end
        if  ( flags & MKD_NOHTML          ).nonzero? then opthash[:escape_html]      = true; end
        if  ( flags & MKD_STRICT          ).nonzero? then opthash[:strict_mode]      = true; end
        if  ( flags & MKD_TAGTEXT         ).nonzero? then opthash[:tagtext_mode]     = true; end
        if !( flags & MKD_NO_EXT          ).nonzero? then opthash[:pseudoprotocols]  = true; end
        if  ( flags & MKD_CDATA           ).nonzero? then opthash[:xml_cdata]        = true; end
        if !( flags & MKD_NOSUPERSCRIPT   ).nonzero? then opthash[:superscript]      = true; end
        if !( flags & MKD_NORELAXED       ).nonzero? then opthash[:relaxed]          = true; end
        if !( flags & MKD_NOTABLES        ).nonzero? then opthash[:tables]           = true; end
        if !( flags & MKD_NOSTRIKETHROUGH ).nonzero? then opthash[:strikethrough]    = true; end
        if  ( flags & MKD_TOC             ).nonzero? then opthash[:header_labels]    = true; end
        if  ( flags & MKD_1_COMPAT        ).nonzero? then opthash[:mdtest_1_compat]  = true; end
        if  ( flags & MKD_AUTOLINK        ).nonzero? then opthash[:auto_links]       = true; end
        if  ( flags & MKD_SAFELINK        ).nonzero? then opthash[:safe_links]       = true; end
        if !( flags & MKD_NOHEADER        ).nonzero? then opthash[:pandoc_headers]   = true; end
        if  ( flags & MKD_TABSTOP         ).nonzero? then opthash[:expand_tabs]      = true; end
        if !( flags & MKD_NODIVQUOTE      ).nonzero? then opthash[:divquotes]        = true; end
        if !( flags & MKD_NOALPHALIST     ).nonzero? then opthash[:alphalists]       = true; end
        if !( flags & MKD_NODLIST         ).nonzero? then opthash[:definition_lists] = true; end
        if  ( flags & MKD_EXTRA_FOOTNOTE  ).nonzero? then opthash[:footnotes]        = true; end

        return opthash
end

Public Instance Methods

header → hash click to toggle source

Return the hash of Pandoc-style headers from the parsed document. If there were no headers, or the BlueCloth object was not constructed with the :pandoc_headers option enabled, an empty Hash is returned.

markdown = "%title My Essay\n%author Me\n%date Today\n\nSome stuff..."
bc = BlueCloth.new( markdown, :pandoc_headers => true )
# => 
bc.header
# =>
static VALUE
bluecloth_header( VALUE self ) {
        MMIOT *document = bluecloth_get_ptr( self );
        char *field;
        VALUE fieldstring, headers = rb_hash_new();

        bluecloth_debug( "Fetching pandoc headers for document %p", document );

        if ( (field = mkd_doc_title(document)) ) {
                fieldstring = rb_str_new2( field );
                OBJ_INFECT( fieldstring, self );
                rb_hash_aset( headers, ID2SYM(rb_intern("title")), fieldstring );
        }
        if ( (field = mkd_doc_author(document)) ) {
                fieldstring = rb_str_new2( field );
                OBJ_INFECT( fieldstring, self );
                rb_hash_aset( headers, ID2SYM(rb_intern("author")), fieldstring );
        }
        if ( (field = mkd_doc_date(document)) ) {
                fieldstring = rb_str_new2( field );
                OBJ_INFECT( fieldstring, self );
                rb_hash_aset( headers, ID2SYM(rb_intern("date")), fieldstring );
        }

        return headers;
}
Also aliased as: pandoc_header
inspect() click to toggle source

Return a human-readable representation of the object suitable for debugging.

# File lib/bluecloth.rb, line 181
def inspect
        return "#<%s:0x%x text: %p; options: %p>" % [
                self.class.name,
                self.object_id / 2,
                self.text.length > INSPECT_TEXT_LENGTH ?
                        self.text[ 0, INSPECT_TEXT_LENGTH - 5] + '[...]' :
                        self.text,
                self.options,
        ]
end
pandoc_header()
Alias for: header
to_html → string click to toggle source

Transform the document into HTML.

static VALUE
bluecloth_to_html( VALUE self ) {
        MMIOT *document = bluecloth_get_ptr( self );
        char *output;
        int length;
        VALUE result = Qnil;

        bluecloth_debug( "Compiling document %p", document );

        if ( (length = mkd_document( document, &output )) != EOF ) {
#ifdef M17N_SUPPORTED
                VALUE orig_encoding = rb_obj_encoding( rb_iv_get(self, "@text") );
                VALUE utf8_result = rb_enc_str_new( output, strlen(output), rb_utf8_encoding() );
                result = rb_str_encode( utf8_result, orig_encoding, 0, Qnil );
                bluecloth_debug( "Bytes after un-utf8ification (if necessary): %s",
                        RSTRING_PTR(rb_funcall(result, rb_intern("dump"), 0, Qnil)) );
#else
                result = rb_str_new2( output );
#endif /* M17N_SUPPORTED */

                OBJ_INFECT( result, self );

                return result;
        } else {
                return Qnil;
        }
}