<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"
  xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Counsell's Soks Wiki Textile to HTML</title>
    <link>http://tom.counsell.org</link>
    <description>A vanity site</description>
    <image>
      <url>http://tom.counsell.org/Static/logo.png</url>
      <title>Tom Counsell's Soks Wiki</title>
      <link>http://tom.counsell.org</link>
    </image>
    <item>
      <title>		[ /^\'/, '‘' ], # single opening</title>
      <link>http://tom.counsell.org/view/TextileToHtml</link>
      <description>		[ /^\'/, '‘' ], # single opening&lt;br /&gt;		[ /^&quot;/, '“' ], # double opening&lt;br /&gt;		[ /\'$/, '’' ], # single closing&lt;br /&gt;       	[ /\&quot;$/, '”' ], # double closing&lt;br /&gt;        [ /\.{3}$/, '\1…' ], # ellipsis&lt;br /&gt;        [ '--', '\1—' ], # em dash&lt;br /&gt;        [ '-&gt;', ' ? ' ], # right arrow&lt;br /&gt;        [ '-$', ' – ' ], # en dash&lt;br /&gt;&amp;#8230;&lt;br /&gt;        [ '(TM)', '™' ], # trademark&lt;br /&gt;        [ '(R)', '®' ], # registered&lt;br /&gt;        [ '(C)', '©' ] # copyright&lt;br /&gt;&amp;#8230;&lt;br /&gt;        str.gsub!( '&amp;', '&amp;' )&lt;br /&gt;        str.gsub!( '&quot;', '&quot;' )&lt;br /&gt;        str.gsub!( '&lt;', '&lt;')&lt;br /&gt;        str.gsub!( '&gt;', '&gt;')&lt;br /&gt;&amp;#8230;&lt;br /&gt;Content was also deleted</description>
      <author>tamc</author>
      <pubDate>Tue, 09 Aug 2005 08:43:14 +0000</pubDate>
    </item>
    <item>
      <title>h1. Textile to HTML</title>
      <link>http://tom.counsell.org/view/TextileToHtml</link>
      <description>h1. Textile to HTML&lt;br /&gt;&lt;br /&gt;Textile is a markup language that is meant to make it quick and easy to write basic web pages for wikis, blogs and other uses.  Redcloth is a ruby class that converts textile to html, written by _why.  Details are at http://www.whytheluckystiff.net/ruby/redcloth/ .  Unfortunately, due to my own failings, I find it hard to understand _why's code, so I wrote a partial reimplementation bellow.  This has the benefit of (for me) being clearer and easier to extend.  The drawback is that it doesn't do all that _why's version does and is slower.  But it is here in case anyone finds it useful.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;require 'strscan'&lt;br /&gt;&lt;br /&gt;# Note: Does not implement anything beyond that on http://hobix.com/textile/&lt;br /&gt;# i.e. No markdown, link titles, and converting out of range ASCII&lt;br /&gt;# AND IT IS MUCH SLOWER THAN REDCLOTH !!&lt;br /&gt;#&lt;br /&gt;# Bodged together in a few evenings by Tom Counsell (tamc2@cam.ac.uk)&lt;br /&gt;# Feel free to do whatever you like with the code.&lt;br /&gt;#&lt;br /&gt;# Use is the same as for Redcloth (except that none of the options work):&lt;br /&gt;# html = TextileParser.new( &quot;textile string&quot;).to_html &lt;br /&gt;#&lt;br /&gt;class TextileParser&lt;br /&gt;	&lt;br /&gt;	# These are applied first&lt;br /&gt;	BLOCK_COMMANDS = [&lt;br /&gt;		[ /&lt;pre.*?&gt;/, :pre_tag ], &lt;br /&gt;		[ /&lt;code.*?&gt;/, :code_tag ],&lt;br /&gt;		[ /&lt;notextile.*?&gt;/, :notextile_tag ],&lt;br /&gt;		[ /h(\d)(.*?)\.\s+/i, :heading_block ],&lt;br /&gt;		[ /bq(.*?)\.\s+/i, :quote_block ],&lt;br /&gt;		[ /(\*+|\#+)\s+/,  :list_block ],&lt;br /&gt;		[ /table(.*?)\.\s+/i, :table_block ],&lt;br /&gt;		[ /\|/i, :unspecified_table_block ],&lt;br /&gt;		[ /\{.+?\}\.\s+\|/i, :unspecified_table_block ], # A styled table row		&lt;br /&gt;		[ /p(.*?)\.\s+/i, :paragraph_block ],&lt;br /&gt;		[ /fn(\d+)(.*?)\.\s+/i, :footnote_block ],&lt;br /&gt;		[ /\S+/i, :unspecified_block ],&lt;br /&gt;		[ /\s+/i, :skip ],&lt;br /&gt;	]&lt;br /&gt;	&lt;br /&gt;	# Then these&lt;br /&gt;	COMMANDS = [&lt;br /&gt;		[ /&lt;pre.*?&gt;/, :pre_tag ], # Can be inline as well as in a block&lt;br /&gt;		[ /&lt;code.*?&gt;/, :code_tag ],  # Can be inline as well as in a block&lt;br /&gt;		[ /&lt;notextile.*?&gt;/, :notextile_tag ],  # Can be inline as well as in a block&lt;br /&gt;		[ /@(\S.*?\S)@/, :quick_escape_code ], &lt;br /&gt;		[ /&quot;(.+?)&quot;:(\S*\w\/?)/, :textile_link ],&lt;br /&gt;		[ /\[(.+?)\]:(\S*\w\/?)/, :textile_link_alias ],&lt;br /&gt;		[ /!(.+?)!(\S*)/, :image_link ],&lt;br /&gt;		[ /([A-Z0-9]+)\((.*?)\)/, :acronym ],&lt;br /&gt;		[ /(\S+?)\[(\d+)\]/, :footnote ]&lt;br /&gt;	]	&lt;br /&gt;	&lt;br /&gt;	# Bit of a bodge, but need a different definition of phrase and whitespace in a table&lt;br /&gt;	INLINE_COMMANDS = COMMANDS + [&lt;br /&gt;		[ /\S+/i, :phrase ],&lt;br /&gt;		[ /\s+/i, :space ],&lt;br /&gt;	]&lt;br /&gt;	&lt;br /&gt;	TABLE_INLINE_COMMANDS = COMMANDS + [&lt;br /&gt;		[ /[^\s\t\r\n\f\|]+/i, :phrase ],&lt;br /&gt;		[ /\s+/i, :space ],&lt;br /&gt;	]		&lt;br /&gt;	&lt;br /&gt;	# Then these are applied to phrases from above&lt;br /&gt;	PHRASE_MODIFIERS = [ &lt;br /&gt;		[ '__', 'i' ],&lt;br /&gt;		[ '**', 'b' ],&lt;br /&gt;		[ '_', 'em' ],&lt;br /&gt;		[ '*', 'strong' ],&lt;br /&gt;		[ '??', 'cite' ],&lt;br /&gt;		[ '-', 'del' ],&lt;br /&gt;		[ '+', 'ins' ],&lt;br /&gt;		[ '^', 'sup' ],&lt;br /&gt;		[ '~', 'sub' ],&lt;br /&gt;		[ '%', 'span' ], # How to avoid when people use % as in 3.0% growth?&lt;br /&gt;		].collect! { |regexp,tag| [ /^#{Regexp.escape(regexp)}/, /#{Regexp.escape(regexp)}$/, tag ] }&lt;br /&gt;			&lt;br /&gt;	# Character substitutions done last to any words&lt;br /&gt;	GLYPHS = [&lt;br /&gt;		[ /^\'/, '&amp;#8216;' ], # single opening&lt;br /&gt;		[ /^&quot;/, '&amp;#8220;' ], # double opening&lt;br /&gt;		[ /\'$/, '&amp;#8217;' ], # single closing&lt;br /&gt;       	[ /\&quot;$/, '&amp;#8221;' ], # double closing&lt;br /&gt;        [ /\.{3}$/, '\1&amp;#8230;' ], # ellipsis&lt;br /&gt;        [ '--', '\1&amp;#8212;' ], # em dash&lt;br /&gt;        [ '-&gt;', ' &amp;rarr; ' ], # right arrow&lt;br /&gt;        [ '-$', ' &amp;#8211; ' ], # en dash&lt;br /&gt;&lt;br /&gt;        [ '(TM)', '&amp;#8482;' ], # trademark&lt;br /&gt;        [ '(R)', '&amp;#174;' ], # registered&lt;br /&gt;        [ '(C)', '&amp;#169;' ] # copyright&lt;br /&gt;    ]&lt;br /&gt;    &lt;br /&gt;	# This is just used to give the ouput html a more beautiful layout&lt;br /&gt;	# All tags in here will get a newline after they are output&lt;br /&gt;	# and the indent for following lines increased by the number&lt;br /&gt;	INDENTING_TAGS = { 	'ul' =&gt; 1,&lt;br /&gt;						'ol' =&gt; 1,&lt;br /&gt;						'li' =&gt; 0,&lt;br /&gt;						'blockquote' =&gt; 1,&lt;br /&gt;						'table' =&gt; 1,&lt;br /&gt;						'tr' =&gt; 1,&lt;br /&gt;						'td' =&gt; 0,&lt;br /&gt;						'th' =&gt; 0,&lt;br /&gt;						'p' =&gt; 0,&lt;br /&gt;					 }&lt;br /&gt;	&lt;br /&gt;	def initialize( text )&lt;br /&gt;		@text = text&lt;br /&gt;	end&lt;br /&gt;&lt;br /&gt;	def to_html( settings = nil )&lt;br /&gt;		reset&lt;br /&gt;		convert_text&lt;br /&gt;		return html.chomp.chomp # the tests don't have any trailing \ns&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	private&lt;br /&gt;	&lt;br /&gt;	## Methods dealing with blocks of text are called first&lt;br /&gt;	&lt;br /&gt;	def convert_text&lt;br /&gt;		until @scanner.eos?&lt;br /&gt;			send( BLOCK_COMMANDS.detect { |regexp, method| @scanner.scan( regexp ) }[1] )&lt;br /&gt;			add_to_html &quot;\n&quot; # Prettier html if extra space between blocks &lt;br /&gt;		end&lt;br /&gt;		insert_any_link_aliases&lt;br /&gt;		html&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# These are all the block commands&lt;br /&gt;	&lt;br /&gt;	def paragraph_block&lt;br /&gt;		tag( 'p', parse_attributes( @scanner[1] ) ) do &lt;br /&gt;			standard_paragraph&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def quote_block&lt;br /&gt;		tag( &quot;blockquote&quot;, parse_attributes( @scanner[1] ) ) do&lt;br /&gt;			tag 'p' do&lt;br /&gt;				standard_paragraph&lt;br /&gt;			end&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def unspecified_block&lt;br /&gt;		@scanner.unscan&lt;br /&gt;		tag 'p' do&lt;br /&gt;			standard_paragraph&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;		&lt;br /&gt;	def heading_block&lt;br /&gt;		tag( &quot;h#{@scanner[1]}&quot;, parse_attributes( @scanner[2] ) ) do&lt;br /&gt;			standard_line # Assume titles may only be on one line&lt;br /&gt;		end &lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def list_block&lt;br /&gt;		ordered = list_ordered? # See what sort of list we have&lt;br /&gt;		depth = list_depth&lt;br /&gt;		@scanner.unscan # So that the lines can be scanned individually&lt;br /&gt;		tag( ordered ? 'ol' : 'ul' ) do&lt;br /&gt;			list_line( ordered, depth ) until end_of_list?( depth )&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def table_block&lt;br /&gt;		tag( 'table', parse_attributes( @scanner[1] ) ) do&lt;br /&gt;			table_line until end_of_paragraph?&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def unspecified_table_block&lt;br /&gt;		@scanner.unscan&lt;br /&gt;		tag( 'table' ) do&lt;br /&gt;			table_line until end_of_paragraph?&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def footnote_block&lt;br /&gt;		number = @scanner[1]&lt;br /&gt;		attributes = parse_attributes( @scanner[2] )&lt;br /&gt;		attributes[:id] = &quot;fn#{number}&quot;&lt;br /&gt;		tag 'p', attributes do&lt;br /&gt;			add_to_html &quot;&lt;sup&gt;#{number}&lt;/sup&gt; &quot;&lt;br /&gt;			standard_line until end_of_paragraph?&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# Now descend into methods dealing with lines of text&lt;br /&gt;	&lt;br /&gt;	def pre_tag&lt;br /&gt;		escape_tag 'pre'&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def code_tag&lt;br /&gt;		escape_tag 'code'&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def notextile_tag&lt;br /&gt;		escape_tag 'notextile', false&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# This escapes until a matching close tag&lt;br /&gt;	def escape_tag( tag, include_tag_in_output = true )&lt;br /&gt;		add_to_html( @scanner.matched ) if include_tag_in_output&lt;br /&gt;		level = 1&lt;br /&gt;		while level &gt; 0&lt;br /&gt;			break unless @scanner.scan(/(.*?)(&lt;(\/)?#{tag}.*?&gt;)/m) # Breaks if no closing tag&lt;br /&gt;			add_to_html( htmlesc( @scanner[1] || &quot;&quot; ) )&lt;br /&gt;			level = level + ( @scanner[3] ? -1 : 1 )&lt;br /&gt;			add_to_html( htmlesc( @scanner[2] ) ) unless level == 0&lt;br /&gt;		end&lt;br /&gt;		add_to_html &quot;&lt;/#{tag}&gt;&quot; if include_tag_in_output&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def quick_escape_code&lt;br /&gt;		tag 'code' do &lt;br /&gt;			add_to_html( htmlesc( @scanner[1] ) )&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def list_line( ordered, depth )&lt;br /&gt;		tag 'li' do&lt;br /&gt;			@scanner.scan(/(#+|\*+)\s+/)&lt;br /&gt;			if ( list_ordered? == ordered ) &amp;&amp; ( list_depth == depth )&lt;br /&gt;				standard_line&lt;br /&gt;			else # Recursive for sub lists&lt;br /&gt;				list_block&lt;br /&gt;			end&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;		&lt;br /&gt;	def table_line&lt;br /&gt;		# Are their row attributes at that start of the line?&lt;br /&gt;		attributes = @scanner.scan(/(\{.+?\})\.\s+/) ? parse_attributes(@scanner[1]) : {} 	&lt;br /&gt;		@scanner.scan(/\|/) # Get rid of any leading cell opening&lt;br /&gt;		tag( 'tr', attributes ) do &lt;br /&gt;			table_cell until end_of_table_line?&lt;br /&gt;		end&lt;br /&gt;	end	&lt;br /&gt;	&lt;br /&gt;	def standard_paragraph&lt;br /&gt;		until end_of_paragraph?	&lt;br /&gt;			send( INLINE_COMMANDS.detect { |regexp, method| @scanner.scan( regexp ) }[1] )&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def standard_line&lt;br /&gt;		until end_of_line?&lt;br /&gt;			send( INLINE_COMMANDS.detect { |regexp, method| @scanner.scan( regexp ) }[1] )&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# Now descend into methods dealing with phrases&lt;br /&gt;	&lt;br /&gt;	def table_cell&lt;br /&gt;		# Style defined at start of cell ?&lt;br /&gt;		attributes = @scanner.scan(/(_)?(\S*?)\.\s*/) ?  parse_attributes(@scanner[2]) : {}&lt;br /&gt;		tag( @scanner[1] ? 'th' : 'td', attributes) do &lt;br /&gt;			until end_of_table_cell?&lt;br /&gt;				send( TABLE_INLINE_COMMANDS.detect { |regexp, method| @scanner.scan( regexp ) }[1] )&lt;br /&gt;			end	&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def footnote&lt;br /&gt;		add_to_html &quot;#{@scanner[1]}&lt;sup&gt;&lt;a href=\&quot;#fn#{@scanner[2]}\&quot;&gt;#{@scanner[2]}&lt;/a&gt;&lt;/sup&gt;&quot;&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def acronym&lt;br /&gt;		add_to_html &quot;&lt;acronym title=\&quot;#{@scanner[2]}\&quot;&gt;#{@scanner[1]}&lt;/acronym&gt;&quot;&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def phrase&lt;br /&gt;		word = @scanner.matched&lt;br /&gt;		&lt;br /&gt;		return add_to_html( parse_glyphs( word ) ) unless word =~ /\w+/ # If a word is entirely symbols then we will leave it in peace.&lt;br /&gt;		&lt;br /&gt;		# Open tags&lt;br /&gt;		PHRASE_MODIFIERS.each do |start_r, end_r, tag|&lt;br /&gt;			if word =~ start_r&lt;br /&gt;				word = $' # The bit after the match&lt;br /&gt;				# Look for matching brackets that indicate there are attributes&lt;br /&gt;				if word =~ /(\(.+?\)|\{.+?\}|\[.+?\])/ 				&lt;br /&gt;					open_tag( tag, parse_attributes( $1 ) )&lt;br /&gt;					word = $'&lt;br /&gt;				else&lt;br /&gt;					open_tag tag&lt;br /&gt;				end&lt;br /&gt;				break&lt;br /&gt;			end&lt;br /&gt;		end&lt;br /&gt;		&lt;br /&gt;		# Close tags&lt;br /&gt;		end_tag = nil&lt;br /&gt;		PHRASE_MODIFIERS.each do |start_r, end_r, tag|&lt;br /&gt;			if word =~ end_r&lt;br /&gt;				end_tag = tag&lt;br /&gt;				word = $` # The bit before the match&lt;br /&gt;				break&lt;br /&gt;			end&lt;br /&gt;		end&lt;br /&gt;		add_to_html parse_glyphs( word )&lt;br /&gt;		close_tag( end_tag ) if end_tag&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def space&lt;br /&gt;		add_to_html @scanner.matched&lt;br /&gt;	end&lt;br /&gt;		&lt;br /&gt;	def image_link&lt;br /&gt;		@scanner.matched =~ /^!([&lt;&gt;]*)(.*?)(!|\((.*?)\)!)($|(:(.+?)$))/&lt;br /&gt;		alignment, src, title, url = $1, $2, $4, $7&lt;br /&gt;		attributes = {}&lt;br /&gt;		attributes[:style] = 'float:right' if alignment == '&gt;'&lt;br /&gt;		attributes[:style] = 'float:left' if alignment == '&lt;'&lt;br /&gt;&lt;br /&gt;		attributes[:src] = src&lt;br /&gt;		attributes[:alt] = attributes[ :title ] = title if title&lt;br /&gt;		if url&lt;br /&gt;			tag 'a', { :href =&gt; url } do&lt;br /&gt;				open_tag 'img', attributes, true&lt;br /&gt;			end&lt;br /&gt;		else&lt;br /&gt;			open_tag 'img', attributes, true&lt;br /&gt;		end	&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def skip&lt;br /&gt;		# Do nothing !&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def textile_link&lt;br /&gt;		add_to_html &quot;&lt;a href=\&quot;#{@scanner[2]}\&quot;&gt;#{@scanner[1]}&lt;/a&gt;&quot;&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def textile_link_alias&lt;br /&gt;		# These are saved for later resubstitution&lt;br /&gt;		@aliases[ @scanner[1] ] = @scanner[2]&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# These feels clunky, and is done last&lt;br /&gt;	def insert_any_link_aliases&lt;br /&gt;		@aliases.each do |als, href|&lt;br /&gt;			html.gsub!( /href=&quot;#{als}&quot;/, &quot;href=\&quot;#{href}\&quot;&quot; )&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# These are helper methods that make sure html is properly closed and indented&lt;br /&gt;	&lt;br /&gt;	def tag( tag, attributes = {} )&lt;br /&gt;		open_tag( tag, attributes )&lt;br /&gt;		yield&lt;br /&gt;		close_tag tag&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def close_tag( tag = :all_tags )&lt;br /&gt;		# Check the tag has been opened&lt;br /&gt;		return unless open_tags.include?( tag ) || ( tag == :all_tags )&lt;br /&gt;		&lt;br /&gt;		# Close all tags up to that tag (in case one was not closed)&lt;br /&gt;		until open_tags.empty?&lt;br /&gt;			open_tag = open_tags.pop&lt;br /&gt;			# This is just stuff to make the html look pretty&lt;br /&gt;			if (indent = INDENTING_TAGS[ open_tag ] ) &lt;br /&gt;				if indent == 0&lt;br /&gt;					add_to_html &quot;&lt;/#{open_tag}&gt;&quot;&lt;br /&gt;					add_to_html &quot;\n&quot;&lt;br /&gt;				else&lt;br /&gt;					add_to_html &quot;\n&quot; unless html =~ /\n$/&lt;br /&gt;					@indent -= indent&lt;br /&gt;					add_to_html( &quot;\t&quot; * @indent )&lt;br /&gt;					add_to_html &quot;&lt;/#{open_tag}&gt;&quot;&lt;br /&gt;					add_to_html &quot;\n&quot;&lt;br /&gt;				end&lt;br /&gt;			else&lt;br /&gt;				add_to_html &quot;&lt;/#{open_tag}&gt;&quot;&lt;br /&gt;			end&lt;br /&gt;			return if open_tag == tag&lt;br /&gt;		end&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def open_tag( tag, attributes = {}, no_close_tag = false )&lt;br /&gt;		add_to_html( &quot;\t&quot; * @indent )&lt;br /&gt;		&lt;br /&gt;		add_to_html &quot;&lt;#{tag}&quot;&lt;br /&gt;		&lt;br /&gt;		attributes.each { |key, value| 	add_to_html( &quot; #{key.to_s}=\&quot;#{value.to_s}\&quot;&quot; )	}&lt;br /&gt;		&lt;br /&gt;		if no_close_tag&lt;br /&gt;			add_to_html &quot; /&gt;&quot;&lt;br /&gt;			return&lt;br /&gt;		end&lt;br /&gt;		&lt;br /&gt;		add_to_html &quot;&gt;&quot;&lt;br /&gt;		&lt;br /&gt;		if (indent = INDENTING_TAGS[ tag ] )			&lt;br /&gt;			add_to_html &quot;\n&quot; unless indent == 0&lt;br /&gt;			@indent += indent&lt;br /&gt;		end&lt;br /&gt;		open_tags &lt;&lt; tag&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def open_tags&lt;br /&gt;		@open_tags ||= []&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def parse_attributes( attribute_text )&lt;br /&gt;		return {} unless attribute_text &amp;&amp; attribute_text != &quot;&quot;&lt;br /&gt;		a = { :style =&gt; &quot;&quot; }&lt;br /&gt;		&lt;br /&gt;		# The hand-entered classes, ids, styles and langs&lt;br /&gt;		# These are replaced with &quot;&quot; so their content cannot be matched below&lt;br /&gt;		a[:lang] = $1 if attribute_text =~ /\[(.+?)\]/&lt;br /&gt;		a[:class] = $1 if attribute_text.sub!(/\((.+?)\)/,'')&lt;br /&gt;		a[:class], a[:id] = $1, $2 if a[:class] =~  /^(.*?)#(.*)$/&lt;br /&gt;		a[:style] &lt;&lt; &quot;#{$1};&quot; if attribute_text.sub!(/\{(.+?)\}/,'')&lt;br /&gt;&lt;br /&gt;		# Various padding and indents&lt;br /&gt;		a[:style] &lt;&lt; &quot;padding-left:#{ $1.length }em;&quot; if attribute_text =~ /(\(+)/&lt;br /&gt;		a[:style] &lt;&lt; &quot;padding-right:#{ $1.length }em;&quot; if attribute_text =~ /(\)+)/		&lt;br /&gt;&lt;br /&gt;		# The various alignments&lt;br /&gt;		a[:style] &lt;&lt; &quot;text-align:left;&quot; if attribute_text =~ /&lt;(?!&gt;)/&lt;br /&gt;		a[:style] &lt;&lt; &quot;text-align:right;&quot; if attribute_text =~ /(?!&lt;)&gt;/&lt;br /&gt;		a[:style] &lt;&lt; &quot;text-align:justify;&quot; if attribute_text =~ /&lt;&gt;/&lt;br /&gt;		a[:style] &lt;&lt; &quot;text-align:center;&quot; if attribute_text =~ /=/&lt;br /&gt;		&lt;br /&gt;		#Various column spans on tables&lt;br /&gt;		a[:colspan] = $1 if attribute_text =~ /\\(\d+)/&lt;br /&gt;		a[:rowspan] = $1 if attribute_text =~ /\/(\d+)/&lt;br /&gt;		&lt;br /&gt;		#Vertical alignments on tables&lt;br /&gt;		a[:style] &lt;&lt; &quot;vertical-align:top;&quot; if attribute_text =~ /\^/&lt;br /&gt;		a[:style] &lt;&lt; &quot;vertical-align:bottom;&quot; if attribute_text =~ /\~/&lt;br /&gt;		&lt;br /&gt;		# Get rid of any empty attributes before returning&lt;br /&gt;		a.delete_if { |k,v| !v || (v == &quot;&quot;) }&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def parse_glyphs( word )&lt;br /&gt;		GLYPHS.each do |regexp,replacement|&lt;br /&gt;			word.gsub!( regexp, replacement )&lt;br /&gt;		end&lt;br /&gt;		word&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# Now some helper methods for spotting the ends of sections&lt;br /&gt;	&lt;br /&gt;	def end_of_paragraph?&lt;br /&gt;		return true if @scanner.eos?&lt;br /&gt;		@scanner.scan(/\n{2,}/)&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def end_of_list?( depth )&lt;br /&gt;		return true if @scanner.eos?&lt;br /&gt;		return true unless @scanner.check(/(#+|\*+)\s+/) # Not a list any more&lt;br /&gt;		return true if list_depth &lt; depth # End of this sub list&lt;br /&gt;		@scanner.scan(/\n{2,}/)&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def end_of_line?&lt;br /&gt;		return true if @scanner.eos?&lt;br /&gt;		return true if @scanner.check(/\n{2,}/)&lt;br /&gt;		@scanner.scan(/\n/)&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def end_of_table_line?&lt;br /&gt;		return true if @scanner.eos?&lt;br /&gt;		return true if @scanner.check(/\n{2,}/)&lt;br /&gt;		@scanner.scan(/\|\s*\n/)&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def end_of_table_cell?&lt;br /&gt;		return true if @scanner.eos?&lt;br /&gt;		return true if @scanner.check(/\n/)&lt;br /&gt;		return true if @scanner.check(/\|\s*\n/)&lt;br /&gt;		@scanner.scan(/\|/)&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	# Now some random helper methods for decoding&lt;br /&gt;	&lt;br /&gt;	def list_ordered?&lt;br /&gt;		@scanner.matched[0,1] == '#'&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def list_depth&lt;br /&gt;		@scanner[1].size&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def htmlesc( str )&lt;br /&gt;        str.gsub!( '&amp;', '&amp;amp;' )&lt;br /&gt;        str.gsub!( '&quot;', '&amp;quot;' )&lt;br /&gt;        str.gsub!( '&lt;', '&amp;lt;')&lt;br /&gt;        str.gsub!( '&gt;', '&amp;gt;')&lt;br /&gt;        str&lt;br /&gt;    end&lt;br /&gt;	&lt;br /&gt;	# Now the low level matching functions&lt;br /&gt;	&lt;br /&gt;	def add_to_html( object )&lt;br /&gt;		@html &lt;&lt; object.to_s&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def html&lt;br /&gt;		@html&lt;br /&gt;	end&lt;br /&gt;	&lt;br /&gt;	def reset&lt;br /&gt;		@html, @scanner = &quot;&quot; , StringScanner.new( @text )&lt;br /&gt;		@aliases = {}&lt;br /&gt;		@indent = 0&lt;br /&gt;	end	&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&amp;#8230;&lt;br /&gt;Content was also deleted</description>
      <author>tamc</author>
      <pubDate>Tue, 09 Aug 2005 08:43:13 +0000</pubDate>
    </item>
    <item>
      <title>content moved from [[A re-write of Redcloth textile to html convertor]]</title>
      <link>http://tom.counsell.org/view/TextileToHtml</link>
      <description>content moved from [[A re-write of Redcloth textile to html convertor]]&lt;br /&gt;&amp;#8230;&lt;br /&gt;</description>
      <author>tamc</author>
      <pubDate>Tue, 09 Aug 2005 08:43:13 +0000</pubDate>
    </item>
    <textInput>
      <title>Search</title>
      <description>Search Tom Counsell's Soks Wiki's text</description>
      <name>regex</name>
      <link>http://tom.counsell.org/find/Searchpage</link>
    </textInput>
  </channel>
</rss>