Compare commits
No commits in common. "main" and "v0.2.19" have entirely different histories.
23 changed files with 115 additions and 214 deletions
|
@ -1,14 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 0.2.35
|
|
||||||
|
|
||||||
- Use _Lora_ font for the article body.
|
|
||||||
|
|
||||||
## 0.2.24
|
|
||||||
|
|
||||||
- Better default fonts - `sans-serif` style for the index and the titles,
|
|
||||||
`serif` for the articles' body.
|
|
||||||
|
|
||||||
## 0.2.19
|
## 0.2.19
|
||||||
|
|
||||||
- Added `short_feed` configuration flag to permanently disable returning the
|
- Added `short_feed` configuration flag to permanently disable returning the
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = "0.2.35"
|
__version__ = '0.2.19'
|
||||||
|
|
106
madblog/app.py
106
madblog/app.py
|
@ -12,11 +12,11 @@ from ._sorters import PagesSorter, PagesSortByTime
|
||||||
|
|
||||||
|
|
||||||
class BlogApp(Flask):
|
class BlogApp(Flask):
|
||||||
_title_header_regex = re.compile(r"^#\s*((\[(.*)\])|(.*))")
|
_title_header_regex = re.compile(r'^#\s*((\[(.*)\])|(.*))')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, template_folder=config.templates_dir, **kwargs)
|
super().__init__(*args, template_folder=config.templates_dir, **kwargs)
|
||||||
self.pages_dir = os.path.join(config.content_dir, "markdown")
|
self.pages_dir = os.path.join(config.content_dir, 'markdown')
|
||||||
self.img_dir = config.default_img_dir
|
self.img_dir = config.default_img_dir
|
||||||
self.css_dir = config.default_css_dir
|
self.css_dir = config.default_css_dir
|
||||||
self.js_dir = config.default_js_dir
|
self.js_dir = config.default_js_dir
|
||||||
|
@ -27,77 +27,73 @@ class BlogApp(Flask):
|
||||||
# `config.content_dir` is treated as the root for markdown files.
|
# `config.content_dir` is treated as the root for markdown files.
|
||||||
self.pages_dir = config.content_dir
|
self.pages_dir = config.content_dir
|
||||||
|
|
||||||
img_dir = os.path.join(config.content_dir, "img")
|
img_dir = os.path.join(config.content_dir, 'img')
|
||||||
if os.path.isdir(img_dir):
|
if os.path.isdir(img_dir):
|
||||||
self.img_dir = os.path.abspath(img_dir)
|
self.img_dir = os.path.abspath(img_dir)
|
||||||
else:
|
else:
|
||||||
self.img_dir = config.content_dir
|
self.img_dir = config.content_dir
|
||||||
|
|
||||||
css_dir = os.path.join(config.content_dir, "css")
|
css_dir = os.path.join(config.content_dir, 'css')
|
||||||
if os.path.isdir(css_dir):
|
if os.path.isdir(css_dir):
|
||||||
self.css_dir = os.path.abspath(css_dir)
|
self.css_dir = os.path.abspath(css_dir)
|
||||||
|
|
||||||
js_dir = os.path.join(config.content_dir, "js")
|
js_dir = os.path.join(config.content_dir, 'js')
|
||||||
if os.path.isdir(js_dir):
|
if os.path.isdir(js_dir):
|
||||||
self.js_dir = os.path.abspath(js_dir)
|
self.js_dir = os.path.abspath(js_dir)
|
||||||
|
|
||||||
fonts_dir = os.path.join(config.content_dir, "fonts")
|
fonts_dir = os.path.join(config.content_dir, 'fonts')
|
||||||
if os.path.isdir(fonts_dir):
|
if os.path.isdir(fonts_dir):
|
||||||
self.fonts_dir = os.path.abspath(fonts_dir)
|
self.fonts_dir = os.path.abspath(fonts_dir)
|
||||||
|
|
||||||
templates_dir = os.path.join(config.content_dir, "templates")
|
templates_dir = os.path.join(config.content_dir, 'templates')
|
||||||
if os.path.isdir(templates_dir):
|
if os.path.isdir(templates_dir):
|
||||||
self.template_folder = os.path.abspath(templates_dir)
|
self.template_folder = os.path.abspath(templates_dir)
|
||||||
|
|
||||||
def get_page_metadata(self, page: str) -> dict:
|
def get_page_metadata(self, page: str) -> dict:
|
||||||
if not page.endswith(".md"):
|
if not page.endswith('.md'):
|
||||||
page = page + ".md"
|
page = page + '.md'
|
||||||
|
|
||||||
md_file = os.path.join(self.pages_dir, page)
|
md_file = os.path.join(self.pages_dir, page)
|
||||||
if not os.path.isfile(md_file):
|
if not os.path.isfile(md_file):
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
metadata = {}
|
metadata = {}
|
||||||
with open(md_file, "r") as f:
|
with open(md_file, 'r') as f:
|
||||||
metadata["uri"] = "/article/" + page[:-3]
|
metadata['uri'] = '/article/' + page[:-3]
|
||||||
|
|
||||||
for line in f:
|
for line in f.readlines():
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not (m := re.match(r"^\[//]: # \(([^:]+):\s*(.*)\)\s*$", line)):
|
if not (m := re.match(r'^\[//]: # \(([^:]+):\s*([^)]+)\)\s*$', line)):
|
||||||
break
|
break
|
||||||
|
|
||||||
if m.group(1) == "published":
|
if m.group(1) == 'published':
|
||||||
metadata[m.group(1)] = datetime.datetime.fromisoformat(
|
metadata[m.group(1)] = datetime.date.fromisoformat(m.group(2))
|
||||||
m.group(2)
|
|
||||||
).date()
|
|
||||||
else:
|
else:
|
||||||
metadata[m.group(1)] = m.group(2)
|
metadata[m.group(1)] = m.group(2)
|
||||||
|
|
||||||
if not metadata.get("title"):
|
if not metadata.get('title'):
|
||||||
# If the `title` header isn't available in the file,
|
# If the `title` header isn't available in the file,
|
||||||
# infer it from the first line of the file
|
# infer it from the first line of the file
|
||||||
with open(md_file, "r") as f:
|
with open(md_file, 'r') as f:
|
||||||
header = ""
|
header = ''
|
||||||
for line in f.readlines():
|
for line in f.readlines():
|
||||||
header = line
|
header = line
|
||||||
break
|
break
|
||||||
|
|
||||||
metadata["title_inferred"] = True
|
metadata['title_inferred'] = True
|
||||||
m = self._title_header_regex.search(header)
|
m = self._title_header_regex.search(header)
|
||||||
if m:
|
if m:
|
||||||
metadata["title"] = m.group(3) or m.group(1)
|
metadata['title'] = m.group(3) or m.group(1)
|
||||||
else:
|
else:
|
||||||
metadata["title"] = os.path.basename(md_file)
|
metadata['title'] = os.path.basename(md_file)
|
||||||
|
|
||||||
if not metadata.get("published"):
|
if not metadata.get('published'):
|
||||||
# If the `published` header isn't available in the file,
|
# If the `published` header isn't available in the file,
|
||||||
# infer it from the file's creation date
|
# infer it from the file's creation date
|
||||||
metadata["published"] = datetime.date.fromtimestamp(
|
metadata['published'] = datetime.date.fromtimestamp(os.stat(md_file).st_ctime)
|
||||||
os.stat(md_file).st_ctime
|
metadata['published_inferred'] = True
|
||||||
)
|
|
||||||
metadata["published_inferred"] = True
|
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
@ -106,42 +102,37 @@ class BlogApp(Flask):
|
||||||
page: str,
|
page: str,
|
||||||
title: Optional[str] = None,
|
title: Optional[str] = None,
|
||||||
skip_header: bool = False,
|
skip_header: bool = False,
|
||||||
skip_html_head: bool = False,
|
skip_html_head: bool = False
|
||||||
):
|
):
|
||||||
if not page.endswith(".md"):
|
if not page.endswith('.md'):
|
||||||
page = page + ".md"
|
page = page + '.md'
|
||||||
|
|
||||||
metadata = self.get_page_metadata(page)
|
metadata = self.get_page_metadata(page)
|
||||||
# Don't duplicate the page title if it's been inferred
|
# Don't duplicate the page title if it's been inferred
|
||||||
if not (title or metadata.get("title_inferred")):
|
if not (title or metadata.get('title_inferred')):
|
||||||
title = metadata.get("title", config.title)
|
title = metadata.get('title', config.title)
|
||||||
|
|
||||||
with open(os.path.join(self.pages_dir, page), "r") as f:
|
with open(os.path.join(self.pages_dir, page), 'r') as f:
|
||||||
return render_template(
|
return render_template(
|
||||||
"article.html",
|
'article.html',
|
||||||
config=config,
|
config=config,
|
||||||
title=title,
|
title=title,
|
||||||
image=metadata.get("image"),
|
image=metadata.get('image'),
|
||||||
description=metadata.get("description"),
|
description=metadata.get('description'),
|
||||||
author=(
|
author=(
|
||||||
re.match(r"(.+?)\s+<([^>]+>)", metadata["author"])[1]
|
re.match(r'(.+?)\s+<([^>]+>)', metadata['author'])[1]
|
||||||
if "author" in metadata
|
if 'author' in metadata else None
|
||||||
else None
|
|
||||||
),
|
),
|
||||||
author_email=(
|
author_email=(
|
||||||
re.match(r"(.+?)\s+<([^>]+)>", metadata["author"])[2]
|
re.match(r'(.+?)\s+<([^>]+)>', metadata['author'])[2]
|
||||||
if "author" in metadata
|
if 'author' in metadata else None
|
||||||
else None
|
|
||||||
),
|
),
|
||||||
published=(
|
published=(
|
||||||
metadata["published"].strftime("%b %d, %Y")
|
metadata['published'].strftime('%b %d, %Y')
|
||||||
if metadata.get("published")
|
if metadata.get('published') and not metadata.get('published_inferred')
|
||||||
and not metadata.get("published_inferred")
|
|
||||||
else None
|
else None
|
||||||
),
|
),
|
||||||
content=markdown(
|
content=markdown(f.read(), extensions=['fenced_code', 'codehilite', MarkdownLatex()]),
|
||||||
f.read(), extensions=["fenced_code", "codehilite", "tables", MarkdownLatex()]
|
|
||||||
),
|
|
||||||
skip_header=skip_header,
|
skip_header=skip_header,
|
||||||
skip_html_head=skip_html_head,
|
skip_html_head=skip_html_head,
|
||||||
)
|
)
|
||||||
|
@ -154,25 +145,26 @@ class BlogApp(Flask):
|
||||||
sorter: Type[PagesSorter] = PagesSortByTime,
|
sorter: Type[PagesSorter] = PagesSortByTime,
|
||||||
reverse: bool = True,
|
reverse: bool = True,
|
||||||
) -> List[Tuple[int, dict]]:
|
) -> List[Tuple[int, dict]]:
|
||||||
pages_dir = app.pages_dir.rstrip("/")
|
pages_dir = app.pages_dir.rstrip('/')
|
||||||
pages = [
|
pages = [
|
||||||
{
|
{
|
||||||
"path": os.path.join(root[len(pages_dir) + 1 :], f),
|
'path': os.path.join(root[len(pages_dir)+1:], f),
|
||||||
"folder": root[len(pages_dir) + 1 :],
|
'folder': root[len(pages_dir)+1:],
|
||||||
"content": (
|
'content': (
|
||||||
self.get_page(
|
self.get_page(
|
||||||
os.path.join(root, f),
|
os.path.join(root, f),
|
||||||
skip_header=skip_header,
|
skip_header=skip_header,
|
||||||
skip_html_head=skip_html_head,
|
skip_html_head=skip_html_head,
|
||||||
)
|
)
|
||||||
if with_content
|
if with_content else ''
|
||||||
else ""
|
),
|
||||||
|
**self.get_page_metadata(
|
||||||
|
os.path.join(root[len(pages_dir)+1:], f)
|
||||||
),
|
),
|
||||||
**self.get_page_metadata(os.path.join(root[len(pages_dir) + 1 :], f)),
|
|
||||||
}
|
}
|
||||||
for root, _, files in os.walk(pages_dir, followlinks=True)
|
for root, _, files in os.walk(pages_dir, followlinks=True)
|
||||||
for f in files
|
for f in files
|
||||||
if f.endswith(".md")
|
if f.endswith('.md')
|
||||||
]
|
]
|
||||||
|
|
||||||
sorter_func = sorter(pages)
|
sorter_func = sorter(pages)
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from urllib.parse import urljoin
|
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
jsonify,
|
jsonify,
|
||||||
|
@ -117,12 +115,8 @@ def article_route(article: str):
|
||||||
|
|
||||||
@app.route("/rss", methods=["GET"])
|
@app.route("/rss", methods=["GET"])
|
||||||
def rss_route():
|
def rss_route():
|
||||||
short_description = "short" in request.args or config.short_feed
|
pages = app.get_pages(with_content=True, skip_header=True, skip_html_head=True)
|
||||||
pages = app.get_pages(
|
short_description = "short" in request.args
|
||||||
with_content=not short_description,
|
|
||||||
skip_header=True,
|
|
||||||
skip_html_head=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
"""<?xml version="1.0" encoding="UTF-8" ?>
|
"""<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
@ -155,36 +149,32 @@ def rss_route():
|
||||||
),
|
),
|
||||||
items="\n\n".join(
|
items="\n\n".join(
|
||||||
[
|
[
|
||||||
(
|
"""
|
||||||
"""
|
|
||||||
<item>
|
<item>
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
<link>{base_link}{link}</link>
|
<link>{base_link}{link}</link>
|
||||||
<pubDate>{published}</pubDate>
|
<pubDate>{published}</pubDate>"""
|
||||||
<description><![CDATA[{content}]]></description>
|
+ (
|
||||||
<media:content medium="image" url="{image}" width="200" height="150" />
|
"<description><![CDATA[{content}]]></description>"
|
||||||
|
if not config.short_feed
|
||||||
|
else ""
|
||||||
|
)
|
||||||
|
+ """
|
||||||
|
<media:content medium="image" url="{base_link}{image}" width="200" height="150" />
|
||||||
</item>
|
</item>
|
||||||
"""
|
""".format(
|
||||||
).format(
|
|
||||||
base_link=config.link,
|
base_link=config.link,
|
||||||
title=page.get("title", "[No Title]"),
|
title=page.get("title", "[No Title]"),
|
||||||
link=page.get("uri", ""),
|
link=page.get("uri", ""),
|
||||||
published=(
|
published=page["published"].strftime(
|
||||||
page["published"].strftime("%a, %d %b %Y %H:%M:%S GMT")
|
"%a, %d %b %Y %H:%M:%S GMT"
|
||||||
if "published" in page
|
)
|
||||||
else ""
|
if "published" in page
|
||||||
),
|
else "",
|
||||||
content=(
|
content=page.get("description", "")
|
||||||
page.get("description", "")
|
if short_description
|
||||||
if short_description
|
else page.get("content", ""),
|
||||||
else page.get("content", "")
|
image=page.get("image", ""),
|
||||||
),
|
|
||||||
image=(
|
|
||||||
urljoin(config.link, page["image"])
|
|
||||||
if page.get("image")
|
|
||||||
and not re.search(r"^https?://", page["image"])
|
|
||||||
else page.get("image", "")
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
for _, page in pages
|
for _, page in pages
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,31 +2,22 @@ main .content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
font-size: 0.95em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main .content p,
|
main .content p,
|
||||||
main .content ul,
|
main .content ul {
|
||||||
main .content ol {
|
|
||||||
font-family: Lora, "Palatino Linotype", "Book Antiqua", "New York", "DejaVu serif", serif;
|
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
line-height: 1.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main .content code, .codehilite {
|
main .content code, .codehilite {
|
||||||
font-size: 0.9em;
|
font-size: .85em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 767px) {
|
@media screen and (max-width: 767px) {
|
||||||
main {
|
main {
|
||||||
font-size: 0.95em;
|
font-size: 0.9em;
|
||||||
padding: 0.25em 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
main p {
|
|
||||||
padding: 0.25em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +45,13 @@ a:hover {
|
||||||
|
|
||||||
@media screen and (min-width: 1024px) {
|
@media screen and (min-width: 1024px) {
|
||||||
main .container {
|
main .container {
|
||||||
max-width: 40em;
|
max-width: 35em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.codehilite {
|
.codehilite {
|
||||||
padding: 0 .5em;
|
padding: 0 .5em;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-image-container {
|
.main-image-container {
|
||||||
|
|
|
@ -2,8 +2,7 @@ html {
|
||||||
height: -webkit-fill-available;
|
height: -webkit-fill-available;
|
||||||
height: -moz-available;
|
height: -moz-available;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
/* font-family: Lora, "Palatino Linotype", "Book Antiqua", "New York", "DejaVu serif", serif; */
|
font-family: -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Open Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +95,18 @@ main {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 0.25em;
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
main {
|
||||||
|
padding: 0 0.75em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
main {
|
||||||
|
padding: 0 2em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -109,10 +119,6 @@ h2 {
|
||||||
line-height: 1.1em;
|
line-height: 1.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
|
||||||
font-family: -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Open Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: .65em;
|
font-size: .65em;
|
||||||
|
@ -123,7 +129,3 @@ footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: 1px -2px 2px 0 #bbb;
|
box-shadow: 1px -2px 2px 0 #bbb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.index {
|
|
||||||
font-family: -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Open Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,36 +0,0 @@
|
||||||
/* lora-regular - latin */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lora';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
src: url('/fonts/Lora-Regular.eot'); /* IE9 Compat Modes */
|
|
||||||
src: local('Lora'), local('Lora-Regular'),
|
|
||||||
url('/fonts/Lora-Regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
|
||||||
url('/fonts/Lora-Regular.woff2') format('woff2'), /* Super Modern Browsers */
|
|
||||||
url('/fonts/Lora-Regular.woff') format('woff'), /* Modern Browsers */
|
|
||||||
url('/fonts/Lora-Regular.ttf') format('truetype'); /* Safari, Android, iOS */
|
|
||||||
}
|
|
||||||
/* lora-700 - latin */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lora';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
src: url('/fonts/Lora-Bold.eot'); /* IE9 Compat Modes */
|
|
||||||
src: local('Lora Bold'), local('Lora-Bold'),
|
|
||||||
url('/fonts/Lora-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
|
||||||
url('/fonts/Lora-Bold.woff2') format('woff2'), /* Super Modern Browsers */
|
|
||||||
url('/fonts/Lora-Bold.woff') format('woff'), /* Modern Browsers */
|
|
||||||
url('/fonts/Lora-Bold.ttf') format('truetype'); /* Safari, Android, iOS */
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lora';
|
|
||||||
font-style: italic;
|
|
||||||
font-weight: 400;
|
|
||||||
src: url('/fonts/Lora-Italic.eot'); /* IE9 Compat Modes */
|
|
||||||
src: local('Lora Italic'), local('Lora-Italic'),
|
|
||||||
url('/fonts/Lora-Italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
|
||||||
url('/fonts/Lora-Italic.woff2') format('woff2'), /* Super Modern Browsers */
|
|
||||||
url('/fonts/Lora-Italic.woff') format('woff'), /* Modern Browsers */
|
|
||||||
url('/fonts/Lora-Italic.ttf') format('truetype'); /* Safari, Android, iOS */
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
<!-- RSS feed -->
|
<!-- RSS feed -->
|
||||||
<link rel="alternate" type="application/rss+xml" title="{{ config.title }}" href="/rss" />
|
<link rel="alternate" type="application/rss+xml" title="{{ config.title }}" href="/rss" />
|
||||||
<!-- Fonts & Styles -->
|
<!-- Fonts & Styles -->
|
||||||
<link rel="stylesheet" href="/fonts/lora.css">
|
|
||||||
<link rel="stylesheet" href="/fonts/poppins.css">
|
<link rel="stylesheet" href="/fonts/poppins.css">
|
||||||
<link rel="stylesheet" href="/fonts/fira-sans.css">
|
<link rel="stylesheet" href="/fonts/fira-sans.css">
|
||||||
<link rel="stylesheet" href="/css/common.css">
|
<link rel="stylesheet" href="/css/common.css">
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
[project]
|
|
||||||
name = "madblog"
|
|
||||||
description = "A general-purpose framework for automation"
|
|
||||||
dynamic = ["version", "dependencies", "optional-dependencies", "entry-points", "license"]
|
|
||||||
authors = [
|
|
||||||
{name = "Fabio Manganiello", email = "fabio@manganiello.tech"},
|
|
||||||
]
|
|
||||||
|
|
||||||
classifiers=[
|
|
||||||
"Topic :: Utilities",
|
|
||||||
"License :: OSI Approved :: MIT License",
|
|
||||||
"Development Status :: 4 - Beta",
|
|
||||||
]
|
|
||||||
|
|
||||||
readme = "README.md"
|
|
||||||
requires-python = '>= 3.8'
|
|
||||||
keywords = ["blog", "markdown"]
|
|
||||||
|
|
||||||
[tool.setuptools.dynamic]
|
|
||||||
version = {attr = "madblog.__version__"}
|
|
||||||
dependencies = {file = "requirements.txt"}
|
|
||||||
|
|
||||||
[project.scripts]
|
|
||||||
madblog = 'madblog:__main__'
|
|
||||||
|
|
||||||
[tool.bumpversion]
|
|
||||||
current_version = "0.2.35"
|
|
||||||
commit = true
|
|
||||||
tag = true
|
|
||||||
|
|
||||||
[[tool.bumpversion.files]]
|
|
||||||
filename = "madblog/__init__.py"
|
|
||||||
|
|
||||||
[[tool.bumpversion.files]]
|
|
||||||
filename = "setup.py"
|
|
7
setup.cfg
Normal file
7
setup.cfg
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[bumpversion]
|
||||||
|
current_version = 0.2.19
|
||||||
|
commit = True
|
||||||
|
tag = True
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
description-file = README.md
|
39
setup.py
39
setup.py
|
@ -1,41 +1,42 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
|
||||||
def readfile(file):
|
def readfile(file):
|
||||||
with open(file, "r") as f:
|
with open(file, 'r') as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="madblog",
|
name='madblog',
|
||||||
version="0.2.35",
|
version='0.2.19',
|
||||||
author="Fabio Manganiello",
|
author='Fabio Manganiello',
|
||||||
author_email="info@fabiomanganiello.com",
|
author_email='info@fabiomanganiello.com',
|
||||||
description="A minimal platform for Markdown-based blogs",
|
description='A minimal platform for Markdown-based blogs',
|
||||||
license="MIT",
|
license='MIT',
|
||||||
python_requires=">= 3.8",
|
python_requires='>= 3.8',
|
||||||
keywords="blog markdown",
|
keywords='blog markdown',
|
||||||
url="https://git.platypush.tech/blacklight/madblog",
|
url='https://git.platypush.tech/blacklight/madblog',
|
||||||
packages=find_packages(include=["madblog"]),
|
packages=find_packages(include=['madblog']),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": [
|
'console_scripts': [
|
||||||
"madblog=madblog.cli:run",
|
'madblog=madblog.cli:run',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
long_description=readfile("README.md"),
|
long_description=readfile('README.md'),
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type='text/markdown',
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Topic :: Utilities",
|
"Topic :: Utilities",
|
||||||
"License :: OSI Approved :: MIT License",
|
"License :: OSI Approved :: MIT License",
|
||||||
"Development Status :: 4 - Beta",
|
"Development Status :: 4 - Beta",
|
||||||
],
|
],
|
||||||
install_requires=[
|
install_requires=[
|
||||||
"flask",
|
'flask',
|
||||||
"markdown",
|
'markdown',
|
||||||
"pygments",
|
'pygments',
|
||||||
"pyyaml",
|
'pyyaml',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue