Brian S. Stephan 1ace0e1427
static site generator part 2 --- config and other fixes
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2025-03-13 18:57:19 -05:00

96 lines
4.0 KiB
Python

"""General page functionality.
SPDX-FileCopyrightText: © 2020 Brian S. Stephan <bss@incorporeal.org>
SPDX-License-Identifier: AGPL-3.0-or-later
"""
import logging
import os
from markupsafe import Markup
from werkzeug.security import safe_join
from incorporealcms import env
from incorporealcms.config import Config
from incorporealcms.lib import get_meta_str, init_md, instance_resource_path_to_request_path, parse_md
logger = logging.getLogger(__name__)
def handle_markdown_file_path(path: str) -> str:
"""Given a location on disk, attempt to open it and render the markdown within."""
try:
content, md, page_name, page_title, mtime = parse_md(path)
except OSError:
logger.exception("path '%s' could not be opened!", path)
raise
except ValueError:
logger.exception("error parsing/rendering markdown!")
raise
except TypeError:
logger.exception("error loading/rendering markdown!")
raise
else:
parent_navs = generate_parent_navs(path)
extra_footer = get_meta_str(md, 'footer') if md.Meta.get('footer') else None
template_name = get_meta_str(md, 'template') if md.Meta.get('template') else 'base.html'
# check if this has a HTTP redirect
redirect_url = get_meta_str(md, 'redirect') if md.Meta.get('redirect') else None
if redirect_url:
raise ValueError("redirects in markdown are unsupported!")
template = env.get_template(template_name)
return template.render(title=page_title,
config=Config,
description=get_meta_str(md, 'description'),
image=get_meta_str(md, 'image'),
content=content,
user_style=Config.PAGE_STYLES.get(Config.DEFAULT_PAGE_STYLE),
base_url=Config.BASE_HOST + instance_resource_path_to_request_path(path),
navs=parent_navs,
mtime=mtime.strftime('%Y-%m-%d %H:%M:%S %Z'),
extra_footer=extra_footer)
def generate_parent_navs(path):
"""Create a series of paths/links to navigate up from the given resource path."""
if path == 'index.md':
# bail and return the domain name as a terminal case
return [(Config.DOMAIN_NAME, '/')]
else:
if path.endswith('index.md'):
# index case: one dirname for foo/bar/index.md -> foo/bar, one for foo/bar -> foo
parent_resource_dir = os.path.dirname(os.path.dirname(path))
else:
# usual case: foo/buh.md -> foo
parent_resource_dir = os.path.dirname(path)
# generate the request path (i.e. what the link will be) for this path, and
# also the resource path of this parent (which is always a dir, so always index.md)
request_path = instance_resource_path_to_request_path(path)
parent_resource_path = os.path.join(parent_resource_dir, 'index.md')
logger.debug("resource path: '%s'; request path: '%s'; parent resource path: '%s'", path,
request_path, parent_resource_path)
# for issues regarding parser reuse (see lib.init_md) we reinitialize the parser here
md = init_md()
# read the resource
try:
with open(path, 'r') as entry_file:
entry = entry_file.read()
_ = Markup(md.convert(entry))
page_name = (" ".join(md.Meta.get('title')) if md.Meta.get('title')
else request_path_to_breadcrumb_display(request_path))
return generate_parent_navs(parent_resource_path) + [(page_name, request_path)]
except FileNotFoundError:
return generate_parent_navs(parent_resource_path) + [(request_path, request_path)]
def request_path_to_breadcrumb_display(path):
"""Given a request path, e.g. "/foo/bar/baz/", turn it into breadcrumby text "baz"."""
undired = path.rstrip('/')
leaf = undired[undired.rfind('/'):]
return leaf.strip('/')