Initial Commit

This commit is contained in:
aleylara 2022-02-21 20:18:57 +11:00
parent 90a0df0201
commit a4ae976473
28 changed files with 6624 additions and 0 deletions

208
README.md
View File

@ -1 +1,209 @@
# Papyrus
>This project is based on [hugo-PaperMod](https://github.com/adityatelange/hugo-PaperMod) which is a fork of [hugo-paper](https://github.com/nanxiaobei/hugo-paper). The goal of the project is to make a replica theme that works under Pelican site generator.
A fast and responsive theme built for the [Pelican](https://blog.getpelican.com/) site generator. It is styled using [Tailwind CSS](https://tailwindcss.com/). It supports dark mode and built in search function.
### Demo
Live-Demo at [https://aleylara.github.io/Papyrus](https://aleylara.github.io/Papyrus)
### Installation
The theme requires the [pelican-search](https://github.com/pelican-plugins/search), [pelican-neighbors](https://github.com/pelican-plugins/neighbors), [pelican-readtime](https://github.com/JenkinsDev/pelican-readtime) and [pelican-toc](https://github.com/ingwinlu/pelican-toc) plugins. First three plugins can be installed using `pip`. Pelican-toc will be installed manually. We will also need [stork](https://stork-search.net/) and `beautifulsoup4` as dependencies.
```bash
$ pip install pelican-search
$ pip install pelican-neighbors
$ pip install pelican-readtime
```
Create two directories `themes` and `pelican-plugins` inside the root level of your project. Clone the Papyrus theme inside the `themes` directory that you created.
```bash
$ mkdir themes
$ cd themes
$ git clone https://github.com/aleylara/Papyrus.git
```
Now clone the pelican-toc plugin repo (not available via pip) into your pelican-plugins directory and install `beautifulsoup4` that is required by this plugin.
```bash
$ mkdir pelican-plugins
$ cd pelican-plugins
$ git clone https://github.com/ingwinlu/pelican-toc.git
$ pip install beautifulsoup4
```
Papyrus theme is already setup for your search functionality. However you will still need to have the `stork` package installed in your operating system. Verify [stork](https://stork-search.net/) is in your path by `stork -h` otherwise go ahead and install it.
```bash
# Install using Homebrew
$ brew install stork-search/stork-tap/stork
# Install using the Rust toolchain and install Stork with Cargo
$ cargo install stork-search --locked
```
### Settings
This is the `pelicanconf.py` settings file for the demo site, please change values to meet your needs.
```python
AUTHOR = 'Author'
SITENAME = 'Papyrus'
SITEURL = 'https://aleylara.github.io/Papyrus/'
TIMEZONE = 'Australia/Sydney'
DEFAULT_LANG = 'en'
SUBTITLE = 'Papyrus'
SUBTEXT = '''A fast and responsive theme built for the <a class="underline"
href="https://blog.getpelican.com/">Pelican</a> site generator.<br>
The theme is inspired from <a class="underline"
href="https://github.com/adityatelange/hugo-PaperMod">Hugo-PaperMod</a>.
It is styled using <a class="underline"
href="https://tailwindcss.com/">Tailwind CSS</a>.
It supports dark mode and built in search function.
'''
COPYRIGHT = '©2022'
PATH = 'content'
THEME = 'themes/Papyrus'
THEME_STATIC_PATHS = ['static']
PLUGIN_PATHS = ['pelican-plugins']
PLUGINS = ['readtime', 'search', 'neighbors', 'pelican-toc']
DISPLAY_PAGES_ON_MENU = True
DIRECT_TEMPLATES = (('index', 'search', 'tags', 'categories', 'archives',))
PAGINATED_TEMPLATES = {'index':None,'tag':None,'category':None,'author':None,'archives':24,}
# Site search plugin
SEARCH_MODE = "output"
SEARCH_HTML_SELECTOR = "main"
# Table of Content Plugin
TOC = {
'TOC_HEADERS' : '^h[1-3]', # What headers should be included in
# the generated toc
# Expected format is a regular expression
'TOC_RUN' : 'true', # Default value for toc generation,
# if it does not evaluate
# to 'true' no toc will be generated
'TOC_INCLUDE_TITLE': 'false', # If 'true' include title in toc
}
# Feed generation is usually not desired when developing
FEED_ALL_ATOM = 'feeds/all.atom.xml'
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None
AUTHOR_FEED_ATOM = None
AUTHOR_FEED_RSS = None
RSS_FEED_SUMMARY_ONLY = True
# Social widgets
SOCIAL = (
('github', 'https://github.com/aleylara/Papyrus'),
('twitter', 'https://twitter.com/'),
)
# Article share widgets
SHARE = (
("twitter", "https://twitter.com/intent/tweet/?text=Features&amp;url="),
("linkedin", "https://www.linkedin.com/sharing/share-offsite/?url="),
("reddit", "https://reddit.com/submit?url="),
("facebook", "https://facebook.com/sharer/sharer.php?u="),
("whatsapp", "https://api.whatsapp.com/send?text=Features - "),
("telegram", "https://telegram.me/share/url?text=Features&amp;url="),
)
DEFAULT_PAGINATION = 8
# Uncomment following line if you want document-relative URLs when developing
#RELATIVE_URLS = True
# DISQUS_SITENAME = ''
# GOOGLE_ANALYTICS = ''
```
### Generate Articles
A sample article header is below. Adding a `Summary` field is highly recommended. It substitutes as the article decription and gets added into html `<meta name="description" content="...">`. Summaries are also used in blog's home page. They help to keep similar height article previews without titles, images or code blocks.
```markdown
Title: Installation
Date: 2021-12-14
Tags: CSS, Markdown, Python, AI
Category: Software
Summary: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam dignissim convallis est. Quisque aliquam. Donec faucibus. Nunc iaculis suscipit dui. Nam sit amet sem. Aliquam libero nisi, imperdiet at, tincidunt nec, gravida vehicula, nisl.
```
Articles created inside directory named `pages` will have a separate static page and a direct link similar to the `About` page in the demo.
You can now run the development server and visit the `http://localhost:8000`
```bash
cd myBlog
$ pelican --autoreload --listen --ignore-cache
```
Final project directory structure should look similar to this.
```bash
$ (pelican) ➜ myProject tree
├── myBlog
│ ├── content
│ │ ├── images
│ │ │ └── camera.png
│ │ ├── pages
│ │ │ ├── about.md
│ │ │ └── events.md
│ │ ├── Hardware
│ │ │ ├── article-one.md
│ │ │ └── article-two.md
│ │ └── Software
│ │ ├── article-three.md
│ │ └── article-four.md
│ ├── Makefile
│ ├── output
│ │
│ ├── pelicanconf.py
│ ├── pelican-plugins
│ │ └── pelican-toc
│ │
│ ├── publishconf.py
│ ├── tasks.py
│ └── themes
│ └── Papyrus
└── venv
```
### Image size and placement
Images can be placed on page by adding a custom class names such as `image-left`, `image-right`, `image-center` in your markdown.
Similarly, placed images can be given a size using custom classes `image-thumbnail`, `image-small`, `image-medium` and`image-large`.
You can use `<img/>` tags along with the custom image classes straight in your Markdown.
```html
<img src="{static}/images/screenshot.png" alt="screenshot" class="image-left image-medium" />
<img src="{static}/images/screenshot.png" alt="screenshot" class="image-right image-thumbnail" />
Alternatively you could use inline styling.
<img src="{static}/images/screenshot.png" alt="screenshot" style="width:200px;" />
```
### Embeding YouTube Videos
In order to have a responsiveness video tumbnail, the `<iframe>` tags must be wrapped inside the `<div class="aspect-w-16 aspect-h-9"></div>` in your markdown file.
```html
<div class="aspect-w-16 aspect-h-9">
<iframe width="736" height="414" src="https://www.youtube.com/embed/TmWIrBPE6Bc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>
</iframe>
</div>
```
### Tailwind CSS
If you would like to make any local changes, tailwindcss configuration files are included with the theme. First go into the Papyrus directory and install missing packages with `npm install`.
Then run the development server that watches for your changed tailwind classes inside the templates folder and updates `main.css` on the go.
```bash
# Initial installation of packages
$ npm install
# JIT compiled main.css
$ npm run dev
```

8
node_modules/readme.md generated vendored Normal file
View File

@ -0,0 +1,8 @@
If you would liked to play around with Tailwind CSS settings or regenerate `main.css` after adding new classes to any of the template files then you will have to install the missing node modules and regenerate `main.css`.
```bash
$ cd themes/Papyrus
$ npm install
$ npm run dev
```

3659
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "peli-paper",
"version": "1.0.0",
"description": "",
"main": "tailwind.config.js",
"scripts": {
"dev": "TAILWIND_MODE=WATCH postcss tailwind.css -o ./static/css/main.css --watch --verbose",
"prod": "NODE_ENV=production postcss tailwind.css -o ./static/css/main.css"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@tailwindcss/typography": "^0.5.0",
"autoprefixer": "^10.4.2",
"cssnano": "^5.0.13",
"postcss": "^8.4.5",
"postcss-cli": "^9.1.0",
"tailwindcss": "^3.0.13"
},
"dependencies": {
"@tailwindcss/aspect-ratio": "^0.4.0"
}
}

8
postcss.config.js Normal file
View File

@ -0,0 +1,8 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {})
}
}

1583
static/css/main.css Normal file

File diff suppressed because it is too large Load Diff

38
static/css/stork-dark.css Normal file
View File

@ -0,0 +1,38 @@
@import url(https://files.stork-search.net/basic.css);
body:not(.stork-multitheme),
.stork-wrapper-dark {
--stork-border-color: hsl(0, 0%, 36%);
--stork-background-color: hsl(0, 0%, 22%);
--stork-accent-color: hsl(194, 90%, 53%);
--stork-input-text-color: white;
--stork-results-hover-color: hsl(210, 83%, 16%);
--stork-results-title-color: white;
--stork-results-excerpt-color: hsla(0, 0%, 80%, 1);
--stork-results-highlight-color: rgb(94, 201, 186);
--stork-results-border-color: hsl(0, 0%, 30%);
}
body:not(.stork-multitheme) .stork-close-button,
.stork-wrapper-dark .stork-close-button {
background: linear-gradient(
to bottom,
hsl(0, 0%, 60%) 0%,
hsl(0, 0%, 50%) 100%
);
border: 1px solid hsla(0, 0%, 50%, 0.8);
color: hsl(0, 0%, 25%);
}
body:not(.stork-multitheme) .stork-close-button:hover,
.stork-wrapper-dark .stork-close-button:hover {
background: hsla(0, 0%, 45%);
cursor: pointer;
}
body:not(.stork-multitheme) .stork-close-button:active,
.stork-wrapper-dark .stork-close-button:active {
background: hsla(0, 0%, 40%);
}

212
static/css/stork.css Normal file
View File

@ -0,0 +1,212 @@
:root {
--stork-border-color: hsl(0, 0%, 65%);
--stork-background-color: hsla(0, 0%, 97%, 1);
--stork-font-family: inherit;
--stork-size-multiplier: 1;
--stork-accent-color: hsl(210, 72%, 45%);
--stork-input-width: 100%;
--stork-input-border-radius: 8px;
--stork-input-text-color: black;
--stork-input-shadow: 1;
--stork-results-width: 100%;
--stork-results-border-radius: 4px;
--stork-results-shadow: 1;
--stork-results-hover-color: hsl(210, 65%, 75%);
--stork-results-title-color: black;
--stork-results-excerpt-color: black;
--stork-results-highlight-color: rgb(245, 230, 26);
--stork-results-border-color: var(--stork-border-color);
}
.stork-wrapper {
position: relative;
font-family: var(--stork-font-family);
box-sizing: border-box;
font-size: 1em * var(--stork-size-multiplier);
}
.stork-wrapper *,
.stork-wrapper *:before,
.stork-wrapper *:after {
box-sizing: border-box;
}
.stork-input {
width: var(--stork-input-width);
height: 2.4em;
font-size: 1em;
padding: 0.4em 0.8em;
position: relative;
box-shadow: inset 0 0.1em 0.3em
hsla(0, 0%, 0%, calc(var(--stork-input-shadow) * 0.25));
border: 1px solid var(--stork-border-color);
border-radius: var(--stork-input-border-radius);
background-color: var(--stork-background-color);
color: var(--stork-input-text-color);
font-family: var(--stork-font-family);
}
.stork-input:focus {
outline: none;
}
.stork-progress {
position: absolute;
display: block;
content: "";
bottom: 1px;
background-color: var(--stork-accent-color);
box-shadow: 0 0 8px var(--stork-accent-color);
height: 1px;
transition: width 0.25s ease, opacity 0.4s ease 0.4s;
}
.stork-output {
position: absolute;
width: var(--stork-results-width);
margin-top: 0.5em;
border-radius: var(--stork-results-border-radius);
display: flex;
flex-direction: column;
z-index: 100;
color: var(--stork-results-title-color);
font-weight: 400;
font-family: var(--stork-font-family);
}
.stork-attribution a:link,
.stork-attribution a:visited {
color: var(--stork-accent-color);
}
.stork-output-visible {
border: 1px solid var(--stork-border-color);
box-shadow: 0px 0px 2.2px
rgba(0, 0, 0, calc(var(--stork-results-shadow) * 0.02)),
0px 0px 5.3px rgba(0, 0, 0, calc(var(--stork-results-shadow) * 0.028)),
0px 0px 10px rgba(0, 0, 0, calc(var(--stork-results-shadow) * 0.035)),
0px 0px 17.9px rgba(0, 0, 0, calc(var(--stork-results-shadow) * 0.042)),
0px 0px 33.4px rgba(0, 0, 0, calc(var(--stork-results-shadow) * 0.05)),
0px 0px 80px rgba(0, 0, 0, calc(var(--stork-results-shadow) * 0.07));
background: var(--stork-background-color);
}
.stork-message {
width: 100%;
padding: 0.5em 1em;
color: var(--stork-results-title-color);
}
.stork-attribution {
width: 100%;
padding: 0.5em 1em;
font-size: 0.8em;
color: var(--stork-results-title-color);
}
.stork-results {
margin: 0;
padding: 0.25em 0;
width: 100%;
list-style-type: none;
max-height: 25em;
overflow-y: scroll;
border-top: 1px solid var(--stork-border-color);
border-bottom: 1px solid var(--stork-border-color);
box-shadow: inset 0em 0.7em 0.7em -0.7em hsla(0, 0%, 0%, calc(var(
--stork-results-shadow
) * 0.34)),
inset 0em -0.7em 0.7em -0.7em
hsl(0, 0%, 0%, calc(var(--stork-results-shadow) * 0.34));
}
.stork-result:not(:last-child) {
border-bottom: 1px solid var(--stork-results-border-color);
}
.stork-result.selected {
background: var(--stork-results-hover-color);
}
.stork-result a:link {
padding: 1em;
display: block;
color: currentcolor;
text-decoration: none;
}
.stork-result p {
margin: 0;
}
.stork-title {
font-weight: bold;
font-size: 0.95em;
margin: 0 0 0.75em 0;
color: var(--stork-results-title-color);
/* Flexbox container for the title and the score, when debugging */
display: flex;
justify-content: space-between;
}
.stork-excerpt {
font-size: 0.8em;
line-height: 1;
margin: 0;
color: var(--stork-results-excerpt-color);
/* Flexbox container for the title and the score, when debugging */
display: flex;
justify-content: space-between;
}
.stork-excerpt:not(:last-of-type) {
margin-bottom: 0.6em;
}
.stork-highlight {
background-color: var(--stork-results-highlight-color);
padding: 0 0.1em;
}
.stork-error {
outline: 2px solid hsl(0, 89%, 46%);
}
.stork-close-button {
position: absolute;
bottom: 0;
right: 0;
margin: 0.3em 0.4em;
height: 1.5em;
width: 1.5em;
padding: 0px;
background: linear-gradient(
to bottom,
hsl(0, 0%, 85%) 0%,
hsl(0, 0%, 75%) 100%
);
border: 1px solid hsla(0, 0%, 50%, 0.8);
font-size: 1.1em;
color: hsl(0, 0%, 45%);
border-radius: 15%;
line-height: 1;
}
.stork-close-button svg {
width: 0.8em;
position: relative;
top: 1px;
}
.stork-close-button:hover {
background: hsla(0, 0%, 70%);
cursor: pointer;
}
.stork-close-button:active {
background: hsla(0, 0%, 65%);
}

17
tailwind.config.js Normal file
View File

@ -0,0 +1,17 @@
module.exports = {
darkMode: 'class',
content: ["./templates/*.{html,js}"],
theme: {
extend: {
fontFamily: {
sans: ['-apple-system','BlinkMacSystemFont','"segoe ui"','Roboto','Oxygen','Ubuntu','Cantarell','"open sans"','"helvetica neue"','"sans-serif"'],
'display': ['Georama',]
},
},
},
plugins: [
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
],
}

41
tailwind.css Normal file
View File

@ -0,0 +1,41 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
/* Disable mobile browser tap background highlight */
-webkit-tap-highlight-color: transparent;
}
#toc ul li {
/* Table of contents styling */
list-style-type: disc;
}
.image-thumbnail {
@apply sm:w-1/6 shadow-md;
}
.image-small {
@apply sm:w-1/3 shadow-md;
}
.image-medium {
@apply sm:w-1/2 shadow-md;
}
.image-large {
@apply w-full h-full shadow-md;
}
.image-left {
@apply sm:float-left mr-5;
}
.image-right {
@apply sm:float-right sm:ml-5;
}
.image-center {
@apply mx-auto;
}

33
templates/analytics.html Normal file
View File

@ -0,0 +1,33 @@
{% if GOOGLE_ANALYTICS %}
<script type="text/javascript">
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
ga('create', '{{GOOGLE_ANALYTICS}}', '{{GA_COOKIE_DOMAIN if GA_COOKIE_DOMAIN else "auto"}}');
ga('send', 'pageview');
</script>
{% endif %}
{% if GAUGES %}
<script type="text/javascript">
var _gauges = _gauges || [];
(function () {
var t = document.createElement('script');
t.type = 'text/javascript';
t.async = true;
t.id = 'gauges-tracker';
t.setAttribute('data-site-id', '{{GAUGES}}');
t.src = '//secure.gaug.es/track.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(t, s);
})();
</script>
{% endif %}

120
templates/archives.html Normal file
View File

@ -0,0 +1,120 @@
{% extends "base.html" %}
{% block title %}Archive | {{ SITENAME }}{% endblock %}
{% set current = "archive" %}
{% macro countyear(year) %}
{% set name = namespace(y=0) %}
{% for article in dates %}
{% if article.date | strftime('%Y') == year %}
{% set name.y = name.y + 1 %}
{% endif %}
{% endfor %}
{{name.y}}
{% endmacro %}
{% macro countmonth(month, year) %}
{% set name = namespace(m=0) %}
{% for article in dates %}
{% if article.date | strftime('%B') == month and article.date | strftime('%Y') == year %}
{% set name.m = name.m + 1 %}
{% endif %}
{% endfor %}
{{name.m}}
{% endmacro %}
{% block content %}
<div class="md:mt-14 text-zinc-800 dark:text-zinc-300 pb-6">
<h1 class="font-bold text-4xl my-10">Archive</h1>
<ul class=" flex-col">
{% for year, year_group in dates_page.object_list|groupby('date.year')|reverse %}
{% for month, month_group in year_group|groupby('date.month')|reverse %}
{% for article in month_group %}
{% if article == month_group[0] and article == year_group[0] %}
<h3 class="text-2xl font-semibold my-8">{{(month_group|first).date|strftime('%Y')}}
<sup class="text-sm text-zinc-800 dark:text-zinc-400">
{{ countyear(article.date | strftime('%Y')) }}
</sup>
</h3>
<div class="md:flex my-1">
<time class="text-xl font-semibold flex mt-6 md:mt-2 md:w-40">{{ (month_group|first).date|strftime('%B') }}
<sup class="text-sm m-1 text-zinc-800 dark:text-zinc-400">
{{ countmonth(article.date | strftime('%B'), article.date | strftime('%Y')) }}
</sup>
</time>
<a href="{{ SITEURL }}/{{ article.url }}">
<li class="flex-1 md:mt-2"><span class="text-lg">{{ article.title}}</span><br>
<div class="flex text-xs text-zinc-800 dark:text-zinc-400">
<time>{{ article.date|strftime('%B %d, %Y') }}</time>
<div>
{% if article.readtime %}
<span>&nbsp;·&nbsp;{{ article.readtime }} min read</span>
{% endif %}
</div>
<div>
{% if article.author != '' %}
<span>&nbsp;·&nbsp;{{ article.author }}</span>
{% endif %}
</div>
</div>
</li>
</a>
</div>
{% elif article == month_group[0] %}
<div class="md:flex mt-3">
<time class="text-xl font-semibold flex mt-6 md:mt-2 md:w-40">{{ (month_group|first).date|strftime('%B') }}
<sup class="text-sm m-1 text-zinc-800 dark:text-zinc-400">
{{ countmonth(article.date | strftime('%B'), article.date | strftime('%Y')) }}
</sup>
</time>
<a href="{{ SITEURL }}/{{ article.url }}">
<li class="flex-1 md:mt-2"><span class="text-lg">{{ article.title}}</span><br>
<div class="flex text-xs text-zinc-800 dark:text-zinc-400">
<time>{{ article.date|strftime('%B %d, %Y') }}</time>
<div>
{% if article.readtime %}
<span>&nbsp;·&nbsp;{{ article.readtime }} min read</span>
{% endif %}
</div>
<div>
{% if article.author != '' %}
<span>&nbsp;·&nbsp;{{ article.author }}</span>
{% endif %}
</div>
</div>
</li>
</a>
</div>
{% else %}
<div class="md:flex">
<time class="flex md:w-40"></time>
<a href="{{ SITEURL }}/{{ article.url }}">
<li class="flex-1 md:mt-2 mt-1"><span class="text-lg">{{ article.title}}</span><br>
<div class="flex text-xs text-zinc-800 dark:text-zinc-400">
<time>{{ article.date|strftime('%B %d, %Y') }}</time>
<div>
{% if article.readtime %}
<span>&nbsp;·&nbsp;{{ article.readtime }} min read</span>
{% endif %}
</div>
<div>
{% if article.author != '' %}
<span>&nbsp;·&nbsp;{{ article.author }}</span>
{% endif %}
</div>
</div>
</li>
</a>
</div>
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
</ul>
</div>
{% if dates_page.has_other_pages() %}
{% include 'pagination.html' %}
{% endif %}
{% endblock %}

123
templates/article.html Normal file
View File

@ -0,0 +1,123 @@
{% extends "base.html" %}
{% block html_lang %}{{ article.lang }}{% endblock %}
{% block head -%}
{{ super() -}}
{% if article.summary %}
<meta name="description" content="{{ article.summary | striptags | safe | truncate(150) }}" />
{% endif %}
{% endblock %}
{% block title %}{{ article.title|striptags }}{% endblock %}
{% block extra_head %}
{% import 'translations.html' as translations with context %}
{% if translations.entry_hreflang(article) %}
{{ translations.entry_hreflang(article) }}
{% endif %}
{% endblock %}
{% block content %}
<main>
<header>
<h1 class="font-semibold text-3xl my-2">{{article.title}}</h1>
<footer class="flex text-sm text-zinc-800 dark:text-zinc-400">
<div class="flex text-xs text-zinc-800 dark:text-zinc-400">
<time>{{ article.date|strftime('%B %d, %Y') }}</time>
<div>
{% if article.readtime %}
<span>&nbsp;·&nbsp;{{ article.readtime }} min read</span>
{% endif %}
</div>
<div>
{% if article.author != '' %}
<span>&nbsp;·&nbsp;{{ article.author }}</span>
{% endif %}
</div>
</div>
</footer>
{% if article.modified %}
<div class="flex text-xs text-zinc-800 dark:text-zinc-400">
<span>Last updated: {{ article.modified|strftime('%B %d, %Y') }}</span>
</div>
{% endif %}
</header>
{% if article.toc %}
<details class="flex flex-col my-6 p-4 bg-zinc-200 dark:bg-zinc-800 rounded-lg">
<summary class="text-lg font-bold">Table of contents</summary>
<div class="mx-4 px-4 underline">
{{ article.toc }}
</div>
</details>
{% endif %}
<div class="max-w-7xl container mx-auto my-8 text-zinc-800 dark:text-zinc-300
prose lg:max-w-none prose-headings:text-zinc-800 prose-headings:dark:text-zinc-300
prose-h1:text-3xl lg:prose-h1:text-3xl prose-headings:font-semibold
prose-pre:bg-zinc-200 prose-pre:text-zinc-800
dark:prose-pre:bg-zinc-800 dark:prose-pre:text-zinc-200
prose-blockquote:text-zinc-800
dark:prose-blockquote:text-zinc-200
prose-a:text-gray-500
dark:prose-a:text-gray-400
dark:prose-strong:text-zinc-200
dark:prose-code:text-zinc-200
dark:prose-code:bg-zinc-800
prose-code:bg-zinc-200
prose-code:font-light
prose-img:rounded-md
">
{{ article.content }}
<!-- <div class="aspect-w-16 aspect-h-9 mx-auto"></div> CSS placeholder -->
</div>
<footer class="flex flex-col mt-10 ">
<ul class="flex flex-wrap">
{% for tag in article.tags|sort %}
<a href="{{ SITEURL }}/{{ tag.url }}">
<li
class="bg-zinc-200 hover:bg-zinc-300 dark:hover:bg-zinc-800 dark:bg-zinc-700 text-zinc-500 dark:text-neutral-400 mb-2 mr-2 px-3 py-1.5 rounded-md transition ease-in active:-translate-y-1 active:scale-110 duration-75">
{{ tag }}
</li>
</a>
{% endfor %}
</ul>
<div class="flex w-full my-2 bg-zinc-200 dark:bg-zinc-700 rounded-lg">
{% if article.next_article %}
<div class="w-1/2 hover:bg-zinc-300 dark:hover:bg-zinc-800 rounded-l-lg">
<a class="flex flex-col pr-2" href="{{ SITEURL }}/{{ article.next_article.url }}">
<div class="mx-4 py-2 text-left">
<p class="text-zinc-500 dark:text-neutral-400 text-sm">« PREV PAGE</p>
<p class="text-left py-1 hover:underline">{{ article.next_article.title }}</p>
</div>
</a>
</div>
{% else %}
<div class="w-1/2 rounded-l-lg"></div>
{% endif %}
{% if article.prev_article %}
<div class="w-1/2 hover:bg-zinc-300 dark:hover:bg-zinc-800 rounded-r-lg ">
<a class="flex flex-col" href="{{ SITEURL }}/{{ article.prev_article.url }}">
<div class="text-right mx-4 py-2">
<p class="text-zinc-500 dark:text-neutral-400 text-sm">NEXT PAGE »</p>
<p class="text-right py-1 hover:underline">{{ article.prev_article.title }}</p>
</div>
</a>
</div>
{% endif %}
</div>
<div class="flex bg-zinc-200 dark:bg-zinc-700 py-2 rounded-lg justify-center space-x-2 text-xs">
{% for name, link in SHARE %}
<ul>
<a target="_blank" rel="noopener noreferrer" title="{{ name }}" aria-label="share Features on {{ name }}"
href="{{ link }}{{ SITEURL }}/{{ article.url }}">
<li class="bg-gray-900 p-1 text-white rounded-md">
<i class="fab fa-{{ name }} fa-2x" aria-hidden="true"></i>
</li>
</a>
</ul>
{% endfor %}
</div>
</footer>
<div>
{% include 'disqus_script.html' %}
</div>
</main>
{% endblock %}

2
templates/author.html Normal file
View File

@ -0,0 +1,2 @@
{% extends "index.html" %}
{% block title %}{{ SITENAME }} - {{ author }}{% endblock %}

12
templates/authors.html Normal file
View File

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block title %}{{ SITENAME }} - Authors{% endblock %}
{% block content %}
<h1>Authors on {{ SITENAME }}</h1>
<ul>
{% for author, articles in authors|sort %}
<li><a href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a> ({{ articles|count }})</li>
{% endfor %}
</ul>
{% endblock %}

252
templates/base.html Normal file
View File

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="{% block html_lang %}{{ DEFAULT_LANG }}{% endblock html_lang %}">
<head>
{% block head %}
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="generator" content="Pelican" />
<title>{% block title %} {{ SITENAME }} {% endblock %}</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Slab|Ruda" />
<link rel="stylesheet" type="text/css" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/css/main.css" />
<link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/css/stork.css">
<link rel="stylesheet" media="screen and (prefers-color-scheme: dark)"
href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/css/stork-dark.css">
{% if FEED_ALL_ATOM %}
<link
href="{{ FEED_DOMAIN }}/{% if FEED_ALL_ATOM_URL %}{{ FEED_ALL_ATOM_URL }}{% else %}{{ FEED_ALL_ATOM }}{% endif %}"
type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Atom Feed" />
{% endif %}
{% if FEED_ALL_RSS %}
<link
href="{{ FEED_DOMAIN }}/{% if FEED_ALL_RSS_URL %}{{ FEED_ALL_RSS_URL }}{% else %}{{ FEED_ALL_RSS }}{% endif %}"
type="application/rss+xml" rel="alternate" title="{{ SITENAME }} RSS Feed" />
{% endif %}
{% block extra_head %}{% endblock extra_head %}
{% endblock head %}
<script>
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia(
'(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark')
}
</script>
</head>
<body class="min-h-screen flex flex-col max-w-7xl lg:max-w-none text-zinc-800 bg-neutral-100
dark:bg-neutral-900 dark:text-zinc-300 container mx-auto justify-center md:px-3 ">
<nav class="sm:flex sm:justify-between xl:ml-32 pl-4 items-center">
<div class="flex pt-4">
<h1 class="font-semibold text-2xl"><a href="{{ SITEURL }}/">{{ SITENAME }}</a></h1>
<button id="theme-toggle" type="button"
class="text-zinc-700 dark:text-zinc-400 rounded-full focus:outline-none text-sm ml-2 p-1">
<svg id="theme-toggle-dark-icon" class="w-5 h-5 hidden" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
</svg>
<svg id="theme-toggle-light-icon" class="w-5 h-5 hidden" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
fill-rule="evenodd" clip-rule="evenodd"></path>
</svg>
</button>
</div>
<ul class="flex flex-wrap lg:mr-24 md:pt-0">
{% if DISPLAY_PAGES_ON_MENU %}
{% for p in pages %}
<li class="mr-4 pt-6"><a {% if p==page %} class="border-b-2 border-zinc-800 dark:border-zinc-300"
{% endif %} href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
{% endif %}
<li class="mr-4 pt-6"><a {% if current=="archive" %} class="border-b-2 border-zinc-800 dark:border-zinc-300"
{% endif %} href="{{ SITEURL }}/archives.html">Archive</a></li>
<li class="mr-4 pt-6"><a {% if current=="categories" %}
class="border-b-2 border-zinc-800 dark:border-zinc-300" {% endif %}
href="{{ SITEURL }}/categories.html">Categories</a></li>
<li class="mr-4 pt-6"><a {% if current=="tags" %} class="border-b-2 border-zinc-800 dark:border-zinc-300"
{% endif %} href="{{ SITEURL }}/tags.html">Tags</a></li>
<li class="mr-4 pt-6"><a {% if current=="search" %} class="border-b-2 border-zinc-800 dark:border-zinc-300"
{% endif %} href="{{ SITEURL }}/search.html">Search</a></li>
</ul>
</nav>
<div class="flex-grow md:max-w-screen-md md:mx-auto md:w-3/4 px-4">
{% if article %}
<nav class="text-zinc-800 dark:text-zinc-300 mt-12 pb-2 md:mt-16" aria-label="Breadcrumb">
<ul class="p-0 inline-flex items-center">
<li class="flex items-center">
<a href="{{ SITEURL }}/" class="text-zinc-800 dark:text-zinc-300 inline-flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z">
</path>
</svg>
Home
</a>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</li>
<li class="flex items-center">
<a href="{{ SITEURL }}/categories.html">Categories</a>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</li>
<li class="flex items-center">
<a href="{{ SITEURL }}/{{category.url}}">{{ category }}</a>
</li>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</ul>
</nav>
{% elif tag %}
<nav class="text-zinc-800 dark:text-zinc-300 mt-12 pb-3 md:mt-16" aria-label="Breadcrumb">
<ul class="p-0 inline-flex">
<li class="flex items-center">
<a href="{{ SITEURL }}/" class="text-zinc-800 dark:text-zinc-300 inline-flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z">
</path>
</svg>
Home
</a>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</li>
<li class="flex items-center">
<a href="{{ SITEURL }}/tags.html">Tags</a>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</li>
<li class="border-b-2 border-zinc-800 dark:border-zinc-300">
{{ tag }}
</li>
</ul>
</nav>
{% elif page %}
<nav class="text-zinc-800 dark:text-zinc-300 mt-12 pb-3 md:mt-16" aria-label="Breadcrumb">
<ul class="p-0 inline-flex">
<li class="flex items-center">
<a href="{{ SITEURL }}/" class="text-zinc-800 dark:text-zinc-300 inline-flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z">
</path>
</svg>
Home
</a>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</li>
<li class="border-b-2 border-zinc-800 dark:border-zinc-300">
{{page.title}}
</li>
</ul>
</nav>
{% elif category %}
<nav class="text-zinc-800 dark:text-zinc-300 mt-12 pb-3 md:mt-16" aria-label="Breadcrumb">
<ul class="p-0 inline-flex">
<li class="flex items-center">
<a href="{{ SITEURL }}/" class="text-zinc-800 dark:text-zinc-300 inline-flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z">
</path>
</svg>
Home
</a>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</li>
<li class="flex items-center">
<a href="{{ SITEURL }}/categories.html">Categories</a>
<svg class="fill-current w-3 h-3 mr-2 ml-1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512">
<path
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" />
</svg>
</li>
<li class="border-b-2 border-zinc-800 dark:border-zinc-300">
{{ category }}
</li>
</ul>
</nav>
{% endif %}
{% block content %} {% endblock %}
</div>
<footer class="flex w-full text-xs justify-center mt-10 mb-6 text-zinc-500 dark:text-zinc-400">
<div class="px-4">
<span>{% if COPYRIGHT %}{{ COPYRIGHT }}&nbsp;&#8226;&nbsp;{% endif %}</span>Powered by
<a class="underline" href="https://getpelican.com/">Pelican</a>&nbsp;&
<a class="underline" href="https://github.com/aleylara/Papyrus">&nbsp;Papyrus</a>
</div>
</footer>
{% include 'analytics.html' %}
{% include 'disqus_script.html' %}
<script>
let themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
let themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia(
'(prefers-color-scheme: dark)').matches)) {
themeToggleLightIcon.classList.remove('hidden');
} else {
themeToggleDarkIcon.classList.remove('hidden');
}
let themeToggleBtn = document.getElementById('theme-toggle');
themeToggleBtn.addEventListener('click', function () {
themeToggleDarkIcon.classList.toggle('hidden');
themeToggleLightIcon.classList.toggle('hidden');
if (localStorage.getItem('color-theme')) {
if (localStorage.getItem('color-theme') === 'light') {
document.documentElement.classList.add('dark');
localStorage.setItem('color-theme', 'dark');
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem('color-theme', 'light');
}
} else {
if (document.documentElement.classList.contains('dark')) {
document.documentElement.classList.remove('dark');
localStorage.setItem('color-theme', 'light');
} else {
document.documentElement.classList.add('dark');
localStorage.setItem('color-theme', 'dark');
}
}
});
</script>
<script src="https://files.stork-search.net/releases/v1.4.0/stork.js"></script>
<script>
stork.register("sitesearch", "{{ SITEURL }}/search-index.st")
</script>
</body>
</html>

21
templates/categories.html Normal file
View File

@ -0,0 +1,21 @@
{% extends "base.html" %}
{% block title %}{{ SITENAME }} | Categories{% endblock %}
{% set current = "categories" %}
{% block content %}
<div class="mb-12 md:mt-14 text-zinc-800 dark:text-zinc-300">
<h1 class="font-bold text-4xl my-10">Categories</h1>
<ul class="flex flex-wrap font-medium">
{% for category, articles in categories|sort %}
<a href="{{ SITEURL }}/{{ category.url }}">
<li
class="bg-zinc-300 dark:bg-neutral-700 text-zinc-800 dark:text-zinc-300 hover:bg-zinc-400 dark:hover:bg-zinc-800 m-2 py-2 px-2 md:px-4 rounded-md transition ease-in active:-translate-y-1 active:scale-110 duration-75">
{{ category }}<sup class="p-1">{{ articles|count }}</sup></li>
</a>
{% endfor %}
</ul>
</div>
{% endblock %}

7
templates/category.html Normal file
View File

@ -0,0 +1,7 @@
{% extends "index.html" %}
{% block title %}{{ category }} | {{SITENAME}}{% endblock %}
{% block content_title %}
{% endblock %}

5
templates/comments.html Normal file
View File

@ -0,0 +1,5 @@
{% if DISQUS_SITENAME %}
<p>
There are <a href="{{ SITEURL }}/{{ article.url }}#disqus_thread">comments</a>.
</p>
{% endif %}

View File

@ -0,0 +1,12 @@
{% if DISQUS_SITENAME %}
<script type="text/javascript">
var disqus_shortname = '{{ DISQUS_SITENAME }}';
(function () {
var s = document.createElement('script');
s.async = true;
s.type = 'text/javascript';
s.src = 'https://' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>
{% endif %}

89
templates/index.html Normal file
View File

@ -0,0 +1,89 @@
{% extends "base.html" %}
{% block content %}
{% block content_title %}
{% if not category and not tag %}
<div class="my-12 md:my-24 text-zinc-800 dark:text-zinc-300">
{% if SUBTITLE %}
<h1 class="mb-6 text-3xl font-bold">{{ SUBTITLE }}</h1>
{%endif%}
{%if SUBTEXT %}
<p class="mb-8 text-zinc-500 dark:text-zinc-400"> {{ SUBTEXT }}</p>
{% endif %}
{% if SOCIAL or FEED_ALL_ATOM or FEED_ALL_RSS %}
<ul class="flex px-2 space-x-4 text-lg">
{% for name, link in SOCIAL %}
<li><a href="{{ link }}"><i class="fab fa-{{ name }} fa-lg" aria-hidden="true" target="_blank"
rel="noopener noreferrer" title="{{ name }}"></i></a></li>
{% endfor %}
{% if FEED_ALL_ATOM %}
<li><a href="{{ FEED_DOMAIN }}/
{% if FEED_ALL_ATOM_URL %}{{ FEED_ALL_ATOM_URL }}{% else %}{{ FEED_ALL_ATOM }}{% endif %}"
type="application/atom+xml" title="{{ FEED_ALL_ATOM }}" rel="alternate"><i class="fa fa-rss fa-lg"
aria-hidden="true"></i></a>
</li>
{% endif %}
{% if FEED_ALL_RSS %}
<li><a href="{{ FEED_DOMAIN }}/
{% if FEED_ALL_RSS_URL %}{{ FEED_ALL_RSS_URL }}{% else %}{{ FEED_ALL_RSS }}{% endif %}"
type="application/rss+xml" title="{{ FEED_ALL_RSS }}" rel="alternate"><i class="fa fa-rss fa-lg"
aria-hidden="true"></i></a>
</li>
{% endif %}
</ul>
{% endif %}
</div>
{% endif %}
{% endblock %}
<div class="py-1">
<ul>
{% for article in articles_page.object_list %}
<a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark" title="Permalink to {{ article.title|striptags }}">
<li class="transition ease-in active:-translate-y-1 active:scale-110 duration-75">
<div class="bg-white dark:bg-zinc-800 p-4 md:p-6 mb-4 rounded-lg">
<header class="font-semibold text-2xl mb-2">
<h1>{{ article.title }}</h1>
</header>
<div class="max-w-7xl container mx-auto my-4 justify-center overflow-hidden mb-2 text-sm text-zinc-800 dark:text-zinc-400
prose lg:max-w-none prose-headings:text-zinc-800 prose-headings:dark:text-zinc-300
prose-h1:text-3xl prose-headings:font-semibold
prose-pre:bg-zinc-200 prose-pre:text-zinc-800
dark:prose-pre:bg-zinc-800 dark:prose-pre:text-zinc-200
prose-blockquote:text-zinc-800
dark:prose-blockquote:text-zinc-200
prose-a:text-gray-500
dark:prose-a:text-gray-400
dark:prose-strong:text-zinc-200
dark:prose-code:text-zinc-200
dark:prose-code:bg-zinc-800
prose-code:bg-zinc-200
prose-code:font-light
prose-img:rounded-md
">
{{ article.summary }}
</div>
<div class="flex text-xs text-zinc-800 dark:text-zinc-400">
<time>{{ article.date|strftime('%B %d, %Y') }}</time>
<div>
{% if article.readtime %}
<span>&nbsp;·&nbsp;{{ article.readtime }} min read</span>
{% endif %}
</div>
<div>
{% if article.author != '' %}
<span>&nbsp;·&nbsp;{{ article.author }}</span>
{% endif %}
</div>
</div>
</li>
</a>
{% endfor %}
</ul>
</div>
{% if articles_page.has_other_pages() %}
{% include 'pagination.html' %}
{% endif %}
{% endblock content %}

47
templates/page.html Normal file
View File

@ -0,0 +1,47 @@
{% extends "base.html" %}
{% block html_lang %}{{ page.lang }}{% endblock %}
{% block title %}{{ SITENAME }} | {{ page.title }}{%endblock%}
{% block content %}
<main class="text-zinc-800 dark:text-zinc-300">
<div class="max-w-7xl container mx-auto my-2 text-zinc-800 dark:text-zinc-300
prose lg:max-w-none prose-headings:text-zinc-800 prose-headings:dark:text-zinc-300
prose-h1:text-3xl lg:prose-h1:text-3xl prose-headings:font-semibold
prose-pre:bg-zinc-200 prose-pre:text-zinc-800
dark:prose-pre:bg-zinc-800 dark:prose-pre:text-zinc-200
prose-blockquote:text-zinc-800
dark:prose-blockquote:text-zinc-200
prose-a:text-gray-500
dark:prose-a:text-gray-400
dark:prose-strong:text-zinc-200
dark:prose-code:text-zinc-200
dark:prose-code:bg-zinc-800
prose-code:bg-zinc-200
prose-code:font-light
prose-img:rounded-md
">
{% import 'translations.html' as translations with context %}
{{ translations.translations_for(page) }}
{{ page.content }}
<!-- <div class="aspect-w-16 aspect-h-9 mx-auto"></div> CSS placeholder -->
</div>
<footer class="flex bg-zinc-200 dark:bg-zinc-700 mt-10 py-2 rounded-lg justify-center space-x-2 text-xs">
{% for name, link in SHARE %}
<ul>
<a target="_blank" rel="noopener noreferrer" title="{{ name }}" aria-label="share Features on {{ name }}"
href="{{ link }}{{ SITEURL }}/{{ page.url }}">
<li class="bg-gray-900 p-1 text-white rounded-md">
<i class="fab fa-{{ name }} fa-2x" aria-hidden="true"></i>
</li>
</a>
</ul>
{% endfor %}
</footer>
<div>
{% include 'disqus_script.html' %}
</div>
</main>
{% endblock %}

20
templates/pagination.html Executable file
View File

@ -0,0 +1,20 @@
{% if DEFAULT_PAGINATION %}
{% set first_page = articles_paginator.page(1) %}
{% set last_page = articles_paginator.page(articles_paginator.num_pages) %}
<div class="relative h-12 mt-3">
{% if articles_page.has_previous() %}
<a href="{{ SITEURL }}/{{ articles_previous_page.url }}">
<button
class="bg-zinc-800 dark:bg-zinc-300 rounded-full py-2.5 px-4 text-zinc-100 dark:text-zinc-800 font-medium text-xs absolute left-0">
&laquo; Prev Page
</button></a>
{% endif %}
{% if articles_page.has_next() %}
<a href="{{ SITEURL }}/{{ articles_next_page.url }}">
<button
class="bg-zinc-800 dark:bg-zinc-300 rounded-full py-2.5 px-4 text-zinc-100 dark:text-zinc-800 font-medium text-xs absolute right-0">
Next Page &raquo;
</button></a>
{% endif %}
</div>
{% endif %}

View File

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% block title %}{{ SITENAME }} | {{ period | reverse | join(' ') }} archives{% endblock %}
{% block content %}
<h1>Archives for {{ period | reverse | join(' ') }}</h1>
<dl>
{% for article in dates %}
<dt>{{ article.locale_date }}</dt>
<dd><a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></dd>
{% endfor %}
</dl>
{% endblock %}

24
templates/search.html Normal file
View File

@ -0,0 +1,24 @@
{% extends "base.html" %}
{% block title %}Search | {{ SITENAME }}{% endblock %}
{% set current = "search" %}
{% block content %}
<div class="relative mb-12 md:mt-14 text-zinc-800 dark:text-zinc-300">
<h1 class="flex font-bold my-10 text-4xl mb-12 md:my-12 text-zinc-800 dark:text-zinc-300">Search&nbsp;
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none"
stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</h1>
<div class="stork-wrapper">
<input
class="font-semibold h-10 w-full border-2 border-zinc-500 bg-zinc-100 dark:bg-zinc-800 placeholder-zinc-400 dark:placeholder-zinc-300 focus:border-zinc-500 focus:outline-none rounded-lg pl-4"
data-stork="sitesearch" autofocus="" placeholder=" Search ↵" aria-label="search" type="search">
<div data-stork="sitesearch-output" class=""></div>
</div>
</div>
{% endblock %}

7
templates/tag.html Normal file
View File

@ -0,0 +1,7 @@
{% extends "index.html" %}
{% block title %} {{ tag }} | {{ SITENAME }}{% endblock %}
{% block content_title %}
{% endblock %}

22
templates/tags.html Normal file
View File

@ -0,0 +1,22 @@
{% extends "base.html" %}
{% block title %}{{ SITENAME }} | Tags{% endblock %}
{% set current = "tags" %}
{% block content %}
<div class="mb-12 md:mt-14 text-gray-800 dark:text-gray-300">
<h1 class="font-bold text-4xl my-10">Tags</h1>
<ul class="flex flex-wrap font-medium">
{% for tag, articles in tags|sort %}
<a href="{{ SITEURL }}/{{ tag.url }}">
<li
class="bg-zinc-300 dark:bg-neutral-700 text-zinc-800 dark:text-zinc-300 hover:bg-zinc-400 dark:hover:bg-zinc-800 m-2 py-2 px-2 md:px-4 rounded-md transition ease-in active:-translate-y-1 active:scale-110 duration-75">
{{ tag }}<sup class="p-1">{{ articles|count }}</sup>
</li>
</a>
{% endfor %}
</ul>
</div>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% macro translations_for(article) %}
{% if article.translations %}
Translations:
{% for translation in article.translations %}
<a href="{{ SITEURL }}/{{ translation.url }}" hreflang="{{ translation.lang }}">{{ translation.lang }}</a>
{% endfor %}
{% endif %}
{% endmacro %}
{% macro entry_hreflang(entry) %}
{% if entry.translations %}
{% for translation in entry.translations %}
<link rel="alternate" hreflang="{{ translation.lang }}" href="{{ SITEURL }}/{{ translation.url }}">
{% endfor %}
{% endif %}
{% endmacro %}