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

Medias in odoc #1005

Closed
wants to merge 17 commits into from
Closed

Medias in odoc #1005

wants to merge 17 commits into from

Conversation

panglesd
Copy link
Collaborator

Based on #1002.
See #985 for discussion about the syntax.

The syntax

The syntax is the following, where <media> can be either image, video or audio:

{<media>!reference_to_asset}

{{<media>!reference_to_asset}replacement/alternative text}

{<media>:link_to_asset}

{{<media>:link_to_asset}replacement/alternative text}

The media elements are block elements, and as such should be separated from the rest of the content with new lines.
They cannot be put inline (so, for now, no {{:link-to-something}{image!ref}}...) or even inside other block elements (such as table, lists, ...).
The reason for this is that without attributes (e.g. to define the size) it would be quite hard to style the inserted media as an inline in a consistent way...
I think it is enough for most cases. Searching github for {html% and embedding of images seems to comfort this.

The rendering

Only html display medias, using the html5 elements audio, video and img. Even images are not displayed in latex (it lacks "asset" support).

For images, the "replacement text" is used an alt text. The replacement text is also used in case of unresolved reference.

For latex and manpage backend, the replacement text is always used.

Future work

I wondered whether something such as {href!reference.to."asset.png"}, which would render as ../../reference/to/asset.png (for instance) would be a good addition? It would allow more html embedding, such as {html% <img src="%}{href!ref}{html%"/>%}.
What do you think?

Having a way to specify the size (but this requires some syntax discussion!), or to add inline media, would be nice.

| Error exn ->
(* FIXME: better error message *)
Printf.eprintf "Id.href failed: %S\n%!"
(Url.Error.to_string exn);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Something like: "Can't resolve asset file path/url"?

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 taken from a "warning" thrown in similar situations.
However, yes, we could finally fix those FIXME instead of propagating them through the code...
Related: #1010 which removed similar unconditional eprintfs.

@@ -90,6 +94,9 @@ and Block : sig
| Verbatim of string
| Raw_markup of Raw_markup.t
| Table of t Table.t
| Image of Target.t * Inline.t
| Video of Target.t * Inline.t
| Audio of Target.t * Inline.t
Copy link
Collaborator

Choose a reason for hiding this comment

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

The 3 implementations is very similar, what do you think of using something similar to the model:

type media = [ `Image | `Audio | `Video ]

type t =
  ...
  | Media of media * Target.t * Inline.t

?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think both implementations are very similar but I can try to see if it can make some part of the code more factorized!

@dbuenzli
Copy link
Contributor

They cannot be put inline (so, for now, no {{:link-to-something}{image!ref}}...) or even inside other block elements (such as table, lists, ...).

That seems rather limiting. I don't really care about the inline bit but you definitively want to put these things into lists, for example:

This can be either:
{ul
{- A sine wave {audio!sine.wav}}
{- A triangle wave {audio!tri.wav}}}

I don't really care if the assets element ends up being a block level element rather than an inline but I definitively want it into list elements.

@Julow
Copy link
Collaborator

Julow commented Sep 28, 2023

I'm in favor of medias to be (nestable) block elements. These elements take time to show up and might never do. I think it's important to make sure they are visible, for example by nesting them in a block with a border and a large padding.
We also need space for a caption in the syntax and in the rendering.

@panglesd
Copy link
Collaborator Author

I turned medias into nestable block elements: it is now possible to add them inside lists and tables.
They will still be displayed as blocks. I haven't added any fixed size, border...
About the caption, I think this should be left for figures. I could add a new media, figure whose "replacement text" is the caption.

@panglesd panglesd force-pushed the medias-in-odoc branch 2 times, most recently from 4fa1ec4 to 76071aa Compare September 28, 2023 15:08
@panglesd panglesd requested review from jonludlam and Julow September 29, 2023 07:59
@@ -349,7 +349,7 @@ module L = struct
when name = LabelName.to_string name' ->
Ok (`Identifier label)
| _ -> find tl)
| [] -> Error (`Find_by_name (`Page, name))
| [] -> Error (`Find_by_name (`Label, name))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this a fix that could be made in a separate PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it could be made in another PR. Not sure that's worth it, given how small it is! But if anyone confirm it's helpful, I'll separate it into another PR!

image url
| Internal Unresolved ->
let a = [ Html.a_class [ "xref-unresolved" ] ] in
[ Html.span ~a (inline ~config ~resolve alt) ]
Copy link
Collaborator

Choose a reason for hiding this comment

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

For unresolved images, what do you think of displaying placeholder images like:
Image_not_available (1)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

When there is no alt text, yes that's a good idea! (are we allowed to use this particular image?)

When there is alt text, I'm not sure what's best!

Copy link
Contributor

@dbuenzli dbuenzli Oct 17, 2023

Choose a reason for hiding this comment

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

Personally I think it's better to let things break. This makes it mechanically discoverable (404) if you add a stub, then the page has no problem as far as machines are concerned.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Readers also need to distinguish missing images. Perhaps the alt text could be made mandatory ?
That's what I was most worried about when I suggested to add border, padding and a caption around image blocks.

Copy link
Contributor

Choose a reason for hiding this comment

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

Readers also need to distinguish missing images.

Browsers already have their own way of notifying users about broken image sources (typically via a small icon representing a broken document), there's no need to invent anything here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah but of course this should not be an a this should be an img tag with the class xref-unresolved and perhaps with the src attribute being simply the undefined reference (so that the broken icon shows up, it does not with an empty src).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Currently it's a span (the a is for attribute) which include visual feedback that something is wrong, but nothing tells the user or the browser that an image should be there. So yes, I think an img with broken url and the alt text as alt text (if there is one) makes sense.
I'll check if "broken url" can be made a real concept, and how the browser react!

@panglesd
Copy link
Collaborator Author

panglesd commented Nov 3, 2023

Here is the state of this PR!

It is mostly finished, I think. There is one remaining question: what do we do with unresolved medias.

@dbuenzli suggested to use an "unresolved" URL, so that the browser is responsible for showing the breakage.
I think it is a good idea, I just have some trouble accepting to forge an invalid url. Putting the reference as an url is making my brain output "Error: This expression has type reference but an expression was expected of type url" even if both ultimately are strings. It also creates a web request which, maybe, could work and show something unintended?

I have tested how my browser (firefox) displays an image with an url that returns 404. When there is no alt text, it shows an icon of a broken image. When there is an empty alt-text, it shows nothing. When there is a non-empty alt-text, it shows the alt-text as an image. All of this is a very good behaviour in my opinion.
With video, it is also very clear when the file is not found.
With audio however, the normal controls are shown, but as if the file were of length 0s, nothing happens when you click on the "play" button, there is no indication that a file could not be loaded.

Also, to note, I have tried some "invalid" urls, such as \\, and it shows the broken image without needing to make a network request. But this is very browser implementation specific...

I won't have time to work on this more in the coming month.

@dbuenzli
Copy link
Contributor

dbuenzli commented Nov 4, 2023

@dbuenzli suggested to use an "unresolved" URL, so that the browser is responsible for showing the breakage.
I think it is a good idea,

In fact I forgot that odoc would already tell you that something is wrong, this reference doesn't exist. So there's little interest in these 404, there is already a way to discover these errors when you produce the docs. So maybe you can just output text "Missing {image,audio,video} asset" classified with xref-unresolved in a span or a div depending whether it's a block or inline element.

Copy link
Collaborator

@gpetiot gpetiot left a comment

Choose a reason for hiding this comment

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

A few typos left in the code.

Otherwise, it looks good to me, is something else missing or blocking this PR?

src/model_desc/paths_desc.ml Outdated Show resolved Hide resolved
reference_kind
* media_href with_location
* inline_element with_location list
* media (** @since 2.3.0 *)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

probably 2.4.0?

src/parser/token.ml Outdated Show resolved Hide resolved
src/parser/token.ml Outdated Show resolved Hide resolved
src/parser/token.ml Outdated Show resolved Hide resolved
src/parser/token.ml Outdated Show resolved Hide resolved
src/parser/token.ml Outdated Show resolved Hide resolved
src/parser/token.ml Outdated Show resolved Hide resolved
src/parser/token.ml Outdated Show resolved Hide resolved
@@ -729,26 +770,55 @@ let resolve_reference_dot env parent name =
| (`C _ | `CT _) as p -> resolve_reference_dot_class env p name
| `P _ as page -> resolve_reference_dot_page env page name

let resolve_page_reference env (r : Reference.Page.t) =
match r with
| `Resolved _ -> failwith "unimplemented"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's not forget this

@jonludlam
Copy link
Member

Otherwise, it looks good to me, is something else missing or blocking this PR?

Yes, I'd just like to try the suggestion in #1002 before we merge that, then this can be rebased on top.

@favonia
Copy link
Contributor

favonia commented Nov 14, 2023

I have a related request which I believe will come up once this PR is merged: I hope there's a way for odoc to download external images, audios, and maybe videos and generate offline-viewable pages. The reason is that I might want to generate a self-contained documentation site for offline reading without putting everything in the same git repo.

Maybe this can be done in a different PR, but I hope the current design is compatible with this request.

Reference can now be toward assets.
When resolving them, look up the assets of the current page, and if
not found, recurse in the parent page.

Signed-off-by: Paul-Elliot <[email protected]>
Signed-off-by: Paul-Elliot <[email protected]>
Signed-off-by: Paul-Elliot <[email protected]>
Signed-off-by: Paul-Elliot <[email protected]>
Signed-off-by: Paul-Elliot <[email protected]>
Signed-off-by: Paul-Elliot <[email protected]>
@panglesd panglesd force-pushed the medias-in-odoc branch 2 times, most recently from ef077e3 to 4e40617 Compare January 10, 2024 07:42
@panglesd
Copy link
Collaborator Author

Closing now since asset referencing will change subsequently soon. But some of the code will be used!

@panglesd panglesd closed this Mar 18, 2024
@panglesd panglesd mentioned this pull request Aug 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants