diff --git a/CHANGES.md b/CHANGES.md index 551d12f499..7771ef3991 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,14 @@ # Unreleased +### Added - Support for OxCaml unboxed named types (@art-w, #1407) - Support for OxCaml zero alloc definitions (@Leonidas-from-XIV, #1422, #1444) - Remove requirement for ppx_expect in tests (@jonludlam, #1445) - Support for OxCaml modalities (@art-w, #1420) +### Fixed +- Allow to break link into multiline (@Tim-ats-d, #1439) + # 3.2.1 ### Fixed diff --git a/doc/cheatsheet.mld b/doc/cheatsheet.mld index 62eeeda26d..4233a85333 100644 --- a/doc/cheatsheet.mld +++ b/doc/cheatsheet.mld @@ -57,11 +57,17 @@ Quick reference for the odoc language! {@text[ Here is a link: {:https://www.example.com}. - You can also click {{:https://www.example.com}here}.]}} + You can also click {{:https://www.example.com}here}. + + Multi lines links are also supported: {:https://www.example.com/\ + a-very\ + long-path/}]}} {td Here is a link: {:https://www.example.com}. - You can also click {{:https://www.example.com}here}.}} + You can also click {{:https://www.example.com}here}. + + Multi lines links are also supported: {:https://www.example.com/a-very-long-path/}.}} {tr {th {{!odoc_for_authors.links_and_references}References} } {td diff --git a/doc/odoc_for_authors.mld b/doc/odoc_for_authors.mld index c2b558ae4a..9f10727e62 100644 --- a/doc/odoc_for_authors.mld +++ b/doc/odoc_for_authors.mld @@ -545,9 +545,17 @@ A link to a URL may be put into the text as follows: (** See {{: https://ocaml.org/ }the OCaml website} for news about OCaml *) ]} -This will render as a link to [https://ocaml.org/] with the text "the OCaml website" +This will render as a link to [https://ocaml.org/] with the text "the OCaml website". -References are links to other elements, e.g., comments might wish to refer to +Link can also be spread accross lines: +{[ +{{: https://github.com/ocaml/\ + odoc/issues/ }Issues opened on Odoc} +]} + +Use a backslash to mark line breaks. When a backslash is followed by whitespace, both are removed. + +References are links to other elements, e.g., comments might wish to refer to a module or type elsewhere as follows: {[ diff --git a/src/parser/syntax.ml b/src/parser/syntax.ml index 454aa20c9d..0998e4c648 100644 --- a/src/parser/syntax.ml +++ b/src/parser/syntax.ml @@ -167,6 +167,33 @@ type token_that_always_begins_an_inline_element = | `Begin_link_with_replacement_text of string | `Math_span of string ] +(** When a backslash is followed by space, remove both the backslash and the + space. *) +let escape_link link = + let link = String.trim link in + let buf = Buffer.create (String.length link) in + let add_backslash = function + | `Backslash -> Buffer.add_char buf '\\' + | `Escaping | `Char -> () + in + let last_state = + String.fold_left + (fun state chr -> + match (state, chr) with + | `Char, '\\' -> `Backslash + | `Char, _ -> + Buffer.add_char buf chr; + `Char + | (`Backslash | `Escaping), _ when Char.Ascii.is_white chr -> `Escaping + | ((`Backslash | `Escaping) as state), _ -> + add_backslash state; + Buffer.add_char buf chr; + `Char) + `Char link + in + add_backslash last_state; + Buffer.contents buf + (* Check that the token constructors above actually are all in [Token.t]. *) let _check_subset : token_that_always_begins_an_inline_element -> Token.t = fun t -> (t :> Token.t) @@ -269,7 +296,7 @@ let rec inline_element : | `Simple_link u -> junk input; - let u = String.trim u in + let u = escape_link u |> String.trim in if u = "" then Parse_error.should_not_be_empty @@ -281,7 +308,7 @@ let rec inline_element : | `Begin_link_with_replacement_text u as parent_markup -> junk input; - let u = String.trim u in + let u = escape_link u |> String.trim in if u = "" then Parse_error.should_not_be_empty diff --git a/test/model/semantics/expected/heading.expected b/test/model/semantics/expected/heading.expected index a5659c0810..205519bd6e 100644 --- a/test/model/semantics/expected/heading.expected +++ b/test/model/semantics/expected/heading.expected @@ -174,6 +174,13 @@ foo --- output --- {"value":[{"`Heading":[{"heading_level":"`Subsection","heading_label_explicit":"false"},{"`Label":[{"`Page":["None","f.ml"]},""]},[{"`Link":["foo",[]]}]]}],"warnings":[]} --- input --- +{{:https://github.com/ocaml/\ + odoc/\ +issues/\ + 865\ }this issue} +--- output --- +{"value":[{"`Paragraph":[{"`Link":["https://github.com/ocaml/odoc/issues/865\\",[{"`Word":"this"},"`Space",{"`Word":"issue"}]]}]}],"warnings":["File \"f.ml.mld\":\nPages (.mld files) should start with a heading."]} +--- input --- {2 {!foo}} --- output --- {"value":[{"`Heading":[{"heading_level":"`Subsection","heading_label_explicit":"false"},{"`Label":[{"`Page":["None","f.ml"]},""]},[{"`Reference":[{"`Root":["foo","`TUnknown"]},[]]}]]}],"warnings":[]} diff --git a/test/model/semantics/odoc_semantic_test.ml b/test/model/semantics/odoc_semantic_test.ml index 7758c8b7bf..0931384a2a 100644 --- a/test/model/semantics/odoc_semantic_test.ml +++ b/test/model/semantics/odoc_semantic_test.ml @@ -264,6 +264,13 @@ let heading () = let link_in_markup = test "{2 {{:foo}}}" + let multilines_link_in_markup = + test + {|{{:https://github.com/ocaml/\ + odoc/\ +issues/\ + 865\ }this issue}|} + let reference_in_markup = test "{2 {!foo}}" let two = test "{2 Foo}\n{2 Bar}"