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 *.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 argparse
import datetime import datetime
import shutil
import sys
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Any
from typing import Dict
from typing import NamedTuple from typing import NamedTuple
from typing import Optional from typing import Optional
from typing import Sequence from typing import Sequence
@ -18,21 +22,25 @@ yaml = ruamel.yaml.YAML(typ="safe")
@dataclass @dataclass
class MediaContainer: class MediaContainer:
title: str title: str
asset: str source: str
preview: Optional[str] = None
anchor: Optional[Union[str, int]] = None anchor: Optional[Union[str, int]] = None
source: Optional[str] = None
content: Optional[str] = None content: Optional[str] = None
hide_source: bool = False hide_source: bool = False
class MediaSerializer(msh.Schema): class MediaSerializer(msh.Schema):
title = msh.fields.String() title = msh.fields.String(required=True)
asset = msh.fields.URL() source = msh.fields.String(required=True)
preview = msh.fields.String(required=False)
anchor = msh.fields.String(required=False) anchor = msh.fields.String(required=False)
source = msh.fields.URL(required=False)
content = msh.fields.String(required=False) content = msh.fields.String(required=False)
hide_source = msh.fields.Boolean(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 @dataclass
class LinkContainer: class LinkContainer:
@ -42,10 +50,14 @@ class LinkContainer:
class LinkSerializer(msh.Schema): class LinkSerializer(msh.Schema):
link = msh.fields.URL() link = msh.fields.URL(required=True)
title = msh.fields.String(required=False) title = msh.fields.String(required=False)
icon = 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): class Location(NamedTuple):
title: str title: str
@ -53,8 +65,12 @@ class Location(NamedTuple):
class LocationSeralizer(msh.Schema): class LocationSeralizer(msh.Schema):
title = msh.fields.String() title = msh.fields.String(required=True)
link = msh.fields.URL() link = msh.fields.URL(required=True)
@msh.post_load
def _make_dataclass(self, data: Dict[str, Any], *args, **kwargs) -> Location:
return Location(**data)
@dataclass @dataclass
@ -70,47 +86,93 @@ class PostContainer:
class PostSerializer(msh.Schema): class PostSerializer(msh.Schema):
title = msh.fields.String() title = msh.fields.String(required=True)
location = msh.fields.Nested(LocationSeralizer) location = msh.fields.Nested(LocationSeralizer, required=True)
date = msh.fields.Date() date = msh.fields.Date("%Y-%m-%d", required=True)
banner = msh.fields.URL() banner = msh.fields.URL(required=True)
slug = msh.fields.String(required=False) slug = msh.fields.String(required=False)
links = msh.fields.List(msh.fields.Nested(LinkSerializer), 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: def get_args() -> argparse.Namespace:
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument(
"--config", help="Path to the config file", default=(Path.cwd() / "config.yaml")
)
parser.add_argument( parser.add_argument(
"-c", "--check", action="store_true", help="Check the config without building" "-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() return parser.parse_args()
def main(): def main():
cwd = Path.cwd().resolve() args = get_args()
output = cwd / "explore"
with (cwd / "config.yaml").open() as infile: cwd = Path.cwd().resolve()
config = yaml.load(infile) 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( env = jinja2.Environment(
loader=jinja2.FileSystemLoader(str(cwd / "templates")), loader=jinja2.FileSystemLoader(str(cwd / "templates")),
autoescape=jinja2.select_autoescape(["html", "xml"]), autoescape=jinja2.select_autoescape(["html", "xml"]),
) )
if not output.exists(): output.mkdir(exist_ok=True)
output.mkdir() explore.mkdir(exist_ok=True)
index = env.get_template("index.html.j2").render(config=config) index = env.get_template("index.html.j2").render(config=config)
with (explore / "index.html").open("w") as outfile:
with (output / "index.html").open("w") as outfile:
outfile.write(index) 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") post_template = env.get_template("post.html.j2")
for post_data in config["posts"]: for post_data in config["posts"]:
post = post_template.render(post=post_data) 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) outfile.write(post)
nginx = env.get_template("nginx.conf.d.j2").render(config=config) nginx = env.get_template("nginx.conf.d.j2").render(config=config)
@ -119,4 +181,4 @@ def main():
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

View File

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

View File

@ -4,5 +4,6 @@ User-agent: *
# Disallow access to non-content directories # Disallow access to non-content directories
Disallow: /css Disallow: /css
Disallow: /js Disallow: /js
Disallow: /error
Sitemap: https://allaroundhere.org/sitemap.xml 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" content="https://cdn.enp.one/img/backgrounds/cl-photo-boston.jpg">
<meta name="twitter:image:alt" content="All Around Here"> <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="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="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="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"> <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 }}"/> <link rel="stylesheet" href="../css/explore.css"/>
{% endfor %}
<link <link
rel="stylesheet" rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"
integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
crossorigin="anonymous" crossorigin="anonymous"
/> />
{% for script in config.assets.js %}
<script type="text/javascript" src="http{{ 's' if config.https else '' }}://{{ config.site }}/{{ script }}"></script> <script type="text/javascript" src="../js/custom.js"></script>
{% endfor %}
<noscript><style>.nojs { display: none; }</style></noscript> <noscript><style>.nojs { display: none; }</style></noscript>
</head> </head>
@ -58,16 +57,16 @@
<div id="toggle-description" class="nojs"><i class="fas fa-paragraph"></i></div> <div id="toggle-description" class="nojs"><i class="fas fa-paragraph"></i></div>
<div id="content"> <div id="content">
<div id="header"><h1>{{ config.title }}</h1></div> <div id="header"><h1>Explore All Around Here</h1></div>
<ul> <ul>
{% for post in config.posts %} {% for post in config.posts %}
<li class="article"> <li class="article">
<div class="article-banner" style="background-image: url('{{ post.banner }}');"> <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> <h2>{{ post.title }}</h2>
<p> <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 }} <i class="far fa-calendar-alt"></i>{{ post.date }}
</p> </p>
</a> </a>

View File

@ -1,16 +1,16 @@
location = http{{ 's' if config.https else '' }}://{{ config.site }}/robots.txt { location = robots.txt {
allow all; allow all;
log_not_found off; log_not_found off;
access_log off; access_log off;
} }
location = http{{ 's' if config.https else '' }}://{{ config.site }}/{{ config.path.output }}/ { location = explore/ {
index index.html index index.html
} }
location ~* http{{ 's' if config.https else '' }}://{{ config.site }}/{{ config.path.output }}/(.*)/ { location ~* explore/(.*)/ {
if ($request_uri ~ ^/(.*)\.html) { 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; 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>