marimo-team / marimo

A reactive notebook for Python — run reproducible experiments, execute as a script, deploy as an app, and version with git.
https://marimo.io
Apache License 2.0
6.1k stars 197 forks source link

Export Marimo notebook to PDF #896

Open scls19fr opened 6 months ago

scls19fr commented 6 months ago

Description

Hello,

I think PDF export is missing

Kind regards

Suggested solution

Following #892 a PDF export feature will be great. It will be even greater if it is accessible both through CLI and from UI Embedding code into PDF to be able to regenerate notebook (into https://marimo.app/ or in our own Marimo install) could be a nice feature to also have.

Alternative

No response

Additional context

No response

akshayka commented 6 months ago

Thanks for the feature request! It's one we've gotten several times now, so it's definitely in our backlog.

mscolnick commented 6 months ago

@scls19fr are there any pdf rendering libraries you recommend?

Exporting to PDF by CLI will be tricky. It'll still require a browser. Do you expect that to run a headless browser? Where do you want to run this CLI command?

scls19fr commented 6 months ago

Yes headless CLI command will be fine.

Maybe fpdf2 https://py-pdf.github.io/fpdf2/

Or

Reportlab https://docs.reportlab.com/

Or for low level pdf generation

pydyf https://www.courtbouillon.org/pydyf/

See https://akpolatcem.medium.com/creating-various-pdf-files-via-python-eba91a40df9d

scls19fr commented 6 months ago

This SO question can help https://stackoverflow.com/questions/27649600/python-html-to-pdf-with-full-support-for-css3-and-html5 about rendering html/css to pdf.

This post also https://apitemplate.io/blog/how-to-convert-html-to-pdf-using-python/

fujimuramasa commented 5 months ago

It would be better if native pdf export could provide choice disabling some cells like slider or dropdown.

mscolnick commented 4 months ago

@scls19fr @fujimuramasa We have a way to HTML export now from the CLI: marimo export html notebook.py -o notebook.html. Could you pipe this into one of those other CLI/tools to convert it to a PDF? Not sure if our html -> pdf looks clunky (would likely need a browser to render it well)

scls19fr commented 4 months ago

Hi @mscolnick ,

Sorry for not answering quickly I was quite busy.

export to html seems to be broken in my install.

> marimo export html am_modulation.py -o am_modulation.html
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\scelles\anaconda3\Scripts\marimo.exe\__main__.py", line 7, in <module>
  File "C:\Users\scelles\anaconda3\Lib\site-packages\click\core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\click\core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\click\core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\click\core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\click\core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\marimo\_cli\export\commands.py", line 97, in html
    (html, _filename) = asyncio.run(
                        ^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\marimo\_server\export\utils.py", line 43, in run_app_then_export_as_html
    session = await run_app_until_completion(file_manager, cli_args)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\marimo\_server\export\utils.py", line 92, in run_app_until_completion
    session = Session.create(
              ^^^^^^^^^^^^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\marimo\_server\sessions.py", line 290, in create
    return cls(
           ^^^^
  File "C:\Users\scelles\anaconda3\Lib\site-packages\marimo\_server\sessions.py", line 330, in __init__
    self.message_distributor.start()
  File "C:\Users\scelles\anaconda3\Lib\site-packages\marimo\_utils\distributor.py", line 54, in start
    asyncio.get_event_loop().add_reader(
  File "C:\Users\scelles\anaconda3\Lib\asyncio\events.py", line 530, in add_reader
    raise NotImplementedError
NotImplementedError
(base) C:\.....\marimo [main ≡ +1 ~0 -0 !]> marimo --version
0.4.5
mscolnick commented 4 months ago

This might be an issue with windows (or the python version) - @scls19fr can you create a different issue with your python version and env info (with marimo env)

roaldarbol commented 4 months ago

Could it make sense to consider making a pandoc writer? That would enable not just PDF export (through both LaTeX/Typst which would also allow use of many templates for customised PDFs), but endless other conversion opportunities. It seems that the writers need to be written in Lua or Haskell, but I'm not quite sure whether that is the case (https://pandoc.org/custom-writers.html). There is already support for Jupyter notebooks, and it is also what Quarto/RMarkdown uses for PDF generation, so would be a proven path (https://pandoc.org/index.html). It could maybe also be possible to use the HTML as an intermediate step and then convert the HTML to PDF with pandoc.

dmadisetti commented 4 months ago

Here's an example of a PDF with marimo: https://dmadisetti.github.io/quarto-marimo/tutorials/example-pdf.pdf

Using a pandoc filter (and quarto, but you can remove the quarot bit). I think now that marimo can interpret markdown, I can rewrite the filter to be less convoluted