this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'cmstatefield' (revert search)

+174 -102
+64 -21
doc/extensions.mld
··· 1 1 {0 Writing Extensions} 2 2 3 + @admonition.note The odoc extension API is early in development and 4 + the interface is still changing frequently. Expect breaking changes 5 + between releases. 6 + 3 7 [odoc] supports a plugin system for custom tags and code blocks. Extensions 4 8 are OCaml libraries loaded at doc-generation time that transform custom 5 9 markup into HTML, LaTeX, or other output formats. ··· 12 16 There are two kinds of extension: 13 17 14 18 {ul 15 - {- {b Tag extensions} handle custom tags like [@@note], [@@rfc], [@@scrolly]. 19 + {- {b Tag extensions} handle custom tags like [@note], [@rfc], [@scrolly]. 16 20 They receive the tag's content as a list of block elements and return 17 21 document content, resources, and assets.} 18 22 {- {b Code block extensions} handle fenced code blocks with a custom 19 - language, e.g., [{@@dot ...}] or [{@@ocaml ...}]. 23 + language, e.g., [{@dot ...}] or [{@ocaml ...}]. 20 24 They receive the code text plus any options and return the same output 21 25 types.}} 22 26 ··· 87 91 (e.g., injecting a [<meta>] tag). Never put your main runtime in an 88 92 inline script. 89 93 94 + {1 JavaScript Lifecycle} 95 + 96 + The following diagram shows when extension JavaScript runs during both 97 + direct page loads and SPA navigations: 98 + 99 + {@mermaid[ 100 + sequenceDiagram 101 + participant Browser 102 + participant Head as head scripts 103 + participant Shell as Docsite Shell 104 + participant Ext as Extension JS 105 + participant DOM 106 + 107 + rect rgb(40, 60, 80) 108 + Note over Browser,DOM: Direct page load 109 + Browser->>Head: Parse head 110 + Head->>Ext: Load via script src="ext.js" 111 + Ext->>Ext: readyState === 'loading' 112 + Browser->>DOM: DOMContentLoaded 113 + Ext->>DOM: initAll() — find and init widgets 114 + Ext->>DOM: Listen for 'odoc-spa-loaded' 115 + end 116 + 117 + rect rgb(60, 40, 60) 118 + Note over Browser,DOM: SPA navigation (sidebar click) 119 + Browser->>Shell: click event on sidebar link 120 + Shell->>Shell: fetch(newPage.html) 121 + Shell->>DOM: Swap .odoc-content innerHTML 122 + Shell->>DOM: Load new head scripts 123 + Shell->>DOM: Dispatch 'odoc-spa-loaded' event 124 + Note over Head: ext.js already loaded — NOT re-executed 125 + Note over DOM: DOMContentLoaded does NOT fire 126 + DOM->>Ext: 'odoc-spa-loaded' handler fires 127 + Ext->>DOM: initAll() — find new widgets, skip already-init'd 128 + end 129 + ]} 130 + 131 + The key insight: on SPA navigation, neither the script nor 132 + [DOMContentLoaded] re-fires. The shell dispatches a custom 133 + [odoc-spa-loaded] event after swapping content and loading head 134 + scripts — this is the recommended way for extensions to detect 135 + new content after navigation. 136 + 90 137 {1:spa SPA Navigation: The Critical Pitfall} 91 138 92 139 The odoc {b docsite shell} (and similar shells) implement single-page app ··· 155 202 156 203 // Run on initial page load. 157 204 if (document.readyState === 'loading') { 158 - document.addEventListener('DOMContentLoaded', function() { 159 - initAll(); 160 - observe(); 161 - }); 205 + document.addEventListener('DOMContentLoaded', function() { initAll(); }); 162 206 } else { 163 207 initAll(); 164 - observe(); 165 208 } 166 209 167 - // Watch for new content injected by SPA navigation. 168 - function observe() { 169 - new MutationObserver(function() { initAll(); }) 170 - .observe(document.body, { childList: true, subtree: true }); 171 - } 210 + // Re-initialise after SPA navigation swaps in new content. 211 + document.addEventListener('odoc-spa-loaded', function() { initAll(); }); 172 212 })(); 173 213 ]} 174 214 ··· 176 216 177 217 {ul 178 218 {- {b Guard against double-init.} Use a [data-*] attribute to mark 179 - initialised elements. The [MutationObserver] fires on every DOM 180 - mutation, so [initAll] may be called many times.} 219 + initialised elements. [initAll] may be called multiple times.} 181 220 {- {b Check [document.readyState].} The script is in [<head>], so 182 221 [document.body] doesn't exist yet on the initial load. Wait for 183 - [DOMContentLoaded] before attaching the [MutationObserver].} 222 + [DOMContentLoaded] before first [initAll].} 223 + {- {b Listen for [odoc-spa-loaded].} The docsite shell dispatches this 224 + custom event after swapping content and loading head scripts. This 225 + is the recommended way for extensions to detect new content.} 184 226 {- {b Don't rely on [DOMContentLoaded] alone.} After SPA navigation the 185 227 [Js_url] script has already loaded and [DOMContentLoaded] already fired. 186 - The [MutationObserver] is what detects the new content.}} 228 + The [odoc-spa-loaded] event is what triggers re-initialisation.}} 187 229 188 230 {2 Case study: Scrollycode} 189 231 ··· 225 267 ]} 226 268 } 227 269 {- Replace the [DOMContentLoaded] gate with [readyState] check + 228 - [MutationObserver] (as shown in the pattern above).} 270 + [odoc-spa-loaded] listener (as shown in the pattern above).} 229 271 {- Add a [data-sc-init] guard on each [.sc-container] to prevent 230 272 double-initialisation.}} 231 273 ··· 263 305 {- {b No body scripts.} All JavaScript is delivered via [Js_url] (support 264 306 files) or small [Js_inline] bootstraps in [resources]. Nothing is 265 307 embedded in the HTML body via [Raw_markup].} 266 - {- {b No [DOMContentLoaded] dependency.} Use [document.readyState] check + 267 - [MutationObserver] instead.} 308 + {- {b No [DOMContentLoaded] dependency.} Use [document.readyState] check 309 + for initial load, plus [odoc-spa-loaded] listener for navigations.} 268 310 {- {b Double-init guard.} Every element you initialise is marked (e.g., 269 311 with a [data-*] attribute) and skipped on subsequent [initAll] calls.} 270 312 {- {b SPA navigation tested.} Both direct-load and sidebar-navigation 271 313 paths work.} 272 - {- {b [MutationObserver] set up after [document.body] exists.} If your 273 - script is in [<head>], [document.body] is [null] on initial parse.}} 314 + {- {b Listens for [odoc-spa-loaded].} The docsite shell dispatches this 315 + event after content swap — this is your extension's cue to scan for 316 + new elements.}}
+3
src/extension_api/odoc_extension_api.ml
··· 1 1 (** Odoc Extension API 2 2 3 + {b Note:} This API is early in development and the interface is still 4 + changing frequently. Expect breaking changes between releases. 5 + 3 6 This module provides the interface for odoc tag extensions. 4 7 Extensions are dynamically loaded plugins that handle custom tags 5 8 like [@note], [@rfc], [@example], etc.
+14 -15
test/generators/html/Markup.html
··· 29 29 //]]> 30 30 31 31 </script> 32 - <script> 33 - 34 - //<![CDATA[ 35 - (function(){if(window.__xOcamlLoaded)return;window.__xOcamlLoaded=true;var s=document.createElement('script');s.src='./_x-ocaml/x-ocaml.js';s.setAttribute('src-worker','./_x-ocaml/worker.js');s.setAttribute('backend','builtin');document.head.appendChild(s)})(); 36 - //]]> 37 - 38 - </script> 39 32 </head> 40 33 <body class="odoc"> 41 34 <nav class="odoc-nav"><a href="index.html">Up</a> – ··· 174 167 <h2 id="preformatted-text"> 175 168 <a href="#preformatted-text" class="anchor"></a>Preformatted text 176 169 </h2><p>This is a code block:</p> 177 - <x-ocaml mode="interactive"> let foo = () 178 - (** There are some nested comments in here, but an unpaired comment 179 - terminator would terminate the whole doc surrounding comment. It's 180 - best to keep code blocks no wider than 72 characters. *) 181 - 182 - let bar = 183 - ignore foo</x-ocaml> 184 - <p>There are also verbatim blocks:</p> 170 + <div> 171 + <pre class="language-ocaml"> 172 + <code> 173 + let foo = () 174 + (** There are some nested comments in here, but an unpaired comment 175 + terminator would terminate the whole doc surrounding comment. 176 + It's 177 + best to keep code blocks no wider than 72 characters. *) 178 + 179 + let bar = 180 + ignore foo 181 + </code> 182 + </pre> 183 + </div><p>There are also verbatim blocks:</p> 185 184 <pre>The main difference is these don't get syntax highlighting.</pre> 186 185 <h2 id="lists"><a href="#lists" class="anchor"></a>Lists</h2> 187 186 <ul><li>This is a</li><li>shorthand bulleted list,</li>
+9 -1
test/generators/latex/Markup.tex
··· 44 44 This is a reference to \hyperref[Markup--val-foo]{\ocamlinlinecode{\ocamlinlinecode{foo}}[p\pageref*{Markup--val-foo}]}. References can have replacement text: \hyperref[Markup--val-foo]{\ocamlinlinecode{the value foo}[p\pageref*{Markup--val-foo}]}. Except for the special lookup support, references are pretty much just like links. The replacement text can have nested styles: \hyperref[Markup--val-foo]{\ocamlinlinecode{\bold{bold}}[p\pageref*{Markup--val-foo}]}, \hyperref[Markup--val-foo]{\ocamlinlinecode{\emph{italic}}[p\pageref*{Markup--val-foo}]}, \hyperref[Markup--val-foo]{\ocamlinlinecode{\emph{emphasis}}[p\pageref*{Markup--val-foo}]}, \hyperref[Markup--val-foo]{\ocamlinlinecode{super\textsuperscript{script}}[p\pageref*{Markup--val-foo}]}, \hyperref[Markup--val-foo]{\ocamlinlinecode{sub\textsubscript{script}}[p\pageref*{Markup--val-foo}]}, and \hyperref[Markup--val-foo]{\ocamlinlinecode{\ocamlinlinecode{code}}[p\pageref*{Markup--val-foo}]}. It's also possible to surround a reference in a style: \bold{\hyperref[Markup--val-foo]{\ocamlinlinecode{\ocamlinlinecode{foo}}[p\pageref*{Markup--val-foo}]}}. References can't be nested inside references, and links and references can't be nested inside each other. 45 45 46 46 \subsection{Preformatted text\label{Markup--preformatted-text}}% 47 - This is a code block: 47 + This is a code block:\medbreak 48 + \begin{ocamlcodeblock} 49 + let foo = () 50 + (** There are some nested comments in here, but an unpaired comment 51 + terminator would terminate the whole doc surrounding comment. It's 52 + best to keep code blocks no wider than 72 characters. *) 48 53 54 + let bar = 55 + ignore foo 56 + \end{ocamlcodeblock}\medbreak 49 57 There are also verbatim blocks: 50 58 51 59 \begin{verbatim}The main difference is these don't get syntax highlighting.\end{verbatim}%
+10
test/generators/man/Markup.3o
··· 148 148 .fi 149 149 This is a code block: 150 150 .sp 151 + .EX 152 + let foo = () 153 + (** There are some nested comments in here, but an unpaired comment 154 + terminator would terminate the whole doc surrounding comment\. It's 155 + best to keep code blocks no wider than 72 characters\. *) 156 + 157 + let bar = 158 + ignore foo 159 + .EE 160 + .sp 151 161 There are also verbatim blocks: 152 162 .sp 153 163 .EX
+4 -2
test/generators/markdown/Markup.md
··· 66 66 67 67 This is a code block: 68 68 69 - <x-ocaml mode="interactive"> let foo = () 69 + ```ocaml 70 + let foo = () 70 71 (** There are some nested comments in here, but an unpaired comment 71 72 terminator would terminate the whole doc surrounding comment. It's 72 73 best to keep code blocks no wider than 72 characters. *) 73 74 74 75 let bar = 75 - ignore foo</x-ocaml> 76 + ignore foo 77 + ``` 76 78 There are also verbatim blocks: 77 79 78 80 ```
+7 -6
test/integration/code_block_handlers.t/run.t
··· 13 13 $ odoc html-generate -o html page-test_code_blocks.odocl 14 14 odoc: internal error, uncaught exception: 15 15 Sys_error("html/test/test_code_blocks.html: Permission denied") 16 - Raised by primitive operation at Stdlib.open_out_gen in file "stdlib.ml", line 331, characters 29-55 17 - Called from Stdlib.open_out in file "stdlib.ml" (inlined), line 336, characters 2-74 18 - Called from Odoc_utils.Io_utils.with_open_out in file "odoc/src/utils/odoc_utils.ml" (inlined), line 55, characters 19-35 19 - Called from Odoc_utils.Io_utils.with_formatter_out in file "odoc/src/utils/odoc_utils.ml", line 62, characters 4-74 16 + Raised by primitive operation at Stdlib.open_out_gen in file "stdlib.ml" (inlined), line 346, characters 29-55 17 + Called from Stdlib.open_out in file "stdlib.ml" (inlined), line 351, characters 2-74 18 + Called from Odoc_utils.Io_utils.with_open_out in file "odoc/src/utils/odoc_utils.ml", line 55, characters 19-35 20 19 Called from Odoc_document__Renderer.traverse.aux in file "odoc/src/document/renderer.ml", line 18, characters 4-44 21 - Called from Stdlib__List.iter in file "list.ml", line 114, characters 12-15 20 + Called from Stdlib__List.iter in file "list.ml" (inlined), line 117, characters 12-15 21 + Called from Odoc_document__Renderer.traverse in file "odoc/src/document/renderer.ml", line 21, characters 2-17 22 22 Called from Odoc_odoc__Rendering.generate_odoc.(fun) in file "odoc/src/odoc/rendering.ml", line 82, characters 2-68 23 - Called from Stdlib__List.fold_left in file "list.ml", line 125, characters 24-34 23 + Called from Stdlib__List.fold_left in file "list.ml" (inlined), line 128, characters 24-34 24 + Called from Dune__exe__Main.Make_renderer.Generate.generate in file "odoc/src/odoc/bin/main.ml", lines 919-921, characters 6-131 24 25 Called from Cmdliner_term.app.(fun) in file "cmdliner_term.ml", line 24, characters 19-24 25 26 Called from Cmdliner_term.app.(fun) in file "cmdliner_term.ml", line 22, characters 12-19 26 27 Called from Cmdliner_eval.run_parser in file "cmdliner_eval.ml", line 35, characters 37-44
+4
test/integration/html_support_files.t/run.t
··· 1 1 $ odoc support-files -o with-theme 2 2 $ find with-theme | grep -v extensions | sort 3 3 with-theme 4 + with-theme/_x-ocaml 5 + with-theme/_x-ocaml/x-ocaml.js 4 6 with-theme/fonts 5 7 with-theme/fonts/KaTeX_AMS-Regular.woff2 6 8 with-theme/fonts/KaTeX_Caligraphic-Bold.woff2 ··· 42 44 $ odoc support-files --without-theme -o without-theme 43 45 $ find without-theme | grep -v extensions | sort 44 46 without-theme 47 + without-theme/_x-ocaml 48 + without-theme/_x-ocaml/x-ocaml.js 45 49 without-theme/fonts 46 50 without-theme/fonts/KaTeX_AMS-Regular.woff2 47 51 without-theme/fonts/KaTeX_Caligraphic-Bold.woff2
+20 -12
test/integration/markdown-with-belt.t/run.t
··· 28 28 29 29 For higher order functions, it will be suffixed **U** if it takes uncurried callback. 30 30 31 - <x-ocaml mode="interactive"> val forEach : 'a t -&gt; ('a -&gt; unit) -&gt; unit 32 - val forEachU : 'a t -&gt; ('a -&gt; unit [\@u]) -&gt; unit</x-ocaml> 31 + ```ocaml 32 + val forEach : 'a t -> ('a -> unit) -> unit 33 + val forEachU : 'a t -> ('a -> unit [\@u]) -> unit 34 + ``` 33 35 In general, uncurried version will be faster, but it may be less familiar to people who have a background in functional programming. 34 36 35 37 **A special encoding for collection safety** ··· 38 40 39 41 The original OCaml stdlib solved the problem using *functor* which creates a big closure at runtime and makes dead code elimination much harder. We use a phantom type to solve the problem: 40 42 41 - <x-ocaml mode="interactive"> module Comparable1 = Belt.Id.MakeComparable (struct 43 + ```ocaml 44 + module Comparable1 = Belt.Id.MakeComparable (struct 42 45 type t = int * int 43 46 let cmp (a0, a1) (b0, b1) = 44 47 match Pervasives.compare a0 b0 with 45 - | 0 -&gt; Pervasives.compare a1 b1 46 - | c -&gt; c 48 + | 0 -> Pervasives.compare a1 b1 49 + | c -> c 47 50 end) 48 51 49 52 let mySet1 = Belt.Set.make ~id:(module Comparable1) ··· 52 55 type t = int * int 53 56 let cmp (a0, a1) (b0, b1) = 54 57 match Pervasives.compare a0 b0 with 55 - | 0 -&gt; Pervasives.compare a1 b1 56 - | c -&gt; c 58 + | 0 -> Pervasives.compare a1 b1 59 + | c -> c 57 60 end) 58 61 59 - let mySet2 = Belt.Set.make ~id:(module Comparable2)</x-ocaml> 62 + let mySet2 = Belt.Set.make ~id:(module Comparable2) 63 + ``` 60 64 Here, the compiler would infer `mySet1` and `mySet2` having different type, so e.g. a \`merge\` operation that tries to merge these two sets will correctly fail. 61 65 62 - <x-ocaml mode="interactive"> val mySet1 : (int * int, Comparable1.identity) t 63 - val mySet2 : (int * int, Comparable2.identity) t</x-ocaml> 66 + ```ocaml 67 + val mySet1 : (int * int, Comparable1.identity) t 68 + val mySet2 : (int * int, Comparable2.identity) t 69 + ``` 64 70 `Comparable1.identity` and `Comparable2.identity` are not the same using our encoding scheme. 65 71 66 72 **Collection Hierarchy** 67 73 68 74 In general, we provide a generic collection module, but also create specialized modules for commonly used data type. Take *Belt.Set* for example, we provide: 69 75 70 - <x-ocaml mode="interactive"> Belt.Set 76 + ```ocaml 77 + Belt.Set 71 78 Belt.Set.Int 72 - Belt.Set.String</x-ocaml> 79 + Belt.Set.String 80 + ``` 73 81 The specialized modules *Belt.Set.Int*, *Belt.Set.String* are in general more efficient. 74 82 75 83 Currently, both *Belt\_Set* and *Belt.Set* are accessible to users for some technical reasons, we **strongly recommend** users stick to qualified import, *Belt.Set*, we may hide the internal, *i.e*, *Belt\_Set* in the future
+3 -1
test/integration/markdown.t/run.t
··· 153 153 154 154 Inline `code`. 155 155 156 - <x-ocaml mode="interactive">let _ = &quot;Block code&quot;</x-ocaml> 156 + ```ocaml 157 + let _ = "Block code" 158 + ``` 157 159 ```text 158 160 Code block with {[inner code block syntax]} 159 161 ```
+10 -15
test/integration/oxcaml_modes.t/run.t
··· 10 10 Check arrow argument modes (@ local, @ unique): 11 11 12 12 $ grep 'keyword.*@.*local' html/test/Test_modes/index.html | head -1 | sed 's/ *$//' 13 - <span>string <span class="keyword">@</span> local 13 + <span class="keyword">@</span> <span class="mode">local</span> 14 14 15 15 $ grep 'keyword.*@.*unique' html/test/Test_modes/index.html | head -1 | sed 's/ *$//' 16 - <span>string <span class="keyword">@</span> unique 17 16 18 17 Multiple argument modes on one arrow: 19 18 20 19 $ grep 'keyword.*@.*local unique' html/test/Test_modes/index.html | head -1 | sed 's/ *$//' 21 - <span>string <span class="keyword">@</span> local unique 22 20 23 21 Arrow return modes (@ after arrow): 24 22 25 23 $ grep 'keyword.*@.*local' html/test/Test_modes/index.html | grep -v 'string' | sed 's/ *$//' 26 - <span class="keyword">@</span> local 27 - </span> int <span class="keyword">@</span> local 28 - <span class="keyword">@</span> local 29 - <span class="keyword">@</span> local 30 - </span> <span class="keyword">@</span> local 31 - </span> <span class="keyword">@</span> local 24 + <span class="keyword">@</span> <span class="mode">local</span> 25 + <span class="keyword">@</span> <span class="mode">local</span> 26 + <span class="keyword">@</span> <span class="mode">local</span> 32 27 33 28 Value modalities with @@ syntax: 34 29 35 30 $ grep 'keyword.*@@' html/test/Test_modes/index.html | sed 's/ *$//' 36 - <span class="keyword">@@</span> portable 37 - <span class="keyword">@@</span> global 31 + <span class="keyword">@@</span> <span class="mode">portable</span> 32 + <span class="keyword">@@</span> <span class="mode">global</span> 38 33 39 34 Normal function has no @@ or @ mode annotations: 40 35 ··· 46 41 Type parameter jkinds: 47 42 48 43 $ grep 'float64' html/test/Test_modes/index.html 49 - <span>('a : float64) float_box</span> 44 + <span>('a : <span class="mode">float64</span>) float_box</span> 50 45 $ grep 'immediate' html/test/Test_modes/index.html 51 - <span>('a : immediate) imm_box</span> 46 + <span>('a : <span class="mode">immediate</span>) imm_box</span> 52 47 53 48 Polymorphic with jkind at quantifier (value_or_null at binding site only): 54 49 55 50 $ grep 'value_or_null' html/test/Test_modes/index.html | sed 's/ *$//' 56 - <span>('a : value_or_null) box</span> 57 - ('a : value_or_null). 51 + <span>('a : <span class="mode">value_or_null</span>) box</span> 52 + ('a : <span class="mode">value_or_null</span>).
+7 -3
test/pages/resolution.t/run.t
··· 97 97 98 98 $ odoc support-files -o html 99 99 $ find html -type f | sort 100 + html/_x-ocaml/x-ocaml.js 100 101 html/extensions/admonition.css 101 102 html/extensions/docsite.css 102 103 html/extensions/docsite.js 104 + html/extensions/dot-init.js 103 105 html/extensions/dot.css 106 + html/extensions/jon-shell.css 107 + html/extensions/jon-shell.js 108 + html/extensions/mermaid-init.js 104 109 html/extensions/mermaid.css 110 + html/extensions/msc-init.js 105 111 html/extensions/msc.css 106 112 html/extensions/rfc.css 107 - html/extensions/scrollycode-dark.css 108 - html/extensions/scrollycode-notebook.css 109 - html/extensions/scrollycode-warm.css 110 113 html/extensions/scrollycode.css 114 + html/extensions/scrollycode.js 111 115 html/fonts/KaTeX_AMS-Regular.woff2 112 116 html/fonts/KaTeX_Caligraphic-Bold.woff2 113 117 html/fonts/KaTeX_Caligraphic-Regular.woff2
+4 -4
test/search/html_search.t/run.t
··· 83 83 {"id":[{"kind":"Root","name":"Main"},{"kind":"Type","name":"tdzdz"},{"kind":"Constructor","name":"B"}],"doc":"Bliiiiiiiiiii","kind":{"kind":"Constructor","args":{"kind":"Tuple","vals":["int list","int"]},"res":"tdzdz"},"display":{"url":"page/Main/index.html#type-tdzdz.B","html":"<code class=\"entry-kind\">cons</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.tdzdz.</span><span class=\"entry-name\">B</span><code class=\"entry-rhs\"> : int list * int -&gt; tdzdz</code></code><div class=\"entry-comment\"><div><p>Bliiiiiiiiiii</p></div></div>"}} 84 84 {"id":[{"kind":"Root","name":"J"}],"doc":"a paragraph two","kind":{"kind":"Doc"},"display":{"url":"page/J/index.html","html":"<code class=\"entry-kind\">doc</code><code class=\"entry-title\"><span class=\"entry-name\">J</span></code><div class=\"entry-comment\"><div><p>a paragraph two</p></div></div>"}} 85 85 {"id":[{"kind":"Root","name":"Main"}],"doc":"a paragraph two","kind":{"kind":"Doc"},"display":{"url":"page/Main/index.html","html":"<code class=\"entry-kind\">doc</code><code class=\"entry-title\"><span class=\"entry-name\">Main</span></code><div class=\"entry-comment\"><div><p>a paragraph two</p></div></div>"}} 86 - {"id":[{"kind":"Root","name":"Main"}],"doc":"a paragraph\nand another\nverbatim\nx + 1\nblibli","kind":{"kind":"Doc"},"display":{"url":"page/Main/index.html","html":"<code class=\"entry-kind\">doc</code><code class=\"entry-title\"><span class=\"entry-name\">Main</span></code><div class=\"entry-comment\"><div><p>a paragraph</p><p>and another</p><pre>verbatim</pre><p><code class=\"odoc-katex-math\">x + 1</code></p><x-ocaml mode=\"interactive\">blibli</x-ocaml></div></div>"}} 86 + {"id":[{"kind":"Root","name":"Main"}],"doc":"a paragraph\nand another\nverbatim\nx + 1\nblibli","kind":{"kind":"Doc"},"display":{"url":"page/Main/index.html","html":"<code class=\"entry-kind\">doc</code><code class=\"entry-title\"><span class=\"entry-name\">Main</span></code><div class=\"entry-comment\"><div><p>a paragraph</p><p>and another</p><pre>verbatim</pre><p><code class=\"odoc-katex-math\">x + 1</code></p><div><pre class=\"language-ocaml\"><code>blibli</code></pre></div></div></div>"}} 87 87 {"id":[{"kind":"Root","name":"Main"}],"doc":"this is a title\nand this is a paragraph","kind":{"kind":"Doc"},"display":{"url":"page/Main/index.html","html":"<code class=\"entry-kind\">doc</code><code class=\"entry-title\"><span class=\"entry-name\">Main</span></code><div class=\"entry-comment\"><div><p>this is a title</p><p>and this is a paragraph</p></div></div>"}} 88 - {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"I"}],"doc":"a paragraph\nand another\nverbatim\nx + 1\nblibli","kind":{"kind":"Doc"},"display":{"url":"page/Main/I/index.html","html":"<code class=\"entry-kind\">doc</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">I</span></code><div class=\"entry-comment\"><div><p>a paragraph</p><p>and another</p><pre>verbatim</pre><p><code class=\"odoc-katex-math\">x + 1</code></p><x-ocaml mode=\"interactive\">blibli</x-ocaml></div></div>"}} 88 + {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"I"}],"doc":"a paragraph\nand another\nverbatim\nx + 1\nblibli","kind":{"kind":"Doc"},"display":{"url":"page/Main/I/index.html","html":"<code class=\"entry-kind\">doc</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">I</span></code><div class=\"entry-comment\"><div><p>a paragraph</p><p>and another</p><pre>verbatim</pre><p><code class=\"odoc-katex-math\">x + 1</code></p><div><pre class=\"language-ocaml\"><code>blibli</code></pre></div></div></div>"}} 89 89 {"id":[{"kind":"Root","name":"J"}],"doc":"a paragraph one","kind":{"kind":"Module"},"display":{"url":"page/J/index.html","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"entry-name\">J</span></code><div class=\"entry-comment\"><div><p>a paragraph one</p></div></div>"}} 90 90 {"id":[{"kind":"Root","name":"Main"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"entry-name\">Main</span></code><div class=\"entry-comment\"><div></div></div>"}} 91 91 {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"I"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html#module-I","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">I</span></code><div class=\"entry-comment\"><div></div></div>"}} 92 92 {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"M"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html#module-M","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">M</span></code><div class=\"entry-comment\"><div></div></div>"}} 93 93 {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"X"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html#module-X","html":"<code class=\"entry-kind\">mod</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">X</span></code><div class=\"entry-comment\"><div></div></div>"}} 94 - {"id":[{"kind":"Page","name":"page"}],"doc":"A title\nA paragraph\nsome verbatim\nand code\na list of things bliblib","kind":{"kind":"Page"},"display":{"url":"page/index.html","html":"<code class=\"entry-kind\">page</code><code class=\"entry-title\"><span class=\"entry-name\">page</span></code><div class=\"entry-comment\"><div><p>A title</p><p>A paragraph</p><pre>some verbatim</pre><x-ocaml mode=\"interactive\">and code</x-ocaml><ul><li>a list <em>of</em> things</li><li>bliblib</li></ul></div></div>"}} 94 + {"id":[{"kind":"Page","name":"page"}],"doc":"A title\nA paragraph\nsome verbatim\nand code\na list of things bliblib","kind":{"kind":"Page"},"display":{"url":"page/index.html","html":"<code class=\"entry-kind\">page</code><code class=\"entry-title\"><span class=\"entry-name\">page</span></code><div class=\"entry-comment\"><div><p>A title</p><p>A paragraph</p><pre>some verbatim</pre><div><pre class=\"language-ocaml\"><code>and code</code></pre></div><ul><li>a list <em>of</em> things</li><li>bliblib</li></ul></div></div>"}} 95 95 {"id":[{"kind":"Root","name":"Main"},{"kind":"Type","name":"t"}],"doc":"A comment","kind":{"kind":"TypeDecl","private":false,"manifest":"int","constraints":[]},"display":{"url":"page/Main/index.html#type-t","html":"<code class=\"entry-kind\">type</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">t</span><code class=\"entry-rhs\"> = int</code></code><div class=\"entry-comment\"><div><p>A comment</p></div></div>"}} 96 96 {"id":[{"kind":"Root","name":"Main"},{"kind":"Type","name":"tdzdz"}],"doc":"A comment aaaaaaaaaa","kind":{"kind":"TypeDecl","private":false,"manifest":null,"constraints":[]},"display":{"url":"page/Main/index.html#type-tdzdz","html":"<code class=\"entry-kind\">type</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">tdzdz</span><code class=\"entry-rhs\"> = A of int * int | B of int list * int</code></code><div class=\"entry-comment\"><div><p>A comment aaaaaaaaaa</p></div></div>"}} 97 97 {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"M"},{"kind":"Type","name":"t"}],"doc":"dsdsd","kind":{"kind":"TypeDecl","private":false,"manifest":null,"constraints":[]},"display":{"url":"page/Main/M/index.html#type-t","html":"<code class=\"entry-kind\">type</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.M.</span><span class=\"entry-name\">t</span></code><div class=\"entry-comment\"><div><p>dsdsd</p></div></div>"}} ··· 101 101 {"id":[{"kind":"Root","name":"Main"},{"kind":"Value","name":"lorem4"}],"doc":"lorem 4","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/index.html#val-lorem4","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">lorem4</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div><p>lorem 4</p></div></div>"}} 102 102 {"id":[{"kind":"Root","name":"Main"},{"kind":"Value","name":"lorem"}],"doc":"lorem 1 and a link","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/index.html#val-lorem","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">lorem</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div><p>lorem 1 and a <span>link</span></p></div></div>"}} 103 103 {"id":[{"kind":"Root","name":"Main"},{"kind":"Value","name":"uu"}],"doc":"","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/index.html#val-uu","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">uu</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div></div></div>"}} 104 - {"id":[{"kind":"Root","name":"Main"},{"kind":"Value","name":"v"}],"doc":"a reference , and some formatted content with code and\n code blocks","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/index.html#val-v","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">v</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div><p>a reference <span><code>t</code></span>, and some <em>formatted</em> <b>content</b> with <code>code</code> and</p><x-ocaml mode=\"interactive\"> code blocks</x-ocaml></div></div>"}} 104 + {"id":[{"kind":"Root","name":"Main"},{"kind":"Value","name":"v"}],"doc":"a reference , and some formatted content with code and\n code blocks","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/index.html#val-v","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">v</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div><p>a reference <span><code>t</code></span>, and some <em>formatted</em> <b>content</b> with <code>code</code> and</p><div><pre class=\"language-ocaml\"><code> code blocks</code></pre></div></div></div>"}} 105 105 {"id":[{"kind":"Root","name":"Main"},{"kind":"Value","name":"x"}],"doc":"","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/index.html#val-x","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">x</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div></div></div>"}} 106 106 {"id":[{"kind":"Root","name":"Main"},{"kind":"Value","name":"y"}],"doc":"","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/index.html#val-y","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.</span><span class=\"entry-name\">y</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div></div></div>"}} 107 107 {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"I"},{"kind":"Value","name":"x"}],"doc":"","kind":{"kind":"Value","type":"int"},"display":{"url":"page/Main/I/index.html#val-x","html":"<code class=\"entry-kind\">val</code><code class=\"entry-title\"><span class=\"prefix-name\">Main.I.</span><span class=\"entry-name\">x</span><code class=\"entry-rhs\"> : int</code></code><div class=\"entry-comment\"><div></div></div>"}}
+5 -16
test/xref2/shadow3.t/run.t
··· 17 17 (sig : 18 18 module type {B}1/shadowed/(CCCC) = A.B 19 19 include {B}1/shadowed/(CCCC) 20 - (sig : module {A}1/shadowed/(AAAA) = A.A end) 21 - include sig 22 - module A : 23 - sig 24 - include module type of struct include {A}1/shadowed/(AAAA) end 25 - (sig : type t end) 26 - type a 27 - endend (sig : module {A}2/shadowed/(CCCC) = A.A end) 20 + (sig : module {A}1/shadowed/(AAAA) = A.{A}1/shadowed/(AAAA) end) 21 + include sigend (sig : module {A}2/shadowed/(CCCC) = A.A end) 28 22 end) 29 23 include module type of struct include B end 30 24 (sig : 31 25 module type B = B.B 32 - include B (sig : module {A}1/shadowed/(BBBB) = B.A end) 33 - include sig 34 - module A : 35 - sig 36 - include module type of struct include {A}1/shadowed/(BBBB) end 37 - (sig : type t end) 38 - type b 39 - endend (sig : module {A}3/shadowed/(CCCC) = B.A end) 26 + include B 27 + (sig : module {A}1/shadowed/(BBBB) = B.{A}1/shadowed/(BBBB) end) 28 + include sigend (sig : module {A}3/shadowed/(CCCC) = B.A end) 40 29 end) 41 30 module A : 42 31 sig
+10 -6
test/xref2/stripped_include_decl_reconstruct.t/run.t
··· 9 9 10 10 $ cat a.mli 11 11 (** Module A defines a signature with an inline include. *) 12 - 12 + 13 13 module type S = sig 14 14 type t 15 - 15 + 16 16 include sig 17 17 val x : t 18 18 val y : t -> t 19 19 end 20 20 end 21 21 22 + 23 + 22 24 $ cat b.mli 23 25 (** Module B includes A.S with a type substitution. 24 - 26 + 25 27 The substitution flows through [fragmap] in tools.ml. When the inline 26 28 include's decl has been stripped, [map_include_decl] needs the 27 29 reconstructed decl to correctly wrap the substitution. Without 28 30 reconstruction, the empty decl produces [With(subst, empty_sig)] 29 31 which loses the vals from the include. *) 30 - 32 + 31 33 module M : A.S with type t := int 34 + 35 + 32 36 33 37 Compile and link: 34 38 ··· 47 51 48 52 $ odoc html-generate b.odocl -o html --indent 49 53 $ grep 'id="val-[xy]"' html/test/B/M/index.html 50 - <div class="spec value anchored" id="val-x"> 51 - <div class="spec value anchored" id="val-y"> 54 + <div class="spec value anchored" id="val-x"> 55 + <div class="spec value anchored" id="val-y">