diff --git a/CHANGES.md b/CHANGES.md index d4dd54ed1c..10bf17bdce 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,7 +35,8 @@ - Fix missing katex headers (@panglesd, #1096) - Fix resolution of module synopses in {!modules} lists that require --open (@jonludlam, #1104} -- Fix top comment not being taken from includes often enough (#1117, @panglesd) +- Fix top comment not being taken from includes often enough (@panglesd, #1117) +- Fixed 404 links from search results (@panglesd, #1108) # 2.4.0 diff --git a/src/search/html.ml b/src/search/html.ml index de102fceda..747d45e88e 100644 --- a/src/search/html.ml +++ b/src/search/html.ml @@ -3,11 +3,22 @@ type html = Html_types.div_content Tyxml.Html.elt open Odoc_model open Lang -let url id = - match - Odoc_document.Url.from_identifier ~stop_before:false - (id :> Odoc_model.Paths.Identifier.t) - with +let url { Entry.id; kind; doc = _ } = + let open Entry in + let stop_before = + (* Some module/module types/... might not have an expansion, so we need to + be careful and set [stop_before] to [true] for those kind of search + entries, to avoid linking to an inexistant page. + + Docstring do not have an ID in the model, and use the ID from the parent + signature in search entries. Therefore, links to doc comments need + [stop_before] to be [false] to point to the page where they are present. + + Values, types, ... are not sensitive to [stop_before], allowing us to + shorten the match. *) + match kind with Doc _ -> false | _ -> true + in + match Odoc_document.Url.from_identifier ~stop_before id with | Ok url -> let config = Odoc_html.Config.v ~search_result:true ~semantic_uris:false diff --git a/src/search/html.mli b/src/search/html.mli index 80065848e5..dd66127908 100644 --- a/src/search/html.mli +++ b/src/search/html.mli @@ -4,9 +4,7 @@ type html = Html_types.div_content Tyxml.Html.elt val of_entry : Entry.t -> html list -val url : - Odoc_model.Paths.Identifier.Any.t -> - (string, Odoc_document.Url.Error.t) Result.result +val url : Entry.t -> (string, Odoc_document.Url.Error.t) Result.result (** The below is intended for search engine that do not use the Json output but Odoc as a library. Most search engine will use their own representation diff --git a/src/search/json_index/json_display.ml b/src/search/json_index/json_display.ml index c51ea9e71b..e269291cab 100644 --- a/src/search/json_index/json_display.ml +++ b/src/search/json_index/json_display.ml @@ -1,7 +1,7 @@ open Odoc_search -let of_entry { Entry.id; doc = _; kind = _ } h = - match Html.url id with +let of_entry entry h = + match Html.url entry with | Result.Ok url -> let html = h diff --git a/test/search/dune b/test/search/dune index a79b344326..058962202d 100644 --- a/test/search/dune +++ b/test/search/dune @@ -8,4 +8,4 @@ (cram (deps %{bin:odoc} %{bin:odoc_print}) (enabled_if - (>= %{ocaml_version} 4.04.0))) + (>= %{ocaml_version} 4.08.0))) diff --git a/test/search/html_search.t/run.t b/test/search/html_search.t/run.t index c0d7763175..755ec401b3 100644 --- a/test/search/html_search.t/run.t +++ b/test/search/html_search.t/run.t @@ -108,9 +108,9 @@ The index file, one entry per line: {"id":[{"kind":"Page","name":"page"},{"kind":"Label","name":"a-title"}],"doc":"A title","kind":{"kind":"Doc","subkind":"Heading"},"display":{"url":"page/index.html#a-title","html":"docpage.a-title

A title

"}} {"id":[{"kind":"Root","name":"J"}],"doc":"a paragraph one","kind":{"kind":"Module"},"display":{"url":"page/J/index.html","html":"modJ

a paragraph one

"}} {"id":[{"kind":"Root","name":"Main"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html","html":"modMain
"}} - {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"I"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/I/index.html","html":"modMain.I
"}} - {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"M"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/M/index.html","html":"modMain.M
"}} - {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"X"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/X/index.html","html":"modMain.X
"}} + {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"I"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html#module-I","html":"modMain.I
"}} + {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"M"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html#module-M","html":"modMain.M
"}} + {"id":[{"kind":"Root","name":"Main"},{"kind":"Module","name":"X"}],"doc":"","kind":{"kind":"Module"},"display":{"url":"page/Main/index.html#module-X","html":"modMain.X
"}} {"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":"typeMain.t = int

A comment

"}} {"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":"typeMain.tdzdz = A of int * int | B of int list * int

A comment aaaaaaaaaa

"}} {"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":"typeMain.M.t

dsdsd

"}} diff --git a/test/search/module_aliases.t/main.ml b/test/search/module_aliases.t/main.ml new file mode 100644 index 0000000000..ab6e06b7b9 --- /dev/null +++ b/test/search/module_aliases.t/main.ml @@ -0,0 +1,19 @@ +module X = struct + let x = 1 + + (** some comment *) +end + +module Y = X +module Z = Y + +module L = Stdlib.List + +module type X = sig + val x : int +end + +module type Y = X +module type Z = Y + +module type L = module type of Stdlib.List diff --git a/test/search/module_aliases.t/run.t b/test/search/module_aliases.t/run.t new file mode 100644 index 0000000000..404e605dad --- /dev/null +++ b/test/search/module_aliases.t/run.t @@ -0,0 +1,26 @@ +Compile the files + + $ ocamlc -c main.ml -bin-annot -I . + +Compile and link the documentation + + $ odoc compile main.cmt + $ odoc link main.odoc + $ odoc compile-index main.odocl + +Search results only redirect to their definition point (not the +expansions). Comments link to the expansion they are in. + + $ cat index.json | jq -r '.[] | "\(.id[-1].name) -> \(.display.url)"' + Main -> Main/index.html + X -> Main/index.html#module-X + x -> Main/X/index.html#val-x + X -> Main/X/index.html + Y -> Main/index.html#module-Y + Z -> Main/index.html#module-Z + L -> Main/index.html#module-L + X -> Main/index.html#module-type-X + x -> Main/module-type-X/index.html#val-x + Y -> Main/index.html#module-type-Y + Z -> Main/index.html#module-type-Z + L -> Main/index.html#module-type-L