3 Commits

Author SHA1 Message Date
d89fd151ca use just the page part of the path in breadcrumbs
rather than showing the full path (e.g. /foo/bar/baz) in breadcrumbs
when the page doesn't have a Title, show just the leaf (baz)

Closes #4
2021-02-27 00:30:32 -06:00
ce1ed60dd2 allow for configuration to override the favicon
Closes #5
2021-02-27 00:10:03 -06:00
70a8d4f06a add configurable contact email for error pages 2021-02-23 13:11:52 -06:00
8 changed files with 46 additions and 11 deletions

View File

@@ -48,7 +48,11 @@ class Config(object):
}, },
} }
DEFAULT_PAGE_STYLE = 'light'
TITLE_SUFFIX = 'incorporeal.org'
MEDIA_DIR = 'media' MEDIA_DIR = 'media'
# customizations
DEFAULT_PAGE_STYLE = 'light'
TITLE_SUFFIX = 'incorporeal.org'
CONTACT_EMAIL = 'bss@incorporeal.org'
# specify FAVICON in your instance config.py to override the suou icon

View File

@@ -130,5 +130,13 @@ def generate_parent_navs(path):
with app.open_instance_resource(path, 'r') as entry_file: with app.open_instance_resource(path, 'r') as entry_file:
entry = entry_file.read() entry = entry_file.read()
_ = Markup(md.convert(entry)) _ = Markup(md.convert(entry))
page_name = " ".join(md.Meta.get('title')) if md.Meta.get('title') else request_path 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)] return generate_parent_navs(parent_resource_path) + [(page_name, 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('/')

View File

@@ -11,7 +11,7 @@
<h1>NOT FOUND</h1> <h1>NOT FOUND</h1>
<p>Sorry, <b><tt>{{ request.path }}</tt></b> does not seem to exist, at least not anymore.</p> <p>Sorry, <b><tt>{{ request.path }}</tt></b> does not seem to exist, at least not anymore.</p>
<p>It's possible you followed a dead link on this site, in which case I would appreciate it if you could email me via: <p>It's possible you followed a dead link on this site, in which case I would appreciate it if you could email me via:
bss @ &lt;this domain&gt; and I can take a look. I make an effort to symlink old content to its new location, {{ config.CONTACT_EMAIL }} and I can take a look. I make an effort to symlink old content to its new location,
so old links and URLs should, generally speaking, work.</p> so old links and URLs should, generally speaking, work.</p>
<p>Otherwise, I suggest you go <a href="/">to the index</a> and navigate your way (hopefully) to what <p>Otherwise, I suggest you go <a href="/">to the index</a> and navigate your way (hopefully) to what
you're looking for.</p> you're looking for.</p>

View File

@@ -9,6 +9,6 @@
{% block body %} {% block body %}
<div class="content"> <div class="content">
<h1>INTERNAL SERVER ERROR</h1> <h1>INTERNAL SERVER ERROR</h1>
<p>Something bad happened! Please email me at bss @ &lt;this domain&gt; and tell me what happened.</p> <p>Something bad happened! Please email me at {{ config.CONTACT_EMAIL }} and tell me what happened.</p>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -9,7 +9,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename=user_style) }}"> <link rel="stylesheet" href="{{ url_for('static', filename=user_style) }}">
<link rel="icon" href="{{ url_for('static', filename='img/favicon.png') }}"> <link rel="icon" href="{% if config.FAVICON %}{{ config.FAVICON }}{% else %}{{ url_for('static', filename='img/favicon.png') }}{% endif %}">
<div class="site-wrap"> <div class="site-wrap">
{% block header %} {% block header %}

View File

@@ -14,6 +14,8 @@ def test_page_that_doesnt_exist(client):
response = client.get('/ohuesthaoeusth') response = client.get('/ohuesthaoeusth')
assert response.status_code == 404 assert response.status_code == 404
assert b'<b><tt>/ohuesthaoeusth</tt></b> does not seem to exist' in response.data assert b'<b><tt>/ohuesthaoeusth</tt></b> does not seem to exist' in response.data
# test the contact email config
assert b'bss@incorporeal.org' in response.data
def test_files_outside_pages_do_not_get_served(client): def test_files_outside_pages_do_not_get_served(client):
@@ -28,6 +30,8 @@ def test_internal_server_error_serves_error_page(client):
response = client.get('/actually-a-png') response = client.get('/actually-a-png')
assert response.status_code == 500 assert response.status_code == 500
assert b'INTERNAL SERVER ERROR' in response.data assert b'INTERNAL SERVER ERROR' in response.data
# test the contact email config
assert b'bss@incorporeal.org' in response.data
def test_weird_paths_do_not_get_served(client): def test_weird_paths_do_not_get_served(client):

View File

@@ -58,3 +58,13 @@ def test_media_file_access(client):
response = client.get('/media/favicon.png') response = client.get('/media/favicon.png')
assert response.status_code == 200 assert response.status_code == 200
assert response.headers['content-type'] == 'image/png' assert response.headers['content-type'] == 'image/png'
def test_favicon_override():
"""Test that a configuration with a specific favicon overrides the default."""
instance_path = os.path.join(HERE, 'instance')
app = create_app(instance_path=instance_path, test_config={'FAVICON': '/media/foo.png'})
client = app.test_client()
response = client.get('/no-title')
assert response.status_code == 200
assert b'<link rel="icon" href="/media/foo.png">' in response.data

View File

@@ -3,7 +3,7 @@ import pytest
from werkzeug.http import dump_cookie from werkzeug.http import dump_cookie
from incorporealcms.pages import (generate_parent_navs, instance_resource_path_to_request_path, render, from incorporealcms.pages import (generate_parent_navs, instance_resource_path_to_request_path, render,
request_path_to_instance_resource_path) request_path_to_breadcrumb_display, request_path_to_instance_resource_path)
def test_generate_page_navs_index(app): def test_generate_page_navs_index(app):
@@ -15,13 +15,13 @@ def test_generate_page_navs_index(app):
def test_generate_page_navs_subdir_index(app): def test_generate_page_navs_subdir_index(app):
"""Test that dir pages have navs to the root and themselves.""" """Test that dir pages have navs to the root and themselves."""
with app.app_context(): with app.app_context():
assert generate_parent_navs('pages/subdir/index.md') == [('incorporeal.org', '/'), ('/subdir/', '/subdir/')] assert generate_parent_navs('pages/subdir/index.md') == [('incorporeal.org', '/'), ('subdir', '/subdir/')]
def test_generate_page_navs_subdir_real_page(app): def test_generate_page_navs_subdir_real_page(app):
"""Test that real pages have navs to the root, their parent, and themselves.""" """Test that real pages have navs to the root, their parent, and themselves."""
with app.app_context(): with app.app_context():
assert generate_parent_navs('pages/subdir/page.md') == [('incorporeal.org', '/'), ('/subdir/', '/subdir/'), assert generate_parent_navs('pages/subdir/page.md') == [('incorporeal.org', '/'), ('subdir', '/subdir/'),
('Page', '/subdir/page')] ('Page', '/subdir/page')]
@@ -31,7 +31,7 @@ def test_generate_page_navs_subdir_with_title_parsing_real_page(app):
assert generate_parent_navs('pages/subdir-with-title/page.md') == [ assert generate_parent_navs('pages/subdir-with-title/page.md') == [
('incorporeal.org', '/'), ('incorporeal.org', '/'),
('SUB!', '/subdir-with-title/'), ('SUB!', '/subdir-with-title/'),
('/subdir-with-title/page', '/subdir-with-title/page') ('page', '/subdir-with-title/page')
] ]
@@ -162,3 +162,12 @@ def test_request_resource_request_page(app):
"""Test that a request can resolve to a resource and back to a request.""" """Test that a request can resolve to a resource and back to a request."""
with app.test_request_context(): with app.test_request_context():
instance_resource_path_to_request_path(request_path_to_instance_resource_path('no-title')) == 'no-title' instance_resource_path_to_request_path(request_path_to_instance_resource_path('no-title')) == 'no-title'
def test_request_path_to_breadcrumb_display_patterns():
"""Test various conversions from request path to leaf nodes for display in the breadcrumbs."""
assert request_path_to_breadcrumb_display('/foo') == 'foo'
assert request_path_to_breadcrumb_display('/foo/') == 'foo'
assert request_path_to_breadcrumb_display('/foo/bar') == 'bar'
assert request_path_to_breadcrumb_display('/foo/bar/') == 'bar'
assert request_path_to_breadcrumb_display('/') == ''