Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add markdown generator #723

Closed
wants to merge 4 commits into from
Closed

Add markdown generator #723

wants to merge 4 commits into from

Conversation

lubegasimon
Copy link
Collaborator

@lubegasimon lubegasimon commented Sep 9, 2021

Fixes #709

Todo
- [] Don’t render OCaml syntax, that is sig,end etc. This might require tweaking the document library slightly. (Edit: Disclaimer, no tweaking of the document library is needed!)

  • Add options to render markdown in different flavours. That is, pandoc and github’s markdown. (Stretch goal)
  • Add option to enable and disable links (suggested by @lpw25 in odoc-dev meeting 9/9/21)
  • Fix end keyword that is poorly aligned for submodules.
  • handling of labels
  • use unicode character rather than &nbsp (by @lpw25).
  • tie anchor tags to —generate-links options (@lpw25)
    - [ ] Treat doc comments in modules and records a little different from those outside.
  • updating the docs to include the markdown generator

@lubegasimon lubegasimon marked this pull request as ready for review September 9, 2021 08:52
@lubegasimon lubegasimon marked this pull request as draft September 9, 2021 08:56
@lubegasimon lubegasimon force-pushed the add-markdown-generator branch 4 times, most recently from 9059f17 to b0cc543 Compare September 15, 2021 15:27
@lubegasimon lubegasimon marked this pull request as ready for review September 15, 2021 15:28
@lubegasimon
Copy link
Collaborator Author

@Drup, this is ready for review 🙂.

Copy link
Contributor

@Drup Drup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a first set of comments. Could you post the result for various files so that people can look at the results.

Maybe we can try a version that inline submodules, like in the latex version. Not sure It'll give good results, but it might be more readable in a text editor than 1 file per module.

src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
in
list ~sep:break (List.map f descrs) ++ continue rest
| Source content -> source_code content ++ continue rest
| Verbatim content -> str "%s" content ++ continue rest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not marked up as verbatim (it needs indentation or backticks).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Env is supposed to implement indentation ? (seems planned in the types but there's no implementation)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, indentation will be better

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must be resolved in the most recent commit using space ++ space — > (“ “)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not fixed. Indentation is not applied to every lines:

(** {v
verbatim
text
v} *)

renders to:

    verbatim
text

Also, this should be rended the same way (existing indentation should be detected and normalized):

(** {v
      verbatim
      text
    v} *)

let bullet =
match list_typ with
| Unordered -> escaped "- "
| Ordered -> str "%d) " (n + 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ordered lists in the standard are %d., might as well use that.

Also, you'll need to be pretty careful about breaks inside list items (it requires some indentation to preserve list-ness).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation of list items is still broken:

(** {ul
     {- p1

        p2}
    } *)

renders to:

- p1
p2

in
match label with
| Some _ -> command level (str " " ++ inline title)
| None -> command (level ^ " ") (inline title)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what's the difference between those two, but in any case, the label is missing. There is a pandoc extension for labels.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extension is header_attributes.
We might need to add a "target" option (with values either pandoc or gh let's say) and to use the syntax only if it makes sense.

Anyway, for now, we need to at least use the <a id="..."> trick to make the label work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have the flavour option, this is wanted.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no <a id...> on headings with --generate-links enabled.

let def = block i.Description.definition in
break ++ str "@" ++ key ++ str " : " ++ def ++ break ++ break
in
list ~sep:break (List.map f descrs) ++ continue rest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the definition_list extension from pandoc ? It'll be non-standard anyway.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being that we now have a —md-flavour option, more of the renderer<Pandoc and GFM>-specific syntaxes will be added. Thanks!

src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
in
list ~sep:break (List.map f descrs) ++ continue rest
| Source content -> source_code content ++ continue rest
| Verbatim content -> str "%s" content ++ continue rest
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Env is supposed to implement indentation ? (seems planned in the types but there's no implementation)

src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
src/markdown/generator.ml Outdated Show resolved Hide resolved
@lubegasimon
Copy link
Collaborator Author

This PR is ready for another review 🙂.

Copy link
Collaborator

@Julow Julow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spacing between block elements is not right:

(** p1 *)

(** p2

   p3

   {ul
     {- a}
     {- b}
    } *)

renders to:

p1
p2
p3
- a

- b

We expect an empty line between two blocks.


val concat : t list -> t

val inline' : string list -> t
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't necessary, it's used once and can be inlined to gain some readability.

Comment on lines +7 to +9
Odoc_markdown.Generator.args.md_flavour := args.md_flavour;
Odoc_markdown.Generator.args.generate_links := args.generate_links;
Odoc_markdown.Generator.render page
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to use mutable fields.
A value of type Odoc_markdown.Generator.args can be passed directly to Odoc_markdown.Generator.render.
The type args above doesn't need to be a different type, it can be equal to Odoc_markdown.Generator.args.

@@ -100,6 +111,7 @@ let () =
(html_target_rule, Fpath.v "html", Some "--flat");
(latex_target_rule, Fpath.v "latex", None);
(man_target_rule, Fpath.v "man", None);
(markdown_target_rule, Fpath.v "markdown", None);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to test md flavours as well as the generate-links option. Perhaps we can use other kinds of tests for that to avoid having a huge number of test outputs.

in
Arg.(
value & opt string ""
& info ~docv:"MARKDOWN_FLAVOUR" ~doc [ "md-flavour" ])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This option should be renamed flavour.

Comment on lines +254 to +264
let level =
match level with
| 1 -> make_hashes 1
| 2 -> make_hashes 2
| 3 -> make_hashes 3
| 4 -> make_hashes 4
| 5 -> make_hashes 5
| 6 -> make_hashes 6
| _ -> ""
(* We can be sure that h6 will never be exceded! *)
in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let level =
match level with
| 1 -> make_hashes 1
| 2 -> make_hashes 2
| 3 -> make_hashes 3
| 4 -> make_hashes 4
| 5 -> make_hashes 5
| 6 -> make_hashes 6
| _ -> ""
(* We can be sure that h6 will never be exceded! *)
in
let level = make_hashes level in

Comment on lines +212 to +214
cond
(source_code content nbsp ++ continue rest)
(backticks ++ source_code content nbsp ++ backticks ++ continue rest)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this change formatting depending on generate-links ? I see no reason.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s because we would end up with links in back ticks which will confuse the reader, that is, [text](href) (text will be a link, but it won’t be displayed as a link rather as source code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of links inside "source code" ?
Anyway, removing the backticks isn't the solution because we want them.

| Text "" -> continue rest
| Text s -> (
match s with
| "end" | "}" | "]" ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation containing these words is broken:

(** end } ] *)

The keywords must not be matched into any text, only when nested into a source_code with the right tag.

Copy link
Collaborator Author

@lubegasimon lubegasimon Oct 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm! only } and ] behave not right but yes, that’s a good catch. Thanks!

"type nums = [ | `One | `Two ]" would be rendered as "``|`````Monday`` "
if the spaces were missing.
*)
| Backticks -> Format.fprintf fmt " `` "
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use a single backtick when possible (when there is no backticks in the enclosed code).

| Text b -> block b nbsp' ++ continue rest
| Heading h -> break ++ heading h nbsp' ++ break ++ break ++ continue rest
| Declaration { attr = _; anchor; content; doc } ->
let nbsp'' = nbsp ++ nbsp ++ nbsp ++ nbsp in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move that code into documented_src because it needs both values.


type args = { generate_links : bool ref; md_flavour : string ref }

let args = { generate_links = ref true; md_flavour = ref "" }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use a global variable. The args value should be passed to every functions.

@lubegasimon
Copy link
Collaborator Author

Closed in favour of #791

@lubegasimon lubegasimon closed this Dec 1, 2021
@lubegasimon lubegasimon deleted the add-markdown-generator branch February 18, 2022 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Markdown output
3 participants