Welcome to gendoc!

The gendoc tool is a small tool that generates documentation into a formatted static HTML. It is similar to Sphinx and ReadtheDocs, but much better and way cooler, because it has no server component parts and works without JavaScript too.

Hint

This documentation is short, a LOT shorter that RtD's. This isn't because I was lazy to write it, but because gendoc is really simple to use! You know, "Keep it Simple, Stupid!"

Advantages

  • Available as an ANSI C tool as well as a PHP script (both dependency-free).
  • Looks like, feels like ReadtheDocs, but it works without internet connection too.
  • Unlike Sphinx, gendoc is easy to use, and generates a single static file (which passes W3C's HTML5 validation btw).
  • The gendoc document is free of dependencies and external resources, no third party CSS nor webfonts required.
  • Does not depend on jQuery or any other third party libraries and has no server component parts.
  • You can download a gendoc document to your computer and use it as a local file, everything will work, even the search!
  • It also works with JavaScript turned off! Everything (except the search) is based on CSS-only solutions.
  • Much smaller and cleaner CSS + HTML than what Sphinx generates, using selectors instead of classnames whenever possible.
  • A lot easier to theme than Sphinx, and the generated documentation has responsive design out-of-the-box.
  • It includes a much better generic syntax highlighter than Sphinx, works with any language but you can add langauge-specific rules too
  • Has a built-in API generation tool, but you can add plugins if you don't like its output format (which is pretty basic)

Disadvantages

  • Unlike RtD, gendoc does not provide hosting. But since docs are just single files and we have gitlab, github, etc. this isn't a real issue. (Maybe letting you have a copy of your own documentation and not taking it away from you into the cloud isn't a disadvantage at all...)


Getting started

Download

First things first, download the source or the script from the repo. Both are single files, about 100 kilobytes each. Seriously, no dependencies (other than a php interpreter for the script of course). Everything is included sucklessly.

Usage

For the ANSI C Version

$ gcc gendoc.c -o gendoc
$ ./gendoc <output.html> <input file> [input file...]

And with the PHP version

$ php ./gendoc.php <output> <input file> [input file...]

Output

The output's format is detected by the extension, and in lack of a writer plugin for that extension, defaults to a single, W3C valid, self-contained, dependency-free HTML5 file that you can take anywhere with you (just like the one you're reading now).

The output of the ANSI C version and PHP version should be identical bit-to-bit (except if you have the php-gd extension installed, then the PHP version will transparently shrink the inlined images to save storage space).

Input Files

You can use one input file, or multiple files. It doesn't matter, gendoc will generate a single output file either way. You have full control in how you organize your source documents, it doesn't inflience the output (not like Sphinx).

Input files likewise to the output, their format is detected by extension, and in lack of a reader plugin defaults to gendoc tags.

Note

The ANSI C version only reads gendoc tags and only generates into HTML5 output format, it does not support file format reader / writer plugins. It has a built-in filter to convert MarkDown into gendoc though, based on smu. The PHP plugin uses an extended ParseDown class.



Creating Documents

You write simple text files, by default with tags similar to HTML, but MUCH MUCH simpler. You can also add plugins to support any input format, like ReadFirst or MarkDown. This documentation hereafter talks about the default gendoc tags format.

There are two categories for the tags. The tags in the first one specify the meta and overall structure of the documentation.

Specifying Meta Info

These are enclosed in <doc>...</doc>. Pretty simple, they just specify some variable data and translated labels for the document, most notably for the Alert Boxes. The <doc> should be the first tag in the source documentation file. Its subtags are as follows:

<title>...</title>
Specifies the title of the document, shown at different places, on the top left and on the windowbar too for example
<titleimg>(filename) ...</titleimg>
Optionally specify a title image. The filename is a path relative to the source document, and the remaining text after the space will be used as alt attribute as well as added to the title string as a prefix.
<url>...</url>
The URL where the big title on the top left leads.
<version>...</version>
The version string shown below the title on the top left.
<theme>...</theme>
Specifies the name of the CSS file for customizing theme (and the theme only).
<lang>...</lang>
The documentation's language in two letter ISO-639-1 format. Only informational, I don't think anybody cares what's in the HTML tag's lang attribute.
<rslt>...</rslt>
The translated "Search Results" string.
<home>...</home>
The translated "Home" string (tooltip for the breadcrumbs navigation above).
<link>...</link>
The translated tooltip for the heading links, "Permalink to this heading".
<info>...</info>
The translated header of the info type alerts, "Info" or "Important" or something.
<note>...</note>
The translated header of the "Note" type alerts.
<also>...</also>
The translated header of the "See Also" type alerts.
<todo>...</todo>
The translated header of the "To Do" type alerts.
<warn>...</warn>
The translated header of the "Warning" type alerts.
<args>...</args>
The translated header of the "Arguments" table (used by the API generator).
<rval>...</rval>
The translated header of the "Return Value" table (used by the API generator).
<prev>...</prev>
The translated label on the previous page button on the bottom.
<next>...</next>
The translated label on the next page button on the bottom.
<copy>...</copy>
Finally, the content of the copyright label at the bottom.

For example:

<doc>
    <titleimg>logo.png gendoc</titleimg>
    <title>documentation</title>
    <url>https://bztsrc.gitlab.io/gendoc</url>
    <version>1.0.0</version>
    <theme>theme.css</theme>
    <lang>en</lang>
    <rslt>Search Results</rslt>
    <home>Home</home>
    <link>Permalink to this headline</link>
    <info>Important</info>
    <hint>Hint</hint>
    <note>Note</note>
    <also>See Also</also>
    <todo>To Do</todo>
    <args>Arguments</args>
    <rval>Return Value</rval>
    <warn>Warning</warn>
    <prev>Previous</prev>
    <next>Next</next>
    <copy>2022 bzt (bztsrc@gitlab)</copy>
</doc>

Note

If both <titleimg> and <title> is given, then the actual title is concatenated from the alt text and the <title> tag, therefore will be "gendoc documentation" in the above example.

Table of Contents

The following tags influences how the TOC on the left is generated. These tags are

<cap>...</cap>
which adds a caption to the TOC, and the
<h1>...</h1>, <h2>...</h2>, up to <h6>...</h6>
heading tags.

The <h1> tag opens a new page. Other sub-headings add sections to that page. The links and urls are automatically generated from the heading's text, but just in case the generated name doesn't suit your needs, you can specify the label id by hand with <h1 (id)>, <h2 (id)>, <h3 (id)> etc.

For example:

<h1>Simple Heading</h1>                    (will use "simple_heading" as label)
<h1 my_specific_label>Another Heading</h1> (will use "my_specific_label")

The Welcome Page

You can enclose the first, and exactly one <h1> tag with its subheadings in a

<hello>...</hello>
Encloses the welcome headings and sections

These headings will then be excluded from the Table of Contents, and in return will be shown as a welcome page. Also the "Home" link in the breadcrumbs navigation above will lead to this page instead of the first entry in the TOC.

Include Source Document

<include (filename)>
This tag includes another source document just as if it were given on the command line.

Security Considerations

None. It is assumed that Alice needs a documentation, so Alice writes the input files and Alice runs gendoc on her local computer, and hopefully Alice doesn't want to hack Alice (maybe if she is schizofrenic?). In short, there's only one party in the generation process.

Then Bob receives the generated static HTML only, and Bob has no access to the input files and does not run gendoc nor gets he involved with the documentation generation process in any way. All he gets is the final static product.

If Alice uploads the documentation to a server, that's not an issue either, because gendoc has absolutely no server component parts. Bob will download the documentation to his local computer (probably into his browser's local cache), and the search runs only on Bob's local computer. If Bob tries to hack the search, he will only get bad search results on his own computer, but won't influence Cecil or other document readers.



Formatting

The second category is for the tags that you use to format the document. gendoc liftens the burden of modern web from your shoulders, eases your mind from the madness of stylesheets and context-neutral tags, and you can use simple tags just the way as Sir Burners Lee originally intended.

In a well-formated source document no other tags than listed here should exists (forget <span>,<div> etc.). But to provide backward compatibility with HTML, this isn't enforced by the generators, all tags that are not recognized by gendoc are copied verbatim to the final documentation (with a warning).

Warning

Don't let the resemblence fool you! gendoc tags aren't HTML tags, they just look like it to shorten your learning curve significantly.

Warning

As soon as you write your first tag attribute, then you can be sure that you're doing it wrong.

All tags have a corresponding closing tag, except <include>, <api>, <br>, <mb*> and <img*> (where '*' can be l,r,w). This is validated and errors are reported for each section individually.

Styling Texts

<h1>...</h1>, <h2>...</h2>, up to <h6>...</h6>
To style text as a heading.
<b>...</b>
Makes the text bold.
<i>...</i>
Makes the text italic (or oblique).
<u>...</u>
Makes the text underlined.
<s>...</s>
Makes the text striked-through.
<sup>...</sup>
Makes the text superscript.
<sub>...</sub>
Makes the text subscript.
<tt>...</tt>
Makes the text to use monospace font. It also disables interpretation of tags inside. All the tags you can see on this page are printed with <tt>. (You do not need to know what &lt; and &gt; are and what the hell is that &amp;lt; doing there...)
<quote>...</quote>
Makes the text a
quote, don't think you'll need this in a documentation, but just in case.

Structuring Texts

<p>...</p>
You wrap your paragraphs in, well, paragraphs. This element has no visual, it just separates blocks of text. If you have displaying issues, try wrapping the text in a paragraph.
<br>
Break line. Use only if you really really have to. This tag has no closing pair.
<ol>...</ol>, <ul>...</ul>, <li>...</li>
Ordered <ol>...</ol> and unordered <ul>...</ul> lists. Both are enclosing list item <li>...</li> tags. Do not want to have fancy list bullets, those are extremely annoying for documentation readers.
  1. one
    1. one and a half
  2. two
  • one
    • one and a half
  • two
<dl>...</dl>, <dt>...</dt>, <dd>...</dd>
Data blocks, like this one you're reading now. The list is enclosed in <dl>...</dl> tags, and contains multiple topics and descriptions. The topic is in <dt>...</dt>, and the description is in <dd>...</dd>.
<grid>...</grid>, <gr>...</gr>, <gd>/<gD>...</gd>
The grid rows <gr>...</gr> are enclosed in <grid>...</grid> tags. Each row contains one or more <gd> grid cells. It looks like and works like an invisible table with equal sized cells. The upper-case <gD> opening tag makes the cell wide.
<table>...</table>, <tr>...</tr>, and <th>/<tH>, <td>/<tD>, <tn>/<tN>
The table rows <tr>...</tr> are enclosed in <table>...</table> tags. Each row contains one or more table cells. Here <th>...</th> formats as header, <tH>...</th> as wide-header (looks the same as header, but scretches the coloumn wide). The <td>...</td> is for table data and makes the cell left-aligned, but if you need right-alignment (like for decimal numbers), use <tn>...</tn>. If you don't have headers, but you need wide cells, then you can use the upper-case opening variants, like <tD> and <tN> to scretch cells.
Sample header 1Sample header 2Sample header 3
Sample data 1Sample data 2Sample data 3
Sample data 4Sample data 5Sample data 6

Preformatted Text

<pre>...</pre>
Just like <tt>, changes font to monospace and disables tag parsing, but what's more it provides an optionally scrollable area around the text. <pre> is for any text or program output or command line samples.
This is an example
   pre-formatted text with
  multiple lines and which is very very long, so long that it does not fit into the screen and a scrollbar should appear.
<hl>...</hl>, <hm>...</hm>
Highlights parts of <pre> (and <code>) blocks. Use <hl> to highlight something, or <hm> to hightlight entire, multiple lines.
This is an example
   pre-formatted text which has
   some highlighted text,
      and even
some highlighted
 entire
 lines
as an example

Source Code

<code>...</code>,<code (lang)>...</code>
Just like <pre>, provides scrollbars, etc., but <code> should contain program source code which will be syntax highlighted. By default it uses a generic highlighter, but you can add rules to specific languages with plugins and specify the language like <code c>,<code php>,<code python> etc. Inside the code block, you can use <hl>...</hl> and <hm>...</hm> to manually hightlight some part of the code ("World" inside a string literal in this example):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdlib.h> /* comment1 multiline */ // single line comment2 int main(int argc, char **argv) { volatile static int i, a = 0xff, b = -1ULL; wchar_t c = L'\e', *d = L"wide string"; float e = 1.0f, f = .5, g = -1e10; for(i = 0; i < 128; i++) a += b->c; printf("Hello World!\n"); }
<api (lang) (filename)>

This tag generates a simple API documentation for a source file written in the specified programming language. The default formatting is pretty basic, but it supports any language that accepts C-style multiline comments (that is, C, C++, PHP, JavaScript, Java, Go, Rust etc.). Furthermore, you can use plugins to add custom formatting and to support any programming language or doctype standard.

For an example, see this documentation's API section.

There are two kinds of links in the document:

<a>...</a>
Creates an internal link to one of the headings, for example <a>Getting Started</a> looks like this: Getting Started. Internal links always open in the same tab as the document.
<a (url)>...</a>
External link. These open a new tab, except when url starts with a `#`.

User Input

In a software documentation it is very common that you have to explain how user input is done. gendoc helps you with that a lot.

<ui1>...</ui1>, <ui2>...</ui2>, up to <ui6>...</ui6>
These do nothing in particular, but you can style them from the theme to mimic your software's user interface elements. For example: "set the checkbox and then click on the Save button".
<kbd>...</kbd>
This is used to represent keyboard buttons, like <kbd>Ctrl</kbd> + <kbd>C</kbd> looks like Ctrl + C.
<mbl>, <mbr>, <mbw>
Represents mouse buttons and wheel. These tags has no closing pair, they are like images. The <mbl> looks like , the right button <mbr> like , and the wheel <mbw> like . Originally I wanted to use UNICODE "upper left quadrant" and "upper right quadrant" glyphs with a gradient background and round border, but some fonts (*khm* FreeSans) has those incorrectly swapped, and it displayed very differently with different fonts (not sure why, <kbd> is quite consistent and so where the mouse wheel with U+2579). Anyway this looks better, but depending on browsers might be a few pixels vertically off in conjunction with <kbd>, like
Alt + .

Images

<imgt (filename)>
Insert an image gplv3.png into the document as inlined text. The filename is a path relative to the source document. The image tags have no closing pair.
<imgl (filename)>
gplv3.pngInsert an image into the document which is aligned on the left and floated around with text. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex commondo consequat.
<imgr (filename)>
gplv3.pngInsert an image into the document which is aligned on the right and floated around with text. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex commondo consequat.
<imgc (filename)>
Insert an image into the document which is centered and not floated around with text.
gplv3.png
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<imgw (filename)>
Insert a wide image into the document which is centered and not floated around with text.gplv3.pngFigure: GPLv3+ logo (sorry about the quality of the image)Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<fig>...</fig>
Sets the image's caption, like <imgw figure.png><fig>Figure: blah blah</fig>.

Alert Boxes

For these boxes, the header's text can be defined in the <doc> tag.

<hint>...</hint>
Creates a hint box, like this one:

Hint

This is a hint

<info>...</info>
Creates an informational box, like this one:

Important

This is an important information

<note>...</note>
Creates a note box, like this one:

Note

This is a note

<also>...</also>
Creates a see also box, like this one:

See Also

A good movie. You have played with the computer too much.

<warn>...</warn>
Creates a warning box, like this one:

Warning

This is a warning

<todo>...</todo>
Creates a to do box, like this one:

To Do

You probably should never use this, finish your code instead.



MarkDown

You can choose to use MarkDown for your source format. For that, use the .md extension on your input files. The ANSI C version has a built-in parser, the PHP version needs a plugin. In both cases, you can mix simple MarkDown with gendoc tags (not HTML), like <mbl>, <imgl> etc.

Note

Use the <doc> tag just like you would with the XML format to specify the meta data.

Table of Contents

Uses standard MD, lines underlined with equal sign = will make <h1> headings, the hypen - will make <h2> headings. You can also use the hashmark # prefix, where the number of hashmarks sets the heading's level (from one to six).

Heading 1
=========

Heading 2
---------

# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6

Styling Texts

These are not really MD standard.

** ... **
Makes the text bold.
* ... *
Makes the text italic (or oblique).
_ ... _
Makes the text underlined.
~ ... ~
Makes the text striked-through.
^^ ... ^^
Makes the text superscript.
,, ... ,,
Makes the text subscript.
` ... `
Makes the text to use monospace font.
> ...
Lines staring with > are groupped together and presented as a quote.
> this is a quote
> this also belongs to the same quote
> I don't think you'll need this in a documentation

Structuring Texts

Empty lines
Empty lines start and end a paragraph.
Two spaces at the end of the line
Break line. Use only if you really really have to.
Lists with * ..., - ..., + ..., 1. ...
Ordered and unordered lists. Can be nested.
* unordered list 1
* unordered list 2
* unordered list 3
- unordered list 1
- unordered list 2
- unordered list 3
1. ordered list 1
2. ordered list 2
3. ordered list 3
Tables
Again, almost standard, looks like:
| Sample header 1 | Sample header 2 | Sample header 3 |
|-----------------|-----------------|----------------:|
| Sample data 1   | Sample data 2   |   Sample data 3 |
| Sample data 4   | Sample data 5   |   Sample data 6 |
In the second line if there's a double-punct colon (like |----:|), then that coloumn will be right aligned (no matter where the : located). In addition to MD, if it contains an asterisk * on the left (like |*----|), then it will make a wide data cell, if its on the right (like |----*|), then a wide number cell (so location matters).

Preformatted Texts

``` ... ```
Just like ` ... `, also changes font to monospace and disables tag parsing, but what's more it provides an optionally scrollable area around the text. This is for any text or program output or command line samples.

Source Code

```(lang) ... ```
Just like ```, provides scrollbars, etc., but it should contain program source code which will be syntax highlighted. By default it uses a generic highlighter, but you can add rules to specific languages with plugins and specify the language like ```c, ```php, ```python etc. Inside the code block, you can use <hl>...</hl> and <hm>...</hm> to manually hightlight some part of the code.

There are two kinds of links in the document:

[(text)]
Creates an internal link to one of the headings, for example [Getting Started] looks like this: Getting Started. Internal links always open in the same tab as the document.
[(text)]((url))
External link. These open a new tab, except when url starts with a `#`.

Images

![(text description)]((filename))
Insert a wide image with image caption into the document which is centered and not floated around with text. (For more control, you can use the <imgt>, <imgl> etc. tags).

Alert Boxes

Standard paragraphs which start with one of the following strings are converted into alert boxes.

HINT:
Converts paragraph into a hint box.
INFO:
Converts paragraph into an informational box.
NOTE:
Converts paragraph into a note box.
SEE ALSO:, ALSO:
Converts paragraph into a see also box.
WARNING:, WARN:
Converts paragraph into a warning box.
TODO:
Converts paragraph into a to do box, do not use, rather finish your code.


Customizing Theme

Now this part is really much simpler than with Sphinx and ReadtheDocs. Unlike with those, here the logic and the look'n'feel are truly separated. Yes, I know that RtD has two stylesheet references, but look at the .css files! The main css has color codes in it, and the theme css is full of setting margins, paddings, overflows, displays etc. That will not do!

Hint

In gendoc all the navigation logic is implemented in CSS. No JavaScript is needed!

The Theme Tag

First of all, you specify the theme with the <doc>'s tag <theme>...</theme> sub-tag. This should contain a filename relative to the source document.

The Theme CSS

Although the CSS is a valid stylesheet, it only includes just a few, specific DOM selectors with only theming attributes.

DOM SelectorDescription
hr,table,th,tdSet the border's color and the table header's background color if you want to.
trSet altering row background colors.
aSet the color and decoration for links.
.contentChange the entire documentation's overall default font color and font family here.
.titleChange the look of the big area on the top left.
.title, .home,
h1>a,h2>a,h3>a,
h4>a,h5>a,h6>a
You should set the same background color for these for a good looking theme.
.searchChange the colors of the search input box.
.navChange the font color and background color of the navigation bar.
.nav pThe TOC caption selector. Also sets the look of the "Search Results" caption.
.nav labelInactive top level TOC entry
.nav .currentThe active top level TOC entry
.nav aSearch result TOC entry
.nav li>ul>liBackground of sub-levels
.nav li>ul>li>aForeground of sub-levels
.preBackground and border of the preformatted blocks
.info, .hint, .warnChange the alert boxes' background color.
.info>p:firstchildThe alert boxes' header, change the background color.
.btnThe style of the "Previous" and "Next" buttons at the bottom.
.ui1, .ui2, .ui3,
.ui4, .ui5, .ui6
You can use these classes to mimic your software user interface's input elements, like buttons for example.

That's about it. This list covers all the important and changeable selectors of the theme CSS. Isn't that too much, right?

Warning

NEVER change the logic from a theme CSS, like setting "display", "position" etc. attributes! Only change the background color, border color, font color, font family, font size etc.

Syntax Highlight

For that, you have to define a few classes in your theme CSS. There's really only a few, these classes are generic to all languages:

ClassDescription
.hl_hManually highlighted part.
.hl_cSyntax highlight comment.
.hl_pSyntax highlight pseudo element (like precompiler directives, could be the same as comments).
.hl_oSyntax highlight operator.
.hl_nSyntax highlight number literal.
.hl_sSyntax highlight string literal.
.hl_tSyntax highlight type.
.hl_kSyntax highlight keyword.
.hl_fSyntax highlight function.
.hl_vSyntax highlight variable.

Theme Example

hr,table,th,td{border-color:#e1e4e5;}
th{background:#d6d6d6;}
tr:nth-child(odd){background:#f3f6f6;}
a{text-decoration:none;color:#2980B9;}
.content{background:#fcfcfc;color:#404040;font-family:Helvetica,sans-serif;}
.title,.home,h1>a,h2>a,h3>a,h4>a,h5>a,h6>a{background:#2980B9;color:#fcfcfc;}
.version{color:rgba(255,255,255,0.3);}
.search{border:1px solid #2472a4;background:#fcfcfc;}
.nav{background:#343131;color:#d9d9d9;}
.nav p{color:#55a5d9;}
.nav label:hover,.nav a:hover{background:#4e4a4a;}
.nav .current{background:#fcfcfc;color:#404040;}
.nav li>ul>li{background:#e3e3e3;}
.nav li>ul>li>a{color:#404040;}
.nav li>ul>li>a:hover{background:#d6d6d6;}
.pre {border:1px solid #e1e4e5;background:#f8f8f8;}
.info{background:#e7f2fa;}
.info>p:first-child{background:#6ab0de;color:#fff;}
.hint{background:#dbfaf4;}
.hint>p:first-child{background:#1abc9c;color:#fff;}
.warn{background:#ffedcc;}
.warn>p:first-child{background:#f0b37e;color:#fff;}
.btn{background:#f3f6f6;}
.btn:hover{background:#e5ebeb;}
.ui1{font-family:Serif;font-size:12px;border-radius:3px;background:#cfcfcf;}
.hl_h{background-color:#ccffcc;}
.hl_c{color:#808080;font-style:italic;}
.hl_p{color:#1f7199;}
.hl_o{color:#404040;}
.hl_n{color:#0164eb;}
.hl_s{color:#986801;}
.hl_t{color:#60A050;}
.hl_k{color:#a626a4;}
.hl_f{color:#2a9292;}
.hl_v{color:#e95649;}


Plugins

Plugins are located in the same directory as the gendoc.php file, under the "plugins" sub-directory. The ANSI C version also checks the "/usr/share/gendoc/plugins" directory. They are named consistently, with a prefix that tells what kind of plugin that is.

Note

The similarity between File Reader and Writer Plugins isn't a coincidence: the same File Format Plugin can implement both reader and writer functionalities.

Syntax Highlighter Plugins

Named as plugins/hl_(lang).json, for example plugins/hl_python.json.

Used by both the ANSI C version and the PHP version. The generic highlighter works pretty well with any programming language (worst case scenario, some language keywords or special operators are highlighted as a variable). But just in case you need some language specific stuff, you can add rules with these plugins. These files should contain an RFC 8259 compliant JSON string with an array of the following fields:

IndexDescription
0an array of regexp that match comments
1an array of regexp that match pesudo elements (like precompiler directives)
2an array of regexp that match operators (like +, -, *, /, >=, =, <= etc.)
3an array of regexp that match numbers (usually [0-9]+, but could match floating point numbers too)
4an array of strings that start and end string literals (usually ", ', ` but could be L", b' etc.)
5an array of characters that always separate tokens (usually {, }, ; etc.)
6an array of strings that match types (these are keywords, just highlighted differently, like true, false, nullptr etc.)
7an array of strings that match keywords (like function, for, forach etc.)

Strings are matched case-insensitively, and for compatibility and performance reasons, regular expressions are allowed to contain these rules only (most notably no parenthesis allowed):

IndexDescription
$matches end of line
.*?matches zero or more occurance of any character until the pattern that follows matches (for example .*?abc matches anything until abc matches)
.matches any character
[(list)]matches the characters in the list. List may contain (start)-(end) intervals, therefore to match hypen, use \-
[(list)]?matches zero or one occurance of the characters in the list
[(list)]+matches multiple (at least one or more) occurance of the characters in the list
[(list)]*matches multiple (zero or more) occurance of the characters in the list
[^(list)]matches any character that's not in the list
[^(list)]?matches zero or one occurance of any character that's not in the list
[^(list)]+matches multiple (at least one or more) occurance of any character that's not in the list
[^(list)]*matches multiple (zero or more) occurance of any character that's not in the list

Note that slash (/) and backslash (\) always has to be escaped. For example:

plugins/hl_c.json
1
2
3
4
5
6
7
8
9
10
11
/* syntax highlight rules for the C language */ [ /* 0 comments */ [ "\/\/.*?$", "\/\*.*?\*\/" ], /* 1 pseudo */ [ "#.*?$" ], /* 2 operators */ [ "->", "[=\<\>\+\-\*\/%&\^\|!:\.][=]?" ], /* 3 numbers */ [ "[0-9][0-9bx]?[0-9\.a-f\+\-]*[UL]*" ], /* 4 strings */ [ "\"", "'", "L\"", "L'" ], /* 5 separators */ [ "[", "]", "{", "}", ",", ";" ], /* 6 types */ [ "char", "short", "int", "long", "float", ... ], /* 7 keywords */ [ "if", "else", "switch", "case", "for", ... ] ]

API Documenting Plugins

Named as plugins/api_(lang).php, for example plugins/api_python.php.

These plugins should implement a single function by the name gendoc_api_(lang), which receives the source file's content, parses it for doctype comments and calls various gendoc:: methods to generate output.

For example:

plugins/api_c.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php /* generate API documentation for the C language */ function gendoc_api_c($str) { /* get all comments with doctype strings in it */ if(preg_match_all("/\/\*\*[^\*](.*?)\*\/[\n](.*?)$/ims", $s, $M, PREG_SET_ORDER)) { gendoc::data_list_open(); foreach($M as $m) { gendoc::data_topic_open(); gendoc::source_code($m[2], "c"); gendoc::data_topic_close(); gendoc::data_description_open(); /* generate a good-looking output from the comment here */ gendoc::data_description_close(); } gendoc::data_list_close(); } }

Input File Reader Plugins

Named as plugins/fmt_(extension).php, for example plugins/fmt_rst.php.

These plugins (just like File Writer Plugins) should implement a class by the name gendoc_(extension). For a reader, one static method is required, called gendoc_(extension)::parse, which receives the source document's content as string, parses it and calls various gendoc:: methods to generate output. The file reader plugins are responsible for increasing the line number counter in gendoc::$l whenever they parse a newline character (required for correct error reporting).

For example:

plugins/fmt_md.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php /* MarkDown file format reader plugin */ class gendoc_md { public static parse($str) { /* do something with the source document in $str * and call gendoc methods to generate output */ gendoc::heading(1, "The Hundread Years Old Man Who Climbed Out on the Window and Disappeared"); gendoc::heading(2, "Chapter 1"); gendoc::paragraph_open(); gendoc::text("Lorem ipsum sic dolor amet"); gendoc::paragraph_close(); gendoc::heading(2, "Chapter 2"); /* ... */ /* keep the current line counter up-to-date */ gendoc::$l++; } }

Alternatively if generating the output through calling methods isn't feasable, an Input Reader Plugin could return a string with gendoc tags.

plugins/fmt_ext.php
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php /* A file format reader plugin that does not use gendoc:: methods */ class gendoc_ext { public static parse($str) { /* do something with the source document in $str * and generate output string with gendoc tags */ return "<h1>The Hundread Years Old Man Who Climbed Out on the Window and Disappeared</h1>". "<h2>Chapter 1</h2>". "<p>Lorem ipsum sic dolor amet</p>". "<h2>Chapter 2</h2>"; } }

Warning

This returns gendoc tags, and not HTML tags.

Output File Writer Plugins

Named as plugins/fmt_(extension).php, for example plugins/fmt_md.php.

These plugins (just like File Reader Plugins) should implement a class by the name gendoc_(extension). For a writer, all methods must be implemented that are marked as "has to be implemented by writer plugins" in the API list below. Furthermore, they must instantiate that class and return an instance.

For example:

plugins/fmt_pdf.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php /* PDF file format writer plugin */ class gendoc_pdf { /* hooks to generate output to this instance */ public function heading($level, $id, $name) { /* ... */ } public function paragraph_open() { /* ... */ } public function paragraph_close() { /* ... */ } public function source_code($str, $type = "", $tokens = []) { /* ... */ } /* ... more methods ... */ /* output this instance to a file */ public function output($fn) { $f = fopen($fn, "wb+"); if(!$f) { gendoc::report_error("unable to write file"); die; } /* print out in format */ fclose($f); } } /* this is very important! */ return new gendoc_pdf;

A little on implementing the source code hook: the plugin gets the source as string in $str, but doesn't have to parse it on its own, because gendoc also passes the source in a tokenized form as well (the third $tokens parameter). Here each array element is another array with the following fields:

IndexDescription
0the type of the token ("" text, "c" comment, "o" operator, "n" number, "s" string, "k" keyword, "t" type, "v" variable, same as in the highlight CSS classes)
1string, the part of the source included in this token

Both for preformatted text and source code the File Format Writer plugin is responsible for handling the <hl> and <hm> tags (which are included in the $str input string, no matter the format).

Hint

Concatenating the 2nd fields in the tokens array should result in the original source code string.

API

These methods are used by the plugins. Save a few, which are only implemented in the gendoc class and listed at the beginning, the writer plugins have to implement all of these (as non-static functions). Reader plugins have to implement the static parse method only, but they call these methods in order to generate output.

1
public static function safeid($str)
Convert a string into an URL and id attribute-safe string. Sometimes it sucks that internet was designed by English only speakers. gendoc class only method.
Arguments
string input
Return Value
string the converted string

1
public static function report_error($msg)
Report an error. gendoc class only method.
Arguments
string error message

1
public static function api($c, $fn)
Generate API documentation. gendoc class only method.
Arguments
string language
string file name

1
public static function include($fn) {
Include another source document. gendoc class only method.
Arguments
string file name

1
public static function doc($str)
Parse <doc> tag. gendoc class only method.
Arguments
string with <doc> sub-tags

1
public static function hello_open()
Start <hello> tag. gendoc class only method.

1
public static function hello_close()
End <hello> tag. gendoc class only method.

1
public static function caption($name)
Add a caption to TOC. gendoc class only method.
Arguments
string caption's name

1
public static function heading($level, $name, $id = "", $alias = "")
Add a heading. Has to be implemented by writer plugins.
Arguments
string "1" to "6"
string heading user-readable name
string heading label id

1
public static function paragraph_open()
Start a paragraph. Has to be implemented by writer plugins.

1
public static function paragraph_close()
End a paragraph. Has to be implemented by writer plugins.

1
public static function bold_open()
Start bold text. Has to be implemented by writer plugins.

1
public static function bold_close()
Stop bold text. Has to be implemented by writer plugins.

1
public static function italic_open()
Start italic text. Has to be implemented by writer plugins.

1
public static function italic_close()
Stop italic text. Has to be implemented by writer plugins.

1
public static function underline_open()
Start underlined text. Has to be implemented by writer plugins.

1
public static function underline_close()
Stop underlined text. Has to be implemented by writer plugins.

1
public static function strike_open()
Start striked-through text. Has to be implemented by writer plugins.

1
public static function strike_close()
Stop striked-through text. Has to be implemented by writer plugins.

1
public static function superscript_open()
Start superscript text. Has to be implemented by writer plugins.

1
public static function superscript_close()
Stop superscript text. Has to be implemented by writer plugins.

1
public static function subscript_open()
Start subscript text. Has to be implemented by writer plugins.

1
public static function subscript_close()
Stop subscript text. Has to be implemented by writer plugins.

1
public static function quote_open()
Start quote text. Has to be implemented by writer plugins.

1
public static function quote_close()
Stop quote text. Has to be implemented by writer plugins.

1
public static function line_break()
Add line break. Has to be implemented by writer plugins.

1
public static function horizontal_ruler()
Add a horizontal ruler. Has to be implemented by writer plugins.

1
public static function ordered_list_open()
Start ordered list. Has to be implemented by writer plugins.

1
public static function ordered_list_close()
End ordered list. Has to be implemented by writer plugins.

1
public static function unordered_list_open()
Start unordered list. Has to be implemented by writer plugins.

1
public static function unordered_list_close()
End unordered list. Has to be implemented by writer plugins.

1
public static function list_item_open()
Start list item. Has to be implemented by writer plugins.

1
public static function list_item_close()
End list item. Has to be implemented by writer plugins.

1
public static function data_list_open()
Start data list. Has to be implemented by writer plugins.

1
public static function data_list_close()
End data list. Has to be implemented by writer plugins.

1
public static function data_topic_open()
Start data topic. Has to be implemented by writer plugins.

1
public static function data_topic_close()
End data topic. Has to be implemented by writer plugins.

1
public static function data_description_open()
Start data description. Has to be implemented by writer plugins.

1
public static function data_description_close()
End data description. Has to be implemented by writer plugins.

1
public static function grid_open()
Start grid. Has to be implemented by writer plugins.

1
public static function grid_row_open()
Start grid row. Has to be implemented by writer plugins.

1
public static function grid_cell_open()
Start grid cell. Has to be implemented by writer plugins.

1
public static function grid_cell_wide_open()
Start wide grid cell. Has to be implemented by writer plugins.

1
public static function grid_cell_close()
End grid cell. Has to be implemented by writer plugins.

1
public static function grid_row_close()
End grid row. Has to be implemented by writer plugins.

1
public static function grid_close()
End grid. Has to be implemented by writer plugins.

1
public static function table_open()
Start table. Has to be implemented by writer plugins.

1
public static function table_row_open()
Start table row. Has to be implemented by writer plugins.

1
public static function table_header_open()
Start table header. Has to be implemented by writer plugins.

1
public static function table_header_wide_open()
Start wide table header. Has to be implemented by writer plugins.

1
public static function table_header_close()
End table header. Has to be implemented by writer plugins.

1
public static function table_cell_open()
Start table cell. Has to be implemented by writer plugins.

1
public static function table_cell_wide_open()
Start wide table cell. Has to be implemented by writer plugins.

1
public static function table_number_open()
Start numeric table cell. Has to be implemented by writer plugins.

1
public static function table_number_wide_open()
Start wide numeric table cell. Has to be implemented by writer plugins.

1
public static function table_cell_close()
End table cell. Has to be implemented by writer plugins.

1
public static function table_row_close()
End table row. Has to be implemented by writer plugins.

1
public static function table_close()
End table. Has to be implemented by writer plugins.

1
public static function teletype($str)
Add teletype (monospace) text. Has to be implemented by writer plugins.
Arguments
string the text

1
public static function preformatted($str)
Add preformatted (multiline monospace) text. Has to be implemented by writer plugins.
Arguments
string the text

1
public static function source_code($str, $type = "", $tokens = [])
Add source code. Has to be implemented by writer plugins.
Arguments
string the source code as string
string the language type (or empty string)
array tokenized source code (for syntax highlighting)

1
public static function prev_link()
Add link to previous page. Could be implemented by writer plugins.

1
public static function next_link($id, $name)
Add link to next page. Could be implemented by writer plugins.
Arguments
string heading label id
string heading user-readable name

1
public static function internal_link($name, $lnk = "")
Add an internal link to any heading. Could be implemented by writer plugins.
Arguments
string heading user-readable name
string where to link to, could be a substitute string for forward references

1
public static function resolve_link($subst, $id)
Resolve a forward internal link. Could be implemented by writer plugins.
Arguments
string the substitution string that was used as id
string the real id

1
public static function external_link_open($url)
Start an external link. Could be implemented by writer plugins.
Arguments
string link's URL

1
public static function external_link_close()
End an external link. Could be implemented by writer plugins.

1
public static function user_interface_open($type)
Start a user interface element. Has to be implemented by writer plugins.
Arguments
string type, "1" to "6"

1
public static function user_interface_close()
End a user interface element. Has to be implemented by writer plugins.

1
public static function keyboard($key)
Add a keyboard key. Has to be implemented by writer plugins.
Arguments
string key's name

1
public static function mouse_button($type)
Add a mouse button image. Has to be implemented by writer plugins.
Arguments
string either "l" (left button), "r" (right button) or "w" (wheel)

1
public static function image($align, $fn, $a = [], $img = "")
Add an image. Has to be implemented by writer plugins.
Arguments
string either "t" (inlined as text), "l" (left), "r" (right), "c" (centered) or "w" (wide, centered)
string image's file name
array index 0 width, 1 height, 'mime' mime-type
string image data

1
public static function figure($name)
Add an image caption. Has to be implemented by writer plugins.
Arguments
string figure description

1
public static function alert_box_open($type)
Start an alert box. Has to be implemented by writer plugins.
Arguments
string either "info", "hint", "note", "also", "todo" or "warn"

1
public static function alert_box_close()
End an alert box. Has to be implemented by writer plugins.

1
public static function text($str)
Add any arbitrary text to output. If a tag is open, then to that. Has to be implemented by writer plugins.
Arguments
string the text

1
public static function parse($s)
Parse a source document. Has to be implemented by file format reader plugins.
Arguments
string source document's content
gendoc::\$fn name of the source file
Return Value
gendoc::\$l current line number, must be incremented by the reader plugin

1
public static function output($fn)
Output documentation. Has to be implemented by writer plugins.
Arguments
string name of the file to write to



Tips and Tricks

The Not Refreshed Issue

Some browsers refuse to reload the page if you enter an URL with an anchor label in it (the one after '#'). Besides of typing the URL and pressing ↵ Enter, you also have to press an F5 (refresh page). This should not be, but could be problematic when linking the documentation from other sources, therefore the generated document also accepts the labels as URL query string (after '?' in URL). All browsers think that an URL with a query has to be reloaded. URLs with such a query string are transparently redirected to an URL with an anchor variant (which is then fine, because the reload has already happened).

No JavaScript

Is not a problem. The navigation bar on the left with the TOC will work as expected. So will the "Home" on the top, and "Previous" and "Next" links on the bottom. However internal links created using <a> will only work within the same page, and they will not switch pages (because of the no-reload with anchors issue explained above, and the workaround requires JavaScript).



License

The gendoc Generators

gplv3.pngThe ANSI C source as well as the PHP script are available under GPLv3+ or any later version of that license.

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

The Embedded Icons

ccby.pngThat few icons embedded into the output originate from public FontAwesome icons and they are licensed CC-BY-4.0.

You are free to:

 - Share — copy and redistribute the material in any medium or format

 - Adapt — remix, transform, and build upon the material
     The licensor cannot revoke these freedoms as long as you follow
     the license terms.

Under the following terms:

 - Attribution — You must give appropriate credit, provide a link to
     the license, and indicate if changes were made. You may do so in
     any reasonable manner, but not in any way that suggests the
     licensor endorses you or your use.

The Embedded Style Sheet

ccby.pngI would like to say that the embedded CSS is from RtD, but the thruth is, RtD's style was such a mess I had to rewrite everything from scratch. So it looks like and feels like the original RtD stylesheet, but it is a complete rewrite from ground up, licensed under CC-BY.

The Embedded JavaScript

ccby.pngThat minimal vanilla JavaScript code that gets into the documents (to provide search results) is also licensed under CC-BY.