diff --git a/README.md b/README.md index 4cc9fef..eaceeb9 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,21 @@ -# Platypush blog pages and engine +# Platypush blog pages -This project provides the pages and the webapp needed by the Platypush blog. +This project provides the content of the Platypush blog. -## Dependencies +It uses [`madblog`](https://git.platypush.tech/blacklight/madblog) +as a Markdown-based blogging micro-framework. -- `flask` -- `markdown` -- `pygments` - -## Start the web app +## Setup ```shell -# The application will listen on port 8000 -python -m app +$ pip install madblog ``` + +## Run + +```shell +$ git clone https://git.platypush.tech/platypush/blog.git +$ cd blog +$ madblog +``` + diff --git a/app/__init__.py b/app/__init__.py deleted file mode 100644 index 2ec71df..0000000 --- a/app/__init__.py +++ /dev/null @@ -1,157 +0,0 @@ -import datetime -import os -import re - -from glob import glob -from typing import Optional - -from flask import Flask, Response, abort, send_from_directory, render_template -from markdown import markdown - -from .latex import MarkdownLatex - -basedir = os.path.abspath(os.path.join(os.path.realpath(__file__), '..', '..')) -templates_dir = os.path.join(basedir, 'templates') -static_dir = os.path.join(basedir, 'static') -pages_dir = os.path.join(static_dir, 'pages') -img_dir = os.path.join(static_dir, 'img') -css_dir = os.path.join(static_dir, 'css') -fonts_dir = os.path.join(static_dir, 'fonts') - -app = Flask(__name__, template_folder=templates_dir) - - -def parse_page_title(page: str) -> str: - if page.endswith('.md'): - page = page[:-3] - - return page.replace('-', ' ') - - -def get_page_metadata(page: str) -> dict: - if not page.endswith('.md'): - page = page + '.md' - - if not os.path.isfile(os.path.join(pages_dir, page)): - abort(404) - - 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 - - if not (m := re.match(r'^\[//]: # \(([^:]+):\s*([^)]+)\)\s*$', line)): - break - - 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 - - -def get_page(page: str, title: Optional[str] = None, skip_header: bool = False): - if not page.endswith('.md'): - page = page + '.md' - - 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'), - image=metadata.get('image'), - description=metadata.get('description'), - author=re.match(r'(.+?)\s+<([^>]+>)', metadata['author'])[1] if 'author' in metadata else None, - author_email=re.match(r'(.+?)\s+<([^>]+)>', metadata['author'])[2] if 'author' in metadata else None, - published=(metadata['published'].strftime('%b %d, %Y') - if metadata.get('published') else None), - content=markdown(f.read(), extensions=['fenced_code', 'codehilite', MarkdownLatex()]), - skip_header=skip_header) - - -def get_pages(with_content: bool = False, skip_header: bool = False) -> list: - return sorted([ - { - 'path': path, - 'content': get_page(path, skip_header=skip_header) if with_content else '', - **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 render_template('index.html', pages=get_pages()) - - -@app.route('/favicon.ico', methods=['GET']) -def favicon_route(): - return send_from_directory(img_dir, 'favicon.ico') - - -@app.route('/img/', methods=['GET']) -def img_route(img: str): - return send_from_directory(img_dir, img) - - -@app.route('/css/""" - -# Cache and temp file paths -tmpdir = tempfile.gettempdir() + '/markdown-latex' -cache_file = tmpdir + '/latex.cache' - - -class LaTeXPreprocessor(markdown.preprocessors.Preprocessor): - # These are our cached expressions that are stored in latex.cache - cached = {} - - # Basic LaTex Setup as well as our list of expressions to parse - tex_preamble = r"""\documentclass[14pt]{article} -\usepackage{amsmath} -\usepackage{amsthm} -\usepackage{amssymb} -\usepackage{bm} -\usepackage{graphicx} -\usepackage[usenames,dvipsnames]{color} -\pagestyle{empty} -""" - - # Math TeX extraction regex - math_extract_regex = re.compile(r'(.+?)((\\\(.+?\\\))|(\$\$\n.+?\n\$\$\n))(.*)', re.MULTILINE | re.DOTALL) - - # Math TeX matching regex - math_match_regex = re.compile(r'\s*(\\\(.+?\\\))|(\$\$\n.+?\n\$\$\n)\s*', re.MULTILINE | re.DOTALL) - - def __init__(self, *_, **__): - if not os.path.isdir(tmpdir): - os.makedirs(tmpdir) - try: - with open(cache_file, 'r') as f: - self.cached = json.load(f) - except (IOError, json.JSONDecodeError): - self.cached = {} - - self.config = { - ("general", "preamble"): "", - ("dvipng", "args"): "-q -T tight -bg Transparent -z 9 -D 200", - ("delimiters", "text"): "%", - ("delimiters", "math"): "$", - ("delimiters", "preamble"): "%%"} - - def _latex_to_base64(self, tex): - """Generates a base64 representation of TeX string""" - - # Generate the temporary file - tmp_file_fd, path = tempfile.mkstemp(dir=tmpdir) - with os.fdopen(tmp_file_fd, "w") as tmp_file: - tmp_file.write(self.tex_preamble) - tmp_file.write(tex) - tmp_file.write('\n\\end{document}') - - # compile LaTeX document. A DVI file is created - status = call(('latex -halt-on-error -output-directory={:s} {:s}' - .format(tmpdir, path)).split(), - stdout=PIPE, timeout=10) - - # clean up if the above failed - if status: - self._cleanup(path, err=True) - raise Exception("Couldn't compile LaTeX document." + - "Please read '%s.log' for more detail." % path) - - # Run dvipng on the generated DVI file. Use tight bounding box. - # Magnification is set to 1200 - dvi = "%s.dvi" % path - png = "%s.png" % path - - # Extract the image - cmd = "dvipng %s %s -o %s" % (self.config[("dvipng", "args")], dvi, png) - status = call(cmd.split(), stdout=PIPE) - - # clean up if we couldn't make the above work - if status: - self._cleanup(path, err=True) - raise Exception("Couldn't convert LaTeX to image." + - "Please read '%s.log' for more detail." % path) - - # Read the png and encode the data - try: - with open(png, "rb") as png: - data = png.read() - return base64.b64encode(data) - finally: - self._cleanup(path) - - @staticmethod - def _cleanup(path, err=False): - # don't clean up the log if there's an error - extensions = ["", ".aux", ".dvi", ".png", ".log"] - if err: - extensions.pop() - - # now do the actual cleanup, passing on non-existent files - for extension in extensions: - try: - os.remove("%s%s" % (path, extension)) - except (IOError, OSError): - pass - - def run(self, lines): - """Parses the actual page""" - # Checks for the LaTeX header - use_latex = any(line == '[//]: # (latex: 1)' for line in lines) - if not use_latex: - return lines - - # Re-creates the entire page so we can parse in a multiline env. - page = "\n".join(lines) - - # Adds a preamble mode - self.tex_preamble += self.config[("general", "preamble")] + "\n\\begin{document}\n" - - # Figure out our text strings and math-mode strings - tex_expr = self.math_extract_regex.findall(page) - - # No sense in doing the extra work - if not len(tex_expr): - return page.split("\n") - - # Parse the expressions - new_cache = {} - new_page = '' - n_multiline_expressions = 0 - - while page: - m = self.math_extract_regex.match(page) - if not m: - new_page += page - break - - new_page += m.group(1) - math_match = self.math_match_regex.match(m.group(2)) - if not math_match: - new_page += m.group(2) - else: - expr = m.group(2) - is_multiline = math_match.group(2) is not None - tex_hash = self.hash(expr) - if tex_hash in self.cached: - data = self.cached[tex_hash] - else: - data = self._latex_to_base64(expr).decode() - new_cache[tex_hash] = data - - if is_multiline and n_multiline_expressions > 0: - new_page += '

' - new_page += (multiline_img_expr if is_multiline else img_expr) % ('true', expr, tex_hash, data) - - if is_multiline: - new_page += '

' - n_multiline_expressions += 1 - - page = m.group(5) - - if n_multiline_expressions > 0: - new_page += '

' - - # Cache our data - self.cached.update(new_cache) - with open(cache_file, 'w') as f: - json.dump(self.cached, f) - - # Make sure to re-split the lines - return new_page.split("\n") - - @staticmethod - def hash(tex: str) -> str: - return hashlib.sha1(tex.encode()).hexdigest() - - -class LaTeXPostprocessor(markdown.postprocessors.Postprocessor): - """This post processor extension just allows us to further - refine, if necessary, the document after it has been parsed.""" - - # noinspection PyMethodMayBeStatic - def run(self, text): - # Inline a style for default behavior - text = img_css + text - return text - - -class MarkdownLatex(markdown.Extension): - """Wrapper for LaTeXPreprocessor""" - - def extendMarkdown(self, md): - # Our base LaTeX extension - md.preprocessors.add('latex', - LaTeXPreprocessor(self), ">html_block") - # Our cleanup postprocessing extension - md.postprocessors.add('latex', - LaTeXPostprocessor(self), ">amp_substitute") diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..ea9967c --- /dev/null +++ b/config.yaml @@ -0,0 +1,10 @@ +title: Platypush +description: The Platypush blog +link: https://blog.platypush.tech +home_link: https://platypush.tech +categories: + - IoT + - automation + - python + - programming + - machine learning diff --git a/static/img/adafruit-16-pwm.jpg b/img/adafruit-16-pwm.jpg similarity index 100% rename from static/img/adafruit-16-pwm.jpg rename to img/adafruit-16-pwm.jpg diff --git a/static/img/arduino-1.gif b/img/arduino-1.gif similarity index 100% rename from static/img/arduino-1.gif rename to img/arduino-1.gif diff --git a/static/img/baby-1.png b/img/baby-1.png similarity index 100% rename from static/img/baby-1.png rename to img/baby-1.png diff --git a/static/img/baby-2.jpg b/img/baby-2.jpg similarity index 100% rename from static/img/baby-2.jpg rename to img/baby-2.jpg diff --git a/static/img/brushless-motor-1.png b/img/brushless-motor-1.png similarity index 100% rename from static/img/brushless-motor-1.png rename to img/brushless-motor-1.png diff --git a/static/img/ci-1.png b/img/ci-1.png similarity index 100% rename from static/img/ci-1.png rename to img/ci-1.png diff --git a/static/img/custom-widget-1.png b/img/custom-widget-1.png similarity index 100% rename from static/img/custom-widget-1.png rename to img/custom-widget-1.png diff --git a/static/img/dashboard-1.png b/img/dashboard-1.png similarity index 100% rename from static/img/dashboard-1.png rename to img/dashboard-1.png diff --git a/static/img/data-visualization-1.png b/img/data-visualization-1.png similarity index 100% rename from static/img/data-visualization-1.png rename to img/data-visualization-1.png diff --git a/static/img/drone-lift.gif b/img/drone-lift.gif similarity index 100% rename from static/img/drone-lift.gif rename to img/drone-lift.gif diff --git a/static/img/drone-schema.png b/img/drone-schema.png similarity index 100% rename from static/img/drone-schema.png rename to img/drone-schema.png diff --git a/static/img/drone-warning.png b/img/drone-warning.png similarity index 100% rename from static/img/drone-warning.png rename to img/drone-warning.png diff --git a/static/img/esc-1.jpg b/img/esc-1.jpg similarity index 100% rename from static/img/esc-1.jpg rename to img/esc-1.jpg diff --git a/static/img/esc-pwm.png b/img/esc-pwm.png similarity index 100% rename from static/img/esc-pwm.png rename to img/esc-pwm.png diff --git a/static/img/extension-1.png b/img/extension-1.png similarity index 100% rename from static/img/extension-1.png rename to img/extension-1.png diff --git a/static/img/extension-2.png b/img/extension-2.png similarity index 100% rename from static/img/extension-2.png rename to img/extension-2.png diff --git a/static/img/extension-3.png b/img/extension-3.png similarity index 100% rename from static/img/extension-3.png rename to img/extension-3.png diff --git a/static/img/extension-4.png b/img/extension-4.png similarity index 100% rename from static/img/extension-4.png rename to img/extension-4.png diff --git a/static/img/extension-5.png b/img/extension-5.png similarity index 100% rename from static/img/extension-5.png rename to img/extension-5.png diff --git a/static/img/extension-6.png b/img/extension-6.png similarity index 100% rename from static/img/extension-6.png rename to img/extension-6.png diff --git a/static/img/extension-7.png b/img/extension-7.png similarity index 100% rename from static/img/extension-7.png rename to img/extension-7.png diff --git a/static/img/extension-8.png b/img/extension-8.png similarity index 100% rename from static/img/extension-8.png rename to img/extension-8.png diff --git a/static/img/favicon.ico b/img/favicon.ico similarity index 100% rename from static/img/favicon.ico rename to img/favicon.ico diff --git a/static/img/git-integration-1.png b/img/git-integration-1.png similarity index 100% rename from static/img/git-integration-1.png rename to img/git-integration-1.png diff --git a/static/img/gitlab-1.png b/img/gitlab-1.png similarity index 100% rename from static/img/gitlab-1.png rename to img/gitlab-1.png diff --git a/static/img/google-fit-1.png b/img/google-fit-1.png similarity index 100% rename from static/img/google-fit-1.png rename to img/google-fit-1.png diff --git a/static/img/grafana-1.png b/img/grafana-1.png similarity index 100% rename from static/img/grafana-1.png rename to img/grafana-1.png diff --git a/static/img/grafana-2.png b/img/grafana-2.png similarity index 100% rename from static/img/grafana-2.png rename to img/grafana-2.png diff --git a/static/img/grafana-3.png b/img/grafana-3.png similarity index 100% rename from static/img/grafana-3.png rename to img/grafana-3.png diff --git a/static/img/icon.png b/img/icon.png similarity index 100% rename from static/img/icon.png rename to img/icon.png diff --git a/static/img/light-hue-ui-1.png b/img/light-hue-ui-1.png similarity index 100% rename from static/img/light-hue-ui-1.png rename to img/light-hue-ui-1.png diff --git a/static/img/lipo-1.jpg b/img/lipo-1.jpg similarity index 100% rename from static/img/lipo-1.jpg rename to img/lipo-1.jpg diff --git a/static/img/madness-screenshot.png b/img/madness-screenshot.png similarity index 100% rename from static/img/madness-screenshot.png rename to img/madness-screenshot.png diff --git a/static/img/mopidy-iris-1.jpeg b/img/mopidy-iris-1.jpeg similarity index 100% rename from static/img/mopidy-iris-1.jpeg rename to img/mopidy-iris-1.jpeg diff --git a/static/img/mpd-1.png b/img/mpd-1.png similarity index 100% rename from static/img/mpd-1.png rename to img/mpd-1.png diff --git a/static/img/ncmpcpp-1.png b/img/ncmpcpp-1.png similarity index 100% rename from static/img/ncmpcpp-1.png rename to img/ncmpcpp-1.png diff --git a/static/img/ncmpcpp-2.png b/img/ncmpcpp-2.png similarity index 100% rename from static/img/ncmpcpp-2.png rename to img/ncmpcpp-2.png diff --git a/static/img/ncmpcpp-3.png b/img/ncmpcpp-3.png similarity index 100% rename from static/img/ncmpcpp-3.png rename to img/ncmpcpp-3.png diff --git a/static/img/newsletter-1.png b/img/newsletter-1.png similarity index 100% rename from static/img/newsletter-1.png rename to img/newsletter-1.png diff --git a/static/img/notebook.jpg b/img/notebook.jpg similarity index 100% rename from static/img/notebook.jpg rename to img/notebook.jpg diff --git a/static/img/obsidian-screenshot.png b/img/obsidian-screenshot.png similarity index 100% rename from static/img/obsidian-screenshot.png rename to img/obsidian-screenshot.png diff --git a/static/img/people-detect-1.png b/img/people-detect-1.png similarity index 100% rename from static/img/people-detect-1.png rename to img/people-detect-1.png diff --git a/static/img/people-detect-2.png b/img/people-detect-2.png similarity index 100% rename from static/img/people-detect-2.png rename to img/people-detect-2.png diff --git a/static/img/people-detect-3.png b/img/people-detect-3.png similarity index 100% rename from static/img/people-detect-3.png rename to img/people-detect-3.png diff --git a/static/img/people-detect-4.png b/img/people-detect-4.png similarity index 100% rename from static/img/people-detect-4.png rename to img/people-detect-4.png diff --git a/static/img/people-detect-5.png b/img/people-detect-5.png similarity index 100% rename from static/img/people-detect-5.png rename to img/people-detect-5.png diff --git a/static/img/pitch-roll-yaw-1.png b/img/pitch-roll-yaw-1.png similarity index 100% rename from static/img/pitch-roll-yaw-1.png rename to img/pitch-roll-yaw-1.png diff --git a/static/img/pitch-roll-yaw-2.png b/img/pitch-roll-yaw-2.png similarity index 100% rename from static/img/pitch-roll-yaw-2.png rename to img/pitch-roll-yaw-2.png diff --git a/static/img/propeller-1.png b/img/propeller-1.png similarity index 100% rename from static/img/propeller-1.png rename to img/propeller-1.png diff --git a/static/img/propeller-schema.png b/img/propeller-schema.png similarity index 100% rename from static/img/propeller-schema.png rename to img/propeller-schema.png diff --git a/static/img/pwm-1.png b/img/pwm-1.png similarity index 100% rename from static/img/pwm-1.png rename to img/pwm-1.png diff --git a/static/img/rpi-pinout.jpg b/img/rpi-pinout.jpg similarity index 100% rename from static/img/rpi-pinout.jpg rename to img/rpi-pinout.jpg diff --git a/static/img/rss-1.jpeg b/img/rss-1.jpeg similarity index 100% rename from static/img/rss-1.jpeg rename to img/rss-1.jpeg diff --git a/static/img/rss.png b/img/rss.png similarity index 100% rename from static/img/rss.png rename to img/rss.png diff --git a/static/img/self-hosted-notebook-architecture.png b/img/self-hosted-notebook-architecture.png similarity index 100% rename from static/img/self-hosted-notebook-architecture.png rename to img/self-hosted-notebook-architecture.png diff --git a/static/img/self-hosted-notebook-architecture.svg b/img/self-hosted-notebook-architecture.svg similarity index 100% rename from static/img/self-hosted-notebook-architecture.svg rename to img/self-hosted-notebook-architecture.svg diff --git a/static/img/self-hosted-notebook-extension-1.png b/img/self-hosted-notebook-extension-1.png similarity index 100% rename from static/img/self-hosted-notebook-extension-1.png rename to img/self-hosted-notebook-extension-1.png diff --git a/static/img/snapcast-1.png b/img/snapcast-1.png similarity index 100% rename from static/img/snapcast-1.png rename to img/snapcast-1.png diff --git a/static/img/snapcast-2.jpeg b/img/snapcast-2.jpeg similarity index 100% rename from static/img/snapcast-2.jpeg rename to img/snapcast-2.jpeg diff --git a/static/img/standards.png b/img/standards.png similarity index 100% rename from static/img/standards.png rename to img/standards.png diff --git a/static/img/static-thrust-1.png b/img/static-thrust-1.png similarity index 100% rename from static/img/static-thrust-1.png rename to img/static-thrust-1.png diff --git a/static/img/tasker-screen-1.jpeg b/img/tasker-screen-1.jpeg similarity index 100% rename from static/img/tasker-screen-1.jpeg rename to img/tasker-screen-1.jpeg diff --git a/static/img/tasker-screen-2.jpeg b/img/tasker-screen-2.jpeg similarity index 100% rename from static/img/tasker-screen-2.jpeg rename to img/tasker-screen-2.jpeg diff --git a/static/img/tasker-screen-3.jpeg b/img/tasker-screen-3.jpeg similarity index 100% rename from static/img/tasker-screen-3.jpeg rename to img/tasker-screen-3.jpeg diff --git a/static/img/tasker-screen-4.jpeg b/img/tasker-screen-4.jpeg similarity index 100% rename from static/img/tasker-screen-4.jpeg rename to img/tasker-screen-4.jpeg diff --git a/static/img/tasker-screen-5.jpeg b/img/tasker-screen-5.jpeg similarity index 100% rename from static/img/tasker-screen-5.jpeg rename to img/tasker-screen-5.jpeg diff --git a/static/img/tasker-screen-6.jpeg b/img/tasker-screen-6.jpeg similarity index 100% rename from static/img/tasker-screen-6.jpeg rename to img/tasker-screen-6.jpeg diff --git a/static/img/telegram-1.jpg b/img/telegram-1.jpg similarity index 100% rename from static/img/telegram-1.jpg rename to img/telegram-1.jpg diff --git a/static/img/telegram-2.png b/img/telegram-2.png similarity index 100% rename from static/img/telegram-2.png rename to img/telegram-2.png diff --git a/static/img/telegram-3.png b/img/telegram-3.png similarity index 100% rename from static/img/telegram-3.png rename to img/telegram-3.png diff --git a/static/img/telegram-4.png b/img/telegram-4.png similarity index 100% rename from static/img/telegram-4.png rename to img/telegram-4.png diff --git a/static/img/voice-1.jpg b/img/voice-1.jpg similarity index 100% rename from static/img/voice-1.jpg rename to img/voice-1.jpg diff --git a/static/img/voice-assistant-1.png b/img/voice-assistant-1.png similarity index 100% rename from static/img/voice-assistant-1.png rename to img/voice-assistant-1.png diff --git a/static/img/xt60-board.jpg b/img/xt60-board.jpg similarity index 100% rename from static/img/xt60-board.jpg rename to img/xt60-board.jpg diff --git a/static/img/zigbee-zwave-1.jpg b/img/zigbee-zwave-1.jpg similarity index 100% rename from static/img/zigbee-zwave-1.jpg rename to img/zigbee-zwave-1.jpg diff --git a/static/img/zigbee-zwave-2.png b/img/zigbee-zwave-2.png similarity index 100% rename from static/img/zigbee-zwave-2.png rename to img/zigbee-zwave-2.png diff --git a/static/img/zigbee-zwave-3.png b/img/zigbee-zwave-3.png similarity index 100% rename from static/img/zigbee-zwave-3.png rename to img/zigbee-zwave-3.png diff --git a/static/img/zigbee-zwave-4.png b/img/zigbee-zwave-4.png similarity index 100% rename from static/img/zigbee-zwave-4.png rename to img/zigbee-zwave-4.png diff --git a/static/img/zigbee-zwave-5.png b/img/zigbee-zwave-5.png similarity index 100% rename from static/img/zigbee-zwave-5.png rename to img/zigbee-zwave-5.png diff --git a/static/img/zigbee-zwave-6.png b/img/zigbee-zwave-6.png similarity index 100% rename from static/img/zigbee-zwave-6.png rename to img/zigbee-zwave-6.png diff --git a/static/pages/Build-a-bot-to-communicate-with-your-smart-home-over-Telegram.md b/markdown/Build-a-bot-to-communicate-with-your-smart-home-over-Telegram.md similarity index 100% rename from static/pages/Build-a-bot-to-communicate-with-your-smart-home-over-Telegram.md rename to markdown/Build-a-bot-to-communicate-with-your-smart-home-over-Telegram.md diff --git a/static/pages/Build-an-open-source-drone-with-a-Raspberry-Pi-and-Platypush.md b/markdown/Build-an-open-source-drone-with-a-Raspberry-Pi-and-Platypush.md similarity index 100% rename from static/pages/Build-an-open-source-drone-with-a-Raspberry-Pi-and-Platypush.md rename to markdown/Build-an-open-source-drone-with-a-Raspberry-Pi-and-Platypush.md diff --git a/static/pages/Build-custom-voice-assistants.md b/markdown/Build-custom-voice-assistants.md similarity index 100% rename from static/pages/Build-custom-voice-assistants.md rename to markdown/Build-custom-voice-assistants.md diff --git a/static/pages/Build-your-customizable-voice-assistant-with-Platypush.md b/markdown/Build-your-customizable-voice-assistant-with-Platypush.md similarity index 100% rename from static/pages/Build-your-customizable-voice-assistant-with-Platypush.md rename to markdown/Build-your-customizable-voice-assistant-with-Platypush.md diff --git a/static/pages/Build-your-open-source-multi-room-and-multi-provider-sound-server-with-Platypush-Mopidy-and-Snapcast.md b/markdown/Build-your-open-source-multi-room-and-multi-provider-sound-server-with-Platypush-Mopidy-and-Snapcast.md similarity index 100% rename from static/pages/Build-your-open-source-multi-room-and-multi-provider-sound-server-with-Platypush-Mopidy-and-Snapcast.md rename to markdown/Build-your-open-source-multi-room-and-multi-provider-sound-server-with-Platypush-Mopidy-and-Snapcast.md diff --git a/static/pages/Build-your-self-hosted-Evernote.md b/markdown/Build-your-self-hosted-Evernote.md similarity index 100% rename from static/pages/Build-your-self-hosted-Evernote.md rename to markdown/Build-your-self-hosted-Evernote.md diff --git a/static/pages/Create-your-smart-baby-monitor-with-Platypush-and-Tensorflow.md b/markdown/Create-your-smart-baby-monitor-with-Platypush-and-Tensorflow.md similarity index 100% rename from static/pages/Create-your-smart-baby-monitor-with-Platypush-and-Tensorflow.md rename to markdown/Create-your-smart-baby-monitor-with-Platypush-and-Tensorflow.md diff --git a/static/pages/Deliver-articles-to-your-favourite-e-reader-using-Platypush.md b/markdown/Deliver-articles-to-your-favourite-e-reader-using-Platypush.md similarity index 100% rename from static/pages/Deliver-articles-to-your-favourite-e-reader-using-Platypush.md rename to markdown/Deliver-articles-to-your-favourite-e-reader-using-Platypush.md diff --git a/static/pages/Deliver-customized-newsletters-from-RSS-feeds-with-Platypush.md b/markdown/Deliver-customized-newsletters-from-RSS-feeds-with-Platypush.md similarity index 100% rename from static/pages/Deliver-customized-newsletters-from-RSS-feeds-with-Platypush.md rename to markdown/Deliver-customized-newsletters-from-RSS-feeds-with-Platypush.md diff --git a/static/pages/Detect-people-with-a-RaspberryPi-a-thermal-camera-Platypush-and-a-pinch-of-machine-learning.md b/markdown/Detect-people-with-a-RaspberryPi-a-thermal-camera-Platypush-and-a-pinch-of-machine-learning.md similarity index 100% rename from static/pages/Detect-people-with-a-RaspberryPi-a-thermal-camera-Platypush-and-a-pinch-of-machine-learning.md rename to markdown/Detect-people-with-a-RaspberryPi-a-thermal-camera-Platypush-and-a-pinch-of-machine-learning.md diff --git a/static/pages/How-to-build-your-personal-infrastructure-for-data-collection-and-visualization.md b/markdown/How-to-build-your-personal-infrastructure-for-data-collection-and-visualization.md similarity index 100% rename from static/pages/How-to-build-your-personal-infrastructure-for-data-collection-and-visualization.md rename to markdown/How-to-build-your-personal-infrastructure-for-data-collection-and-visualization.md diff --git a/static/pages/One-browser-extension-to-rule-them-all.md b/markdown/One-browser-extension-to-rule-them-all.md similarity index 100% rename from static/pages/One-browser-extension-to-rule-them-all.md rename to markdown/One-browser-extension-to-rule-them-all.md diff --git a/static/pages/Set-up-self-hosted-CI-CD-git-pipelines-with-Platypush.md b/markdown/Set-up-self-hosted-CI-CD-git-pipelines-with-Platypush.md similarity index 100% rename from static/pages/Set-up-self-hosted-CI-CD-git-pipelines-with-Platypush.md rename to markdown/Set-up-self-hosted-CI-CD-git-pipelines-with-Platypush.md diff --git a/static/pages/Transform-a-RaspberryPi-into-a-universal-Zigbee-and-Z-Wave-bridge.md b/markdown/Transform-a-RaspberryPi-into-a-universal-Zigbee-and-Z-Wave-bridge.md similarity index 100% rename from static/pages/Transform-a-RaspberryPi-into-a-universal-Zigbee-and-Z-Wave-bridge.md rename to markdown/Transform-a-RaspberryPi-into-a-universal-Zigbee-and-Z-Wave-bridge.md diff --git a/static/pages/Ultimate-self-hosted-automation-with-Platypush.md b/markdown/Ultimate-self-hosted-automation-with-Platypush.md similarity index 100% rename from static/pages/Ultimate-self-hosted-automation-with-Platypush.md rename to markdown/Ultimate-self-hosted-automation-with-Platypush.md diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index bce1c0d..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -flask -markdown -pygments diff --git a/static/css/blog.css b/static/css/blog.css deleted file mode 100644 index 5726700..0000000 --- a/static/css/blog.css +++ /dev/null @@ -1,50 +0,0 @@ -main .content { - display: flex; - flex-direction: column; - line-height: 1.5em; -} - -main .content p, -main .content ul { - font-family: Avenir, Palatino, charter, Georgia, Cambria, "Times New Roman", Times, serif; - text-align: justify; - overflow-wrap: break-word; - word-break: break-word; -} - -main .content code, .codehilite { - font-size: .85em; -} - -a:hover { - opacity: 0.7; -} - -.description h3 { - font-weight: normal; - opacity: 0.6; - margin: -.5em auto .5em auto; -} - -.published-date { - font-size: 0.75em; - opacity: .75; - margin-bottom: 2em; -} - -@media screen and (max-width: 1024px) { - main .container { - width: 100%; - } -} - -@media screen and (min-width: 1024px) { - main .container { - max-width: 768px; - } -} - -.codehilite { - padding: 0 .5em; - overflow: auto; -} diff --git a/static/css/code.css b/static/css/code.css deleted file mode 100644 index a099275..0000000 --- a/static/css/code.css +++ /dev/null @@ -1,74 +0,0 @@ -pre { line-height: 125%; } -td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; } -span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; } -td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -.codehilite .hll { background-color: #ffffcc } -.codehilite { background: #f8f8f8; } -.codehilite .c { color: #408080; font-style: italic } /* Comment */ -.codehilite .err { border: 1px solid #FF0000 } /* Error */ -.codehilite .k { color: #008000; font-weight: bold } /* Keyword */ -.codehilite .o { color: #666666 } /* Operator */ -.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */ -.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */ -.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */ -.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */ -.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */ -.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */ -.codehilite .gd { color: #A00000 } /* Generic.Deleted */ -.codehilite .ge { font-style: italic } /* Generic.Emph */ -.codehilite .gr { color: #FF0000 } /* Generic.Error */ -.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.codehilite .gi { color: #00A000 } /* Generic.Inserted */ -.codehilite .go { color: #888888 } /* Generic.Output */ -.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.codehilite .gs { font-weight: bold } /* Generic.Strong */ -.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.codehilite .gt { color: #0044DD } /* Generic.Traceback */ -.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.codehilite .kp { color: #008000 } /* Keyword.Pseudo */ -.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.codehilite .kt { color: #B00040 } /* Keyword.Type */ -.codehilite .m { color: #666666 } /* Literal.Number */ -.codehilite .s { color: #BA2121 } /* Literal.String */ -.codehilite .na { color: #7D9029 } /* Name.Attribute */ -.codehilite .nb { color: #008000 } /* Name.Builtin */ -.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -.codehilite .no { color: #880000 } /* Name.Constant */ -.codehilite .nd { color: #AA22FF } /* Name.Decorator */ -.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */ -.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -.codehilite .nf { color: #0000FF } /* Name.Function */ -.codehilite .nl { color: #A0A000 } /* Name.Label */ -.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */ -.codehilite .nv { color: #19177C } /* Name.Variable */ -.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -.codehilite .w { color: #bbbbbb } /* Text.Whitespace */ -.codehilite .mb { color: #666666 } /* Literal.Number.Bin */ -.codehilite .mf { color: #666666 } /* Literal.Number.Float */ -.codehilite .mh { color: #666666 } /* Literal.Number.Hex */ -.codehilite .mi { color: #666666 } /* Literal.Number.Integer */ -.codehilite .mo { color: #666666 } /* Literal.Number.Oct */ -.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */ -.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */ -.codehilite .sc { color: #BA2121 } /* Literal.String.Char */ -.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */ -.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ -.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */ -.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */ -.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -.codehilite .sx { color: #008000 } /* Literal.String.Other */ -.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */ -.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */ -.codehilite .ss { color: #19177C } /* Literal.String.Symbol */ -.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */ -.codehilite .fm { color: #0000FF } /* Name.Function.Magic */ -.codehilite .vc { color: #19177C } /* Name.Variable.Class */ -.codehilite .vg { color: #19177C } /* Name.Variable.Global */ -.codehilite .vi { color: #19177C } /* Name.Variable.Instance */ -.codehilite .vm { color: #19177C } /* Name.Variable.Magic */ -.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/static/css/common.css b/static/css/common.css deleted file mode 100644 index e97dd82..0000000 --- a/static/css/common.css +++ /dev/null @@ -1,107 +0,0 @@ -html { - height: 100%; - font-size: 20px; - font-family: BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial, sans-serif; - font-weight: 400; - text-rendering: optimizeLegibility; -} - -body { - margin: 0; - width: 100%; - height: 100%; -} - -a, a:visited { - color: #555; - border-bottom: 1px dashed #999; - text-decoration: none; -} - -header { - display: flex; - align-items: center; - height: 3em; - padding: 0 .5em; - font-size: .9em; - box-shadow: 1px 3px 3px 0 #bbb; -} - -header a { - color: initial; - opacity: .8; - text-decoration: none; - border-bottom: 0; -} - -header .left a { - display: flex; - align-items: center; - color: initial !important; - opacity: .9; -} - -header a:hover { - opacity: .6; -} - -header .title { - font-family: 'Poppins', sans-serif; - margin-left: .333em; -} - -header .left, -header .right { - display: inline-flex; - align-items: center; - width: 50%; -} - -header .right { - display: inline-flex; - justify-content: right; - text-align: right; - direction: rtl; - opacity: .8; -} - -header .icon { - background-size: 40px !important; - width: 40px; - height: 40px; - display: inline-flex; -} - -header .left .icon { - width: 2.5em; - height: 2.5em; - margin-right: .5em; -} - -header .right .icon { - background: url(/img/rss.png); -} - -header .title { - display: inline-flex; -} - -main { - height: calc(100% - 3em); - overflow: auto; - display: flex; - flex-direction: column; - align-items: center; - 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 deleted file mode 100644 index 07f56f3..0000000 --- a/static/css/home.css +++ /dev/null @@ -1,112 +0,0 @@ -main { - padding: 0; -} - -.articles { - width: 100%; - height: 100%; - display: flex; - flex-wrap: wrap; - overflow: auto; - padding: 0; -} - -.article { - display: block; - width: 100%; - max-height: 80%; - box-shadow: 0 1px 3px 1px #ccc; - overflow: hidden; - text-overflow: ellipsis; - color: black !important; -} - -.article:hover { - box-shadow: 0 1px 4px 3px #989898; - opacity: 1; - border-radius: .5em; -} - -@media screen and (min-width: 767px) { - .article { - max-height: 55%; - } -} - -@media screen and (min-width: 640px) and (max-width: 767px) { - .article { - padding: 0 calc(1em + 7vw); - } -} - -@media screen and (min-width: 768px) and (max-width: 979px) { - .article { - width: 50%; - } -} - -@media screen and (min-width: 980px) and (max-width: 1279px) { - .article { - width: 33.33%; - } -} - -@media screen and (min-width: 1280px) and (max-width: 1599px) { - .article { - width: 25%; - } -} - -@media screen and (min-width: 1600px) { - .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; -} - - -a:hover { - opacity: 0.8; -} - -.description { - color: rgba(0, 0, 0, 0.7); - font-size: .8em; -} - -.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/fonts/Poppins.ttf b/static/fonts/Poppins.ttf deleted file mode 100644 index 8e2c012..0000000 Binary files a/static/fonts/Poppins.ttf and /dev/null differ diff --git a/static/fonts/fira-sans-200.ttf b/static/fonts/fira-sans-200.ttf deleted file mode 100644 index 0feb17a..0000000 Binary files a/static/fonts/fira-sans-200.ttf and /dev/null differ diff --git a/static/fonts/fira-sans-300.ttf b/static/fonts/fira-sans-300.ttf deleted file mode 100644 index 7b416ac..0000000 Binary files a/static/fonts/fira-sans-300.ttf and /dev/null differ diff --git a/static/fonts/fira-sans.css b/static/fonts/fira-sans.css deleted file mode 100644 index 81c55a4..0000000 --- a/static/fonts/fira-sans.css +++ /dev/null @@ -1,14 +0,0 @@ -@font-face { - font-family: 'Fira Sans'; - font-style: normal; - font-weight: 200; - font-display: swap; - src: url(./fira-sans-200.ttf) format('truetype'); -} -@font-face { - font-family: 'Fira Sans'; - font-style: normal; - font-weight: 300; - font-display: swap; - src: url(./fira-sans-300.ttf) format('truetype'); -} diff --git a/static/fonts/poppins.css b/static/fonts/poppins.css deleted file mode 100644 index d90a349..0000000 --- a/static/fonts/poppins.css +++ /dev/null @@ -1,7 +0,0 @@ -@font-face { - font-family: 'Poppins'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(./Poppins.ttf) format('truetype'); -} diff --git a/templates/article.html b/templates/article.html deleted file mode 100644 index 4aa9ebc..0000000 --- a/templates/article.html +++ /dev/null @@ -1,43 +0,0 @@ -{% with title=title or 'Platypush blog', skip_header=skip_header, styles=['/css/blog.css', '/css/code.css'] %} - {% include 'common-head.html' %} -{% endwith %} - -
-
- {% if not skip_header %} -
-

{{ title }}

-
- - {% if description %} -
-

{{ description }}

-
- {% endif %} - - {% if published %} -
- Published - {% if author %} by - {% if author_email %} - - {% endif %} - - {{ author }} - - {% if author_email %} - - {% endif %} - {% endif %} - on {{ published }} -
- {% endif %} - {% endif %} - -
- {{ content | safe }} -
-
-
- -{% include 'common-tail.html' %} diff --git a/templates/common-head.html b/templates/common-head.html deleted file mode 100644 index bc6b3c6..0000000 --- a/templates/common-head.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - {% if styles %} - {% for style in styles %} - - {% endfor %} - {% endif %} - {{ title }} - - - {% if not skip_header %} -
-
- - Logo - - - - Blog - -
- -
- -
-
-
-
- {% endif %} diff --git a/templates/common-tail.html b/templates/common-tail.html deleted file mode 100644 index 308b1d0..0000000 --- a/templates/common-tail.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index 2e9ccb6..0000000 --- a/templates/index.html +++ /dev/null @@ -1,37 +0,0 @@ -{% with title=title or 'Platypush blog', skip_header=False, styles=['/css/home.css'] %} - {% include 'common-head.html' %} -{% endwith %} - -
-
- {% for page in pages %} - -
- {% if page['image'] %} -
- -
- {% endif %} - -
- {{ page['title'] }} -
- - {% if page['published'] %} -
- {{ page['published'].strftime('%b %d, %Y') }} -
- {% endif %} - - {% if page['description'] %} -
- {{ page['description'] }} -
- {% endif %} -
-
- {% endfor %} -
-
- -{% include 'common-tail.html' %}