From f50d8f9d69c74a5cc4de0d95d83d5488181500e3 Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Tue, 30 Sep 2025 19:01:59 +0200 Subject: [PATCH] fixed stuff included a fully working downloader for webpages which inlines the css / js. images do not work because they are hosted on the server --- .gitignore | 3 ++- html/base/template.html | 15 +++++++++-- js/post/download.js | 56 ++++++++++++++++++++++++++++++++--------- webserver.py | 10 ++++---- 4 files changed, 64 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index bb5b095..7cee265 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ __pycache__ env target -Cargo.lock \ No newline at end of file +Cargo.lock +.idea \ No newline at end of file diff --git a/html/base/template.html b/html/base/template.html index c6ecaed..f2997e7 100644 --- a/html/base/template.html +++ b/html/base/template.html @@ -16,6 +16,10 @@ + + + + @@ -50,8 +54,15 @@ Hash2 Hash 2 (Windows-1252):{{ hash2 }}
- Hash2 - Download as Markdown + + Save + Download as Markdown + + + + Script + Download as HTML + diff --git a/js/post/download.js b/js/post/download.js index 9e050b5..7b25acf 100644 --- a/js/post/download.js +++ b/js/post/download.js @@ -1,18 +1,50 @@ document.addEventListener("DOMContentLoaded", () => { - // current page URL - let url = window.location.href; + const htmlDownload = document.getElementById("download-html"); - // replace `/html/` with `/markdown/` - url = url.replace("/html/", "/markdown/"); + htmlDownload.addEventListener("click", async (e) => { + e.preventDefault(); - // replace `.html` with `.md` - url = url.replace(/\.html$/, ".md"); + const linkElements = document.querySelectorAll('link[rel="stylesheet"]'); + for (const link of linkElements) { + const href = link.getAttribute("href"); + try { + const res = await fetch(href); + const cssText = await res.text(); + const styleEl = document.createElement("style"); + styleEl.textContent = cssText; + document.head.appendChild(styleEl); + link.remove(); // remove original link + } catch (err) { + console.error("Failed to inline CSS:", href, err); + } + } - // assign to - const a = document.getElementById("download-md"); - a.href = url; + const scriptElements = document.querySelectorAll('script[src]'); + for (const script of scriptElements) { + const src = script.getAttribute("src"); + try { + const res = await fetch(src); + const jsText = await res.text(); + const inlineScript = document.createElement("script"); + inlineScript.textContent = jsText; + document.body.appendChild(inlineScript); + script.remove(); // remove original script + } catch (err) { + console.error("Failed to inline JS:", src, err); + } + } - // suggest filename - const filename = url.split("/").pop(); // e.g. markdowntest.md - a.download = filename; + const htmlContent = document.documentElement.outerHTML; + + const blob = new Blob([htmlContent], { type: "text/html" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = "index.html"; // or derive from URL + document.body.appendChild(a); + a.click(); + a.remove(); + setTimeout(() => URL.revokeObjectURL(url), 1000); + }); }); + diff --git a/webserver.py b/webserver.py index 714b2ed..acc4c2c 100644 --- a/webserver.py +++ b/webserver.py @@ -139,8 +139,8 @@ class MyHandler(BaseHTTPRequestHandler): logger.log_info(f"Served markdown file: {markdown_filename}") return - except Exception as e: - logger.log_error(f"Error serving markdown file {markdown_filename}: {e}") + except Exception as err: + logger.log_error(f"Error serving markdown file {markdown_filename}: {err}") self.send_response(500) self.end_headers() self.wfile.write(b"500 - Internal Server Error") @@ -166,8 +166,8 @@ class MyHandler(BaseHTTPRequestHandler): if mime_type == "application/javascript" or file_path.endswith(".js"): try: content = jsmin(content.decode("utf-8")).encode("utf-8") - except Exception as e: - logger.log_error(f"Error minifying JS file {file_path}: {e}") + except Exception as err: + logger.log_error(f"Error minifying JS file {file_path}: {err}") self.send_response(200) self.send_header("Content-type", mime_type) @@ -190,7 +190,7 @@ if __name__ == "__main__": logger.log_debug("Started PyPost.py in background watcher thread.") server_address = ("localhost", 8000) - httpd = HTTPServer(server_address, MyHandler) + httpd: HTTPServer = HTTPServer(server_address, MyHandler) # type: ignore[arg-type] logger.log_info(f"Serving on http://{server_address[0]}:{server_address[1]}") httpd.serve_forever() except (Exception, KeyboardInterrupt) as e: