# Rocqnavi: an HTML documentation generator for Rocq prover

## Overview

Rocqnavi is a fork of [coq2html](https://github.com/xavierleroy/coq2html). It generates HTML documentation from Rocq files. Proof scripts are hidden by default but can be revealed by clicking ([folding in action](https://compcert.org/doc/html/compcert.common.Memory.html#Mem.valid_access_dec)).

The initial motivation for this fork it to provide a documentation tool for [MathComp-Analysis](https://github.com/math-comp/analysis).

This fork extends coq2html with:
* generation of indexes (like `rocq doc`)
* clickable notations (like `rocq doc`)
* an option `-Q <dir> <coqdir>` to map physical dir to logical coqdir
* Markdown and LaTeX notations in comments
* darkmode
* a sidebar that displays the tree of modules

[Examples of documentation generated using Rocqnavi](https://yoshihiro503.github.io/rocqnavi/)

**Warning:** To produce cross-references, rocqnavi reads `.glob` files produced by Rocq. The format of `.glob` files is [documented](https://github.com/coq/coq/blob/master/interp/dumpglob.mli). `.glob` files exists since Coq 7.3 (2002-05) but their format has been changing silently between major releases of Coq; it was first documented officially in 2021.

## Usage

```
          rocqnavi [options] file.glob ... file.v ...
```

Option                     | Summary
---------------------------|----------------------------
`-coqlib` _URL_            | Set base URL for Rocq standard library
`-d` _DIR_                 | Output files to directory _DIR_ (default: current directory)
`-external` _URL_ _COQDIR_ | Set base URL for linking references whose names start with _COQDIR_
`-no-css`                  | Do not add rocqnavi.css to the output directory
`-redirect`                | Generate redirection files
`-short-names`             | Use short, unqualified module names in the output
`-title` _TITLE_           | Set the title of the index page
`-Q` _DIR_ _COQDIR_        | Map the directory _DIR_ to correspond to the module name _COQDIR_ (similar to `rocq compile`)
`-structure-graph` _FILE_  | Show the hierarchy graph of <dot-file> on the index.html (You have need Graphviz command line tool)
`-file-graph` _FILE_       | Show the dependency graph from a pre-generated <dot-file> on the index.html
`-file-graph-from-depend` _FILE_ | Automatically generate and show the dependency graph from a <depend-file> on the index.html
`-index-blacklist` _FILE_  | Exclude specified items from the index
`-show-type-information-using-coqtop-process` | Show type information of definitions as a tooltip
`-doc-source-url`          | The Link to the source repository

The dot-file of structure-graph could be generated by `HB.graph` vernacular command.
For dependency graphs, you can either:
- Use `-file-graph-from-depend` with a `.depend.d` file (generated by the build system with `rocq dep`), which automatically generates the graph, or
- Use `-file-graph` with a pre-generated `.dot` file (e.g., produced by `rocq dep` and `ocamldot` commands).

Users of the option `-no-css` are expected to provide their own style sheet.  It must be named rocqnavi.css and it must reside in the directory where rocqnavi generates its files.

### Usage example

Let us assume that the project [MathComp-Analysis](https://github.com/math-comp/analysis) is in the directory `analysis`.

Then the following command generates the documentation of MathComp-Analysis:

```console
find . -not -path '*/.*' -name "*.v" -or -name "*.glob" | xargs rocqnavi \
	-title "Mathcomp Analysis" \
	-d html -base mathcomp -Q theories analysis \
	-coqlib https://rocq-prover.org/doc/V9.0.0/stdlib/ \
	-file-graph-from-depend html/depend.d \
	-structure-graph html/hierarchy_graph.dot \
        -index-blacklist etc/rocqnavi_index-blacklist \
        -show-type-information-using-coqtop-process \
	-external https://math-comp.github.io/htmldoc_2_3_0/ mathcomp
```

Here, `depend.d` is generated by the build system (e.g., using `rocq dep` with appropriate options).

### Additional details about HTML generation

<details><summary>(click to expand)</summary><p>

In addition to HTML files, rocqnavi also produces two auxiliary files:
* rocqnavi.css: the style sheet for the generated HTML files;
* rocqnavi.js: auxiliary JavaScript code that implements proof folding.


For a source file `F.v` in the current directory, the generated HTML file is named `F.html`.  If the source file is in a subdirectory, a Rocq-Style fully-qualified name is used as the name of the generated HTML file, as shown below:

`-Q`               |  Source file name     |   Generated HTML file name
-------------------|-----------------------|---------------------------
none               | `F.v`                 | `F.html`
none               | `D/E/F.v`             | `D.E.F.html`
`-Q A.B.C src`     | `src/F.v`             | `A.B.C.F.html`
`-Q A.B.C src`     | `src/D/E/F.v`         | `A.B.C.D.E.F.html`

This file naming convention is compatible with that of `rocq doc` and ensures that file names are globally unique across multiple Rocq libraries and packages.

The fully-qualified name is also used to produce the title of the generated HTML page.  In the last example above, the fully-qualified name is A.B.C.D.E.F and the title of the page will be **Module A.B.C.D.E.F**.  If the `-short-names` option is given, the unqualified, local name is used instead, giving **Module F** as title.

Earlier versions of rocqnavi used short names `F.html` instead of fully-qualified names to name the generated HTML files.  For backward compatibility, the `-redirect` option can be given.  It causes an additional `F.html` file to be generated, containing a HTTP redirection to the file `A.B.C.D.E.F.html`.

</p></details>

### Additonal details about cross-referencing

<details><summary>(click to expand)</summary><p>

rocqnavi can generate cross-references as hyperlinks from uses to definitions of Rocq names, provided the appropriate `.glob` files are given on the command-line.

A cross-reference file `F.glob` is generated by the Rocq compiler coqc when it processes the `F.v` source file. When giving `F.v` as argument to rocqnavi, also give `F.glob` as argument, so that rocqnavi can use those cross-references to produce hyperlinks.

**Important:** if the source files are compiled within a Rocq namespace, you must give a `-Q` option to rocqnavi indicating this namespace. For example, if you compile with
```console
        rocq compile -Q A.B.C .
```
meaning that the current directory means namespace A.B.C, then you must invoke rocqnavi with
```console
        rocqnavi -Q A.B.C .
```

By default, cross-references are generated if the referenced definition is
* in one of the `.glob` files given to rocqnavi on the command line, or
* in the Rocq standard library.

For this reason, to get better cross-referencing, you should either do a single run of rocqnavi with all the `.v` and `.glob` files of your Rocq development, or give all the `.glob` files of your library to every run of rocqnavi on every `.v` file.

The cross-references to the Rocq standard library use the online version of this library at https://rocq-prover.org/library/, which corresponds to the latest release of Rocq.  If you wish to reference a specific version of the standard library, use the `-coqlib` option, e.g.
```console
        rocqnavi -coqlib https://rocq-prover.org/doc/V9.0.0/stdlib
```
for the 9.0.0 version of the standard library.

Using the `-external` option, you can add cross-references to other external libraries whose rocq doc or rocqnavi-generated documentation is accessible online.  For example,
```console
        rocqnavi -external https://math-comp.github.io/htmldoc_2_3_0 mathcomp ...
```
should produce cross-references to the `mathcomp` library modules.

</p></details>

### Additional details about the display of proof scripts

<details><summary>(click to expand)</summary><p>

Proof scripts are Rocq text (outside comments) that
* starts with `Proof` or `Next Obligation` at the beginning of a line;
* ends with `Qed.` or `Defined.` or `Save.` or `Admitted.` or `Abort.` at the end of a line.

A proof script can start and end on the same line, e.g. `Proof. auto. Qed.`

Proof scripts are formatted in a smaller font and folded by default, leaving only the starting line (`Proof`, etc) visible.  Clicking on this first line displays the whole proof script.

The syntax of proof scripts is strict.  In particular, after stating a `Theorem` or `Lemma`, it does not work to omit the `Proof` keyword and start the script immediately, nor to abort it immediately with `Admitted.` or `Abort.`.  Likewise, the dot `.` must follow `Qed`, `Defined`, etc. without spaces.  For example, the following proof scripts won't be properly formatted:
```rocq
Lemma x:...
auto. Qed.                      (* No "Proof." to mark the beginning of the script. *)

Lemma x:...
Admitted.                       (* No "Proof." to mark the beginning of the script. *)

Lemma x:...
Proof. auto. Defined .          (* Whitespace between "Defined" and "." *)
```

</p></details>

## Documentation comments

Documentation comments start with
- `(** ` (two stars followed by a space),
- `(**r ` (two stars, the "r" character, one space), or
- `(**md ` (two stars, the "md" string, one space).
```
     (** This is a documentation comment. *)
     (**r This is a right-aligned documentation comment. *)
     (**md This is a Markdown comment. *)
     (* This is a regular comment. *)
```
Regular, non-documentation comments are removed from the HTML output, except within proof scripts, where they are kept as is.

Documentation comments of the `(**` kind are formatted as described next, then inserted as a paragraph in the HTML output.  Right-aligned documentation comments of the `(**r` kind are formatted likewise, but do not start a paragraph.  Instead, they hang to the right of the Rocq code on the same line.  Example:
```rocq
     (** This is the type of lists. *)

     Inductive list (A: Type) : Type :=
     | nil                         (**r the empty list *)
     | cons (hd: A) (tl: list A).  (**r the  nonempty list [hd::tl] *)
```

Documentation comments of the `(**md` kind are interpreted as Mardown input with possibly LaTeX mathematical notations (between `$` and `$`) inserted.

In addition, comments formatted as follows (80 characters wide)
```
     (**md***************************************************************************)
     (*                                                                             *)
     (* Some Mardown + LaTeX comment.                                               *)
     (*                                                                             *)
     (*******************************************************************************)
```
are displayed inside a frame.

### Markup language for coq2html (Deprecated: use markdown instead)

Inside documentation comments that are not Markdown, one can use the following features to improve the rendering of comments.
Many of them are subsumed by the Mardown language available in Mardown + LaTeX documentation comments which
should be preferred when possible.

#### Inline Rocq text

<details><summary>(click to expand)</summary><p>

Within a documentation comment, text within square brackets `[...]` is taken to be Rocq text and is formatted in monospace font.  You can write `[x + S y]` and will get `x + S y`.  Square brackets nest properly, hence `[[x;y]]` gives `[x;y]`.

</p></details>

#### Inline HTML

<details><summary>(click to expand)</summary><p>

Within a documentation comment, text between hash signs `#...#` is treated as pure HTML and copied verbatim to the output, without escaping of HTML special characters.  Hence, `#...#` escapes are the only way to insert HTML tags.  Example:
```
    (** 32-bit integers are less than #2<sup>32</sup># *)
```

</p></details>

#### Verbatim text

<details><summary>(click to expand)</summary><p>

Verbatim text starts with `<<` on a line by itself and ends with `>>` on a line by itself.  The lines between those two markers are copied to the output, in typewriter font, respecting newlines.  Example:
```
(** This is normal documentation text.
<<
        This is verbatim text.
        Second line of verbatim text.
>>
    This is normal text again. *)
```

Warning: `<<` and `>>` must be at the beginning of a line, without any space before.

</p></details>

#### Sections

<details><summary>(click to expand)</summary><p>

Section titles are denoted by one to four `*` characters at the beginning of a documentation comment:
```
    (** * Section title *)
    (** ** Subsection *)
    (** *** Sub-sub section *)
    (** **** Sub-sub-sub section *)
```
The section title extends until the end of the documentation comment.

</p></details>

#### Lists of items

<details><summary>(click to expand)</summary><p>

Lists start with a dash `-` at the beginning of the line.  Subsequent lines starting with a dash are items in the list.  A blank line terminates the list.  Example:
```
(** A list is either:
-     [nil], denoting the empty list;
-     [cons h t], also written [h :: t], denoting the nonempty list
      with head [h] and tail [t].

  If we remove the [nil] case and declare a [CoInductive], we get infinite
  streams instead of lists. *)
```
Nested lists are built using two, three or four dashes instead of one:
```
- Outer list, item #1
-- Inner list, item #1
-- Inner list, item #2
- Outer list, item #2
```

</p></details>

## Known limitations

- Cross-referencing (HTML links on identifiers that jump to the definition of the identifiers) is implemented for identifiers bound at the top-level of a Rocq source file (by `Definition`, `Fixpoint`, `Inductive`, `Module`, `Variable`, etc), but not for identifiers bound within Rocq terms (by `fun`, `match`, `forall`, etc). There is no cross-referencing for user-defined notations either.

- All non-ASCII Unicode characters are treated as being parts of identifiers.  Hence, `A ⊕ B` is read as three identifiers, `A`, `⊕`, and `B`, and links are correctly added to `A` and `B` if they are bound at top-level.  However, `A⊕B` is read as a single identifier, which has no corresponding definition, therefore no link is added.

- The formatting of right-hanging documentation comments `(**r` is inflexible and not appropriate for narrow display windows or long source lines.
