moving injected styles to a static .css file
Table of Contents
Intro
prelim: this is a following my css-in-cljs method from my garden css has ascended, which was exceptionally good for the first draft/version of the project but eventually should cede to normal CSS once you are ready for hardening the product. The goal here is to remove all the per-html CSS rules that were so perfect for Dev with a single CSS file that can be called from all the html files in the project and is both far more efficient file-size wise, and the Right Way™ to do it for caching and synchronization. Asking online people1 made a good point: rather than trying to write a funky sed or awt script to do this, emacs is well positioned because it knows the syntax and it has good file-navigation facilities.
First, Create a git branch for this work in my project
Magit is great for this. For any project of a less then 1000 text (ie html) files, git is irreplaceable for managing text-replacements or project-wide refactoring.
in-browser grab the latest injected styles
Paste them into a new file for referencing in the HTML of your project. I positioned mine at /css/fonetica.css
.
Replace all in-file style definitions from the html with a distinctive string
I used html macros combined with dired for this.
init the html file list with find-name-dired
In dired of our root-of-the-html directory, I ran find-name-dired
with to list only and all the HTML files regardless of whether they were nested.
From that list view, begin recording the macro
To explain what you see above in the gif above,: I press <f3>
to start the macro recording. Thun <RET>
to visit the file, search with C-s
for <style
2 and, upon finding it, use <RET>
to finish the search and then M-b C-b
to place me right before the word “style” and one more C-b
to put my cursor right before the <
. Then CCSSZZ =(set-mark-command)
to start marking, C-M-f
3 to navigate to the end of the <style>
tag, and C-w
(kill-region
) to remove it. Then I type in my distinct key. I used CSSZZ
. Then, I save the buffer C-x C-s
and go back to my dired listing. I move my cursor down to the next file, and then I hit <f4>
to conclude my macro. It is now in a repeatable state so, checking if it works correctly, I then do M 0 <f4>
to run it until it can’t run anymore – making changes to all my html files.
Double-check in git that the changes are as desired
Check the git status, which is a good idea whenever you are doing bult operations in a project, to make sure all the changes are there and are what you expect them to be. You can commit these to ensure a nice save-point in your process.
Run find/sed on the static html files to replace the code with the link
Notice the use of single quoties in the sed parts of the command, so that I can freely define double-quotied HTML syntax (unlike the shell, HTML doesn’t distinguish between single quotes and double quotes).
find . -type f -name "*.html" -print0 | xargs -0 sed -i '' -e 'sCSSZZ
@<link rel="stylesheet" href="/css/fonetica.css"/>@g'
Double-check in git that the changes are as desired
Git is such a life-saver, and now the static site refactoring is even more static and has the benefits thereof.
Bonus: make the css-in-cljs only for dev mode
I will want the rapidity of my css-dev to still work for any future dev work. The following makes the serverless code only use the css-in-cljs when in dev (repl-driven) mode.
(defn init! []
(routes/init-routes!)
(mount-components)
(when goog.DEBUG ;; use cljs styles for styles in dev
(println "DEV: We are generating styles in CLJS")
(style/mount-style (style/fonetica))))
Footnotes
1 The little conversation is on reddit here https://www.reddit.com/r/emacs/comments/11xpwlx/bulk_multiline_findandreplace/
2 since smart completion tools like vertico and helm play havoc with macro, it is really helpful to preload your search so that C-s C-s
searches for the last search, which I want to be <style
. Then I don’t need to use the completion for the isearch.
3 For me this is puni-forward-sexp
but there is the built in forward-sexp
on the same key that should work fine.