diff --git a/app/__init__.py b/app/__init__.py index 8f8f3b3..1839f87 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,11 +1,12 @@ import datetime import os import re + +from glob import glob from typing import Optional -from markdown import markdown - from flask import Flask, abort, send_from_directory, render_template +from markdown import markdown basedir = os.path.abspath(os.path.join(os.path.realpath(__file__), '..', '..')) templates_dir = os.path.join(basedir, 'templates') @@ -33,6 +34,8 @@ def get_page_metadata(page: str) -> dict: metadata = {} with open(os.path.join(pages_dir, page), 'r') as f: + metadata['uri'] = '/article/' + page[:-3] + for line in f.readlines(): if not line: continue @@ -40,7 +43,10 @@ def get_page_metadata(page: str) -> dict: if not (m := re.match(r'^\[//]: # \(([^:]+):\s*([^)]+)\)\s*$', line)): break - metadata[m.group(1)] = m.group(2) + if m.group(1) == 'published': + metadata[m.group(1)] = datetime.date.fromisoformat(m.group(2)) + else: + metadata[m.group(1)] = m.group(2) return metadata @@ -52,15 +58,27 @@ def get_page(page: str, title: Optional[str] = None): metadata = get_page_metadata(page) with open(os.path.join(pages_dir, page), 'r') as f: return render_template('article.html', - title=title if title else metadata.get('title', 'Platypush Blog'), - published=(datetime.date.fromisoformat(metadata['published']).strftime('%b %d, %Y') + title=title if title else metadata.get('title', 'Platypush blog'), + image=metadata.get('image'), + description=metadata.get('description'), + published=(metadata['published'].strftime('%b %d, %Y') if metadata.get('published') else None), content=markdown(f.read(),extensions=['fenced_code', 'codehilite'])) +def get_pages() -> list: + return sorted([ + { + 'path': path, + **get_page_metadata(os.path.basename(path)), + } + for path in glob(os.path.join(pages_dir, '*.md')) + ], key=lambda page: page.get('published'), reverse=True) + + @app.route('/', methods=['GET']) def home_route(): - return get_page('Home', title='Platypush Blog') + return render_template('index.html', pages=get_pages()) @app.route('/favicon.ico', methods=['GET']) @@ -78,9 +96,6 @@ def css_route(style: str): return send_from_directory(css_dir, style) -@app.route('/', methods=['GET']) -def catch_all(path: str): - if path.endswith('.md'): - return get_page(path) - - abort(404) +@app.route('/article/
', methods=['GET']) +def article_route(article: str): + return get_page(article) diff --git a/static/css/blog.css b/static/css/blog.css index 13cb250..ed726dc 100644 --- a/static/css/blog.css +++ b/static/css/blog.css @@ -1,114 +1,40 @@ -html { - font-size: calc(1em + 1vw); -} - -@media screen and (min-width: 1024px) { - html { - font-size: 20px; - } -} - -body { - margin: 0; - width: 100%; - height: 100%; -} - -a, a:visited { - color: #555; - border-bottom: 1px dashed #999; - text-decoration: none; -} - -a:hover { - opacity: 0.7; -} - -header { - display: flex; - align-items: center; - height: 3em; - padding: 0 .5em; - box-shadow: 1px 3px 3px 0 #bbb; -} - -@media screen and (max-width: 767px) { - header { - height: 4em; - } -} - -header > a { - display: flex; - align-items: center; - border-bottom: none; -} - -header .icon { - background: url(/img/icon.png); - background-size: 40px; - width: 40px; - height: 40px; - display: inline-flex; - margin-right: 1em; -} - -header .title { - display: inline-flex; -} - -main { - height: calc(100% - 3em); - overflow: auto; - display: flex; - flex-direction: column; - align-items: center; - font-family: Avenir, Palatino, Georgia, Verdana, Helvetica, Arial, sans-serif; - padding: 0 2em; -} - main .content { - display: flex; - flex-direction: column; - text-align: justify; - line-height: 1.5em; - letter-spacing: .04em; + display: flex; + flex-direction: column; + text-align: justify; + line-height: 1.5em; + letter-spacing: .04em; } main .content code, .codehilite { - font-size: .85em; + font-size: .85em; } -h1 { - font-size: 2em; - line-height: 1.2em; -} - -h2 { - font-size: 1.5em; - line-height: 1.1em; +.description h3 { + font-weight: normal; + opacity: 0.6; + margin: -.5em auto .5em auto; } .published-date { - font-size: 0.75em; - opacity: .75; - margin-top: -1em; - margin-bottom: 2em; + font-size: 0.75em; + opacity: .75; + margin-bottom: 2em; } @media screen and (max-width: 1024px) { - main .content, main .title { - width: 100%; - } + main .container { + width: 100%; + } } @media screen and (min-width: 1024px) { - main .content, main .title { - max-width: 768px; - } + main .container { + max-width: 768px; + } } .codehilite { - padding: 0 .5em; - overflow: auto; + padding: 0 .5em; + overflow: auto; } diff --git a/static/css/common.css b/static/css/common.css new file mode 100644 index 0000000..6639bf0 --- /dev/null +++ b/static/css/common.css @@ -0,0 +1,78 @@ +html { + font-size: calc(1em + 1vw); +} + +@media screen and (min-width: 1024px) { + html { + font-size: 20px; + } +} + +body { + margin: 0; + width: 100%; + height: 100%; +} + +a, a:visited { + color: #555; + border-bottom: 1px dashed #999; + text-decoration: none; +} + +a:hover { + opacity: 0.7; +} + +header { + display: flex; + align-items: center; + height: 3em; + padding: 0 .5em; + box-shadow: 1px 3px 3px 0 #bbb; +} + +@media screen and (max-width: 767px) { + header { + height: 4em; + } +} + +header > a { + display: flex; + align-items: center; + border-bottom: none; +} + +header .icon { + background: url(/img/icon.png); + background-size: 40px; + width: 40px; + height: 40px; + display: inline-flex; + margin-right: 1em; +} + +header .title { + display: inline-flex; +} + +main { + height: calc(100% - 3em); + overflow: auto; + display: flex; + flex-direction: column; + align-items: center; + font-family: Avenir, Palatino, Georgia, Verdana, Helvetica, Arial, sans-serif; + padding: 0 2em; +} + +h1 { + font-size: 2em; + line-height: 1.2em; +} + +h2 { + font-size: 1.5em; + line-height: 1.1em; +} diff --git a/static/css/home.css b/static/css/home.css new file mode 100644 index 0000000..867e14b --- /dev/null +++ b/static/css/home.css @@ -0,0 +1,94 @@ +main { + padding: 0; +} + +.articles { + width: 100%; + display: flex; +} + +.article { + display: block; + box-shadow: 0 1px 3px 1px #ddd; + overflow: hidden; + text-overflow: ellipsis; + max-height: 30em; + color: black !important; +} + +.article:hover { + box-shadow: 0 1px 4px 2px #bcbcbc; + } + +@media screen and (max-width: 767px) { + .article { + width: 100%; + } +} + +@media screen and (min-width: 768px) and (max-width: 990px) { + .article { + width: 50%; + } +} + +@media screen and (min-width: 990px) and (max-width: 1023px) { + .article { + width: 33%; + } +} + +@media screen and (min-width: 1024px) and (max-width: 1279px) { + .article { + width: 25%; + } +} + +@media screen and (min-width: 1280px) { + .article { + width: 20%; + } +} + +.article .container { + height: 100%; + padding: 2em; +} + +.image { + height: 35%; + z-index: 1; +} + +.image img { + width: 100%; + height: 100%; +} + +.article .title { + font-size: 1.2em; + font-weight: bold; + margin-top: .4em; + text-align: center; +} + +a { + border-bottom: 0; +} + +.description { + color: rgba(0, 0, 0, 0.7); + font-size: .9em; +} + +.published-date { + font-size: .8em; + color: rgba(0, 0, 0, 0.4); + margin: .5em 0 2em 0; + text-align: center; +} + +h3 { + margin: 40px 0 0; +} + diff --git a/static/img/dashboard-1.png b/static/img/dashboard-1.png new file mode 100644 index 0000000..5c729a7 Binary files /dev/null and b/static/img/dashboard-1.png differ diff --git a/static/pages/Ultimate-self-hosted-automation-with-Platypush.md b/static/pages/Ultimate-self-hosted-automation-with-Platypush.md index e4beddc..1667b57 100644 --- a/static/pages/Ultimate-self-hosted-automation-with-Platypush.md +++ b/static/pages/Ultimate-self-hosted-automation-with-Platypush.md @@ -1,4 +1,6 @@ [//]: # (title: Ultimate self-hosted automation with Platypush) +[//]: # (description: Get started with Platypush to automate your smart home and beyond) +[//]: # (image: /img/dashboard-1.png) [//]: # (published: 2019-07-28) In the last few years we have experienced a terrific spike of products and solutions targeting home automation and diff --git a/templates/article.html b/templates/article.html index db0c2ca..f1a26d8 100644 --- a/templates/article.html +++ b/templates/article.html @@ -1,5 +1,6 @@ + {{ title }} @@ -9,22 +10,31 @@
-
Platypush Blog
+
Platypush blog
-
-

{{ title }}

+
+
+

{{ title }}

+
+ + {% if description %} +
+

{{ description }}

+
+ {% endif %} + {% if published %}
Published on {{ published }}
{% endif %} -
-
- {{ content | safe }} +
+ {{ content | safe }} +
diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..d6ea44b --- /dev/null +++ b/templates/index.html @@ -0,0 +1,48 @@ + + + + + Platypush blog + + + +
+ +
+
Platypush blog
+
+
+ +
+ +
+ +