First commit

This commit is contained in:
2026-01-14 23:24:24 +01:00
commit c9f15b87b3
214 changed files with 9851 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
yhtml { overflow-y:scroll; }
body { padding:4vw; margin:0; font-family:sans-serif; color:#333;
position:relative; }
a { color:inherit; text-decoration:none; -webkit-user-select:none;
-moz-user-select:none; -ms-user-select:none; user-select:none; }
.edit { display:block; color:#ccc; text-align:center; text-decoration:none;
width:30px; line-height:30px; display:block; transition:all 0.2s;
cursor:pointer; margin:0; padding:0; position:absolute; top:0; right:0; }
.edit:hover { color:white; background:#333; text-decoration:none; }
.category { overflow:hidden; }
.category h1 { font-size:15px; margin:0; border-bottom:1px solid #333;
line-height:30px; outline:none; position:relative; padding:0 35px 0 0;
cursor:pointer; }
.category h1 a:hover { text-decoration:none; }
.category .badge { display:inline-block; font-weight:normal; font-size:8px;
padding:0 5px; border:1px solid #aaa; border-radius:3px; line-height:15px;
text-align:center; min-width:11px; margin-left:10px; vertical-align:middle;
color:#555; font-family:monospace; box-shadow:1px 1px 0 #ccc; }
.bookmarks { display:none; list-style:none; margin:0; padding:30px 0; }
.category.open .bookmarks { display:block; }
.bookmark { display:block; padding:0; position:relative;
border-bottom:1px dotted #ccc; }
.bookmark .link { color:inherit; display:block; min-height:20px;
line-height:20px; padding:2px 0; }
.bookmark .link:hover { background-color:#eef; }
.bookmark .editicon { width:20px; height:20px; float:left;
margin-right:5px; border-radius:2px; position:relative;
cursor:pointer; margin-top:2px; }
.bookmark .editicon img { width:16px; height:16px; position:absolute;
top:2px; left:2px; }
.bookmark .editicon:hover { background-color:#333; }
button,
.button { display:inline-block; padding:5px 20px; border:1px solid #333;
text-decoration:none; color:#333; background:white; font-size:inherit;
cursor:pointer; transition:all 0.2s; -webkit-user-select:none;
-moz-user-select:none; -ms-user-select:none; user-selct:none; }
button:hover,
.button:hover { color:#ddd; background:#333; }
.buttons { margin-top:20px; }
#slidein { position:fixed; top:0; right:0; width:300px; height:100%;
transform:translateX(100%); transition:transform 0.3s;
background:rgba(0,0,0,0.9); }
#slidein.open { transform:translateX(0); }
#slidein .closer { position:absolute; top:10px; right:10px; width:30px;
height:30px; cursor:pointer; }
#slidein .closer:before,
#slidein .closer:after { display:block; content:""; width:30px; height:1px;
background:white; position:absolute; top:50%; left:0; }
#slidein .closer:before { transform:rotate(45deg); }
#slidein .closer:after { transform:rotate(-45deg); }
#slidein .inner { padding:50px 20px 20px 20px; color:white; }
.field label { display:block; margin:10px 0 3px 0; }
.field label:after { display:inline; content:":"; }
.field input[type="text"],
.field select { display:block; width:100%; box-sizing:border-box;
padding:3px 5px; border:1px solid #333; color:#333;
background:white; font-size:inherit; }
#favlet { position:absolute; top:10px; right:10px; color:#ccc;
text-decoration:none; font-size:10px; cursor:pointer; }
.favletcode { word-break:break-all; }
#addcontent { padding:5vw; }
/*
@media screen and (min-width:500px) {
.categories { margin:-10px; }
.categories:after { display:table; content:""; clear:left; }
.category { float:left; width:50%; box-sizing:border-box; padding:0 10px; }
.category:nth-of-type(2n+1) { clear:left; }
}
@media screen and (min-width:750px) {
.category { width:33.33%; }
.category:nth-of-type(2n+1) { clear:none; }
.category:nth-of-type(3n+1) { clear:left; }
}
@media screen and (min-width:1000px) {
.category { width:25%; }
.category:nth-of-type(3n+1) { clear:none; }
.category:nth-of-type(4n+1) { clear:left; }
}
*/

35
hugo/static/css/main.css Normal file

File diff suppressed because one or more lines are too long

4
hugo/static/css/pico-2.1.1.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" id="svg8" version="1.1" viewBox="0 0 200 30" height="30" width="200">
<defs id="defs2"/>
<metadata id="metadata5">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="translate(0,-303.77081)" id="layer1">
<path id="path817" d="m 50,303.77081 -40,14.70001 40,15.29999 z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69282031px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<rect y="303.77081" x="0" height="29.999996" width="10" id="rect819" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.62703514;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"/>
<path id="path817-3" d="M 100.00001,303.77081 60,318.47082 l 40.00001,15.29999 z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69282031px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<path id="path817-3-6" d="M 100,303.77081 140.00001,318.47082 100,333.77081 Z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69282031px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<path id="path817-3-6-7" d="M 150,303.77081 190.00001,318.47082 150,333.77081 Z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69282031px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<rect y="303.77081" x="190" height="29.999996" width="10" id="rect819-5" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.62703514;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
hugo/static/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

5
hugo/static/js/alpine-3.15.3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,134 @@
document.addEventListener('alpine:init', () => {
Alpine.store('alphabreed', {
backUrl: '/',
pending: false,
async apiCall(method, url, data) {
this.pending = true;
const options = {
method: method,
headers: { 'Authorization': localStorage.getItem('alphabreedtoken') }
};
if (data) {
options.body = new FormData();
for (let key in data)
if (data.hasOwnProperty(key))
options.body.append(key, data[key]);
}
const response = await fetch(url, options);
this.pending = false;
if (!response.ok)
return false;
if (response.status == 204)
return true;
return await response.json();
},
async checkToken() {
const token = localStorage.getItem('alphabreedtoken');
if (!token) {
window.location = '/login/?back='+encodeURIComponent(this.backUrl);
return false;
}
const result = await this.apiCall('POST', '/api/collections/users/auth-refresh');
if (!result.token) {
window.location = '/login/?back='+encodeURIComponent(this.backUrl);
return false;
}
localStorage.setItem('alphabreedtoken', result.token);
localStorage.setItem('alphabreedid', result.record.id);
return true;
},
async createBookmarkCategory(name) {
const result = await this.apiCall('POST',
'/api/collections/bookmarkcategories/records',
{ owner: localStorage.getItem('alphabreedid'), name: name }
);
return result.id;
},
async updateBookmarkCategory(id, name) {
await this.apiCall('PATCH',
'/api/collections/bookmarkcategories/records/'+encodeURIComponent(id),
{ owner: localStorage.getItem('alphabreedid'), name: name }
);
},
async deleteBookmarkCategory(id) {
await this.apiCall('DELETE',
'/api/collections/bookmarkcategories/records/'+encodeURIComponent(id)
);
},
async createBookmark(categoryId, name, url) {
const result = await this.apiCall('POST',
'/api/collections/bookmarks/records',
{
owner: localStorage.getItem('alphabreedid'),
category: categoryId,
name: name,
url: url
}
);
return result.id;
},
async updateBookmark(id, categoryId, name, url) {
await this.apiCall('PATCH',
'/api/collections/bookmarks/records/'+encodeURIComponent(id),
{
owner: localStorage.getItem('alphabreedid'),
category: categoryId,
name: name,
url: url
}
);
},
async deleteBookmark(id) {
await this.apiCall('DELETE',
'/api/collections/bookmarks/records/'+encodeURIComponent(id)
);
},
async getBookmarkCategories() {
const result = await this.apiCall('GET',
'/api/collections/bookmarkcategories/records?perPage=9999&fields=id,name&sort=name'
);
return result.items;
},
async getBookmarks() {
const result = await this.apiCall('GET',
'/api/collections/bookmarks/records?perPage=1000&expand=category&fields=id,name,url,expand.category.id,expand.category.name&sort=name'
);
return result.items;
},
async getNotes() {
const owner = localStorage.getItem('alphabreedid');
const result = await this.apiCall('GET',
'/api/collections/notes/records/'+encodeURIComponent(owner)+'?fields=notes'
);
if (result === false)
return false;
return result.notes;
},
async createNotes(notes) {
return await this.apiCall('POST',
'/api/collections/notes/records',
{ id: localStorage.getItem('alphabreedid'), notes: notes }
);
},
async updateNotes(notes) {
const owner = localStorage.getItem('alphabreedid');
return await this.apiCall('PATCH',
'/api/collections/notes/records/'+encodeURIComponent(owner),
{ notes: notes }
);
},
});
});

15
hugo/static/js/menu.js Normal file
View File

@@ -0,0 +1,15 @@
(function() {
var onHamburger = function(e) {
e.preventDefault();
var open = hamburger.className == 'open';
hamburger.className = open ? '' : 'open';
nav.className = open ? '' : 'open';
};
var nav = document.querySelector('header nav');
var hamburger = document.createElement('div');
hamburger.id = 'hamburger';
hamburger.innerHTML = '<div class="top"></div><div class="middle"></div><div class="bottom"></div>';
hamburger.onclick = onHamburger;
document.querySelector('header').appendChild(hamburger);
})();