REBOL [
    Title: "Specs Document Converter (Text to HTML)"
    Date: 8-Jun-2000
    File: %makespec.r
    Author: "Carl Sassenrath"
    Purpose: {(See MakeDoc2 for the latest version.)
We use this script to save a lot of time when writing specification documents here at REBOL HQ. Very little notation is required to produce good looking HTML documents with titles, table of contents, section headers, indented fixed-spaced examples, "sidebars", and more. Does all the formatting so we can focus on writing the words (the hard part).}
    History: [
        10-Jun-2000 "Posted to library" 
        8-Mar-2000 "Merged features: TOC, HR, etc." 
        29-Feb-2000 "Fixed newline bug" 
        12-Oct-1999 orig
    ]
    Example: {  (This would be flush left in text editor)
        First line is The Title

        ===Section Title

        Section paragraph here.

        ---Subsection Title

        This is a subsection paragraph.

            Code examples are indented and monospaced

        #indent
            This is a specially indented paragraph.
        /indent

        #side This is the sidebar label
            And this is the text of the sidebar.
        /side
    }
    library: [
        level: 'intermediate 
        platform: 'all 
        type: 'tool
        domain: [text-processing markup] 
        tested-under: none 
        support: none 
        license: none 
        see-also: none
    ]
    Version: 1.0.0
]

text-to-html: make object! [
    html: make string! 10000
    emit: func [data] [append html reduce data]
    code: text: none
    subnum: sectnum: toc-marker: 0
    sections: []
    space: charset " ^-"
    chars: complement charset " ^-^/"
    font: 
    marg-in: 
marg-out:
escape-html: func [ "Format a code example" code ][ replace/all code "&" "&" replace/all code "<" "<" replace/all code ">" ">" insert code [
]
        append code reduce [
newline] ] ;--- Text Format Language: rules: [title some parts done] title: [text-line (emit [textfont

text

])] parts: [newline | "===" section | "---" subsect | "#indent" (emit marg-in) | "/indent" (emit marg-out) | "#side" side | "/side" (emit []) | "###" to end (emit [marg-out "-End-"]) | example | paragraph] section: [ text-line ( if sectnum > 0 [emit marg-out] sectnum: sectnum + 1 subnum: 1 if sectnum = 1 [toc-marker: length? html] emit [{


} {}] emit [

font

(head insert text reduce [sectnum ". "])

] append sections rejoin [{} text ] emit marg-in ) newline ] subsect: [text-line (emit [

font

head insert trim text reduce [sectnum "." subnum ". "]

] subnum: subnum + 1) newline] example: [copy code some [indented | some newline indented] (emit escape-html code)] paragraph: [copy para some [chars thru newline] (emit [para

])] done: [(emit [])] text-line: [copy text thru newline] indented: [some space thru newline] side: [text-line (emit [
text
]) ] make-contents: func [] [ html: skip html toc-marker html: insert html reduce [


font

"Contents:"

marg-in] foreach section sections [ html: insert html reduce [section
] ] insert html reduce [
marg-out

] html: head html ] convert: func [data] [ clear html: head html subnum: sectnum: toc-marker: 0 sections: clear [] parse/all detab data rules make-contents html ] ] file: to-file ask "Filename? " if not empty? file [ if not find file ".txt" [append file ".txt"] if not exists? file [print ["Error:" file "does not exist"] halt] data: text-to-html/convert read file write head change find file "." ".html" data ]