File: user-guide.md

package info (click to toggle)
cl-markdown 20101006-2
  • links: PTS, VCS
  • area: main
  • in suites: buster, jessie, jessie-kfreebsd, stretch
  • size: 556 kB
  • sloc: lisp: 5,863; makefile: 11
file content (171 lines) | stat: -rw-r--r-- 6,528 bytes parent folder | download | duplicates (2)
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}