/lib/red_cloth_formatters_plain.rb
https://github.com/codenauts/redcloth-formatters-plain · Ruby · 239 lines · 193 code · 23 blank · 23 comment · 2 complexity · d3c527cb81f879c4b36e4babbfddc689 MD5 · raw file
- # encoding: UTF-8
- require "red_cloth_formatters_plain/version"
- require "cgi"
- require "RedCloth"
- module RedCloth
- module Formatters
- module Plain
- class Sanitizer
- def self.strip_tags(text)
- # use Rails Sanitizer if available
- begin
- text = ActionController::Base.helpers.strip_tags(text)
- rescue
- # otherwise, use custom method inspired from:
- # RedCloth::Formatters::HTML.clean_html
- # not very secure, but it's ok as output is still
- # meant to be escaped if it needs to be shown
- text.gsub!( /<!\[CDATA\[/, '' )
- text.gsub!( /<(\/*)([A-Za-z]\w*)([^>]*?)(\s?\/?)>/ ){|m| block_given? ? yield(m) : ""}
- end
- CGI.unescapeHTML(text)
- end
- end
- include RedCloth::Formatters::Base
- [:h1, :h2, :h3, :h4, :h5, :h6, :p, :pre, :div].each do |m|
- define_method(m) do |opts|
- "#{opts[:text]}\n"
- end
- end
- [:strong, :code, :em, :i, :b, :ins, :sup, :sub, :span, :cite].each do |m|
- define_method(m) do |opts|
- opts[:block] = true
- "#{opts[:text]}"
- end
- end
- def hr(opts)
- "\n"
- end
- def acronym(opts)
- opts[:block] = true
- opts[:title] ? "#{opts[:text]}(#{opts[:title]})" : "#{opts[:text]}"
- end
- def caps(opts)
- "#{opts[:text]}"
- end
- # don't render deleted text
- def del(opts)
- ""
- end
- # simple list with dashes
- [:ol, :ul].each do |m|
- define_method("#{m}_open") do |opts|
- opts[:block] = true
- opts[:nest] > 1 ? "\n" : ""
- end
- define_method("#{m}_close") do |opts|
- ""
- end
- end
- def li_open(opts)
- @li_need_closing = true
- num = opts[:nest] - 1
- "#{" " * (num > 0 ? num : 0)}- #{opts[:text]}"
- end
- def li_close(opts=nil)
- # avoid multiple line breaks when closing multiple list items
- output = @li_need_closing ? "\n" : ""
- @li_need_closing = false
- output
- end
- def dl_open(opts)
- opts[:block] = true
- ""
- end
- def dl_close(opts=nil)
- ""
- end
- def dt(opts)
- "#{opts[:text]}:\n"
- end
- def dd(opts)
- " #{opts[:text]}\n"
- end
- # don't render tables
- [:td, :tr_open, :tr_close, :table_open, :table_close].each do |m|
- define_method(m) do |opts|
- ""
- end
- end
- # just add newlines before blockquotes
- [:bc_open, :bq_open].each do |m|
- define_method(m) do |opts|
- opts[:block] = true
- ""
- end
- end
- def bc_close(opts)
- "\n"
- end
- def bq_close(opts)
- ""
- end
- # render link name followed by <url>
- # uses !LINK_OPEN_TAG! and !LINK_CLOSE_TAG! as a way to identify
- # the < > otherwise they will be stripped when all html tags are stripped
- #
- def link(opts)
- "#{opts[:name]} !LINK_OPEN_TAG!#{opts[:href]}!LINK_CLOSE_TAG!"
- end
- # render image alternative text or title if not available
- def image(opts)
- "#{opts[:alt] || opts[:title]}"
- end
- # don't render footnotes
- [:footno, :fn].each do |m|
- define_method(m) do |opts|
- ""
- end
- end
- def snip(opts)
- opts[:text] + "\n"
- end
- # render unescaped quotes and special chars
- def quote1(opts)
- "'#{opts[:text]}'"
- end
- def quote2(opts)
- "\"#{opts[:text]}\""
- end
- def multi_paragraph_quote(opts)
- "\"#{opts[:text]}"
- end
- def ellipsis(opts)
- "#{opts[:text]}..."
- end
- {
- :emdash => "-",
- :endash => " - ",
- :arrow => "->",
- :trademark => "™",
- :registered => "®",
- :copyright => "©",
- :amp => "&",
- :gt => ">",
- :lt => "<",
- :br => "\n",
- :quot => "\"",
- :squot => "'",
- :apos => "'",
- }.each do |method, output|
- define_method(method) do |opts|
- output
- end
- end
- def dim(opts)
- opts[:text]
- end
- def entity(opts)
- unescape("&#{opts[:text]};")
- end
- # strip HTML tags
- def html(opts)
- strip_tags(opts[:text]) + "\n"
- end
- def html_block(opts)
- strip_tags(opts[:text])
- end
- def notextile(opts)
- if filter_html
- "#{opts[:text]}"
- else
- strip_tags(opts[:text])
- end
- end
- def inline_html(opts)
- if filter_html
- "#{opts[:text]}"
- else
- strip_tags(opts[:text])
- end
- end
- # unchanged
- def ignored_line(opts)
- opts[:text] + "\n"
- end
- private
- def strip_tags(text)
- Sanitizer.strip_tags(text)
- end
- def unescape(str)
- CGI.unescapeHTML(str.to_s)
- end
- # no escaping
- [:escape, :escape_pre, :escape_attribute].each do |m|
- define_method(m) do |text|
- text
- end
- end
- def after_transform(text)
- text.chomp!
- end
- def before_transform(text)
- end
- end
- end
- class TextileDoc
- def to_plain(*rules)
- apply_rules(rules)
- output = to(Formatters::Plain)
- output = Formatters::Plain::Sanitizer.strip_tags(output)
- # replace special link hooks with < and >
- # See #RedCloth::Formatters::Plain#link above
- output.gsub("!LINK_OPEN_TAG!", "<").gsub("!LINK_CLOSE_TAG!", ">")
- end
- end
- end