module TaskJuggler::RichTextSyntaxRules
This modules contains the syntax definition for the RichTextParser
. The defined syntax aims to be compatible to the most commonly used markup elements of the MediaWiki system. See en.wikipedia.org/wiki/Wikipedia:Cheatsheet for details.
Linebreaks are treated just like spaces as word separators unless it is followed by another newline or any of the start-of-line special characters. These characters start sequences that mark headlines, bullet items and such. The special meaning only gets activated when used at the start of the line.
The parser traverses the input text and creates a tree of RichTextElement
objects. This is the intermediate representation that can be converted to the final output format.
Public Instance Methods
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 410 def rule_blankLines optional repeatable pattern(%w( $LINEBREAK )) pattern(%w( $SPACE )) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 417 def rule_blockFunction pattern(%w( $BLOCKFUNCSTART $ID !functionArguments $BLOCKFUNCEND ), lambda { args = {} @val[2].each { |arg| args[arg[0]] = arg[1] } if @val[2] el = RichTextElement.new(@richTextI, :blockfunc) # Data is a 2 element Array with the function name and a Hash for the # arguments. unless @richTextI.richText.functionHandler(@val[1], true) error('bad_block_function', "Unsupported block function #{@val[1]}") end el.data = [@val[1], args ] el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 135 def rule_bulletList1 optional repeatable pattern(%w( $BULLET1 !text ), lambda { RichTextElement.new(@richTextI, :bulletitem1, @val[1]) }) pattern(%w( !bulletList2 ), lambda { RichTextElement.new(@richTextI, :bulletlist2, @val[0]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 146 def rule_bulletList2 repeatable pattern(%w( $BULLET2 !text ), lambda { RichTextElement.new(@richTextI, :bulletitem2, @val[1]) }) pattern(%w( !bulletList3 ), lambda { RichTextElement.new(@richTextI, :bulletlist3, @val[0]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 156 def rule_bulletList3 repeatable pattern(%w( $BULLET3 !text ), lambda { RichTextElement.new(@richTextI, :bulletitem3, @val[1]) }) pattern(%w( !bulletList4 ), lambda { RichTextElement.new(@richTextI, :bulletlist4, @val[0]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 166 def rule_bulletList4 repeatable pattern(%w( $BULLET4 !text ), lambda { RichTextElement.new(@richTextI, :bulletitem4, @val[1]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 453 def rule_functionArguments optional repeatable pattern(%w( $ID _= $STRING ), lambda { [ @val[0], @val[2] ] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 74 def rule_headlines pattern(%w( !title1 ), lambda { @val[0] }) pattern(%w( !title2 ), lambda { @val[0] }) pattern(%w( !title3 ), lambda { @val[0] }) pattern(%w( !title4 ), lambda { @val[0] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 395 def rule_htmlBlob repeatable pattern(%w( $HTMLBLOB ), lambda { @val[0] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 434 def rule_inlineFunction pattern(%w( $INLINEFUNCSTART $ID !functionArguments $INLINEFUNCEND !space ), lambda { args = {} @val[2].each { |arg| args[arg[0]] = arg[1] } if @val[2] el = RichTextElement.new(@richTextI, :inlinefunc) # Data is a 2 element Array with the function name and a Hash for the # arguments. unless @richTextI.richText.functionHandler(@val[1], false) error('bad_inline_function', "Unsupported inline function #{@val[1]}") end el.data = [@val[1], args ] el.appendSpace = !@val[4].nil? el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 338 def rule_moreRefToken repeatable optional pattern(%w( _| !refToken ), lambda { @val[1].join }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 173 def rule_numberList1 repeatable pattern(%w( $NUMBER1 !text !blankLines ), lambda { el = RichTextElement.new(@richTextI, :numberitem1, @val[1]) @numberListCounter[0] += 1 el.data = @numberListCounter.dup el }) pattern(%w( !numberList2 ), lambda { @numberListCounter[1, 2] = [ 0, 0 ] RichTextElement.new(@richTextI, :numberlist2, @val[0]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 187 def rule_numberList2 repeatable pattern(%w( $NUMBER2 !text !blankLines ), lambda { el = RichTextElement.new(@richTextI, :numberitem2, @val[1]) @numberListCounter[1] += 1 el.data = @numberListCounter.dup el }) pattern(%w( !numberList3 ), lambda { @numberListCounter[2] = 0 RichTextElement.new(@richTextI, :numberlist3, @val[0]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 201 def rule_numberList3 repeatable pattern(%w( $NUMBER3 !text !blankLines ), lambda { el = RichTextElement.new(@richTextI, :numberitem3, @val[1]) @numberListCounter[2] += 1 el.data = @numberListCounter.dup el }) pattern(%w( !numberList4 ), lambda { @numberListCounter[3] = 0 RichTextElement.new(@richTextI, :numberlist4, @val[0]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 215 def rule_numberList4 repeatable pattern(%w( $NUMBER4 !text !blankLines ), lambda { el = RichTextElement.new(@richTextI, :numberitem4, @val[1]) @numberListCounter[3] += 1 el.data = @numberListCounter.dup el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 225 def rule_paragraph pattern(%w( !text ), lambda { RichTextElement.new(@richTextI, :paragraph, @val[0]) }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 371 def rule_plainText repeatable optional pattern(%w( !htmlBlob !space ), lambda { el = RichTextElement.new(@richTextI, :htmlblob, @val[0].join) el.appendSpace = !@val[1].nil? el }) pattern(%w( $WORD !space ), lambda { el = RichTextElement.new(@richTextI, :text, @val[0]) el.appendSpace = !@val[1].nil? el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 284 def rule_plainTextWithLinks pattern(%w( !plainText ), lambda { @val[0] }) pattern(%w( $REF !refToken !moreRefToken $REFEND !space ), lambda { v1 = @val[1].join if v1.index(':') protocol, locator = v1.split(':') else protocol = nil end el = nil if protocol == 'File' el = RichTextElement.new(@richTextI, :img) unless (index = locator.rindex('.')) error('rt_file_no_ext', "File name without extension: #{locator}") end extension = locator[index + 1..-1].downcase unless %w( jpg gif png svg ).include?(extension) error('rt_file_bad_ext', "Unsupported file type: #{extension}") end el.data = img = RichTextImage.new(locator) if @val[2] @val[2].each do |token| if token[0, 4] == 'alt=' img.altText = token[4..-1] elsif %w( top middle bottom baseline sub super text-top text-bottom ).include?(token) img.verticalAlign = token else error('rt_bad_file_option', "Unknown option '#{token}' for file reference " + "#{v1}.") end end end else val = @val[2] || v1 el = RichTextElement.new(@richTextI, :ref, RichTextElement.new(@richTextI, :text, val)) el.data = v1 el.appendSpace = !@val[4].nil? end el }) pattern(%w( $HREF !wordWithQueries !space !plainTextWithQueries $HREFEND !space ), lambda { el = RichTextElement.new(@richTextI, :href, @val[3] || @val[1]) el.data = RichTextElement.new(@richTextI, :richtext, @val[1]) el.appendSpace = !@val[5].nil? el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 386 def rule_plainTextWithQueries repeatable optional pattern(%w( !wordWithQueries !space ), lambda { @val[0][-1].appendSpace = true if @val[1] @val[0] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 89 def rule_pre repeatable pattern(%w( $PRE ), lambda { @val[0] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 346 def rule_refToken repeatable pattern(%w( $WORD ), lambda { @val[0] }) end
This is the entry node.
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 33 def rule_richtext pattern(%w( !sections . ), lambda { RichTextElement.new(@richTextI, :richtext, @val[0]) }) end
The following syntax elements are all block elements that can span multiple lines.
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 49 def rule_section pattern(%w( !headlines ), lambda { @val[0] }) pattern(%w( $HLINE ), lambda { RichTextElement.new(@richTextI, :hline, @val[0]) }) pattern(%w( !paragraph ), lambda { @val[0] }) pattern(%w( !pre ), lambda { RichTextElement.new(@richTextI, :pre, @val[0].join) }) pattern(%w( !bulletList1 ), lambda { RichTextElement.new(@richTextI, :bulletlist1, @val[0]) }) pattern(%w( !numberList1 ), lambda { @numberListCounter = [ 0, 0, 0, 0 ] RichTextElement.new(@richTextI, :numberlist1, @val[0]) }) pattern(%w( !blockFunction ), lambda { @val[0] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 39 def rule_sections optional repeatable pattern(%w( !section !blankLines ), lambda { @val[0] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 402 def rule_space optional repeatable pattern(%w( $SPACE ), lambda { true }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 231 def rule_text pattern(%w( !textWithSpace ), lambda { @val[0].last.appendSpace = false @val[0] }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 238 def rule_textWithSpace repeatable pattern(%w( !plainTextWithLinks ), lambda { @val[0] }) pattern(%w( !inlineFunction ), lambda { @val[0] }) pattern(%w( $ITALIC !space !plainTextWithLinks $ITALIC !space ), lambda { el = RichTextElement.new(@richTextI, :italic, @val[2]) # Since the italic end marker will disappear we need to make sure # there was no space before it. @val[2].last.appendSpace = false if @val[2].last el.appendSpace = !@val[4].nil? el }) pattern(%w( $BOLD !space !plainTextWithLinks $BOLD !space ), lambda { el = RichTextElement.new(@richTextI, :bold, @val[2]) @val[2].last.appendSpace = false if @val[2].last el.appendSpace = !@val[4].nil? el }) pattern(%w( $CODE !space !plainTextWithLinks $CODE !space ), lambda { el = RichTextElement.new(@richTextI, :code, @val[2]) @val[2].last.appendSpace = false if @val[2].last el.appendSpace = !@val[4].nil? el }) pattern(%w( $BOLDITALIC !space !plainTextWithLinks $BOLDITALIC !space ), lambda { el = RichTextElement.new(@richTextI, :bold, RichTextElement.new(@richTextI, :italic, @val[2])) @val[2].last.appendSpace = false if @val[2].last el.appendSpace = !@val[4].nil? el }) pattern(%w( $FCOLSTART !space !plainTextWithLinks $FCOLEND !space ), lambda { el = RichTextElement.new(@richTextI, :fontCol, @val[2]) el.data = @val[0] el.appendSpace = !@val[4].nil? el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 96 def rule_title1 pattern(%w( $TITLE1 !space !text $TITLE1END ), lambda { el = RichTextElement.new(@richTextI, :title1, @val[2]) @sectionCounter[0] += 1 @sectionCounter[1] = @sectionCounter[2] = 0 el.data = @sectionCounter.dup el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 106 def rule_title2 pattern(%w( $TITLE2 !space !text $TITLE2END ), lambda { el = RichTextElement.new(@richTextI, :title2, @val[2]) @sectionCounter[1] += 1 @sectionCounter[2] = 0 el.data = @sectionCounter.dup el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 116 def rule_title3 pattern(%w( $TITLE3 !space !text $TITLE3END ), lambda { el = RichTextElement.new(@richTextI, :title3, @val[2]) @sectionCounter[2] += 1 @sectionCounter[3] = 0 el.data = @sectionCounter.dup el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 126 def rule_title4 pattern(%w( $TITLE4 !space !text $TITLE4END ), lambda { el = RichTextElement.new(@richTextI, :title4, @val[2]) @sectionCounter[3] += 1 el.data = @sectionCounter.dup el }) end
# File lib/taskjuggler/RichText/SyntaxRules.rb, line 353 def rule_wordWithQueries repeatable pattern(%w( $WORD ), lambda { RichTextElement.new(@richTextI, :text, @val[0]) }) pattern(%w( $QUERY ), lambda { # The <-attributeID-> syntax is a shortcut for an embedded query # inline function. It can only be used within a ReportTableCell # context that provides a property and a scope property. el = RichTextElement.new(@richTextI, :inlinefunc) # Data is a 2 element Array with the function name and a Hash for the # arguments. el.data = ['query', { 'attribute' => @val[0] } ] el }) end