Merge pull request 'Add zola' (#5) from feat/zola into main

Reviewed-on: #5
This commit is contained in:
Kasper Juul Hermansen 2023-04-03 00:49:41 +00:00
commit 4828b83c23
41 changed files with 5903 additions and 218 deletions

View File

@ -1,28 +0,0 @@
kind: pipeline
name: default
type: docker
steps:
- name: submodules
image: alpine/git
commands:
- git submodule update --init --recursive
- name: blog
image: plugins/docker
settings:
username: kasperhermansen
password:
from_secret:
docker_secret
repo: kasperhermansen/kasperhermansen-blog
tags: latest
- name: send telegram notification
image: appleboy/drone-telegram
settings:
token:
from_secret: telegram_token
to: 2129601481
format: markdown
depends_on:
- blog
when:
status: [failure, success]

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
public/
node_modules/
.env
target/

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "themes/anubis"]
path = themes/anubis
url = https://github.com/mitrichius/hugo-theme-anubis.git

View File

8
.idea/.gitignore vendored
View File

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/blog-2.iml" filepath="$PROJECT_DIR$/.idea/blog-2.iml" />
</modules>
</component>
</project>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/themes/anubis" vcs="Git" />
</component>
</project>

View File

@ -1,10 +0,0 @@
{
auto_https off
debug
http_port: 80
}
blog.kasperhermansen.com {
root * /usr/share/caddy
file_server
}

View File

@ -1,4 +0,0 @@
FROM klakegg/hugo:0.93.2-onbuild AS hugo
FROM nginx
COPY --from=hugo /target /usr/share/nginx/html

View File

@ -1,6 +0,0 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

2164
ci/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

15
ci/Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "ci"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.24"
color-eyre = "0.6.2"
dagger-sdk = "0.2.19"
eyre = "0.6.8"
tokio = { version = "1.27.0", features = ["full"] }
tokio-scoped = "0.2.0"
dotenv = "0.15.0"

148
ci/src/main.rs Normal file
View File

@ -0,0 +1,148 @@
use std::sync::Arc;
use dagger_sdk::{HostDirectoryOptsBuilder, QueryContainerOptsBuilder};
use tokio::sync::Mutex;
#[tokio::main]
async fn main() -> eyre::Result<()> {
dotenv::dotenv().unwrap();
let client = dagger_sdk::connect().await?;
let src = client.host().directory_opts(
".",
HostDirectoryOptsBuilder::default()
.exclude(vec![".git", "node_modules", "public", "ci", "target"])
.build()?,
);
let node_cache = client.cache_volume("node_cache");
let debian_cache = client.cache_volume("debian_cache");
let styles_file = client
.container()
.from("node:16")
.with_workdir("/app")
.with_directory(".", src.id().await?)
.with_mounted_cache("node_modules", node_cache.id().await?)
.with_exec(vec!["yarn"])
.with_exec(vec!["yarn", "compile"])
.file("static/styles/styles.css");
let zola_version = "0.17.2-1";
let debian_edition = "bullseye";
let debian_platform = "amd64";
let tag = chrono::Utc::now().timestamp();
let github_zola_download = format!("https://github.com/barnumbirr/zola-debian/releases/download/v{zola_version}/zola_{zola_version}_{debian_platform}_{debian_edition}.deb");
let pull_articles = client
.container()
.from("docker.io/kasperhermansen/pull-articles:1680482220")
.with_exec(vec!["echo", &format!("{}", tag)])
.with_env_variable("GIT_USERNAME", "kjuulh")
.with_env_variable("GIT_PASSWORD", std::env::var("GIT_PASSWORD").unwrap())
.with_exec(vec![
"pull-articles",
"--repo",
"https://git.front.kjuulh.io/kjuulh/obsidian.git",
"--path",
"areas/blog/posts",
"--out",
"/mnt/posts",
])
.directory("/mnt/posts");
let dist_dir = client
.container_opts(
dagger_sdk::QueryContainerOptsBuilder::default()
.platform(format!("linux/{debian_platform}"))
.build()?,
)
.from(format!("debian:{debian_edition}"))
.with_exec(vec!["apt", "update"])
.with_exec(vec!["apt", "install", "wget", "-y"])
.with_workdir("/mnt")
.with_mounted_cache("/mnt", debian_cache.id().await?)
.with_exec(vec!["wget", &github_zola_download])
.with_exec(vec![
"dpkg",
"-i",
format!("zola_{zola_version}_{debian_platform}_{debian_edition}.deb").as_str(),
])
.with_workdir("/app")
.with_directory(".", src.id().await?)
.with_directory("content/posts", pull_articles.id().await?)
.with_file(
"content/posts/_index.md",
src.file("content/posts/_index.md").id().await?,
)
.with_file("static/styles/styles.css", styles_file.id().await?)
.with_exec(vec!["zola", "build"])
.directory("public");
let caddy_file = client.host().directory("deployment").file("Caddyfile");
let variants = vec!["linux/amd64", "linux/arm64"];
let platform_variants = Arc::new(Mutex::new(Vec::new()));
tokio_scoped::scope(|s| {
for platform in variants {
let caddy_file = caddy_file.clone();
let client = client.clone();
let dist_dir = dist_dir.clone();
let platform_variants = platform_variants.clone();
s.spawn(async move {
let dep_image = client
.container_opts(
QueryContainerOptsBuilder::default()
.platform(platform)
.build()
.unwrap(),
)
.from("caddy")
.with_directory("/usr/share/caddy", dist_dir.id().await.unwrap())
.with_file("/etc/caddy/Caddyfile", caddy_file.id().await.unwrap());
let mut platform_variants = platform_variants.lock().await;
platform_variants.push(dep_image.id().await.unwrap())
});
}
});
let variants = platform_variants
.lock()
.await
.iter()
.map(|c| c.clone())
.collect::<Vec<_>>();
let version = client
.container()
.publish_opts(
format!("kasperhermansen/kasperhermansen-blog:{tag}"),
dagger_sdk::ContainerPublishOptsBuilder::default()
.platform_variants(variants)
.build()?,
)
.await?;
let update_deployment = client
.container()
.from("kasperhermansen/update-deployment:1680472594")
.with_env_variable("GIT_USERNAME", "kjuulh")
.with_env_variable("GIT_PASSWORD", std::env::var("GIT_PASSWORD").unwrap())
.with_exec(vec![
"update-deployment",
"--repo",
"https://git.front.kjuulh.io/kjuulh/blog-deployment.git",
"--service",
"blog",
"--image",
&format!("kasperhermansen/kasperhermansen-blog:{tag}"),
])
.exit_code()
.await?;
Ok(())
}

View File

@ -1,19 +0,0 @@
http {
include mime.types;
sendfile on;
server {
listen 80;
listen [::]:80;
autoindex off;
server_name _;
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
}
}
events {}

10
config.toml Normal file
View File

@ -0,0 +1,10 @@
# The URL the site will be built for
base_url = "https://blog.kasperhermansen.com"
[markdown]
# Whether to do syntax highlighting
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
highlight_code = true
[extra]
# Put all your custom variables here

View File

@ -1,76 +0,0 @@
languageCode: "en-us"
baseUrl: "https://blog.kasperhermansen.com"
title: "Kjuulh"
theme: "anubis"
paginate: 10
disqusShortname: "kjuulh"
googleAnalytics: "G-12345"
enableRobotsTXT: true
menu:
main:
- identifier: archive
name: Archive
title: Archive
url: /posts/
weight: 0
taxonomies:
category: "categories"
tag: "tags"
params:
author: "Kasper J. Hermansen"
email: contact@kasperhermansen.com # used for microformats
#avatar: "/images/me.png" # used for microformats
description: "A blog about what I am working on and think about at the moment and in the past"
# Uncomment if you need this
# images:
# - images/og-featured.png # relative path to "static" directory
# customCSS:
# - css/my.css # relative path to "assets" directory (don't use main.css filename)
# customJS:
# - js/main.js # relative path to "assets" directory
dateFormat: "2006-01-02"
paginationSinglePost: true
style: dark
readMore: false # show read more button
readNextPosts: 5 # show 5 related posts, 0 by default
disableSummary: false
copyCodeButton: true # true by default
rssAsSocialIcon: true
# utteranc.es support
utterancesRepo: "" # mandatory
utterancesTheme: "" # optional
utterancesIssue: "" # optional
utterancesLabel: "" # optional
# isso support
isso:
enabled: true # mandatory
data: "https://comments.example.com/" # mandatory
jsLocation: "https://comments.example.com/js/embed.min.js" # mandatory
css: true # optional
lang: "dk" # optional
replyToSelf: true # mandatory
requireAuthor: true # mandatory
requireEmail: true # mandatory
id: "thread-id" # optional
avatar: true # optional
avatar-bg: "#f0f0f0" # optional
graphcommentId: ""
webmentions:
url: https://yourdomain.com/webemntions/receive
login: hugo-theme-anubis
pingback: true
social:
- id: github
name: kjuulh
# - id: hugo
# url: "https://gohugo.io/"
# icon: "hugo"
markup:
goldmark:
renderer:
unsafe: true # enable raw HTML in Markdown

4
content/_index.md Normal file
View File

@ -0,0 +1,4 @@
+++
[extra]
section_path = "posts/_index.md"
+++

View File

@ -1,7 +0,0 @@
+++
aliases = ["posts","articles","blog","showcase","docs"]
title = "Posts"
author = "kjuulh"
tags = ["index"]
+++

View File

@ -1,4 +0,0 @@
+++
hidden = true
+++

View File

@ -1,12 +0,0 @@
+++
author = "kjuulh"
title = "Start of blog"
date = "2022-05-22"
description = "Start of the blog"
aliases = ["start"]
favorite = false
+++
Some start of blog

6
content/posts/_index.md Normal file
View File

@ -0,0 +1,6 @@
+++
title = "Kasper Hermansen"
path = "posts"
sort_by = "date"
paginate_by = 5
+++

39
content/posts/first.md Normal file
View File

@ -0,0 +1,39 @@
+++
title = "My first post"
date = 2019-11-27
draft = true
+++
This is my first blog post.
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim
labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi
anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est
aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia
pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa
proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia
eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim.
Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa
duis. <!-- more -->
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim
labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi
anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est
aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia
pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa
proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia
eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim.
Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa
duis.
```rust
fn main() -> eyre::Result<()> {
Ok(())
}
```
![image](https://images.unsplash.com/photo-1680188591202-22a2f6d7d6af?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1270&q=80)

39
content/posts/second.md Normal file
View File

@ -0,0 +1,39 @@
+++
title = "My second post"
date = 2020-11-27
draft = true
+++
This is my first blog post.
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim
labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi
anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est
aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia
pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa
proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia
eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim.
Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa
duis.
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim
labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi
anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est
aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia
pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa
proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia
eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim.
Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa
duis.
```rust
fn main() -> eyre::Result<()> {
Ok(())
}
```
![image](https://images.unsplash.com/photo-1680188591202-22a2f6d7d6af?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1270&q=80)

39
content/posts/third.md Normal file
View File

@ -0,0 +1,39 @@
+++
title = "My second post"
date = 2020-12-27
draft = true
+++
This is my first blog post.
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim
labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi
anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est
aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia
pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa
proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia
eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim.
Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa
duis.
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim
labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi
anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est
aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia
pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa
proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia
eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim.
Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa
duis.
```rust
fn main() -> eyre::Result<()> {
Ok(())
}
```
![image](https://images.unsplash.com/photo-1680188591202-22a2f6d7d6af?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1270&q=80)

8
deployment/Caddyfile Normal file
View File

@ -0,0 +1,8 @@
{
debug
}
http://blog.kasperhermansen.com {
root * /usr/share/caddy
file_server
}

View File

@ -1,7 +0,0 @@
services:
kasperhermansen_blog:
build:
context: .
restart: always
ports:
- 15000:80

View File

@ -1,6 +0,0 @@
services:
kasperhermansen_blog:
image: kasperhermansen/kasperhermansen-blog:latest
restart: always
ports:
- 15000:80

23
package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "kasperhermansen-blog",
"version": "1.0.0",
"main": "index.js",
"repository": "https://git.front.kjuulh.io/kjuulh/kasperhermansen-blog",
"author": "kjuulh <contact@kjuulh.io>",
"license": "MIT",
"scripts": {
"compile": "tailwindcss -i ./styles/styles.css -o ./static/styles/styles.css",
"compile:watch": "tailwindcss -i ./styles/styles.css -o ./static/styles/styles.css --watch=always",
"serve:watch": "zola serve --drafts",
"dev": "yarn compile:watch & yarn serve:watch",
"build": "cd ci && cargo build && cd .. && ./ci/target/debug/ci"
},
"dependencies": {
"@tailwindcss/typography": "^0.5.9",
"tailwindcss": "^3.3.1"
},
"devDependencies": {
"@catppuccin/tailwindcss": "^0.1.1",
"@tailwindcss/cli": "^0.1.2"
}
}

View File

@ -1,3 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
}

2084
static/styles/styles.css Normal file

File diff suppressed because it is too large Load Diff

45
styles/styles.css Normal file
View File

@ -0,0 +1,45 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
html,
body,
body > div:first-child {
@apply h-full bg-base text-text;
}
}
.blog-content {
@apply prose
lg:prose-lg
max-w-3xl
prose-headings:text-peach
prose-p:text-gray-100
prose-a:text-orange-200
prose-li:text-gray-100
prose-ul:text-gray-100
prose-code:text-peach
prose-strong:text-white;
}
.blog-summary {
@apply prose
lg:prose-lg
prose-headings:text-peach
prose-p:text-gray-400
prose-a:text-orange-300
prose-strong:text-gray-300
prose-li:text-gray-400
prose-ul:text-gray-400
prose-code:text-peach
pl-6
ml-6
border-l-2
border-peach
;
}
.blog-summary > p:first-child {
@apply mt-0;
}

14
tailwind.config.js Normal file
View File

@ -0,0 +1,14 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./templates/**/*.html"],
theme: {},
variants: {},
plugins: [
require('@tailwindcss/typography'),
require("@catppuccin/tailwindcss")({
prefix: false,
defaultFlavour: "frappe"
}),
]
}

24
templates/base.html Normal file
View File

@ -0,0 +1,24 @@
{% import "macros/macros.html" as post_macros %}
{% import "macros/prev.html" as prev_macros %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>kasperhermansen</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="{{ get_url(path="styles/styles.css") | safe }}" />
<script defer data-domain="blog.kasperhermansen.com" src="https://plausible.front.kjuulh.io/js/script.js"></script>
</head>
<body>
<section class="section container mx-auto">
{% block content %} {% endblock %}
</section>
</body>
</html>

1
templates/index.html Normal file
View File

@ -0,0 +1 @@
{% extends "section.html" %}

View File

@ -0,0 +1,36 @@
{% macro list_posts(pages) %}
<ul>
{%- for page in pages %}
<section class="list-item">
<h1 class="title text-peach">
<a href={{ page.permalink }}>{{page.title}}</a>
</h1>
<div class="meta">
{%- if page.date %}
<time>{{ page.date | date(format="%Y-%m-%d") }}</time>
{% endif -%}
{% if page.draft %}
<span class="draft-label">DRAFT</span>
{% endif %}
</div>
<br />
<div class="blog-summary ">
{% if page.description %}
<p>{{ page.description }}</p>
{% elif page.summary %}
{{ page.summary | safe }}&hellip;
{% else %}
{% set hide_read_more = true %}
{% endif %}
</div>
{% if not hide_read_more %}
<a class="readmore text-peach" href={{ page.permalink }}>Read more ⟶</a>
{% endif %}
</section>
{% endfor -%}
</ul>
{% endmacro list_posts %}

View File

@ -0,0 +1,10 @@
{% macro page_back_link(page) %}
{% set top_section = get_section(path=page.ancestors | last) %}
<a class="previous" href="{{ top_section.permalink }}"> back</a>
{% endmacro page_back_link %}
{% macro section_back_link(section) %}
{% set top_section = get_section(path=section.ancestors | last) %}
<a class="previous" href="{{ top_section.permalink }}"> back</a>
{% endmacro section_back_link %}

32
templates/page.html Normal file
View File

@ -0,0 +1,32 @@
{% extends "base.html" %}
{% block content %}
<div class="mx-auto px-4 max-w-3xl py-8">
<div class="py-2">
{{ prev_macros::page_back_link(page=page) }}
</div>
<article class="blog-content">
<h1 class="title">
{{ page.title }}
</h1>
<p class="subtitle"><strong>{{ page.date }}</strong></p>
{{ page.content | safe }}
</article>
{% if page.lower or page.higher %}
<div class="flex place-content-around max-w-lg mx-auto">
{% if page.lower %}
<a class="previous" href="{{ page.lower.permalink }}"> {{ page.lower.title }}</a>
{% endif %}
{% if page.higher %}
<a class="next" href="{{ page.higher.permalink }}">{{ page.higher.title }} </a>
{% endif %}
</div>
{% endif %}
</div>
{% endblock content %}

44
templates/section.html Normal file
View File

@ -0,0 +1,44 @@
{% extends "base.html" %}
{% block content %}
<div class="container mx-auto px-4 max-w-3xl py-8 space-y-4">
{% if section.ancestors | length > 0 %}
{{ prev_macros::section_back_link(section=section) }}
{% endif %}
{% if section.extra.section_path -%}
{% set section = get_section(path=section.extra.section_path) %}
{% endif -%}
<h1 class="title text-peach text-3xl">
{{ section.title }}
</h1>
<main>
{%- if paginator %}
{%- set show_pages = paginator.pages -%}
{% else %}
{%- set show_pages = section.pages -%}
{% endif -%}
{{ post_macros::list_posts(pages=show_pages) }}
</main>
{% if paginator %}
<ul class="pagination">
{% if paginator.previous %}
<span class="page-item page-prev">
<a href={{ paginator.previous }} class="page-link" aria-label="Previous"><span aria-hidden="true">← Prev</span></a>
</span>
{% endif %}
{% if paginator.next %}
<span class="page-item page-next">
<a href={{ paginator.next }} class="page-link" aria-label="Next"><span aria-hidden="true">Next →</span></a>
</span>
{% endif %}
</ul>
{% endif %}
</div>
{% endblock content %}

@ -1 +0,0 @@
Subproject commit cdef276335a7537d065251727487b7e744aff98d

1114
yarn.lock Normal file

File diff suppressed because it is too large Load Diff