1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
{include resources/ug-header.md}
{set-property title "CL-Markdown User's Guide"}
# CL-Markdown - Quick Start
{table-of-contents :start 2 :depth 3}
CL-Markdown is an enhanced version of John Gruber's [Markdown][] text
markup langauge. Markdown's goal is to keep text readable as *text* and
as HTML. CL-Markdown keeps this principle and adds a flexible extension
mechanism so that you can build complex documents easily.
[Markdown]: http://daringfireball.net/projects/markdown/
### Getting Started
The easiest way to install CL-Markdown is using the
[bundle][]. You can also use [ASDF-Install][], download
tarballs or grab the sources directly (usings [darcs][]). If
you do use the bundle, here is what you'd do:
shell> cd <lisp-sources>
shell> curl http://common-lisp.net/project/cl-markdown/cl-markdown-bundle.tar.gz > cl-markdown-bundle.tar.gz
shell> tar -zxvf cl-markdown-bundle.tar.gz
shell> lisp
;; Super Lisp 5.3 (just kidding)
lisp: (require 'asdf)
lisp: (load "cl-markdown-bundle/cl-markdown.asd")
lisp: (asdf:oos 'asdf:load-op 'cl-markdown)
lisp: (in-package cl-markdown)
The top-level CL-Markdown command is `markdown`. It creates a
`document` from a source (pathname, stream or string) and
then sends the document to a stream in a `format`. The
default format is `:html` and the default output is `t`
(which sends the output to `*standard-output*`.). You can use
an already open stream for output, provide a pathname to a
file (which will be overwritten!) or use the symbol `nil` to
direct output to a new stream. At this time, support for
formats other than HTML is not provided. For example:
lisp: (markdown "# Hello *there*")
"<h1>Hello <em>there</em></h1>"
CL-Markdown implements most of John Gruber's
[specification][markdown-specification] (though it does not
yet handle e-mails and some edges cases). It also adds a new
syntax for extensions.
[markdown-specification]: http://daringfireball.net/projects/markdown/syntax
### Function calls: \{ and \}
Calling extension functions requires three things:
1. writing (or finding) the extension that you want
2. telling CL-Markdown that you want to use the extension
3. writing your Markdown text with calls to the extension
The last part is the easiest; all you need to do is open a
curly brace, type the name of extension function, type in the
arguments (separated by spaces) and type a closing curly
brace. For example:
"\{now\}" will generate the text "{now}".
The second step is necessary because CL-Markdown won't
recognize functions as functions unless you tell it to up
front. After all, you wouldn't want to allow people to
execute arbitrary code; it **might** be a security risk
(smile). Because CL-Markdown operates in two stages, there
are two times when functions can be called: during parsing
and during rendering. Functions active during these stages
are keep in the special variables `*render-active-functions*`
and `*parse-active-functions*`.
An example might make this clearer. First, we'll call Markdown
without specifying any functions:
? (markdown "Today is {today}. It is {now}."
:format :html :stream t)
<P>Today is
; Warning: Inactive or undefined CL-Markdown function TODAY
; While executing: #<STANDARD-METHOD RENDER-SPAN-TO-HTML ((EQL EVAL) T)>
. It is
; Warning: Inactive or undefined CL-Markdown function NOW
; While executing: #<STANDARD-METHOD RENDER-SPAN-TO-HTML ((EQL EVAL) T)>
. </P>
As you can see, the functions weren't ones that CL-Markdown was ready
to recognize, so we got warnings and no text was generated. If we
tell CL-Markdown that `today` and `now` should be treated as
functions, then we see a far prettier picture:
? (let ((*render-active-functions*
(append '(today now) *render-active-functions*)))
(markdown "Today is {today}. It is {now}."
:format :html :stream t))
<P>Today is 1 August 2006. It is 11:36. </P>
By now, we've seen how to include function calls in CL-Markdown
documents and how to generate those documents with CL-Markdown. The
final piece of the puzzle is actually writing the extensions.
#### Writing Cl-Markdown extensions
There are several ways to write extensions. {footnote
Extensions beg for a little {abbrev DSL Domain Specific
Language} but those macros are still to be written.} The
easiest is one is to write functions active during rendering
that return the text that you wish to be included in the
document. For example:
(defun today (phase arguments result)
(declare (ignore phase arguments result))
(format-date "%e %B %Y" (get-universal-time)))
The format-date command is part of [metatilities-base][]; it
returns a string of the date using the C library inspired
date format. This string is placed in the document whereever
the function call (\{today\}) is found.
[metatilities]:
Alternately, one can use the `*output-stream*` variable to
insert more complicated text. This would look like:
(defun now (phase arguments result)
(declare (ignore phase arguments result))
(format *output-stream* "~a"
(format-date "%H:%M" (get-universal-time)))
nil)
(Note that `now` returns `nil` so that the date isn't inserted
twice!).
The other alternative is to use your function calls to alter
the structure of the CL-Markdown document and then let
Markdown deal with some or all of the rest. The `anchor`
extension provides an example of this:
(defun anchor (phase &rest args)
(ecase phase
(:parse
(let ((name (caar args))
(title (cadar args)))
(setf (item-at (link-info *current-document*) name)
(make-instance 'link-info
:id name :url (format nil "#~a" name)
:title (or title "")))))
(:render (let ((name (caar args)))
(format nil "<a id='~a' id='~a'></a>"
name name)))))
`Anchor` makes it easier to insert anchors into your document
and to link to those anchors from elsewhere. It is active
during both parsing and rendering. During the parsing phase,
it uses it's arguments to determine the name and title of the
link and places this into the current document's link
information table. During rendering, it outputs the HTML
needed to mark the link. {footnote If you would like to see
more examples, look in the files `extensions.lisp` or
`footnotes.lisp`.}
<hr>
{footnotes}
{include resources/ug-footer.md}
|