diff --git a/awk/fenced_code.awk b/awk/fenced_code.awk
index 6a866ea..0ddd63c 100644
--- a/awk/fenced_code.awk
+++ b/awk/fenced_code.awk
@@ -1,11 +1,20 @@
-BEGIN { in_fence = 0; first_line = 0 }
+BEGIN { in_fence = 0; first_line = 0; code_tag = "" }
{
if (!in_fence && $0 ~ /^```/) {
in_fence = 1
first_line = 1
+ lang = $0
+ sub(/^```[[:space:]]*/, "", lang)
+ sub(/[[:space:]]*$/, "", lang)
+ if (lang != "") {
+ code_tag = ""
+ } else {
+ code_tag = ""
+ }
next
}
if (in_fence && $0 ~ /^```[[:space:]]*$/) {
+ if (first_line) printf "%s", "" code_tag
print ""
in_fence = 0
next
@@ -14,8 +23,12 @@ BEGIN { in_fence = 0; first_line = 0 }
gsub(/&/, "\\&"); gsub(/, "\\<"); gsub(/>/, "\\>")
if (first_line) {
first_line = 0
- if ($0 == "") next
- print "" $0
+ printf "%s", "" code_tag
+ if ($0 == "") {
+ print ""
+ next
+ }
+ print $0
} else {
print
}
@@ -24,5 +37,8 @@ BEGIN { in_fence = 0; first_line = 0 }
}
}
END {
- if (in_fence) print "
"
+ if (in_fence) {
+ if (first_line) printf "%s", "" code_tag
+ print "
"
+ }
}
diff --git a/awk/indented_code.awk b/awk/indented_code.awk
index c67dd02..285d842 100644
--- a/awk/indented_code.awk
+++ b/awk/indented_code.awk
@@ -1,9 +1,20 @@
-BEGIN { in_code = 0 }
-/^ | / {
- if (!in_code) { print ""; in_code = 1 }
- sub(/^ | /, "", $0)
- gsub(/&/, "\\&"); gsub(/, "\\<"); gsub(/>/, "\\>")
- print; next
+BEGIN { in_code = 0; in_html_pre = 0 }
+{
+ if ($0 ~ //) in_html_pre = 1
+ if ($0 ~ /<\/pre>/) { in_html_pre = 0; if (in_code) { print "
"; in_code = 0 }; print; next }
+
+ if (!in_html_pre && $0 ~ /^(\t| )/) {
+ if (!in_code) { printf "%s", ""; in_code = 1 }
+ sub(/^(\t| )/, "", $0)
+ gsub(/&/, "\\&"); gsub(/, "\\<"); gsub(/>/, "\\>")
+ print
+ next
+ }
+
+ if (in_code) {
+ print "
"
+ in_code = 0
+ }
+ print
}
-{ if (in_code) { print ""; in_code = 0 } print }
END { if (in_code) print "" }
diff --git a/awk/render_template.awk b/awk/render_template.awk
index 90d3b06..ca103d9 100644
--- a/awk/render_template.awk
+++ b/awk/render_template.awk
@@ -1,9 +1,17 @@
-function replace_all(text, token, value, pos, token_len) {
+function replace_all(text, token, value, pos, token_len, res) {
token_len = length(token)
+ res = ""
while ((pos = index(text, token)) > 0) {
- text = substr(text, 1, pos - 1) value substr(text, pos + token_len)
+ res = res substr(text, 1, pos - 1) value
+ text = substr(text, pos + token_len)
+ }
+ return res text
+}
+
+BEGIN {
+ if (current_url != "") {
+ nav = replace_all(nav, "href=\"" current_url "\"", "href=\"" current_url "\" class=\"current-page\"")
}
- return text
}
{
diff --git a/kewt.sh b/kewt.sh
index 36103d9..a99a20a 100755
--- a/kewt.sh
+++ b/kewt.sh
@@ -69,6 +69,7 @@ EOF
+
{{TITLE}}
@@ -207,6 +208,7 @@ CONFEOF
+
{{TITLE}}
@@ -623,6 +625,15 @@ copy_style_with_resolved_vars() {
render_markdown() {
file="$1"
is_home="$2"
+ url_override="$3"
+
+ if [ -n "$url_override" ]; then
+ current_url="$url_override"
+ else
+ rel_path="${file#"$src"}"
+ rel_path="${rel_path#/}"
+ current_url="/${rel_path%.md}.html"
+ fi
content_file="$file"
if [ -n "$posts_dir" ] && [ "$file" != "$src/$posts_dir/index.md" ]; then
@@ -704,7 +715,7 @@ render_markdown() {
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 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" 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"
}
echo "Building site from '$src' to '$out'..."
@@ -734,7 +745,9 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
if [ "$md_count" -eq 1 ]; then
md_file=$(find "$dir" ! -name "$(basename "$dir")" -prune -name "*.md")
is_home="false"; [ "$dir" = "$src" ] && is_home="true"
- render_markdown "$md_file" "$is_home" > "$out_dir/index.html"
+ target_url="/$rel_dir/index.html"
+ [ "$rel_dir" = "." ] && target_url="/index.html"
+ render_markdown "$md_file" "$is_home" "$target_url" > "$out_dir/index.html"
continue
fi
fi
@@ -792,7 +805,9 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
fi
done
is_home="false"; [ "$dir" = "$src" ] && is_home="true"
- render_markdown "$temp_index" "$is_home" > "$out_dir/index.html"
+ target_url="/$rel_dir/index.html"
+ [ "$rel_dir" = "." ] && target_url="/index.html"
+ render_markdown "$temp_index" "$is_home" "$target_url" > "$out_dir/index.html"
rm "$temp_index"
fi
done
@@ -840,7 +855,7 @@ if [ -n "$error_page" ] && [ ! -f "$out/$error_page" ]; then
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"
+ render_markdown "$temp_404" "false" "/$error_page" > "$out/$error_page"
rm -f "$temp_404"
fi
diff --git a/site/index.md b/site/index.md
index b71cfbf..8e7f448 100644
--- a/site/index.md
+++ b/site/index.md
@@ -22,6 +22,11 @@ It's meant to be a static site generator, like _[kew](https://github.com/uint23/
- Admonition support (that's what the blocks like the warning block below are called)
- RSS/Feed generation and Sitemap support
- Post creation via `--post`
+- Automatic 404 page generation
+- `?v=n` support for cache busting
+- Code block classes for use with external libraries like highlight.js or prism.js (both tested)
+- Clickable markdown header anchors
+- Mobile responsive layout
If you want to **force** a file to be inlined, use `\!![]` instead of `\![]`
@@ -43,6 +48,7 @@ On Arch Linux, _kewt_ is available on the AUR:
```sh
./kewt.sh --help
+./kewt.sh --version
./kewt.sh --new [title]
./kewt.sh --post
./kewt.sh --from --to
@@ -79,6 +85,7 @@ base_url = ""
generate_feed = false
feed_file = "rss.xml"
posts_dir = ""
+enable_header_links = true
```
- `title` site title
@@ -104,6 +111,7 @@ posts_dir = ""
- `generate_feed` enable RSS feed generation (requires `base_url`)
- `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.
+- `enable_header_links` turns markdown section headings into clickable anchor links (default: true)
## Ignores
diff --git a/styles/kewt.css b/styles/kewt.css
index 24fa6fc..e250723 100644
--- a/styles/kewt.css
+++ b/styles/kewt.css
@@ -1,25 +1,28 @@
:root {
- --bg: #646c7f;
- --fg: #fffde0;
- --fg-link: #fff18f;
- --code-bg: #32394a;
- --code-border: #8f95a4;
- --code-fg: #fffde0;
- --code-sel: #fff18f;
- --code-prop: #ffd27f;
- --code-val: #cde7ff;
- --code-var: #b9ffbe;
- --code-com: #d0d0d0;
- --adm-note-bg: #3f5666;
- --adm-note-border: #a8d8ff;
- --adm-tip-bg: #3f664c;
- --adm-tip-border: #b9ffbe;
- --adm-important-bg: #5a4a6c;
- --adm-important-border: #e4c7ff;
- --adm-warning-bg: #6b5539;
- --adm-warning-border: #ffe0a8;
- --adm-caution-bg: #6f3f3f;
- --adm-caution-border: #ffb4b4;
+ --bg: #4a3b69;
+ --bg-deep: #352654;
+ --fg: #fbf5ff;
+ --fg-muted: #c8b9df;
+ --fg-link: #dfaeff;
+ --fg-heading: #debfff;
+ --code-bg: #31234c;
+ --code-border: #8060af;
+ --code-fg: #fbf5ff;
+ --code-sel: #ffef99;
+ --code-prop: #ffdfba;
+ --code-val: #cae2ff;
+ --code-var: #caffc2;
+ --code-com: #b8aac8;
+ --adm-note-bg: #353866;
+ --adm-note-border: #b8c5ff;
+ --adm-tip-bg: #295246;
+ --adm-tip-border: #aeffda;
+ --adm-important-bg: #533076;
+ --adm-important-border: #f4d9ff;
+ --adm-warning-bg: #634631;
+ --adm-warning-border: #ffe2bd;
+ --adm-caution-bg: #662d43;
+ --adm-caution-border: #ffc4d5;
}
body {
@@ -29,18 +32,22 @@ body {
color: var(--fg);
font-family: serif;
font-size: 16px;
- line-height: 1.2;
+ line-height: 1.5;
}
header {
padding: 20px;
+ padding-bottom: 0;
+ border-bottom: 1px solid var(--code-border);
+ margin-bottom: 20px;
}
header h1 {
margin: 0;
font-size: 35px;
- font-weight: normal;
+ font-weight: bold;
font-style: italic;
+ color: var(--fg-heading);
}
.site-logo {
@@ -57,18 +64,26 @@ header a {
text-decoration: none;
}
+header a:hover {
+ color: var(--bg-deep);
+ background: var(--fg);
+}
+
#side-bar {
position: absolute;
top: 80px;
left: 0;
width: 200px;
padding-left: 20px;
+ margin-right: 14px;
+ border-right: 1px solid var(--code-border);
+ padding-right: 7px;
}
.side-title {
font-size: 25px;
margin: 20px 0 8px 0;
- color: var(--fg);
+ color: var(--fg-heading);
}
#side-bar ul {
@@ -87,6 +102,14 @@ a {
padding: 1px 2px;
}
+#side-bar a.current-page {
+ font-weight: bold;
+ color: var(--fg);
+ border-left: 3px solid var(--fg-link);
+ padding-left: 7px;
+ margin-left: -10px;
+}
+
a:hover {
background: var(--fg);
color: var(--bg);
@@ -100,7 +123,7 @@ article {
h3 {
margin-top: 30px;
font-size: 25px;
- color: var(--fg);
+ color: var(--fg-heading);
font-weight: normal;
}
@@ -197,10 +220,11 @@ pre code {
}
footer {
- padding-top: 80px;
+ padding-top: 60px;
font-style: italic;
font-size: 17px;
margin-bottom: 20px;
+ color: var(--fg-muted);
}
article,
@@ -220,3 +244,33 @@ footer img {
display: inline-block;
vertical-align: top;
}
+
+hr {
+ height: 0;
+ margin: 24px 0;
+ border: 0;
+ border-top: 1px solid var(--code-border);
+}
+
+@media screen and (max-width: 600px) {
+ #side-bar {
+ position: relative;
+ top: auto;
+ left: auto;
+ width: auto;
+ border-right: none;
+ border-bottom: 1px solid var(--code-border);
+ padding: 0 0 20px 0;
+ margin: 0 20px 20px 20px;
+ }
+
+ article {
+ margin: 0 20px 0 20px;
+ }
+
+ footer {
+ margin-left: 20px;
+ margin-right: 20px;
+ padding-top: 30px;
+ }
+}
\ No newline at end of file