1 unstable release

Uses new Rust 2024

0.1.0 Jun 1, 2025

#326 in Command line utilities

Download history 107/week @ 2025-05-30 8/week @ 2025-06-06 4/week @ 2025-06-13 2/week @ 2025-06-20

121 downloads per month

GPL-3.0-or-later

20KB
376 lines

resource-rewriter

Single-file HTML projects that contain inline styles and JavaScript are incredibly convenient to develop with and share, however they constrain some security features, namely the Content Security Policy (CSP).

resource-rewriter automatically moves any inline styles and scripts to separate files that are loaded by URL so you can set a strict CSP that bans the use of unsafe inline <style> and <script> tags. (Note: no rewriting of inline style/script attributes is attempted.)

This tool is intended to be used at deploy time, so you can develop and share in a single HTML file, and then split it up as you deploy it.

It also adds Subresource Integrity (SRI) hashes to and uses content-based cache invalidation hashes to URLs (optional).

Example

Given an index.html file with both inline styles and scripts and ones already stored in separate files, here's what it looks like in practice:

index.html

 <head>
     <title>Test</title>
-    <link href="styles.css" rel="stylesheet">
-    <style>
-        body {
-            background-color: lightblue;
-        }
-    </style>
+    <link href="styles.css?468d601e37c90f84" rel="stylesheet" integrity="sha384-Kxw/5TXm6N3RHnfs61s9T51oEX9svegYJ+k7D7CEBi+UkiDFKR0UJPd1vCRKkpD4">
+    <link href="styles2.css?14c217a379e00324" rel="stylesheet" integrity="sha384-debHmHz4j3OVP8XwFi6CwbUC8eO7ywH+jHQIZBj5yK8MrBd8ZHzm5nR+CCAbhVMi">
 </head>
 
 <body>
     <h1>Test</h1>
-    <script src="script.js"></script>
-    <script>
-        console.log("Hello world from an inline script!");
-    </script>
+    <script src="script.js?ac5b60349abad073" integrity="sha384-G8jfQwKJiDSJqbfHwdgRD0BnU25phD0D3GvhDkEOrFy0e/6pVvduKyfg3+BwLXeN"></script>
+    <script src="script2.js?8e5cd755d8d444f2" integrity="sha384-iutpq87ZotclarBPMYz6s4nA4xmvaJOs6zucEwXTi0zgwvdmK7xo79OwrZ9OWkoc"></script>
 </body>

styles2.css

+
+        body {
+            background-color: lightblue;
+        }
+    

script2.js

+
+        console.log("Hello world from an inline script!");
+    

Installing

cargo install --git https://git.legoktm.com/legoktm/resource-rewriter

Usage

$ resource-rewriter --help
Usage: resource-rewriter [OPTIONS] <PATH>

Arguments:
  <PATH>  Folder to rewrite resources in

Options:
      --diff                   Print diff for each change
      --dry-run                Don't make changes, best used with `--diff`
      --disable-cache-busting  Disable addition of cache busting URL parameters
  -h, --help                   Print help
  -V, --version                Print version

It'll process all HTML files, move any inline scripts and styles to separate files, calculate and set SRI hashes and cache busting URL parameters.

Architecture

We use the lol-html crate to rewrite the HTML in three passes.

  1. Copy any content in inline <script> and <style> tags to individual files.
  2. Remove the content from those inline tags and turn <style> into <link rel="stylesheet">.
  3. Calculate SRI hashes and cache busting URL parameters.

The separate passes are mostly to work around limitations in lol-html, namely directly accessing the text content of tags.

No benchmarking or performance optimizations have been performed yet.

Security

Please use caution when using this with untrusted input. While it should work fine, it has not explicitly been tested against adversarial input and may contain bugs.

License

GPL-3.0-or-later

Dependencies

~12–21MB
~343K SLoC