feat: add script source files
Diff
requirements.txt | 13 ++++++-
src/filters.py | 47 +++++++++++++++++++++-
src/livejrnl.py | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 183 insertions(+)
@@ -0,0 +1,13 @@
arrow==1.2.3
beautifulsoup4==4.11.2
jinja-markdown==1.210911
Jinja2==3.1.2
jinja2-time==0.2.0
Markdown==3.4.1
MarkupSafe==2.1.2
Pygments==2.14.0
pymdown-extensions==9.9.2
python-dateutil==2.8.2
six==1.16.0
soupsieve==2.3.2.post1
strip-markdown==1.3
@@ -0,0 +1,47 @@
import strip_markdown
from datetime import datetime
import markdown
class TemplateFilters():
def str_to_datetime(value: str, format: str = "%a, %d %b %Y %H:%M:%S %z", dt_offset="+0100") -> str:
Formats a Jrnl date to the desired date string.
Keyword arguments:
value -- the string to format
format -- the format to format the string to
dt_offset -- the timezone offset to use for DateTime formatting
extracted_date: datetime = datetime.strptime(
value + dt_offset, "%Y-%m-%d %H:%M%z")
return extracted_date.strftime(format)
def strip_markdown(value: str) -> str:
Strips Markdown formatting from a string
Keyword arguments:
value -- the string to strip formatting from
return strip_markdown.strip_markdown(value)
def strip_entry_tag(value: str) -> str:
Removes the first character from a tag string.
Keyword arguments:
value -- the string to strip the tag from
return value[1:]
def markdown_to_html(value: str) -> str:
Formats Markdown as HTML
Keyword arguments:
value -- the string to format as HTML
return markdown.markdown(value)
@@ -0,0 +1,123 @@
from argparse import ArgumentParser
import subprocess
import json
from jinja2 import Environment, Template, FileSystemLoader
from filters import TemplateFilters
from pathlib import Path
def parse_args() -> dict:
parser: ArgumentParser = ArgumentParser(
prog="LiveJrnl",
description="Renders a Jrnl journal as a static site."
)
parser.add_argument("-t", "--template", type=str,
help="the template file to use to build the output", required=True)
parser.add_argument("-o", "--output", type=str,
help="the output file to write to", required=True)
parser.add_argument("-x", "--cutoff", type=int,
help="the maximum number of items to render", default=-1)
parser.add_argument("-c", "--config", type=str,
help="the configuration file to use for building your journal")
args: dict = parser.parse_args()
return args
def get_journal() -> dict:
json_data: str = subprocess.getoutput("jrnl --format json")
return json.loads(json_data)
def get_default_config() -> dict:
default_config: dict = {
"title": "Ashley Robin's Journal",
"base_url": "https://localhost",
"description": "Write a bit about your website here.",
"author": "Ashley Robin",
"author_link": "https://localhost/arobin",
"year": "2023",
"language": "en",
"rss_language": "en-gb"
}
return default_config
def load_config(args: dict) -> str:
Keyword arguments:
args -- arguments passed from parse_args()
if args.config is None:
return get_default_config()
else:
with open(args.config, 'r') as config_file:
data = config_file.read()
return json.loads(data)
def generate_from_template(template: str, loaded_config: str) -> str:
Keyword arguments:
template -- the path to the template to use for output
loaded_config -- a dictionary of extra information to render
template_path: Path = Path(template)
if template_path.exists():
jrnl_json: dict = get_journal()
environment: Environment = Environment(loader=FileSystemLoader(template_path.parent), extensions=[
'jinja2_time.TimeExtension', 'jinja_markdown.MarkdownExtension'])
environment.filters['datetime'] = TemplateFilters.str_to_datetime
environment.filters['md2html'] = TemplateFilters.markdown_to_html
environment.filters['tagstrip'] = TemplateFilters.strip_entry_tag
loaded_template: Template = environment.get_template(
template_path.name)
return loaded_template.render(jrnl_json, config=loaded_config)
return str()
def remove_empty_lines(string: str) -> str:
Keyword arguments:
string -- the string to clean up
return "".join([s for s in string.splitlines(True) if s.strip()])
def write_output_file(filename: str, contents: str) -> None:
Keyword arguments:
filename -- the full path to the file to write to
contents -- the contents to write to file
output_path: Path = Path(filename)
output_path.parent.mkdir(parents=True, exist_ok=True)
with open(output_path, "w") as output_file:
output_file.write(remove_empty_lines(contents))
if __name__ == '__main__':
args: dict = parse_args()
config = load_config(args)
if not args.cutoff is None:
config["cutoff"] = int(args.cutoff)
contents = generate_from_template(args.template, config)
write_output_file(args.output, contents)