Remove node
This commit is contained in:
parent
527d017e34
commit
0441d03206
17 changed files with 163 additions and 2406 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1 @@
|
||||||
.qlot
|
.qlot
|
||||||
node_modules
|
|
||||||
dist
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
20.9.0
|
|
13
README.md
13
README.md
|
@ -1,14 +1,3 @@
|
||||||
# homepage (WIP)
|
# homepage (WIP)
|
||||||
|
|
||||||
My homepage.
|
My homepage made with Common Lisp, HTMX and Alpine.js.
|
||||||
|
|
||||||
## Tech stack
|
|
||||||
|
|
||||||
- [Common Lisp](https://lisp-lang.org/)
|
|
||||||
- [jingle](https://github.com/dnaeon/cl-jingle): Web framework based on [ningle](https://github.com/fukamachi/ningle)
|
|
||||||
- [ningle-fbr](https://github.com/skyizwhite/ningle-fbr): ningle plugin for file-based routing
|
|
||||||
- [piccolo](https://github.com/skyizwhite/piccolo): HTML generator
|
|
||||||
- [HTMX](https://htmx.org/): high power tools for HTML
|
|
||||||
- [Alpine.js](https://alpinejs.dev/): rugged, minimal tool for composing behavior directly in markup
|
|
||||||
- [Tailwind CSS](https://tailwindcss.com/): utility-first CSS framework
|
|
||||||
- [daisyUI](https://daisyui.com/): component library for Tailwind CSS
|
|
||||||
|
|
2302
package-lock.json
generated
2302
package-lock.json
generated
File diff suppressed because it is too large
Load diff
25
package.json
25
package.json
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"name": "hp",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build",
|
|
||||||
"preview": "vite preview"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"autoprefixer": "^10.4.17",
|
|
||||||
"daisyui": "^4.7.2",
|
|
||||||
"postcss": "^8.4.35",
|
|
||||||
"tailwindcss": "^3.4.1",
|
|
||||||
"vite": "^5.1.4"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@alpinejs/anchor": "^3.13.5",
|
|
||||||
"@alpinejs/intersect": "^3.13.5",
|
|
||||||
"@alpinejs/persist": "^3.13.5",
|
|
||||||
"alpinejs": "^3.13.5",
|
|
||||||
"htmx.org": "^1.9.10"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
5
public/js/alpine.min.js
vendored
Normal file
5
public/js/alpine.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
141
public/js/htmx-ext/head-support.js
Normal file
141
public/js/htmx-ext/head-support.js
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
//==========================================================
|
||||||
|
// head-support.js
|
||||||
|
//
|
||||||
|
// An extension to htmx 1.0 to add head tag merging.
|
||||||
|
//==========================================================
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
var api = null;
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
//console.log(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeHead(newContent, defaultMergeStrategy) {
|
||||||
|
|
||||||
|
if (newContent && newContent.indexOf('<head') > -1) {
|
||||||
|
const htmlDoc = document.createElement("html");
|
||||||
|
// remove svgs to avoid conflicts
|
||||||
|
var contentWithSvgsRemoved = newContent.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, '');
|
||||||
|
// extract head tag
|
||||||
|
var headTag = contentWithSvgsRemoved.match(/(<head(\s[^>]*>|>)([\s\S]*?)<\/head>)/im);
|
||||||
|
|
||||||
|
// if the head tag exists...
|
||||||
|
if (headTag) {
|
||||||
|
|
||||||
|
var added = []
|
||||||
|
var removed = []
|
||||||
|
var preserved = []
|
||||||
|
var nodesToAppend = []
|
||||||
|
|
||||||
|
htmlDoc.innerHTML = headTag;
|
||||||
|
var newHeadTag = htmlDoc.querySelector("head");
|
||||||
|
var currentHead = document.head;
|
||||||
|
|
||||||
|
if (newHeadTag == null) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// put all new head elements into a Map, by their outerHTML
|
||||||
|
var srcToNewHeadNodes = new Map();
|
||||||
|
for (const newHeadChild of newHeadTag.children) {
|
||||||
|
srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// determine merge strategy
|
||||||
|
var mergeStrategy = api.getAttributeValue(newHeadTag, "hx-head") || defaultMergeStrategy;
|
||||||
|
|
||||||
|
// get the current head
|
||||||
|
for (const currentHeadElt of currentHead.children) {
|
||||||
|
|
||||||
|
// If the current head element is in the map
|
||||||
|
var inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML);
|
||||||
|
var isReAppended = currentHeadElt.getAttribute("hx-head") === "re-eval";
|
||||||
|
var isPreserved = api.getAttributeValue(currentHeadElt, "hx-preserve") === "true";
|
||||||
|
if (inNewContent || isPreserved) {
|
||||||
|
if (isReAppended) {
|
||||||
|
// remove the current version and let the new version replace it and re-execute
|
||||||
|
removed.push(currentHeadElt);
|
||||||
|
} else {
|
||||||
|
// this element already exists and should not be re-appended, so remove it from
|
||||||
|
// the new content map, preserving it in the DOM
|
||||||
|
srcToNewHeadNodes.delete(currentHeadElt.outerHTML);
|
||||||
|
preserved.push(currentHeadElt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mergeStrategy === "append") {
|
||||||
|
// we are appending and this existing element is not new content
|
||||||
|
// so if and only if it is marked for re-append do we do anything
|
||||||
|
if (isReAppended) {
|
||||||
|
removed.push(currentHeadElt);
|
||||||
|
nodesToAppend.push(currentHeadElt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if this is a merge, we remove this content since it is not in the new head
|
||||||
|
if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: currentHeadElt}) !== false) {
|
||||||
|
removed.push(currentHeadElt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the tremaining new head elements in the Map into the
|
||||||
|
// nodes to append to the head tag
|
||||||
|
nodesToAppend.push(...srcToNewHeadNodes.values());
|
||||||
|
log("to append: ", nodesToAppend);
|
||||||
|
|
||||||
|
for (const newNode of nodesToAppend) {
|
||||||
|
log("adding: ", newNode);
|
||||||
|
var newElt = document.createRange().createContextualFragment(newNode.outerHTML);
|
||||||
|
log(newElt);
|
||||||
|
if (api.triggerEvent(document.body, "htmx:addingHeadElement", {headElement: newElt}) !== false) {
|
||||||
|
currentHead.appendChild(newElt);
|
||||||
|
added.push(newElt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all removed elements, after we have appended the new elements to avoid
|
||||||
|
// additional network requests for things like style sheets
|
||||||
|
for (const removedElement of removed) {
|
||||||
|
if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: removedElement}) !== false) {
|
||||||
|
currentHead.removeChild(removedElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
api.triggerEvent(document.body, "htmx:afterHeadMerge", {added: added, kept: preserved, removed: removed});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
htmx.defineExtension("head-support", {
|
||||||
|
init: function(apiRef) {
|
||||||
|
// store a reference to the internal API.
|
||||||
|
api = apiRef;
|
||||||
|
|
||||||
|
htmx.on('htmx:afterSwap', function(evt){
|
||||||
|
var serverResponse = evt.detail.xhr.response;
|
||||||
|
if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) {
|
||||||
|
mergeHead(serverResponse, evt.detail.boosted ? "merge" : "append");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
htmx.on('htmx:historyRestore', function(evt){
|
||||||
|
if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) {
|
||||||
|
if (evt.detail.cacheMiss) {
|
||||||
|
mergeHead(evt.detail.serverResponse, "merge");
|
||||||
|
} else {
|
||||||
|
mergeHead(evt.detail.item.head, "merge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
htmx.on('htmx:historyItemCreated', function(evt){
|
||||||
|
var historyItem = evt.detail.item;
|
||||||
|
historyItem.head = document.head.outerHTML;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})()
|
1
public/js/htmx.min.js
vendored
Normal file
1
public/js/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
public/style/main.css
Normal file
6
public/style/main.css
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100svh;
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
import './style.css'
|
|
||||||
import HTMX from 'htmx.org'
|
|
||||||
import Alpine from 'alpinejs'
|
|
||||||
import anchor from '@alpinejs/anchor'
|
|
||||||
import intersect from '@alpinejs/intersect'
|
|
||||||
import persist from '@alpinejs/persist'
|
|
||||||
|
|
||||||
window.htmx = HTMX
|
|
||||||
import("htmx.org/dist/ext/debug.js")
|
|
||||||
import("htmx.org/dist/ext/alpine-morph.js")
|
|
||||||
import("htmx.org/dist/ext/head-support.js")
|
|
||||||
|
|
||||||
window.Alpine = Alpine
|
|
||||||
Alpine.plugin(anchor)
|
|
||||||
Alpine.plugin(intersect)
|
|
||||||
Alpine.plugin(persist)
|
|
||||||
Alpine.start()
|
|
|
@ -1,3 +0,0 @@
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
|
@ -9,8 +9,10 @@
|
||||||
(html
|
(html
|
||||||
(head
|
(head
|
||||||
(title "skyizwhite.dev")
|
(title "skyizwhite.dev")
|
||||||
(script :type "module" :src "http://localhost:5173/@vite/client")
|
(script :src "/js/htmx.min.js")
|
||||||
(script :type "module" :src "http://localhost:5173/src/assets/main.js"))
|
(script :src "/js/htmx-ext/head-support.js")
|
||||||
(body :hx-ext "debug, alpine-morph, head-support" :class "h-[100svh] w-screen"
|
(script :src "/js/alpine.min.js" :defer t)
|
||||||
(main :class "h-full"
|
(link :rel "stylesheet" :href "/style/main.css" type="text/css"))
|
||||||
|
(body :hx-ext "head-support"
|
||||||
|
(main
|
||||||
pi:children)))))
|
pi:children)))))
|
||||||
|
|
|
@ -9,6 +9,5 @@
|
||||||
(pi:define-element not-found-page ()
|
(pi:define-element not-found-page ()
|
||||||
(pi:h
|
(pi:h
|
||||||
(layout
|
(layout
|
||||||
(section :class "h-full flex justify-center items-center"
|
(section
|
||||||
(h1 :class "text-error text-4xl"
|
(h1 "404 Not Found")))))
|
||||||
"404 Not Found")))))
|
|
||||||
|
|
|
@ -10,14 +10,7 @@
|
||||||
|
|
||||||
(pi:define-element page ()
|
(pi:define-element page ()
|
||||||
(pi:h
|
(pi:h
|
||||||
(cmp:layout
|
(div)))
|
||||||
(section :class "h-full flex justify-center items-center"
|
|
||||||
(div :class "flex flex-col items-center gap-2"
|
|
||||||
(div :class "avatar"
|
|
||||||
(div :class "w-32 mask mask-squircle"
|
|
||||||
(img :src "/img/me.jpg")))
|
|
||||||
(p :class "text-primary text-3xl text-center"
|
|
||||||
"Hello, World!"))))))
|
|
||||||
|
|
||||||
;;; Controller
|
;;; Controller
|
||||||
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
export default {
|
|
||||||
content: [
|
|
||||||
"./src/routes/**/*.lisp",
|
|
||||||
"./src/components/**/*.lisp"
|
|
||||||
],
|
|
||||||
plugins: [require("daisyui")],
|
|
||||||
daisyui: {
|
|
||||||
themes: ["cupcake"]
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
build: {
|
|
||||||
outDir: 'public',
|
|
||||||
emptyOutDir: false,
|
|
||||||
copyPublicDir: false,
|
|
||||||
rollupOptions: {
|
|
||||||
input: 'src/assets/main.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
Loading…
Add table
Add a link
Reference in a new issue