diff --git a/src/app.lisp b/src/app.lisp index 213fb90..1e608ab 100644 --- a/src/app.lisp +++ b/src/app.lisp @@ -4,6 +4,7 @@ (:local-nicknames (#:jg #:jingle)) (:local-nicknames (#:fbr #:ningle-fbr)) (:local-nicknames (#:cfg #:hp/config/*)) + (:local-nicknames (#:asset #:hp/view/asset)) (:local-nicknames (#:mw #:hp/middlewares/*)) (:export #:start #:stop @@ -25,8 +26,8 @@ (fbr:assign-routes *app* :system "hp" :directory "src/routes") - (jg:static-path *app* (cfg:asset-root :script) "src/scripts/") - (jg:static-path *app* (cfg:asset-root :style) "src/styles/") + (jg:static-path *app* (asset:asset-root :script) "src/scripts/") + (jg:static-path *app* (asset:asset-root :style) "src/styles/") (jg:install-middleware *app* mw:*public-files*) (jg:install-middleware *app* mw:*recovery*) (jg:install-middleware *app* mw:*normalize-path*) diff --git a/src/config/asset.lisp b/src/config/asset.lisp deleted file mode 100644 index 89e9f44..0000000 --- a/src/config/asset.lisp +++ /dev/null @@ -1,16 +0,0 @@ -(defpackage #:hp/config/asset - (:use #:cl) - (:export #:asset-root - #:asset-path)) -(in-package #:hp/config/asset) - -(defparameter *asset-roots* - (list :style "/styles/" - :script "/scripts/" - :vendor "/vendor/")) - -(defun asset-root (destination) - (getf *asset-roots* destination)) - -(defun asset-path (destination path) - (concatenate 'string (asset-root destination) path)) diff --git a/src/view/asset.lisp b/src/view/asset.lisp index e8eeb9e..41b8f6d 100644 --- a/src/view/asset.lisp +++ b/src/view/asset.lisp @@ -1,11 +1,62 @@ (defpackage #:hp/view/asset (:use #:cl) (:local-nicknames (#:re #:cl-ppcre)) - (:local-nicknames (#:cfg #:hp/config/asset)) - (:export #:get-css-links + (:export #:*ress* + #:*global-css* + #:*global-js* + #:*htmx* + #:*htmx-extentions* + #:*alpine* + #:*alpine-extentions* + #:asset-root + #:get-css-paths #:asset-props)) (in-package #:hp/view/asset) +(defparameter *asset-roots* + '(:style "/styles/" + :script "/scripts/" + :vendor "/vendor/" + :htmx-ext "/vendor/htmx-ext/" + :alpine-ext "/vendor/alpine-ext/")) + +(defun asset-root (group) + (getf *asset-roots* group)) + +(defun asset-path (group path) + (concatenate 'string (asset-root group) path)) + +(defun asset-path-under (root) + (lambda (ext) + (asset-path root ext))) + +(defmacro define-asset (name root &body files) + `(defparameter ,name + ,(if (rest files) + `(mapcar (asset-path-under ,root) ',files) + `(funcall (asset-path-under ,root) ,(car files))))) + +(define-asset *ress* :vendor + "ress@5.0.2.css") +(define-asset *global-css* :style + "global.css") + +(define-asset *global-js* :script + "global.js") + +(define-asset *htmx* :vendor + "htmx@1.9.12.js") +(define-asset *htmx-extentions* :htmx-ext + "alpine-morph@1.9.12.js" + "head-support@1.9.12.js") + +(define-asset *alpine* :vendor + "alpine@3.13.8.js") +(define-asset *alpine-extentions* :alpine-ext + "async-alpine@1.2.2.js" + "persist@3.13.8.js" + "morph@3.13.8.js") + (defun detect-data-props (html-str data-prop-name) (remove-duplicates (re:all-matches-as-strings (format nil "(?<=~a=\")[^\"]*(?=\")" @@ -13,15 +64,15 @@ html-str) :test #'string=)) -(defun get-css-links (html-str) +(defun get-css-paths (html-str) (mapcar (lambda (data-prop) - (cfg:asset-path :style data-prop)) + (asset-path :style data-prop)) (detect-data-props html-str "data-style"))) (defun asset-props (&key style script x-data) (append (and style `(:data-style ,style)) (and script x-data `(:ax-load t - :ax-load-src ,(cfg:asset-path :script script) + :ax-load-src ,(asset-path :script script) :x-ignore t :x-data ,x-data)))) diff --git a/src/view/components/document.lisp b/src/view/components/document.lisp index 207105e..c8a1781 100644 --- a/src/view/components/document.lisp +++ b/src/view/components/document.lisp @@ -2,51 +2,64 @@ (:use #:cl) (:local-nicknames (#:pi #:piccolo)) (:local-nicknames (#:asset #:hp/view/asset)) - (:local-nicknames (#:cfg #:hp/config/asset)) (:export #:document #:partial-document)) (in-package #:hp/view/components/document) (pi:define-element on-demand-stylesheets () - (let* ((html-str (pi:elem-str pi:children)) - (css-links (asset:get-css-links html-str))) + (let* ((pi:*escape-html* nil) + (html-str (pi:elem-str pi:children)) + (css-paths (asset:get-css-paths html-str))) (pi:h (<> - (mapcar (lambda (href) - (link :rel "stylesheet" :type "text/css" :href href)) - css-links))))) + (mapcar (lambda (path) + (link :rel "stylesheet" :type "text/css" :href path)) + css-paths))))) -(pi:define-element document (title description) +(pi:define-element stylesheets () + (pi:h + (<> + (link :rel "stylesheet" :type "text/css" :href asset:*ress*) + (link :rel "stylesheet" :type "text/css" :href asset:*global-css*) + (on-demand-stylesheets pi:children) + (link :rel "preconnect" :href "https://fonts.googleapis.com") + (link :rel "preconnect" :href "https://fonts.gstatic.com" :crossorigin t) + (link + :rel "stylesheet" + :href "https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap")))) + +(pi:define-element extentions (paths defer) + (pi:h + (<> + (mapcar (lambda (path) + (script :src path :defer defer)) + paths)))) + +(pi:define-element scripts () + (pi:h + (<> + (script :src asset:*htmx*) + (extentions :paths asset:*htmx-extentions*) + (extentions :paths asset:*alpine-extentions* :defer t) + (script :src asset:*global-js* :defer t) + (script :src asset:*alpine* :defer t)))) + +(pi:define-element seo (title description) + (pi:h + (<> + (title (format nil "~@[~a - ~]skyizwhite.dev" title)) + (meta + :name "description" + :content (or description "pakuの個人サイト"))))) + +(pi:define-element document (metadata) (pi:h (html :lang "ja" (head (meta :charset "UTF-8") - (link - :rel "stylesheet" - :type "text/css" - :href (cfg:asset-path :vendor "ress@5.0.2.css")) - (link - :rel "stylesheet" - :type "text/css" - :href (cfg:asset-path :style "global.css")) - (on-demand-stylesheets pi:children) - (link :rel "preconnect" :href "https://fonts.googleapis.com") - (link :rel "preconnect" :href "https://fonts.gstatic.com" :crossorigin t) - (link - :rel "stylesheet" - :href "https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap") - (script :src (cfg:asset-path :vendor "htmx@1.9.12.js")) - (script :src (cfg:asset-path :vendor "htmx-ext/alpine-morph@1.9.12.js")) - (script :src (cfg:asset-path :vendor "htmx-ext/head-support@1.9.12.js")) - (script :src (cfg:asset-path :vendor "alpine-ext/async-alpine@1.2.2.js") :defer t) - (script :src (cfg:asset-path :vendor "alpine-ext/persist@3.13.8.js") :defer t) - (script :src (cfg:asset-path :vendor "alpine-ext/morph@3.13.8.js") :defer t) - (script :src (cfg:asset-path :script "global.js") :defer t) - (script :src (cfg:asset-path :vendor "alpine@3.13.8.js") :defer t) - (title (format nil "~@[~a - ~]skyizwhite.dev" title)) - (meta - :name "description" - :content (or description "pakuの個人サイト"))) + (stylesheets pi:children) + (scripts) + (seo metadata)) pi:children))) (pi:define-element partial-document () diff --git a/src/view/renderer.lisp b/src/view/renderer.lisp index 995d5c4..a8c6016 100644 --- a/src/view/renderer.lisp +++ b/src/view/renderer.lisp @@ -10,7 +10,7 @@ (defun render (page &key status metadata) (jg:with-html-response (if status (jg:set-response-status status)) - (pi:elem-str (cmp:document metadata + (pi:elem-str (cmp:document :metadata metadata (cmp:layout page))))) (defun partial-render (component &key status)