ElementFactory
Defines constructor methods used to build each of the elements in knockoff. This
can then be easily overriden by specialized versions of the block or span elements,
so that the output BlockSeq might render things a bit differently, for example.
HasElementFactory
For any Discounter, there should really only be one, configurable,
ElementFactory instance. And for the things that need to fetch that instance,
there is the HasElementFactory trait.
// In com/tristanhunt/knockoff/HasElementFactory.scala
package com.tristanhunt.knockoff
trait HasElementFactory {
def elementFactory : ElementFactory = defaultElementFactory
private val defaultElementFactory = new ElementFactory
}
Note that the top-level element, Discounter, maintains this reference as well. So
customizing the ElementFactory is pretty simple. You create a subtype of
ElementFactory, then override that in your custom Discounter instance:
// Your custom ElementFactory
// You probably want something like this to bind in prettification in your
// HTML documents...
class MyCodeSpan( content : String ) extends CodeSpan( content ) {
override def = <code class="myCodeClass">{ content }</code>
}
class MyElementFactory extends ElementFactory {
override def codeSpan( c : String ) = new MyCodeSpan( c )
}
class MyDiscounter extends Discounter {
override val elementFactory = new MyElementFactory
}
ElementFactory
// In com/tristanhunt/knockoff/ElementFactory.scala
// See the ElementFactory package and imports
class ElementFactory {
// Block Elements
def para( s : SpanSeq, p : Position ) =
new Paragraph( s, p )
def head( l : Int, s : SpanSeq, p : Position ) =
new Header( l, s, p )
def hr( p : Position ) =
new HorizontalRule( p )
def linkdef( i : String, u : String, t : Option[ String ], p : Position ) =
new LinkDefinition( i, u, t, p )
def blockquote( c : Seq[ Block ], p : Position ) : Blockquote =
new Blockquote( c, p )
def codeBlock( s : String, p : Position ) : CodeBlock =
codeBlock( text(s), p )
def codeBlock( t : Text, p : Position ) : CodeBlock =
new CodeBlock( t, p )
def olist( olis : OrderedItem * ) : OrderedList =
new OrderedList( olis )
def ulist( ulis : UnorderedItem * ) : UnorderedList =
new UnorderedList( ulis )
def uli( b : Block, p : Position ) : UnorderedItem =
new UnorderedItem( b, p )
def uli( bs : Seq[ Block ], p : Position ) : UnorderedItem =
new UnorderedItem( bs, p )
def oli( b : Block, p : Position ) : OrderedItem =
new OrderedItem( b, p )
def oli( bs : Seq[ Block ], p : Position ) : OrderedItem =
new OrderedItem( bs, p )
// Span Elements
def text( c : String ) = new Text( c )
/** A shorthand for text (popular with my tests) */
def t( c : String ) = text( c )
def em( s : Seq[ Span ] ) : Emphasis =
new Emphasis( s )
def strong( s : Seq[ Span ] ) : Strong =
new Strong( s )
def link( c : SpanSeq, u : String, t : Option[ String ] ) : Link =
new Link( c, u, t )
def link( c : SpanSeq, u : String ) : Link = link( c, u, None )
def link( c : SpanSeq, ld : LinkDefinition ) : IndirectLink =
new IndirectLink( c, ld )
def ilink( c : SpanSeq, u : String, t : Option[ String ] ) : ImageLink =
new ImageLink( c, u, t )
def ilink( c : SpanSeq, u : String ) : ImageLink = ilink( c, u )
def ilink( c : SpanSeq, ld : LinkDefinition ) : IndirectImageLink =
new IndirectImageLink( c, ld )
def codeSpan( c : String ) : CodeSpan =
new CodeSpan( c )
def htmlSpan( h : String ) : HTMLSpan =
new HTMLSpan( h )
// Uh... fun with my object model?
def toSpan( seq : Seq[ Span ] ) : Span =
if ( seq.length == 1 ) seq.first else new GroupSpan( seq )
}
I used heavy abbreviation in this class in order to draw focus to the types.
ElementFactory - Package and Imports
// The ElementFactory package and imports
package com.tristanhunt.knockoff
import scala.io.Source
import scala.util.parsing.input.Position