This commit is contained in:
NN Solex 2023-04-30 14:08:32 +03:00
parent ca8e39e641
commit 3b75097fed
45 changed files with 3567 additions and 0 deletions

89
web/Makefile Normal file
View file

@ -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=root
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 publish ssh_upload rsync_upload

Binary file not shown.

5
web/content/pages/404.md Normal file
View file

@ -0,0 +1,5 @@
Title: 404
Save_as: 404.html
Template: 404
The page could not be found

View file

@ -0,0 +1,4 @@
Title:
URL:
Save_as: index.html

View file

@ -0,0 +1,7 @@
Slug: e8229
Date: 2023-04-12
Category: Blue Eyed Donkey
Title: Entry 1
Location: 32.70124169424201, 34.9805500394171
I noticed a peculiar sensation in the air as soon as I arrived in town. It was as if an electric charge was coursing through the air beneath the pastoral tranquillity, making me nervous. I looked around, but there was no one to be found. The faint odor of decay lingered around me, mingled with the sweet fragrance of incense. The mix made me feel uneasy, like if I'd stepped into a strange, surreal dream.

14
web/nfc-theme/LICENSE Normal file
View file

@ -0,0 +1,14 @@
Copyright (c) 2015 Michael Cardell Widerkrantz <mc@hack.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

16
web/nfc-theme/Makefile Normal file
View file

@ -0,0 +1,16 @@
VERSION=20150208
DIST=mc-pelican-$(VERSION)
DISTFILES=README.txt LICENSE Makefile static templates
$(DIST).tar.bz2:
mkdir $(DIST)
cp -r $(DISTFILES) $(DIST)/
tar cf $(DIST).tar --exclude .git $(DIST)
bzip2 -9 $(DIST).tar
$(RM) -rf $(DIST)
dist: $(DIST).tar.bz2
clean:
$(RM) -f $(DIST).tar.bz2

28
web/nfc-theme/README.txt Normal file
View file

@ -0,0 +1,28 @@
A minimalist theme for the Pelican static blog generator:
http://blog.getpelican.com/
It's based on the built-in simple theme with some small changes to the
templates and some very minimalist CSS.
Install like this:
# pelican-themes -i mc-pelican
Then, in your pelicanconf.py:
THEME = 'mc-pelican'
You add menu items with MENUITEMS like this:
MENUITEMS = (
('Homepage', '/mc/'),
('About MC', '/mc/bio.html'),
('Contact', '/mc/contact.html'),
('Archives', '{0}/archives.html'.format(SITEURL)), )
If you want a blog description in the footer of all pages, define
DESCRIPTION.
Happy blogging,
MC.

Binary file not shown.

View file

@ -0,0 +1,10 @@
const ua = String(platform.os).toLowerCase();
const android = ua.indexOf("android") > -1;
const ios = ua.indexOf("ios") > -1;
const windows = ua.indexOf("windows") > -1;
const linux = ua.indexOf("linux") > -1;
const mac = ua.indexOf("macos") > -1;
var hashlink = document.querySelector(".geo a");
if ( windows || mac || linux ) hashlink.href = "https://maps.google.com/?q=" + hashlink.getAttribute("latlon");
else if ( android ) hashlink.href = "geo:0,0?q=" + hashlink.getAttribute("latlon");
else if ( ios ) hashlink.href = "http://maps.apple.com/?ll=" + hashlink.getAttribute("latlon") + "&q=" + hashlink.innerHTML;

View file

@ -0,0 +1,144 @@
@font-face {
font-family: 'David Libre';
src: local('David Libre'), local('DavidLibre'),
url('DavidLibre-Regular.ttf') format('ttf')
}
/* CSS Reset */
html {
margin: 0;
padding: 0;
text-align: left;
text-rendering: optimizeLegibility;
}
/* HTML5 tag defaults. */
header, footer, aside, nav, article
{
display: block;
}
h1, h2, h3, h4, h5 {
margin-block-start: 0;
font-weight: normal;
text-align: left;
font-size: 1em;
}
body {
font-family: 'David Libre';
padding: 1em;
font-size: 1.4em;
line-height: 1.2em;
text-align: left;
color: #090A0E;
height: 100vh;
overflow-x: hidden;
overflow-y: hidden;
margin: auto;
max-width: 40em;
}
p {
margin-block-start: 0;
}
ul, ul li {
margin:0;
padding:0;
list-style:none
}
ul li::before {
content: '*\00a0';
}
/* Use a thin border around all images. */
img
{
border: 1px solid;
max-width: 40em;
width: 100%;
}
/* Navigation bar. */
nav
{
padding-bottom: 1ex;
margin-bottom: 4em;
}
nav::after {
clear:left;
}
nav ul
{
padding: 0;
margin-left: 0;
list-style: none;
}
nav ul li
{
display: inline;
float: left;
margin-right: .4em; /* How far between items. */
margin-top: .3em;
}
nav li::before {
content: none;
}
nav ul li a
{
display: inline;
margin: 0;
}
/*
* Use a border around tables, but don't draw lines around individual
* cells.
*/
table
{
border-style: solid;
border-collapse: collapse;
border-width: thin;
font-size: 100%;
}
th, td
{
border-style: solid;
border-width: thin;
}
a {
border-bottom: 1px solid #090A0E;
}
/* for unvisited links: blue */
a:link
{
text-decoration: none;
}
/* for visited links: purple */
a:visited
{
text-decoration: none;
}
/* when mouse is over link or the link is active*/
a:hover, a:active
{
text-decoration: none;
}
blockquote {
border: 1px solid;
margin: 0;
padding-left: 1em;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="english">
<head>
<title>404</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/theme/local.css" rel="stylesheet">
<style>
body {
color: white;
background-color: blue;
display: table;
height: 100vh;
max-width: 100%;
overflow: hidden;
margin: 0;
}
a {
color: blue
}
div {
display: table-cell;
height: 100%;
vertical-align: middle;
}
</style>
</head>
<body id="index">
<div id="404">
<center><a>Windows</a></center>
<p>An exception 404 has occurred. The page could not be found. It may be possible to continue normally.</p>
<ul>
<li>Press the backspace key to attempt to continue.</li>
<li>Press CTRL+ALT+DEL to restart your computer. You will<br />
lose any unsaved information in all applications.</li>
</ul>
</div>
</body>
</html>

View file

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

View file

@ -0,0 +1,13 @@
{% extends "base.html" %}
{% block content %}
<section id="content" class="body">
<div class="entry-content">
{{ article.content }}
{% if article.metadata.geohash %}
<span class="geo"><a latlon="{{ article.metadata.latlon }}" href="geo:{{ article.metadata.latlon }}">{{ article.metadata.geohash }}</a></span>
{% endif %}
</div>
</section>
<script src="{{ SITEURL }}/theme/platform.js"></script>
<script src="{{ SITEURL }}/theme/geo.js"></script>
{% endblock %}

View file

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

View file

@ -0,0 +1,13 @@
{% 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 %}

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="{{ DEFAULT_LANG }}">
<head>
{% block head %}
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{{ SITEURL }}/theme/local.css" rel="stylesheet">
{% endblock head %}
</head>
<body id="index" class="home">
{% block content %}
{% endblock %}
{% if DESCRIPTION %}
<footer id="contentinfo" class="body">
<hr>
{{ DESCRIPTION }}
</footer>
{% endif %}
</body>
</html>

View file

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<ul>
{% for category, articles in categories %}
<li><a href="{{ SITEURL }}/{{ category.url }}">{{ category }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View file

@ -0,0 +1,5 @@
{% extends "index.html" %}
{% block content_title %}
<h2>{{ category }}</h2>
{% endblock %}

View file

@ -0,0 +1,14 @@
{% if GOSQUARED_SITENAME %}
<script type="text/javascript">
var GoSquared={};
GoSquared.acct = "{{ GOSQUARED_SITENAME }}";
(function(w){
function gs(){
w._gstc_lt=+(new Date); var d=document;
var g = d.createElement("script"); g.type = "text/javascript"; g.async = true; g.src = "//d1l6p2sc9645hc.cloudfront.net/tracker.js";
var s = d.getElementsByTagName("script")[0]; s.parentNode.insertBefore(g, s);
}
w.addEventListener?w.addEventListener("load",gs,false):w.attachEvent("onload",gs);
})(window);
</script>
{% endif %}

View file

@ -0,0 +1,21 @@
{% extends "base.html" %}
{% block content %}
<section id="content">
{% block content_title %}
{% endblock %}
{% for article in articles_page.object_list %}
<article class="hentry">
<header>
<h2 class="entry-title">
<a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark" title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a>
</h2>
<span class="entry-summary">{{ article.summary }}</span>
</header>
</article>
{% endfor %}
{% include 'pagination.html' %}
</section><!-- /#content -->
{% endblock content %}

View file

@ -0,0 +1,15 @@
{% extends "base.html" %}
{% block title %}{{ page.title }}{%endblock%}
{% block content %}
<h1>{{ page.title }}</h1>
{% import 'translations.html' as translations with context %}
{{ translations.translations_for(page) }}
{{ page.content }}
{% if page.modified %}
<p>
Last updated: {{ page.locale_modified }}
</p>
{% endif %}
{% endblock %}

View file

@ -0,0 +1,11 @@
{% if DEFAULT_PAGINATION %}
<p class="paginator">
{% if articles_page.has_previous() %}
<a href="{{ SITEURL }}/{{ articles_previous_page.url }}">&laquo;</a>
{% endif %}
Page {{ articles_page.number }} / {{ articles_paginator.num_pages }}
{% if articles_page.has_next() %}
<a href="{{ SITEURL }}/{{ articles_next_page.url }}">&raquo;</a>
{% endif %}
</p>
{% endif %}

View file

@ -0,0 +1,11 @@
{% extends "base.html" %}
{% 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 %}

View file

View file

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block title %}{{ SITENAME }} - Tags{% endblock %}
{% block content %}
<h1>Tags for {{ SITENAME }}</h1>
{%- for tag, articles in tags|sort %}
<li><a href="{{ SITEURL }}/{{ tag.url }}">{{ tag }}</a> ({{ articles|count }})</li>
{% endfor %}
{% endblock %}

View file

@ -0,0 +1,8 @@
{% macro translations_for(article) %}
{% if article.translations %}
{% for translation in article.translations %}
<a class="translation" href="{{ SITEURL }}/{{ translation.url }}">{{ translation.lang }}</a>
{% endfor %}
{% endif %}
{% endmacro %}

39
web/output/404.html Normal file
View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="english">
<head>
<title>404</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/theme/local.css" rel="stylesheet">
<style>
body {
color: white;
background-color: blue;
display: table;
height: 100vh;
max-width: 100%;
overflow: hidden;
margin: 0;
}
a {
color: blue
}
div {
display: table-cell;
height: 100%;
vertical-align: middle;
}
</style>
</head>
<body id="index">
<div id="404">
<center><a>Windows</a></center>
<p>An exception 404 has occurred. The page could not be found. It may be possible to continue normally.</p>
<ul>
<li>Press the backspace key to attempt to continue.</li>
<li>Press CTRL+ALT+DEL to restart your computer. You will<br />
lose any unsaved information in all applications.</li>
</ul>
</div>
</body>
</html>

21
web/output/e8229.html Normal file
View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="english">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/theme/local.css" rel="stylesheet">
</head>
<body id="index" class="home">
<section id="content" class="body">
<div class="entry-content">
<p>I noticed a peculiar sensation in the air as soon as I arrived in town. It was as if an electric charge was coursing through the air beneath the pastoral tranquillity, making me nervous. I looked around, but there was no one to be found. The faint odor of decay lingered around me, mingled with the sweet fragrance of incense. The mix made me feel uneasy, like if I'd stepped into a strange, surreal dream.</p>
<span class="geo"><a latlon="32.70124169424201,34.9805500394171" href="geo:32.70124169424201,34.9805500394171">svbfh1049ck</a></span>
</div>
</section>
<script src="/theme/platform.js"></script>
<script src="/theme/geo.js"></script>
</body>
</html>

18
web/output/index.html Normal file
View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="english">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/theme/local.css" rel="stylesheet">
</head>
<body id="index" class="home">
<h1></h1>
</body>
</html>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="english">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/theme/local.css" rel="stylesheet">
</head>
<body id="index" class="home">
<section id="content">
<h2>Blue Eyed Donkey</h2>
<article class="hentry">
<header>
<h2 class="entry-title">
<a href="/e8229.html" rel="bookmark" title="Permalink to Entry 1">Entry 1</a>
</h2>
<span class="entry-summary"></span>
</header>
</article>
</section><!-- /#content -->
</body>
</html>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="english">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/theme/local.css" rel="stylesheet">
</head>
<body id="index" class="home">
<ul>
<li><a href="/projects/blue-eyed-donkey/index.html">Blue Eyed Donkey</a></li>
</ul>
</body>
</html>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="english">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/theme/local.css" rel="stylesheet">
</head>
<body id="index" class="home">
<section id="content">
<article class="hentry">
<header>
<h2 class="entry-title">
<a href="/e8229.html" rel="bookmark" title="Permalink to Entry 1">Entry 1</a>
</h2>
<span class="entry-summary"></span>
</header>
</article>
</section><!-- /#content -->
</body>
</html>

Binary file not shown.

10
web/output/theme/geo.js Normal file
View file

@ -0,0 +1,10 @@
const ua = String(platform.os).toLowerCase();
const android = ua.indexOf("android") > -1;
const ios = ua.indexOf("ios") > -1;
const windows = ua.indexOf("windows") > -1;
const linux = ua.indexOf("linux") > -1;
const mac = ua.indexOf("macos") > -1;
var hashlink = document.querySelector(".geo a");
if ( windows || mac || linux ) hashlink.href = "https://maps.google.com/?q=" + hashlink.getAttribute("latlon");
else if ( android ) hashlink.href = "geo:0,0?q=" + hashlink.getAttribute("latlon");
else if ( ios ) hashlink.href = "http://maps.apple.com/?ll=" + hashlink.getAttribute("latlon") + "&q=" + hashlink.innerHTML;

144
web/output/theme/local.css Normal file
View file

@ -0,0 +1,144 @@
@font-face {
font-family: 'David Libre';
src: local('David Libre'), local('DavidLibre'),
url('DavidLibre-Regular.ttf') format('ttf')
}
/* CSS Reset */
html {
margin: 0;
padding: 0;
text-align: left;
text-rendering: optimizeLegibility;
}
/* HTML5 tag defaults. */
header, footer, aside, nav, article
{
display: block;
}
h1, h2, h3, h4, h5 {
margin-block-start: 0;
font-weight: normal;
text-align: left;
font-size: 1em;
}
body {
font-family: 'David Libre';
padding: 1em;
font-size: 1.4em;
line-height: 1.2em;
text-align: left;
color: #090A0E;
height: 100vh;
overflow-x: hidden;
overflow-y: hidden;
margin: auto;
max-width: 40em;
}
p {
margin-block-start: 0;
}
ul, ul li {
margin:0;
padding:0;
list-style:none
}
ul li::before {
content: '*\00a0';
}
/* Use a thin border around all images. */
img
{
border: 1px solid;
max-width: 40em;
width: 100%;
}
/* Navigation bar. */
nav
{
padding-bottom: 1ex;
margin-bottom: 4em;
}
nav::after {
clear:left;
}
nav ul
{
padding: 0;
margin-left: 0;
list-style: none;
}
nav ul li
{
display: inline;
float: left;
margin-right: .4em; /* How far between items. */
margin-top: .3em;
}
nav li::before {
content: none;
}
nav ul li a
{
display: inline;
margin: 0;
}
/*
* Use a border around tables, but don't draw lines around individual
* cells.
*/
table
{
border-style: solid;
border-collapse: collapse;
border-width: thin;
font-size: 100%;
}
th, td
{
border-style: solid;
border-width: thin;
}
a {
border-bottom: 1px solid #090A0E;
}
/* for unvisited links: blue */
a:link
{
text-decoration: none;
}
/* for visited links: purple */
a:visited
{
text-decoration: none;
}
/* when mouse is over link or the link is active*/
a:hover, a:active
{
text-decoration: none;
}
blockquote {
border: 1px solid;
margin: 0;
padding-left: 1em;
}

1260
web/output/theme/platform.js Normal file

File diff suppressed because it is too large Load diff

59
web/pelicanconf.py Normal file
View file

@ -0,0 +1,59 @@
# Disable Setext Headers Monkey Patch
from markdown import blockprocessors as bp
class NoProcessing(bp.BlockProcessor):
def test(self, parent, block):
return False
bp.SetextHeaderProcessor = NoProcessing
AUTHOR = 'NFC'
SITENAME = 'NFC'
THEME = 'nfc-theme'
PLUGIN_PATHS = ['plugins']
TIMEZONE = 'Asia/Jerusalem'
DEFAULT_LANG = 'English'
# 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
DEFAULT_PAGINATION = False
# Uncomment following line if you want document-relative URLs when developing
#RELATIVE_URLS = True
MARKDOWN = {
'extension_configs': {
'markdown.extensions.tables':{},
'markdown.extensions.footnotes':{},
'markdown.extensions.nl2br':{},
}
}
ARTICLE_URL = "{slug}.html"
ARTICLE_SAVE_AS = "{slug}.html"
INDEX_SAVE_AS = "tags/index.html"
ARCHIVES_SAVE_AS = ''
AUTHOR_SAVE_AS = ''
AUTHORS_SAVE_AS = ''
TAGS_SAVE_AS = ''
PATH = 'content'
ARTICLE_PATHS = ['tags',]
PAGE_PATHS = ['pages',]
SUMMARY_MAX_LENGTH = 0
DEFAULT_DATE_FORMAT = '%Y-%m-%d'
DEFAULT_CATEGORY = 'tag'
CATEGORIES_SAVE_AS = 'projects/index.html'
CATEGORY_URL = 'projects/{slug}/index.html'
CATEGORY_SAVE_AS = 'projects/{slug}/index.html'
DELETE_OUTPUT_DIRECTORY = True
PLUGINS = ['geohash']

View file

@ -0,0 +1 @@
from .geohash import *

View file

@ -0,0 +1,12 @@
from pelican import signals
import geohash_tools as gh
def generate_geohash(generator):
for article in generator.articles:
if "location" in article.metadata:
lat, lon = [float(i) for i in article.metadata['location'].replace(' ', '').split(',')]
article.metadata['latlon'] = article.metadata['location'].replace(' ', '')
article.metadata['geohash'] = gh.encode(lat, lon, 11)
def register():
signals.article_generator_finalized.connect(generate_geohash)

21
web/publishconf.py Normal file
View file

@ -0,0 +1,21 @@
# 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 = ""

143
web/tasks.py Normal file
View file

@ -0,0 +1,143 @@
# -*- coding: utf-8 -*-
import os
import shlex
import shutil
import sys
import datetime
from invoke import task
from invoke.main import program
from invoke.util import cd
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': 'root',
'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'],
'{}/templates/**/*.html'.format(theme_path),
]
content_file_extensions = ['.md', '.rst']
for extension in content_file_extensions:
content_glob = '{0}/**/*{1}'.format(SETTINGS['PATH'], extension)
watched_globs.append(content_glob)
static_file_extensions = ['.css', '.js']
for extension in static_file_extensions:
static_file_glob = '{0}/static/**/*{1}'.format(theme_path, 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))