Skip to content

Commit 4bc9254

Browse files
committed
Add a tooltip to references with text
The tooltip shows what would be rendered instead if no text was written. This is currently the original reference. This is most useful for references that do not resolve, because the original reference is not visible at all. The tooltip is generally easier to read than the target URL shown by the browser on hover and might benefit from smarter rendering of references in the future.
1 parent 6ff5381 commit 4bc9254

File tree

9 files changed

+103
-55
lines changed

9 files changed

+103
-55
lines changed

src/document/comment.ml

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,34 @@ module Reference = struct
5757
render_resolved (r :> t) ^ "." ^ InstanceVariableName.to_string s
5858
| `Label (_, s) -> LabelName.to_string s
5959

60+
let rec render_unresolved : Reference.t -> string =
61+
let open Reference in
62+
function
63+
| `Resolved r -> render_resolved r
64+
| `Root (n, _) -> n
65+
| `Dot (p, f) -> render_unresolved (p :> t) ^ "." ^ f
66+
| `Module (p, f) ->
67+
render_unresolved (p :> t) ^ "." ^ ModuleName.to_string f
68+
| `ModuleType (p, f) ->
69+
render_unresolved (p :> t) ^ "." ^ ModuleTypeName.to_string f
70+
| `Type (p, f) -> render_unresolved (p :> t) ^ "." ^ TypeName.to_string f
71+
| `Constructor (p, f) ->
72+
render_unresolved (p :> t) ^ "." ^ ConstructorName.to_string f
73+
| `Field (p, f) -> render_unresolved (p :> t) ^ "." ^ FieldName.to_string f
74+
| `Extension (p, f) ->
75+
render_unresolved (p :> t) ^ "." ^ ExtensionName.to_string f
76+
| `Exception (p, f) ->
77+
render_unresolved (p :> t) ^ "." ^ ExceptionName.to_string f
78+
| `Value (p, f) -> render_unresolved (p :> t) ^ "." ^ ValueName.to_string f
79+
| `Class (p, f) -> render_unresolved (p :> t) ^ "." ^ ClassName.to_string f
80+
| `ClassType (p, f) ->
81+
render_unresolved (p :> t) ^ "." ^ ClassTypeName.to_string f
82+
| `Method (p, f) ->
83+
render_unresolved (p :> t) ^ "." ^ MethodName.to_string f
84+
| `InstanceVariable (p, f) ->
85+
render_unresolved (p :> t) ^ "." ^ InstanceVariableName.to_string f
86+
| `Label (p, f) -> render_unresolved (p :> t) ^ "." ^ LabelName.to_string f
87+
6088
(* This is the entry point. stop_before is false on entry, true on recursive
6189
call. *)
6290
let rec to_ir : ?text:Inline.t -> stop_before:bool -> Reference.t -> Inline.t
@@ -70,7 +98,9 @@ module Reference = struct
7098
let s = source_of_code s in
7199
[ inline @@ Inline.Source s ]
72100
| Some content ->
73-
let link = { InternalLink.target = Unresolved; content } in
101+
let link =
102+
{ InternalLink.target = Unresolved; content; tooltip = Some s }
103+
in
74104
[ inline @@ Inline.InternalLink link ])
75105
| `Dot (parent, s) -> unresolved ?text (parent :> t) s
76106
| `Module (parent, s) ->
@@ -101,16 +131,20 @@ module Reference = struct
101131
| `Resolved r -> (
102132
(* IDENTIFIER MUST BE RENAMED TO DEFINITION. *)
103133
let id = Reference.Resolved.identifier r in
134+
let rendered = render_resolved r in
104135
let content =
105136
match text with
106-
| None ->
107-
[ inline @@ Inline.Source (source_of_code (render_resolved r)) ]
137+
| None -> [ inline @@ Inline.Source (source_of_code rendered) ]
108138
| Some s -> s
139+
and tooltip =
140+
(* Add a tooltip if the content is not the rendered reference. *)
141+
match text with None -> None | Some _ -> Some rendered
109142
in
110143
match Url.from_identifier ~stop_before id with
111144
| Ok url ->
112145
let target = InternalLink.Resolved url in
113-
[ inline @@ Inline.InternalLink { InternalLink.target; content } ]
146+
let link = { InternalLink.target; content; tooltip } in
147+
[ inline @@ Inline.InternalLink link ]
114148
| Error (Not_linkable _) -> content
115149
| Error exn ->
116150
(* FIXME: better error message *)
@@ -121,7 +155,8 @@ module Reference = struct
121155
fun ?text parent field ->
122156
match text with
123157
| Some content ->
124-
let link = { InternalLink.target = Unresolved; content } in
158+
let tooltip = Some (render_unresolved parent ^ "." ^ field) in
159+
let link = { InternalLink.target = Unresolved; content; tooltip } in
125160
[ inline @@ InternalLink link ]
126161
| None ->
127162
let tail = [ inline @@ Text ("." ^ field) ] in

src/document/generator.ml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ let type_var tv = tag "type-var" (O.txt tv)
3333
let enclose ~l ~r x = O.span (O.txt l ++ x ++ O.txt r)
3434

3535
let resolved p content =
36-
let link = { InternalLink.target = Resolved p; content } in
36+
let link = { InternalLink.target = Resolved p; content; tooltip = None } in
3737
O.elt [ inline @@ InternalLink link ]
3838

3939
let path p content = resolved (Url.from_path p) content
4040

4141
let unresolved content =
42-
let link = { InternalLink.target = Unresolved; content } in
42+
let link = { InternalLink.target = Unresolved; content; tooltip = None } in
4343
O.elt [ inline @@ InternalLink link ]
4444

4545
let path_to_id path =
@@ -1814,8 +1814,9 @@ module Make (Syntax : SYNTAX) = struct
18141814
in
18151815
let li ?(attr = []) name url =
18161816
let link url desc =
1817-
let content = [ Inline.{ attr = []; desc } ] in
1818-
Inline.InternalLink { InternalLink.target = Resolved url; content }
1817+
let content = [ Inline.{ attr = []; desc } ] and tooltip = None in
1818+
Inline.InternalLink
1819+
{ InternalLink.target = Resolved url; content; tooltip }
18191820
in
18201821
[ block ~attr @@ Block.Inline (inline @@ link url (Text name)) ]
18211822
in

src/document/types.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ end =
88
and InternalLink : sig
99
type target = Resolved of Url.t | Unresolved
1010

11-
type t = { target : target; content : Inline.t }
11+
type t = { target : target; content : Inline.t; tooltip : string option }
1212
end =
1313
InternalLink
1414

src/html/generator.ml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,21 +92,22 @@ and styled style ~emph_level =
9292
| `Superscript -> (emph_level, Html.sup ~a:[])
9393
| `Subscript -> (emph_level, Html.sub ~a:[])
9494

95-
let rec internallink ~config ~emph_level ~resolve ?(a = []) (t : InternalLink.t)
96-
=
95+
let rec internallink ~config ~emph_level ~resolve ?(a = [])
96+
{ InternalLink.target; content; tooltip } =
97+
let a = match tooltip with Some s -> Html.a_title s :: a | None -> a in
9798
let elt =
98-
match t.target with
99+
match target with
99100
| Resolved uri ->
100101
let href = Link.href ~config ~resolve uri in
101102
let a = (a :> Html_types.a_attrib Html.attrib list) in
102-
Html.a ~a:(Html.a_href href :: a) (inline_nolink ~emph_level t.content)
103+
Html.a ~a:(Html.a_href href :: a) (inline_nolink ~emph_level content)
103104
| Unresolved ->
104105
(* let title =
105106
* Html.a_title (Printf.sprintf "unresolved reference to %S"
106107
* (ref_to_string ref)
107108
* in *)
108109
let a = Html.a_class [ "xref-unresolved" ] :: a in
109-
Html.span ~a (inline ~config ~emph_level ~resolve t.content)
110+
Html.span ~a (inline ~config ~emph_level ~resolve content)
110111
in
111112
[ (elt :> phrasing Html.elt) ]
112113

test/generators/html/Labels.html

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -178,20 +178,20 @@ <h2 id="L2"><a href="#L2" class="anchor"></a>Attached to nothing</h2>
178178
</ol><code><span>}</span></code>
179179
</div>
180180
</div><p>Testing that labels can be referenced</p>
181-
<ul><li><a href="#L1">Attached to unit</a></li>
182-
<li><a href="#L2">Attached to nothing</a></li>
183-
<li><a href="#L3">Attached to module</a></li>
184-
<li><a href="#L4">Attached to type</a></li>
185-
<li><a href="#L5">Attached to value</a></li>
186-
<li><a href="#L6">Attached to module type</a></li>
187-
<li><a href="#L7">Attached to class</a></li>
188-
<li><a href="#L8">Attached to class type</a></li>
189-
<li><a href="#L9">Attached to exception</a></li>
190-
<li><a href="#L10">Attached to extension</a></li>
191-
<li><a href="#L11">Attached to module subst</a></li>
192-
<li><a href="#L12">Attached to type subst</a></li>
193-
<li><a href="#L13">Attached to constructor</a></li>
194-
<li><a href="#L14">Attached to field</a></li>
181+
<ul><li><a href="#L1" title="L1">Attached to unit</a></li>
182+
<li><a href="#L2" title="L2">Attached to nothing</a></li>
183+
<li><a href="#L3" title="L3">Attached to module</a></li>
184+
<li><a href="#L4" title="L4">Attached to type</a></li>
185+
<li><a href="#L5" title="L5">Attached to value</a></li>
186+
<li><a href="#L6" title="L6">Attached to module type</a></li>
187+
<li><a href="#L7" title="L7">Attached to class</a></li>
188+
<li><a href="#L8" title="L8">Attached to class type</a></li>
189+
<li><a href="#L9" title="L9">Attached to exception</a></li>
190+
<li><a href="#L10" title="L10">Attached to extension</a></li>
191+
<li><a href="#L11" title="L11">Attached to module subst</a></li>
192+
<li><a href="#L12" title="L12">Attached to type subst</a></li>
193+
<li><a href="#L13" title="L13">Attached to constructor</a></li>
194+
<li><a href="#L14" title="L14">Attached to field</a></li>
195195
</ul>
196196
</div>
197197
</body>

test/generators/html/Markup.html

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@ <h4 id="sub-subsection-headings">
7676
<p>but odoc has banned deeper headings. There are also title headings,
7777
but they are only allowed in mld files.
7878
</p><h4 id="anchors"><a href="#anchors" class="anchor"></a>Anchors</h4>
79-
<p>Sections can have attached <a href="#anchors">Anchors</a>, and
80-
it is possible to <a href="#anchors">link</a> to them. Links to section
81-
headers should not be set in source code style.
79+
<p>Sections can have attached
80+
<a href="#anchors" title="anchors">Anchors</a>, and it is possible
81+
to <a href="#anchors" title="anchors">link</a> to them. Links to
82+
section headers should not be set in source code style.
8283
</p>
8384
<h5 id="paragraph"><a href="#paragraph" class="anchor"></a>Paragraph</h5>
8485
<p>Individual paragraphs can have a heading.</p>
@@ -137,17 +138,19 @@ <h2 id="links-and-references">
137138
</p>
138139
<p>This is a reference to <a href="#val-foo"><code>foo</code></a>.
139140
References can have replacement text:
140-
<a href="#val-foo">the value foo</a>. Except for the special lookup
141-
support, references are pretty much just like links. The replacement
142-
text can have nested styles: <a href="#val-foo"><b>bold</b></a>,
143-
<a href="#val-foo"><i>italic</i></a>,
144-
<a href="#val-foo"><em>emphasis</em></a>,
145-
<a href="#val-foo">super<sup>script</sup></a>,
146-
<a href="#val-foo">sub<sub>script</sub></a>, and
147-
<a href="#val-foo"><code>code</code></a>. It's also possible to surround
148-
a reference in a style: <b><a href="#val-foo"><code>foo</code></a></b>
149-
. References can't be nested inside references, and links and references
150-
can't be nested inside each other.
141+
<a href="#val-foo" title="foo">the value foo</a>. Except for the
142+
special lookup support, references are pretty much just like links.
143+
The replacement text can have nested styles:
144+
<a href="#val-foo" title="foo"><b>bold</b></a>,
145+
<a href="#val-foo" title="foo"><i>italic</i></a>,
146+
<a href="#val-foo" title="foo"><em>emphasis</em></a>,
147+
<a href="#val-foo" title="foo">super<sup>script</sup></a>,
148+
<a href="#val-foo" title="foo">sub<sub>script</sub></a>, and
149+
<a href="#val-foo" title="foo"><code>code</code></a>. It's also possible
150+
to surround a reference in a style:
151+
<b><a href="#val-foo"><code>foo</code></a></b>. References can't
152+
be nested inside references, and links and references can't be nested
153+
inside each other.
151154
</p>
152155
<h2 id="preformatted-text">
153156
<a href="#preformatted-text" class="anchor"></a>Preformatted text

test/generators/html/Ocamlary.html

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,9 @@ <h4 id="emptySig"><a href="#emptySig" class="anchor"></a>EmptySig</h4>
266266
</a> or
267267
<a href="Ocamlary-module-type-SuperSig-module-type-EmptySig.html">
268268
<code>SuperSig.EmptySig</code>
269-
</a>. Section <a href="#s9000">Section 9000</a> is also interesting.
270-
<a href="#emptySig">EmptySig</a> is the section and
269+
</a>. Section <a href="#s9000" title="s9000">Section 9000</a> is
270+
also interesting. <a href="#emptySig" title="emptySig">EmptySig</a>
271+
is the section and
271272
<a href="Ocamlary-module-type-EmptySig.html"><code>EmptySig</code></a>
272273
is the module signature.
273274
</p>
@@ -2764,9 +2765,13 @@ <h2 id="section-title-splicing">
27642765
</h2><p>I can refer to</p>
27652766
<ul>
27662767
<li><code>{!section:indexmodules}</code> :
2767-
<a href="#indexmodules">Trying the {!modules: ...} command.</a>
2768+
<a href="#indexmodules" title="indexmodules">Trying the {!modules:
2769+
...} command.
2770+
</a>
2771+
</li>
2772+
<li><code>{!aliases}</code> :
2773+
<a href="#aliases" title="aliases">Aliases again</a>
27682774
</li>
2769-
<li><code>{!aliases}</code> : <a href="#aliases">Aliases again</a></li>
27702775
</ul><p>But also to things in submodules:</p>
27712776
<ul>
27722777
<li><code>{!section:SuperSig.SubSigA.subSig}</code> :
@@ -2780,15 +2785,17 @@ <h2 id="section-title-splicing">
27802785
</ul><p>And just to make sure we do not mess up:</p>
27812786
<ul>
27822787
<li><code>{{!section:indexmodules}A}</code> :
2783-
<a href="#indexmodules">A</a>
2784-
</li><li><code>{{!aliases}B}</code> : <a href="#aliases">B</a></li>
2788+
<a href="#indexmodules" title="indexmodules">A</a>
2789+
</li>
2790+
<li><code>{{!aliases}B}</code> : <a href="#aliases" title="aliases">B</a>
2791+
</li>
27852792
<li><code>{{!section:SuperSig.SubSigA.subSig}C}</code> :
2786-
<a href="Ocamlary-module-type-SuperSig-module-type-SubSigA.html#subSig">
2787-
C
2793+
<a href="Ocamlary-module-type-SuperSig-module-type-SubSigA.html#subSig"
2794+
title="subSig">C
27882795
</a>
27892796
</li>
27902797
<li><code>{{!Aliases.incl}D}</code> :
2791-
<a href="Ocamlary-Aliases.html#incl">D</a>
2798+
<a href="Ocamlary-Aliases.html#incl" title="incl">D</a>
27922799
</li>
27932800
</ul>
27942801
<h2 id="new-reference-syntax">

test/generators/html/Toplevel_comments-Comments_on_open.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ <h1>Module <code><span>Toplevel_comments.Comments_on_open</span></code>
3232
</div>
3333
</div><h3 id="sec"><a href="#sec" class="anchor"></a>Section</h3>
3434
<p>Comments attached to open are treated as floating comments. Referencing
35-
<a href="#sec">Section</a>
35+
<a href="#sec" title="sec">Section</a>
3636
<a href="Toplevel_comments-Comments_on_open-M.html#type-t">
3737
<code>M.t</code>
3838
</a> works

test/xref2/labels/labels.t/run.t

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ There are two references in N, one should point to a local label and the other t
6363
</nav>
6464
<div class="odoc-content">
6565
<h2 id="B"><a href="#B" class="anchor"></a>An other conflicting label</h2>
66-
<p><a href="#B">An other conflicting label</a>
66+
<p><a href="#B" title="B">An other conflicting label</a>
6767
<a href="../M/index.html#B"><code>B</code></a>
6868
</p>
6969
</div>
@@ -125,7 +125,8 @@ The second occurence of 'B' in the main page should be disambiguated
125125
</div><h2 id="B_2"><a href="#B_2" class="anchor"></a>Dupplicate B</h2>
126126
<p>Define <code>B</code> again in the same scope.</p>
127127
<p>References to the labels:</p>
128-
<p><a href="#A">First label</a> <a href="#B">Dupplicate B</a>
128+
<p><a href="#A" title="A">First label</a>
129+
<a href="#B" title="B">Dupplicate B</a>
129130
<a href="M/index.html#C"><code>C</code></a>
130131
<a href="M/index.html#D"><code>D</code></a>
131132
<a href="M/index.html#B"><code>B</code></a>

0 commit comments

Comments
 (0)