/
apidocs.fsx
416 lines (302 loc) · 13.1 KB
/
apidocs.fsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
(**
*)
#r "nuget: FSharp.Formatting,1.0.0"
(**
[![Binder](img/badge-binder.svg)](https://mybinder.org/v2/gh/fsprojects/fsharp.formatting/gh-pages?filepath=apidocs.ipynb) 
[![Script](img/badge-script.svg)](https://fsprojects.github.io/FSharp.Formatting//apidocs.fsx) 
[![Notebook](img/badge-notebook.svg)](https://fsprojects.github.io/FSharp.Formatting//apidocs.ipynb)
# API Documentation Generation
The [command-line tool `fsdocs`](commandline.html) can be used to generate documentation
for F# libraries with XML comments. The documentation is normally built using `fsdocs build` and developed using `fsdocs watch`. For
the former the output will be placed in `output\reference` by default.
## Selected projects
`fsdocs` automatically selects the projects and "cracks" the project files for information
* Projects with `GenerateDocumentationFile` and without `IsTestProject` are selected.
* Projects must not use `TargetFrameworks` (only `TargetFramework`, singular).
```text
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
```
## Templates
The HTML is built by instantiating a template. The template used is the first of:
* `docs/reference/_template.html`
* `docs/_template.html`
* The default template
Usually the same template can be used as for [other content](content.html).
## Classic XML Doc Comments
XML Doc Comments may use [the normal F# and C# XML doc standards](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/).
The tags that form the core of the XML doc specification are:
```
<c> <para> <see>* <value>
<code> <param>* <seealso>*
<example> <paramref> <summary>
<exception>* <permission>* <typeparam>*
<include>* <remarks> <typeparamref>
<list> <inheritdoc> <returns>
```
In addition, you may also use the [Recommended XML doc extensions for F# documentation tooling](https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1031-xmldoc-extensions.md).
* `<a href = "...">` links
* Arbitrary paragraph-level HTML such as `<b>` for bold in XML doc text
* `<namespacedoc>` giving documentation for the enclosing namespace
* `<exclude/>` to exclude from XML docs
* `<category>` to give a category for an entity or member. An optional `index` attribute can be specified
to help sort the list of categories.
* `\(...\)` for inline math and `$$...$$` and `\[...\]`for math environments, see [http://docs.mathjax.org.
Some](http://docs.mathjax.org.
Some) escaping of characters (e.g. `<`, `>`) may be needed to form valid XML
An example of an XML documentation comment, assuming the code is in namespace `TheNamespace`:
*)
/// <summary>
/// A module
/// </summary>
///
/// <namespacedoc>
/// <summary>A namespace to remember</summary>
///
/// <remarks>More on that</remarks>
/// </namespacedoc>
///
module SomeModule =
/// <summary>
/// Some actual comment
/// <para>Another paragraph, see <see cref="T:TheNamespace.SomeType"/>. </para>
/// </summary>
///
/// <param name="x">The input</param>
///
/// <returns>The output</returns>
///
/// <example>
/// Try using
/// <code>
/// open TheNamespace
/// SomeModule.a
/// </code>
/// </example>
///
/// <category>Foo</category>
let someFunction x = 42 + x
/// <summary>
/// A type, see <see cref="T:TheNamespace.SomeModule"/> and
/// <see cref="M:TheNamespace.SomeModule.someFunction"/>.
/// </summary>
///
type SomeType() =
member x.P = 1
(**
Like types, members are referred to by xml doc sig. These must currently be precise as the F#
compiler doesn't elaborate these references from simpler names:
*)
type Class2() =
member this.Property = "more"
member this.Method0() = "more"
member this.Method1(c: string) = "more"
member this.Method2(c: string, o: obj) = "more"
/// <see cref="P:TheNamespace.Class2.Property" />
/// and <see cref="M:TheNamespace.Class2.OtherMethod0" />
/// and <see cref="M:TheNamespace.Class2.Method1(System.String)" />
/// and <see cref="M:TheNamespace.Class2.Method2(System.String,System.Object)" />
let referringFunction1 () = "result"
(**
Generic types are referred to by .NET compiled name, e.g.
*)
type GenericClass2<'T>() =
member this.Property = "more"
member this.NonGenericMethod(_c: 'T) = "more"
member this.GenericMethod(_c: 'T, _o: 'U) = "more"
/// See <see cref="T:TheNamespace.GenericClass2`1" />
/// and <see cref="P:TheNamespace.GenericClass2`1.Property" />
/// and <see cref="M:TheNamespace.GenericClass2`1.NonGenericMethod(`0)" />
/// and <see cref="M:TheNamespace.GenericClass2`1.GenericMethod``1(`0,``0)" />
let referringFunction2 () = "result"
(**
### Cross-referencing with <seealso>
Use `<seealso cref="..."/>` within `<summary>` to create cross-references.
For example:
*)
module Forest =
/// <summary>
/// Find at most <c>limit</c> foxes in current forest
///
/// See also: <seealso cref="M:App.Forest.findSquirrels(System.Int32)"/>
/// </summary>
let findFoxes (limit : int) = []
/// <summary>
/// Find at most <c>limit</c> squirrels in current forest
///
/// See also: <seealso cref="M:App.Forest.findFoxes(System.Int32)"/>
/// </summary>
let findSquirrels (limit : int) = []
(**
You can find the correct value for `cref` in the generated `.xml` documentation file (this will be generated alongside the assembly's `.dll``).
You can also omit the `cref`'s arguments, and `fsdocs` will make an attempt to find the first member that matches.
For example:
```
/// See also: <seealso cref="M:App.Forest.findSquirrels"/>
```
If the member cannot be found, a link to the containing module/type will be used instead.
### Classic XMl Doc Comments: Excluding APIs from the docs
If you want to exclude modules or functions from the API docs you can use the `<exclude/>` tag.
It needs to be set on a separate triple-slashed line, and can either appear on its own or as part
of an existing `<summary>` (for example, you may wish to hide existing documentation while it's in progress).
The `<exclude/>` tag can be the first or last line in these cases.
Some examples:
*)
/// <exclude/>
module BottleKids1 =
let a = 42
// Ordinary comment
/// <exclude/>
module BottleKids2 =
let a = 43
/// <exclude/>
/// BottleKids3 provides improvements over BottleKids2
module BottleKids3 =
let a = 44
/// BottleKids4 implements several new features over BottleKids3
/// <exclude/>
module BottleKids4 =
let a = 45
/// <exclude/>
/// <summary>
/// BottleKids5 is all you'll ever need in terms of bottles or kids.
/// </summary>
module BottleKids5 =
let a = 46
(**
Note that the comments for `BottleKids3` (and `BottleKids4`) will generate a warning. This is because
the `<exclude/>` tag will be parsed as part of the `summary` text, and so the documentation generator
can't be completely sure you meant to exclude the item, or whether it was a valid part of the documentation.
It will assume the exclusion was intended, but you may want to use explicit `<summary>` tags to remove
the warning.
The warning will be of the following format:
```
Warning: detected "<exclude/>" in text of "<summary>" for "M:YourLib.BottleKids4". Please see https://fsprojects.github.io/FSharp.Formatting/apidocs.html#Classic-XML-Doc-Comments
```
You will find that `[omit]` also works, but is considered part of the Markdown syntax and is
deprecated for XML Doc comments. This will also produce a warning, such as this:
```
The use of `[omit]` and other commands in XML comments is deprecated, please use XML extensions, see https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1031-xmldoc-extensions.md
```
## Go to Source links
'fsdocs' normally automatically adds GitHub links to each functions, values and class members for further reference.
This is normally done automatically based on the following settings:
```xml
<RepositoryUrl>https://github.com/...</RepositoryUrl>
<RepositoryBranch>...</RepositoryBranch>
<RepositoryType>git</RepositoryType>
```
If your source is not built from the same project where you are building documentation then
you may need these settings:
```xml
<FsDocsSourceRepository>...</FsDocsSourceRepository> -- the URL for the root of the source
<FsDocsSourceFolder>...</FsDocsSourceFolder> -- the root soure folder at time of build
```
It is assumed that `sourceRepo` and `sourceFolder` have synchronized contents.
## Markdown Comments
You can use Markdown instead of XML in `///` comments. If you do, you should set `<UsesMarkdownComments>true</UsesMarkdownComments>` in
your F# project file.
> Note: Markdown Comments are not supported in all F# IDE tooling.
>
### Adding cross-type links to modules and types in the same assembly
You can automatically add cross-type links to the documentation pages of other modules and types in the same assembly.
You can do this in two different ways:
* Add a [markdown inline link](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#links) were the link
title is the name of the type you want to link.
/// this will generate a link to [Foo.Bar] documentation
* Add a [Markdown inline code](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) (using
back-ticks) where the code is the name of the type you want to link.
/// This will also generate a link to `Foo.Bar` documentation
You can use either the full name (including namespace and module) or the simple name of a type.
If more than one type is found with the same name the link will not be generated.
If a type with the given name is not found in the same assembly the link will not be generated.
*)
/// Contains two types [Bar] and [Foo.Baz]
module Foo =
/// Bar is just an `int` and belongs to module [Foo]
type Bar = int
/// Baz contains a `Foo.Bar` as its `id`
type Baz = { id: Bar }
/// This function operates on `Baz` types.
let f (b: Baz) = b.id * 42
/// Referencing [Foo3] will not generate a link as there is no type with the name `Foo3`
module Foo3 =
/// This is not the same type as `Foo.Bar`
type Bar = double
/// Using the simple name for [Bar] will fail to create a link because the name is duplicated in
/// [Foo.Bar] and in [Foo3.Bar]. In this case, using the full name works.
let f2 b = b * 50
(**
### Markdown Comments: Excluding APIs from the docs
If you want to exclude modules or functions from the API docs you can use the `[omit]` tag.
It needs to be set on a separate triple-slashed line, but it could be either the first or the last:
Example as last line:
*)
/// Some actual comment
/// [omit]
module Bar =
let a = 42
(**
Example as first line:
*)
/// [omit]
/// Some actual comment
module Bar2 =
let a = 42
(**
## Building library documentation programmatically
You can build library documentation programatically using the functionality
in the [ApiDocs](https://fsprojects.github.io/FSharp.Formatting/reference/fsharp-formatting-apidocs-apidocs.html) type. To do this, load the assembly and open necessary namespaces:
*)
#r "FSharp.Formatting.ApiDocs.dll"
open FSharp.Formatting.ApiDocs
open System.IO
(**
For example the [ApiDocs.GenerateHtml](https://fsprojects.github.io/FSharp.Formatting/reference/fsharp-formatting-apidocs-apidocs.html#GenerateHtml) method:
*)
let file = Path.Combine(root, "bin/YourLibrary.dll")
let input = ApiDocInput.FromFile(file)
ApiDocs.GenerateHtml(
[ input ],
output = Path.Combine(root, "output"),
collectionName = "YourLibrary",
template = Path.Combine(root, "templates", "template.html"),
substitutions = []
)
(**
### Adding extra dependencies
When building a library programmatically, you might require a reference to an additional assembly.
You can pass this using the `otherFlags` argument.
*)
let projectAssembly = Path.Combine(root, "bin/X.dll")
let projectInput = ApiDocInput.FromFile(projectAssembly)
ApiDocs.GenerateHtml(
[ projectInput ],
output = Path.Combine(root, "output"),
collectionName = "Project X",
template = Path.Combine(root, "templates", "template.html"),
substitutions = [],
otherFlags = [ "-r:/root/ProjectY/bin/Debug/net6.0/Y.dll" ]
)
(**
or use `libDirs` to include all assemblies from an entire folder.
Tip: A combination of `<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>` in the fsproj file and setting `libDirs` to the compilation output path leads to only one folder with all dependencies referenced.
This might be easier especially for large projects with many dependencies.
*)
ApiDocs.GenerateHtml(
[ projectInput ],
output = Path.Combine(root, "output"),
collectionName = "Project X",
template = Path.Combine(root, "templates", "template.html"),
substitutions = [],
libDirs = [ "ProjectX/bin/Debug/netstandard2.0" ]
)
(**
## Rebasing Links
The `root` parameter is used for the base of page and image links in the generated documentation. By default it is derived from the project's `<PackageProjectUrl>` property.
In some instances, you may wish to override the value for `root` (perhaps for local testing). To do this, you can use the command-line argument `--parameters root <base>`.
For example:
[lang=text]
dotnet fsdocs build --output public/docs --parameters root ../
*)