broken but cool htmx! also improved templating
Signed-off-by: ari melody <ari@arimelody.me>
This commit is contained in:
parent
5c59348362
commit
c1ff03c4e5
16
main.go
16
main.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -34,6 +35,7 @@ var base_template = template.Must(template.ParseFiles(
|
||||||
"views/base.html",
|
"views/base.html",
|
||||||
"views/header.html",
|
"views/header.html",
|
||||||
"views/footer.html",
|
"views/footer.html",
|
||||||
|
"views/prideflag.html",
|
||||||
))
|
))
|
||||||
var htmx_template = template.Must(template.New("root").Parse(`<head>{{block "head" .}}{{end}}</head>{{block "content" .}}{{end}}`))
|
var htmx_template = template.Must(template.New("root").Parse(`<head>{{block "head" .}}{{end}}</head>{{block "content" .}}{{end}}`))
|
||||||
|
|
||||||
|
@ -59,11 +61,21 @@ func handle_request(writer http.ResponseWriter, req *http.Request) {
|
||||||
uri := req.URL.Path
|
uri := req.URL.Path
|
||||||
start_time := time.Now()
|
start_time := time.Now()
|
||||||
|
|
||||||
hx_boosted := len(req.Header["Hx-Boosted"]) > 0 && req.Header["Hx-Boosted"][0] == "true"
|
hx_request := len(req.Header["Hx-Request"]) > 0 && req.Header["Hx-Request"][0] == "true"
|
||||||
|
|
||||||
|
// don't bother fulfilling requests to a page that's already loaded on the client!
|
||||||
|
if hx_request && len(req.Header["Referer"]) > 0 && len(req.Header["Hx-Current-Url"]) > 0 {
|
||||||
|
regex := regexp.MustCompile(`https?:\/\/[^\/]+`)
|
||||||
|
current_location := regex.ReplaceAllString(req.Header["Hx-Current-Url"][0], "")
|
||||||
|
if current_location == req.URL.Path {
|
||||||
|
writer.WriteHeader(204);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
code := func(writer http.ResponseWriter, req *http.Request) int {
|
code := func(writer http.ResponseWriter, req *http.Request) int {
|
||||||
var root *template.Template
|
var root *template.Template
|
||||||
if hx_boosted {
|
if hx_request {
|
||||||
root = template.Must(htmx_template.Clone())
|
root = template.Must(htmx_template.Clone())
|
||||||
} else {
|
} else {
|
||||||
root = template.Must(base_template.Clone())
|
root = template.Must(base_template.Clone())
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
const header_home = document.getElementById("header-home");
|
|
||||||
const header_links = document.getElementById("header-links");
|
const header_links = document.getElementById("header-links");
|
||||||
const hamburger = document.getElementById("header-links-toggle");
|
const hamburger = document.getElementById("header-links-toggle");
|
||||||
|
|
||||||
|
@ -7,14 +6,9 @@ function toggle_header_links() {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("click", event => {
|
document.addEventListener("click", event => {
|
||||||
if (!header_links.contains(event.target) && !hamburger.contains(event.target)) {
|
if (!header_links.contains(event.target) && !hamburger.contains(event.target) && !header_links.href) {
|
||||||
header_links.classList.remove("open");
|
header_links.classList.remove("open");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
hamburger.addEventListener("click", event => { toggle_header_links(); });
|
hamburger.addEventListener("click", event => { toggle_header_links(); });
|
||||||
|
|
||||||
header_home.addEventListener("click", event => {
|
|
||||||
event.preventDefault();
|
|
||||||
location.href = "/";
|
|
||||||
});
|
|
||||||
|
|
141
public/script/lib/htmx-head-support.js
Normal file
141
public/script/lib/htmx-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;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})()
|
|
@ -63,3 +63,17 @@ document.addEventListener("htmx:afterSwap", async event => {
|
||||||
}
|
}
|
||||||
window.scrollY = 0;
|
window.scrollY = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const top_button = document.getElementById("backtotop");
|
||||||
|
window.onscroll = () => {
|
||||||
|
if (!top_button) return;
|
||||||
|
const btt_threshold = 100;
|
||||||
|
if (
|
||||||
|
document.body.scrollTop > btt_threshold ||
|
||||||
|
document.documentElement.scrollTop > btt_threshold
|
||||||
|
) {
|
||||||
|
top_button.classList.add("active");
|
||||||
|
} else {
|
||||||
|
top_button.classList.remove("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ share_btn.onclick = (e) => {
|
||||||
share_btn.classList.add('active');
|
share_btn.classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("go-back").addEventListener("click", () => {
|
const go_back_btn = document.getElementById("go-back")
|
||||||
|
go_back_btn.innerText = "<";
|
||||||
|
go_back_btn.addEventListener("click", () => {
|
||||||
window.history.back();
|
window.history.back();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
document.querySelectorAll("h2.question").forEach(element => {
|
import "./main.js";
|
||||||
element.onclick = (e) => {
|
|
||||||
const url = `${window.location.protocol}//${window.location.host}${window.location.pathname}#${e.target.id}`;
|
|
||||||
window.location = url;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
document.querySelectorAll("div.music").forEach(element => {
|
document.querySelectorAll("h1.music-title").forEach(element => {
|
||||||
console.log(element);
|
element.href = "";
|
||||||
element.addEventListener("click", (e) => {
|
|
||||||
const url = `${window.location.protocol}//${window.location.host}/music/${element.id}`;
|
|
||||||
window.location = url;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
@import url("/style/colours.css");
|
@import url("/style/colours.css");
|
||||||
@import url("/style/header.css");
|
@import url("/style/header.css");
|
||||||
@import url("/style/footer.css");
|
@import url("/style/footer.css");
|
||||||
|
@import url("/style/prideflag.css");
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Monaspace Argon";
|
font-family: "Monaspace Argon";
|
||||||
|
@ -42,6 +43,32 @@ span.newchar {
|
||||||
animation: newchar 0.25s;
|
animation: newchar 0.25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a#backtotop {
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
padding: .5em .8em;
|
||||||
|
display: block;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: .5;
|
||||||
|
transition-property: opacity, transform, border-color, background-color, color;
|
||||||
|
transition-duration: .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a#backtotop.active {
|
||||||
|
top: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a#backtotop:hover {
|
||||||
|
color: #eee;
|
||||||
|
border-color: #eee;
|
||||||
|
background-color: var(--links);
|
||||||
|
box-shadow: 0 0 1em var(--links);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes newchar {
|
@keyframes newchar {
|
||||||
from {
|
from {
|
||||||
background: #fff8;
|
background: #fff8;
|
||||||
|
|
|
@ -241,7 +241,7 @@ div#info p {
|
||||||
#title {
|
#title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
font-size: 3em;
|
font-size: 2.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#year {
|
#year {
|
||||||
|
@ -571,6 +571,7 @@ footer a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
div#info > div {
|
div#info > div {
|
||||||
|
min-width: auto;
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
@import url("/style/index.css");
|
@import url("/style/index.css");
|
||||||
|
|
||||||
|
main {
|
||||||
|
width: min(calc(100% - 4rem), 720px);
|
||||||
|
min-height: calc(100vh - 10.3rem);
|
||||||
|
margin: 0 auto 2rem auto;
|
||||||
|
padding-top: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
div.music {
|
div.music {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
|
@ -114,7 +121,7 @@ h2.question {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapse {
|
div.answer {
|
||||||
margin: -1rem 0 1rem 0;
|
margin: -1rem 0 1rem 0;
|
||||||
padding: .5em 1.5em;
|
padding: .5em 1.5em;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
25
public/style/prideflag.css
Normal file
25
public/style/prideflag.css
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#prideflag svg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 120px;
|
||||||
|
transform-origin: 100% 0%;
|
||||||
|
transition: transform .5s cubic-bezier(.32,1.63,.41,1.01);
|
||||||
|
z-index: 8008135;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#prideflag svg:hover {
|
||||||
|
transform: scale(110%);
|
||||||
|
}
|
||||||
|
#prideflag svg:active {
|
||||||
|
transform: scale(110%);
|
||||||
|
}
|
||||||
|
#prideflag svg * {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 950px) {
|
||||||
|
#prideflag {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,28 +7,14 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
{{block "head" .}}
|
{{block "head" .}}{{end}}
|
||||||
<!-- <title>ari melody 💫</title> -->
|
|
||||||
<!-- <link rel="shortcut icon" href="img/favicon.png" type="image/x-icon"> -->
|
|
||||||
<!---->
|
|
||||||
<!-- <meta name="description" content="home to your local SPACEGIRL 💫"> -->
|
|
||||||
<!---->
|
|
||||||
<!-- <meta property="og:title" content="ari melody"> -->
|
|
||||||
<!-- <meta property="og:type" content="website"> -->
|
|
||||||
<!-- <meta property="og:url" content="www.arimelody.me"> -->
|
|
||||||
<!-- <meta property="og:image" content="https://www.arimelody.me/img/favicon.png"> -->
|
|
||||||
<!-- <meta property="og:site_name" content="ari melody"> -->
|
|
||||||
<!-- <meta property="og:description" content="home to your local SPACEGIRL 💫"> -->
|
|
||||||
<!---->
|
|
||||||
<!-- <link rel="stylesheet" href="style/main.css"> -->
|
|
||||||
<!---->
|
|
||||||
<!-- <script type="module" src="/script/main.js" defer></script> -->
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<!-- <script type="application/javascript" src="/script/lib/htmx.min.js"></script> -->
|
<meta name="htmx-config" content='{"htmx.config.scrollIntoViewOnBoost":false}'>
|
||||||
|
<script type="application/javascript" src="/script/lib/htmx.min.js"></script>
|
||||||
|
<script type="application/javascript" src="/script/lib/htmx-head-support.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body hx-ext="head-support">
|
||||||
{{template "header"}}
|
{{template "header"}}
|
||||||
|
|
||||||
{{block "content" .}}
|
{{block "content" .}}
|
||||||
|
@ -43,8 +29,8 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{template "footer"}}
|
{{template "footer"}}
|
||||||
|
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
{{template "prideflag"}}
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{define "footer"}}
|
{{define "footer"}}
|
||||||
|
|
||||||
<footer hx-preserve="true">
|
<footer>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<small><em>*made with ♥ by ari, 2024*</em></small>
|
<small><em>*made with ♥ by ari, 2024*</em></small>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{{define "header"}}
|
{{define "header"}}
|
||||||
|
|
||||||
<header hx-preserve="true">
|
<header>
|
||||||
<nav>
|
<nav>
|
||||||
<div id="header-home">
|
<div id="header-home" hx-get="/" hx-on="click" hx-target="main" hx-swap="outerHTML show:window:top" hx-push-url="true">
|
||||||
<img src="/img/favicon.png" id="header-icon" width="100" height="100" alt="">
|
<img src="/img/favicon.png" id="header-icon" width="100" height="100" alt="">
|
||||||
<div id="header-text">
|
<div id="header-text">
|
||||||
<h1>ari melody</h1>
|
<h1>ari melody</h1>
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
<rect y="40" width="70" height="10" rx="5" fill="#eee" />
|
<rect y="40" width="70" height="10" rx="5" fill="#eee" />
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<ul id="header-links">
|
<ul id="header-links" hx-boost="true" hx-target="main" hx-swap="outerHTML show:window:top">
|
||||||
<li>
|
<li>
|
||||||
<a href="/">home</a>
|
<a href="/">home</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,28 +1,9 @@
|
||||||
<head>
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta charset="UTF-8">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{{block "head" .}}{{end}}
|
||||||
|
<script type="application/javascript" src="/script/lib/htmx.min.js"></script>
|
||||||
{{block "head" .}}
|
<script type="application/javascript" src="/script/lib/htmx-head-support.js"></script>
|
||||||
<title>ari melody 💫</title>
|
|
||||||
<link rel="shortcut icon" href="img/favicon.png" type="image/x-icon">
|
|
||||||
|
|
||||||
<meta name="description" content="home to your local SPACEGIRL 💫">
|
|
||||||
|
|
||||||
<meta property="og:title" content="ari melody">
|
|
||||||
<meta property="og:type" content="website">
|
|
||||||
<meta property="og:url" content="www.arimelody.me">
|
|
||||||
<meta property="og:image" content="https://www.arimelody.me/img/favicon.png">
|
|
||||||
<meta property="og:site_name" content="ari melody">
|
|
||||||
<meta property="og:description" content="home to your local SPACEGIRL 💫">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="style/main.css">
|
|
||||||
|
|
||||||
<script type="module" src="/script/main.js" defer></script>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<script type="application/javascript" src="/script/lib/htmx.min.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
{{block "content" .}}{{end}}
|
{{block "content" .}}{{end}}
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
<meta property="og:description" content="home to your local SPACEGIRL 💫">
|
<meta property="og:description" content="home to your local SPACEGIRL 💫">
|
||||||
|
|
||||||
<link rel="stylesheet" href="/style/index.css">
|
<link rel="stylesheet" href="/style/index.css">
|
||||||
|
|
||||||
<script type="module" src="/script/main.js" defer></script>
|
<script type="module" src="/script/main.js" defer></script>
|
||||||
<link rel="me" href="https://wetdry.world/@ari">
|
<link rel="me" href="https://wetdry.world/@ari">
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
<meta name="twitter:image:alt" content="Cover art for "{{.Title}}"">
|
<meta name="twitter:image:alt" content="Cover art for "{{.Title}}"">
|
||||||
|
|
||||||
<script type="module" src="/script/music-gateway.js" defer></script>
|
<script type="module" src="/script/music-gateway.js" defer></script>
|
||||||
<script type="application/javascript" src="/script/prideflag.js" defer></script>
|
|
||||||
<link rel="stylesheet" href="/style/music-gateway.css">
|
<link rel="stylesheet" href="/style/music-gateway.css">
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
@ -33,7 +32,8 @@
|
||||||
<main>
|
<main>
|
||||||
<div id="background" data-url="{{.ResolveArtwork}}"></div>
|
<div id="background" data-url="{{.ResolveArtwork}}"></div>
|
||||||
|
|
||||||
<a id="go-back" title="back to arimelody.me" href="/music"><</a>
|
<a href="/music" id="go-back" title="back to arimelody.me">back to arimelody.me</a>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
<div id="music-container">
|
<div id="music-container">
|
||||||
<div id="art-container">
|
<div id="art-container">
|
||||||
|
|
|
@ -12,9 +12,7 @@
|
||||||
<meta property="og:description" content="music from your local SPACEGIRL 💫">
|
<meta property="og:description" content="music from your local SPACEGIRL 💫">
|
||||||
|
|
||||||
<link rel="stylesheet" href="/style/music.css">
|
<link rel="stylesheet" href="/style/music.css">
|
||||||
|
<script type="module" src="/script/music.js" defer></script>
|
||||||
<script type="module" src="/script/main.js" defer></script>
|
|
||||||
<script type="application/javascript" src="/script/music.js" defer></script>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
|
@ -25,11 +23,11 @@
|
||||||
|
|
||||||
<div id="music-container">
|
<div id="music-container">
|
||||||
{{range $Album := .}}
|
{{range $Album := .}}
|
||||||
<div class="music" id="{{$Album.Id}}">
|
<div class="music" id="{{$Album.Id}}" hx-get="/music/{{$Album.Id}}" hx-trigger="click" hx-target="main" hx-swap="outerHTML" hx-push-url="true">
|
||||||
<div class="music-artwork">
|
<div class="music-artwork">
|
||||||
<img src="{{$Album.ResolveArtwork}}" alt="{{$Album.Title}} artwork" width="128">
|
<img src="{{$Album.ResolveArtwork}}" alt="{{$Album.Title}} artwork" width="128">
|
||||||
</div>
|
</div>
|
||||||
<div class="music-details">
|
<div class="music-details" hx-boost="true" hx-target="main" hx-swap="outerHTML">
|
||||||
<a href="/music/{{$Album.Id}}"><h1 class="music-title">{{$Album.Title}}</h1></a>
|
<a href="/music/{{$Album.Id}}"><h1 class="music-title">{{$Album.Title}}</h1></a>
|
||||||
<h2 class="music-artist">{{$Album.PrintPrimaryArtists}}</h2>
|
<h2 class="music-artist">{{$Album.PrintPrimaryArtists}}</h2>
|
||||||
<h3 class="music-type-{{.ResolveType}}">{{$Album.ResolveType}}</h3>
|
<h3 class="music-type-{{.ResolveType}}">{{$Album.ResolveType}}</h3>
|
||||||
|
@ -45,12 +43,12 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 id="usage" class="question">
|
<h2 id="usage" class="question" hx-get="/music#usage" hx-on="click" hx-swap="none" hx-push-url="true">
|
||||||
<a href="#usage">
|
<a href="#usage">
|
||||||
> "can i use your music in my content?"
|
> "can i use your music in my content?"
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="collapse">
|
<div class="answer">
|
||||||
<p>
|
<p>
|
||||||
<strong class="big">yes!</strong> well, in most cases...
|
<strong class="big">yes!</strong> well, in most cases...
|
||||||
</p>
|
</p>
|
||||||
|
@ -85,5 +83,7 @@
|
||||||
> <a href="mailto:ari@arimelody.me">ari@arimelody.me</a>
|
> <a href="mailto:ari@arimelody.me">ari@arimelody.me</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a href="#" id="backtotop">back to top</a>
|
||||||
</main>
|
</main>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
21
views/prideflag.html
Normal file
21
views/prideflag.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{{define "prideflag"}}
|
||||||
|
<a href="https://github.com/mellodoot/prideflag" target="_blank" id="prideflag">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" width="120" height="120" hx-preserve="true">
|
||||||
|
<path id="red" d="M120,80 L100,100 L120,120 Z" style="fill:#d20605"/>
|
||||||
|
<path id="orange" d="M120,80 V40 L80,80 L100,100 Z" style="fill:#ef9c00"/>
|
||||||
|
<path id="yellow" d="M120,40 V0 L60,60 L80,80 Z" style="fill:#e5fe02"/>
|
||||||
|
<path id="green" d="M120,0 H80 L40,40 L60,60 Z" style="fill:#09be01"/>
|
||||||
|
<path id="blue" d="M80,0 H40 L20,20 L40,40 Z" style="fill:#081a9a"/>
|
||||||
|
<path id="purple" d="M40,0 H0 L20,20 Z" style="fill:#76008a"/>
|
||||||
|
|
||||||
|
<rect id="black" x="60" width="60" height="60" style="fill:#010101"/>
|
||||||
|
<rect id="brown" x="70" width="50" height="50" style="fill:#603814"/>
|
||||||
|
<rect id="lightblue" x="80" width="40" height="40" style="fill:#73d6ed"/>
|
||||||
|
<rect id="pink" x="90" width="30" height="30" style="fill:#ffafc8"/>
|
||||||
|
<rect id="white" x="100" width="20" height="20" style="fill:#fff"/>
|
||||||
|
|
||||||
|
<rect id="intyellow" x="110" width="10" height="10" style="fill:#fed800"/>
|
||||||
|
<circle id="intpurple" cx="120" cy="0" r="5" stroke="#7601ad" stroke-width="2" fill="none"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
{{end}}
|
Loading…
Reference in a new issue