Skip to content

Commit

Permalink
Document each part of voodoo (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
gpetiot authored Aug 15, 2023
1 parent 0fa5179 commit 67ccabe
Show file tree
Hide file tree
Showing 50 changed files with 263 additions and 231 deletions.
1 change: 1 addition & 0 deletions .ocamlformat
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
version=0.25.1
profile=conventional
parse-docstrings=true
43 changes: 0 additions & 43 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
.DEFAULT_GOAL := all

ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
$(eval $(ARGS):;@:)

Expand All @@ -19,10 +17,6 @@ create_switch:
.PHONY: switch
switch: create_switch deps ## Create an opam switch and install development dependencies

.PHONY: lock
lock: ## Generate a lock file
opam lock -y .

.PHONY: build
build: ## Build the project, including non installable libraries and executables
opam exec -- dune build --root .
Expand All @@ -47,43 +41,6 @@ doc: ## Generate odoc documentation
fmt: ## Format the codebase with ocamlformat
opam exec -- dune build --root . --auto-promote @fmt

.PHONY: watch
watch: ## Watch for the filesystem and rebuild on every change
opam exec -- script/watch.sh

.PHONY: utop
utop: ## Run a REPL and link with the project's libraries
opam exec -- dune utop --root . lib -- -implicit-bindings

.PHONY: promote
promote: ## Promote files to the source directory
dune build client/voodoo_client.bc.js --profile release
cp _build/default/client/voodoo_client.bc.js src/voodoo-gen/static/voodoo_client.bc.js

_generated:
rm -rf _generated; mkdir _generated

.PHONY: support
support:
odoc support-files -o _generated/html

.PHONY: prep
prep: _generated
cd _generated; opam exec -- dune exec -- voodoo-prep

.PHONY: example
example: all prep ## Build an sample output
cd _generated; opam exec -- dune exec -- voodoo-do -p ocaml-base-compiler -b
cd _generated; opam exec -- dune exec -- voodoo-gen -o output

.PHONY: gen
gen:
cd _generated; rm -rf output
cd _generated; opam exec -- dune exec -- voodoo-gen -o output

.PHONY: serve
serve:
opam exec -- dream-serve _generated/html

.DEFAULT:
cd _generated; opam exec -- dune exec -- voodoo-do -p $@ -b
135 changes: 70 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
# Voodoo
<h1 align="center">
voodoo
</h1>

Voodoo is the OCaml documentation generator.
<p align="center">
<strong>Voodoo is the OCaml documentation generator.</strong>
</p>

## Getting started
<p align="center">
<a href="https://ocaml.ci.dev/github/ocaml-doc/voodoo">
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fci.ocamllabs.io%2Fbadge%2Focaml-doc%2Fvoodoo%2Fmain&logo=ocaml" alt="OCaml-CI Build Status" />
</a>
</p>

This package is intended to be used as part of an
[ocurrent](https://github.com/ocurrent/ocurrent) pipeline, for example
via [ocaml-docs-ci](https://github.com/ocurrent/ocaml-docs-ci). As such,
it's tricky to use in isolation.

Having said that, there is some rudimentary support for using it this way. The steps below will guide you to build to build a small documentation website locally.
## :rocket: Getting started

### Setup your development environment
**voodoo** is intended to be used as part of an
[ocurrent](https://github.com/ocurrent/ocurrent) pipeline, for example
via [ocaml-docs-ci](https://github.com/ocurrent/ocaml-docs-ci).

You need Opam, you can install it by following [Opam's documentation](https://opam.ocaml.org/doc/Install.html).
You need `opam`, you can install it by following [Opam's documentation](https://opam.ocaml.org/doc/Install.html).

With Opam installed, you can install the dependencies in a new local switch with:
With `opam` installed, you can install the dependencies in a new local switch with:

```bash
make switch
Expand All @@ -27,103 +32,103 @@ Then, build the project with:
make build
```

### Generating an example
**voodoo** is run in three successive steps detailed below.

To create an example, run:
## :seedling: 1. Prepare the packages: voodoo-prep

```bash
make example
To prepare the packages just run:

```sh
voodoo-prep [-u <UNIVERSES>]
```

This will create a sample website with the documentation of `ocaml-base-compiler` in `_generated/output/p`.
Where `<UNIVERSES>` is a comma-separated list of packages and universes `pkg1:unv1,pkg2:unv2,...`.

Here are some commands that will be executed when running the above:
When you don't provide a universe explicitly, each package installed in the current switch will be prepared (prepped) for the compiling step.

```bash
$ mkdir _generated
$ cd _generated; opam exec -- dune exec -- voodoo-prep
$ cd _generated; opam exec -- dune exec -- voodoo-do -p ocaml-base-compiler -b
$ cd _generated; opam exec -- dune exec -- voodoo-gen -o output
```
This creates an ad-hoc directory structure and populates it with `.cmt`, `.cmi`, `.cmti`, `.mld` from the current switch.
The `ocamlobjinfo` of the `.cma` files are also copied, as well as the documentation files such as `.md`, `.html` and others (such as the `opam` files).

Read further for the detailed version of the above commands.

```bash
$ cd _generated
$ opam exec -- dune exec -- voodoo-prep
Warning: No universes have been specified: will generate dummy universes
$ opam exec -- dune exec -- voodoo-do -p ocaml-base-compiler -b
$ opam exec -- dune exec -- voodoo-do -p result -b
$ opam exec -- dune exec -- voodoo-do ...
## :sweat_drops: 2. Compiling and linking the packages: voodoo-do

Once `voodoo-prep` has run, `voodoo-do` is able to process packages. Simply run:

```sh
voodoo-do -p <PACKAGE> [-b] [--failed]
```

When new packages are installed in the current switch `voodoo-prep` needs to be executed in
for `voodoo-do` to be able to process them. If the packages are done out of dependency order,
`voodoo-prep` will alert that there are missing dependencies:
This command runs `odoc compile` and `odoc link` on the package specified after `-p`.
If the `--failed` flag is set, a file named `failed` containing `"failed"` is also generated.

```bash
$ opam exec -- dune exec -- voodoo-do -p odoc -b
If the packages are processed out of dependency order, `voodoo-do` will alert that there are missing dependencies.

```sh
voodoo-do -p odoc -b
...
Missing dependency: Stdlib c21c5d26416461b543321872a551ea0d
...
```

In this case, we need to run `voodoo-do -p ocaml-base-compiler -b` first.

Note that when being used in this mode, the `-b` (blessed) switch should
always be passed to `voodoo-do`.
Note that when being used in this mode, the `-b` flag should always be passed to `voodoo-do`.

At this point, to view the output, use `odoc` to generate the support files (mostly: copying `highlight.js` from https://highlightjs.org and `odoc.css`):

```bash
$ cd ..
$ odoc support-files -o _generated/html
cd ..
odoc support-files -o html
```

and load the package index in your browser (adjust `x.y.z` according to the current switch):
You can load the package index in your browser:

```bash
$ open _generated/html/p/ocaml-base-compiler/4.14.0/doc/index.html
```sh
open ./html/p/<PACKAGE>/<VERSION>/doc/index.html
```

~~An alternative to executing `voodoo-do -p ...` in order is simply to run
`voodoo-do` with no arguments. This naively executes `voodoo-do` in order
based on the current switch's dependencies, and is slow and inefficient.~~
## :deciduous_tree: 3. Rendering the packages: voodoo-gen

To generate the website with the documentation, run:
Once `voodoo-do` has run, you can generate the website with the documentation, run:

```bash
$ opam exec -- dune exec -- voodoo-gen -o output
voodoo-gen -o <DIR> [-n <PACKAGE>] [--pkg-version <VERSION>]
```

And serve it with:

```bash
$ opam install dream-serve
$ dream-serve _generated/html
```
This command runs `odoc html-generate` to render the files of the specified package as html.

Load the package index in your browser (adjust `x.y.z` according to the current switch):
You can serve it with:

```bash
$ open http://localhost:8080/p/ocaml-base-compiler/4.14.0/doc/index.html
opam install dream-serve
dream-serve ./html
```

You may use the `.DEFAULT` target from the `Makefile` to generate additional
documentation:
Load the package index in your browser:

```
make odoc
```bash
$ open http://localhost:8080/p/<PACKAGE>/<VERSION>/doc/index.html
```

### Summary
## :horse_racing: TLDR

1. Install packages to be documented in the current switch using `opam`
1. Create `_generated` directory
1. Run `voodoo-prep`. This creates the _ad-hoc_ directory structure inside `_generated` and populates it with `.cmt`, `.cmi`, `.cmti`, `.mld` from the current switch. Documentation files such as `.md`, `.html` and others are also copied.
1. Run `voodoo-do` on each package or all at once. This triggers Odoc to generate the actual HTML documentation files.
1. Run `voodoo-gen` to create the `_generated/output` directory
1. Run `doc support-files -o _generated/html` to add css and styling to the `html` subdirectory
1. Run `voodoo-do` on each package to compile and link the odoc files.
1. Run `voodoo-gen` to create the `_generated/output` directory and generate the HTML files.
1. Run `odoc support-files -o _generated/html` to add css and styling to the `html` subdirectory
1. Serve `_generated/html`

`voodoo-*` commands must be called from the `_generated` directory.

```sh
mkdir _generated
cd _generated
opam exec -- dune exec -- voodoo-prep
opam exec -- dune exec -- voodoo-do -p <PACKAGE> -b
opam exec -- dune exec -- voodoo-gen -o output
cd ..
odoc support-files -o _generated/html
dream-serve _generated/html
```
17 changes: 7 additions & 10 deletions src/voodoo-do/do.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
(* do! - perform the odoc compile and link stages *)

open Voodoo_lib
module Result = Bos_setup.R
open Result.Infix
Expand Down Expand Up @@ -110,7 +108,7 @@ let find_universe_and_version pkg_name =
| _ :: _ :: u :: _, [ version ] -> Ok (u, Fpath.to_string version)
| _ -> Error (`Msg (Format.sprintf "Failed to find package %s" pkg_name))

let run pkg_name is_blessed failed =
let run pkg_name ~blessed ~failed =
let is_interesting p =
List.mem (Fpath.get_ext p) [ ".cmti"; ".cmt"; ".cmi" ]
in
Expand Down Expand Up @@ -153,7 +151,7 @@ let run pkg_name is_blessed failed =
in
let package = { Package.universe; name = pkg_name; version } in
let output_path =
if is_blessed then Fpath.(Paths.link / "p" / pkg_name / version)
if blessed then Fpath.(Paths.link / "p" / pkg_name / version)
else Fpath.(Paths.link / "u" / universe / pkg_name / version)
in
Util.mkdir_p output_path;
Expand Down Expand Up @@ -191,11 +189,11 @@ let run pkg_name is_blessed failed =
let error_log = Error_log.find package in

let parent =
Version.gen_parent package ~blessed:is_blessed ~modules ~dune ~libraries
~package_mlds ~error_log ~failed
Version.gen_parent package ~blessed ~modules ~dune ~libraries ~package_mlds
~error_log ~failed
in

let () = Package_info.gen ~output:output_path ~dune ~libraries () in
let () = Package_info.gen ~output:output_path ~dune ~libraries in

let sis = Compat.List.concat_map (get_source_info parent) prep in
let this_index = InputSelect.select sis in
Expand All @@ -219,7 +217,7 @@ let run pkg_name is_blessed failed =
si.path :: compiled
in
let _ = ignore (Index.M.fold compile this_index.intern []) in
let mldvs = Package_mlds.compile parent package_mlds in
let mldvs = Package_mlds.compile ~parent package_mlds in
let unit_includes = IncludePaths.link index in
let docs_includes = Package_mlds.include_paths mldvs in
let all_includes = Fpath.Set.union unit_includes docs_includes in
Expand Down Expand Up @@ -253,8 +251,7 @@ let run pkg_name is_blessed failed =
Format.eprintf "%d other files to copy\n%!" (List.length otherdocs);
let otherdocs, _opam_file = Otherdocs.copy parent otherdocs opam_file in
List.iter (fun p -> Format.eprintf "dest: %a\n%!" Fpath.pp p) otherdocs;
List.iter (Odoc.html output) odocls;
(* Odoc.voodoo_gen Fpath.(output / "tailwind") pkg_name version; *)
List.iter (Odoc.html ~output) odocls;
let () =
Bos.OS.File.delete (Fpath.v "compile/page-p.odoc") |> Result.get_ok
in
Expand Down
5 changes: 4 additions & 1 deletion src/voodoo-do/do.mli
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
val run : string -> bool -> bool -> unit
val run : string -> blessed:bool -> failed:bool -> unit
(** [run pkg ~blessed ~failed] runs [odoc compile] and [odoc link] on package
[pkg]. If [failed] is set, a file named [failed] containing "failed" is also
generated. *)
2 changes: 1 addition & 1 deletion src/voodoo-do/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ open Cmdliner

let run package blessed switch failed =
Opam.switch := switch;
Do.run package blessed failed
Do.run package ~blessed ~failed

let package =
let doc = "Select the package to process" in
Expand Down
6 changes: 6 additions & 0 deletions src/voodoo-gen/markdown.mli
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ val read_org :
Fpath.t ->
Odoc_document.Url.Path.t ->
(Odoc_document.Types.Page.t, [ `Msg of string ]) result
(** [read_org f url] returns the odoc page generated from the org file [f]
having the url [url]. *)

val read_md :
Fpath.t ->
Odoc_document.Url.Path.t ->
(Odoc_document.Types.Page.t, [ `Msg of string ]) result
(** [read_md f url] returns the odoc page generated from the markdown file [f]
having the url [url]. *)

val read_plain :
Fpath.t ->
Odoc_document.Url.Path.t ->
(Odoc_document.Types.Page.t, [ `Msg of string ]) result
(** [read_plain f url] returns the odoc page generated from the plain file [f]
having the url [url]. *)
3 changes: 3 additions & 0 deletions src/voodoo-gen/package_info.mli
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
val gen :
input:Fpath.t -> output:Fpath.t -> Odoc_document.Types.Page.t list -> unit
(** [gen ~input ~output paths] reads a [packags.json] located at [input] and
generates a new [package.json] located at [output] describing the same
package and using [paths] to add children information. *)
6 changes: 6 additions & 0 deletions src/voodoo-gen/rendering.mli
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ val render :
output:(Fpath.t -> Odoc_odoc.Fs.File.t) ->
Fpath.t ->
(Odoc_document.Types.Page.t list, [ `Msg of string ]) result
(** [render ~output f] renders the [.odocl] file [f] as html by running
[odoc html-generate]. [output] determines the output path from the input
path. *)

val render_other :
output:(Fpath.t -> Odoc_odoc.Fs.File.t) ->
parent:Odoc_odoc.Fs.File.t ->
otherdocs:Fpath.t list ->
(unit, [ `Msg of string ]) result
(** [render_other ~output ~parent ~otherdocs] renders the documents [otherdocs]
as html. [parent] is used to get the path to the document. [output]
determines the output path from the input path. *)
8 changes: 0 additions & 8 deletions src/voodoo-gen/search_index.ml
Original file line number Diff line number Diff line change
Expand Up @@ -359,18 +359,10 @@ let generate_index dirs output =
in
Format.fprintf ppf "let documents = [";
let () = List.iter (Load_doc.unit ppf) units in
(* List.iter *)
(* (fun entry -> *)
(* match string_of_entry entry with *)
(* | Ok entry -> Format.fprintf ppf "%s,\n" entry *)
(* | Error _ -> ()) *)
(* index; *)
let () =
Format.fprintf ppf
{|];
const options = { keys: ['name', 'comment'] };
var idx_fuse = new Fuse(documents, options);|}
in
Ok ()
(* Ok *)
(* (Generate.render_index index output) *)
Loading

0 comments on commit 67ccabe

Please sign in to comment.