commit d42b958
merc
·
2026-07-12 20:14:56 +0000 UTC
parent d42b958
init
10 files changed,
+413,
-0
A
LICENSE
+21,
-0
1@@ -0,0 +1,21 @@
2+MIT License
3+
4+Copyright (c) 2026 niche-yrittaja
5+
6+Permission is hereby granted, free of charge, to any person obtaining a copy
7+of this software and associated documentation files (the "Software"), to deal
8+in the Software without restriction, including without limitation the rights
9+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+copies of the Software, and to permit persons to whom the Software is
11+furnished to do so, subject to the following conditions:
12+
13+The above copyright notice and this permission notice shall be included in all
14+copies or substantial portions of the Software.
15+
16+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+SOFTWARE.
+30,
-0
1@@ -0,0 +1,30 @@
2+<p align="center">
3+ <img src="/assets/logo.png" alt="logo" width="256" style="max-width: 100%; height: auto;">
4+</p>
5+
6+# merc yayy
7+VERY inspired by uint's [kew](https://github.com/uint23/kew) and uriel's [werc](http://werc.cat-v.org)
8+
9+*logo by [uint23](https://github.com/uint23)
10+
11+## usage:
12+
13+```sh
14+./build.sh
15+```
16+
17+config.env MUST be in the same directory as build.sh
18+
19+## config.env example:
20+
21+```
22+TITLE=my-website <-- tab title
23+FOOTER=made in china <-- bottom text
24+INPUT=~/website-source <-- website's source (has .md files)
25+OUTPUT=/var/www/cool-website <-- where to output the built website
26+NAVDIR=/ <-- symbol that indicates directories i.a 'gallery/'
27+NAVFILE=: <-- symbol that indicates inactive tabs i.a ':inactive'
28+NAVCURRENT=@ <-- symbol that indicates an active tab i.a '@active'
29+
30+you can use spaces at the end of each symbol ("@ ", or ": ")
31+```
+0,
-0
A
build.sh
+203,
-0
1@@ -0,0 +1,203 @@
2+#!/bin/sh
3+
4+set -e
5+
6+verbose=1
7+
8+log() {
9+ [ "$verbose" = 1 ] && echo "$1"
10+}
11+
12+err() {
13+ echo "[error] $1" >&2
14+}
15+
16+setup() {
17+ d=$(dirname "$0")
18+ cf="$d/config.env"
19+
20+ if [ ! -f "$cf" ]; then
21+ err "config.env not found in $d"
22+ exit 1
23+ fi
24+
25+ while IFS='=' read -r k val; do
26+ case "$k" in
27+ TITLE) TITLE="$val" ;;
28+ FOOTER) FOOTER="$val" ;;
29+ OUTPUT) OUTPUT="$val" ;;
30+ INPUT) INPUT="$val" ;;
31+ NAVDIR) NAVDIR="$val" ;;
32+ NAVFILE) NAVFILE="$val" ;;
33+ NAVCURRENT) NAVCURRENT="$val" ;;
34+ esac
35+ done < "$cf"
36+
37+ case "$OUTPUT" in
38+ /*) ;;
39+ ~*) OUTPUT="$HOME${OUTPUT#\~}" ;;
40+ *) OUTPUT="$d/$OUTPUT" ;;
41+ esac
42+
43+ case "$INPUT" in
44+ /*) ;;
45+ ~*) INPUT="$HOME${INPUT#\~}" ;;
46+ *) INPUT="$d/$INPUT" ;;
47+ esac
48+
49+ export TITLE FOOTER OUTPUT INPUT NAVDIR NAVFILE NAVCURRENT
50+
51+ if [ -z "$TITLE" ] || [ -z "$FOOTER" ] || [ -z "$OUTPUT" ] || [ -z "$INPUT" ] || [ -z "$NAVDIR" ] || [ -z "$NAVFILE" ] || [ -z "$NAVCURRENT" ]; then
52+ err "missing variables in config.env"
53+ exit 1
54+ fi
55+
56+ log "TITLE=$TITLE"
57+ log "INPUT=$INPUT"
58+ log "OUTPUT=$OUTPUT"
59+ log "NAVDIR=$NAVDIR"
60+ log "NAVFILE=$NAVFILE"
61+ log "NAVCURRENT=$NAVCURRENT"
62+
63+ if [ ! -d "$INPUT" ]; then
64+ err "source directory not found: $INPUT"
65+ exit 1
66+ fi
67+ if [ ! -f "$INPUT/template.html" ]; then
68+ err "template.html not found in $INPUT"
69+ exit 1
70+ fi
71+
72+ rm -rf "$OUTPUT"
73+ mkdir -p "$OUTPUT"
74+ log "setup complete"
75+}
76+
77+cpstat() {
78+ log "copying static files from $INPUT..."
79+
80+ copyfiles() {
81+ for f in "$1"/* "$1"/.[!.]*; do
82+ [ -e "$f" ] || continue
83+ if [ -d "$f" ]; then
84+ copyfiles "$f"
85+ elif [ -f "$f" ]; then
86+ case "$f" in
87+ *.md|*/template.html) continue ;;
88+ *)
89+ rel="${f#$INPUT/}"
90+ mkdir -p "$(dirname "$OUTPUT/$rel")"
91+ cp "$f" "$OUTPUT/$rel"
92+ log " copied $f -> $OUTPUT/$rel"
93+ ;;
94+ esac
95+ fi
96+ done
97+ }
98+
99+ copyfiles "$INPUT"
100+ log "static copy complete"
101+}
102+
103+md2h() {
104+ cmark -t html "$1" | sed 's/"/"/g; s/'/'"'"'/g'
105+}
106+
107+tname() {
108+ name=${1##*/}
109+ name=${name%.md}
110+ echo "$name" | tr '-' ' '
111+}
112+
113+bnav() {
114+ dir="$1"
115+ cur="$2"
116+ depth="$3"
117+ indent=""
118+ i=0
119+ while [ "$i" -lt "$depth" ]; do
120+ indent="${indent} "
121+ i=$((i + 1))
122+ done
123+
124+ for item in "$dir"/*; do
125+ [ ! -e "$item" ] && continue
126+ name=$(basename "$item")
127+
128+ if [ -d "$item" ]; then
129+ if [ -f "$item/index.md" ]; then
130+ dp="${item#$INPUT}"
131+ [ -z "$dp" ] && dp="/"
132+ echo "${indent}<li><a href=\"${dp}/index.html\">${name}${NAVDIR}</a>"
133+ else
134+ echo "${indent}<li>${name}${NAVDIR}"
135+ fi
136+ echo "${indent} <ul>"
137+ bnav "$item" "$cur" $((depth + 1))
138+ echo "${indent} </ul>"
139+ echo "${indent}</li>"
140+ elif [ -f "$item" ] && [ "${item%.md}" != "$item" ]; then
141+ [ "$name" = "index.md" ] && continue
142+ rel="${item#$INPUT/}"
143+ rel="${rel%.md}.html"
144+ title=$(tname "$item")
145+ if [ "/$rel" = "$cur" ]; then
146+ echo "${indent}<li><a href=\"/$rel\" class=\"active-page\"><span class=\"active-indicator\">${NAVCURRENT}</span>${title}</a></li>"
147+ else
148+ echo "${indent}<li><a href=\"/$rel\">${NAVFILE}${title}</a></li>"
149+ fi
150+ fi
151+ done
152+}
153+
154+rnav() {
155+ echo "<ul>"
156+ bnav "$INPUT" "$1" 1
157+ echo "</ul>"
158+}
159+
160+apply() {
161+ awk -v t="$TITLE" -v n="$1" -v c="$2" -v f="$FOOTER" '
162+ {
163+ gsub(/\{\{TITLE\}\}/, t)
164+ gsub(/\{\{NAV\}\}/, n)
165+ gsub(/\{\{CONTENT\}\}/, c)
166+ gsub(/\{\{FOOTER\}\}/, f)
167+ print
168+ }
169+ ' "$INPUT/template.html"
170+}
171+
172+main() {
173+ setup
174+
175+ S="$INPUT"
176+ S="${S#./}"
177+ S="${S%/}"
178+ log "using source directory: $S"
179+
180+ cpstat
181+
182+ procmd() {
183+ for f in "$1"/*; do
184+ [ -e "$f" ] || continue
185+ if [ -d "$f" ]; then
186+ procmd "$f"
187+ elif [ -f "$f" ] && [ "${f##*.}" = "md" ]; then
188+ f="${f#./}"
189+ r="${f#$S/}"
190+ r="${r%.md}.html"
191+ mkdir -p "$(dirname "$OUTPUT/$r")"
192+ h=$(md2h "$f")
193+ c="/$r"
194+ apply "$(rnav "$c")" "$h" > "$OUTPUT/$r"
195+ log "wrote $OUTPUT/$r"
196+ fi
197+ done
198+ }
199+
200+ procmd "$S"
201+ log "build complete"
202+}
203+
204+main
+7,
-0
1@@ -0,0 +1,7 @@
2+TITLE=template
3+FOOTER=made with <a class='footer-link' href='https://srcdump.net/merc/ssg'>merc</a>
4+INPUT=template
5+OUTPUT=template-out
6+NAVDIR=/
7+NAVFILE=
8+NAVCURRENT=>
+2,
-0
1@@ -0,0 +1,2 @@
2+## where to contact YOU
3+YOUR contact information here
+3,
-0
1@@ -0,0 +1,3 @@
2+## welcome!
3+- this is a website.
4+ - wow.
+3,
-0
1@@ -0,0 +1,3 @@
2+## - xplshn
3+*"At least I fully agree with Karl Marx that child labour is necessary
4+so that kids dont come out messed up and gay"*
+122,
-0
1@@ -0,0 +1,122 @@
2+:root {
3+ --bg: #000000;
4+ --fg: #f1f1f1;
5+ --fg-muted: #8f8f8f;
6+ --fg-link: #fce094;
7+}
8+
9+body {
10+ display: flex;
11+ flex-direction: column;
12+ min-height: 100vh;
13+ margin: 0;
14+ padding: 0;
15+ background: var(--bg);
16+ color: var(--fg);
17+ font-family: serif;
18+ font-size: 16px;
19+ line-height: 0.95;
20+ overflow: hidden;
21+}
22+
23+header {
24+ padding: 20px 0 0 40px;
25+ margin-top: 20px;
26+}
27+
28+header h1 {
29+ margin: 0;
30+ font-size: 35px;
31+ font-weight: normal;
32+ font-style: italic;
33+}
34+
35+#side-bar {
36+ position: absolute;
37+ top: 120px;
38+ left: 0;
39+ width: 200px;
40+ padding-left: 20px;
41+}
42+
43+.side-title {
44+ font-size: 25px;
45+ margin: 20px 0 8px 0;
46+ color: var(--fg);
47+}
48+
49+#side-bar ul {
50+ margin: 0 0 0 20px;
51+ padding: 0px;
52+ list-style: none;
53+}
54+
55+#side-bar li {
56+ margin: 6px 0;
57+ white-space: nowrap;
58+}
59+
60+#side-bar a {
61+ display: inline-block;
62+}
63+
64+.active-page {
65+ position: relative;
66+ display: inline-block;
67+ color: var(--fg-link);
68+}
69+
70+.active-indicator {
71+ position: absolute;
72+ right: 100%;
73+ margin-right: 0.25rem;
74+ color: var(--fg);
75+}
76+
77+a {
78+ color: var(--fg-link);
79+ text-decoration: none;
80+ padding: 1px 2px;
81+}
82+
83+a:hover {
84+ background: var(--fg);
85+ color: var(--bg);
86+ text-decoration: underline;
87+}
88+
89+h1, h2, h3, h4, h5, h6 {
90+ margin-top: 30px;
91+ color: var(--fg);
92+ font-weight: normal;
93+}
94+
95+footer {
96+ margin-top: auto;
97+ margin-left: 30px;
98+ font-style: italic;
99+ font-size: 17px;
100+ background: var(--bg);
101+ position: relative;
102+}
103+
104+.footer-link {
105+ text-decoration: underline;
106+}
107+
108+article {
109+ max-width: 800px;
110+ margin: 80px 0 0 0;
111+ margin-left: 240px;
112+ margin-top: 0px;
113+ line-height: 1.25;
114+ position: relative;
115+ top: 15px;
116+}
117+
118+article img {
119+ max-width: 100%;
120+ width: auto;
121+ height: 70vh;
122+ border: 2px dotted var(--fg-link);
123+}
+22,
-0
1@@ -0,0 +1,22 @@
2+<!DOCTYPE html>
3+<html>
4+<head>
5+ <meta charset="UTF-8">
6+ <title>{{TITLE}}</title>
7+ <link rel="stylesheet" href="/style.css" type="text/css">
8+</head>
9+<body>
10+ <header>
11+ <h1><a href="/index.html">~website</a></h1>
12+ </header>
13+ <nav id="side-bar">
14+ {{NAV}}
15+ </nav>
16+ <article>
17+ {{CONTENT}}
18+ </article>
19+ <footer>
20+ <p>{{FOOTER}}</p>
21+ </footer>
22+</body>
23+</html>