cl-html-readme

This library provides a means to generate HTML documentation for Common Lisp projects that are using HTML as markup language for their documentation strings.

The goal of this library is to make it easy to generate a table of contents or to structure the documentation with semantic elements. It shall not impose any styling. To accomplish this, the library provides a DSL as well as a couple of helper functions.

The general concept is to declare an HTML skeleton using the DSL of cl-html-readme and to provide the actual documentation and any arbitrary markup as plain HTML strings embedded into it.

The key features of cl-html-readme are

The source code is available here.

Installation

The library is available via Quicklisp. Within the REPL run (ql:quickload "cl-html-readme") to install and (slot-value (asdf:find-system 'cl-html-readme) 'asdf:version) to get the version number of the installed release.

Change-Log

Version 1.0.0

The first release of cl-html-readme.

Version 1.0.1

Changes

Version 2.0.0

Breaking changes

Changes

Version 3.0.0

Breaking changes

New features

DSL

The DSL (Domain Specific Language) of cl-html-readme is used to declare an HTML skeleton consisting of semantic elements, heading elements and a table of contents placeholder. The actual "content" are plain strings that are embedded into this skeleton. These strings are not parsed during the HTML generation but written "as is".

Examples

Heading elements

(defpackage :cl-html-readme-make-readme-dsl-example-heading
  (:use :cl)
  (:documentation "Example: Heading elements"))
(in-package :cl-html-readme-make-readme-dsl-example-heading)

(defun example ()
  (let ((documentation
    `((heading (:name "Example")
         "Lorem ipsum"
         (heading (:name "Chapter 1"))
         "Lorem ipsum"
         (heading (:name "Chapter 2"))
         "<b>Lorem ipsum</b>"))))
    (cl-html-readme:doc-to-html nil documentation)))

;;(example)

Generated HTML

<h1>Example</h1>Lorem ipsum
<h2>Chapter 1</h2>Lorem ipsum
<h2>Chapter 2</h2><b>Lorem ipsum</b>

Semantic elements

(defpackage :cl-html-readme-make-readme-dsl-example-semantic
  (:use :cl)
  (:documentation "Example: Semantic elements"))
(in-package :cl-html-readme-make-readme-dsl-example-semantic)

(defun example ()
  (let ((documentation
    `((semantic (:name "header")
          (heading (:name "Example")))
      (semantic (:name "section")
          (heading (:name "Chapter 1"))
          "Lorem ipsum")
      (semantic (:name "footer") "Lorem ipsum"))))
    (cl-html-readme:doc-to-html nil documentation)))

;;(example)

Generated HTML

<header>
<h1>Example</h1></header>
<section>
<h1>Chapter 1</h1>Lorem ipsum</section>
<footer>Lorem ipsum</footer>

Add a Table of Contents

(defpackage :cl-html-readme-make-readme-dsl-example-toc
  (:use :cl)
  (:documentation "Example: Table of contents"))
(in-package :cl-html-readme-make-readme-dsl-example-toc)

(defun example ()
  (let ((documentation
    `((heading (:name "Example"))
      (heading (:name "Table of contents")
         (toc))
      (heading (:name "Chapter 1" :toc t)) "Lorem ipsum"
      (heading (:name "Chapter 2" :toc t) "<b>Lorem ipsum</b>"
         (heading (:name "Chapter 2.1") "Lorem ipsum")))))
    (cl-html-readme:doc-to-html nil documentation)))

;;(example)

Generated HTML

<h1>Example</h1>
<h1>Table of contents</h1>
<ul>
<li><a href="#Chapter 1">Chapter 1</a></li>
<li><a href="#Chapter 2">Chapter 2</a></li></ul>
<h1 id="Chapter 1">Chapter 1</h1>Lorem ipsum
<h1 id="Chapter 2">Chapter 2</h1><b>Lorem ipsum</b>
<h2>Chapter 2.1</h2>Lorem ipsum

API

*home-directory*

cl-html-readme:*home-directory* 

Home directory of the project for which documentation is to be generated.

*tab-width*

cl-html-readme:*tab-width* 

The width of a tab.

doc-to-html

cl-html-readme:doc-to-html (output-stream documentation)

Renders a documentation object to HTML. The function has the following parameters:

make-path

cl-html-readme:make-path (path)

Creates an absolute path. The function has the following parameters:

read-string

cl-html-readme:read-string (string &key (replace-tabs nil) (escape nil))

Parses a multiline string and returns it as a string. The function has the following parameters:

Example

(defpackage :cl-html-readme-make-readme-dsl-example-escape
  (:use :cl)
  (:documentation "Example: Escaping of characters"))
(in-package :cl-html-readme-make-readme-dsl-example-escape)

(defun example ()
  (let ((documentation
    `((heading (:name "Example"))
      ,(cl-html-readme:read-string
        "<b>Lorum ipsum</b>"
        :escape t))))
    (cl-html-readme:doc-to-html nil documentation)))

;;(example)

Generated HTML

<h1>Example</h1>&lt;b&gt;Lorum ipsum&lt;/b&gt;

read-file

cl-html-readme:read-file (path &key (replace-tabs nil) (escape nil))

Reads a text file and returns it as a string. The function has the following parameters:

read-stream

cl-html-readme:read-stream (stream &key (replace-tabs nil) (escape nil))

Reads a text stream and returns it as a string. The function has the following parameters:

Rendering Hooks

Rendering hooks provide a means to add custom attributes to the HTML output. A hook is a function that is called with the properties of the (typically) current DSL special form and returns a property list containing the additional attributes. Attribute names are represented by keywords. Attributes are omitted from rendering in the following cases: In the case of multiple occurences of an attribute the last one that is eligable for rendering wins.

Example

(defpackage :cl-html-readme-make-readme-example-rendering-hook
  (:use :cl)
  (:documentation "Example: Rendering hook"))
(in-package :cl-html-readme-make-readme-example-rendering-hook)

(defun example ()
  (let ((documentation
    `((heading (:name "Header" :toc t :app (:class "heading-class"))))))
    (let ((cl-html-readme:*get-heading-attributes*
      (lambda (properties)
        (list
         :class nil
         :class "CLASS"
         :class (getf (getf properties :app) :class)
         :class nil
         :a nil
         :b (list "")
         :c ""
         :id "ID"))))
      (cl-html-readme:doc-to-html nil documentation))))

;;(example)

Generated HTML

<h1 c="" class="heading-class" id="Header">Header</h1>

*get-heading-attributes*

cl-html-readme:*get-heading-attributes* 

Get the attributes of a heading form. A heading is rendered as a "<h1>" ... "<h6>" HTML element. The hook is called with the properties of the DSL heading form.

*get-semantic-attributes*

cl-html-readme:*get-semantic-attributes* 

Get the attributes of a semantic form. A semantic form is rendered as a "<${properties.name}>" HTML element. The hook is called with the properties of the DSL semantic form.

*get-toc-root-attributes*

cl-html-readme:*get-toc-root-attributes* 

Get the attributes of the TOC root form. This form is created during the TOC expansion. The TOC root is rendered as a "<ul>" HTML element. The hook is called with the properties of the DSL toc form.

*get-toc-container-attributes*

cl-html-readme:*get-toc-container-attributes* 

Get the HTML attributes of a TOC container form. Such forms are created during the TOC expansion. A container is an entry of the TOC that has sub-entries. Containers are rendered as "<ul>" HTML elements. The hook is called with the properties of the DSL toc form.

*get-toc-item-attributes*

cl-html-readme:*get-toc-item-attributes* 

Get the attributes of a TOC item form. Such forms are created during the TOC expansion. Each entry of the TOC is represented by an item. Items are rendered as "<li>" HTML elements. The hook is called with the properties of the DSL toc form.

Run tests

(asdf:test-system :cl-html-readme)

Generate documentation

(asdf:load-system :cl-html-readme/doc)
(cl-html-readme-make-doc::make-doc)