first version

This commit is contained in:
Ville Rantanen
2021-06-01 10:56:20 +03:00
commit 91355cf05b
11 changed files with 565 additions and 0 deletions

255
mirva/mirva.py Executable file
View File

@@ -0,0 +1,255 @@
#!/usr/bin/env python3
import configparser
import os
import re
import shutil
import subprocess
from argparse import ArgumentParser
class Mirva:
def __init__(self):
self.resource_src = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "resources"
)
self.resource_dir = ".template"
self.config_file = os.path.join(self.resource_dir, "config")
self.get_options()
os.chdir(self.options.folder)
self.write_resources()
self.file_list = self.get_files()
if self.options.config or not os.path.exists(self.config_file):
self.create_config()
print("Exiting. Check config.")
return
self.get_config()
self.create_posts()
self.write_index()
self.write_mediums()
def create_config(self):
print("Creating config: {}".format(os.path.join(self.options.folder,self.config_file)))
config = configparser.ConfigParser()
config.read(self.config_file)
if not "SITE" in config:
config["SITE"] = {
"title": "",
"sub_title": "",
"intro": "",
}
for f in self.file_list:
if not f in config:
config[f] = {"title": f, "description": ""}
with open(self.config_file, "wt") as fp:
config.write(fp)
def create_posts(self):
self.posts = []
for f in self.file_list:
if not f in self.config:
post = self.get_post(f, f, "")
else:
post = self.get_post(
f, self.config[f]["title"], self.config[f]["description"]
)
self.posts.append(post)
def get_config(self):
self.config = configparser.ConfigParser()
self.config.read(self.config_file)
def get_files(self):
image_match = re.compile(".*\.jpg$|.*\.jpeg$|.*\.png$|.*\.gif$|.*\.tif$", re.I)
files = []
for f in sorted(os.listdir(".")):
if f.startswith("."):
continue
if not image_match.match(f):
continue
files.append(f)
return files
def get_options(self):
parser = ArgumentParser()
#parser.add_argument("-v", default=False, action="store_true")
parser.add_argument(
"--config", default=False, action="store_true", help="Write config and exit"
)
parser.add_argument(
"folder",
type=str,
default=".",
nargs="?",
help="Folder for gallery",
)
self.options = parser.parse_args()
def get_index(self, page_title, sub_title, intro, posts):
return """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Design by TEMPLATED
http://templated.co
Released for free under the Creative Commons Attribution License
Name : Green Forest
Description: A two-column, fixed-width design with dark color scheme.
Version : 1.0
Released : 20110306
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>{page_title}</title>
<link href="{resource}/style.css" rel="stylesheet" type="text/css" media="screen" />
<script>
function r(f){{/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}}
r(function(){{
create_nav();
}});
function create_nav() {{
let navis = document.getElementsByClassName("navigation");
for (let i = 0; i<navis.length; i++) {{
if (navis[i-1]) {{
navis[i].appendChild(create_button("up", navis[i-1]));
}} else {{
navis[i].appendChild(create_button("up", document.body));
}}
if (navis[i+1]) {{
navis[i].appendChild(create_button("down", navis[i+1]));
}}
}}
}}
function create_button(direction, to) {{
let container = document.createElement('div');
container.classList.add("float_" + direction);
let button = document.createElement('img');
button.src = "{resource}/arrow_" + direction + ".png";
button.classList.add("navigation_button");
button.onclick = function(){{
to.parentElement.scrollIntoView({{behavior: "smooth"}});
}};
container.appendChild(button);
return container
}}
</script>
</head>
<body>
<div id="wrapper">
<div id="header">
<div id="logo">
<h1 id="page_title">{page_title}</h1>
<p>{sub_title}</a></p>
</div>
</div>
<!-- end #header -->
<div id="page">
<div id="page-bgtop">
<div id="page-bgbtm">
<div id="content">
<div class="post">
<div class="entry">
{intro}
</div>
</div>
{posts}
<div style="clear: both;">&nbsp;</div>
</div>
<!-- end #content -->
<div style="clear: both;">&nbsp;</div>
</div>
</div>
<!-- end #page -->
</div>
</body>
</html>""".format(
page_title=page_title,
sub_title=sub_title,
intro=intro,
posts="\n".join(posts),
resource=self.resource_dir,
)
def get_post(self, image, title, content):
return """
<div class="post">
<div class="navigation"></div>
<div class=center><a href="{image}"><img class=post_image src=".med/{image}.jpg"></a></div>
<p class="meta"><span class="date">{title}</span></p>
<div style="clear: both;">&nbsp;</div>
<div class="entry">{content}</div>
</div>""".format(
image=image, title=title, content=content
)
def write_index(self):
with open("index.html", "wt") as fp:
fp.write(
self.get_index(
self.config["SITE"]["title"],
self.config["SITE"]["sub_title"],
self.config["SITE"]["intro"],
self.posts,
)
)
def write_resources(self):
try:
os.makedirs(self.resource_dir)
except Exception:
pass
for f in ("style.css", "arrow_up.png", "arrow_down.png", "banner.jpg"):
shutil.copy(
os.path.join(self.resource_src, f), os.path.join(self.resource_dir, f)
)
def write_mediums(self):
try:
os.makedirs(".med")
except Exception:
pass
# TODO: config image res
# TODO opts: force recreation
r = 850
force = False
for f in self.file_list:
res = "{:d}x{:d}>".format(r, r)
outfile = os.path.join(".med", "{}.jpg".format(f))
if not os.path.exists(outfile) or force:
convargs = [
"convert",
"-define",
"jpeg:size={}x{}".format(r, r),
"{}[0]".format(f),
"-background",
"white",
"-flatten",
"-resize",
res,
"-quality",
"85",
outfile,
]
subprocess.call(convargs)