Skip to content

Commit 89f8945

Browse files
committed
fix js/css reload, enable delete/clean, tag for release
1 parent 0cf9598 commit 89f8945

File tree

6 files changed

+60
-30
lines changed

6 files changed

+60
-30
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ optional arguments:
3434
-p port serve website on this port
3535
-i input_dir The input directory (contianing jinja templates) to use. Defaults to the current working directory.
3636
-o output_dir The output directory to write website output files to. Defaults to ./out
37-
-t template_dir Shared templates directory (this must be a subfolder of the input directory). Defaults to ./templates
37+
-t template_dir Shared templates directory (relative path only, this must be a subfolder of the input directory). Defaults to templates
3838
--blacklist ignored_dir [ignored_dir ...]
3939
directories to ignore
4040
```
@@ -51,7 +51,7 @@ jinja2html -d
5151
jinja2html -d --blacklist Foo/ Bar/
5252

5353
# run in dev mode, on port 8080 and ignore folder hello/world/
54-
jinja2html -p 8080 --blacklist hello/world/
54+
jinja2html -d -p 8080 --blacklist hello/world/
5555
```
5656

5757
## Scope

jinja2html/__main__.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from rich.logging import RichHandler
2020
from watchgod import awatch, Change
2121

22-
from .core import Context, JinjaWatcher, WebsiteManager
22+
from .core import Context, is_css_js, JinjaWatcher, WebsiteManager
2323

2424

2525
_SESSIONS = defaultdict(list)
@@ -77,21 +77,28 @@ async def changed_files_handler(wm: WebsiteManager) -> None:
7777
wm (WebsiteManager): The WebsiteManager to associate with this asyncio loop
7878
"""
7979
async for changes in awatch(wm.context.input_dir, watcher_cls=JinjaWatcher, watcher_kwargs={"context": wm.context}):
80-
rebuild: set[Path] = set()
80+
l: set[Path] = set()
81+
build_all = notify_all = False
8182

8283
for change, p in changes:
84+
p = Path(p)
8385
if wm.context.is_template(p) or wm.context.is_config_json(p):
84-
rebuild = wm.find_acceptable_files()
86+
l = wm.find_acceptable_files()
87+
build_all = True
8588
break
8689
elif change in (Change.added, Change.modified):
87-
rebuild.add(Path(p))
90+
l.add(p)
91+
if is_css_js(p):
92+
notify_all = True
8893
else:
89-
# (wm.context.output_dir / wm.context.stub_of(p)).unlink(True)
90-
pass
94+
(wm.context.output_dir / wm.context.stub_of(p)).unlink(True)
9195

92-
wm.build_files(rebuild)
96+
wm.build_files(l)
9397

94-
for p in rebuild:
98+
if notify_all and not build_all:
99+
l = wm.find_acceptable_files()
100+
101+
for p in l:
95102
stub = str(wm.context.stub_of(p))
96103
message = f'{{"command": "reload", "path": "{stub}", "liveCSS": false}}'
97104

@@ -133,14 +140,12 @@ def _main() -> None:
133140
cli_parser.add_argument("-p", type=int, metavar="port", default=8000, help="serve website on this port")
134141
cli_parser.add_argument("-i", type=Path, metavar="input_dir", default=Path("."), help="The input directory (contianing jinja templates) to use. Defaults to the current working directory.")
135142
cli_parser.add_argument("-o", type=Path, metavar="output_dir", default=Path("out"), help="The output directory to write website output files to. Defaults to ./out")
136-
cli_parser.add_argument("-t", type=Path, metavar="template_dir", default=Path("templates"), help="Shared templates directory (this must be a subfolder of the input directory). Defaults to ./templates")
143+
cli_parser.add_argument("-t", type=str, metavar="template_dir", default="templates", help="Shared templates directory (relative path only, this must be a subfolder of the input directory). Defaults to templates")
137144
cli_parser.add_argument("--blacklist", nargs="+", type=Path, metavar="ignored_dir", default=set(), help="directories to ignore")
138145

139146
args = cli_parser.parse_args()
140147

141-
c = Context(args.i, args.o, args.t, args.blacklist, args.d)
142-
# c.clean()
143-
148+
(c := Context(args.i, args.o, args.t, args.blacklist, args.d)).clean()
144149
(wm := WebsiteManager(c)).build_files(auto_find=True)
145150

146151
if not c.dev_mode:

jinja2html/core.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@ class Context:
2626

2727
_NOT_DIR_PATTERN = re.compile(r"(\.|venv_|__pycache)")
2828

29-
def __init__(self, input_dir: Path = Path("."), output_dir: Path = Path("out"), template_dir: Path = Path("./templates"), ignore_list: set[Path] = set(), dev_mode: bool = False) -> None:
29+
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:
3030
"""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).
3131
3232
Args:
3333
input_dir (Path, optional): The directory to watch for changes. Defaults to Path(".").
3434
output_dir (Path, optional): The directory to save generated files. Defaults to Path("out").
35-
template_dir (Path, optional): The directory containing jinja2 mixin-type templates. Defaults to Path("./templates").
35+
template_dir (str, optional): The directory containing jinja2 mixin-type templates. If it exists, this is the name of a folder under `input_dir`. Defaults to "templates".
3636
ignore_list (set[Path], optional): The set of directories to ignore (will not be watched, even if `input_dir` is a parent folder). Defaults to set().
3737
dev_mode (bool, optional): Flag which turns on development mode (i.e. livereload server). Defaults to False.
3838
"""
3939
self.input_dir: Path = input_dir.resolve()
4040
self.output_dir: Path = output_dir.resolve()
41-
self.template_dir: Path = template_dir.resolve()
41+
self.template_dir: Path = self.input_dir / template_dir
4242
self.dev_mode: bool = dev_mode
4343

4444
self.ignore_list: set[Path] = {p.resolve() for p in ignore_list} if ignore_list else ignore_list
@@ -75,7 +75,7 @@ def is_template(self, f: Path) -> bool:
7575
Returns:
7676
bool: `True` if `f` is a template in the `self.template_dir` directory.
7777
"""
78-
return self.template_dir in f.parents and _is_html(f)
78+
return self.template_dir in f.parents and is_html(f)
7979

8080
def is_config_json(self, f: Path) -> bool:
8181
"""Convienience method, determines whether `f` is the `config.json` file.
@@ -160,9 +160,9 @@ def build_files(self, files: Iterable[Path] = (), auto_find: bool = False) -> No
160160
for f in files:
161161
(output_path := self.context.output_dir / (stub := self.context.stub_of(f))).parent.mkdir(parents=True, exist_ok=True) # create dir structure if it doesn't exist
162162

163-
if f.suffix.lower() in (".js", ".css"):
163+
if is_css_js(f):
164164
shutil.copy(f, output_path)
165-
elif _is_html(f):
165+
elif is_html(f):
166166
log.debug("building html for %s", f)
167167

168168
try:
@@ -226,13 +226,38 @@ def should_watch_dir(self, entry: DirEntry) -> bool:
226226
return self.context.should_watch_dir(entry)
227227

228228

229-
def _is_html(f: Path) -> bool:
230-
"""Convenience method, determines whether `f` represents an HTML file.
229+
def _is_ext(f: Path, ext: tuple[str]) -> bool:
230+
"""Determines whether a file has one of the specified extension(s).
231231
232232
Args:
233233
f (Path): The file to check.
234+
ext (tuple[str]): The extension(s) to check for. These should be lower case.
234235
235236
Returns:
236-
bool: `True` if `f` is an html file.
237+
bool: `True` if `f` has an extension in `ext`.
237238
"""
238-
return f.suffix.lower() in (".html", ".htm", ".jinja")
239+
return f.suffix.lower() in ext
240+
241+
242+
def is_css_js(f: Path) -> bool:
243+
"""Convenience method, determines whether `f` represents a css/js file.
244+
245+
Args:
246+
f (Path): The file to check.
247+
248+
Returns:
249+
bool: `True` if `f` is a css/js file.
250+
"""
251+
return _is_ext(f, (".css", ".js"))
252+
253+
254+
def is_html(f: Path) -> bool:
255+
"""Convenience method, determines whether `f` represents an jinja file.
256+
257+
Args:
258+
f (Path): The file to check.
259+
260+
Returns:
261+
bool: `True` if `f` is a jinja file.
262+
"""
263+
return _is_ext(f, (".html", ".htm", ".jinja"))

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
beautifulsoup4==4.10.0
22
Jinja2==3.0.3
3-
lxml==4.6.4
4-
rich==10.15.2
3+
lxml==4.7.1
4+
rich==10.16.0
55
watchgod==0.7
66
websockets==10.1

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="jinja2html",
8-
version="0.3.0",
8+
version="0.4.0",
99
author="Fastily",
1010
author_email="fastily@users.noreply.github.com",
1111
description="user-friendly generation of websites with jinja2 templates",

tests/test_core.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ class TestCore(TestCase):
1919
def test_find_acceptable_files(self):
2020
expected = {_SAMPLE_PROJECT / s for s in ("config.json", "content1.html", "content2.html", "index.html", "shared.css", "shared.js")}
2121
with TemporaryDirectory() as tempdir:
22-
self.assertSetEqual(expected, WebsiteManager(Context(_SAMPLE_PROJECT, Path(tempdir), _SAMPLE_TEMPLATES)).find_acceptable_files())
22+
self.assertSetEqual(expected, WebsiteManager(Context(_SAMPLE_PROJECT, Path(tempdir))).find_acceptable_files())
2323

2424
def test_process_files(self):
2525
with TemporaryDirectory() as tempdir:
26-
WebsiteManager(Context(_SAMPLE_PROJECT, Path(tempdir), _SAMPLE_TEMPLATES)).build_files(auto_find=True)
26+
WebsiteManager(Context(_SAMPLE_PROJECT, Path(tempdir))).build_files(auto_find=True)
2727

2828
self.assertFalse(dircmp(_RES_DIR / "expected_output", tempdir).diff_files)
2929

3030
def test_sanity(self):
3131
with TemporaryDirectory() as tempdir:
32-
c = Context(_SAMPLE_PROJECT, Path(tempdir), _SAMPLE_TEMPLATES)
32+
c = Context(_SAMPLE_PROJECT, Path(tempdir))
3333

3434
self.assertEqual(Path("index.html"), c.stub_of(_SAMPLE_PROJECT / "index.html"))
3535
self.assertEqual(Path("shared.js"), c.stub_of(_SAMPLE_PROJECT / "shared.js"))

0 commit comments

Comments
 (0)