Skip to main content

Bundle assets of distributed HTML docs into one self-contained HTML file

Project description

Zundler

Bundle assets of distributed HTML docs into one self-contained HTML file. It's built with Sphinx in mind, but can be used on all HTML docs.

[!WARNING] This is still experimental. Expect breakages! Feel free to open an issue. Please provide everything that is necessary to reproduce the problem.

Naively building one HTML file out of a directory of HTML files that total dozens of megabytes quickly overwhelm modern browsers. Zundler solves this by taking the following approach:

  • Embed all assets that are referenced in CSS files, such as imports and fonts
  • Endow all HTML files with extra scripts that embed these resources at run time:
    • Convert script tags with a src attribute referencing a local JavaScript file to inline scripts
    • Convert link tags with an href attribute referencing a local CSS file to inline styles
    • Make all img tags with a src attribute referencing local images use a data URI
    • Monkey patch the JavaScript function fetch so requests to local files are turned into queries of the "virtual file tree" (see next item)
    • Monkey patch the JavaScript class URLSearchParams so GET requests to local files can be handeled; this is needed for Sphinx' search function, for example
  • Create a JSON structure (the "global context") out of all files in the directory (the "virtual file tree") and other data
  • Gzip the global context and base64-encode it
  • Bundle it all into a scuffolding file with this structure:
    <!DOCTYPE html><html>
    <head><style>{style}</style></head>
    <body>{body}
    <script>window.global_context = {zipped_global_context}</script>
    <script>{init_js} //# sourceURL=init.js</script>
    </body></html>
    
    The global context is then unzipped using the Pako library, an iframe is created and the document is bootstrapped from the virtual file tree.

The output file is usually smaller than the sum of all input files despite some resources being embedded redundantly and the 33% overhead of the base64 encoding.

Limitations

This approach is quite hacky, but it might work well enough for some purposes.

  • Some scripts may break as the execution flow is different than some scripts expect
  • HTML forms with method="GET" to local HTML files only work if the receiving code uses URLSearchParams, as same-origin policies forbid reading GET parameters otherwise
  • Opening links in a new tab won't work
  • Redirections won't work (yet)
  • Support of themes or extensions that require jQuery is wonky; fortunately Sphinx stopped supporting jQuery in version 6

Installation

Zundler is a Python package and can be installed like any other Python package.

The recommended way is to run this:

$ pip install zundler

If you prefer an alternative like pipx, poetry or manually handled venvs, you probably know what to do.

An entry point called zundler will appear in ~/.local/bin.

Building from source

Install hatch by

pip install hatch

Then run

make clean make build

Move into the dist folder

pip install zundler-yourproducedfilename.whl

Bundling Sphinx docs

The Zundler package provides a Sphinx extension that adds an appropriate builder. The builder is a thin wrapper around the HTML builder, which runs zundler at the end. It can be used with sphinx-build -b zundler or, if there is a suitable Makefile, with make zundler.

Jupyter-Books can be built with jupyter-book build --custom-builder zundler --builder custom .. You may have to add a render priority for Zundler like here:

sphinx:
  config:
    nb_mime_priority_overrides: [
      ["zundler", "application/vnd.jupyter.widget-view+json", 10],
      ["zundler", "application/javascript", 20],
      ["zundler", "text/html", 30],
      ["zundler", "image/svg+xml", 40],
      ["zundler", "image/png", 50],
      ["zundler", "image/jpeg", 60],
      ["zundler", "text/markdown", 70],
      ["zundler", "text/latex", 80],
      ["zundler", "text/plain", 90]
    ]

Demos

Some demo documents are available here: https://adrianvollmer.github.io/Zundler

Copyright

Adrian Vollmer, 2022-2024. MIT licensed; see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zundler-0.3.0.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zundler-0.3.0-py3-none-any.whl (22.7 kB view details)

Uploaded Python 3

File details

Details for the file zundler-0.3.0.tar.gz.

File metadata

  • Download URL: zundler-0.3.0.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.19

File hashes

Hashes for zundler-0.3.0.tar.gz
Algorithm Hash digest
SHA256 a9856bb71af86ea38ef7df761a97d832e6395b3f94bf36c18eb957ad318e2f29
MD5 492da0c882eb7edf091df5bb8d846f26
BLAKE2b-256 d6c4095d38029b510d932d79cef6e33af0908f6c0494157accb335b6c596b00b

See more details on using hashes here.

File details

Details for the file zundler-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: zundler-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 22.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.19

File hashes

Hashes for zundler-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aa8254f4cd18e830ca4d100e6980513fc393e30e47daae3a345a7471e6c28b57
MD5 2920348221503258d6425e6bad2306b9
BLAKE2b-256 d47dfd475816d1215d19fcf1ae874e7d0cba31c34efb32bf680b7bf3de4d2524

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page