11 Commits

Author SHA1 Message Date
7afd041e53 functionality: Dynamic page titles, versioning, automatic 404 page
All checks were successful
Lint / shellcheck (push) Successful in 17s
Release Standalone Builder / build (release) Successful in 32s
Release Standalone Builder / publish-aur (release) Successful in 33s
2026-03-17 01:55:32 +01:00
64d08a0de3 functionality: BetterHelp
All checks were successful
Lint / shellcheck (push) Successful in 19s
Release Standalone Builder / build (release) Successful in 32s
Release Standalone Builder / publish-aur (release) Successful in 35s
2026-03-16 10:33:21 +01:00
dd18bc3367 docs: update readme
All checks were successful
Lint / shellcheck (push) Successful in 39s
2026-03-16 09:33:45 +01:00
f89661c1a5 standalone version tmp spam fix
All checks were successful
Lint / shellcheck (push) Successful in 19s
Release Standalone Builder / build (release) Successful in 31s
Release Standalone Builder / publish-aur (release) Successful in 33s
2026-03-11 13:57:10 +01:00
e0a3b66fa9 docs: AUR
All checks were successful
Lint / shellcheck (push) Successful in 16s
2026-03-11 08:44:37 +01:00
4e6c9dbeb5 kewt-git AUR 2026-03-11 08:43:19 +01:00
af453ca2ec aur now workie pretty please
All checks were successful
Lint / shellcheck (push) Successful in 16s
Release Standalone Builder / build (release) Successful in 33s
Release Standalone Builder / publish-aur (release) Successful in 1m7s
2026-03-11 08:36:22 +01:00
cea84de242 Hopefully AUR fixed
Some checks failed
Lint / shellcheck (push) Successful in 17s
Release Standalone Builder / build (release) Successful in 31s
Release Standalone Builder / publish-aur (release) Failing after 23s
2026-03-11 08:31:00 +01:00
ad1ec9c2e3 Auto GitHub
Some checks failed
Lint / shellcheck (push) Successful in 18s
Release Standalone Builder / build (release) Successful in 31s
Release Standalone Builder / publish-aur (release) Failing after 43s
2026-03-11 08:26:36 +01:00
fa3b5592da AUR
All checks were successful
Lint / shellcheck (push) Successful in 17s
2026-03-11 08:21:12 +01:00
722d687afe docs: add standalone download instructions
All checks were successful
Lint / shellcheck (push) Successful in 15s
2026-03-11 08:07:17 +01:00
10 changed files with 225 additions and 62 deletions

View File

@@ -13,4 +13,4 @@ jobs:
- name: Install Shellcheck - name: Install Shellcheck
run: sudo apt-get update && sudo apt-get install -y shellcheck run: sudo apt-get update && sudo apt-get install -y shellcheck
- name: Run Shellcheck - name: Run Shellcheck
run: shellcheck kewt.sh markdown.sh tools/build-standalone.sh || true run: shellcheck -s sh kewt.sh markdown.sh tools/build-standalone.sh || true

View File

@@ -27,3 +27,83 @@ jobs:
files: |- files: |-
kewt kewt
api_key: '${{secrets.GITEA_TOKEN}}' api_key: '${{secrets.GITEA_TOKEN}}'
- name: Push to GitHub Release
run: |
TAG="${GITHUB_REF#refs/tags/}"
# Create the release on GitHub
curl -sL -X POST \
-H "Authorization: token ${{ secrets.GH_RELEASE_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/n0va-bot/kewt/releases" \
-d "{\"tag_name\":\"${TAG}\",\"name\":\"${TAG}\",\"draft\":false,\"prerelease\":false}" || true
# Get the release ID
RELEASE_ID=$(curl -sL \
-H "Authorization: token ${{ secrets.GH_RELEASE_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/n0va-bot/kewt/releases/tags/${TAG}" | jq -r '.id')
# Upload the asset
curl -sL -X POST \
-H "Authorization: token ${{ secrets.GH_RELEASE_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
"https://uploads.github.com/repos/n0va-bot/kewt/releases/${RELEASE_ID}/assets?name=kewt" \
--data-binary @kewt
publish-aur:
runs-on: local
needs: build
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: Render PKGBUILD and SRCINFO
run: |
VERSION=${GITHUB_REF#refs/tags/v}
VERSION=${VERSION#refs/tags/}
curl -sL -o kewt https://git.krzak.org/N0VA/kewt/releases/download/v${VERSION}/kewt
CHECKSUM=$(sha256sum kewt | awk '{print $1}')
mkdir -p aur-work
sed -e "s/VERSION_PLACEHOLDER/${VERSION}/g" \
-e "s/SHA256SUM_PLACEHOLDER/${CHECKSUM}/g" \
packaging/AUR/PKGBUILD.template > aur-work/PKGBUILD
cat > aur-work/.SRCINFO << SRCEOF
pkgbase = kewt-bin
pkgdesc = A minimalist, 100% POSIX, static site generator inspired by werc and kew
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
uses: KSXGitHub/github-actions-deploy-aur@v3.0.1
with:
pkgname: kewt-bin
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-bin to ${{ github.ref_name }}"

View File

@@ -1,16 +0,0 @@
name: Lint
on:
push:
branches: [ main, master ]
pull_request:
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Shellcheck
run: sudo apt-get update && sudo apt-get install -y shellcheck
- name: Run Shellcheck
run: shellcheck kewt.sh markdown.sh tools/build-standalone.sh || true

View File

@@ -1,25 +0,0 @@
name: Release Standalone Builder
on:
release:
types: [published]
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build standalone executable
run: |
chmod +x tools/build-standalone.sh
./tools/build-standalone.sh
- name: Upload Release Asset
uses: softprops/action-gh-release@v2
with:
files: kewt

View File

@@ -19,6 +19,20 @@ It's meant to be a static site generator, like _[kew](https://github.com/uint23/
If you want to **force** a file to be inlined, use `\!![]` instead of `\![]` If you want to **force** a file to be inlined, use `\!![]` instead of `\![]`
## Installation
You can clone the repository to use `kewt.sh` directly, or you can download the standalone executable, which bundles all dependencies into a single file:
```sh
curl -L -o kewt https://git.krzak.org/N0VA/kewt/releases/latest/download/kewt
chmod +x kewt
```
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-git](https://aur.archlinux.org/packages/kewt-git) — built from the latest git source
## Usage ## Usage
```sh ```sh
@@ -86,7 +100,6 @@ favicon = ""
## Credits ## Credits
- Markdown to html conversion based on [markdown.bash](https://github.com/chadbraunduin/markdown.bash) by [chadbraunduin](https://github.com/chadbraunduin)
- Default css style and html template based on _[kew](https://github.com/uint23/kew)_ by [uint23](https://github.com/uint23) - Default css style and html template based on _[kew](https://github.com/uint23/kew)_ by [uint23](https://github.com/uint23)
>[!WARNING] >[!WARNING]

79
kewt.sh
View File

@@ -6,11 +6,12 @@ die() {
} }
usage() { usage() {
invoked_as=$(basename "${KEWT_INVOKED_AS:-$0}")
cat <<EOF cat <<EOF
Usage: $0 [--from <src>] [--to <out>] Usage: $invoked_as [--from <src>] [--to <out>]
$0 [src] [out] $invoked_as [src] [out]
$0 --new [title] $invoked_as --new [title]
$0 --help $invoked_as --help
Options: Options:
--help Show this help message. --help Show this help message.
@@ -23,6 +24,9 @@ EOF
script_dir=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd) script_dir=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd)
awk_dir="$script_dir/awk" awk_dir="$script_dir/awk"
KEWT_TMPDIR=$(mktemp -d "/tmp/kewt_run.XXXXXX")
trap 'rm -rf "$KEWT_TMPDIR"' EXIT HUP INT TERM
ensure_root_defaults() { ensure_root_defaults() {
if [ ! -f "./site.conf" ]; then if [ ! -f "./site.conf" ]; then
cat > "./site.conf" <<'EOF' cat > "./site.conf" <<'EOF'
@@ -42,6 +46,9 @@ display_logo = false
display_title = true display_title = true
logo_as_favicon = true logo_as_favicon = true
favicon = "" favicon = ""
generate_page_title = true
error_page = "not_found.html"
versioning = false
EOF EOF
fi fi
@@ -151,7 +158,14 @@ ensure_root_defaults
src="${src%/}" src="${src%/}"
out="${out%/}" out="${out%/}"
[ -d "$src" ] || die "Source directory '$src' does not exist." if [ ! -d "$src" ]; then
if [ "$src" = "site" ]; then
usage
exit 1
else
die "Source directory '$src' does not exist."
fi
fi
IGNORE_ARGS="-name '.kewtignore' -o -path '$src/.*'" IGNORE_ARGS="-name '.kewtignore' -o -path '$src/.*'"
@@ -174,14 +188,14 @@ if [ -f "$src/.kewtignore" ]; then
done < "$src/.kewtignore" done < "$src/.kewtignore"
fi fi
find "$src" -name .kewtignore > "/tmp/kewt_ignore_$$" find "$src" -name .kewtignore > "$KEWT_TMPDIR/kewt_ignore"
while read -r ki; do while read -r ki; do
d="${ki%/.kewtignore}" d="${ki%/.kewtignore}"
if [ "$d" != "$src" ] && [ "$d" != "." ]; then if [ "$d" != "$src" ] && [ "$d" != "." ]; then
IGNORE_ARGS="$IGNORE_ARGS -o -path '$d' -o -path '$d/*'" IGNORE_ARGS="$IGNORE_ARGS -o -path '$d' -o -path '$d/*'"
fi fi
done < "/tmp/kewt_ignore_$$" done < "$KEWT_TMPDIR/kewt_ignore"
rm -f "/tmp/kewt_ignore_$$" rm -f "$KEWT_TMPDIR/kewt_ignore"
HIDE_ARGS="-name '.kewtignore' -o -name '.kewthide' -o -name '.kewtpreserve' -o -path '$src/.*'" HIDE_ARGS="-name '.kewtignore' -o -name '.kewthide' -o -name '.kewtpreserve' -o -path '$src/.*'"
@@ -204,14 +218,14 @@ if [ -f "$src/.kewthide" ]; then
done < "$src/.kewthide" done < "$src/.kewthide"
fi fi
find "$src" -name .kewthide > "/tmp/kewt_hide_$$" find "$src" -name .kewthide > "$KEWT_TMPDIR/kewt_hide"
while read -r kh; do while read -r kh; do
d="${kh%/.kewthide}" d="${kh%/.kewthide}"
if [ "$d" != "$src" ] && [ "$d" != "." ]; then if [ "$d" != "$src" ] && [ "$d" != "." ]; then
HIDE_ARGS="$HIDE_ARGS -o -path '$d' -o -path '$d/*'" HIDE_ARGS="$HIDE_ARGS -o -path '$d' -o -path '$d/*'"
fi fi
done < "/tmp/kewt_hide_$$" done < "$KEWT_TMPDIR/kewt_hide"
rm -f "/tmp/kewt_hide_$$" rm -f "$KEWT_TMPDIR/kewt_hide"
PRESERVE_ARGS="-false" PRESERVE_ARGS="-false"
@@ -234,14 +248,14 @@ if [ -f "$src/.kewtpreserve" ]; then
done < "$src/.kewtpreserve" done < "$src/.kewtpreserve"
fi fi
find "$src" -name .kewtpreserve > "/tmp/kewt_preserve_$$" find "$src" -name .kewtpreserve > "$KEWT_TMPDIR/kewt_preserve"
while read -r kp; do while read -r kp; do
d="${kp%/.kewtpreserve}" d="${kp%/.kewtpreserve}"
if [ "$d" != "$src" ] && [ "$d" != "." ]; then if [ "$d" != "$src" ] && [ "$d" != "." ]; then
PRESERVE_ARGS="$PRESERVE_ARGS -o -path '$d' -o -path '$d/*'" PRESERVE_ARGS="$PRESERVE_ARGS -o -path '$d' -o -path '$d/*'"
fi fi
done < "/tmp/kewt_preserve_$$" done < "$KEWT_TMPDIR/kewt_preserve"
rm -f "/tmp/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 -v src="$1" -f "$awk_dir/collect_dir_info.awk")
@@ -265,6 +279,9 @@ display_logo="false"
display_title="true" display_title="true"
logo_as_favicon="true" logo_as_favicon="true"
favicon="" favicon=""
generate_page_title="true"
error_page="not_found.html"
versioning="false"
load_config() { load_config() {
[ -f "$1" ] || return [ -f "$1" ] || return
@@ -302,6 +319,9 @@ load_config() {
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" ;;
error_page) error_page="$val" ;;
versioning) versioning="$val" ;;
esac esac
done < "$1" done < "$1"
} }
@@ -309,6 +329,11 @@ load_config() {
load_config "./site.conf" load_config "./site.conf"
load_config "$src/site.conf" load_config "$src/site.conf"
asset_version=""
if [ "$versioning" = "true" ]; then
asset_version="?v=$(date +%s)"
fi
escape_html_text() { escape_html_text() {
printf '%s' "$1" | sed \ printf '%s' "$1" | sed \
-e 's/&/\&amp;/g' \ -e 's/&/\&amp;/g' \
@@ -458,7 +483,21 @@ render_markdown() {
head_extra="<link rel=\"icon\" href=\"$favicon_src\" />" head_extra="<link rel=\"icon\" href=\"$favicon_src\" />"
fi fi
MARKDOWN_SITE_ROOT="$src" MARKDOWN_FALLBACK_FILE="$script_dir/styles/$style.css" sh "$script_dir/markdown.sh" "$file" | awk -v title="$title" -v nav="$nav" -v footer="$footer" -v style_path="$style_path" -v header_brand="$header_brand" -v head_extra="$head_extra" -f "$awk_dir/render_template.awk" "$local_template" page_title="$title"
if [ "$generate_page_title" = "true" ] && [ -n "$file" ] && [ -f "$file" ]; then
first_heading=$(grep -m 1 '^# ' "$file" | sed 's/^# *//; s/ *$//')
if [ -n "$first_heading" ]; then
page_title="$first_heading - $title"
else
basename_no_ext=$(basename "$file" .md)
if [ "$basename_no_ext" != "index" ] && [ "$basename_no_ext" != "404_gen" ]; then
cap_basename=$(echo "$basename_no_ext" | awk '{print toupper(substr($0,1,1)) substr($0,2)}')
page_title="$cap_basename - $title"
fi
fi
fi
MARKDOWN_SITE_ROOT="$src" MARKDOWN_FALLBACK_FILE="$script_dir/styles/$style.css" sh "$script_dir/markdown.sh" "$file" | awk -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"
} }
echo "Building site from '$src' to '$out'..." echo "Building site from '$src' to '$out'..."
@@ -488,7 +527,7 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
fi fi
fi fi
temp_index="/tmp/kewt_index_$$.md" temp_index="$KEWT_TMPDIR/index.md"
display_dir="${rel_dir#.}" display_dir="${rel_dir#.}"
[ -z "$display_dir" ] && display_dir="/" [ -z "$display_dir" ] && display_dir="/"
echo "# Index of $display_dir" > "$temp_index" echo "# Index of $display_dir" > "$temp_index"
@@ -543,5 +582,13 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type f -print" | sort | while
fi fi
done done
if [ -n "$error_page" ] && [ ! -f "$out/$error_page" ]; then
temp_404="$KEWT_TMPDIR/404_gen.md"
echo "# 404 - Not Found" > "$temp_404"
echo "" >> "$temp_404"
echo "The requested page could not be found." >> "$temp_404"
render_markdown "$temp_404" > "$out/$error_page"
rm -f "$temp_404"
fi
echo "Build complete." echo "Build complete."

View File

@@ -0,0 +1,29 @@
# Maintainer: n0va <n0va@krzak.org>
pkgname=kewt-git
pkgver=r0.0000000
pkgrel=1
pkgdesc="A minimalist, 100% POSIX, static site generator inspired by werc and kew"
arch=('any')
url="https://git.krzak.org/N0VA/kewt"
license=('MIT')
makedepends=('git')
depends=('sh')
provides=('kewt')
conflicts=('kewt' 'kewt-bin')
source=("${pkgname}::git+${url}.git")
sha256sums=('SKIP')
pkgver() {
cd "${pkgname}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
build() {
cd "${pkgname}"
sh tools/build-standalone.sh
}
package() {
cd "${pkgname}"
install -Dm755 kewt "${pkgdir}/usr/bin/kewt"
}

View File

@@ -0,0 +1,21 @@
# Maintainer: n0va <n0va@krzak.org>
pkgname=kewt-bin
pkgver=VERSION_PLACEHOLDER
pkgrel=1
pkgdesc="A minimalist, 100% POSIX, static site generator inspired by werc and kew"
arch=('any')
url="https://git.krzak.org/N0VA/kewt"
license=('MIT')
depends=('sh')
provides=('kewt')
conflicts=('kewt' 'kewt-git')
source=("${pkgname}-${pkgver}.sh::${url}/releases/download/v${pkgver}/kewt")
sha256sums=('SHA256SUM_PLACEHOLDER')
build() {
chmod +x "${srcdir}/${pkgname}-${pkgver}.sh"
}
package() {
install -Dm755 "${srcdir}/${pkgname}-${pkgver}.sh" "${pkgdir}/usr/bin/kewt"
}

View File

@@ -19,6 +19,20 @@ It's meant to be a static site generator, like _[kew](https://github.com/uint23/
If you want to **force** a file to be inlined, use `\!![]` instead of `\![]` If you want to **force** a file to be inlined, use `\!![]` instead of `\![]`
## Installation
You can clone the repository to use `kewt.sh` directly, or you can download the standalone executable, which bundles all dependencies into a single file:
```sh
curl -L -o kewt https://git.krzak.org/N0VA/kewt/releases/latest/download/kewt
chmod +x kewt
```
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-git](https://aur.archlinux.org/packages/kewt-git) — built from the latest git source
## Usage ## Usage
```sh ```sh
@@ -86,7 +100,6 @@ favicon = ""
## Credits ## Credits
- Markdown to html conversion based on [markdown.bash](https://github.com/chadbraunduin/markdown.bash) by [chadbraunduin](https://github.com/chadbraunduin)
- Default css style and html template based on _[kew](https://github.com/uint23/kew)_ by [uint23](https://github.com/uint23) - Default css style and html template based on _[kew](https://github.com/uint23/kew)_ by [uint23](https://github.com/uint23)
>![WARNING] >![WARNING]

3
tools/build-standalone.sh Normal file → Executable file
View File

@@ -20,7 +20,8 @@ trap 'rm -rf "$tmpdir"' EXIT HUP INT TERM
sed '1,/^#==PAYLOAD==$/d' "$0" | tar -xz -C "$tmpdir" sed '1,/^#==PAYLOAD==$/d' "$0" | tar -xz -C "$tmpdir"
# Pass control to the extracted script # Pass control to the extracted script
exec "$tmpdir/kewt.sh" "$@" KEWT_INVOKED_AS="$0" "$tmpdir/kewt.sh" "$@"
exit $?
#==PAYLOAD== #==PAYLOAD==
EOF EOF