]> Vexing Labs - vexingworkshop.git/commitdiff
first commit, getting set up
authorsignal9 <adam@vexingworkshop.com>
Sat, 4 Jan 2025 20:57:23 +0000 (13:57 -0700)
committersignal9 <adam@vexingworkshop.com>
Sat, 4 Jan 2025 20:57:23 +0000 (13:57 -0700)
19 files changed:
Makefile [new file with mode: 0644]
README.md
pelicanconf.py [new file with mode: 0644]
publishconf.py [new file with mode: 0644]
tasks.py [new file with mode: 0644]
themes/vexingworkshop/templates/archives.html [new file with mode: 0644]
themes/vexingworkshop/templates/article.html [new file with mode: 0644]
themes/vexingworkshop/templates/author.html [new file with mode: 0644]
themes/vexingworkshop/templates/authors.html [new file with mode: 0644]
themes/vexingworkshop/templates/base.html [new file with mode: 0644]
themes/vexingworkshop/templates/categories.html [new file with mode: 0644]
themes/vexingworkshop/templates/category.html [new file with mode: 0644]
themes/vexingworkshop/templates/index.html [new file with mode: 0644]
themes/vexingworkshop/templates/page.html [new file with mode: 0644]
themes/vexingworkshop/templates/pagination.html [new file with mode: 0644]
themes/vexingworkshop/templates/period_archives.html [new file with mode: 0644]
themes/vexingworkshop/templates/tag.html [new file with mode: 0644]
themes/vexingworkshop/templates/tags.html [new file with mode: 0644]
themes/vexingworkshop/templates/translations.html [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6ca0b6f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,89 @@
+PY?=
+PELICAN?=pelican
+PELICANOPTS=
+
+BASEDIR=$(CURDIR)
+INPUTDIR=$(BASEDIR)/content
+OUTPUTDIR=$(BASEDIR)/output
+CONFFILE=$(BASEDIR)/pelicanconf.py
+PUBLISHCONF=$(BASEDIR)/publishconf.py
+
+SSH_HOST=localhost
+SSH_PORT=22
+SSH_USER=signal9
+SSH_TARGET_DIR=/var/www
+
+
+DEBUG ?= 0
+ifeq ($(DEBUG), 1)
+       PELICANOPTS += -D
+endif
+
+RELATIVE ?= 0
+ifeq ($(RELATIVE), 1)
+       PELICANOPTS += --relative-urls
+endif
+
+SERVER ?= "0.0.0.0"
+
+PORT ?= 0
+ifneq ($(PORT), 0)
+       PELICANOPTS += -p $(PORT)
+endif
+
+
+help:
+       @echo 'Makefile for a pelican Web site                                           '
+       @echo '                                                                          '
+       @echo 'Usage:                                                                    '
+       @echo '   make html                           (re)generate the web site          '
+       @echo '   make clean                          remove the generated files         '
+       @echo '   make regenerate                     regenerate files upon modification '
+       @echo '   make publish                        generate using production settings '
+       @echo '   make serve [PORT=8000]              serve site at http://localhost:8000'
+       @echo '   make serve-global [SERVER=0.0.0.0]  serve (as root) to $(SERVER):80    '
+       @echo '   make devserver [PORT=8000]          serve and regenerate together      '
+       @echo '   make devserver-global               regenerate and serve on 0.0.0.0    '
+       @echo '   make ssh_upload                     upload the web site via SSH        '
+       @echo '   make sftp_upload                    upload the web site via SFTP       '
+       @echo '   make rsync_upload                   upload the web site via rsync+ssh  '
+       @echo '                                                                          '
+       @echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html   '
+       @echo 'Set the RELATIVE variable to 1 to enable relative urls                    '
+       @echo '                                                                          '
+
+html:
+       "$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
+
+clean:
+       [ ! -d "$(OUTPUTDIR)" ] || rm -rf "$(OUTPUTDIR)"
+
+regenerate:
+       "$(PELICAN)" -r "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
+
+serve:
+       "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
+
+serve-global:
+       "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b $(SERVER)
+
+devserver:
+       "$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
+
+devserver-global:
+       "$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b 0.0.0.0
+
+publish:
+       "$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(PUBLISHCONF)" $(PELICANOPTS)
+
+ssh_upload: publish
+       scp -P $(SSH_PORT) -r "$(OUTPUTDIR)"/* "$(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)"
+
+sftp_upload: publish
+       printf 'put -r $(OUTPUTDIR)/*' | sftp $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)
+
+rsync_upload: publish
+       rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --include tags --cvs-exclude --delete "$(OUTPUTDIR)"/ "$(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)"
+
+
+.PHONY: html help clean regenerate serve serve-global devserver devserver-global publish ssh_upload sftp_upload rsync_upload
index ac971348c6ad6ff7faae7a2fc41351355766b188..482076f6b1e2e03fc5e2e2b95aa1d308125acc4f 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,3 +1,13 @@
 # Vexing Workshop
 
-The personal blog of signal9, of Vexing Workshop.
+The online presense of Vexing Workshop
+
+## Goals
+
+* blog
+* gallery
+* shop
+* events calendar
+* link tree
+
+## Tasks
diff --git a/pelicanconf.py b/pelicanconf.py
new file mode 100644 (file)
index 0000000..6a3928d
--- /dev/null
@@ -0,0 +1,35 @@
+AUTHOR = 'Adam'
+SITENAME = 'VexingWorkshop'
+SITEURL = ""
+
+PATH = "content"
+
+TIMEZONE = 'America/Denver'
+
+DEFAULT_LANG = 'en'
+
+# Feed generation is usually not desired when developing
+FEED_ALL_ATOM = None
+CATEGORY_FEED_ATOM = None
+TRANSLATION_FEED_ATOM = None
+AUTHOR_FEED_ATOM = None
+AUTHOR_FEED_RSS = None
+
+# Blogroll
+LINKS = (
+    ("Pelican", "https://getpelican.com/"),
+    ("Python.org", "https://www.python.org/"),
+    ("Jinja2", "https://palletsprojects.com/p/jinja/"),
+    ("You can modify those links in your config file", "#"),
+)
+
+# Social widget
+SOCIAL = (
+    ("You can add links in your config file", "#"),
+    ("Another social link", "#"),
+)
+
+DEFAULT_PAGINATION = 10
+
+# Uncomment following line if you want document-relative URLs when developing
+# RELATIVE_URLS = True
diff --git a/publishconf.py b/publishconf.py
new file mode 100644 (file)
index 0000000..6f1308b
--- /dev/null
@@ -0,0 +1,22 @@
+# This file is only used if you use `make publish` or
+# explicitly specify it as your config file.
+
+import os
+import sys
+
+sys.path.append(os.curdir)
+from pelicanconf import *
+
+# If your site is available via HTTPS, make sure SITEURL begins with https://
+SITEURL = ""
+RELATIVE_URLS = False
+
+FEED_ALL_ATOM = "feeds/all.atom.xml"
+CATEGORY_FEED_ATOM = "feeds/{slug}.atom.xml"
+
+DELETE_OUTPUT_DIRECTORY = True
+
+# Following items are often useful when publishing
+
+# DISQUS_SITENAME = ""
+# GOOGLE_ANALYTICS = ""
diff --git a/tasks.py b/tasks.py
new file mode 100644 (file)
index 0000000..80944f2
--- /dev/null
+++ b/tasks.py
@@ -0,0 +1,150 @@
+import os
+import shlex
+import shutil
+import sys
+
+from invoke import task
+from invoke.main import program
+from pelican import main as pelican_main
+from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer
+from pelican.settings import DEFAULT_CONFIG, get_settings_from_file
+
+OPEN_BROWSER_ON_SERVE = True
+SETTINGS_FILE_BASE = "pelicanconf.py"
+SETTINGS = {}
+SETTINGS.update(DEFAULT_CONFIG)
+LOCAL_SETTINGS = get_settings_from_file(SETTINGS_FILE_BASE)
+SETTINGS.update(LOCAL_SETTINGS)
+
+CONFIG = {
+    "settings_base": SETTINGS_FILE_BASE,
+    "settings_publish": "publishconf.py",
+    # Output path. Can be absolute or relative to tasks.py. Default: 'output'
+    "deploy_path": SETTINGS["OUTPUT_PATH"],
+    # Remote server configuration
+    "ssh_user": "signal9",
+    "ssh_host": "localhost",
+    "ssh_port": "22",
+    "ssh_path": "/var/www",
+    # Host and port for `serve`
+    "host": "localhost",
+    "port": 8000,
+}
+
+
+@task
+def clean(c):
+    """Remove generated files"""
+    if os.path.isdir(CONFIG["deploy_path"]):
+        shutil.rmtree(CONFIG["deploy_path"])
+        os.makedirs(CONFIG["deploy_path"])
+
+
+@task
+def build(c):
+    """Build local version of site"""
+    pelican_run("-s {settings_base}".format(**CONFIG))
+
+
+@task
+def rebuild(c):
+    """`build` with the delete switch"""
+    pelican_run("-d -s {settings_base}".format(**CONFIG))
+
+
+@task
+def regenerate(c):
+    """Automatically regenerate site upon file modification"""
+    pelican_run("-r -s {settings_base}".format(**CONFIG))
+
+
+@task
+def serve(c):
+    """Serve site at http://$HOST:$PORT/ (default is localhost:8000)"""
+
+    class AddressReuseTCPServer(RootedHTTPServer):
+        allow_reuse_address = True
+
+    server = AddressReuseTCPServer(
+        CONFIG["deploy_path"],
+        (CONFIG["host"], CONFIG["port"]),
+        ComplexHTTPRequestHandler,
+    )
+
+    if OPEN_BROWSER_ON_SERVE:
+        # Open site in default browser
+        import webbrowser
+
+        webbrowser.open("http://{host}:{port}".format(**CONFIG))
+
+    sys.stderr.write("Serving at {host}:{port} ...\n".format(**CONFIG))
+    server.serve_forever()
+
+
+@task
+def reserve(c):
+    """`build`, then `serve`"""
+    build(c)
+    serve(c)
+
+
+@task
+def preview(c):
+    """Build production version of site"""
+    pelican_run("-s {settings_publish}".format(**CONFIG))
+
+@task
+def livereload(c):
+    """Automatically reload browser tab upon file modification."""
+    from livereload import Server
+
+    def cached_build():
+        cmd = "-s {settings_base} -e CACHE_CONTENT=true LOAD_CONTENT_CACHE=true"
+        pelican_run(cmd.format(**CONFIG))
+
+    cached_build()
+    server = Server()
+    theme_path = SETTINGS["THEME"]
+    watched_globs = [
+        CONFIG["settings_base"],
+        f"{theme_path}/templates/**/*.html",
+    ]
+
+    content_file_extensions = [".md", ".rst"]
+    for extension in content_file_extensions:
+        content_glob = "{}/**/*{}".format(SETTINGS["PATH"], extension)
+        watched_globs.append(content_glob)
+
+    static_file_extensions = [".css", ".js"]
+    for extension in static_file_extensions:
+        static_file_glob = f"{theme_path}/static/**/*{extension}"
+        watched_globs.append(static_file_glob)
+
+    for glob in watched_globs:
+        server.watch(glob, cached_build)
+
+    if OPEN_BROWSER_ON_SERVE:
+        # Open site in default browser
+        import webbrowser
+
+        webbrowser.open("http://{host}:{port}".format(**CONFIG))
+
+    server.serve(host=CONFIG["host"], port=CONFIG["port"], root=CONFIG["deploy_path"])
+
+
+@task
+def publish(c):
+    """Publish to production via rsync"""
+    pelican_run("-s {settings_publish}".format(**CONFIG))
+    c.run(
+        'rsync --delete --exclude ".DS_Store" -pthrvz -c '
+        '-e "ssh -p {ssh_port}" '
+        "{} {ssh_user}@{ssh_host}:{ssh_path}".format(
+            CONFIG["deploy_path"].rstrip("/") + "/", **CONFIG
+        )
+    )
+
+
+def pelican_run(cmd):
+    cmd += " " + program.core.remainder  # allows to pass-through args to pelican
+    pelican_main(shlex.split(cmd))
diff --git a/themes/vexingworkshop/templates/archives.html b/themes/vexingworkshop/templates/archives.html
new file mode 100644 (file)
index 0000000..a61bf3c
--- /dev/null
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - Archives{% endblock %}
+
+{% block content %}
+    <h2>Archives for {{ SITENAME }}</h2>
+
+    <dl>
+        {% for article in dates %}
+            <dt>{{ article.locale_date }}</dt>
+            <dd><a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></dd>
+        {% endfor %}
+    </dl>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/article.html b/themes/vexingworkshop/templates/article.html
new file mode 100644 (file)
index 0000000..a01de10
--- /dev/null
@@ -0,0 +1,65 @@
+{% extends "base.html" %}
+{% block html_lang %}{{ article.lang }}{% endblock %}
+
+{% block title %}{{ SITENAME|striptags }} - {{ article.title|striptags  }}{% endblock %}
+
+{% block head %}
+  {{ super() }}
+
+  {% import 'translations.html' as translations with context %}
+  {% if translations.entry_hreflang(article) %}
+    {{ translations.entry_hreflang(article) }}
+  {% endif %}
+
+  {% if article.description %}
+    <meta name="description" content="{{article.description}}" />
+  {% endif %}
+
+  {% for tag in article.tags %}
+    <meta name="tags" content="{{tag}}" />
+  {% endfor %}
+
+{% endblock %}
+
+{% block content %}
+  <article>
+    <header>
+      <h2>
+        <a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark"
+           title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a></h2>
+      {% import 'translations.html' as translations with context %}
+      {{ translations.translations_for(article) }}
+    </header>
+    {{ article.content }}
+    <footer>
+      <p>Published: <time datetime="{{ article.date.isoformat() }}">
+        {{ article.locale_date }}
+      </time></p>
+      {% if article.modified %}
+        <p>Last updated: <time datetime="{{ article.modified.isoformat() }}">
+          {{ article.locale_modified }}
+        </time></p>
+      {% endif %}
+      {% if article.authors %}
+        <address>
+          By {% for author in article.authors %}
+            <a href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a>
+          {% endfor %}
+        </address>
+      {% endif %}
+      {% if article.category %}
+        <p>
+          Category: <a href="{{ SITEURL }}/{{ article.category.url }}">{{ article.category }}</a>
+        </p>
+      {% endif %}
+      {% if article.tags %}
+        <p>
+          Tags:
+          {% for tag in article.tags %}
+            <a href="{{ SITEURL }}/{{ tag.url }}">{{ tag }}</a>
+          {% endfor %}
+        </p>
+      {% endif %}
+    </footer>
+  </article>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/author.html b/themes/vexingworkshop/templates/author.html
new file mode 100644 (file)
index 0000000..06f871d
--- /dev/null
@@ -0,0 +1,7 @@
+{% extends "index.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - Articles by {{ author }}{% endblock %}
+
+{% block content_title %}
+    <h2>Articles by {{ author }}</h2>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/authors.html b/themes/vexingworkshop/templates/authors.html
new file mode 100644 (file)
index 0000000..97a7457
--- /dev/null
@@ -0,0 +1,12 @@
+{% extends "base.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - Authors{% endblock %}
+
+{% block content %}
+    <h2>Authors on {{ SITENAME }}</h2>
+    <ul>
+        {% for author, articles in authors|sort %}
+            <li><a href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a> ({{ articles|count }})</li>
+        {% endfor %}
+    </ul>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/base.html b/themes/vexingworkshop/templates/base.html
new file mode 100644 (file)
index 0000000..e9461fd
--- /dev/null
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html lang="{% block html_lang %}{{ DEFAULT_LANG }}{% endblock html_lang %}">
+  <head>
+    {% block head %}
+      <title>{% block title %}{{ SITENAME|striptags }}{% endblock title %}</title>
+      <meta charset="utf-8" />
+      <meta name="generator" content="Pelican" />
+      <meta name="viewport" content="width=device-width, initial-scale=1.0">
+      {% if SITESUBTITLE %}
+        <meta name="description" content="{{ SITESUBTITLE }}" />
+      {% endif %}
+      {% if STYLESHEET_URL %}
+        <link rel="stylesheet" type="text/css" href="{{ STYLESHEET_URL }}" />
+      {% endif %}
+      {% 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|striptags }} Full 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|striptags }} Full RSS Feed" />
+      {% endif %}
+      {% if FEED_ATOM %}
+        <link href="{{ FEED_DOMAIN }}/{%if FEED_ATOM_URL %}{{ FEED_ATOM_URL }}{% else %}{{ FEED_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME|striptags }} Atom Feed" />
+      {% endif %}
+      {% if FEED_RSS %}
+        <link href="{{ FEED_DOMAIN }}/{% if FEED_RSS_URL %}{{ FEED_RSS_URL }}{% else %}{{ FEED_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME|striptags }} RSS Feed" />
+      {% endif %}
+      {% if CATEGORY_FEED_ATOM and category %}
+        <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_ATOM_URL %}{{ CATEGORY_FEED_ATOM_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_ATOM.format(slug=category.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME|striptags }} Categories Atom Feed" />
+      {% endif %}
+      {% if CATEGORY_FEED_RSS and category %}
+        <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_RSS_URL %}{{ CATEGORY_FEED_RSS_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_RSS.format(slug=category.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME|striptags }} Categories RSS Feed" />
+      {% endif %}
+      {% if TAG_FEED_ATOM and tag %}
+        <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_ATOM_URL %}{{ TAG_FEED_ATOM_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_ATOM.format(slug=tag.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME|striptags }} Tags Atom Feed" />
+      {% endif %}
+      {% if TAG_FEED_RSS and tag %}
+        <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_RSS_URL %}{{ TAG_FEED_RSS_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_RSS.format(slug=tag.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME|striptags }} Tags RSS Feed" />
+      {% endif %}
+    {% endblock head %}
+  </head>
+
+  <body>
+    <header>
+      <hgroup><h1><a href="{{ SITEURL }}/">{{ SITENAME }}</a></h1>{% if SITESUBTITLE %}<p>{{ SITESUBTITLE }}</p>{% endif %}</hgroup>
+      <nav><ul>
+        {% for title, link in MENUITEMS %}
+          <li><a href="{{ link }}">{{ title }}</a></li>
+        {% endfor %}
+        {% if DISPLAY_PAGES_ON_MENU %}
+          {% for p in pages %}
+            <li><a href="{{ SITEURL }}/{{ p.url }}" {% if p==page %} aria-current="page" {% endif %}>{{ p.title }}</a></li>
+          {% endfor %}
+        {% endif %}
+        {% if DISPLAY_CATEGORIES_ON_MENU %}
+          {% for cat, null in categories %}
+            <li><a href="{{ SITEURL }}/{{ cat.url }}" {% if cat==category %} aria-current="page" {% endif %}>{{ cat}}</a></li>
+          {% endfor %}
+        {% endif %}
+      </ul></nav>
+    </header>
+    <main>
+      {% block content %}
+      {% endblock %}
+    </main>
+    <footer>
+      <address>
+        Proudly powered by <a rel="nofollow" href="https://getpelican.com/">Pelican</a>,
+        which takes great advantage of <a rel="nofollow" href="https://www.python.org/">Python</a>.
+      </address>
+    </footer>
+  </body>
+</html>
diff --git a/themes/vexingworkshop/templates/categories.html b/themes/vexingworkshop/templates/categories.html
new file mode 100644 (file)
index 0000000..c723f8a
--- /dev/null
@@ -0,0 +1,12 @@
+{% extends "base.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - Categories{% endblock %}
+
+{% block content %}
+    <h2>Categories on {{ SITENAME }}</h2>
+    <ul>
+        {% for category, articles in categories|sort %}
+            <li><a href="{{ SITEURL }}/{{ category.url }}">{{ category }}</a> ({{ articles|count }})</li>
+        {% endfor %}
+    </ul>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/category.html b/themes/vexingworkshop/templates/category.html
new file mode 100644 (file)
index 0000000..bfad391
--- /dev/null
@@ -0,0 +1,7 @@
+{% extends "index.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - {{ category }} category{% endblock %}
+
+{% block content_title %}
+    <h2>Articles in the {{ category }} category</h2>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/index.html b/themes/vexingworkshop/templates/index.html
new file mode 100644 (file)
index 0000000..97caac6
--- /dev/null
@@ -0,0 +1,27 @@
+{% extends "base.html" %}
+{% block content %}
+    {% block content_title %}
+        <h2>All articles</h2>
+    {% endblock %}
+
+
+    {% for article in articles_page.object_list %}
+        <article>
+            <header> <h2><a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark" title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a></h2> </header>
+            <section>{{ article.summary }}</section>
+            <footer>
+                <p>Published: <time datetime="{{ article.date.isoformat() }}"> {{ article.locale_date }} </time></p>
+                <address>By
+                    {% for author in article.authors %}
+                        <a href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a>
+                    {% endfor %}
+                </address>
+            </footer>
+        </article>
+    {% endfor %}
+
+    {% if articles_page.has_other_pages() %}
+        {% include 'pagination.html' %}
+    {% endif %}
+
+{% endblock content %}
diff --git a/themes/vexingworkshop/templates/page.html b/themes/vexingworkshop/templates/page.html
new file mode 100644 (file)
index 0000000..0eefc7e
--- /dev/null
@@ -0,0 +1,33 @@
+{% extends "base.html" %}
+{% block html_lang %}{{ page.lang }}{% endblock %}
+
+{% block title %}{{ SITENAME|striptags }} - {{ page.title|striptags }}{%endblock%}
+
+{% block head %}
+  {{ super() }}
+
+  {% import 'translations.html' as translations with context %}
+  {% if translations.entry_hreflang(page) %}
+    {{ translations.entry_hreflang(page) }}
+  {% endif %}
+{% endblock %}
+
+{% block content %}
+  <article>
+    <header>
+      <h2>{{ page.title }}</h2>
+    </header>
+    {% import 'translations.html' as translations with context %}
+    {{ translations.translations_for(page) }}
+
+    {{ page.content }}
+
+    {% if page.modified %}
+      <footer>
+        <p>
+          Last updated: {{ page.locale_modified }}
+        </p>
+      </footer>
+    {% endif %}
+  </article>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/pagination.html b/themes/vexingworkshop/templates/pagination.html
new file mode 100644 (file)
index 0000000..9511fdb
--- /dev/null
@@ -0,0 +1,17 @@
+{% if DEFAULT_PAGINATION %}
+  {% set first_page = articles_paginator.page(1) %}
+  {% set last_page = articles_paginator.page(articles_paginator.num_pages) %}
+  <nav>
+    <ul>
+      {% if articles_page.has_previous() %}
+        <li><a href="{{ SITEURL }}/{{ first_page.url }}">&Lang;</a></li>
+        <li><a href="{{ SITEURL }}/{{ articles_previous_page.url }}">&lang;</a></li>
+      {% endif %}
+      <li>Page {{ articles_page.number }} / {{ articles_paginator.num_pages }}</li>
+      {% if articles_page.has_next() %}
+        <li><a href="{{ SITEURL }}/{{ articles_next_page.url }}">&rang;</a></li>
+        <li><a href="{{ SITEURL }}/{{ last_page.url }}">&Rang;</a></li>
+      {% endif %}
+    </ul>
+  </nav>
+{% endif %}
diff --git a/themes/vexingworkshop/templates/period_archives.html b/themes/vexingworkshop/templates/period_archives.html
new file mode 100644 (file)
index 0000000..181f493
--- /dev/null
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - {{ period | reverse | join(' ') }} archives{% endblock %}
+
+{% block content %}
+    <h2>Archives for {{ period | reverse | join(' ') }}</h2>
+
+    <dl>
+        {% for article in dates %}
+            <dt>{{ article.locale_date }}</dt>
+            <dd><a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></dd>
+        {% endfor %}
+    </dl>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/tag.html b/themes/vexingworkshop/templates/tag.html
new file mode 100644 (file)
index 0000000..be21778
--- /dev/null
@@ -0,0 +1,7 @@
+{% extends "index.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - {{ tag }} tag{% endblock %}
+
+{% block content_title %}
+    <h2>Articles tagged with {{ tag }}</h2>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/tags.html b/themes/vexingworkshop/templates/tags.html
new file mode 100644 (file)
index 0000000..b21e5b5
--- /dev/null
@@ -0,0 +1,12 @@
+{% extends "base.html" %}
+
+{% block title %}{{ SITENAME|striptags }} - Tags{% endblock %}
+
+{% block content %}
+    <h2>Tags for {{ SITENAME }}</h2>
+    <ul>
+        {% for tag, articles in tags|sort %}
+            <li><a href="{{ SITEURL }}/{{ tag.url }}">{{ tag }}</a> ({{ articles|count }})</li>
+        {% endfor %}
+    </ul>
+{% endblock %}
diff --git a/themes/vexingworkshop/templates/translations.html b/themes/vexingworkshop/templates/translations.html
new file mode 100644 (file)
index 0000000..eed0703
--- /dev/null
@@ -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 %}