210 lines
5.6 KiB
Python
Executable file
210 lines
5.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
""" Adds a new blog """
|
|
|
|
import os
|
|
import random
|
|
import subprocess
|
|
import sys
|
|
|
|
import markdown # type: ignore
|
|
from bs4 import BeautifulSoup as bs # type: ignore
|
|
|
|
try:
|
|
import readline
|
|
except ImportError:
|
|
readline = 0 # type: ignore
|
|
|
|
del readline
|
|
|
|
CHARACTER_MAP = {
|
|
"/": "_",
|
|
" ": "-",
|
|
"?": "_",
|
|
"#": "_",
|
|
"\\": "_",
|
|
"@": "-",
|
|
"&": "-",
|
|
"=": "_",
|
|
"+": "-",
|
|
"<": "",
|
|
">": "",
|
|
"[": "",
|
|
"]": "",
|
|
"(": "",
|
|
")": "",
|
|
"'": "-",
|
|
}
|
|
|
|
MD_EXTENSIONS = [
|
|
"markdown.extensions.abbr",
|
|
"markdown.extensions.def_list",
|
|
"markdown.extensions.fenced_code",
|
|
"markdown.extensions.footnotes",
|
|
"markdown.extensions.md_in_html",
|
|
"markdown.extensions.tables",
|
|
"markdown.extensions.admonition",
|
|
"markdown.extensions.sane_lists",
|
|
"markdown.extensions.toc",
|
|
"markdown.extensions.wikilinks",
|
|
"pymdownx.betterem",
|
|
"pymdownx.caret",
|
|
"pymdownx.magiclink",
|
|
"pymdownx.mark",
|
|
"pymdownx.tilde",
|
|
]
|
|
|
|
|
|
BLOG_MARKDOWN_TEMPLATE = """# %s
|
|
|
|
<div style="text-align: center;" aria-hidden="true">
|
|
%s | <a href="..">back</a> | <a href="/">home</a> | <a href="/git">git</a>
|
|
</div>
|
|
|
|
<hr/>
|
|
|
|
%s"""
|
|
|
|
HTML_HEADER = """<head>
|
|
<meta charset="UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Ari::web -> OldBlog</title>
|
|
|
|
<meta property="og:type" content="website">
|
|
|
|
<meta name="theme-color" content="#262220">
|
|
<meta name="color-scheme" content="dark">
|
|
|
|
<meta name="keywords" content="website webdev linux programming ari terminal dark blog javascript opensource free">
|
|
<meta name="robots" content="follow"/>
|
|
|
|
<link rel="stylesheet" href="/styles/styles.css"/>"""
|
|
|
|
BLOG_HTML_TEMPLATE = f"""<!DOCTYPE html>
|
|
<html lang="en">
|
|
{HTML_HEADER}
|
|
<meta name="description" content="Blog on %s - %s">
|
|
</head>
|
|
<body>
|
|
<div>
|
|
%s
|
|
</div>
|
|
</body>
|
|
</html>
|
|
<!-- this is automatically generated by scripts/add_blog -->"""
|
|
|
|
HOME_PAGE_HTML_TEMPLATE = f"""<!DOCTYPE html>
|
|
<html lang="en">
|
|
{HTML_HEADER}
|
|
<meta name="description" content="My old blog page">
|
|
</head>
|
|
<body>
|
|
<h1>My old blogs (please use <a href="https://blog.ari.lt/">this page</a> instead)</h1>
|
|
<div style="text-align: center !important;" aria-hidden="true">
|
|
<p>last blog on: <code>%s</code> | latest blog: <a href="%s">%s</a> | <a href="/git">source code</a></p>
|
|
<hr/>
|
|
</div>
|
|
<div>
|
|
%s
|
|
</div>
|
|
</body>
|
|
</html>
|
|
<!-- this is automatically generated by scripts/add_blog -->"""
|
|
|
|
|
|
def sanitise_title(title: str) -> str:
|
|
"""
|
|
This function takes a title and uses CHARACTER_MAP to
|
|
make the title path and netlify compatiple
|
|
"""
|
|
final = title
|
|
|
|
for character, replacement in CHARACTER_MAP.items():
|
|
final = final.replace(character, replacement)
|
|
|
|
return f"{final[0:35]}_{random.randint(-10_000_000_000, 10_000_000_000)}".capitalize().strip()
|
|
|
|
|
|
def main() -> int:
|
|
"""Main function"""
|
|
|
|
open("/tmp/blog.md", "w", encoding="utf-8").close()
|
|
|
|
blog_title = input("Blog title: ").strip()
|
|
blog_title = blog_title[0].upper() + blog_title[1:]
|
|
|
|
sanitised_blog_title = sanitise_title(blog_title)
|
|
|
|
input(
|
|
"""Now this script will open your editor, enter the markdown you want
|
|
in your blog there. press enter to continue"""
|
|
)
|
|
|
|
if os.getenv("EDITOR"):
|
|
os.system(f"{os.getenv('EDITOR')} /tmp/blog.md")
|
|
else:
|
|
os.system(f"{input('What editor should I use?: ') or 'ed'} /tmp/blog.md")
|
|
|
|
with open("/tmp/blog.md", "r", encoding="utf-8") as blog_markdown:
|
|
blog_content = blog_markdown.read()
|
|
|
|
date = subprocess.check_output(["date", "+%F %T %Z"]).decode().rstrip("\n")
|
|
content = BLOG_MARKDOWN_TEMPLATE % (blog_title, date, blog_content)
|
|
with open(
|
|
f"./blogs/{sanitised_blog_title}.html", "w", encoding="utf-8"
|
|
) as blog_html:
|
|
blog_html.write(
|
|
BLOG_HTML_TEMPLATE
|
|
% (
|
|
date,
|
|
blog_title,
|
|
markdown.markdown(
|
|
content, output_format="html", extensions=MD_EXTENSIONS
|
|
)
|
|
.replace("<h1>", "<h2>")
|
|
.replace("<h1/>", "<h2/>"),
|
|
)
|
|
)
|
|
|
|
with open("./index.md", "a", encoding="utf-8") as home_page_markdown:
|
|
home_page_markdown.write(
|
|
f"\n* [{blog_title}](/blogs/{sanitised_blog_title}.html)"
|
|
)
|
|
|
|
with open("./index.html", "w", encoding="utf-8") as home_page:
|
|
with open("./index.md", "r", encoding="utf-8") as home_page_md:
|
|
home_page.write(
|
|
HOME_PAGE_HTML_TEMPLATE
|
|
% (
|
|
date,
|
|
f"/blogs/{sanitised_blog_title}.html",
|
|
blog_title,
|
|
markdown.markdown(home_page_md.read(), extensions=MD_EXTENSIONS),
|
|
)
|
|
)
|
|
|
|
# Pretify the blog and the index page
|
|
with open("./index.html", "r", encoding="utf-8") as home_page:
|
|
index_page = home_page.read()
|
|
|
|
with open("./index.html", "w", encoding="utf-8") as home_page:
|
|
soup = bs(index_page, features="lxml")
|
|
home_page.write(soup.prettify())
|
|
|
|
with open(
|
|
f"./blogs/{sanitised_blog_title}.html", "r", encoding="utf-8"
|
|
) as blog_html:
|
|
blog_page = blog_html.read()
|
|
|
|
with open(
|
|
f"./blogs/{sanitised_blog_title}.html", "w", encoding="utf-8"
|
|
) as blog_html:
|
|
soup = bs(blog_page, features="lxml")
|
|
blog_html.write(soup.prettify())
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
assert main.__annotations__.get("return") is int, "main() should return an integer"
|
|
sys.exit(main())
|