commit d42b958

merc  ·  2026-07-12 20:14:56 +0000 UTC
parent d42b958
init
10 files changed,  +413, -0
+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
+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/&quot;/"/g; s/&#39;/'"'"'/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>