Remove node

This commit is contained in:
Akira Tempaku 2024-04-11 23:01:47 +09:00
parent 527d017e34
commit 0441d03206
17 changed files with 163 additions and 2406 deletions

2
.gitignore vendored
View file

@ -1,3 +1 @@
.qlot
node_modules
dist

View file

@ -1 +0,0 @@
20.9.0

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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"
}
}

View file

@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

5
public/js/alpine.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

6
public/style/main.css Normal file
View file

@ -0,0 +1,6 @@
@charset "utf-8";
body {
height: 100svh;
width: 100%;
}

View file

@ -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()

View file

@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -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)))))

View file

@ -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")))))

View file

@ -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

View file

@ -1,11 +0,0 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./src/routes/**/*.lisp",
"./src/components/**/*.lisp"
],
plugins: [require("daisyui")],
daisyui: {
themes: ["cupcake"]
},
};

View file

@ -1,12 +0,0 @@
import { defineConfig } from 'vite'
export default defineConfig({
build: {
outDir: 'public',
emptyOutDir: false,
copyPublicDir: false,
rollupOptions: {
input: 'src/assets/main.js',
},
},
})