diff --git a/lib/redcloth.rb b/lib/redcloth.rb
index 03df12b3..1228af6e 100644
--- a/lib/redcloth.rb
+++ b/lib/redcloth.rb
@@ -166,7 +166,7 @@
class RedCloth < String
- VERSION = '3.0.3'
+ VERSION = '3.0.4'
DEFAULT_RULES = [:textile, :markdown]
#
@@ -193,6 +193,18 @@ class RedCloth < String
#
attr_accessor :hard_breaks
+ # Accessor for toggling lite mode.
+ #
+ # In lite mode, block-level rules are ignored. This means
+ # that tables, paragraphs, lists, and such aren't available.
+ # Only the inline markup for bold, italics, entities and so on.
+ #
+ # r = RedCloth.new( "And then? She *fell*!", [:lite_mode] )
+ # r.to_html
+ # #=> "And then? She fell!"
+ #
+ attr_accessor :lite_mode
+
#
# Accessor for toggling span caps.
#
@@ -219,7 +231,7 @@ class RedCloth < String
# inline_textile_image:: Textile inline images
# inline_textile_link:: Textile inline links
# inline_textile_span:: Textile inline spans
- # inline_textile_glyphs:: Textile entities (such as em-dashes and smart quotes)
+ # glyphs_textile:: Textile entities (such as em-dashes and smart quotes)
#
# == Markdown
#
@@ -260,7 +272,7 @@ class RedCloth < String
@shelf = []
textile_rules = [:refs_textile, :block_textile_table, :block_textile_lists,
:block_textile_prefix, :inline_textile_image, :inline_textile_link,
- :inline_textile_code, :inline_textile_glyphs, :inline_textile_span]
+ :inline_textile_code, :inline_textile_span, :glyphs_textile]
markdown_rules = [:refs_markdown, :block_markdown_setext, :block_markdown_atx, :block_markdown_rule,
:block_markdown_bq, :block_markdown_lists,
:inline_markdown_reflink, :inline_markdown_link]
@@ -278,14 +290,16 @@ class RedCloth < String
# standard clean up
incoming_entities text
clean_white_space text
- no_textile text
# start processor
@pre_list = []
rip_offtags text
- hard_break text
- refs text
- blocks text
+ no_textile text
+ hard_break text
+ unless @lite_mode
+ refs text
+ blocks text
+ end
inline text
smooth_offtags text
@@ -333,6 +347,8 @@ class RedCloth < String
C = "(?:#{C_CLAS}?#{C_STYL}?#{C_LNGE}?|#{C_STYL}?#{C_LNGE}?#{C_CLAS}?|#{C_LNGE}?#{C_STYL}?#{C_CLAS}?)"
# PUNCT = Regexp::quote( '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' )
PUNCT = Regexp::quote( '!"#$%&\'*+,-./:;=?@\\^_`|~' )
+ PUNCT_NOQ = Regexp::quote( '!"#$&\',./:;=?@\\`|' )
+ PUNCT_Q = Regexp::quote( '*-_+^~%' )
HYPERLINK = '(\S+?)([^\w\s/;=\?]*?)(?=\s|<|$)'
# Text markup tags, don't conflict with block tags
@@ -342,41 +358,6 @@ class RedCloth < String
'br', 'map', 'q', 'sub', 'sup', 'span', 'bdo'
]
- # Elements to handle
- GLYPHS = [
- # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing
- [ /([^\s\[{(>])\'/, '\1’' ], # single closing
- [ /\'(?=\s|s\b|[#{PUNCT}])/, '’' ], # single closing
- [ /\'/, '‘' ], # single opening
- # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing
- [ /([^\s\[{(>])"/, '\1”' ], # double closing
- [ /"(?=\s|[#{PUNCT}])/, '”' ], # double closing
- [ /"/, '“' ], # double opening
- [ /\b( )?\.{3}/, '\1…' ], # ellipsis
- [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '\1' ], # 3+ uppercase acronym
- [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]{2,})([^\2\3', :no_span_caps ], # 3+ uppercase caps
- [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash
- [ /\s->\s/, ' → ' ], # right arrow
- [ /\s-\s/, ' – ' ], # en dash
- [ /(\d+) ?x ?(\d+)/, '\1×\2' ], # dimension sign
- [ /\b ?[(\[]TM[\])]/i, '™' ], # trademark
- [ /\b ?[(\[]R[\])]/i, '®' ], # registered
- [ /\b ?[(\[]C[\])]/i, '©' ] # copyright
- ]
-
- H_ALGN_VALS = {
- '<' => 'left',
- '=' => 'center',
- '>' => 'right',
- '<>' => 'justify'
- }
-
- V_ALGN_VALS = {
- '^' => 'top',
- '-' => 'middle',
- '~' => 'bottom'
- }
-
QTAGS = [
['**', 'b'],
['*', 'strong'],
@@ -398,19 +379,56 @@ class RedCloth < String
(#{rcq})
(#{C})
(?::(\S+?))?
- (.+?)
+ (\S.*?\S|\S)
#{rcq}
(?=\W)/x
else
/(#{rcq})
(#{C})
- (?::(\S+?))?
- (.+?)
+ (?::(\S+))?
+ (\S.*?\S|\S)
#{rcq}/xm
end
[rc, ht, re, rtype]
end
+ # Elements to handle
+ GLYPHS = [
+ # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing
+ [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)\'/, '\1’' ], # single closing
+ [ /\'(?=[#{PUNCT_Q}]*(s\b|[\s#{PUNCT_NOQ}]))/, '’' ], # single closing
+ [ /\'/, '‘' ], # single opening
+ [ /, '<' ], # less-than
+ [ />/, '>' ], # greater-than
+ # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing
+ [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)"/, '\1”' ], # double closing
+ [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing
+ [ /"/, '“' ], # double opening
+ [ /\b( )?\.{3}/, '\1…' ], # ellipsis
+ [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '\1' ], # 3+ uppercase acronym
+ [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^\2\3', :no_span_caps ], # 3+ uppercase caps
+ [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash
+ [ /\s->\s/, ' → ' ], # right arrow
+ [ /\s-\s/, ' – ' ], # en dash
+ [ /(\d+) ?x ?(\d+)/, '\1×\2' ], # dimension sign
+ [ /\b ?[(\[]TM[\])]/i, '™' ], # trademark
+ [ /\b ?[(\[]R[\])]/i, '®' ], # registered
+ [ /\b ?[(\[]C[\])]/i, '©' ] # copyright
+ ]
+
+ H_ALGN_VALS = {
+ '<' => 'left',
+ '=' => 'center',
+ '>' => 'right',
+ '<>' => 'justify'
+ }
+
+ V_ALGN_VALS = {
+ '^' => 'top',
+ '-' => 'middle',
+ '~' => 'bottom'
+ }
+
#
# Flexible HTML escaping
#
@@ -530,7 +548,7 @@ class RedCloth < String
depth.pop
end
end
- if depth.last.length == tl.length
+ if depth.last and depth.last.length == tl.length
lines[line_id - 1] << ''
end
end
@@ -577,7 +595,7 @@ class RedCloth < String
end
def hard_break( text )
- text.gsub!( /(.)\n(?! *[#*\s|]|$)/, "\\1
" ) if hard_breaks
+ text.gsub!( /(.)\n(?!\Z| *([#*=]+(\s|$)|[{|]))/, "\\1
" ) if hard_breaks
end
BLOCKS_GROUP_RE = /\n{2,}(?! )/m
@@ -705,9 +723,9 @@ class RedCloth < String
end
end
- MARKDOWN_RULE_RE = /^#{
+ MARKDOWN_RULE_RE = /^(#{
['*', '-', '_'].collect { |ch| '( ?' + Regexp::quote( ch ) + ' ?){3,}' }.join( '|' )
- }$/
+ })$/
def block_markdown_rule( text )
text.gsub!( MARKDOWN_RULE_RE ) do |blk|
@@ -719,9 +737,6 @@ class RedCloth < String
def block_markdown_lists( text )
end
- def inline_markdown_link( text )
- end
-
def inline_textile_span( text )
QTAGS.each do |qtag_rc, ht, qtag_re, rtype|
text.gsub!( qtag_re ) do |m|
@@ -903,12 +918,12 @@ class RedCloth < String
def shelve( val )
@shelf << val
- " <#{ @shelf.length }>"
+ " :redsh##{ @shelf.length }:"
end
def retrieve( text )
@shelf.each_with_index do |r, i|
- text.gsub!( " <#{ i + 1 }>", r )
+ text.gsub!( " :redsh##{ i + 1 }:", r )
end
end
@@ -965,7 +980,7 @@ class RedCloth < String
HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
ALLTAG_MATCH = /(<\/?\w[^\n]*?>)|.*?(?=<\/?\w[^\n]*?>|$)/m
- def inline_textile_glyphs( text, level = 0 )
+ def glyphs_textile( text, level = 0 )
if text !~ HASTAG_MATCH
pgl text
footnote_ref text
@@ -981,11 +996,11 @@ class RedCloth < String
codepre = 0 if codepre < 0
end
elsif codepre.zero?
- inline_textile_glyphs( line, level + 1 )
+ glyphs_textile( line, level + 1 )
else
htmlesc( line, :NoQuotes )
end
- ## p [level, codepre, orig_line, line]
+ # p [level, codepre, line]
line
end
@@ -1033,8 +1048,10 @@ class RedCloth < String
end
def inline( text )
- @rules.each do |rule_name|
- method( rule_name ).call( text ) if rule_name.to_s.match /^inline_/
+ [/^inline_/, /^glyphs_/].each do |meth_re|
+ @rules.each do |rule_name|
+ method( rule_name ).call( text ) if rule_name.to_s.match( meth_re )
+ end
end
end
@@ -1097,7 +1114,7 @@ class RedCloth < String
q2 = ( q != '' ? q : '\s' )
if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
attrv = $1
- next if prop == 'src' and attrv !~ /^http/
+ next if prop == 'src' and attrv =~ %r{^(?!http)\w+:}
pcs << "#{prop}=\"#{$1.gsub('"', '\\"')}\""
break
end