Skip to content

API Reference Generation ​

Pipeline ​

Fortran .F90 sources
    |  FORD parser
    v
FORD Project (modules, types, procedures, variables)
    |  FORMAL generator
    v
docs/api/*.md + _sidebar.json
    |  VitePress build
    v
Static HTML site

What FORD Does ​

FORD (Fortran Documenter) reads .F90 files and builds a structured object model:

  • Each module becomes a FortranModule with lists of types, variables, subroutines, functions
  • Each type has components (variables) and type-bound procedures
  • Each subroutine/function has argument lists with types and intents
  • Doc comments (!< by default) are attached as doc_list (raw Markdown strings)

FORMAL calls FORD's Project() + correlate() to build this model, then walks it to generate Markdown. It never calls FORD's HTML renderer.

What FORMAL Generates Per Module ​

markdown
---
title: module_name
---
# module_name
> Module description from doc comments

**Source**: `src/lib/common/module_name.F90`

## Variables
| Name | Type | Attributes | Description |

## Derived Types
### type_name
> Type description
#### Components
| Name | Type | Attributes | Description |
#### Type-Bound Procedures
| Name | Attributes | Description |

## Interfaces

## Subroutines
### sub_name
> Subroutine description
```fortran
subroutine sub_name(arg1, arg2)
`` `
**Arguments**
| Name | Type | Intent | Attributes | Description |

## Functions

The FORD Project File ​

The FORD project file (doc/formal.md by default) tells FORD where to find your sources. It's a Markdown file with a metadata header:

project: MyProject
src_dir: ../src/lib
         ../src/app
exclude_dir: ../src/third_party/
docmark: <
display: public
         protected
         private
source: false
warn: true
graph: false
author: Jane Doe

This text after the metadata is the project description (unused by FORMAL).

Key Settings ​

SettingDescriptionFORMAL default
src_dirDirectories to scan for .F90 filesAuto-detected from src/
exclude_dirDirectories to skipAuto-detected (third_party/, etc.)
docmarkDoc comment marker (< means !<)<
displayWhich visibility to includepublic protected private
sourceInclude source code in outputfalse (not needed for VitePress)
graphGenerate dependency graphsfalse (speeds up parsing)
warnPrint warnings for undocumented entitiestrue

Adding Source Directories ​

To cover more code, add paths to src_dir (relative to the FORD project file):

src_dir: ../src/lib
         ../src/app
         ../src/plugins        # <-- add new directories here

Excluding Directories ​

exclude_dir: ../src/third_party/
             ../src/generated/
             ../src/deprecated/

Mirrored Source Layout ​

By default all generated pages land flat inside docs/api/. Passing --mirror-sources reproduces the Fortran source directory tree inside the output directory:

bash
formal generate --mirror-sources
Without --mirror-sourcesWith --mirror-sources
api/my_module.mdapi/src/lib/my_module.md
api/other_module.mdapi/src/app/other_module.md

Sidebar links and cross-reference URLs are updated automatically to match. The sidebar groups also switch from human-readable labels to real directory paths (see Sidebar → Mirroring Source Directory Structure).

Mermaid Diagrams ​

Passing --diagrams embeds Mermaid diagram blocks in every generated page:

bash
formal generate --diagrams
# or combine both flags:
formal generate --mirror-sources --diagrams

Three diagram types are generated from data already present in FORD's correlated object model:

DiagramWhere it appearsSource data
Dependency graphModule page, below the source pathmodule.uses
Inheritance diagramEach derived type sectiontype.extends + child types
Call graphEach subroutine/function sectionproc.calls + inverse lookup

Example dependency diagram in Markdown:

markdown
**Dependencies**

```mermaid
graph LR
  penf["penf"] --> penf_global_parameters_variables["penf_global_parameters_variables"]
  penf["penf"] --> penf_b_size["penf_b_size"]
```

Example call graph showing callers (inbound) and callees (outbound), with the current procedure highlighted:

markdown
**Call graph**

```mermaid
flowchart TD
  strf_r8p["strf_r8p"] --> str_r8p["str_r8p"]
  style str_r8p fill:#dde,stroke:#99b,stroke-width:2px
```

Enabling Mermaid in VitePress ​

Diagrams require vitepress-plugin-mermaid. For new projects, pass --mermaid to formal init and it is wired up automatically:

bash
formal init --mermaid
cd docs && npm install
formal generate --diagrams

For an existing site, install manually and wrap the config:

bash
npm i vitepress-plugin-mermaid mermaid -D
typescript
// .vitepress/config.mts
import { withMermaid } from 'vitepress-plugin-mermaid'  // replace defineConfig import
import apiSidebar from '../api/_sidebar.json'

export default withMermaid({           // replace defineConfig(
  // ... your existing config unchanged ...
  mermaid: {},
})

Customizing API Output ​

FORMAL's generator is in src/formal/generator.py. The formatting functions are modular and can be modified independently:

FunctionWhat it controls
format_module()Overall page layout per module
format_type()Derived type sections
format_procedure()Subroutine/function sections
format_variable_table()Variable/argument tables
format_bound_proc_table()Type-bound procedure tables
format_interface()Interface sections
generate_sidebar()Sidebar grouping logic
_classify_module()How modules map to sidebar groups (default mode)
format_dependency_diagram()Module dependency graph block
format_inheritance_diagram()Type inheritance diagram block
format_call_diagram()Procedure call graph block
build_called_by_index()Project-wide callee→callers mapping
build_type_children_index()Project-wide parent→children type mapping
inline_doc()How doc comments appear in table cells
format_doc()How doc comments appear in block content

By default, _classify_module() groups modules by their source path:

  • src/app/<name>/... → Applications / NAME
  • src/lib/<name>/... → Library / name
  • Other paths → grouped by first two directory components

With --mirror-sources, the group name is the raw source directory path (e.g. src/lib, src/tests). To change grouping in default mode, override _classify_module() or post-process the sidebar JSON after generation.

Programmatic Usage ​

You can also use FORMAL as a library:

python
from pathlib import Path
from formal.generator import generate

result = generate(
    project_file=Path("doc/formal.md"),
    output_dir=Path("docs/api"),
    mirror_sources=True,   # mirror source tree in output
    diagrams=True,         # embed Mermaid diagrams
    verbose=True,
)
print(f"Generated {result['modules']} module pages")
print(f"Sidebar groups: {[g['text'] for g in result['sidebar']]}")