static site generator part 7? --- refactoring, more tests
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
This commit is contained in:
parent
76b1800155
commit
ca9e6623ff
@ -81,49 +81,72 @@ class StaticSiteGenerator(object):
|
|||||||
cprint(f"copying files from '{source_dir}' to '{dest_dir}'", 'green')
|
cprint(f"copying files from '{source_dir}' to '{dest_dir}'", 'green')
|
||||||
os.chdir(source_dir)
|
os.chdir(source_dir)
|
||||||
for base_dir, subdirs, files in os.walk(source_dir):
|
for base_dir, subdirs, files in os.walk(source_dir):
|
||||||
# remove the absolute path of the pages directory from the base_dir
|
# remove the absolute path of the directory from the base_dir
|
||||||
base_dir = os.path.relpath(base_dir, source_dir)
|
base_dir = os.path.relpath(base_dir, source_dir)
|
||||||
# create subdirs seen here for subsequent depth
|
# create subdirs seen here for subsequent depth
|
||||||
for subdir in subdirs:
|
for subdir in subdirs:
|
||||||
dst = os.path.join(dest_dir, base_dir, subdir)
|
self.build_subdir_in_destination(source_dir, base_dir, subdir, dest_dir)
|
||||||
if os.path.islink(os.path.join(base_dir, subdir)):
|
|
||||||
# keep the link relative to the output directory
|
|
||||||
src = self.symlink_to_relative_dest(source_dir, os.path.join(base_dir, subdir))
|
|
||||||
print(f"creating directory symlink '{dst}' -> '{src}'")
|
|
||||||
os.symlink(src, dst, target_is_directory=True)
|
|
||||||
else:
|
|
||||||
print(f"creating directory '{dst}'")
|
|
||||||
try:
|
|
||||||
os.mkdir(dst)
|
|
||||||
except FileExistsError:
|
|
||||||
# already exists
|
|
||||||
pass
|
|
||||||
|
|
||||||
# process and copy files
|
# process and copy files
|
||||||
for file_ in files:
|
for file_ in files:
|
||||||
dst = os.path.join(dest_dir, base_dir, file_)
|
self.build_file_in_destination(source_dir, base_dir, file_, dest_dir, convert_markdown)
|
||||||
if os.path.islink(os.path.join(base_dir, file_)):
|
|
||||||
# keep the link relative to the output directory
|
|
||||||
src = self.symlink_to_relative_dest(source_dir, os.path.join(base_dir, file_))
|
|
||||||
print(f"creating symlink '{dst}' -> '{src}'")
|
|
||||||
os.symlink(src, dst, target_is_directory=False)
|
|
||||||
else:
|
|
||||||
src = os.path.join(base_dir, file_)
|
|
||||||
print(f"copying file '{src}' -> '{dst}'")
|
|
||||||
shutil.copy2(src, dst)
|
|
||||||
|
|
||||||
# render markdown as HTML
|
def build_subdir_in_destination(self, source_dir: str, base_dir: str, subdir: str, dest_dir: str) -> None:
|
||||||
if src.endswith('.md') and convert_markdown:
|
"""Create a subdir (which might actually be a symlink) in the output dir.
|
||||||
rendered_file = dst.removesuffix('.md') + '.html'
|
|
||||||
try:
|
Args:
|
||||||
content = handle_markdown_file_path(src)
|
source_dir: the absolute path of the location in the instance, contains subdir
|
||||||
except UnicodeDecodeError:
|
base_dir: the relative path of the location in the instance, contains subdir
|
||||||
# perhaps this isn't a markdown file at all for some reason; we
|
subdir: the subdir in the instance to replicate in the output
|
||||||
# copied it above so stick with tha
|
dest_dir: the output directory to place the subdir in
|
||||||
cprint(f"{src} has invalid bytes! skipping", 'yellow')
|
"""
|
||||||
continue
|
dst = os.path.join(dest_dir, base_dir, subdir)
|
||||||
with open(rendered_file, 'w') as dst_file:
|
if os.path.islink(os.path.join(base_dir, subdir)):
|
||||||
dst_file.write(content)
|
# keep the link relative to the output directory
|
||||||
|
src = self.symlink_to_relative_dest(source_dir, os.path.join(base_dir, subdir))
|
||||||
|
print(f"creating directory symlink '{dst}' -> '{src}'")
|
||||||
|
os.symlink(src, dst, target_is_directory=True)
|
||||||
|
else:
|
||||||
|
print(f"creating directory '{dst}'")
|
||||||
|
try:
|
||||||
|
os.mkdir(dst)
|
||||||
|
except FileExistsError:
|
||||||
|
# already exists
|
||||||
|
pass
|
||||||
|
|
||||||
|
def build_file_in_destination(self, source_dir: str, base_dir: str, file_: str, dest_dir: str,
|
||||||
|
convert_markdown=False) -> None:
|
||||||
|
"""Create a file (which might actually be a symlink) in the output dir.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
source_dir: the absolute path of the location in the instance, contains subdir
|
||||||
|
base_dir: the relative path of the location in the instance, contains subdir
|
||||||
|
file_: the file in the instance to replicate in the output
|
||||||
|
dest_dir: the output directory to place the subdir in
|
||||||
|
"""
|
||||||
|
dst = os.path.join(dest_dir, base_dir, file_)
|
||||||
|
if os.path.islink(os.path.join(base_dir, file_)):
|
||||||
|
# keep the link relative to the output directory
|
||||||
|
src = self.symlink_to_relative_dest(source_dir, os.path.join(base_dir, file_))
|
||||||
|
print(f"creating symlink '{dst}' -> '{src}'")
|
||||||
|
os.symlink(src, dst, target_is_directory=False)
|
||||||
|
else:
|
||||||
|
src = os.path.join(base_dir, file_)
|
||||||
|
print(f"copying file '{src}' -> '{dst}'")
|
||||||
|
shutil.copy2(src, dst)
|
||||||
|
|
||||||
|
# render markdown as HTML
|
||||||
|
if src.endswith('.md') and convert_markdown:
|
||||||
|
rendered_file = dst.removesuffix('.md') + '.html'
|
||||||
|
try:
|
||||||
|
content = handle_markdown_file_path(src)
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
# perhaps this isn't a markdown file at all for some reason; we
|
||||||
|
# copied it above so stick with tha
|
||||||
|
cprint(f"{src} has invalid bytes! skipping", 'yellow')
|
||||||
|
else:
|
||||||
|
with open(rendered_file, 'w') as dst_file:
|
||||||
|
dst_file.write(content)
|
||||||
|
|
||||||
def symlink_to_relative_dest(self, base_dir: str, source: str) -> str:
|
def symlink_to_relative_dest(self, base_dir: str, source: str) -> str:
|
||||||
"""Given a symlink, make sure it points to something inside the instance and provide its real destination.
|
"""Given a symlink, make sure it points to something inside the instance and provide its real destination.
|
||||||
|
@ -4,64 +4,62 @@ SPDX-FileCopyrightText: © 2021 Brian S. Stephan <bss@incorporeal.org>
|
|||||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from incorporealcms import create_app
|
import pytest
|
||||||
|
|
||||||
|
from incorporealcms import init_instance
|
||||||
|
from incorporealcms.ssg import StaticSiteGenerator
|
||||||
|
|
||||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
init_instance(instance_path=os.path.join(HERE, 'instance'),
|
||||||
def app_with_pydot():
|
extra_config={'MARKDOWN_EXTENSIONS': ['incorporealcms.mdx.pydot', 'incorporealcms.mdx.figures',
|
||||||
"""Create the test app, including the pydot extension."""
|
'attr_list']})
|
||||||
return create_app(instance_path=os.path.join(HERE, 'instance'),
|
|
||||||
test_config={'MARKDOWN_EXTENSIONS': ['incorporealcms.mdx.pydot']})
|
|
||||||
|
|
||||||
|
|
||||||
def test_functional_initialization():
|
|
||||||
"""Test initialization with the graphviz config."""
|
|
||||||
app = app_with_pydot()
|
|
||||||
assert app is not None
|
|
||||||
|
|
||||||
|
|
||||||
def test_graphviz_is_rendered():
|
def test_graphviz_is_rendered():
|
||||||
"""Initialize the app with the graphviz extension and ensure it does something."""
|
"""Initialize the app with the graphviz extension and ensure it does something."""
|
||||||
app = app_with_pydot()
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
client = app.test_client()
|
src_dir = os.path.join(HERE, 'instance')
|
||||||
|
ssg = StaticSiteGenerator(src_dir, tmpdir)
|
||||||
|
os.chdir(os.path.join(src_dir, 'pages'))
|
||||||
|
|
||||||
response = client.get('/test-graphviz')
|
ssg.build_file_in_destination(os.path.join(HERE, 'instance', 'pages'), '', 'test-graphviz.md', tmpdir, True)
|
||||||
assert response.status_code == 200
|
with open(os.path.join(tmpdir, 'test-graphviz.html'), 'r') as graphviz_output:
|
||||||
assert b'~~~pydot' not in response.data
|
data = graphviz_output.read()
|
||||||
assert b'data:image/png;base64' in response.data
|
assert 'data:image/png;base64' in data
|
||||||
|
os.chdir(HERE)
|
||||||
|
|
||||||
def test_two_graphviz_are_rendered():
|
|
||||||
"""Test two images are rendered."""
|
|
||||||
app = app_with_pydot()
|
|
||||||
client = app.test_client()
|
|
||||||
|
|
||||||
response = client.get('/test-two-graphviz')
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert b'~~~pydot' not in response.data
|
|
||||||
assert b'data:image/png;base64' in response.data
|
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_graphviz_is_not_rendered():
|
def test_invalid_graphviz_is_not_rendered():
|
||||||
"""Check that invalid graphviz doesn't blow things up."""
|
"""Check that invalid graphviz doesn't blow things up."""
|
||||||
app = app_with_pydot()
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
client = app.test_client()
|
src_dir = os.path.join(HERE, 'instance')
|
||||||
|
ssg = StaticSiteGenerator(src_dir, tmpdir)
|
||||||
|
os.chdir(os.path.join(src_dir, 'pages'))
|
||||||
|
|
||||||
response = client.get('/test-invalid-graphviz')
|
with pytest.raises(ValueError):
|
||||||
assert response.status_code == 500
|
ssg.build_file_in_destination(os.path.join(HERE, 'instance', 'pages'), '', 'test-invalid-graphviz.md',
|
||||||
assert b'INTERNAL SERVER ERROR' in response.data
|
tmpdir, True)
|
||||||
|
os.chdir(HERE)
|
||||||
|
|
||||||
|
|
||||||
def test_figures_are_rendered(client):
|
def test_figures_are_rendered():
|
||||||
"""Test that a page with my figure syntax renders as expected."""
|
"""Test that a page with my figure syntax renders as expected."""
|
||||||
response = client.get('/figures')
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
assert response.status_code == 200
|
src_dir = os.path.join(HERE, 'instance')
|
||||||
assert (b'<figure class="right"><img alt="fancy captioned logo" src="bss-square-no-bg.png" />'
|
ssg = StaticSiteGenerator(src_dir, tmpdir)
|
||||||
b'<figcaption>this is my cool logo!</figcaption></figure>') in response.data
|
os.chdir(os.path.join(src_dir, 'pages'))
|
||||||
assert (b'<figure><img alt="vanilla captioned logo" src="bss-square-no-bg.png" />'
|
|
||||||
b'<figcaption>this is my cool logo without an attr!</figcaption>\n</figure>') in response.data
|
ssg.build_file_in_destination(os.path.join(HERE, 'instance', 'pages'), '', 'figures.md', tmpdir, True)
|
||||||
assert (b'<figure class="left"><img alt="fancy logo" src="bss-square-no-bg.png" />'
|
with open(os.path.join(tmpdir, 'figures.html'), 'r') as graphviz_output:
|
||||||
b'<span></span></figure>') in response.data
|
data = graphviz_output.read()
|
||||||
assert b'<figure><img alt="just a logo" src="bss-square-no-bg.png" /></figure>' in response.data
|
assert ('<figure class="right"><img alt="fancy captioned logo" src="bss-square-no-bg.png" />'
|
||||||
|
'<figcaption>this is my cool logo!</figcaption></figure>') in data
|
||||||
|
assert ('<figure><img alt="vanilla captioned logo" src="bss-square-no-bg.png" />'
|
||||||
|
'<figcaption>this is my cool logo without an attr!</figcaption>\n</figure>') in data
|
||||||
|
assert ('<figure class="left"><img alt="fancy logo" src="bss-square-no-bg.png" />'
|
||||||
|
'<span></span></figure>') in data
|
||||||
|
assert '<figure><img alt="just a logo" src="bss-square-no-bg.png" /></figure>' in data
|
||||||
|
os.chdir(HERE)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user