Compare commits

..

6 commits

Author SHA1 Message Date
299d472d9b release 1.2.0 2025-07-15 18:43:28 -04:00
d35d3f61fb updated documentation 2025-07-15 18:42:32 -04:00
4ea80a33f8 improved styling of hover symbols 2025-07-15 18:35:13 -04:00
c33acfa1c8 added hover symbols to page titles 2025-07-15 17:53:05 -04:00
bafe70ed37 fix post-nav button order
Navigation now follows newer/older logic. click right to go older, left
to go newer.
2025-07-15 17:18:09 -04:00
fa10a813f2 add to .kakrc 2025-07-15 16:48:03 -04:00
10 changed files with 123 additions and 85 deletions

4
.kakrc
View file

@ -15,6 +15,10 @@ define-command readme %{
root-edit README.md root-edit README.md
} }
define-command kakrc %{
root-edit .kakrc
}
# change working directory to the package # change working directory to the package
hook global -once BufCreate .* %{ hook global -once BufCreate .* %{
change-directory %exp{%opt{project_root}/src/zona} change-directory %exp{%opt{project_root}/src/zona}

View file

@ -101,10 +101,6 @@ If you don't want discovery, you can specify the project root as the first
argument to `zona build`. You may specify a path for the output using the argument to `zona build`. You may specify a path for the output using the
`--output/-o` flag. The `--draft/-d` flag includes draft posts in the output. `--output/-o` flag. The `--draft/-d` flag includes draft posts in the output.
_Note: the previous build is _not_ cleaned before the new site is built. If
you've deleted some pages, you may need to remove the output directory before
rebuilding._
### Live Preview ### Live Preview
To make the writing process as frictionless as possible, zona ships with a live To make the writing process as frictionless as possible, zona ships with a live
@ -121,9 +117,10 @@ By default, the build outputs to a temporary directory. Use `-o/--output` to
override this. override this.
**Note**: if the live preview isn't working as expected, try restarting the **Note**: if the live preview isn't working as expected, try restarting the
server. If you change the configuration or any templates, the server must also server. If you change the configuration, the server must also be restarted. The
be restarted. The live preview uses the same function as `zona build` live preview uses the same function as `zona build` internally; this means that
internally; this means that the output is also written to disk. the output is also written to disk --- a temporary directory by default, unless
overridden with `-o/--output`.
#### Live Reload #### Live Reload
@ -197,12 +194,16 @@ option in its [frontmatter](#frontmatter). The following public variables are
made available to the template engine: made available to the template engine:
| Name | Description | | Name | Description |
| ---------- | ------------------------------------------------------ | | ----------- | -------------------------------------------------------- |
| `content` | The content of this page. | | `content` | The content of this page. |
| `url` | The resolved URL of this page. | | `url` | The resolved URL of this page. |
| `metadata` | The frontmatter of this page (_merged with defaults_). | | `metadata` | The frontmatter of this page (_merged with defaults_). |
| `header` | The sitemap header in HTML form. Can be `False`. | | `header` | The sitemap header in HTML form. Can be `False`. |
| `footer` | The footer in HTML form. Can be `False`. | | `footer` | The footer in HTML form. Can be `False`. |
| `is_post` | Whether this page is a post. |
| `newer` | URL of the newer post in the post list. |
| `older` | URL of the older post in the post list. |
| `post_list` | A sorted list of `Item` objects. Meant for internal use. |
#### Markdown Footer #### Markdown Footer

View file

@ -1,6 +1,6 @@
[project] [project]
name = "zona" name = "zona"
version = "1.1.0" version = "1.2.0"
description = "Opinionated static site generator." description = "Opinionated static site generator."
license = "BSD-3-Clause " license = "BSD-3-Clause "
license-files = ["LICENSE"] license-files = ["LICENSE"]

View file

@ -99,6 +99,8 @@ class ZonaBuilder:
def _build(self): def _build(self):
assert self.items assert self.items
# sort according to date
# descending order
post_list: list[Item] = sorted( post_list: list[Item] = sorted(
[item for item in self.items if item.post], [item for item in self.items if item.post],
key=lambda item: item.metadata.date key=lambda item: item.metadata.date
@ -106,12 +108,16 @@ class ZonaBuilder:
else date.min, else date.min,
reverse=True, reverse=True,
) )
# number of posts
posts = len(post_list) posts = len(post_list)
# link post chronology
for i, item in enumerate(post_list): for i, item in enumerate(post_list):
prev = post_list[i - 1] if i > 0 else None # prev: older post
next = post_list[i + 1] if i < posts - 2 else None older = post_list[i + 1] if i + 1 < posts else None
item.previous = prev # next: newer post
item.next = next newer = post_list[i - 1] if i > 0 else None
item.older = older
item.newer = newer
templater = Templater( templater = Templater(
config=self.config, config=self.config,

View file

@ -1,4 +1,5 @@
:root { :root {
--main-placeholder-color: #b14242;
--main-text-color: #b4b4b4; --main-text-color: #b4b4b4;
--main-text-opaque-color: rgba(180, 180, 180, 0.8); --main-text-opaque-color: rgba(180, 180, 180, 0.8);
--main-bg-color: #121212; --main-bg-color: #121212;
@ -33,27 +34,77 @@ header {
.post-nav { .post-nav {
font-family: monospace; font-family: monospace;
font-size: 0.95em;
white-space: nowrap;
}
.post-nav .bar {
position: relative;
bottom: 0.05em;
display: inline-block;
width: 1px;
height: 0.8em;
background-color: currentColor;
vertical-align: middle;
margin: 0 0.3em;
}
.post-nav .placeholder {
color: var(--main-placeholder-color);
} }
.post-nav .symbol { .post-nav .symbol {
color: var(--main-bullet-color); color: var(--main-bullet-color);
margin: 0;
padding: 0;
display: inline;
} }
.post-nav a { .site-logo.hover-symbol::before {
margin: 0 2px; content: "@";
/* color: var(--main-bullet-color);*/
} }
.site-logo { .title.hover-symbol::before {
content: ">";
/* color: var(--main-bullet-color);*/
}
.hover-symbol {
color: inherit; color: inherit;
position: relative;
font-weight: bold; font-weight: bold;
text-decoration: none; text-decoration: none;
/* font-size: 1.75rem;*/ transition: color 0.15s ease;
}
.hover-symbol::before {
font-family: monospace;
content: "#";
position: absolute;
right: 100%;
margin-right: 0.25em;
top: 50%;
transform: translateY(-50%);
opacity: 0;
transition: opacity 0.15s ease, color 0.15s ease;
color: var(--main-text-color);
}
.hover-symbol:hover::before {
opacity: 1;
color: var(--main-placeholder-color); /* only the symbol changes color */
}
.hover-symbol:hover {
background-color: transparent;
/* color: var(--main-placeholder-color);*/
} }
.toclink { .toclink {
position: relative; position: relative;
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
transition: color 0.15s ease;
} }
.toclink::before { .toclink::before {
@ -64,7 +115,16 @@ header {
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
opacity: 0; opacity: 0;
transition: opacity 0.2s ease; transition: opacity 0.15s ease, color 0.15s ease;
color: var(--main-link-color);
}
.toclink:hover::before {
opacity: 1;
color: var(--main-placeholder-color);
}
.toclink:hover {
background-color: transparent;
} }
h1 .toclink::before { h1 .toclink::before {
@ -83,13 +143,6 @@ h4 .toclink::before {
content: "###"; content: "###";
} }
.toclink:hover::before {
opacity: 1;
}
.toclink:hover {
background-color: transparent;
}
/* h1, */ /* h1, */
h2, h2,
h3, h3,
@ -111,6 +164,11 @@ h1 {
font-family: monospace; font-family: monospace;
} }
.title a {
color: inherit;
text-decoration: none;
}
article h1:first-of-type { article h1:first-of-type {
margin-block-start: 1.67rem; margin-block-start: 1.67rem;
} }
@ -156,38 +214,26 @@ h6 {
ul { ul {
list-style-type: disc; list-style-type: disc;
/* or any other list style */
} }
li::marker { li::marker {
color: var(--main-bullet-color); color: var(--main-bullet-color);
/* Change this to your desired color */
} }
a { a {
color: var(--main-link-color); color: var(--main-link-color);
text-decoration: none; text-decoration: underline;
position: relative; text-decoration-color: rgba(0, 0, 0, 0);
text-underline-offset: 2px;
} }
a::after { a {
content: ""; transition: color 0.15s ease, text-decoration-color 0.15s ease;
position: absolute;
left: 0;
bottom: -2px;
width: 100%;
height: 1px;
background-color: currentColor;
transform: scaleX(0);
transform-origin: center;
transition: transform 0.1s ease;
} }
a:hover::after { a:hover {
transform: scaleX(1); text-decoration-color: var(--main-placeholder-color);
} color: var(--main-bullet-color);
a:has(> code)::after {
display: none;
} }
max-width: 100%; max-width: 100%;
@ -424,23 +470,3 @@ caption {
font-size: 0.8rem; font-size: 0.8rem;
color: var(--main-small-text-color); color: var(--main-small-text-color);
} }
a > code {
text-decoration: none;
color: var(--main-link-color);
position: relative;
}
a:has(> code) {
text-decoration: none;
background: none;
/* position: static;*/
}
a:hover > code {
text-decoration: underline;
}
a:hover:has(> code) {
background: none;
}

View file

@ -1,9 +1,11 @@
<div class="post-nav"> <div class="post-nav">
<center> <center>
<span class="symbol">&lt;</span>{% if previous %}<a <span class="symbol">&lt;</span>{% if newer %}<a href="{{ newer }}">newr</a>{%
href="{{ previous }}" else %}<span class="placeholder">null</span>{% endif %}<span
>prev</a>{% endif %}{% if previous and next %}<span class="symbol" class="symbol"
>|</span>{% endif %}{% if next %}<a href="{{ next }}">next</a>{% endif ><span class="bar"></span></span>{% if older %}<a href="{{ older }}"
%}<span class="symbol">&gt;</span> >oldr</a>{% else %}<span class="placeholder">null</span>{% endif %}<span
class="symbol"
>&gt;</span>
</center> </center>
</div> </div>

View file

@ -1,2 +1,2 @@
<center><h1 class="title">{{ metadata.title }}</h1></center> <center><h1 class="title hover-symbol"><a id="" href="#">{{ metadata.title }}</a></h1></center>

View file

@ -23,8 +23,8 @@ class Item:
type: ItemType | None = None type: ItemType | None = None
copy: bool = True copy: bool = True
post: bool = False post: bool = False
next: Item | None = None newer: Item | None = None
previous: Item | None = None older: Item | None = None
# @dataclass # @dataclass

View file

@ -27,7 +27,6 @@ def get_footer(template_dir: Path) -> str | None:
return html_footer.read_text() return html_footer.read_text()
# TODO: add next/prev post button logic to posts
# TODO: add a recent posts element that can be included elsewhere? # TODO: add a recent posts element that can be included elsewhere?
class Templater: class Templater:
def __init__( def __init__(
@ -79,11 +78,11 @@ class Templater:
header=header, header=header,
footer=footer, footer=footer,
is_post=item.post, is_post=item.post,
next=util.normalize_url(item.next.url) newer=util.normalize_url(item.newer.url)
if item.next if item.newer
else None, else None,
previous=util.normalize_url(item.previous.url) older=util.normalize_url(item.older.url)
if item.previous if item.older
else None, else None,
post_list=self.post_list, post_list=self.post_list,
) )

2
uv.lock generated
View file

@ -459,7 +459,7 @@ wheels = [
[[package]] [[package]]
name = "zona" name = "zona"
version = "1.1.0" version = "1.2.0"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "dacite" }, { name = "dacite" },