Introduced templating and views

This commit is contained in:
Simon Martens
2025-02-09 14:51:04 +01:00
parent 159fa1a7bb
commit a250d1b18e
209 changed files with 74559 additions and 0 deletions

93
views/transform/main.js Normal file
View File

@@ -0,0 +1,93 @@
import "./site.css";
const ATTR_XSLT_ONLOAD = "script[xslt-onload]";
const ATTR_XSLT_TEMPLATE = "xslt-template";
const ATTR_XSLT_STATE = "xslt-transformed";
const xslt_processors = new Map();
function setup_xslt() {
let els = htmx.findAll(ATTR_XSLT_ONLOAD);
for (let element of els) {
transform_xslt(element);
}
}
function transform_xslt(element) {
if (
element.getAttribute(ATTR_XSLT_STATE) === "true" ||
!element.hasAttribute(ATTR_XSLT_TEMPLATE)
) {
return;
}
let templateId = "#" + element.getAttribute(ATTR_XSLT_TEMPLATE);
let processor = xslt_processors.get(templateId);
if (!processor) {
let template = htmx.find(templateId);
if (template) {
let content = template.innerHTML
? new DOMParser().parseFromString(template.innerHTML, "application/xml")
: template.contentDocument;
processor = new XSLTProcessor();
processor.importStylesheet(content);
xslt_processors.set(templateId, processor);
} else {
throw new Error("Unknown XSLT template: " + templateId);
}
}
let data = new DOMParser().parseFromString(element.innerHTML, "application/xml");
let frag = processor.transformToFragment(data, document);
let s = new XMLSerializer().serializeToString(frag);
element.outerHTML = s;
}
function setup_templates() {
let templates = document.querySelectorAll("template[simple]");
templates.forEach((template) => {
let templateId = template.getAttribute("id");
let templateContent = template.content;
customElements.define(
templateId,
class extends HTMLElement {
constructor() {
super();
this.appendChild(templateContent.cloneNode(true));
this.slots = this.querySelectorAll("slot");
}
connectedCallback() {
let toremove = [];
this.slots.forEach((tslot) => {
let slotName = tslot.getAttribute("name");
let slotContent = this.querySelector(`[slot="${slotName}"]`);
if (slotContent) {
tslot.replaceWith(slotContent.cloneNode(true));
toremove.push(slotContent);
}
});
toremove.forEach((element) => {
element.remove();
});
}
},
);
});
}
// INFO: This is intended to be callled once on website load
function setup() {
setup_xslt();
htmx.on("htmx:load", function (_) {
// INFO: We can instead use afterSettle; and also clear the map with
// xslt_processors.clear();
setup_xslt();
});
setup_templates();
}
export { setup };

69
views/transform/site.css Normal file
View File

@@ -0,0 +1,69 @@
@import 'tailwindcss';
@theme {
--font-script: Rancho, ui-serif;
--font-sans: 'Source Sans 3', 'Merriweather Sans', ui-sans-serif;
--font-serif: 'Merriweather', ui-serif;
}
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
@utility font-variant-small-caps {
font-variant-caps: small-caps;
}
@layer base {
}
@layer components {
html {
font-size: 15.5px;
}
body {
@apply bg-slate-50;
}
h1,
h2,
h3,
h4 {
@apply font-serif font-bold;
}
a {
@apply hyphens-none underline decoration-dotted hover:decoration-solid text-slate-700 hover:text-slate-900;
}
ul {
@apply my-2;
}
li {
@apply ml-14 list-disc;
}
a[aria-current="page"] {
@apply text-red-500!;
}
main {
@apply grow shrink-0;
}
}