diff --git a/docs/apidocs.fsx b/docs/apidocs.fsx index c1807b44c..82c019127 100644 --- a/docs/apidocs.fsx +++ b/docs/apidocs.fsx @@ -27,13 +27,13 @@ let root = "C:\\" (** [![Binder](img/badge-binder.svg)](https://mybinder.org/v2/gh/diffsharp/diffsharp.github.io/master?filepath={{fsdocs-source-basename}}.ipynb)  -[![Script](img/badge-script.svg)]({{fsdocs-source-basename}}.fsx)  -[![Notebook](img/badge-notebook.svg)]({{fsdocs-source-basename}}.ipynb) +[![Script](img/badge-script.svg)]({{root}}/{{fsdocs-source-basename}}.fsx)  +[![Notebook](img/badge-notebook.svg)]({{root}}/{{fsdocs-source-basename}}.ipynb) API Documentation Generation ==================================== -The [command-line tool `fsdocs`](commandline.html) can be used to generate documentation +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. @@ -41,7 +41,7 @@ the former the output will be placed in `output\reference` by default. The HTML is built by instantiating a template. The template used is the first of: -* `docs/reference/_template.html` +* `docs/reference/_template.html` * `docs/_template.html` @@ -57,11 +57,11 @@ The tags that form the core of the XML doc specification are: ``` * - * * - -* * * -* - + * * + +* * * +* + ``` 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). @@ -75,7 +75,7 @@ In addition, you may also use the [Recommended XML doc extensions for F# documen * `` to exclude from XML docs * `` to give a category for an entity or member. An optional `index` attribute can be specified - to help sort the list of categories. + to help sort the list of categories. * `\(...\)` for inline math and `$$...$$` and `\[...\]`for math environments, see http://docs.mathjax.org. Some escaping of characters (e.g. `<`, `>`) may be needed to form valid XML @@ -92,7 +92,7 @@ An example of an XML documentation comment, assuming the code is in namespace `T /// More on that /// /// -module SomeModule = +module SomeModule = /// /// Some actual comment /// Another paragraph, see . @@ -115,7 +115,7 @@ module SomeModule = /// /// A type, see and -/// . +/// . /// /// type SomeType() = @@ -127,7 +127,7 @@ Like types, members are referred to by xml doc sig. These must currently be pre compiler doesn't elaborate these references from simpler names: *) -type Class2() = +type Class2() = member this.Property = "more" member this.Method0() = "more" member this.Method1(c: string) = "more" @@ -143,7 +143,7 @@ let referringFunction1 () = "result" Generic types are referred to by .NET compiled name, e.g. *) -type GenericClass2<'T>() = +type GenericClass2<'T>() = member this.Property = "more" member this.NonGenericMethod(_c: 'T) = "more" @@ -171,7 +171,7 @@ This is normally done automatically based on the following settings: If your source is not built from the same project where you are building documentation then you may need these settings: - ... -- the URL for the root of the source + ... -- the URL for the root of the source ... -- the root soure folder at time of build It is assumed that `sourceRepo` and `sourceFolder` have synchronized contents. @@ -204,25 +204,25 @@ If a type with the given name is not found in the same assembly the link will no *) /// Contains two types [Bar] and [Foo.Baz] -module Foo = - +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) = + 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 + /// 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 @@ -236,7 +236,7 @@ It needs to be set on a separate tripple-slashed line, but it could be either th *) /// [omit] /// Some actual comment -module Bar = +module Bar = let a = 42 (** @@ -256,9 +256,9 @@ For example the `cref:M:FSharp.Formatting.ApiDocs.ApiDocs.GenerateHtml` method: *) let file = Path.Combine(root, "bin/YourLibrary.dll") -let input = ApiDocInput.FromFile(file) +let input = ApiDocInput.FromFile(file) ApiDocs.GenerateHtml - ( [ input ], + ( [ input ], output=Path.Combine(root, "output"), collectionName="YourLibrary", template=Path.Combine(root, "templates", "template.html"), diff --git a/docs/codeformat.fsx b/docs/codeformat.fsx index 562d6f185..5135f7d35 100644 --- a/docs/codeformat.fsx +++ b/docs/codeformat.fsx @@ -23,13 +23,13 @@ index: 1 (** [![Binder](img/badge-binder.svg)](https://mybinder.org/v2/gh/diffsharp/diffsharp.github.io/master?filepath={{fsdocs-source-basename}}.ipynb)  -[![Script](img/badge-script.svg)]({{fsdocs-source-basename}}.fsx)  -[![Notebook](img/badge-notebook.svg)]({{fsdocs-source-basename}}.ipynb) +[![Script](img/badge-script.svg)]({{root}}/{{fsdocs-source-basename}}.fsx)  +[![Notebook](img/badge-notebook.svg)]({{root}}/{{fsdocs-source-basename}}.ipynb) Code formatting ============================== -This page demonstrates how to use `FSharp.Formatting.CodeFormat` to tokenize +This page demonstrates how to use `FSharp.Formatting.CodeFormat` to tokenize F# source code, obtain information about the source code (mainly tooltips from the type-checker) and how to turn the code into a nicely formatted HTML. @@ -52,9 +52,9 @@ can be called to format snippets repeatedly: let formattingAgent = CodeFormat.CreateAgent() (** -If you want to process multiple snippets, it is a good idea to keep the +If you want to process multiple snippets, it is a good idea to keep the formatting agent around if possible. The agent needs to load the F# compiler -(which needs to load various files itself) and so this takes a long time. +(which needs to load various files itself) and so this takes a long time. Processing F# source -------------------- @@ -65,7 +65,7 @@ To call the method, we define a simple F# code as a string: *) let source = """ - let hello () = + let hello () = printfn "Hello world" """ let snippets, errors = formattingAgent.ParseAndCheckSource("C:\\snippet.fsx", source) @@ -76,10 +76,10 @@ of the script file. The file does not have to physically exist. It is used by th F# compiler to resolve relative references (e.g. `#r`) and to automatically name the module including all code in the file. -You can also specify additional parameters, such as `*.dll` references, by passing -a third argument with compiler options (e.g. `"-r:Foo.dll -r:Bar.dll"`). +You can also specify additional parameters, such as `*.dll` references, by passing +a third argument with compiler options (e.g. `"-r:Foo.dll -r:Bar.dll"`). -This operation might take some time, so it is a good idea to use an asynchronous +This operation might take some time, so it is a good idea to use an asynchronous variant of the method. It returns two arrays - the first contains F# snippets in the source code and the second contains any errors reported by the compiler. A single source file can include multiple snippets using the same formatting tags @@ -90,7 +90,7 @@ as those used on [fssnip.net](http://www.fssnip.net) as documented in the Working with returned tokens ---------------------------- -Each returned snippet is essentially just a collection of lines and each line +Each returned snippet is essentially just a collection of lines and each line consists of a sequence of tokens. The following snippet prints basic information about the tokens of our sample snippet: *) @@ -102,38 +102,38 @@ let (Snippet(title, lines)) = snippets |> Seq.head for (Line(_, tokens)) in lines do for token in tokens do match token with - | TokenSpan.Token(kind, code, tip) -> + | TokenSpan.Token(kind, code, tip) -> printf "%s" code tip |> Option.iter (fun spans -> - printfn "%A" spans) - | TokenSpan.Omitted _ - | TokenSpan.Output _ + printfn "%A" spans) + | TokenSpan.Omitted _ + | TokenSpan.Output _ | TokenSpan.Error _ -> () printfn "" (** The `TokenSpan.Token` is the most important kind of token. It consists of a kind (identifier, keyword, etc.), the original F# code and tool tip information. -The tool tip is further formatted using a simple document format, but we simply +The tool tip is further formatted using a simple document format, but we simply print the value using the F# pretty printing, so the result looks as follows: - let hello[Literal "val hello : unit -> unit"; ...] () = + let hello[Literal "val hello : unit -> unit"; ...] () = printfn[Literal "val printfn : TextWriterFormat<'T> -> 'T"; ...] "Hello world" The `Omitted` token is generated if you use the special `(*[omit:...]*)` command. The `Output` token is generated if you use the `// [fsi:...]` command to format -output returned by F# interactive. The `Error` command wraps code that should be +output returned by F# interactive. The `Error` command wraps code that should be underlined with a red squiggle if the code contains an error. Generating HTML output ---------------------- Finally, the `CodeFormat` type also includes a method `cref:M:FSharp.Formatting.CodeFormat.CodeFormat.FormatHtml` that can be used -to generate nice HTML output from an F# snippet. This is used, for example, on +to generate nice HTML output from an F# snippet. This is used, for example, on [F# Snippets](http://www.fssnip.net). The following example shows how to call it: *) -let prefix = "fst" +let prefix = "fst" let html = CodeFormat.FormatHtml(snippets, prefix) // Print all snippets, in case there is more of them diff --git a/docs/content.fsx b/docs/content.fsx index 9430d2212..d56c6b6d0 100644 --- a/docs/content.fsx +++ b/docs/content.fsx @@ -24,8 +24,8 @@ index: 3 (** [![Binder](img/badge-binder.svg)](https://mybinder.org/v2/gh/diffsharp/diffsharp.github.io/master?filepath={{fsdocs-source-basename}}.ipynb)  -[![Script](img/badge-script.svg)]({{fsdocs-source-basename}}.fsx)  -[![Notebook](img/badge-notebook.svg)]({{fsdocs-source-basename}}.ipynb) +[![Script](img/badge-script.svg)]({{root}}/{{fsdocs-source-basename}}.fsx)  +[![Notebook](img/badge-notebook.svg)]({{root}}/{{fsdocs-source-basename}}.ipynb) Creating Content =================================== @@ -123,30 +123,30 @@ generated outputs. See [Styling](styling.html) for information about template parameters and styling beyond the default template. -| Substitution name | Generated content | +| Substitution name | Generated content | |:------------------------------|:--------------------------------------------------------------| -| `root` | `` else `/` followed by `fsdocs-collection-name` | -| `fsdocs-collection-name` | Name of .sln, single .fsproj or containing directory | -| `fsdocs-content` | Main page content | -| `fsdocs-list-of-namespaces` | HTML `
  • ` list of namespaces with links | -| `fsdocs-list-of-documents` | HTML `
  • ` list of documents with titles and links | -| `fsdocs-page-title` | First h1 heading in literate file. Generated for API docs | -| `fsdocs-source` | Original literate script or markdown source | -| `fsdocs-source-filename` | Name of original input source, relative to the `docs` root | -| `fsdocs-source-basename` | Name of original input source, excluding its extensions, relative to the `docs` root | -| `fsdocs-tooltips` | Generated hidden div elements for tooltips | +| `root` | `` else `/` followed by `fsdocs-collection-name` | +| `fsdocs-collection-name` | Name of .sln, single .fsproj or containing directory | +| `fsdocs-content` | Main page content | +| `fsdocs-list-of-namespaces` | HTML `
  • ` list of namespaces with links | +| `fsdocs-list-of-documents` | HTML `
  • ` list of documents with titles and links | +| `fsdocs-page-title` | First h1 heading in literate file. Generated for API docs | +| `fsdocs-source` | Original literate script or markdown source | +| `fsdocs-source-filename` | Name of original input source, relative to the `docs` root | +| `fsdocs-source-basename` | Name of original input source, excluding its extensions, relative to the `docs` root | +| `fsdocs-tooltips` | Generated hidden div elements for tooltips | | `fsdocs-watch-script` | The websocket script used in watch mode to trigger hot reload | The following substitutions are extracted from your project files and may or may not be used by the default template: -| Substitution name | Value | -|:-------------------------------------|:-------------------------------| -| `fsdocs-copyright` | `` | -| `fsdocs-package-project-url` | `` | +| Substitution name | Value | +|:-------------------------------------|:-------------------------------| +| `fsdocs-copyright` | `` | +| `fsdocs-package-project-url` | `` | | `fsdocs-package-license-expression` | `` | -| `fsdocs-package-tags` | `` | -| `fsdocs-package-version` | `` | +| `fsdocs-package-tags` | `` | +| `fsdocs-package-version` | `` | For the `fsdocs` tool, additional substitutions can be specified using `--parameters`. @@ -196,7 +196,7 @@ If a file `_template.html` exists then is used as the template for HTML generati To generate .tex output for each script and markdown file, add a `_template.tex`. Substitutions are applied to this template. The file is either empty of contains `{{fsdocs-content}}` as the key where the body -of the document is placed. +of the document is placed. ## Generating iPython Notebook output @@ -207,11 +207,11 @@ To add a `mybinder` badge to your generated notebook, ensure you have a `Dockerf in your `docs` directory and use text like this: [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fsprojects/FSharp.Formatting/gh-pages?filepath=literate.ipynb) - + ## Generating Script outputs To generate .fsx output for each script and markdown file, add a `_template.fsx`, usually empty. Substitutions are applied to this template. It is either empty of contains `{{fsdocs-content}}` as the key where the body -of the script is placed. +of the script is placed. *) diff --git a/docs/evaluation.fsx b/docs/evaluation.fsx index afdf6386f..fd424c0b2 100644 --- a/docs/evaluation.fsx +++ b/docs/evaluation.fsx @@ -23,8 +23,8 @@ index: 6 (** [![Binder](img/badge-binder.svg)](https://mybinder.org/v2/gh/diffsharp/diffsharp.github.io/master?filepath={{fsdocs-source-basename}}.ipynb)  -[![Script](img/badge-script.svg)]({{fsdocs-source-basename}}.fsx)  -[![Notebook](img/badge-notebook.svg)]({{fsdocs-source-basename}}.ipynb) +[![Script](img/badge-script.svg)]({{root}}/{{fsdocs-source-basename}}.fsx)  +[![Notebook](img/badge-notebook.svg)]({{root}}/{{fsdocs-source-basename}}.ipynb) # Embedding script output @@ -96,10 +96,10 @@ Some raw text. directly into the document. -F# Formatting as a Library: Specifying the Evaluator and Formatting +F# Formatting as a Library: Specifying the Evaluator and Formatting --------------------------------------- -If using F# Formatting as a library the embedding of F# output requires specifying an additional parameter to the +If using F# Formatting as a library the embedding of F# output requires specifying an additional parameter to the parsing functions discussed in [literate programming documentation](literate.html). Assuming you have all the references in place, you can now create an instance of `cref:T:FSharp.Formatting.Literate.Evaluation.FsiEvaluator` that represents a wrapper for F# interactive and pass it to all the @@ -126,7 +126,7 @@ it is not created automatically and so the functionality is not available (this you won't accidentally run unexpected code!) If you specify the `fsiEvaluator` parameter, but don't want a specific snippet to be evaluated -(because it might throw an exception, for example), you can use the `(*** do-not-eval ***)` +(because it might throw an exception, for example), you can use the `(*** do-not-eval ***)` command. The constructor of `cref:T:FSharp.Formatting.Literate.Evaluation.FsiEvaluator` takes command line parameters for `fsi.exe` that can @@ -142,7 +142,7 @@ F# Formatting as a Library: Custom formatting functions As mentioned earlier, values are formatted using a simple `"%A"` formatter by default. However, you can specify a formatting function that provides a nicer formatting for values of certain types. For example, let's say that we would want to format F# lists such as -`[1; 2; 3]` as HTML ordered lists `
      `. +`[1; 2; 3]` as HTML ordered lists `
        `. This can be done by calling `cref:M:FSharp.Formatting.Literate.Evaluation.FsiEvaluator.RegisterTransformation` on the `FsiEvaluator` instance: @@ -152,9 +152,9 @@ let fsiOl = FsiEvaluator() fsiOl.RegisterTransformation(fun (o, ty, _executionCount) -> // If the type of value is an F# list, format it nicely if ty.IsGenericType && ty.GetGenericTypeDefinition() = typedefof> then - let items = + let items = // Get items as objects and create paragraph for each item - [ for it in Seq.cast (unbox o) -> + [ for it in Seq.cast (unbox o) -> [ Paragraph([Literal(it.ToString(), None)], None) ] ] // Return option value (success) with ordered list Some [ ListBlock(MarkdownListKind.Ordered, items, None) ] @@ -163,7 +163,7 @@ fsiOl.RegisterTransformation(fun (o, ty, _executionCount) -> The function is called with two arguments - `o` is the value to be formatted and `ty` is the static type of the value (as inferred by the F# compiler). The sample checks -that the type of the value is a list (containing values of any type) and then it +that the type of the value is a list (containing values of any type) and then it casts all values in the list to `obj` (for simplicity). Then we generate Markdown blocks representing an ordered list. This means that the code will work for both LaTeX and HTML formatting - but if you only need one, you can simply produce HTML and diff --git a/docs/literate.fsx b/docs/literate.fsx index 5f553b960..7e5ef53ee 100644 --- a/docs/literate.fsx +++ b/docs/literate.fsx @@ -24,8 +24,8 @@ index: 3 (** [![Binder](img/badge-binder.svg)](https://mybinder.org/v2/gh/diffsharp/diffsharp.github.io/master?filepath={{fsdocs-source-basename}}.ipynb)  -[![Script](img/badge-script.svg)]({{fsdocs-source-basename}}.fsx)  -[![Notebook](img/badge-notebook.svg)]({{fsdocs-source-basename}}.ipynb) +[![Script](img/badge-script.svg)]({{root}}/{{fsdocs-source-basename}}.fsx)  +[![Notebook](img/badge-notebook.svg)]({{root}}/{{fsdocs-source-basename}}.ipynb) Literate Scripts ================ @@ -37,14 +37,14 @@ F# script file with `.fsx` extension. Most of the features should be quite self- # First-level heading Some more documentation using `Markdown`. *) - + let helloWorld() = printfn "Hello world!" - (** + (** ## Second-level heading With some more documentation *) - + let numbers = [ 0 .. 99 ] (*** include-value: numbers ***) @@ -53,12 +53,12 @@ F# script file with `.fsx` extension. Most of the features should be quite self- The F# script files is processed as follows: -- A multi-line comment starting with `(**` and ending with `*)` is - turned into text and is processed using the F# Markdown processor +- A multi-line comment starting with `(**` and ending with `*)` is + turned into text and is processed using the F# Markdown processor (which supports standard Markdown commands). -- A single-line comment starting with `(***` and ending with `***)` - is treated as a special command. The command can consist of +- A single-line comment starting with `(***` and ending with `***)` + is treated as a special command. The command can consist of `key`, `key: value` or `key=value` pairs. | Literate Command | Description | @@ -79,7 +79,7 @@ The F# script files is processed as follows: ### Named snippets -The command `define` defines a named snippet (such as `final-sample`) and removes the command together with +The command `define` defines a named snippet (such as `final-sample`) and removes the command together with the following F# code block from the main document. The snippet can then be referred to using these variations. This makes it possible to write documents without the ordering requirements of the @@ -97,7 +97,7 @@ F# language. #### Hiding code snippets -The command `hide` specifies that the following F# code block (until the next comment or command) should be +The command `hide` specifies that the following F# code block (until the next comment or command) should be omitted from the output. #### Evaluating and formatting results @@ -114,7 +114,7 @@ Substitutions are applied to content, see [content](content.html). For files with `.md` extension, the entire file is a Markdown document, which may contain F# code snippets (but also other code snippets). As usual, snippets are indented with four spaces. In addition, the snippets can be annotated with special -commands. Some of them are demonstrated in the following example: +commands. Some of them are demonstrated in the following example: [lang=text] # First-level heading @@ -158,7 +158,7 @@ Literate Scripts may contain LaTeX sections in Markdown using these forms: 1. Single line latex starting with `$$`. -2. A block delimited by `\begin{equation}...\end{equation}` or `\begin{align}...\end{align}`. +2. A block delimited by `\begin{equation}...\end{equation}` or `\begin{align}...\end{align}`. 3. An indented paragraph starting with `$$$`. This is F#-literate-specific and corresponds to `\begin{equation}...\end{equation}`. @@ -237,7 +237,7 @@ let projInfo = (** -The methods used above (`cref:M:FSharp.Formatting.Literate.Literate.ConvertScriptFile`, `cref:M:FSharp.Formatting.Literate.Literate.ConvertMarkdownFile`) +The methods used above (`cref:M:FSharp.Formatting.Literate.Literate.ConvertScriptFile`, `cref:M:FSharp.Formatting.Literate.Literate.ConvertMarkdownFile`) produce HTML output by default, but they can be also used to produce LaTeX output. This is done by setting the output kind. The following example shows how to call the methods to generate LaTeX documents: @@ -252,7 +252,7 @@ Literate.ConvertMarkdownFile(docTex, templateTex, outputKind=OutputKind.Latex) (** -The methods used above (`ConvertScriptFile`, `ConvertMarkdownFile`) +The methods used above (`ConvertScriptFile`, `ConvertMarkdownFile`) can also produce iPython Notebook output. This is done by setting the named parameter `format` to `OutputKind.Pynb`: *) diff --git a/docs/markdown.fsx b/docs/markdown.fsx index 4f8f3e914..b62c67fe6 100644 --- a/docs/markdown.fsx +++ b/docs/markdown.fsx @@ -21,8 +21,8 @@ index: 2 (** [![Binder](img/badge-binder.svg)](https://mybinder.org/v2/gh/diffsharp/diffsharp.github.io/master?filepath={{fsdocs-source-basename}}.ipynb)  -[![Script](img/badge-script.svg)]({{fsdocs-source-basename}}.fsx)  -[![Notebook](img/badge-notebook.svg)]({{fsdocs-source-basename}}.ipynb) +[![Script](img/badge-script.svg)]({{root}}/{{fsdocs-source-basename}}.fsx)  +[![Notebook](img/badge-notebook.svg)]({{root}}/{{fsdocs-source-basename}}.ipynb) Markdown parser ============================== @@ -43,7 +43,7 @@ Parsing documents ----------------- The F# Markdown parser recognizes the standard [Markdown syntax](http://daringfireball.net/projects/markdown/) -and it is not the aim of this tutorial to fully document it. +and it is not the aim of this tutorial to fully document it. The following snippet creates a simple string containing a document with several elements and then parses it using the `cref:M:FSharp.Formatting.Markdown.Markdown.Parse` method: *) @@ -61,9 +61,9 @@ For more see [fsharp.org][fsorg]. let parsed = Markdown.Parse(document) (** -The sample document consists of a first-level heading (written using -one of the two alternative styles) followed by a paragraph with a -_direct_ link, code snippet and one more paragraph that includes an +The sample document consists of a first-level heading (written using +one of the two alternative styles) followed by a paragraph with a +_direct_ link, code snippet and one more paragraph that includes an _indirect_ link. The URLs of indirect links are defined by a separate block as demonstrated on the last line (and they can then be easily used repeatedly from multiple places in the document). @@ -72,7 +72,7 @@ Working with parsed documents ----------------------------- The F# Markdown processor does not turn the document directly into HTML. -Instead, it builds a nice F# data structure that we can use to analyze, +Instead, it builds a nice F# data structure that we can use to analyze, transform and process the document. First of all the `cref:P:FSharp.Formatting.Markdown.MarkdownDocument.DefinedLinks` property returns all indirect link definitions: *) @@ -90,7 +90,7 @@ The following snippet prints the heading of the document: // Iterate over all the paragraph elements for par in parsed.Paragraphs do match par with - | Heading(size=1; body=[Literal(text=text)]) -> + | Heading(size=1; body=[Literal(text=text)]) -> // Recognize heading that has a simple content // containing just a literal (no other formatting) printfn "%s" text @@ -103,13 +103,13 @@ in the book [F# Deep Dives](http://manning.com/petricek2/). Processing the document recursively ----------------------------------- -The library provides active patterns that can be used to easily process the Markdown +The library provides active patterns that can be used to easily process the Markdown document recursively. The example in this section shows how to extract all links from the document. To do that, we need to write two recursive functions. One that will process all paragraph-style elements and one that will process all inline formattings (inside paragraphs, headings etc.). -To avoid pattern matching on every single kind of span and every single kind of +To avoid pattern matching on every single kind of span and every single kind of paragraph, we can use active patterns from the `cref:T:FSharp.Formatting.Markdown.MarkdownPatterns` module. These can be use to recognize any paragraph or span that can contain child elements: @@ -123,14 +123,14 @@ let rec collectSpanLinks span = seq { | MarkdownPatterns.SpanLeaf _ -> () | MarkdownPatterns.SpanNode(_, spans) -> for s in spans do yield! collectSpanLinks s } - + /// Returns all links in the specified paragraph node let rec collectParLinks par = seq { match par with | MarkdownPatterns.ParagraphLeaf _ -> () - | MarkdownPatterns.ParagraphNested(_, pars) -> - for ps in pars do - for p in ps do yield! collectParLinks p + | MarkdownPatterns.ParagraphNested(_, pars) -> + for ps in pars do + for p in ps do yield! collectParLinks p | MarkdownPatterns.ParagraphSpans(_, spans) -> for s in spans do yield! collectSpanLinks s } @@ -150,11 +150,11 @@ Some span nodes (like emphasis) can contain other formatting, so we need to recu process children. This is done by matching against `MarkdownPatterns.SpanNodes` which is an active pattern that recognizes any node with children. The library also provides a _function_ named `MarkdownPatterns.SpanNode` that can be used to reconstruct the same node (when you want -to transform document). This is similar to how the `ExprShape` module for working with +to transform document). This is similar to how the `ExprShape` module for working with F# quotations works. -The function `collectParLinks` processes paragraphs - a paragraph cannot directly be a -link so we just need to process all spans. This time, there are three options. +The function `collectParLinks` processes paragraphs - a paragraph cannot directly be a +link so we just need to process all spans. This time, there are three options. `ParagraphLeaf` represents a case where the paragraph does not contain any spans (a code block or, for example, a `
        ` line); the `ParagraphNested` case is used for paragraphs that contain other paragraphs (quotation) and `ParagraphSpans` is used for all other