diff --git a/src/routes/about.lisp b/src/routes/about.lisp index d3d9d30..6ef2e24 100644 --- a/src/routes/about.lisp +++ b/src/routes/about.lisp @@ -1,7 +1,7 @@ (defpackage #:hp/routes/about (:use #:cl) (:local-nicknames (#:pi #:piccolo)) - (:local-nicknames (#:view #:hp/view)) + (:local-nicknames (#:view #:hp/view/*)) (:export #:handle-get)) (in-package #:hp/routes/about) diff --git a/src/routes/index.lisp b/src/routes/index.lisp index 525ac0a..10b0618 100644 --- a/src/routes/index.lisp +++ b/src/routes/index.lisp @@ -1,7 +1,7 @@ (defpackage #:hp/routes/index (:use #:cl) (:local-nicknames (#:pi #:piccolo)) - (:local-nicknames (#:view #:hp/view)) + (:local-nicknames (#:view #:hp/view/*)) (:export #:handle-get)) (in-package #:hp/routes/index) diff --git a/src/routes/not-found.lisp b/src/routes/not-found.lisp index 3078a05..f6c7f31 100644 --- a/src/routes/not-found.lisp +++ b/src/routes/not-found.lisp @@ -2,7 +2,7 @@ (:use #:cl) (:local-nicknames (#:jg #:jingle)) (:local-nicknames (#:pi #:piccolo)) - (:local-nicknames (#:view #:hp/view)) + (:local-nicknames (#:view #:hp/view/*)) (:export #:handle-not-found)) (in-package #:hp/routes/not-found) diff --git a/src/view.lisp b/src/view.lisp deleted file mode 100644 index 8719b37..0000000 --- a/src/view.lisp +++ /dev/null @@ -1,56 +0,0 @@ -(defpackage #:hp/view - (:use #:cl) - (:local-nicknames (#:jg #:jingle)) - (:local-nicknames (#:pi #:piccolo)) - (:local-nicknames (#:re #:cl-ppcre)) - (:export #:render)) -(in-package #:hp/view) - -(defun detect-data-cmps (page-str) - (remove-duplicates (cl-ppcre:all-matches-as-strings "(?<=data-cmp=\")[^\"]*(?=\")" - page-str) - :test #'string=)) - -(defun data-cmps->style-hrefs (data-cmps) - (mapcar (lambda (cmp-name) - (concatenate 'string "/styles/" cmp-name ".css")) - data-cmps)) - -(pi:define-element on-demand-stylesheets (hrefs) - (pi:h - (<> '() - (mapcar (lambda (href) - (link :rel "stylesheet" :type "text/css" :href href)) - hrefs)))) - -(pi:define-element document (title description style-hrefs) - (pi:h - (html :lang "ja" - (head - (meta :charset "UTF-8") - (script :src "/scripts/htmx.js") - (script :src "/scripts/htmx-ext/head-support.js") - (script :src "/scripts/alpine.js" :defer t) - (link :rel "stylesheet" :type "text/css" :href "/styles/ress.css") - (link :rel "stylesheet" :type "text/css" :href "/styles/global.css") - (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") - (title (format nil "~@[~a - ~]skyizwhite.dev" title)) - (meta - :name "description" - :content (or description "pakuの個人サイト")) - (on-demand-stylesheets :hrefs style-hrefs)) - (body :hx-ext "head-support" - (main pi:children))))) - -(defun render (page &key status metadata) - (jg:with-html-response - (and status (jg:set-response-status status)) - (let* ((page-str (pi:elem-str page)) - (style-hrefs (data-cmps->style-hrefs (detect-data-cmps page-str)))) - (pi:elem-str - (document `(,@metadata :style-hrefs ,style-hrefs) - page))))) diff --git a/src/view/optimizer.lisp b/src/view/optimizer.lisp new file mode 100644 index 0000000..c86df4e --- /dev/null +++ b/src/view/optimizer.lisp @@ -0,0 +1,18 @@ +(defpackage #:hp/view/optimizer + (:use #:cl) + (:local-nicknames (#:re #:cl-ppcre)) + (:export #:collect-style-links)) +(in-package #:hp/view/optimizer) + +(defun detect-components (page-str) + (remove-duplicates (re:all-matches-as-strings "(?<=data-cmp=\")[^\"]*(?=\")" + page-str) + :test #'string=)) + +(defun components->stylesheets (data-cmps) + (mapcar (lambda (cmp-name) + (concatenate 'string "/styles/" cmp-name ".css")) + data-cmps)) + +(defun collect-style-links (page-str) + (components->stylesheets (detect-components page-str))) diff --git a/src/view/renderer.lisp b/src/view/renderer.lisp new file mode 100644 index 0000000..825408d --- /dev/null +++ b/src/view/renderer.lisp @@ -0,0 +1,59 @@ +(defpackage #:hp/view/renderer + (:use #:cl) + (:local-nicknames (#:jg #:jingle)) + (:local-nicknames (#:pi #:piccolo)) + (:local-nicknames (#:opt #:hp/view/optimizer)) + (:export #:render + #:partial-render)) +(in-package #:hp/view/renderer) + +(pi:define-element stylesheets (hrefs) + (pi:h + (<> '() + (mapcar (lambda (href) + (link :rel "stylesheet" :type "text/css" :href href)) + hrefs)))) + +(pi:define-element document (title description) + (let* ((children-str (pi:elem-str pi:children)) + (style-links (opt:collect-style-links children-str))) + (pi:h + (html :lang "ja" + (head + (meta :charset "UTF-8") + (script :src "/scripts/htmx.js") + (script :src "/scripts/htmx-ext/head-support.js") + (script :src "/scripts/alpine.js" :defer t) + (link :rel "stylesheet" :type "text/css" :href "/styles/ress.css") + (link :rel "stylesheet" :type "text/css" :href "/styles/global.css") + (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") + (title (format nil "~@[~a - ~]skyizwhite.dev" title)) + (meta + :name "description" + :content (or description "pakuの個人サイト")) + (stylesheets :hrefs style-links)) + (body :hx-ext "head-support" + (main pi:children)))))) + +(pi:define-element assets-provider () + (let* ((child-str (pi:elem-str pi:children)) + (style-links (opt:collect-style-links child-str))) + (pi:h + (<> + (head :hx-head "append" + (stylesheets :hrefs style-links)) + pi:children)))) + +(defun render (page &key status metadata) + (jg:with-html-response + (and status (jg:set-response-status status)) + (pi:elem-str (document metadata page)))) + +(defun partial-render (component &key status) + (jg:with-html-response + (and status (jg:set-response-status status)) + (pi:elem-str (assets-provider component))))