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
|
||||
node_modules
|
||||
dist
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
20.9.0
|
13
README.md
13
README.md
|
@ -1,14 +1,3 @@
|
|||
# homepage (WIP)
|
||||
|
||||
My homepage.
|
||||
|
||||
## 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
|
||||
My homepage made with Common Lisp, HTMX and Alpine.js.
|
||||
|
|
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
|
||||
(head
|
||||
(title "skyizwhite.dev")
|
||||
(script :type "module" :src "http://localhost:5173/@vite/client")
|
||||
(script :type "module" :src "http://localhost:5173/src/assets/main.js"))
|
||||
(body :hx-ext "debug, alpine-morph, head-support" :class "h-[100svh] w-screen"
|
||||
(main :class "h-full"
|
||||
(script :src "/js/htmx.min.js")
|
||||
(script :src "/js/htmx-ext/head-support.js")
|
||||
(script :src "/js/alpine.min.js" :defer t)
|
||||
(link :rel "stylesheet" :href "/style/main.css" type="text/css"))
|
||||
(body :hx-ext "head-support"
|
||||
(main
|
||||
pi:children)))))
|
||||
|
|
|
@ -9,6 +9,5 @@
|
|||
(pi:define-element not-found-page ()
|
||||
(pi:h
|
||||
(layout
|
||||
(section :class "h-full flex justify-center items-center"
|
||||
(h1 :class "text-error text-4xl"
|
||||
"404 Not Found")))))
|
||||
(section
|
||||
(h1 "404 Not Found")))))
|
||||
|
|
|
@ -10,14 +10,7 @@
|
|||
|
||||
(pi:define-element page ()
|
||||
(pi:h
|
||||
(cmp:layout
|
||||
(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!"))))))
|
||||
(div)))
|
||||
|
||||
;;; 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