adding hashing script for safer inline

This commit is contained in:
2026-07-09 07:35:44 -06:00
parent c07ef64426
commit 860aeb031a
2 changed files with 29 additions and 0 deletions
+1
View File
@@ -37,6 +37,7 @@ and no external requests — the page is fully self-contained.
| `app.css` / `app.js` | Human-readable, unminified source of the styles/script that are inlined into `index.html`. Edit these, then re-minify and re-inline into `index.html` when publishing a change. | | `app.css` / `app.js` | Human-readable, unminified source of the styles/script that are inlined into `index.html`. Edit these, then re-minify and re-inline into `index.html` when publishing a change. |
| `data/charmap.json` | The full character → Gen 1 byte value → species lookup table, generated from the source spreadsheet. Source of truth for `app.js`'s inlined data. | | `data/charmap.json` | The full character → Gen 1 byte value → species lookup table, generated from the source spreadsheet. Source of truth for `app.js`'s inlined data. |
| `data/charmap.min.json` | Minified copy of the same table. | | `data/charmap.min.json` | Minified copy of the same table. |
| `csp-hash.py` | Prints the `sha256-...` CSP tokens for `index.html`'s inline `<style>`/`<script>` blocks, for a host that locks down `Content-Security-Policy` to hashes instead of `'unsafe-inline'`. Re-run after re-inlining. |
| `CHANGELOG.md` | Release history. | | `CHANGELOG.md` | Release history. |
| `LICENSE` | GPLv3. | | `LICENSE` | GPLv3. |
Executable
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
"""Print CSP sha256-... tokens for index.html's inline <style>/<script> blocks.
Re-run this after editing index.html's inlined CSS/JS (i.e. after the
re-minify/re-inline step described in the README), then paste the printed
values into the nginx server block's Content-Security-Policy header.
"""
import base64
import hashlib
import pathlib
import re
html = pathlib.Path(__file__).with_name("index.html").read_text(encoding="utf-8")
def csp_token(text):
digest = hashlib.sha256(text.encode("utf-8")).digest()
return "'sha256-" + base64.b64encode(digest).decode("ascii") + "'"
style_match = re.search(r"<style[^>]*>(.*?)</style>", html, re.S)
script_match = re.search(r"<script>(.*?)</script>", html, re.S)
if not style_match or not script_match:
raise SystemExit("Couldn't find both an inline <style> and <script> block in index.html")
print("style-src :", csp_token(style_match.group(1)))
print("script-src:", csp_token(script_match.group(1)))