From 6660b0dc2a6e32aa4c4aec910a6a08bf8bb1e807 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Tue, 30 Jun 2026 17:25:50 -0400 Subject: fix(markdown): vendor strapdown.js instead of a plain-HTTP CDN The live markdown preview pulled strapdown.js from http://ndossougbe.github.io over plain HTTP. That broke the preview with no network, loaded third-party JS over an unencrypted connection (mixed content, MITM), and trusted an unmaintained github.io page against the localhost preview. I vendored the self-contained bundle (jQuery, marked, bootstrap themes) into assets/strapdown.js and embed it inline. The whole preview now serves from localhost and works offline. cj/markdown-html reads the file once and caches it. --- modules/markdown-config.el | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'modules/markdown-config.el') diff --git a/modules/markdown-config.el b/modules/markdown-config.el index 4b6c9947d..cb37556f7 100644 --- a/modules/markdown-config.el +++ b/modules/markdown-config.el @@ -70,10 +70,34 @@ lives in a separate command." ;; rendered. (browse-url "http://localhost:8080/imp")) +;; strapdown.js renders the markdown client-side. It is vendored under +;; assets/ and embedded inline rather than loaded from +;; http://ndossougbe.github.io/strapdown/dist/strapdown.js: the CDN was plain +;; HTTP (mixed content), an unmaintained third-party github.io page (a +;; supply-chain and MITM surface), and made the preview fail with no network. +;; The bundle (jQuery + marked + bootstrap themes) is self-contained, so inlining +;; it serves the whole preview from localhost. Refresh by re-downloading the +;; dist build into assets/strapdown.js. +(defconst cj/markdown--strapdown-file + (expand-file-name "assets/strapdown.js" user-emacs-directory) + "Path to the vendored strapdown.js bundle served with the markdown preview.") + +(defvar cj/markdown--strapdown-cache nil + "Cached contents of `cj/markdown--strapdown-file', read once on first preview.") + +(defun cj/markdown--strapdown-js () + "Return the vendored strapdown.js source, reading and caching it once." + (or cj/markdown--strapdown-cache + (setq cj/markdown--strapdown-cache + (with-temp-buffer + (insert-file-contents-literally cj/markdown--strapdown-file) + (buffer-string))))) + (defun cj/markdown-html (buffer) (princ (with-current-buffer buffer - (format "Impatient Markdown %s " - (buffer-substring-no-properties (point-min) (point-max)))) + (format "Impatient Markdown %s " + (buffer-substring-no-properties (point-min) (point-max)) + (cj/markdown--strapdown-js))) (current-buffer))) ;; Bind the preview key after the defun so use-package's `:bind' autoload -- cgit v1.2.3