diff --git a/README.md b/README.md index f83c2f7..151af1d 100644 --- a/README.md +++ b/README.md @@ -10,26 +10,39 @@ 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 JavaScript - file to inline scripts - * Convert `link` tags with an `href` attribute referencing a CSS file to inline styles + * 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` and the class `URLSearchParams` + * 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 this scructure and base64-encode it +* Gzip the global context and base64-encode it * Bundle it all into a scuffolding file with this structure: ```html - - + {body} - + ``` - The global context is then unzipped, an `iframe` is created and the - document is bootstrapped from the virtual file tree. + 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. Installation @@ -54,7 +67,7 @@ add a new builder. Similar to the `latexpdf` Suggested Makefile addition: ```make -.PHONY: latexpdf +.PHONY: zundler latexpdf: $(SPHINXBUILD) -b zundler $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo "Bundle asset into one self-contained HTML file..." @@ -68,11 +81,6 @@ Demos ... -Limitations ------------ - -This approach is quite hacky, but it might work well enough for your -purposes. Copyright diff --git a/setup.cfg b/setup.cfg index 636b60c..8e50910 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [metadata] -name = Zundler +name = zundler summary = Bundle assets of distributed HTML docs into one self-contained HTML file description_file = README.md author = Adrian Vollmer @@ -9,9 +9,8 @@ classifier = Development Status :: 3 - Alpha Environment :: Console Environment :: Web Environment - Framework :: Sphinx :: Extension Intended Audience :: Developers - License :: OSI Approved :: BSD License + License :: OSI Approved :: MIT License Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 3 @@ -20,7 +19,6 @@ classifier = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Topic :: Documentation - Topic :: Documentation :: Sphinx Topic :: Utilities [options] @@ -34,10 +32,7 @@ install_requires = [options.entry_points] console_scripts = - zundler = src.__main__:main - -[files] -packages = src + zundler = zundler.__main__:main [mypy] python_version = 3.8 diff --git a/src/sphinxext/__init__.py b/src/sphinxext/__init__.py deleted file mode 100644 index 4767bb6..0000000 --- a/src/sphinxext/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -def setup(app): - app.add_config_value('html_embed_assets', False, 'html') - - return { - 'version': '0.1', - 'parallel_read_safe': True, - 'parallel_write_safe': True, - } diff --git a/src/__init__.py b/zundler/__init__.py similarity index 100% rename from src/__init__.py rename to zundler/__init__.py diff --git a/src/__main__.py b/zundler/__main__.py similarity index 100% rename from src/__main__.py rename to zundler/__main__.py diff --git a/src/args.py b/zundler/args.py similarity index 100% rename from src/args.py rename to zundler/args.py diff --git a/zundler/assets/LICENSE b/zundler/assets/LICENSE new file mode 100644 index 0000000..0bc50f6 --- /dev/null +++ b/zundler/assets/LICENSE @@ -0,0 +1,52 @@ +Zlib copyright notice: + + (C) 1995-2013 Jean-loup Gailly and Mark Adler + +Copyright (c) <''year''> <''copyright holders''> + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + +pako.js: + +(The MIT License) + +Copyright (C) 2014-2017 by Vitaly Puzrin and Andrei Tuputcyn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +Footer + diff --git a/src/assets/init.css b/zundler/assets/init.css similarity index 100% rename from src/assets/init.css rename to zundler/assets/init.css diff --git a/src/assets/init.html b/zundler/assets/init.html similarity index 100% rename from src/assets/init.html rename to zundler/assets/init.html diff --git a/src/assets/init.js b/zundler/assets/init.js similarity index 100% rename from src/assets/init.js rename to zundler/assets/init.js diff --git a/src/assets/inject.js b/zundler/assets/inject.js similarity index 100% rename from src/assets/inject.js rename to zundler/assets/inject.js diff --git a/src/assets/monkeypatch.js b/zundler/assets/monkeypatch.js similarity index 100% rename from src/assets/monkeypatch.js rename to zundler/assets/monkeypatch.js diff --git a/src/assets/pako.min.js b/zundler/assets/pako.min.js similarity index 100% rename from src/assets/pako.min.js rename to zundler/assets/pako.min.js diff --git a/src/embed.py b/zundler/embed.py similarity index 98% rename from src/embed.py rename to zundler/embed.py index 4d6b7e2..3f54ec3 100644 --- a/src/embed.py +++ b/zundler/embed.py @@ -39,6 +39,7 @@ def embed_assets(index_file, output_path=None): 'init.html', 'monkeypatch.js', 'pako.min.js', + 'LICENSE', ]: path = os.path.join(SCRIPT_PATH, 'assets', filename) init_files[filename] = open(path, 'r').read() @@ -77,13 +78,14 @@ def embed_assets(index_file, output_path=None): - + """.format( style=init_files['init.css'], init_js=init_files['init.js'], pako=init_files['pako.min.js'], body=init_files['init.html'], global_context=global_context, + license=init_files['LICENSE'], ) with open(output_path, 'w') as fp: diff --git a/zundler/sphinxext/__init__.py b/zundler/sphinxext/__init__.py new file mode 100644 index 0000000..ca8df50 --- /dev/null +++ b/zundler/sphinxext/__init__.py @@ -0,0 +1,21 @@ +from sphinx.builders.html import StandaloneHTMLBuilder + +MAKEFILE = """ +""" + + +class ZundlerBuilder(StandaloneHTMLBuilder): + def handle_finish(self) -> None: + super().handle_finish() + + +def setup(app): + app.add_config_value('html_embed_assets', False, 'html') + + app.add_builder(ZundlerBuilder) + + return { + 'version': '0.1', + 'parallel_read_safe': True, + 'parallel_write_safe': True, + }