{"id":17978324,"url":"https://github.com/adrianvollmer/zundler","last_synced_at":"2025-10-08T18:42:56.824Z","repository":{"id":61653092,"uuid":"549588865","full_name":"AdrianVollmer/Zundler","owner":"AdrianVollmer","description":"Bundle assets of distributed HTML docs into one self-contained HTML file","archived":false,"fork":false,"pushed_at":"2025-01-11T06:28:26.000Z","size":68729,"stargazers_count":25,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-20T14:23:01.241Z","etag":null,"topics":["documentation","html","sphinx"],"latest_commit_sha":null,"homepage":"https://adrianvollmer.github.io/Zundler/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AdrianVollmer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-11T12:24:02.000Z","updated_at":"2025-02-14T12:23:04.000Z","dependencies_parsed_at":"2024-02-18T21:24:30.443Z","dependency_job_id":"020384aa-b293-474c-95e2-452b07a3860c","html_url":"https://github.com/AdrianVollmer/Zundler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdrianVollmer%2FZundler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdrianVollmer%2FZundler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdrianVollmer%2FZundler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdrianVollmer%2FZundler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AdrianVollmer","download_url":"https://codeload.github.com/AdrianVollmer/Zundler/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245510668,"owners_count":20627236,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["documentation","html","sphinx"],"created_at":"2024-10-29T17:33:10.489Z","updated_at":"2025-10-08T18:42:51.805Z","avatar_url":"https://github.com/AdrianVollmer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Zundler\n=======\n\nBundle assets of distributed HTML docs into one self-contained HTML file.\nIt's built with Sphinx in mind, but can be used on all HTML docs.\n\n\u003e [!WARNING]\n\u003e This is still experimental. Expect breakages! Feel free\n\u003e to open an issue. Please provide everything that is necessary to reproduce\n\u003e the problem.\n\nNaively building one HTML file out of a directory of HTML files that total\ndozens of megabytes quickly overwhelm modern browsers. Zundler solves this\nby taking the following approach:\n\n* Embed all assets that are referenced in CSS files, such as imports and\n  fonts\n* Endow all HTML files with extra scripts that embed these resources at run time:\n  * Convert `script` tags with a `src` attribute referencing a local JavaScript file to inline scripts\n  * Convert `link` tags with an `href` attribute referencing a local CSS file to inline styles\n  * Make all `img` tags with a `src` attribute referencing local images use a data URI\n  * Monkey patch the JavaScript function `fetch` so requests to local files are turned into queries of the \"virtual file tree\" (see next item)\n  * Monkey patch the JavaScript class `URLSearchParams` so GET requests to\n    local files can be handeled; this is needed for Sphinx' search function, for example\n* Create a JSON structure (the \"global context\") out of all files in the directory (the \"virtual file tree\") and other data\n* Gzip the global context and base64-encode it\n* Bundle it all into a scuffolding file with this structure:\n  ```html\n  \u003c!DOCTYPE html\u003e\u003chtml\u003e\n  \u003chead\u003e\u003cstyle\u003e{style}\u003c/style\u003e\u003c/head\u003e\n  \u003cbody\u003e{body}\n  \u003cscript\u003ewindow.global_context = {zipped_global_context}\u003c/script\u003e\n  \u003cscript\u003e{init_js} //# sourceURL=init.js\u003c/script\u003e\n  \u003c/body\u003e\u003c/html\u003e\n  ```\n  The global context is then unzipped using the Pako library, an `iframe` is\n  created and the document is bootstrapped from the virtual file tree.\n\nThe output file is usually smaller than the sum of all input files despite\nsome resources being embedded redundantly and the 33% overhead of the base64\nencoding.\n\n\nLimitations\n-----------\n\nThis approach is quite hacky, but it might work well enough for some purposes.\n\n* Some scripts may break as the execution flow is different than some scripts\n  expect\n* HTML forms with `method=\"GET\"` to local HTML files only work if the\n  receiving code uses URLSearchParams, as same-origin policies forbid\n  reading GET parameters otherwise\n* Opening links in a new tab won't work\n* Redirections won't work (yet)\n* Support of themes or extensions that require jQuery is wonky; fortunately\n  Sphinx stopped supporting jQuery in version 6\n\n\nInstallation\n------------\n\nZundler is a Python package and can be installed like any other Python\npackage.\n\nThe recommended way is to run this:\n\n```shell-session\n$ pip install zundler\n```\n\nIf you prefer an alternative like `pipx`, `poetry` or manually handled\n`venv`s, you probably know what to do.\n\nAn entry point called `zundler` will appear in `~/.local/bin`.\n\n\nBuilding from source\n------------\n\nInstall `hatch` by\n\n`pip install hatch`\n\nThen run\n\n`make clean`\n`make build`\n\nMove into the `dist` folder\n\n`pip install zundler-yourproducedfilename.whl`\n\n\n\nBundling Sphinx docs\n--------------------\n\nThe Zundler package provides a Sphinx extension that adds an appropriate\nbuilder. The builder is a thin wrapper around the HTML builder, which runs\n`zundler` at the end. It can be used with `sphinx-build -b zundler` or, if\nthere is a suitable Makefile, with `make zundler`.\n\nJupyter-Books can be built with `jupyter-book build --custom-builder\nzundler --builder custom .`. You may have to add a render priority for Zundler like\n[here](https://jupyterbook.org/en/stable/content/code-outputs.html#render-priority):\n\n```yaml\nsphinx:\n  config:\n    nb_mime_priority_overrides: [\n      [\"zundler\", \"application/vnd.jupyter.widget-view+json\", 10],\n      [\"zundler\", \"application/javascript\", 20],\n      [\"zundler\", \"text/html\", 30],\n      [\"zundler\", \"image/svg+xml\", 40],\n      [\"zundler\", \"image/png\", 50],\n      [\"zundler\", \"image/jpeg\", 60],\n      [\"zundler\", \"text/markdown\", 70],\n      [\"zundler\", \"text/latex\", 80],\n      [\"zundler\", \"text/plain\", 90]\n    ]\n```\n\nDemos\n-----\n\nSome demo documents are available here:\n\u003chttps://adrianvollmer.github.io/Zundler\u003e\n\n\nCopyright\n---------\n\nAdrian Vollmer, 2022-2024. MIT licensed; see `LICENSE` for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrianvollmer%2Fzundler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadrianvollmer%2Fzundler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrianvollmer%2Fzundler/lists"}