Compare commits

...

7 Commits

9 changed files with 146 additions and 136 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
explore/
build/
.venv/
*.conf

3
Makefile Normal file
View File

@ -0,0 +1,3 @@
clean:
rm --recursive --force build
rm --force nginx.conf

108
build.py
View File

@ -1,7 +1,11 @@
import argparse
import datetime
import shutil
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from typing import Dict
from typing import NamedTuple
from typing import Optional
from typing import Sequence
@ -18,21 +22,25 @@ yaml = ruamel.yaml.YAML(typ="safe")
@dataclass
class MediaContainer:
title: str
asset: str
source: str
preview: Optional[str] = None
anchor: Optional[Union[str, int]] = None
source: Optional[str] = None
content: Optional[str] = None
hide_source: bool = False
class MediaSerializer(msh.Schema):
title = msh.fields.String()
asset = msh.fields.URL()
title = msh.fields.String(required=True)
source = msh.fields.String(required=True)
preview = msh.fields.String(required=False)
anchor = msh.fields.String(required=False)
source = msh.fields.URL(required=False)
content = msh.fields.String(required=False)
hide_source = msh.fields.Boolean(required=False)
@msh.post_load
def _make_dataclass(self, data: Dict[str, Any], *args, **kwargs) -> MediaContainer:
return MediaContainer(**data)
@dataclass
class LinkContainer:
@ -42,10 +50,14 @@ class LinkContainer:
class LinkSerializer(msh.Schema):
link = msh.fields.URL()
link = msh.fields.URL(required=True)
title = msh.fields.String(required=False)
icon = msh.fields.String(required=False)
@msh.post_load
def _make_dataclass(self, data: Dict[str, Any], *args, **kwargs) -> LinkContainer:
return LinkContainer(**data)
class Location(NamedTuple):
title: str
@ -53,8 +65,12 @@ class Location(NamedTuple):
class LocationSeralizer(msh.Schema):
title = msh.fields.String()
link = msh.fields.URL()
title = msh.fields.String(required=True)
link = msh.fields.URL(required=True)
@msh.post_load
def _make_dataclass(self, data: Dict[str, Any], *args, **kwargs) -> Location:
return Location(**data)
@dataclass
@ -70,47 +86,93 @@ class PostContainer:
class PostSerializer(msh.Schema):
title = msh.fields.String()
location = msh.fields.Nested(LocationSeralizer)
date = msh.fields.Date()
banner = msh.fields.URL()
title = msh.fields.String(required=True)
location = msh.fields.Nested(LocationSeralizer, required=True)
date = msh.fields.Date("%Y-%m-%d", required=True)
banner = msh.fields.URL(required=True)
slug = msh.fields.String(required=False)
links = msh.fields.List(msh.fields.Nested(LinkSerializer), required=False)
media = msh.fields.List()
media = msh.fields.List(msh.fields.Nested(MediaSerializer), required=True)
@msh.validates_schema
def _unique_anchors(self, data: Dict[str, Any], **kwargs):
anchors = [item.anchor for item in data["media"] if item.anchor is not None]
if len(anchors) != len(set(anchors)):
raise msh.ValidationError(
f"Media anchors used multiple times: {set([item for item in anchors if anchors.count(item) > 1])}"
)
@msh.post_load
def _make_dataclass(self, data: Dict[str, Any], *args, **kwargs) -> PostContainer:
for index, item in enumerate(data["media"]):
item.anchor = item.anchor or index
data["media"][index] = item
return PostContainer(**data)
class ConfigSerializer(msh.Schema):
static = msh.fields.List(msh.fields.String(), required=False)
posts = msh.fields.List(msh.fields.Nested(PostSerializer), required=True)
@msh.validates_schema
def _unique_slugs(self, data: Dict[str, Any], **kwargs):
slugs = [item.slug for item in data["posts"] if item.slug is not None]
if len(slugs) != len(set(slugs)):
raise msh.ValidationError(
f"Post slugs used multiple times: {set([item for item in slugs if slugs.count(item) > 1])}"
)
def get_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument(
"--config", help="Path to the config file", default=(Path.cwd() / "config.yaml")
)
parser.add_argument(
"-c", "--check", action="store_true", help="Check the config without building"
)
parser.add_argument("-p", "--publish", action="store_true", help="Publish the site")
return parser.parse_args()
def main():
cwd = Path.cwd().resolve()
output = cwd / "explore"
args = get_args()
with (cwd / "config.yaml").open() as infile:
config = yaml.load(infile)
cwd = Path.cwd().resolve()
output = cwd / "build"
explore = output / "explore"
with Path(args.config).resolve().open() as infile:
config = ConfigSerializer().load(yaml.load(infile))
if args.check:
return 0
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(str(cwd / "templates")),
autoescape=jinja2.select_autoescape(["html", "xml"]),
)
if not output.exists():
output.mkdir()
output.mkdir(exist_ok=True)
explore.mkdir(exist_ok=True)
index = env.get_template("index.html.j2").render(config=config)
with (output / "index.html").open("w") as outfile:
with (explore / "index.html").open("w") as outfile:
outfile.write(index)
sitemap = env.get_template("sitemap.xml.j2").render(config=config)
with (output / "sitemap.xml").open("w") as outfile:
outfile.write(sitemap)
for static in config["static"]:
dest = Path(output / static).resolve()
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(static, str(output / static), follow_symlinks=True)
post_template = env.get_template("post.html.j2")
for post_data in config["posts"]:
post = post_template.render(post=post_data)
with (output / f"{post_data['slug']}.html").open("w") as outfile:
with (explore / f"{post_data.slug}.html").open("w") as outfile:
outfile.write(post)
nginx = env.get_template("nginx.conf.d.j2").render(config=config)
@ -119,4 +181,4 @@ def main():
if __name__ == "__main__":
main()
sys.exit(main())

View File

@ -1,99 +1,32 @@
---
site: allaroundhere.org
title: Explore All Around Here
https: true
path:
output: explore
assets:
js:
- css/explore.css
css:
- js/custom.js
static:
- css/style.css
- css/explore.css
- js/custom.js
- error/404.html
- index.html
- robots.txt
posts:
- title: A 1:1 recreation of the set for Star Trek the Original Series
slug: star-trek-set-tours
location:
title: Ticonderoga, NY
link: https://maps.google.com
date: 2020-01-01
date: "2020-01-01"
banner: https://cdn.enp.one/img/backgrounds/cl-photo-denver.jpg
links:
- title: Star Trek Set Tours
link: https://www.startrektour.com/
media:
- anchor: foo-bar-baz
title: Foo Bar Baz
- title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
asset: https://cdn.enp.one/img/backgrounds/cl-network.jpg
source: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
- title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
source: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
source: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- title: A 1:1 recreation of the set for Star Trek the Original Series
slug: star-trek-set-tours
location: Ticonderoga, NY
date: 2020-01-01
banner: https://cdn.enp.one/img/backgrounds/cl-photo-denver.jpg
description: foo bar baz
media:
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- title: A 1:1 recreation of the set for Star Trek the Original Series
slug: star-trek-set-tours
location: Ticonderoga, NY
date: 2020-01-01
banner: https://cdn.enp.one/img/backgrounds/cl-photo-denver.jpg
description: foo bar baz
media:
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
- anchor: foo-bar-baz
title: Foo Bar Baz
content: Fizz buzz, lorem ipsum dolher, siamet
link: https://cdn.enp.one/img/backgrounds/cl-network.jpg
preview: https://cdn.enp.one/img/backgrounds/cl-network.jpg
source: https://cdn.enp.one/img/backgrounds/cl-network.jpg

View File

@ -4,5 +4,6 @@ User-agent: *
# Disallow access to non-content directories
Disallow: /css
Disallow: /js
Disallow: /error
Sitemap: https://allaroundhere.org/sitemap.xml

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
<url>
<loc>https://allaroundhere.org/</loc>
<lastmod>2021-02-01T00:30:55+00:00</lastmod>
<priority>1.00</priority>
</url>
</urlset>

View File

@ -30,23 +30,22 @@
<meta name="twitter:image" content="https://cdn.enp.one/img/backgrounds/cl-photo-boston.jpg">
<meta name="twitter:image:alt" content="All Around Here">
<title>{{ config.title }}</title>
<title>Explore All Around Here</title>
<link rel="shortcut icon" href="https://cdn.enp.one/img/logos/aah-b-sm.png">
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.enp.one/img/logos/aah-b-sm.png">
<link rel="icon" type="image/png" sizes="32x32" href="https://cdn.enp.one/img/logos/aah-b-sm.png" >
<link rel="icon" type="image/png" sizes="16x16" href="https://cdn.enp.one/img/logos/aah-b-sm.png">
{% for style in config.assets.css %}
<link rel="stylesheet" href="http{{ 's' if config.https else '' }}://{{ config.site }}/{{ style }}"/>
{% endfor %}
<link rel="stylesheet" href="../css/explore.css"/>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"
integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
crossorigin="anonymous"
/>
{% for script in config.assets.js %}
<script type="text/javascript" src="http{{ 's' if config.https else '' }}://{{ config.site }}/{{ script }}"></script>
{% endfor %}
<script type="text/javascript" src="../js/custom.js"></script>
<noscript><style>.nojs { display: none; }</style></noscript>
</head>
@ -58,16 +57,16 @@
<div id="toggle-description" class="nojs"><i class="fas fa-paragraph"></i></div>
<div id="content">
<div id="header"><h1>{{ config.title }}</h1></div>
<div id="header"><h1>Explore All Around Here</h1></div>
<ul>
{% for post in config.posts %}
<li class="article">
<div class="article-banner" style="background-image: url('{{ post.banner }}');">
<a href="http{{ 's' if config.https else '' }}://{{ config.site }}/{{ config.path.output }}/{{ post.slug }}/" class="article-content">
<a href="explore/{{ post.slug }}/" class="article-content">
<h2>{{ post.title }}</h2>
<p>
<i class="fas fa-map-marker-alt"></i>{{ post.location }}
<i class="fas fa-map-marker-alt"></i>{{ post.location.title }}
<i class="far fa-calendar-alt"></i>{{ post.date }}
</p>
</a>

View File

@ -1,16 +1,16 @@
location = http{{ 's' if config.https else '' }}://{{ config.site }}/robots.txt {
location = robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = http{{ 's' if config.https else '' }}://{{ config.site }}/{{ config.path.output }}/ {
location = explore/ {
index index.html
}
location ~* http{{ 's' if config.https else '' }}://{{ config.site }}/{{ config.path.output }}/(.*)/ {
location ~* explore/(.*)/ {
if ($request_uri ~ ^/(.*)\.html) {
return 302 http{{ 's' if config.https else '' }}://{{ config.site }}/{{ config.path.output }}/$1/;
return 302 explore/$1/;
}
try_files $uri $uri.html $uri/ =404;
}

27
templates/sitemap.xml.j2 Normal file
View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://allaroundhere.org/</loc>
<lastmod>2021-02-01T00:30:55+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<loc>https://allaroundhere.org/explore/</loc>
<lastmod>2021-02-01T00:30:55+00:00</lastmod>
<priority>1.10</priority>
</url>
{% for post in config.posts %}
<url>
<loc>https://allaroundhere.org/explore/{{ post.slug }}/</loc>
<lastmod>2021-02-01T00:30:55+00:00</lastmod>
<priority>0.90</priority>
</url>
{% endfor %}
</urlset>