Skip to content

Document how to write documentation for modules #644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 25, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 164 additions & 1 deletion src/odoc/using-odoc.mld
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,171 @@ complementary notes.

{1:interfaces Documenting your interfaces}

...
Odoc is built to produce documentation for your {e libraries}, and the unit of
organisation is the {e module}. Documentation is written by putting special
{{!comments} comments} into the source of the {e module} or {e module
interface}, and correctly placing these is critical to producing good output.
Odoc expects the documentation to be structured in a logical way, and will work
best if the following conventions are applied.

The overall structure is that modules start with a {{!preamble} preamble} or
'Lead Section' that serves as an overview of the most important information
about module. This is followed by the content of the module, organised into {e
sections} and {e subsections}, the structure of which will be used to populate
a {e table of contents} which will be structurally placed immediately after the
preamble.

The first paragraph of the preamble will be treated as the module {{!synopsis}
synopsis}, and will be used as a short description of the module when it
appears in a list of modules elsewhere in the documentation of the library.

{2 Comments}

Documentation comments are delimited with [(** ] (exactly two [*]) and [*)] and
can be attached to a declaration or be floating in a signature.
{{:https://caml.inria.fr/pub/docs/manual-ocaml/doccomments.html}This is defined
by OCaml.} It is also possible to attach documentation comments to individual
record fields, constructors, function arguments, class items, etc..

{[
(** This is the top-comment. It documents the whole module and will be used to
derive the preamble and the synopsis. *)

type t
(** This comment is attached to [t]. *)

(** This comment is "floating", it can be used to define sections.

{1 This is a heading} *)

(* ... *)
]}

The documentation can be formatted, Odoc accepts the same markup language as
{{:https://caml.inria.fr/pub/docs/manual-ocaml/ocamldoc.html#s%3Aocamldoc-comments}
ocamldoc} with some exceptions, see {!page-interface.Changes}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the topic of this PR, but I think we should just include the markup language documentation in our documentation, and only just say "this is based on the ocamldoc one".


{2 Top-comment}

The top-comment is the first item of a signature, if it is a documentation
comment. For example, in an [.mli] file:

{[
(** This is the top-comment of the current module. *)

module M : sig
(** This is the top-comment of [M]. *)

(* ... *)
end

module type T = sig
(** This is the top-comment of [T]. *)

(* ... *)
end

class c =
object
(** This is the top-comment of [c]. *)

(* ... *)
end
]}

As an exception, [open] items are allowed to be placed before the top-comment.
For example:

{[
(* Copyright header *)

open Base

(** This is the top-comment *)

(* ... *)
]}

Note that the top-comment can't be attached to a declaration, for example:

{[
(** This is {e not} the top-comment because it's attached to [t]. *)
type t
]}

{2 Preamble}

The preamble is composed of the comment attached to a declaration and the
top-comment of the corresponding signature, if there is one.
It is special only because it will be placed in the [header] part of the page,
just before the TOC (if any), and is used to compute the {e synopsis}.

{[
(** This is the comment attached to the declaration. This paragraph will be the
first of the preamble. *)
module M : sig
(** This is the top-comment of the expansion. This paragraph will be the
second of the preamble. *)

(* ... *)
end
]}

The preamble stops at the first heading, the rest is moved into the [content]
part of the page. For example, the next two snippets will {e render} the same
way:

{[
module M : sig
(** Preamble.

{1 Heading}

This paragraph is not part of the preamble. *)
end
]}

{[
module M : sig
(** Preamble. *)

(** {1 Heading}

This paragraph is not part of the preamble. *)
end
]}

Note: A comment attached to a declaration shouldn't contain any heading.

{2 Synopsis}

The synopsis of a module (a module type, a class, etc..) is the first
paragraph of the {!preamble}, {e if} the preamble starts with a paragraph.

It is rendered after the corresponding declaration and in [{!modules:...}]
lists.

Note that the synopsis is computed on top of the {e preamble}, in these two
examples, the synopsis is the same:

{[
(** This paragraph is the synopsis of the module [M].

This paragraph is no longer the synopsis and won't be rendered in the
current page near the declaration of [M]. This paragraph will be part of
[M]'s preamble. *)
module M : sig
(* ... *)
end
]}

{[
module M : sig
(** This paragraph is the synopsis of the module [M]. *)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here again might be worth indicating what happens when you have:

(** Bli bla *)
module M : sig 
  (** Hey ho *)
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an other before that covering this case. This example comes in pair, maybe I should merge them in a single block and call my modules M and N ?


(* ... *)
end
]}

{1:doc-pages Writing documentation pages}

Expand Down