<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/bluecloth/transform.rb</filename>
    </added>
    <added>
      <filename>lib/bluecloth/transform/blocks.rb</filename>
    </added>
    <added>
      <filename>lib/bluecloth/transform/inline.rb</filename>
    </added>
    <added>
      <filename>lib/bluecloth/transform/links.rb</filename>
    </added>
    <added>
      <filename>lib/bluecloth/transform/util.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,3 @@
-#!/usr/bin/ruby
 # 
 # Bluecloth is a Ruby implementation of Markdown, a text-to-HTML conversion
 # tool.
@@ -49,81 +48,18 @@
 #   regexps.
 #
 # * Put the StringScanner in the render state for thread-safety.
-#
-# == Version
-#
-#  $Id$
-# 
 
-require 'digest/md5'
 require 'logger'
-require 'strscan'
-
-
-### BlueCloth is a Ruby implementation of Markdown, a text-to-HTML conversion
-### tool.
-class BlueCloth &lt; String
-
-	### Exception class for formatting errors.
-	class FormatError &lt; RuntimeError
-
-		### Create a new FormatError with the given source +str+ and an optional
-		### message about the +specific+ error.
-		def initialize( str, specific=nil )
-			if specific
-				msg = &quot;Bad markdown format near %p: %s&quot; % [ str, specific ]
-			else
-				msg = &quot;Bad markdown format near %p&quot; % str
-			end
-
-			super( msg )
-		end
-	end
-
 
+# BlueCloth is a Ruby implementation of Markdown, a text-to-HTML conversion
+# tool.
+class BlueCloth
+  
 	# Release Version
 	Version = '0.0.3'
 
-	# SVN Revision
-	SvnRev = %q$Rev$
-
-	# SVN Id tag
-	SvnId = %q$Id$
-
-	# SVN URL
-	SvnUrl = %q$URL$
-
-
-	# Rendering state struct. Keeps track of URLs, titles, and HTML blocks
-	# midway through a render. I prefer this to the globals of the Perl version
-	# because globals make me break out in hives. Or something.
-	RenderState = Struct::new( &quot;RenderState&quot;, :urls, :titles, :html_blocks, :log )
-
-	# Tab width for #detab! if none is specified
-	TabWidth = 4
-
-	# The tag-closing string -- set to '&gt;' for HTML
-	EmptyElementSuffix = &quot;/&gt;&quot;;
-
-	# Table of MD5 sums for escaped characters
-	EscapeTable = {}
-	'\\`*_{}[]()#.!'.split(//).each {|char|
-		hash = Digest::MD5::hexdigest( char )
-
-		EscapeTable[ char ] = {
- 			:md5 =&gt; hash,
-			:md5re =&gt; Regexp::new( hash ),
-			:re  =&gt; Regexp::new( '\\\\' + Regexp::escape(char) ),
-		}
-	}
-
-
-	#################################################################
-	###	I N S T A N C E   M E T H O D S
-	#################################################################
-
-	### Create a new BlueCloth string.
-	def initialize( content=&quot;&quot;, *restrictions )
+	# Create a new BlueCloth string.
+	def initialize(content = &quot;&quot;, *restrictions)
 		@log = Logger::new( $deferr )
 		@log.level = $DEBUG ?
 			Logger::DEBUG :
@@ -137,16 +73,11 @@ class BlueCloth &lt; String
 		restrictions.flatten.each {|r| __send__(&quot;#{r}=&quot;, true) }
 		@fold_lines = true
 
-		super( content )
+    @content = content
 
 		@log.debug &quot;String is: %p&quot; % self
 	end
 
-
-	######
-	public
-	######
-
 	# Filters for controlling what gets output for untrusted input. (But really,
 	# you're filtering bad stuff out of untrusted input at submission-time via
 	# untainting, aren't you?)
@@ -156,989 +87,7 @@ class BlueCloth &lt; String
 	# so this isn't used by anything.
 	attr_accessor :fold_lines
 
+end
 
-	### Render Markdown-formatted text in this string object as HTML and return
-	### it. The parameter is for compatibility with RedCloth, and is currently
-	### unused, though that may change in the future.
-	def to_html( lite=false )
-
-		# Create a StringScanner we can reuse for various lexing tasks
-		@scanner = StringScanner::new( '' )
-
-		# Make a structure to carry around stuff that gets placeholdered out of
-		# the source.
-		rs = RenderState::new( {}, {}, {} )
-
-		# Make a copy of the string with normalized line endings, tabs turned to
-		# spaces, and a couple of guaranteed newlines at the end
-		text = self.gsub( /\r\n?/, &quot;\n&quot; ).detab
-		text += &quot;\n\n&quot;
-		@log.debug &quot;Normalized line-endings: %p&quot; % text
-
-		# Filter HTML if we're asked to do so
-		if self.filter_html
-			text.gsub!( &quot;&lt;&quot;, &quot;&amp;lt;&quot; )
-			text.gsub!( &quot;&gt;&quot;, &quot;&amp;gt;&quot; )
-			@log.debug &quot;Filtered HTML: %p&quot; % text
-		end
-
-		# Simplify blank lines
-		text.gsub!( /^ +$/, '' )
-		@log.debug &quot;Tabs -&gt; spaces/blank lines stripped: %p&quot; % text
-
-		# Replace HTML blocks with placeholders
-		text = hide_html_blocks( text, rs )
-		@log.debug &quot;Hid HTML blocks: %p&quot; % text
-		@log.debug &quot;Render state: %p&quot; % rs
-
-		# Strip link definitions, store in render state
-		text = strip_link_definitions( text, rs )
-		@log.debug &quot;Stripped link definitions: %p&quot; % text
-		@log.debug &quot;Render state: %p&quot; % rs
-
-		# Escape meta-characters
-		text = escape_special_chars( text )
-		@log.debug &quot;Escaped special characters: %p&quot; % text
-
-		# Transform block-level constructs
-		text = apply_block_transforms( text, rs )
-		@log.debug &quot;After block-level transforms: %p&quot; % text
-
-		# Now swap back in all the escaped characters
-		text = unescape_special_chars( text )
-		@log.debug &quot;After unescaping special characters: %p&quot; % text
-
-		return text
-	end
-	
-
-	### Convert tabs in +str+ to spaces.
-	def detab( tabwidth=TabWidth )
-		copy = self.dup
-		copy.detab!( tabwidth )
-		return copy
-	end
-
-
-	### Convert tabs to spaces in place and return self if any were converted.
-	def detab!( tabwidth=TabWidth )
-		newstr = self.split( /\n/ ).collect {|line|
-			line.gsub( /(.*?)\t/ ) do
-				$1 + ' ' * (tabwidth - $1.length % tabwidth)
-			end
-		}.join(&quot;\n&quot;)
-		self.replace( newstr )
-	end
-
-
-	#######
-	#private
-	#######
-
-	### Do block-level transforms on a copy of +str+ using the specified render
-	### state +rs+ and return the results.
-	def apply_block_transforms( str, rs )
-		# Port: This was called '_runBlockGamut' in the original
-
-		@log.debug &quot;Applying block transforms to:\n  %p&quot; % str
-		text = transform_headers( str, rs )
-		text = transform_hrules( text, rs )
-		text = transform_lists( text, rs )
-		text = transform_code_blocks( text, rs )
-		text = transform_block_quotes( text, rs )
-		text = transform_auto_links( text, rs )
-		text = hide_html_blocks( text, rs )
-
-		text = form_paragraphs( text, rs )
-
-		@log.debug &quot;Done with block transforms:\n  %p&quot; % text
-		return text
-	end
-
-
-	### Apply Markdown span transforms to a copy of the specified +str+ with the
-	### given render state +rs+ and return it.
-	def apply_span_transforms( str, rs )
-		@log.debug &quot;Applying span transforms to:\n  %p&quot; % str
-
-		str = transform_code_spans( str, rs )
-		str = encode_html( str )
-		str = transform_images( str, rs )
-		str = transform_anchors( str, rs )
-		str = transform_italic_and_bold( str, rs )
-
-		# Hard breaks
-		str.gsub!( / {2,}\n/, &quot;&lt;br#{EmptyElementSuffix}\n&quot; )
-
-		@log.debug &quot;Done with span transforms:\n  %p&quot; % str
-		return str
-	end
-
-
-	# The list of tags which are considered block-level constructs and an
-	# alternation pattern suitable for use in regexps made from the list
-	StrictBlockTags = %w[ p div h[1-6] blockquote pre table dl ol ul script noscript
-		form fieldset iframe math ins del ]
-	StrictTagPattern = StrictBlockTags.join('|')
-
-	LooseBlockTags = StrictBlockTags - %w[ins del]
-	LooseTagPattern = LooseBlockTags.join('|')
-
-	# Nested blocks:
-	# 	&lt;div&gt;
-	# 		&lt;div&gt;
-	# 		tags for inner block must be indented.
-	# 		&lt;/div&gt;
-	# 	&lt;/div&gt;
-	StrictBlockRegex = %r{
-		^						# Start of line
-		&lt;(#{StrictTagPattern})	# Start tag: \2
-		\b						# word break
-		(.*\n)*?				# Any number of lines, minimal match
-		&lt;/\1&gt;					# Matching end tag
-		[ ]*					# trailing spaces
-		$						# End of line or document
-	  }ix
-
-	# More-liberal block-matching
-	LooseBlockRegex = %r{
-		^						# Start of line
-		&lt;(#{LooseTagPattern})	# start tag: \2
-		\b						# word break
-		(.*\n)*?				# Any number of lines, minimal match
-		.*&lt;/\1&gt;					# Anything + Matching end tag
-		[ ]*					# trailing spaces
-		$						# End of line or document
-	  }ix
-
-	# Special case for &lt;hr /&gt;.
-	HruleBlockRegex = %r{
-		(						# $1
-			\A\n?				# Start of doc + optional \n
-			|					# or
-			.*\n\n				# anything + blank line
-		)
-		(						# save in $2
-			[ ]*				# Any spaces
-			&lt;hr					# Tag open
-			\b					# Word break
-			([^&lt;&gt;])*?			# Attributes
-			/?&gt;					# Tag close
-			$					# followed by a blank line or end of document
-		)
-	  }ix
-
-	### Replace all blocks of HTML in +str+ that start in the left margin with
-	### tokens.
-	def hide_html_blocks( str, rs )
-		@log.debug &quot;Hiding HTML blocks in %p&quot; % str
-		
-		# Tokenizer proc to pass to gsub
-		tokenize = lambda {|match|
-			key = Digest::MD5::hexdigest( match )
-			rs.html_blocks[ key ] = match
-			@log.debug &quot;Replacing %p with %p&quot; % [ match, key ]
-			&quot;\n\n#{key}\n\n&quot;
-		}
-
-		rval = str.dup
-
-		@log.debug &quot;Finding blocks with the strict regex...&quot;
-		rval.gsub!( StrictBlockRegex, &amp;tokenize )
-
-		@log.debug &quot;Finding blocks with the loose regex...&quot;
-		rval.gsub!( LooseBlockRegex, &amp;tokenize )
-
-		@log.debug &quot;Finding hrules...&quot;
-		rval.gsub!( HruleBlockRegex ) {|match| $1 + tokenize[$2] }
-
-		return rval
-	end
-
-
-	# Link defs are in the form: ^[id]: url &quot;optional title&quot;
-	LinkRegex = %r{
-		^[ ]*\[(.+)\]:		# id = $1
-		  [ ]*
-		  \n?				# maybe *one* newline
-		  [ ]*
-		&lt;?(\S+?)&gt;?				# url = $2
-		  [ ]*
-		  \n?				# maybe one newline
-		  [ ]*
-		(?:
-			# Titles are delimited by &quot;quotes&quot; or (parens).
-			[&quot;(]
-			(.+?)			# title = $3
-			[&quot;)]			# Matching ) or &quot;
-			[ ]*
-		)?	# title is optional
-		(?:\n+|\Z)
-	  }x
-
-	### Strip link definitions from +str+, storing them in the given RenderState
-	### +rs+.
-	def strip_link_definitions( str, rs )
-		str.gsub( LinkRegex ) {|match|
-			id, url, title = $1, $2, $3
-
-			rs.urls[ id.downcase ] = encode_html( url )
-			unless title.nil?
-				rs.titles[ id.downcase ] = title.gsub( /&quot;/, &quot;&amp;quot;&quot; )
-			end
-			&quot;&quot;
-		}
-	end
-
-
-	### Escape special characters in the given +str+
-	def escape_special_chars( str )
-		@log.debug &quot;  Escaping special characters&quot;
-		text = ''
-
-		# The original Markdown source has something called '$tags_to_skip'
-		# declared here, but it's never used, so I don't define it.
-
-		tokenize_html( str ) {|token, str|
-			@log.debug &quot;   Adding %p token %p&quot; % [ token, str ]
-			case token
-
-			# Within tags, encode * and _
-			when :tag
-				text += str.
-					gsub( /\*/, EscapeTable['*'][:md5] ).
-					gsub( /_/, EscapeTable['_'][:md5] )
-
-			# Encode backslashed stuff in regular text
-			when :text
-				text += encode_backslash_escapes( str )
-			else
-				raise TypeError, &quot;Unknown token type %p&quot; % token
-			end
-		}
-
-		@log.debug &quot;  Text with escapes is now: %p&quot; % text
-		return text
-	end
-
-
-	### Swap escaped special characters in a copy of the given +str+ and return
-	### it.
-	def unescape_special_chars( str )
-		EscapeTable.each {|char, hash|
-			@log.debug &quot;Unescaping escaped %p with %p&quot; % [ char, hash[:md5re] ]
-			str.gsub!( hash[:md5re], char )
-		}
-
-		return str
-	end
-
-
-	### Return a copy of the given +str+ with any backslashed special character
-	### in it replaced with MD5 placeholders.
-	def encode_backslash_escapes( str )
-		# Make a copy with any double-escaped backslashes encoded
-		text = str.gsub( /\\\\/, EscapeTable['\\'][:md5] )
-		
-		EscapeTable.each_pair {|char, esc|
-			next if char == '\\'
-			text.gsub!( esc[:re], esc[:md5] )
-		}
-
-		return text
-	end
-
-
-	### Transform any Markdown-style horizontal rules in a copy of the specified
-	### +str+ and return it.
-	def transform_hrules( str, rs )
-		@log.debug &quot; Transforming horizontal rules&quot;
-		str.gsub( /^( ?[\-\*_] ?){3,}$/, &quot;\n&lt;hr#{EmptyElementSuffix}\n&quot; )
-	end
-
-
-
-	# Patterns to match and transform lists
-	ListMarkerOl = %r{\d+\.}
-	ListMarkerUl = %r{[*+-]}
-	ListMarkerAny = Regexp::union( ListMarkerOl, ListMarkerUl )
-
-	ListRegexp = %r{
-		  (?:
-			^[ ]{0,#{TabWidth - 1}}		# Indent &lt; tab width
-			(#{ListMarkerAny})			# unordered or ordered ($1)
-			[ ]+						# At least one space
-		  )
-		  (?m:.+?)						# item content (include newlines)
-		  (?:
-			  \z						# Either EOF
-			|							#  or
-			  \n{2,}					# Blank line...
-			  (?=\S)					# ...followed by non-space
-			  (?![ ]*					# ...but not another item
-				(#{ListMarkerAny})
-			   [ ]+)
-		  )
-	  }x
-
-	### Transform Markdown-style lists in a copy of the specified +str+ and
-	### return it.
-	def transform_lists( str, rs )
-		@log.debug &quot; Transforming lists at %p&quot; % (str[0,100] + '...')
-
-		str.gsub( ListRegexp ) {|list|
-			@log.debug &quot;  Found list %p&quot; % list
-			bullet = $1
-			list_type = (ListMarkerUl.match(bullet) ? &quot;ul&quot; : &quot;ol&quot;)
-			list.gsub!( /\n{2,}/, &quot;\n\n\n&quot; )
-
-			%{&lt;%s&gt;\n%s&lt;/%s&gt;\n} % [
-				list_type,
-				transform_list_items( list, rs ),
-				list_type,
-			]
-		}
-	end
-
-
-	# Pattern for transforming list items
-	ListItemRegexp = %r{
-		(\n)?							# leading line = $1
-		(^[ ]*)							# leading whitespace = $2
-		(#{ListMarkerAny}) [ ]+			# list marker = $3
-		((?m:.+?)						# list item text   = $4
-		(\n{1,2}))
-		(?= \n* (\z | \2 (#{ListMarkerAny}) [ ]+))
-	  }x
-
-	### Transform list items in a copy of the given +str+ and return it.
-	def transform_list_items( str, rs )
-		@log.debug &quot; Transforming list items&quot;
-
-		# Trim trailing blank lines
-		str = str.sub( /\n{2,}\z/, &quot;\n&quot; )
-
-		str.gsub( ListItemRegexp ) {|line|
-			@log.debug &quot;  Found item line %p&quot; % line
-			leading_line, item = $1, $4
-
-			if leading_line or /\n{2,}/.match( item )
-				@log.debug &quot;   Found leading line or item has a blank&quot;
-				item = apply_block_transforms( outdent(item), rs )
-			else
-				# Recursion for sub-lists
-				@log.debug &quot;   Recursing for sublist&quot;
-				item = transform_lists( outdent(item), rs ).chomp
-				item = apply_span_transforms( item, rs )
-			end
-
-			%{&lt;li&gt;%s&lt;/li&gt;\n} % item
-		}
-	end
-
-
-	# Pattern for matching codeblocks
-	CodeBlockRegexp = %r{
-		(?:\n\n|\A)
-		(									# $1 = the code block
-		  (?:
-			(?:[ ]{#{TabWidth}} | \t)		# a tab or tab-width of spaces
-			.*\n+
-		  )+
-		)
-		(^[ ]{0,#{TabWidth - 1}}\S|\Z)		# Lookahead for non-space at
-											# line-start, or end of doc
-	  }x
-
-	### Transform Markdown-style codeblocks in a copy of the specified +str+ and
-	### return it.
-	def transform_code_blocks( str, rs )
-		@log.debug &quot; Transforming code blocks&quot;
-
-		str.gsub( CodeBlockRegexp ) {|block|
-			codeblock = $1
-			remainder = $2
-
-			# Generate the codeblock
-			%{\n\n&lt;pre&gt;&lt;code&gt;%s\n&lt;/code&gt;&lt;/pre&gt;\n\n%s} %
-				[ encode_code( outdent(codeblock), rs ).rstrip, remainder ]
-		}
-	end
-
-
-	# Pattern for matching Markdown blockquote blocks
-	BlockQuoteRegexp = %r{
-		  (?:
-			^[ ]*&gt;[ ]?		# '&gt;' at the start of a line
-			  .+\n			# rest of the first line
-			(?:.+\n)*		# subsequent consecutive lines
-			\n*				# blanks
-		  )+
-	  }x
-	PreChunk = %r{ ( ^ \s* &lt;pre&gt; .+? &lt;/pre&gt; ) }xm
-
-	### Transform Markdown-style blockquotes in a copy of the specified +str+
-	### and return it.
-	def transform_block_quotes( str, rs )
-		@log.debug &quot; Transforming block quotes&quot;
-
-		str.gsub( BlockQuoteRegexp ) {|quote|
-			@log.debug &quot;Making blockquote from %p&quot; % quote
-
-			quote.gsub!( /^ *&gt; ?/, '' ) # Trim one level of quoting 
-			quote.gsub!( /^ +$/, '' )	# Trim whitespace-only lines
-
-			indent = &quot; &quot; * TabWidth
-			quoted = %{&lt;blockquote&gt;\n%s\n&lt;/blockquote&gt;\n\n} %
-				apply_block_transforms( quote, rs ).
-				gsub( /^/, indent ).
-				gsub( PreChunk ) {|m| m.gsub(/^#{indent}/o, '') }
-			@log.debug &quot;Blockquoted chunk is: %p&quot; % quoted
-			quoted
-		}
-	end
-
-
-	AutoAnchorURLRegexp = /&lt;((https?|ftp):[^'&quot;&gt;\s]+)&gt;/
-	AutoAnchorEmailRegexp = %r{
-		&lt;
-		(
-			[-.\w]+
-			\@
-			[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
-		)
-		&gt;
-	  }xi
-
-	### Transform URLs in a copy of the specified +str+ into links and return
-	### it.
-	def transform_auto_links( str, rs )
-		@log.debug &quot; Transforming auto-links&quot;
-		str.gsub( AutoAnchorURLRegexp, %{&lt;a href=&quot;\\1&quot;&gt;\\1&lt;/a&gt;}).
-			gsub( AutoAnchorEmailRegexp ) {|addr|
-			encode_email_address( unescape_special_chars($1) )
-		}
-	end
-
-
-	# Encoder functions to turn characters of an email address into encoded
-	# entities.
-	Encoders = [
-		lambda {|char| &quot;&amp;#%03d;&quot; % char},
-		lambda {|char| &quot;&amp;#x%X;&quot; % char},
-		lambda {|char| char.chr },
-	]
-
-	### Transform a copy of the given email +addr+ into an escaped version safer
-	### for posting publicly.
-	def encode_email_address( addr )
-
-		rval = ''
-		(&quot;mailto:&quot; + addr).each_byte {|b|
-			case b
-			when ?:
-				rval += &quot;:&quot;
-			when ?@
-				rval += Encoders[ rand(2) ][ b ]
-			else
-				r = rand(100)
-				rval += (
-					r &gt; 90 ? Encoders[2][ b ] :
-					r &lt; 45 ? Encoders[1][ b ] :
-							 Encoders[0][ b ]
-				)
-			end
-		}
-
-		return %{&lt;a href=&quot;%s&quot;&gt;%s&lt;/a&gt;} % [ rval, rval.sub(/.+?:/, '') ]
-	end
-
-
-	# Regex for matching Setext-style headers
-	SetextHeaderRegexp = %r{
-		(.+)			# The title text ($1)
-		\n
-		([\-=])+		# Match a line of = or -. Save only one in $2.
-		[ ]*\n+
-	   }x
-
-	# Regexp for matching ATX-style headers
-	AtxHeaderRegexp = %r{
-		^(\#{1,6})	# $1 = string of #'s
-		[ ]*
-		(.+?)		# $2 = Header text
-		[ ]*
-		\#*			# optional closing #'s (not counted)
-		\n+
-	  }x
-
-	### Apply Markdown header transforms to a copy of the given +str+ amd render
-	### state +rs+ and return the result.
-	def transform_headers( str, rs )
-		@log.debug &quot; Transforming headers&quot;
-
-		# Setext-style headers:
-		#	  Header 1
-		#	  ========
-		#  
-		#	  Header 2
-		#	  --------
-		#
-		str.
-			gsub( SetextHeaderRegexp ) {|m|
-				@log.debug &quot;Found setext-style header&quot;
-				title, hdrchar = $1, $2
-				title = apply_span_transforms( title, rs )
-
-				case hdrchar
-				when '='
-					%[&lt;h1&gt;#{title}&lt;/h1&gt;\n\n]
-				when '-'
-					%[&lt;h2&gt;#{title}&lt;/h2&gt;\n\n]
-				else
-					title
-				end
-			}.
-
-			gsub( AtxHeaderRegexp ) {|m|
-				@log.debug &quot;Found ATX-style header&quot;
-				hdrchars, title = $1, $2
-				title = apply_span_transforms( title, rs )
-
-				level = hdrchars.length
-				%{&lt;h%d&gt;%s&lt;/h%d&gt;\n\n} % [ level, title, level ]
-			}
-	end
-
-
-	### Wrap all remaining paragraph-looking text in a copy of +str+ inside &lt;p&gt;
-	### tags and return it.
-	def form_paragraphs( str, rs )
-		@log.debug &quot; Forming paragraphs&quot;
-		grafs = str.
-			sub( /\A\n+/, '' ).
-			sub( /\n+\z/, '' ).
-			split( /\n{2,}/ )
-
-		rval = grafs.collect {|graf|
-
-			# Unhashify HTML blocks if this is a placeholder
-			if rs.html_blocks.key?( graf )
-				rs.html_blocks[ graf ]
-
-			# Otherwise, wrap in &lt;p&gt; tags
-			else
-				apply_span_transforms(graf, rs).
-					sub( /^[ ]*/, '&lt;p&gt;' ) + '&lt;/p&gt;'
-			end
-		}.join( &quot;\n\n&quot; )
-
-		@log.debug &quot; Formed paragraphs: %p&quot; % rval
-		return rval
-	end
-
-
-	# Pattern to match the linkid part of an anchor tag for reference-style
-	# links.
-	RefLinkIdRegex = %r{
-		[ ]?					# Optional leading space
-		(?:\n[ ]*)?				# Optional newline + spaces
-		\[
-			(.*?)				# Id = $1
-		\]
-	  }x
-
-	InlineLinkRegex = %r{
-		\(						# Literal paren
-			[ ]*				# Zero or more spaces
-			&lt;?(.+?)&gt;?			# URI = $1
-			[ ]*				# Zero or more spaces
-			(?:					# 
-				([\&quot;\'])		# Opening quote char = $2
-				(.*?)			# Title = $3
-				\2				# Matching quote char
-			)?					# Title is optional
-		\)
-	  }x
-
-	### Apply Markdown anchor transforms to a copy of the specified +str+ with
-	### the given render state +rs+ and return it.
-	def transform_anchors( str, rs )
-		@log.debug &quot; Transforming anchors&quot;
-		@scanner.string = str.dup
-		text = ''
-
-		# Scan the whole string
-		until @scanner.eos?
-		
-			if @scanner.scan( /\[/ )
-				link = ''; linkid = ''
-				depth = 1
-				startpos = @scanner.pos
-				@log.debug &quot; Found a bracket-open at %d&quot; % startpos
-
-				# Scan the rest of the tag, allowing unlimited nested []s. If
-				# the scanner runs out of text before the opening bracket is
-				# closed, append the text and return (wasn't a valid anchor).
-				while depth.nonzero?
-					linktext = @scanner.scan_until( /\]|\[/ )
-
-					if linktext
-						@log.debug &quot;  Found a bracket at depth %d: %p&quot; % [ depth, linktext ]
-						link += linktext
-
-						# Decrement depth for each closing bracket
-						depth += ( linktext[-1, 1] == ']' ? -1 : 1 )
-						@log.debug &quot;  Depth is now #{depth}&quot;
-
-					# If there's no more brackets, it must not be an anchor, so
-					# just abort.
-					else
-						@log.debug &quot;  Missing closing brace, assuming non-link.&quot;
-						link += @scanner.rest
-						@scanner.terminate
-						return text + '[' + link
-					end
-				end
-				link.slice!( -1 ) # Trim final ']'
-				@log.debug &quot; Found leading link %p&quot; % link
-
-				# Look for a reference-style second part
-				if @scanner.scan( RefLinkIdRegex )
-					linkid = @scanner[1]
-					linkid = link.dup if linkid.empty?
-					linkid.downcase!
-					@log.debug &quot;  Found a linkid: %p&quot; % linkid
-
-					# If there's a matching link in the link table, build an
-					# anchor tag for it.
-					if rs.urls.key?( linkid )
-						@log.debug &quot;   Found link key in the link table: %p&quot; % rs.urls[linkid]
-						url = escape_md( rs.urls[linkid] )
-
-						text += %{&lt;a href=&quot;#{url}&quot;}
-						if rs.titles.key?(linkid)
-							text += %{ title=&quot;%s&quot;} % escape_md( rs.titles[linkid] )
-						end
-						text += %{&gt;#{link}&lt;/a&gt;}
-
-					# If the link referred to doesn't exist, just append the raw
-					# source to the result
-					else
-						@log.debug &quot;  Linkid %p not found in link table&quot; % linkid
-						@log.debug &quot;  Appending original string instead: &quot;
-						@log.debug &quot;%p&quot; % @scanner.string[ startpos-1 .. @scanner.pos-1 ]
-						text += @scanner.string[ startpos-1 .. @scanner.pos-1 ]
-					end
-
-				# ...or for an inline style second part
-				elsif @scanner.scan( InlineLinkRegex )
-					url = @scanner[1]
-					title = @scanner[3]
-					@log.debug &quot;  Found an inline link to %p&quot; % url
-
-					text += %{&lt;a href=&quot;%s&quot;} % escape_md( url )
-					if title
-						title.gsub!( /&quot;/, &quot;&amp;quot;&quot; )
-						text += %{ title=&quot;%s&quot;} % escape_md( title )
-					end
-					text += %{&gt;#{link}&lt;/a&gt;}
-
-				# No linkid part: just append the first part as-is.
-				else
-					@log.debug &quot;No linkid, so no anchor. Appending literal text.&quot;
-					text += @scanner.string[ startpos-1 .. @scanner.pos-1 ]
-				end # if linkid
-
-			# Plain text
-			else
-				@log.debug &quot; Scanning to the next link from %p&quot; % @scanner.rest
-				text += @scanner.scan( /[^\[]+/ )
-			end
-
-		end # until @scanner.empty?
-
-		return text
-	end
-
-
-	# Pattern to match strong emphasis in Markdown text
-	BoldRegexp = %r{ (\*\*|__) (\S|\S.+?\S) \1 }x
-
-	# Pattern to match normal emphasis in Markdown text
-	ItalicRegexp = %r{ (\*|_) (\S|\S.+?\S) \1 }x
-
-	### Transform italic- and bold-encoded text in a copy of the specified +str+
-	### and return it.
-	def transform_italic_and_bold( str, rs )
-		@log.debug &quot; Transforming italic and bold&quot;
-
-		str.
-			gsub( BoldRegexp, %{&lt;strong&gt;\\2&lt;/strong&gt;} ).
-			gsub( ItalicRegexp, %{&lt;em&gt;\\2&lt;/em&gt;} )
-	end
-
-	
-	### Transform backticked spans into &lt;code&gt; spans.
-	def transform_code_spans( str, rs )
-		@log.debug &quot; Transforming code spans&quot;
-
-		# Set up the string scanner and just return the string unless there's at
-		# least one backtick.
-		@scanner.string = str.dup
-		unless @scanner.exist?( /`/ )
-			@scanner.terminate
-			@log.debug &quot;No backticks found for code span in %p&quot; % str
-			return str
-		end
-
-		@log.debug &quot;Transforming code spans in %p&quot; % str
-
-		# Build the transformed text anew
-		text = ''
-
-		# Scan to the end of the string
-		until @scanner.eos?
-
-			# Scan up to an opening backtick
-			if pre = @scanner.scan_until( /.?(?=`)/m )
-				text += pre
-				@log.debug &quot;Found backtick at %d after '...%s'&quot; % [ @scanner.pos, text[-10, 10] ]
-
-				# Make a pattern to find the end of the span
-				opener = @scanner.scan( /`+/ )
-				len = opener.length
-				closer = Regexp::new( opener )
-				@log.debug &quot;Scanning for end of code span with %p&quot; % closer
-
-				# Scan until the end of the closing backtick sequence. Chop the
-				# backticks off the resultant string, strip leading and trailing
-				# whitespace, and encode any enitites contained in it.
-				codespan = @scanner.scan_until( closer ) or
-					raise FormatError::new( @scanner.rest[0,20],
-						&quot;No %p found before end&quot; % opener )
-
-				@log.debug &quot;Found close of code span at %d: %p&quot; % [ @scanner.pos - len, codespan ]
-				codespan.slice!( -len, len )
-				text += &quot;&lt;code&gt;%s&lt;/code&gt;&quot; %
-					encode_code( codespan.strip, rs )
-
-			# If there's no more backticks, just append the rest of the string
-			# and move the scan pointer to the end
-			else
-				text += @scanner.rest
-				@scanner.terminate
-			end
-		end
-
-		return text
-	end
-
-
-	# Next, handle inline images:  ![alt text](url &quot;optional title&quot;)
-	# Don't forget: encode * and _
-	InlineImageRegexp = %r{
-		(					# Whole match = $1
-			!\[ (.*?) \]	# alt text = $2
-		  \([ ]*
-			&lt;?(\S+?)&gt;?		# source url = $3
-		    [ ]*
-			(?:				# 
-			  ([&quot;'])		# quote char = $4
-			  (.*?)			# title = $5
-			  \4			# matching quote
-			  [ ]*
-			)?				# title is optional
-		  \)
-		)
-	  }xs #&quot;
-
-
-	# Reference-style images
-	ReferenceImageRegexp = %r{
-		(					# Whole match = $1
-			!\[ (.*?) \]	# Alt text = $2
-			[ ]?			# Optional space
-			(?:\n[ ]*)?		# One optional newline + spaces
-			\[ (.*?) \]		# id = $3
-		)
-	  }xs
-
-	### Turn image markup into image tags.
-	def transform_images( str, rs )
-		@log.debug &quot; Transforming images&quot; # % str
-
-		# Handle reference-style labeled images: ![alt text][id]
-		str.
-			gsub( ReferenceImageRegexp ) {|match|
-				whole, alt, linkid = $1, $2, $3.downcase
-				@log.debug &quot;Matched %p&quot; % match
-				res = nil
-				alt.gsub!( /&quot;/, '&amp;quot;' )
-
-				# for shortcut links like ![this][].
-				linkid = alt.downcase if linkid.empty?
-
-				if rs.urls.key?( linkid )
-					url = escape_md( rs.urls[linkid] )
-					@log.debug &quot;Found url '%s' for linkid '%s' &quot; % [ url, linkid ]
-
-					# Build the tag
-					result = %{&lt;img src=&quot;%s&quot; alt=&quot;%s&quot;} % [ url, alt ]
-					if rs.titles.key?( linkid )
-						result += %{ title=&quot;%s&quot;} % escape_md( rs.titles[linkid] )
-					end
-					result += EmptyElementSuffix
-
-				else
-					result = whole
-				end
-
-				@log.debug &quot;Replacing %p with %p&quot; % [ match, result ]
-				result
-			}.
-
-			# Inline image style
-			gsub( InlineImageRegexp ) {|match|
-				@log.debug &quot;Found inline image %p&quot; % match
-				whole, alt, title = $1, $2, $5
-				url = escape_md( $3 )
-				alt.gsub!( /&quot;/, '&amp;quot;' )
-
-				# Build the tag
-				result = %{&lt;img src=&quot;%s&quot; alt=&quot;%s&quot;} % [ url, alt ]
-				unless title.nil?
-					title.gsub!( /&quot;/, '&amp;quot;' )
-					result += %{ title=&quot;%s&quot;} % escape_md( title )
-				end
-				result += EmptyElementSuffix
-
-				@log.debug &quot;Replacing %p with %p&quot; % [ match, result ]
-				result
-			}
-	end
-
-
-	# Regexp to match special characters in a code block
-	CodeEscapeRegexp = %r{( \* | _ | \{ | \} | \[ | \] | \\ )}x
-
-	### Escape any characters special to HTML and encode any characters special
-	### to Markdown in a copy of the given +str+ and return it.
-	def encode_code( str, rs )
-		str.gsub( %r{&amp;}, '&amp;amp;' ).
-			gsub( %r{&lt;}, '&amp;lt;' ).
-			gsub( %r{&gt;}, '&amp;gt;' ).
-			gsub( CodeEscapeRegexp ) {|match| EscapeTable[match][:md5]}
-	end
-				
-
-
-	#################################################################
-	###	U T I L I T Y   F U N C T I O N S
-	#################################################################
-
-	### Escape any markdown characters in a copy of the given +str+ and return
-	### it.
-	def escape_md( str )
-		str.
-			gsub( /\*/, EscapeTable['*'][:md5] ).
-			gsub( /_/,  EscapeTable['_'][:md5] )
-	end
-
-
-	# Matching constructs for tokenizing X/HTML
-	HTMLCommentRegexp  = %r{ &lt;! ( -- .*? -- \s* )+ &gt; }mx
-	XMLProcInstRegexp  = %r{ &lt;\? .*? \?&gt; }mx
-	MetaTag = Regexp::union( HTMLCommentRegexp, XMLProcInstRegexp )
-
-	HTMLTagOpenRegexp  = %r{ &lt; [a-z/!$] [^&lt;&gt;]* }imx
-	HTMLTagCloseRegexp = %r{ &gt; }x
-	HTMLTagPart = Regexp::union( HTMLTagOpenRegexp, HTMLTagCloseRegexp )
-
-	### Break the HTML source in +str+ into a series of tokens and return
-	### them. The tokens are just 2-element Array tuples with a type and the
-	### actual content. If this function is called with a block, the type and
-	### text parts of each token will be yielded to it one at a time as they are
-	### extracted.
-	def tokenize_html( str )
-		depth = 0
-		tokens = []
-		@scanner.string = str.dup
-		type, token = nil, nil
-
-		until @scanner.eos?
-			@log.debug &quot;Scanning from %p&quot; % @scanner.rest
-
-			# Match comments and PIs without nesting
-			if (( token = @scanner.scan(MetaTag) ))
-				type = :tag
-
-			# Do nested matching for HTML tags
-			elsif (( token = @scanner.scan(HTMLTagOpenRegexp) ))
-				tagstart = @scanner.pos
-				@log.debug &quot; Found the start of a plain tag at %d&quot; % tagstart
-
-				# Start the token with the opening angle
-				depth = 1
-				type = :tag
-
-				# Scan the rest of the tag, allowing unlimited nested &lt;&gt;s. If
-				# the scanner runs out of text before the tag is closed, raise
-				# an error.
-				while depth.nonzero?
-
-					# Scan either an opener or a closer
-					chunk = @scanner.scan( HTMLTagPart ) or
-						raise &quot;Malformed tag at character %d: %p&quot; % 
-							[ tagstart, token + @scanner.rest ]
-						
-					@log.debug &quot;  Found another part of the tag at depth %d: %p&quot; % [ depth, chunk ]
-
-					token += chunk
-
-					# If the last character of the token so far is a closing
-					# angle bracket, decrement the depth. Otherwise increment
-					# it for a nested tag.
-					depth += ( token[-1, 1] == '&gt;' ? -1 : 1 )
-					@log.debug &quot;  Depth is now #{depth}&quot;
-				end
-
-			# Match text segments
-			else
-				@log.debug &quot; Looking for a chunk of text&quot;
-				type = :text
-
-				# Scan forward, always matching at least one character to move
-				# the pointer beyond any non-tag '&lt;'.
-				token = @scanner.scan_until( /[^&lt;]+/m )
-			end
-
-			@log.debug &quot; type: %p, token: %p&quot; % [ type, token ]
-
-			# If a block is given, feed it one token at a time. Add the token to
-			# the token list to be returned regardless.
-			if block_given?
-				yield( type, token )
-			end
-			tokens &lt;&lt; [ type, token ]
-		end
-
-		return tokens
-	end
-
-
-	### Return a copy of +str+ with angle brackets and ampersands HTML-encoded.
-	def encode_html( str )
-		str.gsub( /&amp;(?!#?[x]?(?:[0-9a-f]+|\w+);)/i, &quot;&amp;amp;&quot; ).
-			gsub( %r{&lt;(?![a-z/?\$!])}i, &quot;&amp;lt;&quot; )
-	end
-
-	
-	### Return one level of line-leading tabs or spaces from a copy of +str+ and
-	### return it.
-	def outdent( str )
-		str.gsub( /^(\t|[ ]{1,#{TabWidth}})/, '')
-	end
-	
-end # class BlueCloth
-
+require 'bluecloth/transform'
+BlueCloth.__send__ :include, BlueCloth::Transform</diff>
      <filename>lib/bluecloth.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>7667deac7fdc6cdb738247682b6a9f16ebdfaa0d</id>
    </parent>
  </parents>
  <author>
    <name>Mislav Marohni&#263;</name>
    <email>mislav.marohnic@gmail.com</email>
  </author>
  <url>http://github.com/cpjolicoeur/bluecloth/commit/a2f123d592dda5539fd317f9530a9936e2b6e3f3</url>
  <id>a2f123d592dda5539fd317f9530a9936e2b6e3f3</id>
  <committed-date>2008-04-22T16:47:16-07:00</committed-date>
  <authored-date>2008-04-22T16:47:16-07:00</authored-date>
  <message>split BlueCloth implementation across transform/blocks,inline,links,util files</message>
  <tree>1e5ed6d236208287d74f6d00b7945665d5062092</tree>
  <committer>
    <name>Mislav Marohni&#263;</name>
    <email>mislav.marohnic@gmail.com</email>
  </committer>
</commit>
