Init zine

This commit is contained in:
Yadunand Prem 2025-08-05 00:34:58 +08:00
parent 477b3c9a79
commit c6fc0b093b
27 changed files with 1027 additions and 0 deletions

2
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,2 @@
{
}

249
assets/Temml-Local.css Normal file
View File

@ -0,0 +1,249 @@
/*
Temml.woff2 is a clone of KaTeX_Script-Regular, except that the code points
have been changed from ASCII to Unicode Mathematical Alphanumeric Symbols Script capitals,
Unicode range 1D49C to 1D4B5.
*/
@font-face {
font-family: 'Temml';
src: url('Temml.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
math {
font-family: "Cambria Math", 'STIXTwoMath-Regular', 'NotoSansMath-Regular', math;
font-style: normal;
font-weight: normal;
line-height: normal;
font-size-adjust: none;
text-indent: 0;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
direction: ltr;
/* Prevent Firefox from omitting the dot on i or j. */
font-feature-settings: "dtls" off;
}
math * {
border-color: currentColor;
}
/* Next line is active in Firefox and Safari.
* Not in Chromium, which recognizes display: "block math" written inline. */
math.tml-display { display: block; }
*.mathcal {
/* NotoSans */
font-feature-settings: 'ss01';
}
math .mathscr {
font-family: "Temml";
}
mo.tml-prime {
font-family: Temml;
}
/* Prevent f' from overlapping in Chromium */
mo.prime-pad {
padding-left: 0.08em;
}
/* \cancel & \phase use background images. Get them to print. */
menclose {
-webkit-print-color-adjust: exact; /* Chrome & Edge */
print-color-adjust: exact;
}
/* Array cell justification in Firefox & WebKit */
.tml-right {
text-align: right;
}
.tml-left {
text-align: left;
}
/* Styles for Chromium only */
@supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
/* MathML Core & Chromium do not support the MathML 3.0 element <menclose> attributes. */
/* So use styles. */
menclose {
position: relative;
padding: 0.5ex 0ex;
}
.tml-overline {
padding: 0.1em 0 0 0;
border-top: 0.065em solid;
}
.tml-underline {
padding: 0 0 0.1em 0;
border-bottom: 0.065em solid;
}
.tml-cancel {
display: inline-block;
position: absolute;
left: 0.5px;
bottom: 0;
width: 100%;
height: 100%;
background-color: currentColor;
}
.upstrike {
clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
}
.downstrike {
clip-path: polygon(0em 0.05em, 0.05em 0em, 100% calc(100% - 0.05em), calc(100% - 0.05em) 100%);
}
.sout {
clip-path: polygon(0em calc(55% + 0.0333em), 0em calc(55% - 0.0333em), 100% calc(55% - 0.0333em), 100% calc(55% + 0.0333em));
}
.tml-xcancel {
background: linear-gradient(to top left,
rgba(0,0,0,0) 0%,
rgba(0,0,0,0) calc(50% - 0.06em),
rgba(0,0,0,1) 50%,
rgba(0,0,0,0) calc(50% + 0.06em),
rgba(0,0,0,0) 100%),
linear-gradient(to top right,
rgba(0,0,0,0) 0%,
rgba(0,0,0,0) calc(50% - 0.06em),
rgba(0,0,0,1) 50%,
rgba(0,0,0,0) calc(50% + 0.06em),
rgba(0,0,0,0) 100%)
}
.longdiv-top {
border-top: 0.067em solid;
padding: 0.1em 0.2em 0.2em 0.433em;
}
.longdiv-arc {
position: absolute;
top: 0;
bottom: 0.1em;
left: -0.4em;
width: 0.7em;
border: 0.067em solid;
transform: translateY(-0.067em);
border-radius: 70%;
clip-path: inset(0 0 0 0.4em);
box-sizing: border-box;}
.menclose {display: inline-block;
text-align: left;
position: relative;
}
.phasor-bottom {
border-bottom: 0.067em solid;
padding: 0.2em 0.2em 0.1em 0.6em;
}
.phasor-angle {
display: inline-block;
position: absolute;
left: 0.5px;
bottom: -0.04em;
height: 100%;
aspect-ratio: 0.5;
background-color: currentColor;
clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
}
.tml-box {
padding: 3pt 0 3pt 0;
border: 1px solid;
}
.tml-fbox {
padding: 3pt;
border: 1px solid;
}
.circle-pad {
padding: 0.267em;
}
.textcircle {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
border: 0.067em solid;
border-radius: 50%;
}
.actuarial {
padding: 0.03889em 0.03889em 0 0.03889em;
border-width: 0.08em 0.08em 0em 0em;
border-style: solid;
margin-right: 0.03889em;
}
/* Stretch \widetilde */
.tml-crooked-2 {
transform: scale(2.0, 1.1)
}
.tml-crooked-3 {
transform: scale(3.0, 1.3)
}
.tml-crooked-4 {
transform: scale(4.0, 1.4)
}
/* set array cell justification */
.tml-right {
text-align: -webkit-right;
}
.tml-left {
text-align: -webkit-left;
}
}
/* Adjust WebKit accents */
@supports (-webkit-backdrop-filter: blur(1px)) {
.tml-xshift { transform: translate(0px, 0.45em) }
.tml-capshift { transform: translate(0px, 0.35em) }
}
/* flex-wrap for line-breaking in Chromium */
math {
display: inline-flex;
flex-wrap: wrap;
align-items: baseline;
}
math > mrow {
padding: 0.5ex 0ex;
}
/* Default mtd top padding is 0.5ex per MathML-Core and user-agent CSS */
/* We adjust for jot and small */
mtable.tml-jot mtd {
padding-top: 0.7ex;
padding-bottom: 0.7ex;
}
mtable.tml-small mtd {
padding-top: 0.35ex;
padding-bottom: 0.35ex;
}
/* Firefox */
@-moz-document url-prefix() {
/* Avoid flex-wrap */
math { display: inline; }
math > mrow { padding: 0 }
/* Adjust Firefox spacing between array rows */
mtd, mtable.tml-small mtd { padding-top: 0; padding-bottom: 0; }
mtable.tml-jot mtd { padding-top: 0.2ex; padding-bottom: 0.ex; }
}
/* AMS environment auto-numbering via CSS counter. */
.tml-eqn::before {
counter-increment: tmlEqnNo;
content: "(" counter(tmlEqnNo) ")";
}
body {
counter-reset: tmlEqnNo;
}

BIN
assets/Temml.woff2 Normal file

Binary file not shown.

37
assets/highlight.css Normal file
View File

@ -0,0 +1,37 @@
:root {
--light-yellow: #e5c07b;
--dark-yellow: #d19a66;
--blue: #61afef;
--cyan: #56b6c2;
--light-red: #e06c75;
--dark-red: #be5046;
--comment-gray: #5c6370;
--magenta: #c678dd;
}
pre {
border-top: 1px solid white;
border-bottom: 1px solid white;
padding: 10px 5px;
}
code.ziggy {
color: var(--cyan);
}
code.ziggy .keyword,
code.ziggy .type {
color: var(--light-yellow);
}
code.ziggy .string {
color: var(--dark-yellow);
}
code.ziggy .numeric.constant {
color: var(--magenta);
}
code.ziggy .function {
color: var(--blue);
}

8
assets/render-mathtex.js Normal file
View File

@ -0,0 +1,8 @@
let eqns = document.querySelectorAll("script[type='math/tex']");
for (let i=eqns.length-1; i>=0; i--) {
let eqn = eqns[i];
let src = eqn.text;
let d = eqn.closest('p') == null;
eqn.outerHTML = temml.renderToString(src, { displayMode: d });
}

85
assets/style.css Normal file
View File

@ -0,0 +1,85 @@
h1,
h2,
h3,
h4,
h5 {
color: #ddd;
font-family: "Verdana", sans-serif;
}
b,
strong {
color: #fff;
}
a {
color: #eee;
}
html {
color: #ccc;
font-family: "Georgia", serif;
font-size: 1.2em;
display: flex;
flex-direction: row;
justify-content: center;
background-color: #111;
}
body {
width: 800px;
padding: 15px;
display: flex;
flex-direction: column;
}
.site-title {
font-size: 2.5em;
margin-bottom: 10px;
/* text-align: center; */
}
nav {
display: flex;
flex-direction: row;
justify-content: left;
font-size: 1.2em;
margin-bottom: 20px;
}
.block {
border: 1px dotted white;
padding: 5px 15px;
margin: 0 10px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.block h1 {
font-size: 1em;
text-align: center;
margin-bottom: 0;
}
.small {
font-size: 0.8em;
}
.wave {
background: #111;
color: #fff;
text-shadow: 1px 1px 10px #fff, 1px 1px 10px #ccc;
}
footer {
margin-top: 30px;
display: flex;
flex-direction: column;
align-items: center;
}
footer hr {
width: 100%;
}

1
assets/temml.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

56
content/about.smd Normal file
View File

@ -0,0 +1,56 @@
---
.title = "About",
.date = @date("1990-01-01T00:00:00"),
.author = "Sample Author",
.layout = "index.shtml",
.draft = false,
---
## About Zine
Zine is an MIT-licensed project created by [Loris Cro](https://kristoff.it) and
other contributors listed on the [official repository](https://github.com/kristoff-it/zine/contributors).
Zine is inspired by [Hugo](https://gohugo.io) but features an entirely custom set
of authoring languages:
- [Scripty](https://zine-ssg.io/docs/scripty/) is the small expression
language that both SuperHTML and SuperMD share to express templating logic.
- [SuperHTML](https://zine-ssg.io/docs/superhtml/) is the HTML templating
language used by Zine. Unlike most `{{curly braced}}` templating languages,
SuperHTML uses valid HTML syntax to express the templating logic, adding only
minor extensions to normal HTML.
Thanks to this approach, it offers instant
syntax checking and autoformatting via [a CLI tool](https://github.com/kristoff-it/superhtml) as well as Language Server support ([VScode Extension](https://marketplace.visualstudio.com/items?itemName=LorisCro.super)).
># [NOTE]($block)
>The correct file extension for SuperHTML templates is `.shtml`.
- [SuperMD](https://zine-ssg.io/docs/supermd/) is a superset of Markdown
that, instead of relying on inline HTML, offers new constructs for expressing
content embeds without pulling into your content needless layouting concerns.
A CLI tool and language server for SuperMD is in the works.
># [NOTE]($block)
>The correct file extension for SuperMD pages is `.smd`.
## Zine is alpha software
Zine is not yet complete. The main functionality is present and you will be able
to build even moderately complex static websites without issue.
That said using Zine today does imply participating in the development process
to some degree, which usually means inquiring about the development status of
a feature you need, or reporting a bug.
Here are some quicklinks related to Zine:
- Official Website: https://zine-ssg.io/
- Source Code: https://github.com/kristoff-it/zine/
- Discord: https://discord.com/invite/B73sGxF

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@ -0,0 +1,110 @@
---
.title = "First Post: What's A Zine?",
.date = @date("1990-01-01T00:00:00"),
.author = "Sample Author",
.layout = "post.shtml",
.draft = false,
---
This is a sample first post for your blog.
This post is defined in `content/blog/first-post/` and contains the following
files:
- `index.smd`
- `fanzine.jpg`
Another interesting thing about this post is that it uses the `layouts/post.shtml`
template which adds at the bottom page navigation within the blog section.
Enough about Zine, let's talk about zines.
## Fanzines
A zine (short for *fanzine*, from "fan" + "magazine") is a non-professional
publication created by people that want to express themselves in paper form,
usually in relation to a cultural phenomenon of some kind.
[An example of zine from 1976.](<$image.asset("fanzine.jpg").alt("A photo of a black and white flyer. The main title reads 'A night of pure energy' and the rest of the page contains a mix of pictures of guitarists interleaved with other text snippets, some seemingly taken from a professional publication of some kind, and some handwritten to announce concert night dates, presumably for the musicians in the picture.")>)
## Zines in the digital era
In the digital age, some of the cultural impetus behind zines got redirected to
personal blogs and similar digital, non-professional publications. The 90's and
early 00's are famous for their whacky websites full of clip art, wordart text
and "under construction" animated gifs.
This initial organic exploration didn't last for too long as the rise of social
media diverted a lot of self-expression energy towards walled gardens, a change
that was also fueled by the much tighter and intense feedback loop that those
platform enable.
In the 90's the stongest dopamine hit you could get was adding a visit counter
to your altavista website and watch it go up, slowly, mostly because of your own
accesses. In modern times views are almost meaningless and interactions such as
*likes*, *retweets* and *comments* provide much stronger positive feedback.
An unfortunate side effect of this new cultural wave centered around social media
is that not only you end up gifting your content to platform owners, but you also
participate in a system where the *language* of the social media site shapes your
thoughts and experience in specific, and often user-hostile, ways.
Art, just like liquids, takes the shape of the container you put it in. A mobile
game that lives off of in app purchases will never be truly great because of the
tension between making the game entertaining enough to keep players engaged, and
the need to make it boring enough so that they will want to buy upgrades to make
the game more fun.
Similarly, self-expression on Twitter is encouraged to take the shape of short,
hyperbolic hot takes that forgo nuance in order to create catchy quips that can
be used for hasty decision making.
Likewise, [corpowave]($text.attrs('wave')) never goes out of style on LinkedIn.
Spend enough time in there and you will become a character from Severance.
## We're not in 1990 anymore
Despite all the issues with social media, there is no point in thinking of the
90's as a better time. It was not. And despite the winks at the past, Zine is
not a tool for indulging in nostalgia.
**The goal is to make art**: the act of inducing a change in others through
our self-expression.
You could argue that the 90's excelled at self-expression, but in doing so you
would also have to accept that social media is infinitely more effective at
inducing change in others (albeit at the expense of freedom of expression).
Once you realize that, the path forward is clear:
1. Own your content.
2. Create new social systems that optimize for creating art over engagement.
Owning your content means that you will be unaffected by enshittification of
platforms that would otherwise keep your data hostage. It also is the single
most effective thing you can do as an individual to take power away from
platforms, all while protecting your own immediate interests.
Creation of new social systems is a *slightly more hairy* problem than self
hosting a static website, but it's something that can be done. Over the years
we've had plenty of social outlets that have allowed people to socialize through
their homemade games, music, drawings, fanfics, etc; and chances are that we
have yet many more of these outlets ahead of us to create.
Zine gives you a small puzzle piece to help you inch closer toward a better
future, partially by providing you with a new iteration over tried and true
patterns (e.g. by facilitating content creation by separating content from
layouting concerns as much as possible), and also by being a bit experimental
with the concept of a devlog, something that you wouldn't normally expect to
find on a static website.
Lastly, Zine makes sure your content (both blog and devlog, but also any
other content format you might come up with yourself) is available via RSS
syndication. RSS feeds are far from a winning technology in the fight against
the ebb and *enshitty*flow of social media, but they are another small puzzle
piece that costs nothing to maintain and that might turn out to be critical once
enough other preconditions are met.
With that in mind, **go make art with your words**.
-- Loris

40
content/blog/index.smd Normal file
View File

@ -0,0 +1,40 @@
---
.title = "Blog",
.date = @date("1990-01-01T00:00:00"),
.author = "Sample Author",
.layout = "blog.shtml",
.alternatives = [{
.name = "rss",
.layout = "blog.xml",
.output = "index.xml",
}],
.draft = false,
---
This page defines the blog section and lists all posts in it.
A "site section" in Zine is a group of pages that form a logical subtree of the
website. It's related to directory structure, but it's not an entirely 1:1 mapping.
What defines a site section in Zine is the presence of `index.smd` files. You
can learn more [in the official Zine docs](https://zine-ssg.io/docs/).
Take also a look at `layouts/blog.shtml` to get an idea of how to render a page
list in a SuperHTML template.
The blog section also has an [RSS feed]($link.alternative('rss')).
In Zine, RSS feeds are considered "alternative" versions of an existing page. In
concrete defines the blog section and that lists all pages in it, is rendered in
two versions: HTML for human readers, and XML for RSS readers.
This is the SuperMD frontmatter code that defines the RSS feed:
```ziggy
.alternatives = [{
.name = "rss",
.layout = "rss.xml",
.output = "index.xml",
}],
```
[(btw syntax highlighting is done statically in Zine, no need for javascript libraries, unless you want to)]($text.attrs('small'))

View File

@ -0,0 +1,28 @@
---
.title = "Second Post",
.date = @date("1990-01-02T00:00:00"),
.author = "Sample Author",
.layout = "post.shtml",
.draft = false,
---
This second post is mainly here to show you that you can also create single file
posts for convenience. The first post contains more interesting content.
Don't forget to read [the official SuperMD
docs](https://zine-ssg.io/docs/supermd/) to know how to *style* your content.
Btw this sample website also includes the JS/CSS dependencies required to render
math:
```=mathtex
\begin{aligned}
f(t) &= \int_{-\infty}^\infty F(\omega) \cdot (-1)^{2 \omega t} \mathrm{d}\omega \\
F(\omega) &= \int_{-\infty}^\infty f(t) \div (-1)^{2 \omega t} \mathrm{d}t \\
\end{aligned}
```
This: [`(-1)^x = \cos(\pi x) + i\sin(\pi x)`]($mathtex) is an inline equation
instead!

18
content/devlog/1989.smd Normal file
View File

@ -0,0 +1,18 @@
---
.title = "Devlog - 1989",
.date = @date("1989-01-01T00:00:00"),
.author = "Sample Author",
.layout = "devlog.shtml",
.draft = false,
---
[]($section.id('about'))
## About this Devlog
This is a non-exhaustive, curated list of changes meant to help users quickly see what has improved since they last checked.
You can [subscribe the latest devlog via RSS]($link.page('devlog').alternative('rss')).
This page lists entries for the year 1989, for past or future entries consult the
[devlog archive](/devlog/).
## [Hello 1989]($section.id("1989-01-01T00:00:00"))
This is a sample entry.

38
content/devlog/1990.smd Normal file
View File

@ -0,0 +1,38 @@
---
.title = "Devlog - 1990",
.date = @date("1990-01-01T00:00:00"),
.author = "Sample Author",
.layout = "devlog.shtml",
.draft = false,
---
[]($section.id('about'))
## About this Devlog
This is where you should describe to your users what your devlog is about.
Refer to the corresponding section in the home page to learn more about devlogs.
For example this is how the Zine devlog describes itself:
> This is a non-exhaustive, curated list of changes meant to help users quickly see what has improved since they last checked.
>
> You can [subscribe to this page via RSS]($link.page('devlog').alternative('rss')).
>
> This page lists entries for the current year, for past entries consult the
[devlog archive](/devlog/).
Feel free to tweak it to your specific use case or replace it entirely as you
see fit.
Regardless of what you decide, you might want to make sure you preserve the
links to the RSS feed and to the devlog archive from the copy above.
## [Third Entry]($section.id("1990-01-03T00:00:00"))
This is the third entry.
## [Second Entry]($section.id("1990-01-02T00:00:00"))
This is the second entry.
## [Hello Zine]($section.id("1990-01-01T00:00:00"))
This is the first entry in this year's devlog created with
[Zine](https://zine-ssg.io)!

32
content/devlog/index.smd Normal file
View File

@ -0,0 +1,32 @@
---
.title = "Devlog Archive",
.date = @date("1990-01-01T00:00:00"),
.author = "Sample Author",
.layout = "devlog-archive.shtml",
.alternatives = [{
.name = "rss",
.layout = "devlog.xml",
.output = "index.xml",
}],
.draft = false,
---
This page lists all the devlog years that are present on this site.
Note how the top navigation menu doesn't link to this page, but instead links
to the latest devlog year directly.
The reason for adopting this structure is to make sure that links that exist in
the wild to entries to our devlog don't become invalidated when a new year comes
around and we rotate the devlog feed.
Devlog rotation ensures that you don't have a single page that grows
indefinitely, eventually compromising your editing expreience and worsening your
user's browsing experience. You can use any arbitrary policy (even deleting old
entries if you are fine with having a more ephemeral devlog), but cutting them
by year is a good default option.
When rotating a devlog all you have to do is create a new page with a newer
date set in the frontmatter `date` field, and update the page description to let
people know that this page is not the current year's devlog anymore.
The latest devlog year is also available [via RSS feed]($link.alternative('rss')).

88
content/index.smd Normal file
View File

@ -0,0 +1,88 @@
---
.title = "Homepage",
.date = @date("1990-01-01T00:00:00"),
.author = "Sample Author",
.layout = "index.shtml",
.draft = false,
---
This sample website showcases:
- A couple simple pages
- `content/index.smd`
- `content/about.smd`
- A blog
- `content/blog/index.smd`
- `content/blog/first-post/index.smd`
- `content/blog/second-post.smd`
- A devlog
- `content/devlog/index.smd`
- `content/devlog/1990.smd`
- `content/devlog/1989.smd`
## About Devlogs
While a blog has each entry be a separate page, a devlog is one single page with
a list of smaller entries in it, making it a form of microblogging. The relative
RSS feed will generate a separate item per devlog entry, creating a
"twitter-like" feed.
This can be a useful pattern for thoughts that are too small for a full blog post
so consider giving it a try!
The name "devlog" comes from the fact that this kind of microblogging feed works
well when you have an open source project and you want to give small updates to
your users, but it might work equally well for other domains, depending on your
interests and audience. Maybe a "foodlog", a "catlog" or a "treklog" could also
work well.
The devlog section contains more information about how devlogs can be implemented
in Zine.
Some examples of devlogs in the wild:
- https://zine-ssg.io/log/
- https://ziglang.org/devlog/
## Next steps
Make sure to read the [official Zine docs](https://zine-ssg.io/docs/)
and then start editing this website!
Start by putting the correct information in `zine.ziggy` and then start editing
the existing pages. Before deleting existing copy consider giving it a brief
look as it will show you some SuperMD specific syntax.
HTML markup in Zine is defined via SuperHTML templates:
- `layouts/index.shtml`
- `layouts/page.shtml`
- `layouts/post.shtml`
- `layouts/blog.shtml`
- `layouts/blog.xml`
- `layouts/devlog.shtml`
- `layouts/devlog.xml`
- `layouts/devlog-archive.shtml`
- `layouts/templates/base.shtml`
**If you're running the Zine development server (by running `zine`), then all
changes you make will be picked up immediately, causing the website to rebuild
and the page in your browser to refresh**.
You can learn more about SuperMD and SuperHTML in [/about/](/about/).
Lastly, this sample website also includes the following asset files:
- `assets/style.css`
- `assets/hightlight.css`
- `assets/under-construction.gif`
- `assets/katex-tag.js`
- `assets/katex0.16.21.css`
- `assets/katex0.16.21.js`
- `content/blog/first-post/fanzine.jpg`
The first few asset files are **site assets**, while the last is a **page asset** that belongs to the "first post" page.
The Zine docs contain more information about [dealing with assets](https://zine-ssg.io/docs/assets/).

25
layouts/blog.shtml Normal file
View File

@ -0,0 +1,25 @@
<extend template="base.shtml">
<head id="head">
<style>
.date {
font-size: 0.9em;
}
.title h3{
margin-top: 0;
}
</style>
</head>
<body id="body">
<h1 :text="$page.title"></h1>
<div :html="$page.content()"></div>
<div>
<h2>Post list</h2>
<div :loop="$page.subpages()">
<span class="date" :text="$loop.it.date.format('January 02, 2006')"></span>
<a class="title" href="$loop.it.link()">
<h3 :text="$loop.it.title"></h3>
</a>
</div>
</div>
</body>

19
layouts/blog.xml Normal file
View File

@ -0,0 +1,19 @@
<rss version="2.0">
<channel>
<title :text="$site.title"></title>
<link :text="$site.host_url"></link>
<description :text="$site.title.suffix(' - Blog')"></description>
<generator>Zine -- https://zine-ssg.io</generator>
<language>en-US</language>
<lastBuildDate :text="$build.generated.formatHTTP()"></lastBuildDate>
<ctx :loop="$page.subpages()">
<item>
<title :text="$loop.it.title"></title>
<description :text="$loop.it.content()"></description>
<link :text="$site.host_url.addPath($loop.it.link())"></link>
<pubDate :text="$loop.it.date.formatHTTP()"></pubDate>
<guid :text="$site.host_url.addPath($loop.it.link())"></guid>
</item>
</ctx>
</channel>
</rss>

View File

@ -0,0 +1,25 @@
<extend template="base.shtml">
<head id="head">
<style>
.date {
font-size: 0.9em;
}
.title h3{
margin-top: 0;
}
</style>
</head>
<body id="body">
<h1 :text="$page.title"></h1>
<div :html="$page.content()"></div>
<div>
<h2>Past years</h2>
<div :loop="$page.subpages()">
<span class="date" :text="$loop.it.date.format('Year 2006')"></span>
<a class="title" href="$loop.it.link()">
<h3 :text="$loop.it.title"></h3>
</a>
</div>
</div>
</body>

45
layouts/devlog.shtml Normal file
View File

@ -0,0 +1,45 @@
<extend template="base.shtml">
<head id="head">
<style>
.feed {
margin-top: 2em;
}
.feed>div {
margin: 0 -20px;
padding: 5px 20px;
margin-bottom: 1em;
}
.feed>div>h2 {
margin-top: 0.4em;
}
.feed>div[id]:target {
animation: pulse-div 2s ease-in-out 1 forwards;
}
@keyframes pulse-div {
0%,
100% {
background-color: #222;
}
50% {
background-color: #111;
}
}
</style>
</head>
<body id="body">
<h1 class="title" :text="$page.title"></h1>
<div :html="$page.contentSection('about')"></div>
<div class="feed" :loop="$page.contentSections().slice(1)">
<div id="$loop.it.id">
<span :text="$loop.it.id.parseDate().format('January 02, 2006')"></span>
<h2><a href="$loop.it.id.prefix('#')" :html="$loop.it.heading()"></a></h2>
<ctx :html="$loop.it.htmlNoHeading()"></ctx>
</div>
</div>
</body>

21
layouts/devlog.xml Normal file
View File

@ -0,0 +1,21 @@
<rss version="2.0">
<channel>
<title :text="$site.title"></title>
<link :text="$site.host_url"></link>
<description :text="$site.title.suffix(' - Devlog')"></description>
<generator>Zine -- https://zine-ssg.io</generator>
<language>en-US</language>
<lastBuildDate :text="$build.generated.formatHTTP()"></lastBuildDate>
<ctx :if="$page.subpages().first?()">
<ctx :loop="$if.contentSections().slice(1)">
<item>
<title :text="$loop.it.heading()"></title>
<description :text="$loop.it.html()"></description>
<link :text="$site.host_url.addPath($page.link().suffix('#', $loop.it.id))"></link>
<pubDate :text="$loop.it.id.parseDate().formatHTTP()"></pubDate>
<guid :text="$site.host_url.addPath($page.link().suffix('#', $loop.it.id))"></guid>
</item>
</ctx>
</ctx>
</channel>
</rss>

7
layouts/index.shtml Normal file
View File

@ -0,0 +1,7 @@
<extend template="base.shtml">
<head id="head">
</head>
<body id="body">
<h1 :text="$page.title"></h1>
<div :html="$page.content()"></div>
</body>

7
layouts/page.shtml Normal file
View File

@ -0,0 +1,7 @@
<extend template="base.shtml">
<head id="head">
</head>
<body id="body">
<h1 :text="$page.title"></h1>
<div :html="$page.content()"></div>
</body>

40
layouts/post.shtml Normal file
View File

@ -0,0 +1,40 @@
<extend template="base.shtml">
<head id="head">
<style>
#prev-next {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 40px;
}
figure {
align-self: center;
text-align: center;
font-style: italic;
}
.post {
display:flex;
flex-direction: column;
}
</style>
</head>
<body id="body">
<h1 :text="$page.title"></h1>
<div class="post" :html="$page.content()"></div>
<div id="prev-next">
<div :if="$page.prevPage?()">
<a href="$if.link()">
<span :text="$if.title"></span>
</a>
</div>
<div :if="$page.nextPage?()">
<a href="$if.link()">
<span :text="$if.title"></span>
</a>
</div>
</div>
</body>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head id="head">
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1">
<title :text="$site.title"></title>
<link type="text/css" rel="stylesheet" href="$site.asset('style.css').link()">
<link type="text/css" rel="stylesheet" href="$site.asset('highlight.css').link()">
<!-- mathtex -->
<link type="text/css" rel="stylesheet" href="$site.asset('Temml-Local.css').link()">
<script defer src="$site.asset('temml.min.js').link()"></script>
<script defer src="$site.asset('render-mathtex.js').link()"></script>
<!-- /mathtex -->
<super>
</head>
<body id="body">
<h1 class="site-title" :text="$site.title"></h1>
<nav>
<a href="$site.page('').link()">Home</a>
&nbsp; • &nbsp;
<a href="$site.page('about').link()">About</a>
&nbsp; • &nbsp;
<a href="$site.page('blog').link()">Blog</a>
<ctx :if="$site.page('devlog').subpages().first?()">
&nbsp; • &nbsp;
<a href="$if.link()">Devlog</a>
</ctx>
</nav>
<super>
<footer>
<hr>
<h5>SITE UNDER CONSTRUCTION</h5>
<img src="$site.asset('under-construction.gif').link()" width=90>
</footer>
</body>
</html>

10
zine.ziggy Normal file
View File

@ -0,0 +1,10 @@
Site {
.title = "Welcome to Zine!",
.host_url = "https://example.com",
.content_dir_path = "content",
.layouts_dir_path = "layouts",
.assets_dir_path = "assets",
.static_assets = [
"Temml.woff2",
],
}