17 Commits

Author SHA1 Message Date
f85abd43c4 fix: brew
Some checks failed
Lint / shellcheck (push) Has been cancelled
Release Standalone Builder / build (release) Successful in 30s
Release Standalone Builder / publish-aur (release) Successful in 32s
Release Standalone Builder / publish-homebrew (release) Successful in 6s
2026-03-20 09:26:20 +01:00
0f66ebf52a dist: brew
All checks were successful
Lint / shellcheck (push) Successful in 18s
2026-03-20 09:23:43 +01:00
55a515ccd5 dist: bpkg preparation
All checks were successful
Lint / shellcheck (push) Successful in 18s
Release Standalone Builder / build (release) Successful in 31s
Release Standalone Builder / publish-aur (release) Successful in 34s
2026-03-20 08:46:13 +01:00
de8cbefb8e feat: task lists
All checks were successful
Lint / shellcheck (push) Successful in 18s
2026-03-20 08:32:28 +01:00
cc7fee573f feat: custom admonitions 2026-03-20 08:31:58 +01:00
137be9579a feat: incremental rebuilds 2026-03-20 08:30:25 +01:00
5afd0170e5 fix: less tmp file spam 2026-03-20 08:29:05 +01:00
5a2053cfb4 fix: publish-aur-git shoudln't run so often now
All checks were successful
Lint / shellcheck (push) Successful in 19s
2026-03-19 22:34:31 +01:00
2fc3d6fc6f fix: AUR links
All checks were successful
Lint / shellcheck (push) Successful in 18s
Publish kewt-git to AUR / publish-aur-git (push) Successful in 29s
Release Standalone Builder / build (release) Successful in 30s
Release Standalone Builder / publish-aur (release) Successful in 44s
2026-03-19 21:50:34 +01:00
c5a9355871 fix: config slashes
All checks were successful
Lint / shellcheck (push) Successful in 18s
Publish kewt-git to AUR / publish-aur-git (push) Successful in 30s
Release Standalone Builder / build (release) Successful in 31s
Release Standalone Builder / publish-aur (release) Successful in 34s
2026-03-19 21:45:38 +01:00
b8cd129c47 fix: rename to later in the alphabet, just in case
All checks were successful
Lint / shellcheck (push) Successful in 17s
Publish kewt-git to AUR / publish-aur-git (push) Successful in 33s
2026-03-19 21:29:22 +01:00
5e033a65e7 dist: AUR updates and upgrades
All checks were successful
Publish kewt-git to AUR / publish-aur-git (push) Successful in 34s
Lint / shellcheck (push) Successful in 20s
2026-03-19 21:26:17 +01:00
5bf2e2abe5 Update LICENSE
All checks were successful
Lint / shellcheck (push) Successful in 20s
2026-03-19 16:27:56 +01:00
3a2056ff8f Update site/site.conf
All checks were successful
Lint / shellcheck (push) Successful in 20s
2026-03-19 16:20:52 +01:00
fd829a3f22 branding: icon
All checks were successful
Lint / shellcheck (push) Successful in 19s
2026-03-19 16:12:21 +01:00
bad02decba docs: add contributing instructions
All checks were successful
Lint / shellcheck (push) Successful in 18s
2026-03-19 15:58:41 +01:00
2aef6ec4a1 Update site/site.conf
All checks were successful
Lint / shellcheck (push) Successful in 19s
2026-03-19 15:40:39 +01:00
26 changed files with 349 additions and 82 deletions

View File

@@ -0,0 +1,38 @@
name: Publish kewt-git to AUR
on:
push:
branches:
- main
paths:
- 'packaging/AUR/PKGBUILD.git'
- 'packaging/AUR/.SRCINFO.git'
workflow_dispatch:
jobs:
publish-aur-git:
runs-on: local
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Arch Linux environment
run: |
sudo apt-get update
sudo apt-get install -y pacman-package-manager curl jq || true
- name: Prepare AUR files
run: |
mkdir -p aur-work
cp packaging/AUR/PKGBUILD.git aur-work/PKGBUILD
cp packaging/AUR/.SRCINFO.git aur-work/.SRCINFO
- name: Publish to AUR
uses: KSXGitHub/github-actions-deploy-aur@v3.0.1
with:
pkgname: kewt-git
pkgbuild: ./aur-work/PKGBUILD
commit_username: ${{ github.actor }}
commit_email: ${{ github.actor }}@users.noreply.github.com
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: "Update kewt-git to ${{ github.sha }}"

View File

@@ -3,6 +3,7 @@ name: Release Standalone Builder
on: on:
release: release:
types: [published] types: [published]
workflow_dispatch:
jobs: jobs:
build: build:
@@ -90,25 +91,9 @@ jobs:
-e "s/SHA256SUM_PLACEHOLDER/${CHECKSUM}/g" \ -e "s/SHA256SUM_PLACEHOLDER/${CHECKSUM}/g" \
packaging/AUR/PKGBUILD.template > aur-work/PKGBUILD packaging/AUR/PKGBUILD.template > aur-work/PKGBUILD
cat > aur-work/.SRCINFO << SRCEOF sed -e "s/VERSION_PLACEHOLDER/${VERSION}/g" \
pkgbase = kewt-bin -e "s/SHA256SUM_PLACEHOLDER/${CHECKSUM}/g" \
pkgdesc = A minimalist, 100% POSIX, static site generator inspired by werc and kew packaging/AUR/.SRCINFO.template > aur-work/.SRCINFO
pkgver = ${VERSION}
pkgrel = 1
url = https://git.krzak.org/N0VA/kewt
arch = any
license = MIT
depends = sh
provides = kewt
conflicts = kewt
conflicts = kewt-git
source = kewt-bin-${VERSION}.sh::https://git.krzak.org/N0VA/kewt/releases/download/v${VERSION}/kewt
sha256sums = ${CHECKSUM}
pkgname = kewt-bin
SRCEOF
# Remove leading whitespace from heredoc
sed -i 's/^ //' aur-work/.SRCINFO
- name: Publish to AUR - name: Publish to AUR
uses: KSXGitHub/github-actions-deploy-aur@v3.0.1 uses: KSXGitHub/github-actions-deploy-aur@v3.0.1
@@ -119,3 +104,37 @@ jobs:
commit_email: ${{ github.actor }}@users.noreply.github.com commit_email: ${{ github.actor }}@users.noreply.github.com
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: "Update kewt-bin to ${{ github.ref_name }}" commit_message: "Update kewt-bin to ${{ github.ref_name }}"
publish-homebrew:
runs-on: local
needs: build
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Render Formula and push to GitHub
run: |
TAG="${GITHUB_REF#refs/tags/}"
VERSION="${TAG#v}"
curl -sL -o kewt-binary \
"https://git.krzak.org/N0VA/kewt/releases/download/${TAG}/kewt"
CHECKSUM=$(sha256sum kewt-binary | awk '{print $1}')
rm -f kewt-binary
mkdir -p brew-work/Formula
sed -e "s/VERSION_PLACEHOLDER/${VERSION}/g" \
-e "s/SHA256SUM_PLACEHOLDER/${CHECKSUM}/g" \
packaging/homebrew/kewt.rb.template > brew-work/Formula/kewt.rb
cd brew-work
git init
git remote add origin https://x-access-token:${{ secrets.GH_RELEASE_TOKEN }}@github.com/n0va-bot/homebrew-tap.git
git fetch origin main || true
git checkout main 2>/dev/null || git checkout --orphan main
git add Formula/kewt.rb
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
git commit -m "Update kewt to ${TAG}" || echo "No changes to commit"
git push origin main

View File

@@ -18,9 +18,8 @@ PERFORMANCE OF THIS SOFTWARE.
--- ---
This project incorporates code (CSS style) from the 'kew' project, which is also licensed under the ISC License: This project incorporates code (CSS style) from the 'kew' project,
which is also licensed under the ISC License: Copyright (c) 2026 uint23
Copyright (c) 2023 uint23
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above

19
Makefile Normal file
View File

@@ -0,0 +1,19 @@
PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin
all: kewt
kewt:
./tools/build-standalone.sh
install: kewt
install -d $(DESTDIR)$(BINDIR)
install -m 755 kewt $(DESTDIR)$(BINDIR)/kewt
uninstall:
rm -f $(DESTDIR)$(BINDIR)/kewt
clean:
rm -f kewt
.PHONY: all install uninstall clean

View File

@@ -1,4 +1,4 @@
# _kewt_ # ![kewt](/icon.svg)
### Pronounced "cute" ### Pronounced "cute"
*** ***
@@ -22,6 +22,10 @@ On Arch Linux, _kewt_ is available on the AUR:
- [kewt-bin](https://aur.archlinux.org/packages/kewt-bin) — prebuilt standalone binary from the latest release - [kewt-bin](https://aur.archlinux.org/packages/kewt-bin) — prebuilt standalone binary from the latest release
- [kewt-git](https://aur.archlinux.org/packages/kewt-git) — built from the latest git source - [kewt-git](https://aur.archlinux.org/packages/kewt-git) — built from the latest git source
## Contributing
Either through a pull request to the **home** repository ([N0VA/kewt](https://git.krzak.org/N0VA/kewt)) or by sending a patch to my email address ([n0va@krzak.org](mailto:n0va@krzak.org))
## Credits ## Credits
- _kew_ css style adapted from _[kew](https://github.com/uint23/kew)_ by [uint23](https://github.com/uint23) - _kew_ css style adapted from _[kew](https://github.com/uint23/kew)_ by [uint23](https://github.com/uint23)

View File

@@ -22,7 +22,19 @@ END {
sub(/^\[!/, "", kind) sub(/^\[!/, "", kind)
sub(/\]$/, "", kind) sub(/\]$/, "", kind)
lkind = tolower(kind) lkind = tolower(kind)
if (lkind == "note" || lkind == "tip" || lkind == "important" || lkind == "warning" || lkind == "caution") { is_valid = 0
if (custom_admonitions != "") {
n = split(tolower(custom_admonitions), adms, ",")
for (idx = 1; idx <= n; idx++) {
adm = adms[idx]
sub(/^[ \t]+/, "", adm)
sub(/[ \t]+$/, "", adm)
if (lkind == adm) { is_valid = 1; break }
}
} else if (lkind == "note" || lkind == "tip" || lkind == "important" || lkind == "warning" || lkind == "caution") {
is_valid = 1
}
if (is_valid) {
print "<div class=\"admonition admonition-" lkind "\">" print "<div class=\"admonition admonition-" lkind "\">"
print "<p class=\"admonition-title\">" cap(lkind) "</p>" print "<p class=\"admonition-title\">" cap(lkind) "</p>"
has_body = 0 has_body = 0

View File

@@ -1,4 +1,5 @@
BEGIN { BEGIN {
src = ENVIRON["AWK_SRC"]
slen = length(src) slen = length(src)
} }

View File

@@ -33,6 +33,13 @@ function compare_paths(p1, p2, parts1, parts2, n1, n2, i, name1, name2, lname
} }
BEGIN { BEGIN {
src = ENVIRON["AWK_SRC"]
single_file_index = ENVIRON["AWK_SINGLE_FILE_INDEX"]
flatten = ENVIRON["AWK_FLATTEN"]
order = ENVIRON["AWK_ORDER"]
home_name = ENVIRON["AWK_HOME_NAME"]
show_home_in_nav = ENVIRON["AWK_SHOW_HOME_IN_NAV"]
dinfo = ENVIRON["AWK_DINFO"]
n_dlines = split(dinfo, dlines, "\n") n_dlines = split(dinfo, dlines, "\n")
for (i = 1; i <= n_dlines; i++) { for (i = 1; i <= n_dlines; i++) {
if (split(dlines[i], dparts, "|") == 3) { if (split(dlines[i], dparts, "|") == 3) {

View File

@@ -48,7 +48,26 @@ BEGIN {
} }
} }
print "<li>" content "</li>" has_checkbox = 0
if (content ~ /^\[[ \t]\] /) {
has_checkbox = 1
is_checked = 0
sub(/^\[[ \t]\] /, "", content)
} else if (content ~ /^\[[xX]\] /) {
has_checkbox = 1
is_checked = 1
sub(/^\[[xX]\] /, "", content)
}
if (has_checkbox) {
if (is_checked) {
print "<li class=\"task-list-item\"><input type=\"checkbox\" class=\"task-list-item-checkbox\" checked disabled> " content "</li>"
} else {
print "<li class=\"task-list-item\"><input type=\"checkbox\" class=\"task-list-item-checkbox\" disabled> " content "</li>"
}
} else {
print "<li>" content "</li>"
}
} else { } else {
while (depth > 0) { while (depth > 0) {
print "</" cur_type[depth] ">" print "</" cur_type[depth] ">"

View File

@@ -9,6 +9,13 @@ function replace_all(text, token, value, pos, token_len, res) {
} }
BEGIN { BEGIN {
current_url = ENVIRON["AWK_CURRENT_URL"]
nav = ENVIRON["AWK_NAV"]
title = ENVIRON["AWK_TITLE"]
footer = ENVIRON["AWK_FOOTER"]
style_path = ENVIRON["AWK_STYLE_PATH"]
head_extra = ENVIRON["AWK_HEAD_EXTRA"]
header_brand = ENVIRON["AWK_HEADER_BRAND"]
if (current_url != "") { if (current_url != "") {
nav = replace_all(nav, "href=\"" current_url "\"", "href=\"" current_url "\" class=\"current-page\"") nav = replace_all(nav, "href=\"" current_url "\"", "href=\"" current_url "\" class=\"current-page\"")
} }

View File

@@ -1,4 +1,7 @@
BEGIN { done = 0 } BEGIN {
new_title = ENVIRON["AWK_NEW_TITLE"]
done = 0
}
/^title[[:space:]]*=/ { /^title[[:space:]]*=/ {
print "title = \"" new_title "\"" print "title = \"" new_title "\""
done = 1 done = 1

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

21
icon.svg Normal file
View File

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
<defs>
<linearGradient id="bg-grad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#4a3b69"/>
<stop offset="100%" stop-color="#352654"/>
</linearGradient>
</defs>
<rect width="512" height="512" rx="80" ry="80" fill="url(#bg-grad)"/>
<text
x="256"
y="296"
text-anchor="middle"
dominant-baseline="central"
font-family="Georgia, 'Times New Roman', Times, serif"
font-size="220"
font-weight="bold"
font-style="italic"
fill="#debfff"
letter-spacing="-8"
>kewt</text>
</svg>

After

Width:  |  Height:  |  Size: 639 B

124
kewt.sh
View File

@@ -33,9 +33,17 @@ awk_dir="$script_dir/awk"
KEWT_TMPDIR=$(mktemp -d "/tmp/kewt_run.XXXXXX") KEWT_TMPDIR=$(mktemp -d "/tmp/kewt_run.XXXXXX")
trap 'rm -rf "$KEWT_TMPDIR"' EXIT HUP INT TERM trap 'rm -rf "$KEWT_TMPDIR"' EXIT HUP INT TERM
ensure_root_defaults() {
if [ ! -f "./site.conf" ]; then
cat > "./site.conf" <<'EOF' create_new_site() {
new_title="$1"
new_dir="site"
[ -n "$new_title" ] && new_dir="$new_title"
[ -e "$new_dir" ] && die "Target '$new_dir' already exists."
mkdir -p "$new_dir"
cat > "$new_dir/site.conf" <<'EOF'
title = "kewt" title = "kewt"
style = "kewt" style = "kewt"
dir_indexes = true dir_indexes = true
@@ -60,11 +68,10 @@ base_url = ""
generate_feed = false generate_feed = false
feed_file = "rss.xml" feed_file = "rss.xml"
posts_dir = "" posts_dir = ""
custom_admonitions = ""
EOF EOF
fi
if [ ! -f "./template.html" ]; then cat > "$new_dir/template.html" <<'EOF'
cat > "./template.html" <<'EOF'
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
@@ -88,24 +95,10 @@ EOF
</body> </body>
</html> </html>
EOF EOF
fi
}
create_new_site() {
new_title="$1"
new_dir="site"
[ -n "$new_title" ] && new_dir="$new_title"
[ -e "$new_dir" ] && die "Target '$new_dir' already exists."
ensure_root_defaults
mkdir -p "$new_dir"
cp "./site.conf" "$new_dir/site.conf"
printf "# _kewt_ website\n" > "$new_dir/index.md" printf "# _kewt_ website\n" > "$new_dir/index.md"
if [ -n "$new_title" ]; then if [ -n "$new_title" ]; then
awk -v new_title="$new_title" -f "$awk_dir/update_site_conf.awk" "$new_dir/site.conf" > "$new_dir/site.conf.tmp" && mv "$new_dir/site.conf.tmp" "$new_dir/site.conf" AWK_NEW_TITLE="$new_title" awk -f "$awk_dir/update_site_conf.awk" "$new_dir/site.conf" > "$new_dir/site.conf.tmp" && mv "$new_dir/site.conf.tmp" "$new_dir/site.conf"
fi fi
echo "Created new site at '$new_dir'." echo "Created new site at '$new_dir'."
@@ -173,6 +166,7 @@ base_url = ""
generate_feed = false generate_feed = false
feed_file = "rss.xml" feed_file = "rss.xml"
posts_dir = "" posts_dir = ""
custom_admonitions = ""
CONFEOF CONFEOF
# Update site.conf # Update site.conf
@@ -307,7 +301,7 @@ done
[ "$new_mode" = "true" ] && create_new_site "$new_title" [ "$new_mode" = "true" ] && create_new_site "$new_title"
ensure_root_defaults
if [ -z "$src" ]; then if [ -z "$src" ]; then
if [ "$post_mode" = "true" ] && [ -f "./site.conf" ]; then if [ "$post_mode" = "true" ] && [ -f "./site.conf" ]; then
@@ -421,12 +415,12 @@ done < "$KEWT_TMPDIR/kewt_preserve"
rm -f "$KEWT_TMPDIR/kewt_preserve" rm -f "$KEWT_TMPDIR/kewt_preserve"
generate_nav() { generate_nav() {
dinfo=$(eval "find \"$1\" \( $IGNORE_ARGS -o $HIDE_ARGS -o $PRESERVE_ARGS \) -prune -o -print" | sort | awk -v src="$1" -f "$awk_dir/collect_dir_info.awk") dinfo=$(eval "find \"$1\" \( $IGNORE_ARGS -o $HIDE_ARGS -o $PRESERVE_ARGS \) -prune -o -print" | sort | AWK_SRC="$1" awk -f "$awk_dir/collect_dir_info.awk")
find_cmd="find \"$1\" \( $IGNORE_ARGS -o $HIDE_ARGS -o $PRESERVE_ARGS \) -prune -o -name \"*.md\" -print" find_cmd="find \"$1\" \( $IGNORE_ARGS -o $HIDE_ARGS -o $PRESERVE_ARGS \) -prune -o -name \"*.md\" -print"
if [ -n "$posts_dir" ] && [ -d "$1/$posts_dir" ]; then if [ -n "$posts_dir" ] && [ -d "$1/$posts_dir" ]; then
find_cmd="$find_cmd && echo \"$1/$posts_dir/index.md\"" find_cmd="$find_cmd && echo \"$1/$posts_dir/index.md\""
fi fi
eval "$find_cmd" | sort -u | awk -v src="$1" -v single_file_index="$single_file_index" -v flatten="$flatten" -v order="$order" -v home_name="$home_name" -v show_home_in_nav="$show_home_in_nav" -v dinfo="$dinfo" -f "$awk_dir/generate_sidebar.awk" eval "$find_cmd" | sort -u | AWK_SRC="$1" AWK_SINGLE_FILE_INDEX="$single_file_index" AWK_FLATTEN="$flatten" AWK_ORDER="$order" AWK_HOME_NAME="$home_name" AWK_SHOW_HOME_IN_NAV="$show_home_in_nav" AWK_DINFO="$dinfo" awk -f "$awk_dir/generate_sidebar.awk"
} }
title="kewt" title="kewt"
@@ -454,6 +448,7 @@ base_url=""
generate_feed="false" generate_feed="false"
feed_file="rss.xml" feed_file="rss.xml"
posts_dir="" posts_dir=""
custom_admonitions=""
load_config() { load_config() {
[ -f "$1" ] || return [ -f "$1" ] || return
@@ -482,7 +477,7 @@ load_config() {
case "$key" in case "$key" in
title) title="$val" ;; title) title="$val" ;;
style) style="$val" ;; style) style="${val#/}" ;;
dir_indexes) dir_indexes="$val" ;; dir_indexes) dir_indexes="$val" ;;
single_file_index) single_file_index="$val" ;; single_file_index) single_file_index="$val" ;;
flatten) flatten="$val" ;; flatten) flatten="$val" ;;
@@ -492,19 +487,20 @@ load_config() {
nav_links) nav_links="$val" ;; nav_links) nav_links="$val" ;;
nav_extra) nav_extra="$val" ;; nav_extra) nav_extra="$val" ;;
footer) footer="$val" ;; footer) footer="$val" ;;
logo) logo="$val" ;; logo) logo="${val#/}" ;;
display_logo) display_logo="$val" ;; display_logo) display_logo="$val" ;;
display_title) display_title="$val" ;; display_title) display_title="$val" ;;
logo_as_favicon) logo_as_favicon="$val" ;; logo_as_favicon) logo_as_favicon="$val" ;;
favicon) favicon="$val" ;; favicon) favicon="${val#/}" ;;
generate_page_title) generate_page_title="$val" ;; generate_page_title) generate_page_title="$val" ;;
error_page) error_page="$val" ;; error_page) error_page="${val#/}" ;;
versioning) versioning="$val" ;; versioning) versioning="$val" ;;
enable_header_links) enable_header_links="$val" ;; enable_header_links) enable_header_links="$val" ;;
base_url) base_url="$val" ;; base_url) base_url="$val" ;;
generate_feed) generate_feed="$val" ;; generate_feed) generate_feed="$val" ;;
feed_file) feed_file="$val" ;; feed_file) feed_file="${val#/}" ;;
posts_dir) posts_dir="$val" ;; posts_dir) posts_dir="${val#/}" ;;
custom_admonitions) custom_admonitions="$val" ;;
esac esac
done < "$1" done < "$1"
} }
@@ -584,7 +580,33 @@ nav_links_html() {
template="$src/template.html" template="$src/template.html"
[ -f "$template" ] || template="./template.html" [ -f "$template" ] || template="./template.html"
[ -f "$template" ] || die "Template '$template' not found." if [ ! -f "$template" ]; then
template="$KEWT_TMPDIR/default_template.html"
cat > "$template" <<'EOF'
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{TITLE}}</title>
<link rel="stylesheet" href="{{CSS}}" type="text/css" />
{{HEAD_EXTRA}}
</head>
<body>
<header>
<h1>{{HEADER_BRAND}}</h1>
</header>
<nav id="side-bar">{{NAV}}</nav>
<article>{{CONTENT}}</article>
<footer>{{FOOTER}}</footer>
</body>
</html>
EOF
fi
[ -d "$out" ] && rm -rf "$out" [ -d "$out" ] && rm -rf "$out"
mkdir -p "$out" mkdir -p "$out"
@@ -715,7 +737,19 @@ render_markdown() {
fi fi
fi fi
ENABLE_HEADER_LINKS="$enable_header_links" MARKDOWN_SITE_ROOT="$src" MARKDOWN_FALLBACK_FILE="$script_dir/styles/$style.css" sh "$script_dir/markdown.sh" "$content_file" | awk -v current_url="$current_url" -v title="$page_title" -v nav="$nav" -v footer="$footer" -v style_path="${style_path}${asset_version}" -v header_brand="$header_brand" -v head_extra="$head_extra" -f "$awk_dir/render_template.awk" "$local_template" ENABLE_HEADER_LINKS="$enable_header_links" CUSTOM_ADMONITIONS="$custom_admonitions" MARKDOWN_SITE_ROOT="$src" MARKDOWN_FALLBACK_FILE="$script_dir/styles/$style.css" sh "$script_dir/markdown.sh" "$content_file" | AWK_CURRENT_URL="$current_url" AWK_TITLE="$page_title" AWK_NAV="$nav" AWK_FOOTER="$footer" AWK_STYLE_PATH="${style_path}${asset_version}" AWK_HEADER_BRAND="$header_brand" AWK_HEAD_EXTRA="$head_extra" awk -f "$awk_dir/render_template.awk" "$local_template"
}
needs_rebuild() {
src_file="$1"
out_file="$2"
[ ! -f "$out_file" ] && return 0
[ "$src_file" -nt "$out_file" ] && return 0
[ -f "./site.conf" ] && [ "./site.conf" -nt "$out_file" ] && return 0
[ -f "$src/site.conf" ] && [ "$src/site.conf" -nt "$out_file" ] && return 0
[ -f "$template" ] && [ "$template" -nt "$out_file" ] && return 0
[ -f "$script_dir/styles/$style.css" ] && [ "$script_dir/styles/$style.css" -nt "$out_file" ] && return 0
return 1
} }
echo "Building site from '$src' to '$out'..." echo "Building site from '$src' to '$out'..."
@@ -728,9 +762,13 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
mkdir -p "$out_dir" mkdir -p "$out_dir"
if [ -f "$dir/styles.css" ]; then if [ -f "$dir/styles.css" ]; then
copy_style_with_resolved_vars "$dir/styles.css" "$out_dir/styles.css" if needs_rebuild "$dir/styles.css" "$out_dir/styles.css"; then
copy_style_with_resolved_vars "$dir/styles.css" "$out_dir/styles.css"
fi
elif [ -f "$dir/style.css" ]; then elif [ -f "$dir/style.css" ]; then
copy_style_with_resolved_vars "$dir/style.css" "$out_dir/styles.css" if needs_rebuild "$dir/style.css" "$out_dir/styles.css"; then
copy_style_with_resolved_vars "$dir/style.css" "$out_dir/styles.css"
fi
fi fi
[ "$dir_indexes" != "true" ] && continue [ "$dir_indexes" != "true" ] && continue
@@ -747,7 +785,9 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
is_home="false"; [ "$dir" = "$src" ] && is_home="true" is_home="false"; [ "$dir" = "$src" ] && is_home="true"
target_url="/$rel_dir/index.html" target_url="/$rel_dir/index.html"
[ "$rel_dir" = "." ] && target_url="/index.html" [ "$rel_dir" = "." ] && target_url="/index.html"
render_markdown "$md_file" "$is_home" "$target_url" > "$out_dir/index.html" if needs_rebuild "$md_file" "$out_dir/index.html"; then
render_markdown "$md_file" "$is_home" "$target_url" > "$out_dir/index.html"
fi
continue continue
fi fi
fi fi
@@ -807,12 +847,14 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
is_home="false"; [ "$dir" = "$src" ] && is_home="true" is_home="false"; [ "$dir" = "$src" ] && is_home="true"
target_url="/$rel_dir/index.html" target_url="/$rel_dir/index.html"
[ "$rel_dir" = "." ] && target_url="/index.html" [ "$rel_dir" = "." ] && target_url="/index.html"
render_markdown "$temp_index" "$is_home" "$target_url" > "$out_dir/index.html" if needs_rebuild "$dir" "$out_dir/index.html"; then
render_markdown "$temp_index" "$is_home" "$target_url" > "$out_dir/index.html"
fi
rm "$temp_index" rm "$temp_index"
fi fi
done done
if [ ! -f "$out/styles.css" ] && [ -f "$script_dir/styles/$style.css" ]; then if [ -f "$script_dir/styles/$style.css" ] && needs_rebuild "$script_dir/styles/$style.css" "$out/styles.css"; then
copy_style_with_resolved_vars "$script_dir/styles/$style.css" "$out/styles.css" copy_style_with_resolved_vars "$script_dir/styles/$style.css" "$out/styles.css"
fi fi
@@ -844,9 +886,13 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type f -print" | sort | while
if [ "${file%.md}" != "$file" ] && [ "$is_preserved" -eq 0 ]; then if [ "${file%.md}" != "$file" ] && [ "$is_preserved" -eq 0 ]; then
is_home="false"; [ "$file" = "$src/index.md" ] && is_home="true" is_home="false"; [ "$file" = "$src/index.md" ] && is_home="true"
out_file="$out/${rel_path%.md}.html" out_file="$out/${rel_path%.md}.html"
render_markdown "$file" "$is_home" > "$out_file" if needs_rebuild "$file" "$out_file"; then
render_markdown "$file" "$is_home" > "$out_file"
fi
else else
cp "$file" "$out/$rel_path" if needs_rebuild "$file" "$out/$rel_path"; then
cp "$file" "$out/$rel_path"
fi
fi fi
done done

View File

@@ -15,7 +15,7 @@ sed_inplace() {
fi fi
} }
temp_file="/tmp/markdown.$$.md" temp_file="${KEWT_TMPDIR:-/tmp}/markdown.$$.md"
cat "$@" > "$temp_file" cat "$@" > "$temp_file"
trap 'rm -f "$temp_file" "$temp_file.tmp"' EXIT INT TERM trap 'rm -f "$temp_file" "$temp_file.tmp"' EXIT INT TERM
@@ -40,14 +40,19 @@ done
sed_inplace "/^\[[^\]]*\]: */d" "$temp_file" sed_inplace "/^\[[^\]]*\]: */d" "$temp_file"
# Blocks # Blocks
sed_inplace "s/^>!\[/> [!/g" "$temp_file"
sed_inplace "s/^>\[!/> [!/g" "$temp_file"
loop_count=0
max_iterations=100
while grep '^>' "$temp_file" >/dev/null; do while grep '^>' "$temp_file" >/dev/null; do
awk -f "$awk_dir/blockquote.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" awk -f "$awk_dir/blockquote.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
loop_count=$((loop_count + 1))
if [ "$loop_count" -gt "$max_iterations" ]; then
echo "Warning: Blockquote processing exceeded $max_iterations iterations on $1. Breaking to prevent infinite loop." >&2
break
fi
done done
awk -f "$awk_dir/blockquote_to_admonition.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" awk -v custom_admonitions="$CUSTOM_ADMONITIONS" -f "$awk_dir/blockquote_to_admonition.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
awk -f "$awk_dir/fenced_code.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" awk -f "$awk_dir/fenced_code.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
awk -f "$awk_dir/indented_code.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" awk -f "$awk_dir/indented_code.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"
awk -f "$awk_dir/pipe_tables.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" awk -f "$awk_dir/pipe_tables.awk" "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file"

7
package.json Normal file
View File

@@ -0,0 +1,7 @@
{
"name": "kewt",
"description": "A minimalist static site generator inspired by werc",
"global": "true",
"install": "make install",
"scripts": ["kewt"]
}

View File

@@ -0,0 +1,16 @@
pkgbase = kewt-git
pkgdesc = A minimalist, 100% POSIX, static site generator inspired by werc and kew
pkgver = r0.0000000
pkgrel = 3
url = https://kewt.krzak.org
arch = any
license = ISC
makedepends = git
depends = sh
provides = kewt
conflicts = kewt
conflicts = kewt-bin
source = kewt-git::git+https://git.krzak.org/N0VA/kewt.git
sha256sums = SKIP
pkgname = kewt-git

View File

@@ -0,0 +1,15 @@
pkgbase = kewt-bin
pkgdesc = A minimalist, 100% POSIX, static site generator inspired by werc and kew
pkgver = VERSION_PLACEHOLDER
pkgrel = 2
url = https://kewt.krzak.org
arch = any
license = ISC
depends = sh
provides = kewt
conflicts = kewt
conflicts = kewt-git
source = kewt-bin-VERSION_PLACEHOLDER.sh::https://git.krzak.org/N0VA/kewt/releases/download/vVERSION_PLACEHOLDER/kewt
sha256sums = SHA256SUM_PLACEHOLDER
pkgname = kewt-bin

View File

@@ -1,16 +1,16 @@
# Maintainer: n0va <n0va@krzak.org> # Maintainer: n0va <n0va@krzak.org>
pkgname=kewt-git pkgname=kewt-git
pkgver=r0.0000000 pkgver=r0.0000000
pkgrel=1 pkgrel=2
pkgdesc="A minimalist, 100% POSIX, static site generator inspired by werc and kew" pkgdesc="A minimalist, 100% POSIX, static site generator inspired by werc and kew"
arch=('any') arch=('any')
url="https://git.krzak.org/N0VA/kewt" url="https://kewt.krzak.org"
license=('MIT') license=('ISC')
makedepends=('git') makedepends=('git')
depends=('sh') depends=('sh')
provides=('kewt') provides=('kewt')
conflicts=('kewt' 'kewt-bin') conflicts=('kewt' 'kewt-bin')
source=("${pkgname}::git+${url}.git") source=("${pkgname}::git+https://git.krzak.org/N0VA/kewt.git")
sha256sums=('SKIP') sha256sums=('SKIP')
pkgver() { pkgver() {

View File

@@ -4,12 +4,12 @@ pkgver=VERSION_PLACEHOLDER
pkgrel=1 pkgrel=1
pkgdesc="A minimalist, 100% POSIX, static site generator inspired by werc and kew" pkgdesc="A minimalist, 100% POSIX, static site generator inspired by werc and kew"
arch=('any') arch=('any')
url="https://git.krzak.org/N0VA/kewt" url="https://kewt.krzak.org"
license=('MIT') license=('ISC')
depends=('sh') depends=('sh')
provides=('kewt') provides=('kewt')
conflicts=('kewt' 'kewt-git') conflicts=('kewt' 'kewt-git')
source=("${pkgname}-${pkgver}.sh::${url}/releases/download/v${pkgver}/kewt") source=("${pkgname}-${pkgver}.sh::https://git.krzak.org/N0VA/kewt/releases/download/v${pkgver}/kewt")
sha256sums=('SHA256SUM_PLACEHOLDER') sha256sums=('SHA256SUM_PLACEHOLDER')
build() { build() {

View File

@@ -0,0 +1,16 @@
class Kewt < Formula
desc "Minimalist static site generator inspired by werc"
homepage "https://kewt.krzak.org"
url "https://github.com/n0va-bot/kewt/releases/download/VERSION_PLACEHOLDER/kewt"
sha256 "SHA256SUM_PLACEHOLDER"
license "ISC"
version "VERSION_PLACEHOLDER"
def install
bin.install "kewt"
end
test do
system "#{bin}/kewt", "--version"
end
end

BIN
site/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@@ -19,7 +19,8 @@ It's meant to be a static site generator, like _[kew](https://github.com/uint23/
- Automatic inlining and embedding of many filetypes with `\![link]` or `\![alt](link)` - Automatic inlining and embedding of many filetypes with `\![link]` or `\![alt](link)`
- Inline html support - Inline html support
- MFM `$font` and `\<plain>` tags - MFM `$font` and `\<plain>` tags
- Admonition support (that's what the blocks like the warning block below are called) - GFM Admonition support (that's what the blocks like the warning block below are called)
- Task list support (`- [ ]`, `- [x]`)
- RSS/Feed generation and Sitemap support - RSS/Feed generation and Sitemap support
- Post creation via `--post` - Post creation via `--post`
- Automatic 404 page generation - Automatic 404 page generation
@@ -86,6 +87,7 @@ generate_feed = false
feed_file = "rss.xml" feed_file = "rss.xml"
posts_dir = "" posts_dir = ""
enable_header_links = true enable_header_links = true
custom_admonitions = ""
``` ```
- `title` site title - `title` site title
@@ -112,6 +114,7 @@ enable_header_links = true
- `feed_file` filename for the generated RSS feed (default: "rss.xml") - `feed_file` filename for the generated RSS feed (default: "rss.xml")
- `posts_dir` directory name containing posts (e.g., "posts"). Enables reverse-chronological sorting, title headings in indexes, and automatic backlinks. - `posts_dir` directory name containing posts (e.g., "posts"). Enables reverse-chronological sorting, title headings in indexes, and automatic backlinks.
- `enable_header_links` turns markdown section headings into clickable anchor links (default: true) - `enable_header_links` turns markdown section headings into clickable anchor links (default: true)
- `custom_admonitions` comma separated list of custom admonitions
## Ignores ## Ignores

View File

@@ -7,8 +7,8 @@ footer = "<a href=\"https://kewt.krzak.org\"><img src=\"/button.gif\" /></a>"
logo = "" logo = ""
display_logo = false display_logo = false
display_title = true display_title = true
logo_as_favicon = true logo_as_favicon = false
favicon = "" favicon = "favicon.ico"
order = "" order = ""
home_name = "Home" home_name = "Home"
show_home_in_nav = true show_home_in_nav = true
@@ -16,6 +16,7 @@ nav_links = ""
nav_extra = "" nav_extra = ""
generate_page_title = true generate_page_title = true
error_page = "not_found.html" error_page = "not_found.html"
versioning = false versioning = true
enable_header_links = true enable_header_links = true
base_url = "https://kewt.krzak.org" base_url = "https://kewt.krzak.org"
custom_admonitions = ""

View File

@@ -273,4 +273,13 @@ hr {
margin-right: 20px; margin-right: 20px;
padding-top: 30px; padding-top: 30px;
} }
}
.task-list-item {
list-style-type: none;
}
.task-list-item-checkbox {
margin: 0 0.2em 0.25em -1.6em;
vertical-align: middle;
} }

View File

@@ -26,7 +26,7 @@ exit $?
#==PAYLOAD== #==PAYLOAD==
EOF EOF
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "standalone") VERSION=$(git describe --tags 2>/dev/null || echo "standalone")
tmpbuild=$(mktemp -d) tmpbuild=$(mktemp -d)
cp -r "$REPO_ROOT/kewt.sh" "$REPO_ROOT/markdown.sh" "$REPO_ROOT/awk" "$REPO_ROOT/styles" "$tmpbuild/" cp -r "$REPO_ROOT/kewt.sh" "$REPO_ROOT/markdown.sh" "$REPO_ROOT/awk" "$REPO_ROOT/styles" "$tmpbuild/"
sed -e "s/kewt version git/kewt version $VERSION/" "$tmpbuild/kewt.sh" > "$tmpbuild/kewt.sh.tmp" && mv "$tmpbuild/kewt.sh.tmp" "$tmpbuild/kewt.sh" sed -e "s/kewt version git/kewt version $VERSION/" "$tmpbuild/kewt.sh" > "$tmpbuild/kewt.sh.tmp" && mv "$tmpbuild/kewt.sh.tmp" "$tmpbuild/kewt.sh"