Include images in rustdoc output

63adaed
Opened by Daniel Collin at 2024-02-29 15:16:38

As written by Luthaf over here

https://users.rust-lang.org/t/include-images-in-rustdoc-output/3487

"Hi rustaceans!

Images in documentation can be really useful to provide some insight on algorithms or modules organisation.

It is already possible to insert a link to an image in documentation comment

/// ![Alt version](url://for/this/image.png)

But using this method, we only get to include images already available in some place of Internet.

Is it a way to make rustdoc copy some files to the target/doc folder, so that it is easy to include specific images in the documentation? The same could go for other static files, like specific CSS or JS.

Is it possible yet? If not, do you think it is worth it?"

I this this would be awesome to include as sometimes using images is much easier when explain something than showing text.

  1. I second this, images can greatly help explaining (geometrical split_at example).

    bluss at 2016-03-07 21:51:20

  2. Since the focus is on doxidize now, rustdoc is in maintenance-only mode. Should this be closed?

    cc: @steveklabnik

    Jim Blandy at 2018-04-26 02:43:47

  3. I'd say "maintenance-only" mode is a bit strong; rustdoc has its own team and they're still working on new stuff. It's entirely possible that this will get added to rustdoc.

    Steve Klabnik at 2018-04-26 11:23:19

  4. Would love this as well! Has there been any updates?

    TotalKrill at 2018-07-30 16:35:23

  5. It‘s work

    //! <div>
    //! <img src="../../../images/rustbook.jpg" height="300" width="220" />
    //! </div>
    //! <hr/>
    

    Alex at 2018-11-21 13:37:52

  6. That only works locally if you're building the docs for your own crate. Does not work on docs.rs or if the crate is a dependency of something else.

    Background: The referred image is not copied / tracked.

    Marco Neumann at 2018-11-22 09:21:22

  7. @crepererum you're right. One solution is to separate the doc file and manually modify it.

    Alex at 2018-12-01 02:03:40

  8. Or you host the image somewhere, like on GitHub pages (that's what ndarray is doing here https://github.com/rust-ndarray/ndarray/blob/master/src/impl_views.rs )

    Marco Neumann at 2018-12-01 11:34:34

  9. I think what would be most optimal is if there could be a folder where images for the doc could be stored in the crate folder structure.

    There is one huge painpoint here though, and that is a lot of people just love to generate extremely large pictures to include in the crates. For no reason: ClickBait article with example

    So if this should be in the code, the file size should be limited.

    TotalKrill at 2018-12-22 15:16:47

  10. There is a workaround.

    You can insert the image data, base64 encoded, directly into your rust source code comments, and rust-doc will pass this to the html, where it will become an inline image in the html code. This is based on rfc2397 aka the data URI.

    http://www.bigfastblog.com/embed-base64-encoded-images-inline-in-html https://tools.ietf.org/html/rfc2397

    $ base64 ../images/mypicture.png  | awk ' { print "/// " $1 } ' > myfile.b64
    
    myfile.rs:
    
    /// my function does blah blah blah. here is a picture:
    /// <div>
    /// <img src="data:image/png;base64,
    /// iVBORw0KGgetcetcetc                       <-- copy/paste myfile.b64 here
    /// ....                                      <-- several dozen lines of myfile.b64
    /// JDIOIDondio00778==                        <-- last line of myfile.b64
    /// ">
    /// </div>
    fn myfunction(x:u64)->bool { x<5 }
    
    $ cargo doc
    

    Now the html file under target/whatever will have the png image baked inside of it as base64 code.

    I think this might be possible with svg but havent tested.


    I think it might be nice to consider if rustdoc could do this on it's own, automatically, taking a <img src=../../image.png file, encoding it as base64, and inline it into the html file itself, without the user having to insert base64 directly into their rust comments.

    don bright at 2019-04-15 01:06:18

  11. I don't think this is a good idea: it'd force rustdoc to download the content to know if it's an image or a video or anything else. Also, from a security perspective, I think this wouldd be an issue as well (cc @pietroalbini ).

    Guillaume Gomez at 2020-01-31 12:06:12

  12. From my point of view it'd be fine if rustdoc included images present in the crate's source tarball into the generated docs. It definitely should not download images from the Internet.

    Pietro Albini at 2020-01-31 13:47:57

  13. I don't see the difference between local image and one from the internet. In both case, it can't be trusted.

    Guillaume Gomez at 2020-01-31 14:24:21

  14. Well then, I am guessing the current way to input it into a comment as base64 isnt much different.

    The end result should still be an image shown online, wherever it is a link to an image, or an image generated from base64.

    Nothing can be trusted anywhere, but still we do it.

    TotalKrill at 2020-01-31 14:35:21

  15. I don't see the difference between local image and one from the internet. In both case, it can't be trusted.

    You can do the same thing with workarounds today, and you'll still be able to do it with workarounds in the future. Besides, it's a legit feature request.

    Pietro Albini at 2020-01-31 15:53:25

  16. Indeed, I don't know why but I was kinda confusing the URL thing... Then yes, it'll require to move the file content to a given target and be sure to not have conflicts. Urg... Headache ahead! I'll try to do it in not too long from now.

    Guillaume Gomez at 2020-01-31 15:55:08

  17. Then yes, it'll require to move the file content to a given target and be sure to not have conflicts.

    A possible solution for this would be to hash the image content, move them to target/doc/{crate}/static-img/{hash}.{ext}, and rewrite the links in the generated HTML accordingly. (static-img not being a valid module name should not clash with other files)

    Guillaume Fraux at 2020-01-31 17:11:59

  18. If I hash the path, it might be easier, indeed. I didn't want to create another folder but that would fix the naming conflict so I think I'll do that. Thanks for the tips!

    Guillaume Gomez at 2020-02-01 09:55:27

  19. I would rather hash the file content than the path, since the same file might be referred to by different .rs files, using different paths.

    Guillaume Fraux at 2020-02-01 20:33:28

  20. With this feature, would it also be possible to link to a file included in the crate inside the doc(html_root_url) attribute?

    Trevor Spiteri at 2020-04-15 18:37:54

  21. I ran into this today and would love to see it happen. @GuillaumeGomez is this something I could help with? I've never contributed to rustdoc before but if you'd be interested in mentoring me maybe I could help implement it?

    Dave Herman at 2021-05-16 19:36:23

  22. It's a tricky issue on many aspects. I tried a first implementation as you can see in #68734. But honestly, I'm not sure if this is a good idea as a first contribution on rustdoc because a lot of questions are not really answered... I prefer to say this so you know what you're stepping into before spending a lot of time working on it. But if you still want to give it a try, maybe take a quick look at #68734 and go for it!

    Guillaume Gomez at 2021-05-16 21:37:14

  23. I appreciate the warning 😅 I'll take a look!

    Dave Herman at 2021-05-16 21:52:01

  24. Is there any process yet? I'd like to add some images into the docs as well :)

    TornaxO7 at 2021-05-31 14:34:00

  25. In addition to images, I also would love to add small GIFs and videos. I am currently using this workaround for my local docs:

    /// <div>
    ///   <video width="640" autoplay muted loop>
    ///     <source src="../../../my-video.mp4" type="video/mp4">
    ///   </video>
    /// </div>
    

    Vinh Truong at 2021-08-05 12:24:16

  26. If your image is a SVG, you can include it directly with include_str!, as SVG is valid HTML.

    //! # BLahblah
    //! 
    //! blahblah
    //!
    #![doc=include_str!("shared-bus.svg")]
    //!
    //! blahblahblah
    

    Dario Nieuwenhuis at 2022-02-16 00:07:44

  27. We should encourage usage of SVG as format in documentation output, it is a well working format for block-diagrams, flowcharts and similar things that are actually useful for documentation purposes.

    Nice tip though!

    TotalKrill at 2022-02-16 07:53:47

  28. If you can rely on Rust >= 1.54, then using embed-doc-image is also similarly simple:

    /// A diagram of something
    ///
    /// ![Diagram](diagram_label)
    /// 
    /// The rest of the docs.
    #![doc = embed_image!("diagram_label", "images/diagram.png")]
    

    This should work with all major file formats supported on the web, and works both locally and on docs.rs. The example code in the docs is much more complex because they explain how to have a graceful fallback to Rust < 1.54. If you don't need this then it's simple to use. I should probably update the docs with the simpler case first.

    Admittedly the crate could still need some improvements in terms of conditionally enabling the feature (so that, for example, for non-doc builds you can easily skip the embed macro compilation). I'm too pressed on time for doing that myself atm, but it wouldn't take too much effort to improve further - though there should probably be a brief discussion about design first.

    Andreas Borgen Longva at 2022-02-16 08:18:18

  29. You can make it generate cfg(doc) and it'll only be generated when rustdoc is running.

    Guillaume Gomez at 2022-02-16 09:03:46

  30. @GuillaumeGomez: that sounds perfect. Seems like cfg(doc) has not been stabilized yet, is this correct? According to https://doc.rust-lang.org/beta/unstable-book/language-features/doc-cfg.html.

    Andreas Borgen Longva at 2022-02-16 09:06:18

  31. doc(cfg()) != cfg(doc). :wink: It's been stable for a while now. There is also cfg(doctest) (which is when you run rustdoc --test).

    Guillaume Gomez at 2022-02-16 09:11:11

  32. The documentation is here.

    Guillaume Gomez at 2022-02-16 09:12:09

  33. @GuillaumeGomez: that's very interesting! I was led to believe otherwise by the following sentence in the unstable book (see link above):

    image

    I couldn't find out when cfg(doc) was stabilized. This would be useful info for documenting a fallback solution. Do you know where to find this info?

    While this cfg directive seems very useful in the context of embedding images, it doesn't directly solve the issue of embed-doc-image, which is that you'll end up including syn and some other dependencies in your non-doc builds. I believe it's not possible to conditionally enable a Cargo feature only for doc builds somehow, is it?

    EDIT: It would however lead to an improvement in the sense that no doc-related code is generated for non-doc builds, other than having to build the dependencies.

    Andreas Borgen Longva at 2022-02-16 09:35:08

  34. No even though there is an open issue about that on cargo. But it hasn't received much attention unfortunately.

    As for cfg(doc), it's stable since 1.40.

    Guillaume Gomez at 2022-02-16 09:39:31

  35. And here is the cargo issue.

    Guillaume Gomez at 2022-02-16 09:40:04

  36. I opened an RFC for this feature: https://github.com/rust-lang/rfcs/pull/3397

    Guillaume Gomez at 2023-03-16 12:57:36

  37. This is how I did it in Github Actions, not complicated, might not be worth a full RFC. However, it would be nice if rustdoc could do this natively so it could check if the image link is valid. https://github.com/ryanpeach/OrbitingSandRust/pull/102

    Ryan Peach at 2024-02-18 05:25:16

  38. Sure, it works in your CI, but how does it work for crates depending on yours? Are your images included into your crate package? If so you're doing something very wrong.

    Guillaume Gomez at 2024-02-18 10:14:53

  39. Just including my PR so that others looking for a more immediate solution who find this on google can see an example.

    Ryan Peach at 2024-02-19 20:51:40

  40. Sure, it works in your CI, but how does it work for crates depending on yours? Are your images included into your crate package? If so you're doing something very wrong.

    Is there a particular issue with including images in a crate package besides size?

    Corey Farwell at 2024-02-29 01:48:59

  41. Not that I can think of. The RFC is currently on hold until the potential cargo archive format becomes a reality (as mentioned here).

    Guillaume Gomez at 2024-02-29 09:41:18

  42. If so you're doing something very wrong.

    @GuillaumeGomez So if this is the only way to do it, then why is it "very wrong"?

    Corey Farwell at 2024-02-29 15:00:17

  43. I answered (too aggressively) to:

    This is how I did it in Github Actions, not complicated, might not be worth a full RFC. However, it would be nice if rustdoc could do this natively so it could check if the image link is valid. https://github.com/ryanpeach/OrbitingSandRust/pull/102

    In particular this part:

    might not be worth a full RFC

    The fact that we might includes megabytes (if not more) of data by default only for documentation sounds like something that should be very carefully considered.

    Guillaume Gomez at 2024-02-29 15:16:38