Skip to content

Commit

Permalink
Create combined CSS or combined JS when new CSS/JS file is created
Browse files Browse the repository at this point in the history
  • Loading branch information
Siecje committed Feb 3, 2024
1 parent 5b6b84f commit e01091c
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 1 deletion.
42 changes: 42 additions & 0 deletions htmd/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
import importlib
from pathlib import Path
import sys
import threading
import warnings

import click
from flask import Flask
from flask_flatpages import FlatPages, Page
from watchdog.observers import Observer
from watchdog.events import DirModifiedEvent, FileModifiedEvent, FileSystemEventHandler

from .utils import (
combine_and_minify_css,
Expand Down Expand Up @@ -202,6 +205,24 @@ def build(
click.echo(click.style(msg, fg='green'))


class StaticHandler(FileSystemEventHandler):
def __init__(self, static_directory: Path) -> None:
super().__init__()
self.static_directory = static_directory

def on_modified(self, event: DirModifiedEvent | FileModifiedEvent) -> None:
dst_css = 'combined.min.css'
dst_js = 'combined.min.js'
if event.is_directory or dst_css in event.src_path or dst_js in event.src_path:
return
if event.event_type == 'modified' and event.src_path.endswith('.css'):
click.echo(f'Changes detected in {event.src_path}. Recreating {dst_css}...')
combine_and_minify_css(self.static_directory)
elif event.event_type == 'modified' and event.src_path.endswith('.js'):
click.echo(f'Changes detected in {event.src_path}. Recreating {dst_js}...')
combine_and_minify_js(self.static_directory)


@cli.command('preview', short_help='Serve files to preview site.')
@click.pass_context
@click.option(
Expand Down Expand Up @@ -245,13 +266,34 @@ def preview(
assert app.static_folder is not None
combine_and_minify_js(Path(app.static_folder))

def watch_static() -> None:
static_directory = Path(app.static_folder)

event_handler = StaticHandler(static_directory)
observer = Observer()
observer.schedule(event_handler, path=static_directory, recursive=True)
observer.start()

try:
while not exit_event.is_set():
observer.join(1)
finally:
observer.stop()
observer.join()

watch_thread = threading.Thread(target=watch_static)
watch_thread.start()

# reload when static files change
# werkzeug will re-run the terminal command
# Which causes the above combine_and_minify_*() to run
# and recreate combined.min.css/combined.min.js files
static_path = site.project_dir / 'static'
extra_files = static_path.iterdir()
exit_event = threading.Event()
app.run(debug=True, host=host, port=port, extra_files=extra_files)
# After Flask has been stopped stop watchdog
exit_event.set()


@cli.command('templates', short_help='Create any missing templates')
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies = [
"jsmin",
"Pygments",
"requests",
"watchdog",
]
description = "Write Markdown and Jinja2 templates to create a website"
maintainers = [
Expand Down Expand Up @@ -67,6 +68,7 @@ order-by-type = false
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]

[tool.ruff.lint.per-file-ignores]
"htmd/cli.py" = ["I001"]
"tests/test_app.py" = ["ARG001"]
"tests/test_build.py" = ["I001"]
"tests/test_drafts.py" = ["ARG001", "I001"]
Expand Down
34 changes: 33 additions & 1 deletion tests/test_preview.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from pathlib import Path
import time
from types import TracebackType
import urllib3

from click.testing import CliRunner
from htmd.cli import preview
Expand Down Expand Up @@ -182,7 +183,7 @@ def test_preview_reload_js(run_start: CliRunner) -> None: # noqa: ARG001
while after == before:
try:
response = requests.get(url, timeout=0.1)
except requests.exceptions.ReadTimeout:
except (requests.exceptions.ReadTimeout, urllib3.exceptions.IncompleteRead):
# happens during restart
read_timeout = True
else:
Expand All @@ -191,3 +192,34 @@ def test_preview_reload_js(run_start: CliRunner) -> None: # noqa: ARG001
assert read_timeout
assert before != after
assert expected in after


def test_preview_reload_js_new_file(run_start: CliRunner) -> None: # noqa: ARG001
url = 'http://localhost:9090/static/combined.min.js'
new_js = 'document.getElementByTagName("body");'
expected = new_js

with run_preview():
response = requests.get(url, timeout=0.01)
assert response.status_code == 404
before = response.text
# Need to create before running preview since no .js files exist
js_path = Path('static') / 'script.js'
with js_path.open('w') as js_file:
js_file.write(new_js)

# Ensure new style is available after reload
read_timeout = False
after = before
while after == before:
try:
response = requests.get(url, timeout=0.1)
except requests.exceptions.ReadTimeout:
# happens during restart
read_timeout = True
else:
after = response.text

assert read_timeout is False
assert before != after
assert expected in after

0 comments on commit e01091c

Please sign in to comment.