Improved page navigation and import of on-demand assets
This commit is contained in:
parent
a0a680c8d2
commit
4663341497
14 changed files with 248 additions and 55 deletions
src
routes
scripts/pages
styles/pages
view
|
@ -11,10 +11,14 @@
|
|||
|
||||
(pi:define-element page ()
|
||||
(pi:h
|
||||
(section :data-css "pages/about"
|
||||
(section (view:asset-props :style "pages/about"
|
||||
:script "pages/about"
|
||||
:x-data "aboutPageState")
|
||||
(h1 "About")
|
||||
(a :href "/"
|
||||
"top"))))
|
||||
(a :href "/" :hx-boost "true"
|
||||
"top")
|
||||
(button :@click "decrement()"
|
||||
(span :x-text "count")))))
|
||||
|
||||
(defun handle-get (params)
|
||||
(declare (ignore params))
|
||||
|
|
|
@ -7,13 +7,18 @@
|
|||
|
||||
(pi:define-element page ()
|
||||
(pi:h
|
||||
(section :data-css "pages/index"
|
||||
(section (view:asset-props :style "pages/index"
|
||||
:script "pages/index"
|
||||
:x-data "indexPageState")
|
||||
(h1
|
||||
"Hello, World!")
|
||||
(a :href "/about"
|
||||
(a :href "/about" :hx-boost "true"
|
||||
"About")
|
||||
(button :x-data t :@click "$store.darkMode.toggle()"
|
||||
"Toggle theme"))))
|
||||
"Toggle theme")
|
||||
(button
|
||||
:@click "increment()"
|
||||
(span :x-text "count")))))
|
||||
|
||||
(defun handle-get (params)
|
||||
(declare (ignore params))
|
||||
|
|
9
src/scripts/pages/about.js
Normal file
9
src/scripts/pages/about.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
export function aboutPageState() {
|
||||
return {
|
||||
count: 0,
|
||||
|
||||
decrement() {
|
||||
this.count--
|
||||
}
|
||||
}
|
||||
}
|
9
src/scripts/pages/index.js
Normal file
9
src/scripts/pages/index.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
export function indexPageState() {
|
||||
return {
|
||||
count: 0,
|
||||
|
||||
increment() {
|
||||
this.count++
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
@scope ([data-css='pages/about']) {
|
||||
@scope ([data-style='pages/about']) {
|
||||
:scope {
|
||||
height: 100svh;
|
||||
display: grid;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@scope ([data-css='pages/index']) {
|
||||
@scope ([data-style='pages/index']) {
|
||||
:scope {
|
||||
height: 100svh;
|
||||
display: grid;
|
||||
|
|
31
src/view/asset.lisp
Normal file
31
src/view/asset.lisp
Normal file
|
@ -0,0 +1,31 @@
|
|||
(defpackage #:hp/view/asset
|
||||
(:use #:cl)
|
||||
(:local-nicknames (#:re #:cl-ppcre))
|
||||
(:export #:get-css-links
|
||||
#:asset-props))
|
||||
(in-package #:hp/view/asset)
|
||||
|
||||
(defun detect-data-props (html-str data-prop-name)
|
||||
(remove-duplicates (re:all-matches-as-strings (format nil
|
||||
"(?<=~a=\")[^\"]*(?=\")"
|
||||
data-prop-name)
|
||||
html-str)
|
||||
:test #'string=))
|
||||
|
||||
(defun data-props->asset-links (parent-path extension data-props)
|
||||
(mapcar (lambda (data-prop)
|
||||
(concatenate 'string parent-path data-prop extension))
|
||||
data-props))
|
||||
|
||||
(defun get-css-links (html-str)
|
||||
(data-props->asset-links "/styles/"
|
||||
".css"
|
||||
(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 ,(format nil "/scripts/~a.js" script)
|
||||
:x-ignore t
|
||||
:x-data ,x-data))))
|
|
@ -1,55 +1,19 @@
|
|||
(defpackage #:hp/view/components/document
|
||||
(:use #:cl)
|
||||
(:local-nicknames (#:re #:cl-ppcre))
|
||||
(:local-nicknames (#:pi #:piccolo))
|
||||
(:export #:document))
|
||||
(:local-nicknames (#:asset #:hp/view/asset))
|
||||
(:export #:document
|
||||
#:partial-document))
|
||||
(in-package #:hp/view/components/document)
|
||||
|
||||
(defun detect-data-props (html-str data-prop-name)
|
||||
(remove-duplicates (re:all-matches-as-strings (format nil
|
||||
"(?<=~a=\")[^\"]*(?=\")"
|
||||
data-prop-name)
|
||||
html-str)
|
||||
:test #'string=))
|
||||
|
||||
(defun data-props->asset-links (parent-path extension data-props)
|
||||
(mapcar (lambda (data-prop)
|
||||
(concatenate 'string parent-path data-prop extension))
|
||||
data-props))
|
||||
|
||||
(defun get-css-links (html-str)
|
||||
(data-props->asset-links "/styles/"
|
||||
".css"
|
||||
(detect-data-props html-str "data-css")))
|
||||
|
||||
(defun get-js-links (html-str)
|
||||
(data-props->asset-links "/scripts/"
|
||||
".js"
|
||||
(detect-data-props html-str "data-js")))
|
||||
|
||||
(pi:define-element scripts (srcs)
|
||||
(pi:h
|
||||
(<>
|
||||
(mapcar (lambda (src)
|
||||
(script :src src :defer t))
|
||||
srcs))))
|
||||
|
||||
(pi:define-element stylesheets (hrefs)
|
||||
(pi:h
|
||||
(<>
|
||||
(mapcar (lambda (href)
|
||||
(link :rel "stylesheet" :type "text/css" :href href))
|
||||
hrefs))))
|
||||
|
||||
(pi:define-element on-demand-assets (component)
|
||||
(let* ((pi:*escape-html* nil)
|
||||
(html-str (pi:elem-str component))
|
||||
(css-links (get-css-links html-str))
|
||||
(js-links (get-js-links html-str)))
|
||||
(pi:define-element on-demand-stylesheets ()
|
||||
(let* ((html-str (pi:elem-str pi:children))
|
||||
(css-links (asset:get-css-links html-str)))
|
||||
(pi:h
|
||||
(<>
|
||||
(stylesheets :hrefs css-links)
|
||||
(scripts :srcs js-links)))))
|
||||
(mapcar (lambda (href)
|
||||
(link :rel "stylesheet" :type "text/css" :href href))
|
||||
css-links)))))
|
||||
|
||||
(pi:define-element document (title description)
|
||||
(pi:h
|
||||
|
@ -58,18 +22,29 @@
|
|||
(meta :charset "UTF-8")
|
||||
(link :rel "stylesheet" :type "text/css" :href "/vendor/ress.css")
|
||||
(link :rel "stylesheet" :type "text/css" :href "/styles/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 "/vendor/htmx@1.9.12.js")
|
||||
(script :src "/vendor/htmx-ext/alpine-morph@1.9.12.js")
|
||||
(script :src "/vendor/htmx-ext/head-support@1.9.12.js")
|
||||
(script :src "/vendor/alpine-ext/async-alpine@1.2.2.js" :defer t)
|
||||
(script :src "/vendor/alpine-ext/persist@3.13.8.js" :defer t)
|
||||
(script :src "/vendor/alpine-ext/morph@3.13.8.js" :defer t)
|
||||
(script :src "/scripts/global.js" :defer t)
|
||||
(on-demand-assets :component pi:children)
|
||||
(script :src "/vendor/alpine@3.13.8.js" :defer t)
|
||||
(title (format nil "~@[~a - ~]skyizwhite.dev" title))
|
||||
(meta
|
||||
:name "description"
|
||||
:content (or description "pakuの個人サイト")))
|
||||
pi:children)))
|
||||
|
||||
(pi:define-element partial-document ()
|
||||
(pi:h
|
||||
(<>
|
||||
(head :hx-head "append"
|
||||
(on-demand-stylesheets pi:children))
|
||||
pi:children)))
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(pi:define-element layout ()
|
||||
(pi:h
|
||||
(body
|
||||
:hx-ext "head-support,alpine-morph"
|
||||
:x-data t
|
||||
:|:data-dark| "$store.darkMode.on"
|
||||
; header
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
(defun partial-render (component &key status)
|
||||
(jg:with-html-response
|
||||
(if status (jg:set-response-status status))
|
||||
(pi:elem-str component)))
|
||||
(pi:elem-str (cmp:partial-document component))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue