Apis Necros преди 2 години
ревизия
ba289b7103

+ 20 - 0
LICENSE

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2022 YOUR_NAME_HERE
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 2 - 0
archetypes/default.md

@@ -0,0 +1,2 @@
++++
++++

+ 0 - 0
layouts/404.html


+ 13 - 0
layouts/_default/baseof.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+    {{- partial "head.html" . -}}
+    <body>
+        <div class="h-screen flex flex-flow flex-wrap">
+            {{- partial "header.html" . -}}
+            <div id="content" class="flex-1 px-4">
+            {{- block "main" . }}{{- end }}
+            {{- partial "footer.html" . -}}
+            </div>
+        </div>
+    </body>
+</html>

+ 14 - 0
layouts/_default/list.html

@@ -0,0 +1,14 @@
+{{ define "main" }}
+	<h1>{{ .Title }}</h1>
+	{{ range .Pages.ByPublishDate.Reverse }}
+	<div id="blog-{{ .Slug }}" class="panel my-2">
+		<h2><a href="{{ .Slug }}">{{ .Title }}</a></h2>
+		<div class="flex flex-row flex-wrap md:flex-nowrap mt-2">
+			<span class="image-wrapper w-full h-32 md:w-32 md:h-32">
+				<img srcset="" src="" alt="Filler" />
+			</span>
+			<p class="m-2 flex-1">{{ .Summary }}</p>
+		</div>
+	</div>
+	{{ end }}
+{{ end }}

+ 13 - 0
layouts/_default/single.html

@@ -0,0 +1,13 @@
+
+{{ define "main" }}
+<div class="panel flex-1 blog-post">
+	<h1 class="blog-post--title">{{ .Title }}</h1>
+	<div class="blog-post--body">
+		{{ .Content }}
+	</div>
+	<div class="blog-post--footer">
+		<div class="blog-post--author">Author: {{ .Site.Author }}</div>
+		<div class="blog-post--updated">Updated: {{ .Date }}</div>
+	</div>
+</div>
+{{ end }}

+ 16 - 0
layouts/index.html

@@ -0,0 +1,16 @@
+
+{{ define "main" }}
+	{{- partial "about.html" . -}}
+	<div id="blog-post" class="panel my-2">
+		<h1 class="mb-4"><a href="/blog/">Blog Posts</a></h1>
+		{{ range first 3 (where .Site.RegularPages "Section" "blog") }}
+			{{ partial "micropanel.html" . }}
+		{{end}}
+	</div>
+	<div id="project-posts" class="panel my-2">
+		<h1 class="mb-4"><a href="/projects/">Featured Projects</a></h1>
+		{{ range first 3 (where .Site.RegularPages "Section" "projects") }}
+			<div>{{ .Title }}</div>
+		{{end}}
+	</div>
+{{ end }}

+ 8 - 0
layouts/partials/about.html

@@ -0,0 +1,8 @@
+<div class="panel my-2 space-y-2">
+	<h1><a href="#" title="/whoami">About Me</a></h1>
+	<h2>Welcome to {{ .Site.Title }}</h2>
+	<p>Here, I like to host assorted web projects and JavaScript prototypes, in case I ever share them with others. I'll also post the occasional blog post. These posts will mostly be technical in nature, but will also just focus on whatever I've got going on at any given time.</p>
+    <p>If you want to drop me a line, email me at the address in the footer.</p>
+    <h2>Indie Web</h2>
+    <p>I am huge supporter of the <a href="https://indieweb.org/" target="_blank">Indie Web</a> movement, and thus make use of a lot of the principals and features that drive it. I encourage anyone and everyone to participate, and help take back the internet from the monopolies who try to keep us subjugated.</p>
+</div>

+ 6 - 0
layouts/partials/footer.html

@@ -0,0 +1,6 @@
+
+<div id="footer" class="panel text-center">
+	&copy; <span id="footer-date"></span> | <a id="footer-email" href="#"></a>
+</div>
+<script src="/projects/Cipher/apiscipher.min.js"></script>
+<script src="/js/email_me.js"></script>

+ 18 - 0
layouts/partials/head.html

@@ -0,0 +1,18 @@
+<head>
+	<meta charset="UTF-8" />
+	<meta http-equiv="content-language" content="en-us" />
+	<meta name="author" content="Apis Necros" />
+	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+	<link rel="pgpkey authn" href="/.well-known/apisnecros.txt" />
+	{{ $title := print .Title " - " .Site.Title }}
+	{{ if .IsHome }} {{ $title = .Site.Title }} {{ end }}
+	<title>{{ $title }}</title>
+
+	<meta name="canonical" content="{{ .Permalink }}" />
+	
+	<link href="/css/tailwind.min.css" rel="stylesheet" />
+	<link rel="preload" as="style" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css" onload="this.onload=null;this.rel='stylesheet'" />
+	<noscript><link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css" /></noscript>
+
+	<script src="/js/Bumble.js"></script>
+</head>

+ 10 - 0
layouts/partials/header.html

@@ -0,0 +1,10 @@
+
+<div id="sidebar">
+	<div id="site-title">{{ .Site.Title }}</div>
+	<img class="w-48 mx-auto rounded-full border border-black" src="/imgs/logo_partial.png" alt="Logo for The Hive" />
+	<div id="nav">
+		{{ range .Site.Menus.main }}
+		<a href="{{ .URL }}">{{ .Name }}</a>
+		{{ end }}
+	</div>
+</div>

+ 10 - 0
layouts/partials/micropanel.html

@@ -0,0 +1,10 @@
+
+<div class="project-item">
+	<img srcset="/imgs/no-image-new.png" src="/imgs/no-img-new.webp" alt="No Image" />
+	<div class="project-body">
+		<div class="project-title">
+			<a href="{{ .Permalink }}">{{ .Title }}</a>
+		</div>
+		<p class="project-description">{{ .Description }}</p>
+	</div>
+</div>

+ 41 - 0
static/.well-known/apisnecros.txt

@@ -0,0 +1,41 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+h1iH7G+IOpjGY/Nd6J7FV0SGjSsAu9YGNLs=
+=TzIy
+-----END PGP PUBLIC KEY BLOCK-----

+ 15 - 0
static/.well-known/security.txt

@@ -0,0 +1,15 @@
+###############################################################################
+#   Thank you for taking the time to visit my security.txt file.
+#   As a security expert myself, I take these things very seriously.
+#   While I DO NOT PAY BOUNTIES, I am very interested in making sure my 
+#   server is secure. If you happen to notice any security issues,
+#   please do let me know at the address below.
+#   
+#   I WILL NOT RESPOND TO BEG BOUNTIES
+#   https://www.troyhunt.com/beg-bounties/
+###############################################################################
+Contact: mailto:apisnecros@protonmail.com
+Expires: 2200-01-01T05:00:00.000Z
+Encryption: https://www.vzqk50.com/.well-known/apisnecros.txt
+Preferred-Languages: en, jp
+Canonical: https://www.vzqk50.com/.well-known/security.txt

Файловите разлики са ограничени, защото са твърде много
+ 2 - 0
static/css/tailwind.min.css


BIN
static/imgs/abandoned.png


BIN
static/imgs/abandoned.webp


BIN
static/imgs/favicons/android-chrome-192x192.png


BIN
static/imgs/favicons/android-chrome-512x512.png


BIN
static/imgs/favicons/apple-touch-icon.png


+ 9 - 0
static/imgs/favicons/browserconfig.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<browserconfig>
+    <msapplication>
+        <tile>
+            <square150x150logo src="/imgs/favicons/mstile-150x150.png"/>
+            <TileColor>#da532c</TileColor>
+        </tile>
+    </msapplication>
+</browserconfig>

BIN
static/imgs/favicons/favicon-16x16.png


BIN
static/imgs/favicons/favicon-32x32.png


BIN
static/imgs/favicons/favicon.ico


BIN
static/imgs/favicons/mstile-150x150.png


BIN
static/imgs/hex_500_1000_10.png


BIN
static/imgs/logo_partial.png


BIN
static/imgs/no-image-new.png


BIN
static/imgs/no-image-new.webp


BIN
static/imgs/no-image.png


+ 263 - 0
static/js/Bumble.js

@@ -0,0 +1,263 @@
+/**
+ * The globally-accessible Bumble Object
+ * 
+ * Here I can store any and all utilities without taking up space in the
+ * gloabl namespace.
+ */
+var Bumble = {};
+
+/**
+ * The info panel
+ * 
+ * The info panel is a utility that allows me to add information to a page
+ * in such a way that it can easily be closed when the user is done reading
+ * it. 
+ * 
+ * This aims to improve the SEO of pages by adding as much descriptive
+ * text as I want, without harming the usability of the page. This takes into
+ * consideration that most of my pages are, currently, JS games on canvasses.
+ * 
+ * @param {HTMLElement} panel - An HTML element with the .infopanel class
+ */
+Bumble.InfoPanel = function(panel){
+    this.panel = panel;
+    this.head = undefined;
+    this.body = undefined;
+    this.title = undefined
+    this.closer = undefined;
+    this.icons = {
+        close: "uil-times-circle",
+        open: "uil-info-circle"
+    }
+    this.isClosed = false;
+
+    /**
+     * Initialzize the info panel
+     */
+    this.init = function(){
+        if(!this.panel){ throw new Error("Panel not found."); }
+
+        this.head = this.panel.querySelector('.infopanel-head');
+        this.body = this.panel.querySelector('.infopanel-body');
+        this.title = this.head.querySelector('.infopanel-title');
+        this.closer = this.head.querySelector('.infopanel-closer');
+        this.isClosed = this.panel.classList.contains('closed');
+
+        this.closer.addEventListener("click", ()=>{ this.toggleVisibility(); });
+        this.toggleCloseButtonIcon();
+        
+    }
+
+    /**
+     * Close the info panel
+     */
+    this.close = function() {
+        this.panel.classList.add("closed");
+        this.isClosed = true;
+    }
+    /**
+     * Open the info panel
+     */
+    this.open = function() {
+        this.panel.classList.remove("closed")
+        this.isClosed = false;
+    }
+    /**
+     * Toggle the info panel's visibility
+     */
+    this.toggleVisibility = function() {
+        if(this.isClosed) { this.open(); }
+        else { this.close(); }
+        
+        this.toggleCloseButtonIcon();
+    }
+    /**
+     * Toggle the icon of the info panel's open/close button
+     */
+    this.toggleCloseButtonIcon = function() {
+        if(this.isClosed) {
+            this.closer.classList.remove(this.icons.close);
+            this.closer.classList.add(this.icons.open);
+        }
+        else {
+            this.closer.classList.remove(this.icons.open);
+            this.closer.classList.add(this.icons.close);
+        }
+    }
+
+    this.init();
+}
+
+/**
+ * A classic modal
+ * 
+ * @param {string} DOMID - An option string of the DOM ID for premade modal
+ */
+Bumble.Modal = function(DOMID) {
+    this.overlay = undefined;
+    this.modal = {
+        base: undefined,
+        header: undefined,
+        title: undefined,
+        closer: undefined,
+        body: undefined
+    };
+    this.isShown = false;
+
+    this.init = function(DOMID) {
+        // Build the overlay
+        this.overlay = document.createElement("div");
+        this.overlay.classList.add("modal-overlay", "hidden");
+        // Initialize a predefined modal
+        if(DOMID) {
+            const elem = document.getElementById(DOMID);
+            if(!elem){
+                console.warn("No element found with ID: ", DOMID);
+                console.warn("Creating modal");
+            }
+            else {
+                this.modal.pane = elem;
+                this.modal.header = elem.querySelector(".modal-header");
+                this.modal.title = elem.querySelector(".modal-title");
+                this.modal.closer = elem.querySelector(".uil-times-circle");
+                this.modal.body = elem.querySelector(".modal-body");
+            }
+        }
+        // Build the modal from scratch
+        if(!this.modal.pane) {
+            this.modal.pane = document.createElement("div");
+            this.modal.pane.classList.add("modal");
+    
+            this.modal.header = document.createElement("div");
+            this.modal.header.classList.add("modal-header");
+    
+            this.modal.title = document.createElement("div");
+            this.modal.title.classList.add("modal-title");
+    
+            const closerContainer = document.createElement("div");
+            closerContainer.classList.add("modal-closer", "text-right");
+    
+            this.modal.closer = document.createElement("i");
+            this.modal.closer.classList.add("uil", "uil-times-circle");
+            closerContainer.appendChild(this.modal.closer);
+    
+            this.modal.header.append(this.modal.title, closerContainer);
+    
+            this.modal.body = document.createElement("div");
+            this.modal.body.classList.add("modal-body");
+    
+            this.modal.pane.append(this.modal.header, this.modal.body);
+        }
+        // Add event listener to closer button
+        this.modal.closer.addEventListener("click", this.hide.bind(this));
+
+        // Add modal pane to the overlay
+        this.overlay.appendChild(this.modal.pane);
+
+        // Add overlay to body
+        document.body.appendChild(this.overlay);
+
+        return;
+    }
+
+    this.SetTitle = function(title) {
+        this.modal.title.innerText = title;
+    }
+
+    this.SetBody = function(bodyHTML) {
+        this.modal.body.innerHTML = bodyHTML;
+    }
+
+    this.show = function() {
+        this.isShown = true;
+        this._toggleVisibility();
+    }
+
+    this.hide = function() {
+        this.isShown = false;
+        this._toggleVisibility();
+    }
+
+    this._toggleVisibility = function() {
+        if(this.isShown) {
+            this.overlay.classList.remove("hidden");
+        }
+        else {
+            this.overlay.classList.add("hidden");
+        }
+    }
+
+    this.init(DOMID);
+}
+
+/**
+ * Store GET Parameters
+ * 
+ * A convenient place to store and access GET parameters sent to the page.
+ */
+Bumble._GET = {
+    /**
+     * Loads the GET parameters into this object
+     */
+    __init: function() {
+        const params = (new URL(document.location)).searchParams.entries();
+        for(const entry of params) {
+            if(entry[0] == "__init"){ continue; }
+            this[entry[0]] = !isNaN(entry[1]) ? Number(entry[1]) : entry[1];
+        }
+    }
+}
+
+Bumble.XFN = {
+    me: "uil-cell",
+    friend: "uil-user-check",
+    colleague: "uil-books",
+
+    _buildIcon: function(iconClass) {
+        const icon = document.createElement("i");
+            icon.classList.add("uil", iconClass);
+
+        return icon;
+    },
+
+    init: function() {
+        const links = document.querySelectorAll("a[rel]");
+
+        for(const link of links) {
+            const rels = link.rel.split(' ');
+            let rel = null;
+
+            if(rels.indexOf("me") >= 0) {
+                rel = this.me;
+            }
+            else if(rels.indexOf("friend") >= 0) {
+                rel = this.friend;
+            }
+            else if(rels.indexOf("colleague") >= 0) {
+                rel = this.colleague;
+            }
+
+            if(rel) {
+                link.insertAdjacentElement("afterbegin", this._buildIcon(rel));
+            }
+        }
+    },
+}
+
+function page_init() {
+    /* Initialize info panels */
+    const panels = document.querySelectorAll('.infopanel');
+    for(const panel of panels) {
+        panel._infoPanel = new Bumble.InfoPanel(panel);
+    }
+
+    Bumble._GET.__init();
+    Bumble.XFN.init();
+}
+
+if(document.readyState != 'loading') {
+    page_init();
+}
+else {
+    document.addEventListener('DOMContentLoaded', page_init);
+}

+ 10 - 0
static/js/email_me.js

@@ -0,0 +1,10 @@
+const address = "20u21c24h10w23i24 4t13s15s9 3p1";
+const footerEmail = document.getElementById("footer-email");
+const footerDate = document.getElementById("footer-date");
+
+if (footerEmail) {
+    const decoded = decode(address).split(" ");
+    footerEmail.href = "mailto:"+decoded[0]+"@"+decoded[1]+"."+decoded[2];
+    footerEmail.textContent = decoded[0]+"@"+decoded[1]+"."+decoded[2];
+    footerDate.textContent = new Date().getFullYear();
+}

+ 5 - 0
static/robots.txt

@@ -0,0 +1,5 @@
+User-agent: *
+Allow: /
+Disallow: /Fusker/
+
+Sitemap: https://www.vzqk50.com/sitemap.xml

+ 21 - 0
theme.toml

@@ -0,0 +1,21 @@
+# theme.toml template for a Hugo theme
+# See https://github.com/gohugoio/hugoThemes#themetoml for an example
+
+name = "ApisNecros"
+license = "MIT"
+licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
+description = ""
+homepage = "http://example.com/"
+tags = []
+features = []
+min_version = "0.41.0"
+
+[author]
+  name = ""
+  homepage = ""
+
+# If porting an existing theme
+[original]
+  name = ""
+  homepage = ""
+  repo = ""

Някои файлове не бяха показани, защото твърде много файлове са промени