Initial Commit
This commit is contained in:
parent
90a0df0201
commit
a4ae976473
208
README.md
208
README.md
|
@ -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&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&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
|
||||
```
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
```
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {})
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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%);
|
||||
}
|
|
@ -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%);
|
||||
}
|
|
@ -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'),
|
||||
],
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 %}
|
|
@ -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> · {{ article.readtime }} min read</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if article.author != '' %}
|
||||
<span> · {{ 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> · {{ article.readtime }} min read</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if article.author != '' %}
|
||||
<span> · {{ 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> · {{ article.readtime }} min read</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if article.author != '' %}
|
||||
<span> · {{ 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 %}
|
|
@ -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> · {{ article.readtime }} min read</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if article.author != '' %}
|
||||
<span> · {{ 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 %}
|
|
@ -0,0 +1,2 @@
|
|||
{% extends "index.html" %}
|
||||
{% block title %}{{ SITENAME }} - {{ author }}{% endblock %}
|
|
@ -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 %}
|
|
@ -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 }} • {% endif %}</span>Powered by
|
||||
<a class="underline" href="https://getpelican.com/">Pelican</a> &
|
||||
<a class="underline" href="https://github.com/aleylara/Papyrus"> 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>
|
|
@ -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 %}
|
|
@ -0,0 +1,7 @@
|
|||
{% extends "index.html" %}
|
||||
|
||||
{% block title %}{{ category }} | {{SITENAME}}{% endblock %}
|
||||
|
||||
{% block content_title %}
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,5 @@
|
|||
{% if DISQUS_SITENAME %}
|
||||
<p>
|
||||
There are <a href="{{ SITEURL }}/{{ article.url }}#disqus_thread">comments</a>.
|
||||
</p>
|
||||
{% endif %}
|
|
@ -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 %}
|
|
@ -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> · {{ article.readtime }} min read</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if article.author != '' %}
|
||||
<span> · {{ article.author }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% if articles_page.has_other_pages() %}
|
||||
{% include 'pagination.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock content %}
|
|
@ -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 %}
|
|
@ -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">
|
||||
« 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 »
|
||||
</button></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
|
@ -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 %}
|
|
@ -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
|
||||
<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 %}
|
|
@ -0,0 +1,7 @@
|
|||
{% extends "index.html" %}
|
||||
|
||||
{% block title %} {{ tag }} | {{ SITENAME }}{% endblock %}
|
||||
|
||||
{% block content_title %}
|
||||
|
||||
{% endblock %}
|
|
@ -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 %}
|
|
@ -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 %}
|
Loading…
Reference in New Issue