# HTML Generation Facility

#### Copyright (c) Franz Inc.

## Introduction

We've defined a pair of macros which enable a program to generate HTML in a
concise and readable manner. These macros are quite a bit different than those
found in other HTML generation systems and thus we'll briefly describe the
justification for this design.

HTML is a concise markup language. There is a tendency in language design to
assume that one's users won't be as smart as one's self and thus one tends to
dumb things down. For example, HTML uses `<p>` to start a paragraph.  The
language designer says to himself: "while I know that `p` means paragraph, my
users won't so I'll spell it out as **`with-paragraph`**". A similar thing is
done for all the other HTML commands and soon a program to generate HTML
contains so many long markup commands that it's hard to see the text of the
document from the markup commands. A second problem is that as a user you're not
sure exactly what HTML will be generated by some high level **`with-xxx`**
forms. If you're trying to generate a particular sequence of HTML you're
left experimenting with the high level forms and hoping that by luck you get the
output you want. A third problem is that with the high level forms you're forced
to learn yet another markup language. There are plenty of books and reference
guides to HTML itself and it's an easy language to master. Learning a
particular high-level mapping of HTML is an added burden.

With our HTML generation macros you write the actual HTML and we just
eliminate some of the tedious parts, such as closing off markup commands. The
result is that the structure of the document is visible and you can use any book
on HTML as a reference.

## Example

The following example of generated web page will be useful to refer to in the
discussion below of the syntax of the [**`html`**](htmlgen.md#f-html) macro.

```lisp
(defvar *my-counter* 0)  ; initialize counter variable.

(html 
  (:html
    (:head (:title "My Document"))
    (:body (:h1 "My Document")
      "Hello AllegroServe, the time is "
      (:prin1 (get-universal-time))
      ;; evaluated but not printed
      (incf *my-counter*))))
```

This particular example generates a complete web page, but it's possible to use
the [**`html`**](htmlgen.md#f-html) macro to generate partial pages as well. In this example, the
generated page is surrounded by `<html>` and `</html>` due to the **`:html`**
form. The page contains a header and a body surrounded by their respective HTML
markers. The body of the document contains a level 1 header followed by the text
beginning "Hello, AllegroServe". Following that is printed the universal time at
the time that the page is generated (i.e now rather than when the macro was
first processed by lisp). The following **`incf`** expression is evaluated but the
result is not printed. In this case we're keeping a private count of the number
of times this page has been accessed.

## `html` macros

Now that you have a sense of how the [**`html`**](htmlgen.md#f-html) macro works, we will describe the
syntax in detail.

-----

<span id="f-html"></span>
#### **`net.html.generator:html`** \[macro\]

```lisp
(html form1 form2 ... formn)
```

The forms are processed from left to right. The most likely effect is that HTML
output is generated. The output is sent to the stream
**`net.html.generator:*html-stream*`**. The [**`html`**](htmlgen.md#f-html) macro is designed to run
inside AllegroServe's [**`with-http-body`**](aserve.md#f-with-http-body) macro which binds **`*html-stream*`**
to the correct stream. Also the [**`html-stream`**](htmlgen.md#f-html-stream) macro described below binds
**`*html-stream*`** before calling [**`html`**](htmlgen.md#f-html). The action taken by [**`html`**](htmlgen.md#f-html)
depends on what the form looks like at macro-expansion time. The possibilities
are:

  - string - A string is simply written (using **`princ`**) to the output stream.
    Thus the string could contain embedded HTML commands.
  - keyword symbol - The keyword must name a known HTML operator. The result is
    that the associated HTML markup command is sent to the output stream. The
    mapping of keyword to HTML command is trivial - the print name of the
    keyword is the HTML command. So **`:p`** emits `<p>`.
  - list beginning with a keyword symbol - This names an [**`html`**](htmlgen.md#f-html) operator
    that may or may not have an associated inverse operator beginning with
    "/". The typical result of this form is to emit the associated HTML markup
    command, then process the items in the list in the same way as the forms are
    processed, and then emit the inverse markup command. Thus **`(:i "foo")`**
    emits `<i>foo</i>`. There is a special case when a single element list is
    given (see below for details). Also there are some special keywords that are
    commands to the [**`html`**](htmlgen.md#f-html) macro rather than markup commands. They are
    described below.
  - list beginning with a list beginning with a keyword symbol - This is used to
    specify markup commands that have parameters. For example **`((:a href
    "/foo/bar.html") "the link")`** turns into `<a href="/foo/bar.html">the
    link</a>`. The arguments are in plist form: a sequence of names and
    values. The names are **not** evaluated, they should be symbols or
    strings. We often use keyword symbols for the names since that looks more
    lisp-like and reduces the number of symbols we create. The values **are**
    evaluated and printed with a function that escapes characters with special
    meaning in HTML : `<`, `>`, `&`, `"`. If the value is a symbol with a zero
    length print name, then something special is done: The name alone is printed
    without a following equal sign. For example: **`((:option :size 4 :selected
    '||) "foo")`** generates `<option size="4" selected>foo</option>`. This form
    of valueless argument is illegal HTML but in some older browsers it's the
    required syntax.
  - anything else - everything else is simply evaluated in the normal lisp way
    and the value thrown away.

Special cases:

  - **`(:princ arg1 arg2 .. argn)`** causes the result of evaluating each of
    the args to be printed to the HTML stream using the **`princ`** function
    (which prints without inserting escape characters needed by the lisp reader
    to read the result).
  - **`(:prin1 arg1 arg2 ... argn)`** causes the result of evaluating each of
    the args to be printed to the HTML stream using the **`prin1`** function
    (which prints by inserting escape characters needed by the lisp reader to
    read the result).
  - **`(:princ-safe arg1 arg2 .. argn)`** acts like the **`:princ`** case except
    that the output is scanned for characters that could be considered HTML
    markup commands, and if found, these characters are escaped to prevent them
    from being treated as HTML markup commands.
  - **`(:prin1-safe arg1 arg2 .. argn)`** acts like the **`:prin1`** case except
    that the output is scanned for characters that could be considered HTML
    markup commands, and if found, these characters are escaped to prevent them
    from being treated as HTML markup commands.
  - **`:newline`** simply inserts a newline into the HTML output stream. This
    will not have an effect on the result as viewed by a web browser (unless it
    is emitted while inside an HTML markup command that specifies preformatted
    input). The main use for this is to make the resulting HTML file easier to
    read by a human.
  - You can conditionally specify arguments to a markup command using an
    argument name of **`:if*`**. Following the **`:if*`** is a lisp expression
    which if true at runtime will cause the following argument value pair to be
    included in the argument tag. For example **`((:td :if* (frob) :bgcolor
    "\#00ff00") "xx")`** will only put `bgcolor="\#00ff00"` in the argument if
    the expression **`(frob)`** returns true at runtime.
 
-----

<span id="f-html-stream"></span>
#### **`net.html.generator:html-stream`** \[macro\]

```lisp
(html-stream stream form1 form2 ... formn)
```

This binds **`net.html.generator:*html-stream*`** to the value of the stream
argument and then evaluates the **`form*`** arguments just like the [**`html`**](htmlgen.md#f-html)
macro.

## Examples

We will show how to build a page containing a table using successively more
runtime customization of the table. First we show how to build a table of
squares.

```lisp
(defun simple-table-a ()
   (with-open-file (p "test.html"
        :direction :output
        :if-exists :supersede
        :if-does-not-exist :create)

     (html-stream p 
        (:html
         (:head (:title "Test Table"))
         (:body 
           (:table
            (:tr (:th "A") (:th "B"))
            (:tr (:td "0") (:td "0"))
            (:tr (:td "1") (:td "1"))
            (:tr (:td "2") (:td "4"))
            (:tr (:td "3") (:td "9"))
            (:tr (:td "4") (:td "16"))
            (:tr (:td "5") (:td "25"))))))))
```

The function **`simple-table-a`** builds a page containing this table:

| A | B  |
|---|----|
| 0 | 0  |
| 1 | 1  |
| 2 | 4  |
| 3 | 9  |
| 4 | 16 |
| 5 | 25 |

It isn't very pretty but it's easy to see the correspondence between the
[**`html`**](htmlgen.md#f-html) macro and the resulting table. Note that if we had done, for example,
**`(:td 1)`** instead of **`(:td "1")`** then nothing would have been emitted. Only
constant strings are printed, not constant integers. To use an integer here we
would have had to do **`(:td (:princ 1))`**.

We can use the ability to pass arguments to HTML markup commands to specify a
border around the elements of the table as shown here:

```lisp
(defun simple-table-b ()
  (with-open-file (p "test.html"
        :direction :output
        :if-exists :supersede)

    (html-stream p 
        (:html
         (:head (:title "Test Table"))
         (:body 
          ((:table border 2)
            (:tr (:th "A") (:th "B"))
            (:tr (:td "0") (:td "0"))
            (:tr (:td "1") (:td "1"))
            (:tr (:td "2") (:td "4"))
            (:tr (:td "3") (:td "9"))
            (:tr (:td "4") (:td "16"))
            (:tr (:td "5") (:td "25"))))))))
```

The resulting table is:

| A | B  |
|---|----|
| 0 | 0  |
| 1 | 1  |
| 2 | 4  |
| 3 | 9  |
| 4 | 16 |
| 5 | 25 |

  
Suppose we wanted to make the table include the squares of numbers from zero
to 100. That would take a lot of typing. Instead, let's modify the table
generation function to compute a table of any size:

```lisp
(defun simple-table-c (count)
  (with-open-file (p "test.html"
        :direction :output
        :if-exists :supersede)

    (html-stream p 
        (:html
          (:head (:title "Test Table"))
          (:body 
           ((:table border 2)
            (:tr (:th "A") (:th "B"))
            (dotimes (i count)
              (html (:tr (:td (:princ i))
                         (:td (:princ (* i i))))))))))))
```
 

Note that we can freely imbed calls to the [**`html`**](htmlgen.md#f-html) macro within another call.
The **`dotimes`** call inside the **`:body`** expression is simply evaluated and its
value ignored. However the side effect of the **`dotimes`** is to generate more
HTML and to send it to the stream bound in the [**`html-stream`**](htmlgen.md#f-html-stream) call. The result
of **`(simple-table-c 8)`** is

| A | B  |
|---|----|
| 0 | 0  |
| 1 | 1  |
| 2 | 4  |
| 3 | 9  |
| 4 | 16 |
| 5 | 25 |
| 6 | 36 |
| 7 | 49 |

 

We can specify at runtime values for the arguments to HTML markup forms. This
function allows us to specify parameters of the table being built:

```lisp
(defun simple-table-d (count border-width backg-color border-color)
  (with-open-file (p "test.html"
        :direction :output
        :if-exists :supersede)

     (html-stream p 
        (:html
         (:head (:title "Test Table"))
         (:body 
           ((:table border border-width
                bordercolor border-color
                bgcolor backg-color
                cellpadding 3)
            (:tr ((:td bgcolor "blue") 
                  ((:font :color "white" :size "+1")
                   "Value"))
                 ((:td bgcolor "blue") 
                  ((:font :color "white" :size "+1")
                   "Square")))
            (dotimes (i count)
             (html (:tr (:td (:princ i))
                        (:td (:princ (* i i))))))))))))
        
```

This demonstrates that in an HTML markup command argument list the keywords
aren't evaluated but the values are. If we evaluate this expression:

```lisp
    (simple-table-d 10 3 "silver" "blue")
```

then we generate this table:


| Value | Square |
|-------|--------|
| 0     | 0      |
| 1     | 1      |
| 2     | 4      |
| 3     | 9      |
| 4     | 16     |
| 5     | 25     |
| 6     | 36     |
| 7     | 49     |
| 8     | 64     |
| 9     | 81     |

An example of conditional arguments to a markup command is this:

```lisp
(defun simple-table-e (count)
   (with-open-file (p "test.html"
        :direction :output
        :if-exists :supersede)

     (html-stream p 
        (:html
          (:head (:title "Test Table"))
          (:body 
            ((:table border 2)
             (:tr (:th "A") (:th "B") (:th "C") (:th "D") (:th "E") (:th "F"))
             (dotimes (i count)
              (html (:tr 
               (dotimes (j count)
                 (html ((:td :if* (evenp j) :bgcolor "red"
                             :if* (not (evenp j)):bgcolor "green")
                        (:princ (* i j))))))))))))))
```

This sets the color of the columns to alternately red and green:  Here
is **`(simple-table-e 6)`**:

| A | B | C  | D  | E  | F  |
|---|---|----|----|----|----|
| 0 | 0 | 0  | 0  | 0  | 0  |
| 0 | 1 | 2  | 3  | 4  | 5  |
| 0 | 2 | 4  | 6  | 8  | 10 |
| 0 | 3 | 6  | 9  | 12 | 15 |
| 0 | 4 | 8  | 12 | 16 | 20 |
| 0 | 5 | 10 | 15 | 20 | 25 |
 

## HTML generation functions

It's possible to express HTML using Lisp data structures. The form is based on
how HTML is written using the [**`html`**](htmlgen.md#f-html) macro above.

Lisp HTML (**`lhtml`**) is defined as one of the following

  - a string, which is rendered as HTML by simply printing it. Thus the string
    can contain embedded HTML commands.
  - a list beginning with a valid **`lhtml`** keyword and containing **`lhtml`**
    forms. The valid keywords are those corresponding to the HTML entity tags,
    plus the special tags **`:princ`**, **`:princ-safe`**, **`:prin1`**,
    **`:prin1-safe`**, **`:newline`** and **`:comment`**. These act just as they
    do in the [**`html`**](htmlgen.md#f-html) macro. This form is rendered as an opening tag, then
    the rendering of the body, and a closing HTML tag if one exists.
  - a list beginning with a list beginning with an **`lhtml`** keyword. This is
    the form used when attributes are to be supplied with the opening entity
    tag.

Examples of valid **`lhtml`**:

  - `"foo<i>bar</i>baz"`;
  - `(:i "foo")`;
  - `((:body :bgcolor "\#xffffff") "the body")`.
  
-----

<span id="f-html-print"></span>
#### **`net.html.generator:html-print`**

```lisp
(html-print lhtml stream)
```

Print the Lisp HTML expression **`lhtml`** to the **`stream`**.

-----

<span id="f-html-print-list"></span>
#### **`net.html.generator:html-print-list`**

```lisp
(html-print-list lhtml-list stream)
```

Print the list of **`lhtml`** forms to the **`stream`**. This is equivalent to
calling [**`html-print`**](htmlgen.md#f-html-print) on every element of **`lhtml-list`**.
