181 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Factor
		
	
	
! Copyright (C) 2008 Doug Coleman.
 | 
						|
! See http://factorcode.org/license.txt for BSD license.
 | 
						|
USING: accessors arrays combinators html.elements io io.streams.string
 | 
						|
kernel math memoize namespaces peg peg.ebnf prettyprint
 | 
						|
sequences sequences.deep strings xml.entities vectors splitting
 | 
						|
xmode.code2html ;
 | 
						|
IN: farkup
 | 
						|
 | 
						|
SYMBOL: relative-link-prefix
 | 
						|
SYMBOL: disable-images?
 | 
						|
SYMBOL: link-no-follow?
 | 
						|
 | 
						|
TUPLE: heading1 obj ;
 | 
						|
TUPLE: heading2 obj ;
 | 
						|
TUPLE: heading3 obj ;
 | 
						|
TUPLE: heading4 obj ;
 | 
						|
TUPLE: strong obj ;
 | 
						|
TUPLE: emphasis obj ;
 | 
						|
TUPLE: superscript obj ;
 | 
						|
TUPLE: subscript obj ;
 | 
						|
TUPLE: inline-code obj ;
 | 
						|
TUPLE: paragraph obj ;
 | 
						|
TUPLE: list-item obj ;
 | 
						|
TUPLE: list obj ;
 | 
						|
TUPLE: table obj ;
 | 
						|
TUPLE: table-row obj ;
 | 
						|
TUPLE: link href text ;
 | 
						|
TUPLE: image href text ;
 | 
						|
TUPLE: code mode string ;
 | 
						|
 | 
						|
EBNF: farkup
 | 
						|
nl               = ("\r\n" | "\r" | "\n") => [[ drop "\n" ]]
 | 
						|
2nl              = nl nl
 | 
						|
 | 
						|
heading1      = "=" (!("=" | nl).)+ "="
 | 
						|
    => [[ second >string heading1 boa ]]
 | 
						|
 | 
						|
heading2      = "==" (!("=" | nl).)+ "=="
 | 
						|
    => [[ second >string heading2 boa ]]
 | 
						|
 | 
						|
heading3      = "===" (!("=" | nl).)+ "==="
 | 
						|
    => [[ second >string heading3 boa ]]
 | 
						|
 | 
						|
heading4      = "====" (!("=" | nl).)+ "===="
 | 
						|
    => [[ second >string heading4 boa ]]
 | 
						|
 | 
						|
strong        = "*" (!("*" | nl).)+ "*"
 | 
						|
    => [[ second >string strong boa ]]
 | 
						|
 | 
						|
emphasis      = "_" (!("_" | nl).)+ "_"
 | 
						|
    => [[ second >string emphasis boa ]]
 | 
						|
 | 
						|
superscript   = "^" (!("^" | nl).)+ "^"
 | 
						|
    => [[ second >string superscript boa ]]
 | 
						|
 | 
						|
subscript     = "~" (!("~" | nl).)+ "~"
 | 
						|
    => [[ second >string subscript boa ]]
 | 
						|
 | 
						|
inline-code   = "%" (!("%" | nl).)+ "%"
 | 
						|
    => [[ second >string inline-code boa ]]
 | 
						|
 | 
						|
escaped-char  = "\" .                => [[ second ]]
 | 
						|
 | 
						|
image-link       = "[[image:" (!("|") .)+  "|" (!("]]").)+ "]]"
 | 
						|
                    => [[ [ second >string ] [ fourth >string ] bi image boa ]]
 | 
						|
                  | "[[image:" (!("]").)+ "]]"
 | 
						|
                    => [[ second >string f image boa ]]
 | 
						|
 | 
						|
simple-link      = "[[" (!("|]" | "]]") .)+ "]]"
 | 
						|
    => [[ second >string dup link boa ]]
 | 
						|
 | 
						|
labelled-link    = "[[" (!("|") .)+ "|" (!("]]").)+ "]]"
 | 
						|
    => [[ [ second >string ] [ fourth >string ] bi link boa ]]
 | 
						|
 | 
						|
link             = image-link | labelled-link | simple-link
 | 
						|
 | 
						|
heading          = heading4 | heading3 | heading2 | heading1
 | 
						|
 | 
						|
inline-tag       = strong | emphasis | superscript | subscript | inline-code
 | 
						|
                   | link | escaped-char
 | 
						|
 | 
						|
inline-delimiter = '*' | '_' | '^' | '~' | '%' | '\' | '['
 | 
						|
 | 
						|
table-column     = (list | (!(nl | inline-delimiter | '|').)+ | inline-tag | inline-delimiter  ) '|'
 | 
						|
    => [[ first ]]
 | 
						|
table-row        = "|" (table-column)+
 | 
						|
    => [[ second table-row boa ]]
 | 
						|
table            =  ((table-row nl => [[ first ]] )+ table-row? | table-row)
 | 
						|
    => [[ table boa ]]
 | 
						|
 | 
						|
paragraph-item = ( table | (!(nl | code | heading | inline-delimiter | table ).) | inline-tag | inline-delimiter)+
 | 
						|
paragraph = ((paragraph-item nl => [[ first ]])+ nl+ => [[ first ]]
 | 
						|
             | (paragraph-item nl)+ paragraph-item?
 | 
						|
             | paragraph-item)
 | 
						|
    => [[ paragraph boa ]]
 | 
						|
                
 | 
						|
list-item      = '-' ((!(inline-delimiter | nl).)+ | inline-tag)*
 | 
						|
    => [[ second list-item boa ]]
 | 
						|
list = ((list-item nl)+ list-item? | list-item)
 | 
						|
    => [[ list boa ]]
 | 
						|
 | 
						|
code       =  '[' (!('{' | nl | '[').)+ '{' (!("}]").)+ "}]"
 | 
						|
    => [[ [ second >string ] [ fourth >string ] bi code boa ]]
 | 
						|
 | 
						|
stand-alone      = (code | heading | list | table | paragraph | nl)*
 | 
						|
;EBNF
 | 
						|
 | 
						|
 | 
						|
 | 
						|
: invalid-url "javascript:alert('Invalid URL in farkup');" ;
 | 
						|
 | 
						|
: check-url ( href -- href' )
 | 
						|
    {
 | 
						|
        { [ dup empty? ] [ drop invalid-url ] }
 | 
						|
        { [ dup [ 127 > ] contains? ] [ drop invalid-url ] }
 | 
						|
        { [ dup first "/\\" member? ] [ drop invalid-url ] }
 | 
						|
        { [ CHAR: : over member? ] [
 | 
						|
            dup { "http://" "https://" "ftp://" } [ head? ] with contains?
 | 
						|
            [ drop invalid-url ] unless
 | 
						|
        ] }
 | 
						|
        [ relative-link-prefix get prepend ]
 | 
						|
    } cond ;
 | 
						|
 | 
						|
: escape-link ( href text -- href-esc text-esc )
 | 
						|
    >r check-url escape-quoted-string r> escape-string ;
 | 
						|
 | 
						|
: write-link ( text href -- )
 | 
						|
    escape-link
 | 
						|
    "<a" write
 | 
						|
    " href=\"" write write "\"" write
 | 
						|
    link-no-follow? get [ " nofollow=\"true\"" write ] when
 | 
						|
    ">" write write "</a>" write ;
 | 
						|
 | 
						|
: write-image-link ( href text -- )
 | 
						|
    disable-images? get [
 | 
						|
        2drop "<strong>Images are not allowed</strong>" write
 | 
						|
    ] [
 | 
						|
        escape-link
 | 
						|
        >r "<img src=\"" write write "\"" write r>
 | 
						|
        dup empty? [ drop ] [ " alt=\"" write write "\"" write ] if
 | 
						|
        "/>" write
 | 
						|
    ] if ;
 | 
						|
 | 
						|
: render-code ( string mode -- string' )
 | 
						|
    >r string-lines r>
 | 
						|
    [
 | 
						|
        <pre>
 | 
						|
            htmlize-lines
 | 
						|
        </pre>
 | 
						|
    ] with-string-writer write ;
 | 
						|
 | 
						|
GENERIC: write-farkup ( obj -- )
 | 
						|
: <foo.> ( string -- ) <foo> write ;
 | 
						|
: </foo.> ( string -- ) </foo> write ;
 | 
						|
: in-tag. ( obj quot string -- ) [ <foo.> call ] keep </foo.> ; inline
 | 
						|
M: heading1 write-farkup ( obj -- ) [ obj>> write-farkup ] "h1" in-tag. ;
 | 
						|
M: heading2 write-farkup ( obj -- ) [ obj>> write-farkup ] "h2" in-tag. ;
 | 
						|
M: heading3 write-farkup ( obj -- ) [ obj>> write-farkup ] "h3" in-tag. ;
 | 
						|
M: heading4 write-farkup ( obj -- ) [ obj>> write-farkup ] "h4" in-tag. ;
 | 
						|
M: strong write-farkup ( obj -- ) [ obj>> write-farkup ] "strong" in-tag. ;
 | 
						|
M: emphasis write-farkup ( obj -- ) [ obj>> write-farkup ] "em" in-tag. ;
 | 
						|
M: superscript write-farkup ( obj -- ) [ obj>> write-farkup ] "sup" in-tag. ;
 | 
						|
M: subscript write-farkup ( obj -- ) [ obj>> write-farkup ] "sub" in-tag. ;
 | 
						|
M: inline-code write-farkup ( obj -- ) [ obj>> write-farkup ] "code" in-tag. ;
 | 
						|
M: list-item write-farkup ( obj -- ) [ obj>> write-farkup ] "li" in-tag. ;
 | 
						|
M: list write-farkup ( obj -- ) [ obj>> write-farkup ] "ul" in-tag. ;
 | 
						|
M: paragraph write-farkup ( obj -- ) [ obj>> write-farkup ] "p" in-tag. ;
 | 
						|
M: link write-farkup ( obj -- ) [ text>> ] [ href>> ] bi write-link ;
 | 
						|
M: image write-farkup ( obj -- ) [ href>> ] [ text>> ] bi write-image-link ;
 | 
						|
M: code write-farkup ( obj -- ) [ string>> ] [ mode>> ] bi render-code ;
 | 
						|
M: table-row write-farkup ( obj -- )
 | 
						|
    obj>> [ [ [ write-farkup ] "td" in-tag. ] each ] "tr" in-tag. ;
 | 
						|
M: table write-farkup ( obj -- ) [ obj>> write-farkup ] "table" in-tag. ;
 | 
						|
M: fixnum write-farkup ( obj -- ) write1 ;
 | 
						|
M: string write-farkup ( obj -- ) write ;
 | 
						|
M: vector write-farkup ( obj -- ) [ write-farkup ] each ;
 | 
						|
M: f write-farkup ( obj -- ) drop ;
 | 
						|
 | 
						|
: convert-farkup ( string -- string' )
 | 
						|
    farkup [ write-farkup ] with-string-writer ;
 |