Compare commits

...

14 commits

10 changed files with 450 additions and 128 deletions

View file

@ -13,7 +13,6 @@ IndentCaseLabels: true
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
AlignAfterOpenBracket: AlwaysBreak AlignAfterOpenBracket: AlwaysBreak
BinPackArguments: false BinPackArguments: false
BinPackArguments: false
PointerAlignment: Left PointerAlignment: Left
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
SortIncludes: false SortIncludes: false

View file

@ -1,4 +1,4 @@
Copyright 2021 Derek Stevens Copyright 2021 Iris Lightshard
Copyright 2021 Devine Lu Linvega Copyright 2021 Devine Lu Linvega
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: 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:

View file

@ -17,6 +17,8 @@ Eureka also parses a [twtxt](https://twtxt.readthedocs.io/en/latest/) file at `S
5. Create a new page, eg `inc/my_first_page.htm` (see the markup section below). 5. Create a new page, eg `inc/my_first_page.htm` (see the markup section below).
6. Edit your `inc/meta.nav.htm` again to reference your new page. 6. Edit your `inc/meta.nav.htm` again to reference your new page.
7. Run `./build.sh` again! You will be warned of any orphaned files. 7. Run `./build.sh` again! You will be warned of any orphaned files.
8. Deploy with `./deploy.sh`. `--syndicate` will syndicate the latest twtxt to the honknet.
9. Revert changes and restore local with the live site with `./deploy.sh --resync`.
## build options ## build options
@ -34,6 +36,8 @@ Combined argument format like `./build.sh -rdt "twt stuff"` is not supported. Us
If you run into issues with your markup crashing `eureka`, edit the `build.sh` file to uncomment the linux debug build line and comment the fast build; this will show you a stack trace of where you are running into buffer overflows, and give you a hint of where your markup is messed up. To see the individual file that has the error, also uncomment the line in `fpinject()` that prints the file names. If you run into issues with your markup crashing `eureka`, edit the `build.sh` file to uncomment the linux debug build line and comment the fast build; this will show you a stack trace of where you are running into buffer overflows, and give you a hint of where your markup is messed up. To see the individual file that has the error, also uncomment the line in `fpinject()` that prints the file names.
If you find a bug, let me know.
# markup # markup
There is a markup language which makes writing long blog posts, memex entries, etc easier by reducing the need for typing out HTML tags: There is a markup language which makes writing long blog posts, memex entries, etc easier by reducing the need for typing out HTML tags:
@ -81,7 +85,7 @@ There is a markup language which makes writing long blog posts, memex entries, e
{@bold text} {@bold text}
// shorthand for italic // shorthand for italic
{~italic text} {\italic text}
// shorthand for code // shorthand for code
{`short code} {`short code}
@ -96,7 +100,7 @@ There is a markup language which makes writing long blog posts, memex entries, e
{>longer quote} {>longer quote}
// shorthand for strikethrough // shorthand for strikethrough
{\crossed-out text} {~crossed-out text}
// shorthand for level 3 heading // shorthand for level 3 heading
{!heading text} {!heading text}
@ -104,8 +108,25 @@ There is a markup language which makes writing long blog posts, memex entries, e
// shorthand for level 4 heading // shorthand for level 4 heading
{.heading text} {.heading text}
// shorthand for tables
{[column 1 header|column 2 header|column 3 header}
{|simple data|{@bold data}|{*https://nilfm.cc|link data}}
{|more|and more|and more data!}
{;}
// shorthand for publish date (renders as <time class='publish-date'>) // shorthand for publish date (renders as <time class='publish-date'>)
{+2022-02-22} {+2022-02-22}
// shorthand for explicit monospace, sans, and serif font respecively:
{=some mono text}
{(some sans serif text}
{)some serif text}
// shorthand for a pictured directory/list item
{%page name|picture}
// shorthand for a shop listing
{^payment-link|description|img1|alttext1|...|imgn|alttextn}
``` ```
# configuration # configuration
@ -116,12 +137,16 @@ The following macros are available in `config.h` to customize to your liking.
- **TAG\_BODY\_SIZE**: max size for an individual markup body (ie, a markup token as above, minus the curly brackets and the rune), in bytes - **TAG\_BODY\_SIZE**: max size for an individual markup body (ie, a markup token as above, minus the curly brackets and the rune), in bytes
- **NAME**: the title of the site - **NAME**: the title of the site
- **DOMAIN**: currently unused - **DOMAIN**: currently unused
- **LOGO**: HTML to put in the header h1 verbatim - **LOGO_HTML**: HTML to put in the header h1 verbatim
- **ABOUT**: HTML content for the front page, placed between `<header>` and `<nav>` - **ABOUT_HTML**: HTML content for the front page
- **CONTACT**: the contact info line at the bottom of every page (except the front page, where it would typically already be in **@ABOUT** - **CONTACT_HTML**: the contact info line at the bottom of every page (except the front page, where it would typically already be in **@ABOUT**
- **FOOTER**: arbitrary footer HTML - **FOOTER_HTML**: arbitrary footer HTML
- **LICENSE**: the license link at the bottom of every page - **LICENSE_HTML**: the license link at the bottom of every page
- **SITEROOT**: the path where the rendered HTML is placed - **SITEROOT**: the path where the rendered HTML is placed; include trailing slash
- **MAINCSS** and **FRONTCSS**: to differentiate styles used for the landing page and the rest of the site - **MAINCSS** and **FRONTCSS**: to differentiate styles used for the landing page and the rest of the site
- **TWTXT**: path to the twtxt file relative to the SITEROOT; if you don't want twtxt on the front page, use a nonexistent filename
- **IS_HTML5_VIDEO_ENABLED**: if videos are embedded or just linked to with a poster image
- **IS_NAV_IN_HEADER**: if the nav is inside the header or its sibling
- **DEPLOY_DEST** and **DEPLOOY_IDENT**: ssh location (host:path) and key name for deployment
- **CONTACT_ADDRESS** email address for ecommerce and can be interpolated in CONTACT_HTML

View file

@ -16,13 +16,15 @@ if [ ! -e inc/meta.nav.htm ]; then
fi fi
# Lint # Lint
clang-format -i main.c config.h if which clang-format > /dev/null; then
clang-format -i main.c config.h
fi
# Cleanup # Cleanup
rm -f ./main rm -f ./main
# Linux(debug) # Linux(debug)
#cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wuninitialized -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined main.c -o main # cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wuninitialized -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined main.c -o main
# Linux(fast) # Linux(fast)
cc main.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o main cc main.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o main

View file

@ -1,37 +1,22 @@
#define DESC "lair of drkste aka nilix: artist, programmer, philosopher" /* clang-format off */
#define LEXICON_SIZE 1024 #define SITEMAP "all_pages"
#define MAINCSS "/new.css" #define DOMAIN "https://amotherfucking.website"
#define FOOTER \ #define DEPLOY_DEST "usr@amotherfucking.website:/opt/site/"
"<a href='/git/'><img src='/img/git.svg' alt='visit the nilFM hack " \ #define DEPLOY_IDENT "id_sub"
"lab.'/></a>&nbsp;\n" \
"<a rel='me' href='https://cafe.nilfm.cc/u/nilix'><img src='/img/honk.svg' " \
"alt='visit me on the Fediverse.'/></a>&nbsp;\n" \
"<a href='https://webring.xxiivv.com'><img src='/img/webring.svg' " \
"alt='visit the Webring.'/></a><br/>\n" \
"<a href='/sitemap.html'>sitemap</a><br/>\n"
#define LICENSE \
"<a rel='license' " \
"href='https://creativecommons.org/licenses/by-nc/4.0/" \
"legalcode.txt'>CC-BY-NC 4</a><br/>\n" \
"<a href='/legal_disclaimer.html'>opinions are my own</a>"
#define SITEROOT "../www/"
#define TAG_BODY_SIZE 4096 #define TAG_BODY_SIZE 4096
#define CONTACT \ #define LOGO_HTML "<img src='/img/logo.png' alt='a website'/>"
"contact: <a href='mailto:nilix@nilfm.cc'>nilix@nilfm.cc</a> (<a " \ #define MAINCSS "/main.css"
"href='keys.html'>keys</a>)<br/>\n" \ #define FOOTER_HTML "peekaboo"
"" #define LICENSE_HTML "<a rel='license' target='_blank' href='/legal.html'>legal</a>"
#define DOMAIN "https://nilfm.cc" #define DESC "website eeeeeeee"
#define IS_NAV_IN_HEADER 01
#define LEXICON_SIZE 1024
#define CONTACT_HTML "<a href='mailto:person@domain.net' class='mono'contact me</a>"
#define FRONTCSS "/front.css" #define FRONTCSS "/front.css"
#define ABOUT \ #define SITEROOT "../www/"
"Derek Stevens &lt;<a " \ #define TWTXT "/twtxt.txt"
"href='mailto:nilix@nilfm.cc'>nilix@nilfm.cc</a>&gt;<br/>\n" \ #define ABOUT_HTML "<h2>Welcome to this website</h2>"
"artist, programmer, philosopher<br/><br/>\n" \ #define NAME "a website"
"verify my signature: <a " \ #define IS_HTML5_VIDEO_ENABLED 0
"href='/serv/90587A740FA4FFA0971575383B7FBC22144E6398.asc'>signing public " \ #define CONTACT_ADDRESS "contact@amotherfuckingwebsite.com"
"key</a><br/>\n" \ /* clang-format on */
"send me an encrypted message: <a " \
"href='/serv/F5672E001CC962BE3B6C8887C65B677280C66DE5.asc'>encryption " \
"public key</a>\n" \
""
#define LOGO "<img src='/img/nilfm_blackHole_96.png' alt='blackHole://server'/>"
#define NAME "nilFM"

View file

@ -1,3 +1,15 @@
DEST="nilix@lynx.uberspace.de:~/lib/nilfm/" #!/bin/sh
rsync -avK --delete ../ ${DEST} DEST=$(grep "#define DEPLOY_DEST" config.h | awk '{print $3}' | sed -e 's/"//g')
IDENT=$(grep "#define DEPLOY_IDENT" config.h | awk '{print $3}' | sed -e 's/"//g')
SITEROOT=$(grep "#define SITEROOT" config.h | awk '{print $3}' | sed -e 's/"//g')
TWTXT=$(grep "#define TWTXT" config.h | awk '{print $3}' | sed -e 's/"//g')
if [ "$1" = "--resync" ]; then
rsync -avk -e "ssh -i ~/.ssh/${IDENT}" --delete ${DEST} ../
else
rsync -avK -e "ssh -i ~/.ssh/${IDENT}" --delete ../ ${DEST}
if [ "$1" = "--syndicate" ] && [ $? -eq 0 ]; then
./underbbs.sh honk "$(cat ${SITEROOT}/${TWTXT} | head -n 1 | cut -f 2)"
fi
fi

372
main.c
View file

@ -2,14 +2,14 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/dir.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
#include "config.h" #include "config.h"
/* /*
Copyright (c) 2021 Derek Stevens Copyright (c) 2021 Iris Lightshard
Copyright (c) 2021 Devine Lu Linvega Copyright (c) 2021 Devine Lu Linvega
Permission to use, copy, modify, and distribute this software for any Permission to use, copy, modify, and distribute this software for any
@ -46,12 +46,20 @@ int clin(char *str, char c) {int i = -1; int j = 0; while(str[j] != '\0'){if(str
/* clang-format on */ /* clang-format on */
int fpinject(FILE* f, Lexicon* l, char* filepath); int fpinject(FILE* f, Lexicon* l, char* filepath);
int fptemplate(FILE*, Lexicon*, char*);
int fpmetatemplate(FILE*, Lexicon*, char*);
int error(char* msg, char* val) { int error(char* msg, char* val) {
printf("Error: %s(%s)\n", msg, val); printf("Error: %s(%s)\n", msg, val);
return 0; return 0;
} }
void clearstr(char* s) {
while (*s) {
*s++ = 0;
}
}
time_t getlater(time_t a, time_t b) { return a > b ? a : b; } time_t getlater(time_t a, time_t b) { return a > b ? a : b; }
int ismetanav(char* name) { return scmp(name, "meta.nav"); } int ismetanav(char* name) { return scmp(name, "meta.nav"); }
@ -67,20 +75,25 @@ int findf(Lexicon* l, char* f) {
} }
int gettwtxt(FILE* f) { int gettwtxt(FILE* f) {
char buf[1024] = {0}; char buf[1024] = {0};
char line[256]; char line[256];
char datebuf[16] = {0}; char datebuf[16] = {0};
char msgbuf[240] = {0}; char msgbuf[240] = {0};
char *l, *d, *m; char urlbuf[256] = {0};
FILE* twtxt = fopen(SITEROOT "twtxt.txt", "r"); char* l;
FILE* twtxt = fopen(SITEROOT TWTXT, "r");
scat(buf, "<div id='twtxtFeed'><h2>recent activity:</h2>\n<table>\n"); scat(buf, "<div id='twtxtFeed'><h2>recent activity</h2>\n<table>\n");
if (!twtxt) { if (!twtxt) {
error("Get twtxt feed", "no twtxt.txt"); return 1;
return 0;
} else { } else {
int i = 0; int i = 0;
while (fgets(line, 256, twtxt) && i < 3) { while (fgets(line, 256, twtxt) && i < 3) {
int has_url = 0;
if (*line == '#') {
continue;
}
l = line; l = line;
while (*l != 'T') { while (*l != 'T') {
ccat(datebuf, *l++); ccat(datebuf, *l++);
@ -88,24 +101,39 @@ int gettwtxt(FILE* f) {
while (*l != '\t') { while (*l != '\t') {
l++; l++;
} }
scat(msgbuf, l); while (*l) {
scat(buf, "<tr><td style='white-space:nowrap;vertical-align: top;'>"); if (*l == '|') {
has_url = 1;
break;
}
ccat(msgbuf, *l++);
}
l++;
scat(urlbuf, l);
scat(
buf,
"<tr><td class='twtxt-date' style='white-space:nowrap;vertical-align: "
"top;'>");
scat(buf, datebuf); scat(buf, datebuf);
scat(buf, ":</td><td> "); scat(buf, "</td><td class='twtxt-twt'> ");
if (has_url) {
scat(buf, "<a href='");
scat(buf, urlbuf);
scat(buf, "'>");
scat(buf, msgbuf); scat(buf, msgbuf);
scat(buf, "</a>");
} else {
scat(buf, msgbuf);
}
scat(buf, "</td></tr>\n"); scat(buf, "</td></tr>\n");
d = datebuf; clearstr(datebuf);
while (*d) { clearstr(msgbuf);
*d++ = 0; clearstr(urlbuf);
}
m = msgbuf;
while (*m) {
*m++ = 0;
}
i++; i++;
} }
fclose(twtxt); fclose(twtxt);
scat(buf, "</table><a href='/twtxt.txt'>see all</a>\n"); scat(buf, "</table><a href='" TWTXT "'>see all</a>\n");
scat(buf, "</div>\n"); scat(buf, "</div>\n");
fputs(buf, f); fputs(buf, f);
return 1; return 1;
@ -114,7 +142,7 @@ int gettwtxt(FILE* f) {
void fpedited(FILE* f) { void fpedited(FILE* f) {
struct tm timebuf; struct tm timebuf;
char strbuf[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; char strbuf[16] = {0};
timebuf = *localtime(&edittime); timebuf = *localtime(&edittime);
strftime(strbuf, 16, "%Y-%m-%d", &timebuf); strftime(strbuf, 16, "%Y-%m-%d", &timebuf);
@ -228,6 +256,69 @@ int fpimg(FILE* f, char* s) {
return 1; return 1;
} }
int fpthead(FILE* f, char* s) {
char sbuf[TAG_BODY_SIZE] = {0};
char* c = s;
int data = 0;
fputs("<table><thead><tr>\n", f);
while (*c) {
data = 1;
if (*c != '|') {
ccat(sbuf, *c);
} else {
fprintf(f, "<th>%s</th>\n", sbuf);
sbuf[0] = 0;
}
c++;
}
if (data) {
fprintf(f, "<th>%s</th>\n", sbuf);
}
fputs("</tr></thead>\n<tbody>", f);
return 1;
}
int fptbody(FILE* f, Lexicon* l, char* s) {
char sbuf[TAG_BODY_SIZE] = {0};
char* c = s;
int data = 0;
int bopen = 0;
int bclose = 0;
fputs("<tr>\n", f);
while (*c) {
data = 1;
if (*c == '{') {
bopen++;
}
if (*c == '}') {
bclose++;
}
if (*c != '|' || bopen != bclose) {
ccat(sbuf, *c);
} else {
fputs("<td>", f);
fpmetatemplate(f, l, sbuf);
fputs("</td>\n", f);
sbuf[0] = 0;
}
c++;
}
if (data) {
fputs("<td>", f);
fpmetatemplate(f, l, sbuf);
fputs("</td>\n", f);
}
fputs("</tr>", f);
return 1;
}
int fptfoot(FILE* f) {
fputs("</tbody></table>", f);
return 1;
}
int fphimg(FILE* f, char* s) { int fphimg(FILE* f, char* s) {
char id[1024] = {0}; char id[1024] = {0};
char href[1024] = {0}; char href[1024] = {0};
@ -299,14 +390,19 @@ int fpvideo(FILE* f, char* s) {
} }
thumbtrans(src, thumb); thumbtrans(src, thumb);
if (IS_HTML5_VIDEO_ENABLED) {
fprintf( fprintf(
f, f,
"<video id='%s' src='%s' controls preload='metadata' poster='%s'>\n", "<video id='%s' src='%s' controls preload='metadata' poster='%s'>\n",
id, id,
href, href,
thumb); thumb);
fprintf(f, "<a href='%s'><img src='%s' alt=''%s'></a>\n", href, thumb, alt); }
fprintf(f, "<a href='%s'><img src='%s' alt='%s'></a>\n", href, thumb, alt);
if (IS_HTML5_VIDEO_ENABLED) {
fprintf(f, "</video>\n"); fprintf(f, "</video>\n");
}
return 1; return 1;
} }
@ -321,28 +417,46 @@ int fpaudio(FILE* f, char* s) {
return 1; return 1;
} }
int fptemplate(FILE*, Lexicon*, char*); int fpmono(FILE* f, Lexicon* l, char* s) {
int fpmetatemplate(FILE*, Lexicon*, char*); fputs("<span style='font-family:monospace;'>", f);
int ret = fpmetatemplate(f, l, s);
fputs("</span>", f);
return ret;
}
int fpserif(FILE* f, Lexicon* l, char* s) {
fputs("<span style='font-family:serif;'>", f);
int ret = fpmetatemplate(f, l, s);
fputs("</span>", f);
return ret;
}
int fpsans(FILE* f, Lexicon* l, char* s) {
fputs("<span style='font-family:sans;'>", f);
int ret = fpmetatemplate(f, l, s);
fputs("</span>", f);
return ret;
}
int fppara(FILE* f, Lexicon* l, char* s) { int fppara(FILE* f, Lexicon* l, char* s) {
fputs("<p>", f); fputs("<p>", f);
fpmetatemplate(f, l, s); int ret = fpmetatemplate(f, l, s);
fputs("</p>", f); fputs("</p>", f);
return 1; return ret;
} }
int fpul(FILE* f, Lexicon* l, char* s) { int fpul(FILE* f, Lexicon* l, char* s) {
fputs("<ul>", f); fputs("<ul>", f);
fpmetatemplate(f, l, s); int ret = fpmetatemplate(f, l, s);
fputs("</ul>", f); fputs("</ul>", f);
return 1; return ret;
} }
int fpol(FILE* f, Lexicon* l, char* s) { int fpol(FILE* f, Lexicon* l, char* s) {
fputs("<ol>", f); fputs("<ol>", f);
fpmetatemplate(f, l, s); int ret = fpmetatemplate(f, l, s);
fputs("</ol>", f); fputs("</ol>", f);
return 1; return ret;
} }
int fppublish(FILE* f, char* s) { int fppublish(FILE* f, char* s) {
@ -354,9 +468,9 @@ int fppublish(FILE* f, char* s) {
int fpli(FILE* f, Lexicon* l, char* s) { int fpli(FILE* f, Lexicon* l, char* s) {
fputs("<li>", f); fputs("<li>", f);
fpmetatemplate(f, l, s); int ret = fpmetatemplate(f, l, s);
fputs("</li>", f); fputs("</li>", f);
return 1; return ret;
} }
int fph3(FILE* f, char* s) { int fph3(FILE* f, char* s) {
@ -396,9 +510,9 @@ int fpitalic(FILE* f, char* s) {
int fpstrike(FILE* f, Lexicon* l, char* s) { int fpstrike(FILE* f, Lexicon* l, char* s) {
fputs("<s>", f); fputs("<s>", f);
fpmetatemplate(f, l, s); int ret = fpmetatemplate(f, l, s);
fputs("</s>", f); fputs("</s>", f);
return 1; return ret;
} }
int fppre(FILE* f, char* s) { int fppre(FILE* f, char* s) {
@ -422,6 +536,139 @@ int fpblock(FILE* f, char* s) {
return 1; return 1;
} }
int fppiclisting(FILE* f, Lexicon* l, char* s) {
char desc[1024] = {0};
char href[1024] = {0};
char img[1024] = {0};
char metaimg[1024] = {0};
int target = 0;
char* c = s;
int i = 0;
while (i < 2) {
if (*c == '|' || !(*c)) {
i++;
c++;
continue;
}
switch (i) {
case 0:
ccat(desc, *c++);
break;
case 1:
ccat(img, *c++);
break;
}
}
scpy(desc, href, slen(desc) + 1);
scsw(stlc(href), ' ', '_');
scat(metaimg, href);
scat(metaimg, "|/");
scat(metaimg, href);
scat(metaimg, ".html|");
scat(metaimg, img);
scat(metaimg, desc);
fputs("<li>", f);
fphimg(f, metaimg);
target = findf(l, desc);
if (target < 0) {
return error("Missing link", s);
}
fprintf(f, "<a href='/%s.html' class='local'>", scsw(stlc(desc), ' ', '_'));
fprintf(f, "%s</a>", scsw(stlc(desc), '_', ' '));
l->refs[target]++;
fputs("</li>", f);
return 1;
}
int fpshop(FILE* f, Lexicon* l, char* s) {
char paylink[1024] = {0};
char desc[1024] = {0};
char img[1024] = {0};
char alt[1024] = {0};
char metaimg[1024] = {0};
char imgcountbuf[12] = {0};
int imgcount = 0;
char* c = s;
int i = 0;
while (i < 2) {
if (*c == '|' || !(*c)) {
i++;
c++;
continue;
}
switch (i) {
case 0:
ccat(paylink, *c++);
break;
case 1:
ccat(desc, *c++);
break;
}
}
fputs("<div class='product'><div class='product-imgs'>", f);
for (;;) {
if (*c == '|' || !(*c)) {
if (i % 2 == 0) {
clearstr(metaimg);
sprintf(imgcountbuf, "%d", ++imgcount);
scat(metaimg, "img");
scat(metaimg, imgcountbuf);
scat(metaimg, "|");
scat(metaimg, img);
scat(metaimg, "|");
} else {
scat(metaimg, alt);
fpimg(f, metaimg);
clearstr(imgcountbuf);
clearstr(img);
clearstr(alt);
}
if (!(*c)) {
if (i % 2 == 0) {
return error("Needs even number of args", s);
} else {
break;
}
}
i++;
c++;
continue;
}
if (i % 2 == 0) {
ccat(img, *c++);
} else {
ccat(alt, *c++);
}
}
fputs("</div>", f);
fppara(f, l, desc);
fprintf(
f,
"<div class='cta'><a href='%s'>purchase</a><a href='mailto:" CONTACT_ADDRESS
"'>inquire</a></div>",
paylink);
fputs("</div>", f);
return 1;
}
int fptemplate(FILE* f, Lexicon* l, char* s) { int fptemplate(FILE* f, Lexicon* l, char* s) {
int target = 0; int target = 0;
switch (s[0]) { switch (s[0]) {
@ -439,7 +686,7 @@ int fptemplate(FILE* f, Lexicon* l, char* s) {
return fpaudio(f, s + 1); return fpaudio(f, s + 1);
case '`': case '`':
return fpcode(f, s + 1); return fpcode(f, s + 1);
case '~': case '\\':
return fpitalic(f, s + 1); return fpitalic(f, s + 1);
case '>': case '>':
return fpblock(f, s + 1); return fpblock(f, s + 1);
@ -449,7 +696,7 @@ int fptemplate(FILE* f, Lexicon* l, char* s) {
return fppre(f, s + 1); return fppre(f, s + 1);
case '@': case '@':
return fpbold(f, s + 1); return fpbold(f, s + 1);
case '\\': case '~':
return fpstrike(f, l, s + 1); return fpstrike(f, l, s + 1);
case '!': case '!':
return fph3(f, s + 1); return fph3(f, s + 1);
@ -465,6 +712,22 @@ int fptemplate(FILE* f, Lexicon* l, char* s) {
return fpli(f, l, s + 1); return fpli(f, l, s + 1);
case '&': case '&':
return fppara(f, l, s + 1); return fppara(f, l, s + 1);
case '[':
return fpthead(f, s + 1);
case '|':
return fptbody(f, l, s + 1);
case ';':
return fptfoot(f);
case '=':
return fpmono(f, l, s + 1);
case '(':
return fpsans(f, l, s + 1);
case ')':
return fpserif(f, l, s + 1);
case '%':
return fppiclisting(f, l, s + 1);
case '^':
return fpshop(f, l, s + 1);
} }
if (s[0]) { if (s[0]) {
target = findf(l, s); target = findf(l, s);
@ -472,7 +735,7 @@ int fptemplate(FILE* f, Lexicon* l, char* s) {
if (target < 0) { if (target < 0) {
return error("Missing link", s); return error("Missing link", s);
} }
fprintf(f, "<a href='./%s.html' class='local'>", scsw(stlc(s), ' ', '_')); fprintf(f, "<a href='/%s.html' class='local'>", scsw(stlc(s), ' ', '_'));
fprintf(f, "%s</a>", scsw(stlc(s), '_', ' ')); fprintf(f, "%s</a>", scsw(stlc(s), '_', ' '));
l->refs[target]++; l->refs[target]++;
return 1; return 1;
@ -574,10 +837,10 @@ int fpfooter(FILE* f, char* name) {
fputs("<footer>", f); fputs("<footer>", f);
if (!ismetanav(name)) { if (!ismetanav(name)) {
fpedited(f); fpedited(f);
fputs(CONTACT, f); fputs(CONTACT_HTML, f);
} }
fputs(FOOTER, f); fputs(FOOTER_HTML, f);
fputs(LICENSE, f); fputs(LICENSE_HTML, f);
fputs("</footer>", f); fputs("</footer>", f);
return 1; return 1;
} }
@ -610,22 +873,23 @@ FILE* build(FILE* f, Lexicon* l, char* name, char* srcpath) {
fputs("<body>\n", f); fputs("<body>\n", f);
/* header */ /* header */
fputs("<header>\n", f); fputs("<header>\n", f);
if (ismetanav(name)) { fputs("<a href='/'><h1>" LOGO_HTML "</h1></a>\n", f);
fputs("<h1>" LOGO "</h1>\n", f); if (IS_NAV_IN_HEADER) {
} else {
fputs("<a href='/'><h1>" LOGO "</h1></a>\n", f);
}
fputs("</header>\n", f);
/* about (main page only) */
if (ismetanav(name)) {
fputs("<div id='about'>" ABOUT "</div>\n", f);
}
/* nav */ /* nav */
fputs("<nav>\n", f); fputs("<nav>\n", f);
if (!fpportal(f, l, "meta.nav", 0)) if (!fpportal(f, l, "meta.nav", 0))
printf(">>> Building failed: %s\n", name); printf(">>> Building failed: %s\n", name);
fputs("</nav>\n", f); fputs("</nav>\n", f);
fputs("</header>\n", f);
} else {
fputs("</header>\n", f);
/* nav */
fputs("<nav>\n", f);
if (!fpportal(f, l, "meta.nav", 0))
printf(">>> Building failed: %s\n", name);
fputs("</nav>\n", f);
}
/* main */ /* main */
stat(srcpath, &attr); stat(srcpath, &attr);
edittime = attr.st_mtime; edittime = attr.st_mtime;
@ -636,6 +900,8 @@ FILE* build(FILE* f, Lexicon* l, char* name, char* srcpath) {
printf(">>> Building failed: %s\n", name); printf(">>> Building failed: %s\n", name);
fputs("\n</main>", f); fputs("\n</main>", f);
} else { } else {
/* about & twtxt (main page only) */
fputs("<div id='about'>" ABOUT_HTML "</div>\n", f);
gettwtxt(f); gettwtxt(f);
} }
/* footer */ /* footer */
@ -696,6 +962,7 @@ void inspect(Lexicon* l) {
void map(Lexicon* l) { void map(Lexicon* l) {
char dstpath[64]; char dstpath[64];
char srcpath[64]; char srcpath[64];
char sitemapName[] = SITEMAP "\0";
struct dirent** d; struct dirent** d;
FILE* siteMap; FILE* siteMap;
int n, i = 0; int n, i = 0;
@ -705,7 +972,7 @@ void map(Lexicon* l) {
dstpath[0] = 0; dstpath[0] = 0;
srcpath[0] = 0; srcpath[0] = 0;
scat(dstpath, SITEROOT); scat(dstpath, SITEROOT);
scat(dstpath, "sitemap.html"); scat(dstpath, SITEMAP ".html");
scat(srcpath, "map.htm"); scat(srcpath, "map.htm");
siteMap = fopen("map.htm", "w"); siteMap = fopen("map.htm", "w");
/* don't use shorthand for the <ul> tag because it will easily overflow /* don't use shorthand for the <ul> tag because it will easily overflow
@ -728,7 +995,8 @@ void map(Lexicon* l) {
free(d); free(d);
fprintf(siteMap, "</ul>\n"); fprintf(siteMap, "</ul>\n");
fclose(siteMap); fclose(siteMap);
fclose(build(fopen(dstpath, "w"), l, "sitemap", srcpath)); fclose(build(fopen(dstpath, "w"), l, scsw(sitemapName, '_', ' '), srcpath));
remove("map.htm");
printf("Created sitemap\n"); printf("Created sitemap\n");
} }

View file

@ -5,14 +5,12 @@ SIZE=500
# transform path to /img/*/.thumb/ # transform path to /img/*/.thumb/
pathtrans() { pathtrans() {
filename=$(echo $1 | awk -F/ '{print $NF}') filename=$(basename "${1%.*}")
filename=$(echo ${filename} | awk 'BEGIN{FS=OFS="."}{NF--; print $0}') pathname="${1%/*}"
transform=$(echo $1 | awk 'BEGIN{FS=OFS="/"}{NF--; print $0}') if [ ! -d ${pathname}/.thumb ]; then
if [ ! -d ${transform}/.thumb ]; then mkdir ${pathname}/.thumb/
mkdir ${transform}/.thumb/
fi fi
transform=${transform}/.thumb/${filename}.png echo "${pathname}/.thumb/${filename}.png"
echo ${transform}
} }
# generate thumbnails in /img/*/.thumb/ # generate thumbnails in /img/*/.thumb/
@ -23,19 +21,19 @@ resize() {
fi fi
if [ ! -f ${output} ]; then if [ ! -f ${output} ]; then
echo "Stripping metadata from $1" echo "Stripping metadata from $1"
convert $1 -strip $1 convert "$1" -strip "$1"
echo "Generating thumbnail for $1" echo "Generating thumbnail for $1"
convert $1 -strip -auto-orient -resize ${SIZE} -dither FloydSteinberg -colors 16 ${output} convert "$1" -strip -auto-orient -resize ${SIZE} -dither FloydSteinberg -colors 16 ${output}
fi fi
} }
if [ -z $1 ]; then if [ -z "$1" ]; then
echo "usage: $0 [build|clean]" echo "usage: $0 [build|clean]"
else else
case $1 in case $1 in
"build") "build")
echo "Updating thumbnails cache" echo "Updating thumbnails cache"
for x in $(find ${SRC}/*/*); do resize $x; done;; for x in $(find ${SRC}/*/*); do resize "$x"; done;;
"clean") "clean")
echo "Cleaning thumbnails cache" echo "Cleaning thumbnails cache"
rm -rf ${SRC}/*/.thumb rm -rf ${SRC}/*/.thumb

10
tw.sh
View file

@ -1,13 +1,13 @@
#!/bin/sh #!/bin/sh
twtxt=../www/twtxt.txt siteroot=$(grep "#define SITEROOT" config.h | awk '{print $3}' | sed -e 's/"//g')
twtxt=$(grep "#define TWTXT" config.h | awk '{print $3}' | sed -e 's/"//g')
twt(){ twt(){
self=$(mktemp) self=$(mktemp)
new=$(mktemp) new=$(mktemp)
echo "$(date -Is)\t$@" > ${self} echo "$(/sbin/date -Is)\t$@" > ${self}
cat ${self} ${twtxt} > ${new} cat ${self} ${siteroot}${twtxt} > ${new}
cp ${new} ${twtxt} cp ${new} ${siteroot}${twtxt}
rm ${new} rm ${new}
rm ${self} rm ${self}
} }

33
underbbs.sh Executable file
View file

@ -0,0 +1,33 @@
#!/bin/sh
. ~/.config/underbbs/cli
helpme() {
echo "later"
}
syndicate_honk() {
# authenticate to the honknet
local token=$(curl -X POST -F "username=${HONK_USERNAME}" -F "password=${HONK_PASSWORD}" -F "gettoken=1" ${HONK_URL}/dologin)
# it's gonna be honked
local result=$(curl -X POST -F "action=honk" -F "token=${token}" -F "noise=$@" ${HONK_URL}/api)
echo $result
}
if [ -z "$2" ]; then
helpme
exit
fi
adapter=$1
shift
case $adapter in
honk)
noise=$(echo "$@" | sed -e 's/|/\|/')
syndicate_honk "$noise"
;;
*)
helpme ;;
esac