Skip to content

Commit ea7fa57

Browse files
committed
drop esoteric exts, more test cases
1 parent e6f5597 commit ea7fa57

File tree

11 files changed

+173
-57
lines changed

11 files changed

+173
-57
lines changed

jinja2html/build_context.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
class Context:
2020
"""Collects shared configuration and simple methods for determining which files/directories to watch. There should only be one instance of this during the program's lifeycle."""
2121

22-
_FILE_PATTERN = re.compile(r"[^.].*?\.(html|htm|css|js)$", re.IGNORECASE)
22+
_FILE_PATTERN = re.compile(r"[^.].*?\.(html|css|js)$", re.IGNORECASE)
2323

2424
def __init__(self, input_dir: Path = Path("."), output_dir: Path = Path("out"), template_dir: str = "templates", ignore_list: set[Path] = set(), dev_mode: bool = False) -> None:
2525
"""Initializer, creates a new `Context`. For best results, all `Path` type arguments should be absolute (this is automatically done in the initializer, but if you want to change the properties after initializing, make sure you do this).
@@ -102,7 +102,6 @@ def is_content_dir(self, p: Union[Path, str]) -> bool:
102102
Returns:
103103
bool: `True` if `p` is a content directory.
104104
"""
105-
106105
return (p := _abs_path_of(p)).is_dir() and \
107106
p != self.template_dir and self.template_dir not in p.parents and \
108107
p.name not in DefaultFilter.ignore_dirs and p not in self.ignored_dirs

jinja2html/utils.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
from pathlib import Path
44

55

6-
def _is_ext(f: Path, ext: tuple[str]) -> bool:
7-
"""Determines whether a file has one of the specified extension(s).
6+
def _normalized_ext(f: Path) -> str:
7+
"""Convenience method, gets the file extension of `f` in lowercase
88
99
Args:
10-
f (Path): The file to check.
11-
ext (tuple[str]): The extension(s) to check for. These should be lower case.
10+
f (Path): The file to get the lowercased extension of.
1211
1312
Returns:
14-
bool: `True` if `f` has an extension in `ext`.
13+
str: The lowercased extension of `f`, if possible
1514
"""
16-
return f.suffix.lower() in ext
15+
return f.suffix.lower()
1716

1817

1918
def is_css_js(f: Path) -> bool:
@@ -25,7 +24,7 @@ def is_css_js(f: Path) -> bool:
2524
Returns:
2625
bool: `True` if `f` is a css/js file.
2726
"""
28-
return _is_ext(f, (".css", ".js"))
27+
return _normalized_ext(f) in (".css", ".js")
2928

3029

3130
def is_html(f: Path) -> bool:
@@ -37,4 +36,4 @@ def is_html(f: Path) -> bool:
3736
Returns:
3837
bool: `True` if `f` is a jinja file.
3938
"""
40-
return _is_ext(f, (".html", ".htm", ".jinja"))
39+
return _normalized_ext(f) == ".html"

jinja2html/web_ui.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,11 @@ async def changed_files_handler(wm: WebsiteManager) -> None:
135135
target.unlink()
136136
elif wm.context.is_content_dir(p):
137137
rmtree(target)
138-
else: # rebuild all if user deleted template or config
138+
else: # rebuild all if user deleted template or config
139139
# l = wm.find_acceptable_files()
140140
build_all = True
141141
break
142-
142+
143143
# handle changed/added content files
144144
elif wm.context.is_content_file(p):
145145
l.add(p)

tests/base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""Shared template `TestCase` classes and methods for use in jinja2html tests"""
2+
3+
from pathlib import Path
4+
from unittest.case import TestCase
5+
6+
7+
class J2hTestCase(TestCase):
8+
"""Basic template for testing jinja2html"""
9+
10+
RES_DIR: Path = Path("tests/resources").resolve() # script is run from the root repo dir
11+
SAMPLE_PROJECT: Path = RES_DIR / "sample_project"
12+
SAMPLE_TEMPLATES: Path = SAMPLE_PROJECT / "templates"

tests/resources/expected_output/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ <h1>Hello, World! This is the index page.</h1>
4141
<ul>
4242
<li><a href="content1.html">content 1</a></li>
4343
<li><a href="content2.html">content 2</a></li>
44+
<li><a href="sub/index.html">example subpage</a></li>
4445
</ul>
4546
</div>
4647

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8+
9+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
10+
11+
12+
<title>jinja2html test - subpage 1</title>
13+
</head>
14+
15+
<body>
16+
<header>
17+
<nav class="navbar navbar-expand-lg navbar-light bg-light">
18+
<div class="container-fluid">
19+
<a class="navbar-brand" href="index.html">jinja2html</a>
20+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
21+
<span class="navbar-toggler-icon"></span>
22+
</button>
23+
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
24+
<div class="navbar-nav">
25+
<a class="nav-link active" aria-current="page" href="#">Home</a>
26+
<a class="nav-link" href="#">Features</a>
27+
<a class="nav-link" href="#">Pricing</a>
28+
<a class="nav-link disabled">Disabled</a>
29+
</div>
30+
</div>
31+
</div>
32+
</nav>
33+
</header>
34+
35+
36+
37+
<div class="container">
38+
<h1>this is a subpage!!!!!</h1>
39+
<p>:D</p>
40+
<p>Click here to go <a href="../index.html">home</a></p>
41+
</div>
42+
43+
44+
45+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
46+
47+
</body>
48+
49+
</html>

tests/resources/sample_project/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ <h1>Hello, World! This is the index page.</h1>
1111
<ul>
1212
<li><a href="content1.html">content 1</a></li>
1313
<li><a href="content2.html">content 2</a></li>
14+
<li><a href="sub/index.html">example subpage</a></li>
1415
</ul>
1516
</div>
1617
{% endraw %}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{% extends 'templates/base.html' %}
2+
3+
{% set title = "subpage 1" %}
4+
5+
{% block content %}
6+
{% raw %}
7+
<div class="container">
8+
<h1>this is a subpage!!!!!</h1>
9+
<p>:D</p>
10+
<p>Click here to go <a href="../index.html">home</a></p>
11+
</div>
12+
{% endraw %}
13+
{% endblock %}

tests/test_build_context.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from pathlib import Path
2+
from tempfile import TemporaryDirectory
3+
4+
from jinja2html.build_context import Context
5+
6+
from .base import J2hTestCase
7+
8+
9+
class TestContext(J2hTestCase):
10+
"""Test methods supporting the build context"""
11+
12+
def test_is_stub_of(self):
13+
with TemporaryDirectory() as tempdir:
14+
c = Context(self.SAMPLE_PROJECT, Path(tempdir))
15+
16+
self.assertEqual(Path("index.html"), c.stub_of(self.SAMPLE_PROJECT / "index.html"))
17+
self.assertEqual(Path("sub/index.html"), c.stub_of(self.SAMPLE_PROJECT / "sub/index.html"))
18+
self.assertEqual(Path("shared.js"), c.stub_of(self.SAMPLE_PROJECT / "shared.js"))
19+
20+
def test_is_some_content(self):
21+
with TemporaryDirectory() as tempdir:
22+
c = Context(self.SAMPLE_PROJECT, Path(tempdir))
23+
24+
self.assertTrue(c.is_template(self.SAMPLE_TEMPLATES / "base.html"))
25+
self.assertFalse(c.is_template(self.SAMPLE_TEMPLATES / "does-not-exist.html"))
26+
self.assertFalse(c.is_template(self.SAMPLE_TEMPLATES / "lol.js"))
27+
self.assertFalse(c.is_template(self.SAMPLE_PROJECT / "base.html"))
28+
self.assertFalse(c.is_template(self.SAMPLE_PROJECT / "index.html"))
29+
30+
self.assertTrue(c.is_config_json(self.SAMPLE_PROJECT / "config.json"))
31+
self.assertFalse(c.is_config_json(self.SAMPLE_PROJECT / "config.js"))
32+
self.assertFalse(c.is_config_json(self.SAMPLE_PROJECT / "sus.json"))
33+
self.assertFalse(c.is_config_json(self.SAMPLE_TEMPLATES / "config.json"))
34+
self.assertFalse(c.is_config_json(self.SAMPLE_PROJECT / "ok.html"))
35+
36+
self.assertTrue(c.is_content_file(self.SAMPLE_PROJECT / "index.html"))
37+
self.assertTrue(c.is_content_file(self.SAMPLE_PROJECT / "content2.html"))
38+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "does-not-exist.js"))
39+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "a.css"))
40+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "config.js"))
41+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "sub"))
42+
self.assertFalse(c.is_content_file(self.SAMPLE_TEMPLATES / "base.html"))
43+
44+
self.assertTrue(c.is_content_dir(self.SAMPLE_PROJECT / "sub"))
45+
self.assertFalse(c.is_content_dir(self.SAMPLE_PROJECT / "config.json"))
46+
self.assertFalse(c.is_content_dir(self.SAMPLE_PROJECT / "foobar"))
47+
48+
def test_ignore(self):
49+
with TemporaryDirectory() as tempdir:
50+
c = Context(self.SAMPLE_PROJECT, Path(tempdir), ignore_list={self.SAMPLE_PROJECT / "sub"})
51+
52+
self.assertTrue(c.is_content_file(self.SAMPLE_PROJECT / "index.html"))
53+
self.assertTrue(c.is_content_file(self.SAMPLE_PROJECT / "content2.html"))
54+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "does-not-exist.js"))
55+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "a.css"))
56+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "config.js"))
57+
self.assertFalse(c.is_content_file(self.SAMPLE_PROJECT / "sub"))
58+
self.assertFalse(c.is_content_file(self.SAMPLE_TEMPLATES / "base.html"))
59+
60+
self.assertFalse(c.is_content_dir(self.SAMPLE_PROJECT / "sub"))
61+
self.assertFalse(c.is_content_dir(self.SAMPLE_PROJECT / "config.json"))
62+
self.assertFalse(c.is_content_dir(self.SAMPLE_PROJECT / "foobar"))

tests/test_core.py

Lines changed: 0 additions & 45 deletions
This file was deleted.

tests/test_website_manager.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Tests for core modules of jinja2html"""
2+
3+
from filecmp import dircmp
4+
from pathlib import Path
5+
from tempfile import TemporaryDirectory
6+
7+
from jinja2html.build_context import Context
8+
from jinja2html.website_manager import WebsiteManager
9+
10+
from .base import J2hTestCase
11+
12+
13+
class TestWebsiteManager(J2hTestCase):
14+
"""Test global methods and classes in core"""
15+
16+
def test_find_acceptable_files(self):
17+
with TemporaryDirectory() as tempdir:
18+
self.assertSetEqual({self.SAMPLE_PROJECT / s for s in ("content1.html", "content2.html", "index.html", "sub/index.html", "shared.css", "shared.js")},
19+
WebsiteManager(Context(self.SAMPLE_PROJECT, Path(tempdir))).find_acceptable_files())
20+
21+
def test_process_files(self):
22+
with TemporaryDirectory() as tempdir:
23+
WebsiteManager(Context(self.SAMPLE_PROJECT, Path(tempdir))).build_files(auto_find=True)
24+
25+
self.assertFalse(dircmp(self.RES_DIR / "expected_output", tempdir).diff_files)

0 commit comments

Comments
 (0)