Skip to content

Commit

Permalink
Write the documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
goerz committed Jan 4, 2024
1 parent 3a478de commit 2bf42fd
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 154 deletions.
118 changes: 8 additions & 110 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A plugin for [Documenter.jl](https://documenter.juliadocs.org/) that enables lin

**WARNING: This is a prototype. If you use this package pre-1.0, be prepared to having to adapt to breaking changes at any time.**

Loading `DocumenterInterLinks` in `Docs/make.jl` causes Documenter to produce an "inventory file" `objects.inv` in the output folder, which should get deployed together with the documentation. This file contains a mapping from names to URLs for all link targets in the documentation.
Loading `DocumenterInterLinks` in `docs/make.jl` causes Documenter to produce an "inventory file" `objects.inv` in the output folder, which should get deployed together with the documentation. This file contains a mapping from names to URLs for all link targets in the documentation.

Other projects may use this inventory file to resolve `@extref` links, see [External Citations](#external-citations).

Expand All @@ -34,7 +34,7 @@ to the relevant `Project.toml` file.

## Plugin Instantiation

In `docs/make.jl`, instantiate an `InterLinks` object:
In `docs/make.jl`, instantiate an [`InterLinks`](https://juliadocs.org/DocumenterInterLinks.jl/stable/internals/#DocumenterInterLinks.InterLinks) object:

```julia
using DocumenterInterLinks
Expand All @@ -53,124 +53,22 @@ See [`docs/make.jl`](https://github.com/JuliaDocs/DocumenterInterLinks.jl/blob/m

The resulting plugin object that must be passed as an element of the `plugins` keyword argument to `Documenter.makedocs`. This then enables `@extref` links in the project's documentation to be resolved.

<details>
<summary>Arguments</summary>

The `InterLinks` plugin receives mappings of project names to the project root URL and inventory locations. Each project names must be an alphanumerical ASCII string. For Julia projects, it should be the name of the package without the `.jl` suffix, e.g., `"Documenter"` for [Documenter.jl](https://documenter.juliadocs.org/). For Python projects, it should be the name of project's main module.

The root url / inventory location (the value of the mapping), can be given in any of the following forms:

* A single string with a URL of the inventory file, e.g.

```
"sphinx" => "https://www.sphinx-doc.org/en/master/objects.inv"
````

The root URL relative which all URIs inside the inventory are taken to be relative is everything up to the final slash in the inventory URL, `"https://www.sphinx-doc.org/en/master/"` in this case.

* A single string with a project root URL, for example,

```
"sphinx" => "https://www.sphinx-doc.org/en/master/",
````

which must end with slash. This is exactly equivalent to previous example: it assumes `"objects.inv"` (the standard [Sphinx](https://www.sphinx-doc.org/) inventory file) to be reachable directly underneath the given URL.

* A tuple of strings, where the first element is the project root URL and all
subsequent elements are locations (URLs or local file paths) to an inventory
file, e.g.,

```
"Julia" => (
"https://docs.julialang.org/en/v1/",
joinpath(@__DIR__, "src", "interlinks", "Julia.toml")
),
"Documenter" => (
"https://documenter.juliadocs.org/stable/",
"https://documenter.juliadocs.org/stable/inventory.toml.gz",
joinpath(@__DIR__, "src", "interlinks", "Documenter.toml")
)
```

The first reachable inventory file will be used. This enables, e.g., to
define a local inventory file as a fallback in case the online inventory file
location is unreachable, as in the last example.

* A `DocInventories.Inventory` instance.

</details>

See [`docs/src/interlinks`](https://github.com/JuliaDocs/DocumenterInterLinks.jl/tree/master/docs/src/interlinks) for some exemplary inventory file in TOML format.


## External Citations

Instead of Documenter's `@ref`, the `@extref` link target can be used to resolve the link via any of the available inventories set up in the `InterLinks` plugin:
Instead of Documenter's `@ref`, the `@extref` link target can be used to resolve the link via any of the available projects defined in the `InterLinks` plugin:

```
* [`Documenter.makedocs`](@extref)
* [Documenter's `makedocs` function](@extref Documenter.makedocs)
* See the section about Documenter's [Writers](@extref).
```

To disambiguate (and speed up) the references, the name of the inventory (as defined when instantiating `InterLinks`) can be included in the `@extref`. The previous example would have been better written as

```
* [Documenter's `makedocs` function](@extref `Documenter.makedocs`)
* See the section about Documenter's [Writers](@extref Documenter).
```

to clarify that we are linking to the section name "Writers" in Documenter's documentation. When the link text and link target differ, the inventory name should be given between `@extref` and the target name.


```
* [`Regex`](@extref Julia Base.Regex)
```


## Compatibility with Sphinx

`DocumenterInterLinks` is fully compatible with [Sphinx](https://www.sphinx-doc.org/en/master/), respectively [Intersphinx](https://www.sphinx-doc.org/en/master/usage/quickstart.html#intersphinx). That is, `DocumenterInterLinks` writes an `objects.inv` file that is compatible with Intersphinx, and conversely, by loading existing `objects.inv` from (mostly Python) projects that build their documentation with Sphinx in the `InterLinks` plugin, `@extref` can link to the documentation of these non-Julia projects.

Sphinx/Intersphinx has the concept of ["domains"](https://www.sphinx-doc.org/en/master/glossary.html#term-domain) and ["roles"](https://www.sphinx-doc.org/en/master/glossary.html#term-role). When generating the `objects.inv` file, `DocumenterInterLinks` uses an ad-hoc `jl` domain for Julia code objects, with the possible roles `obj`, `macro`, `func`, `abstract`, `type`, and `mod` (cf. `DocInventories.JULIA_ROLES`). Section headings are registered with the domain `std` and role `label` and output html files with the domain `std` and role `doc`.

The domain and role can optionally be included in an `@extref` link, using the same [cross-referencing syntax as Sphinx](https://www.sphinx-doc.org/en/master/usage/referencing.html#cross-referencing-syntax):

```
:domain:role:`name`
:role:`name`
```

Some examples:

```
* [`Documenter.makedocs`](@extref :jl:func:`Documenter.makedocs`)
* [`Documenter.makedocs`](@extref :func:`Documenter.makedocs`)
* [Sphinx](@extref sphinx :doc:`index`)
* [`subplots`](@extref matplotlib :py:function:`matplotlib.pyplot.subplots`)
```

`DocumenterInterLinks` is much less strict than Sphinx (which requires that domains are formally defined). The optional domain and role in `@extref` links are for disambiguation only. If a domain or role is not specified, anything will match.


## Available link targets

In order to search for available link targets in an inventory, you can exploit the ability of the `DocInventories.Inventory` to perform [free-form search](https://github.com/JuliaDocs/DocInventories.jl/blob/e053c30938b5ff85dfbe04acb49d280d12ba17cf/src/inventory.jl#L112-L127).

The easiest way to accomplish this is to `include` the `docs/make.jl` file in a REPL (building the documentation, but more importantly in this case, ensuring the `links` (`InterSphinx`) object is loaded into the REPL).

Then, in the same session, run searches like

```
links["Documenter"]("makedocs")
links["Documenter"](":label:")
links["matplotlib"](":doc:")
links["matplotlib"](r":py:function:.*subplots")
```

to see a list of `InventoryItems` that match the query.

See the [documentation](https://juliadocs.org/DocumenterInterLinks.jl/dev/#Using-External-References) and [Recommended Syntax](https://juliadocs.org/DocumenterInterLinks.jl/dev/syntax/#Recommended-Syntax) for details.

## Usage of DocumenterInterLinks inventory files with Sphinx

See [`index.rst`](https://raw.githubusercontent.com/goerz-testing/test-sphinx-to-documenter-links/master/docs/source/index.rst) in [`goerz-testing/test-sphinx-documenter-links`](https://github.com/goerz-testing/test-sphinx-to-documenter-links) for an example of how to use the inventory from within Sphinx.
## Documentation

This includes a minimal [formal definition of the custom `jl` domain](https://github.com/goerz-testing/test-sphinx-to-documenter-links/blob/master/docs/source/_extensions/julia_domain.py), which is required in order for Sphinx to resolve links to Julia objects.
The [full documentation of this project is available online](https://juliadocs.org/DocumenterInterLinks.jl/dev/).
9 changes: 5 additions & 4 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ AUTHORS = join(PROJECT_TOML["authors"], ", ") * " and contributors"
GITHUB = "https://github.com/JuliaDocs/DocumenterInterLinks.jl"

links = InterLinks(
"Documenter" => (
"https://documenter.juliadocs.org/stable/",
joinpath(@__DIR__, "src", "inventories", "Documenter.toml")
),
"Julia" => (
"https://docs.julialang.org/en/v1/",
joinpath(@__DIR__, "src", "inventories", "Julia.toml")
),
"Documenter" => (
"https://documenter.juliadocs.org/stable/",
joinpath(@__DIR__, "src", "inventories", "Documenter.toml")
),
"DocInventories" => "https://juliadocs.org/DocInventories.jl/stable/",
"sphinx" => "https://www.sphinx-doc.org/en/master/",
"sphobjinv" => "https://sphobjinv.readthedocs.io/en/stable/",
Expand All @@ -29,6 +29,7 @@ PAGES = [
"Home" => "index.md",
"Syntax" => "syntax.md",
"Inventory Generation" => "write_inventory.md",
"Compatibility with Sphinx" => "sphinx.md",
"How-Tos" => "howtos.md",
"Internals" => joinpath("api", "internals.md"),
]
Expand Down
106 changes: 102 additions & 4 deletions docs/src/howtos.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,110 @@
# How-Tos

### How do I find a project's inventory file?
---

```@contents
Pages=["howtos.md"]
Depth=3:3
```

### How do I figure out the correct name for the `@extref` link?
---

### [How do I find a project's inventory file?](@id howto-inventory-location)

### What if I want to link to a project that does not provide an inventory file?
The documentation generator [should generate an inventory file](@ref Inventory-Generation) in the root of its output folder. These then get deployed with the rest of the documentation. For most projects, this "root" ends up in a subfolder named after the version or branch.

For example, you will find `objects.inv` inventory files under the following URLs:

### Can I use this plugin for general external links?
* [https://www.sphinx-doc.org/en/master/objects.inv](https://www.sphinx-doc.org/en/master/objects.inv)
* [https://matplotlib.org/3.7.3/objects.inv](https://matplotlib.org/3.7.3/objects.inv)
* [https://docs.python.org/3/objects.inv](https://docs.python.org/3/objects.inv)
* [https://juliadocs.org/DocInventories.jl/stable/objects.inv](https://juliadocs.org/DocInventories.jl/stable/objects.inv)
* [https://juliadocs.org/DocInventories.jl/v0.2/objects.inv](https://juliadocs.org/DocInventories.jl/v0.2/objects.inv)

The [Julia language](@extref Julia :doc:`index`) and [Documenter.jl](@extref Documenter :doc:`index`) currently do not provide an inventory file, but if they did, it would be immediately underneath

* [https://docs.julialang.org/en/v1/](https://docs.julialang.org/en/v1/)
* [https://documenter.juliadocs.org/stable/](https://documenter.juliadocs.org/stable/)

If it is not obvious where an inventory file is located, simply try to load it in the REPL until you find a working URL:

```@repl howto-inventory-location
using DocInventories
Inventory("https://www.sphinx-doc.org/en/objects.inv")
Inventory("https://www.sphinx-doc.org/en/master/objects.inv")
```

If you cannot find any inventory file, see [What if I want to link to a project that does not provide an inventory file?](@ref howto-manual-inventory)


### [How do I figure out the correct name for the `@extref` link?](@id howto-find-extref)

Use the search capabilities of [`InterLinks`](@ref) or [`DocInventories.Inventory`](@extref).

If you have set up an [`InterLinks`](@ref) object named `links` in your `docs/make.jl` [as described before](@ref Declaring-External-Projects), you are presumably able to build your documentation locally by starting a Julia REPL in the appropriate environment (e.g., `julia --project=docs`) and then running `include("docs/make.jl")`.

This also puts the `links` object into your REPL, allowing you to search it interactively.

```@repl howto-find-extref
# include("docs/make.jl")
using DocumenterInterLinks # hide
links = InterLinks("sphinx" => "https://www.sphinx-doc.org/en/master/objects.inv", "matplotlib" => "https://matplotlib.org/3.7.3/", "Documenter" => ("https://documenter.juliadocs.org/stable/", joinpath(@__DIR__, "inventories", "Documenter.toml")), "Julia" => ("https://docs.julialang.org/en/v1/", joinpath(@__DIR__, "inventories", "Julia.toml"))); # hide
links
```

For example, trying to find the appropriate `@extref` link to to the [LaTeX Syntax](@extref Documenter :label:`latex_syntax`) section in the Documenter manual, you might search for

```@repl howto-find-extref
links["Documenter"]("latex")
```

and determine that an appropriate `@extref` would be

```
[LaTeX Syntax](@extref Documenter :label:`latex_syntax`)
```

[This search is quite flexible](@extref DocInventories Exploring-Inventories). Using regular expression, you could do something crazy like search the Julia documentation for docstrings of any method that involves two or more strings:

```@repl howto-find-extref
links["Julia"](r":method:`.*-.*AbstractString.*AbstractString.*`")
```

You can also search *across* all projects, using a lookup in the [`InterLinks`](@ref) object directly, e.g.,

```@repl howto-find-extref
links("`index`")
```

These matching `@extref` links should be modified according to the [Recommended Syntax](@ref).


### [What if I want to link to a project that does not provide an inventory file?](@id howto-manual-inventory)

Inventory files really should created [automatically using a documentation generator](@ref Inventory-Generation). Try to get the project to use one that produces inventory files or help them set up their documentation system so that it does.

Until `Documenter` incorporates the [Inventory Generation](@ref) currently provided by this plugin, one may produce an inventory file for an existing Julia/Documenter-based project by cloning the project, opening a REPL so that `include("docs/make.jl")` successfully builds the documentation for that projects, and then repeat `include("docs/make.jl")` after running

```julia
julia> ] add DocumenterInterLinks
julia> using DocumenterInterLinks
```

in the same REPL. You should then find an `objects.inv` in the `docs/build` folder. [Use the `DocInventories` package to convert it](@extref DocInventories Saving-Inventories-to-File) to [TOML Format](@extref DocInventories). This is how the [inventory files](https://github.com/JuliaDocs/DocumenterInterLinks.jl/tree/master/docs/src/inventories) used in this documentation were generated, e.g., for the Julia project itself.

There may be projects that legitimately do not provide inventories. For example, some simple Julia projects write out their entire documentation in their README on Github. In that case, you should either use [standard links](@extref Julia `Links`) or [manually create an inventory file](@extref DocInventories Creating-Inventory-Files). The easiest way to do this is to write out an inventory in [TOML Format](@extref DocInventories) by hand.


### [Can I use this plugin for general external links?](@id howto-external-links)

Documenter's markdown flavor [lacks the ability for reference links](https://discourse.julialang.org/t/how-to-use-markdown-reference-links-with-documenter-jl/84232). If you link to the same very long URLs repeatedly, this becomes cumbersome.

In principle, you could [manually write out an inventory file](@extref DocInventories Creating-Inventory-Files) that defines link labels and their associated URLs, along the lines of the discussion in [Documenter's PR #1351](https://github.com/JuliaDocs/Documenter.jl/pull/1351). Whether you *should* abuse `DocumenterInterLinks` in this way might be a matter of debate.

A situation where I do think this makes sense is if you repeatedly link to some website with very structured content, e.g. Wikipedia or the [Julia Discourse Forum](https://discourse.julialang.org). As [shown in the `DocInventories` documentation](@extref DocInventories Maintain-an-Inventory-TOML-File-by-Hand), you could write a `Wikipedia` inventory file just for the articles you want to link to, and then have a link such as

```
[Julia](@extref Wikipedia)
```

in your documentation to link to [Julia (programming language)](https://en.wikipedia.org/wiki/Julia_(programming_language)).
Loading

0 comments on commit 2bf42fd

Please sign in to comment.