From dfeffdef2b605cf61b4d0e8c1c2278650754e2ac Mon Sep 17 00:00:00 2001 From: Pagwin Date: Thu, 25 Dec 2025 23:24:33 -0500 Subject: [PATCH] beginning work on CSS and JS minification --- TODO.md | 4 ++++ psb.cabal | 4 ++-- src/Config.hs | 15 ++++++++++++++- src/Psb/Main.hs | 19 +++++++++++++++++++ src/Utilities/CSS.hs | 7 +++++++ src/Utilities/Javascript.hs | 7 +++++++ 6 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/Utilities/CSS.hs create mode 100644 src/Utilities/Javascript.hs diff --git a/TODO.md b/TODO.md index 08da2cf..a92db33 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,8 @@ - [ ] minify js and css when copying over instead of just copying + - CSS + - https://github.com/wereHamster/haskell-css-syntax + - JS + - https://hackage.haskell.org/package/language-ecmascript - [ ] setup fingerprinting in file names for css and js - [ ] process source code blocks to syntax highlight them - tree sitter https://hackage.haskell.org/package/tree-sitter diff --git a/psb.cabal b/psb.cabal index 5291381..8dd324a 100644 --- a/psb.cabal +++ b/psb.cabal @@ -27,8 +27,8 @@ common warnings library hs-source-dirs: src - exposed-modules: Markdown HTML Logger IR Logger.Shake Psb.Main Utilities Utilities.FilePath Utilities.Action Templates Types Config - build-depends: base >=4.20 && < 4.21, mustache >=2.4.2, shake >= 0.19.8, deriving-aeson >= 0.2.9, aeson, text >= 2.1.2, time, unordered-containers, yaml, megaparsec >= 9.7.0, transformers >= 0.6.2 + exposed-modules: Markdown HTML Logger IR Logger.Shake Psb.Main Utilities Utilities.FilePath Utilities.Action Utilities.Javascript Utilities.CSS Templates Types Config + build-depends: base >=4.20 && < 4.21, mustache >=2.4.2, shake >= 0.19.8, deriving-aeson >= 0.2.9, aeson, text >= 2.1.2, time, unordered-containers, yaml, megaparsec >= 9.7.0, transformers >= 0.6.2, css-syntax >= 0.1.0.2, language-ecmascript >= 0.19.1.0 default-extensions: ApplicativeDo DataKinds NamedFieldPuns DerivingVia LambdaCase TypeApplications DeriveGeneric OverloadedRecordDot NamedFieldPuns DuplicateRecordFields DisambiguateRecordFields FlexibleInstances test-suite test-markdown-parse diff --git a/src/Config.hs b/src/Config.hs index f808665..97c05e4 100644 --- a/src/Config.hs +++ b/src/Config.hs @@ -4,7 +4,20 @@ outputDir :: String outputDir = "publish" assetGlobs :: [String] -assetGlobs = ["static//*", "robots.txt", "sw.js", "favicon.ico"] +assetGlobs = ["static//*", "robots.txt", "favicon.ico"] + +-- this insanity is to avoid repetition +resourceGlobs :: [String] +resourceGlobs = jsGlobs ++ cssGlobs + +prependResources :: (Functor m) => m String -> m String +prependResources = fmap ("resources/" ++) + +jsGlobs :: [String] +jsGlobs = prependResources $ liftA2 (++) ["js//*."] ["js", "mjs"] + +cssGlobs :: [String] +cssGlobs = prependResources $ liftA2 (++) ["css//*."] ["css"] -- CAN ONLY BE TYPST DOCS UNLESS YOU CHANGE THINGS AT THE `pages` RULE in `Main.hs pagePaths :: [String] diff --git a/src/Psb/Main.hs b/src/Psb/Main.hs index 355747a..b10ae18 100644 --- a/src/Psb/Main.hs +++ b/src/Psb/Main.hs @@ -23,7 +23,9 @@ import qualified Development.Shake.FilePath as FP import Templates import Types import Utilities.Action (getPublishedPosts, isDraft', markdownToHtml, markdownToPost, now, psbProgress) +import qualified Utilities.CSS as CSS import Utilities.FilePath (indexHtmlOutputPath, indexHtmlSourcePaths, isMarkdownPost, urlConvert) +import qualified Utilities.Javascript as JS -- target = thing we want -- Rule = pattern of thing being made + actions to produce the thing @@ -51,6 +53,9 @@ buildSite = do -- path concat each asset path so it's output into the outputDir Shake.need $ map (outputDir ) assetPaths + -- handle js, css and anything else we want to process before moving + Shake.need <$> Shake.getDirectoryFiles "" resourceGlobs + -- take the misc pages which aren't blog posts and make their html files Shake.need $ map indexHtmlOutputPath pagePaths @@ -67,6 +72,8 @@ buildRules = do assets postsRule rss + css_resources + js_resources -- make a rule of the pattern outputDir/asset_name which copes from outputDir/../pages assets :: Rules () @@ -75,6 +82,18 @@ assets = let src = FP.dropDirectory1 target Shake.copyFileChanged src target +css_resources :: Rules () +css_resources = + map (outputDir ) cssGlobs |%> \target -> do + src <- Shake.readFile' $ FP.dropDirectory1 target + Shake.writeFileChanged target $ CSS.minify src + +js_resources :: Rules () +js_resources = + map (outputDir ) jsGlobs |%> \target -> do + src <- Shake.readFile' $ FP.dropDirectory1 target + Shake.writeFileChanged target $ JS.minify src + -- there's probably a better way of doing this that allows for the target's origin file extension to get passed in but for now we're doing brute force postsRule :: Rules () postsRule = diff --git a/src/Utilities/CSS.hs b/src/Utilities/CSS.hs new file mode 100644 index 0000000..a278229 --- /dev/null +++ b/src/Utilities/CSS.hs @@ -0,0 +1,7 @@ +module Utilities.CSS + ( minify, + ) +where + +minify :: String -> String +minify = id diff --git a/src/Utilities/Javascript.hs b/src/Utilities/Javascript.hs new file mode 100644 index 0000000..9f84230 --- /dev/null +++ b/src/Utilities/Javascript.hs @@ -0,0 +1,7 @@ +module Utilities.Javascript + ( minify, + ) +where + +minify :: String -> String +minify = id