diff --git a/README.md b/README.md
index df3c866..9ae4ef4 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,24 @@
zona
-[zona](https://git.ficd.sh/ficd/zona) is an _opinionated_ static site generator
-written in Python. From a structured directory of Markdown content, zona builds
-a simple static website. It's designed to get out of your way and let you focus
-on writing.
+[zona](https://sr.ht/~ficd/zona) is an _opinionated_ static site generator
+written in Python. From a structured directory of Markdown content, zona
+builds a simple static website. It's designed to get out of your way and
+let you focus on writing.
-**What do I mean by opinionated?** I built zona primarily for myself. I've tried
-making it flexible by exposing as many variables as possible to the template
-engine. However, if you're looking for something stable, complete, and fully
-configurable, zona may not be for you. If you want a minimal Markdown blog and
-are comfortable with modifying `jinja2` templates and CSS, then you're in luck.
+**What do I mean by opinionated?** I built zona primarily for myself. I've
+tried making it flexible by exposing as many variables as possible to the
+template engine. However, if you're looking for something stable,
+complete, and fully configurable, zona may not be for you. If you want a
+minimal Markdown blog and are comfortable with modifying `jinja2`
+templates and CSS, then you're in luck.
-**Note:** This project is in early development, there are no versioned releases
-yet, and breaking changes are likely. Versioned releases will be made and zona
-will be published to PyPI once it's stable. zona was previously implemented in
-Go; I decided to rewrite the project in Python. If you're interested in seeing
-the previous codebase (which is feature incomplete), visit the
-[zona-go](https://git.ficd.sh/ficd/zona-go) repository.
+**Note:** This project is in early development, there are no versioned
+releases yet, and breaking changes are likely. Versioned releases will be
+made and zona will be published to PyPI once it's stable. zona was
+previously implemented in Go; I decided to rewrite the project in Python.
+If you're interested in seeing the previous codebase (which is feature
+incomplete), visit the [~ficd/zona-go](https://git.sr.ht/~ficd/zona-go)
+repository.
For an example of a website built with zona, please see
[ficd.sh](https://ficd.sh).
@@ -29,7 +31,6 @@ For an example of a website built with zona, please see
- [Getting Started](#getting-started)
- [Building](#building)
- [Live Preview](#live-preview)
- - [Live Reload](#live-reload)
- [How It Works](#how-it-works)
- [Site Layout](#site-layout)
- [Templates](#templates)
@@ -59,15 +60,15 @@ For an example of a website built with zona, please see
- Easily configurable sitemap header.
- Site footer written in Markdown.
- Smart site layout discovery.
- - Blog posts are automatically discovered and rendered accordingly (can be
- overridden in frontmatter).
+ - Blog posts are automatically discovered and rendered accordingly (can
+ be overridden in frontmatter).
- Extended Markdown renderer:
- Smart internal link resolution.
- Syntax highlighting.
- Includes Kakoune syntax and [Ashen] highlighting.
- [Image labels](#image-labels).
- - Many `python-markdown` extensions enabled, including footnotes, tables,
- abbreviations, etc.
+ - Many `python-markdown` extensions enabled, including footnotes,
+ tables, abbreviations, etc.
- LaTeX support.
## Installation
@@ -76,7 +77,7 @@ zona is not yet packaged on PyPI. You may use `uv` to install it from this
repository:
```sh
-uv tool install 'git+https://git.ficd.sh/ficd/zona'
+uv tool install 'git+https://git.sr.ht/~ficd/zona'
```
## Usage
@@ -86,78 +87,71 @@ available options and arguments._
### Getting Started
-To set up a new website, create a new directory and run `zona init` inside of
-it. This creates the required directory structure and writes the default
-configuration file. The default templates and default stylesheet are also
-written.
+To set up a new website, create a new directory and run `zona init` inside
+of it. This creates the required directory structure and writes the
+default configuration file. The default templates and default stylesheet
+are also written.
### Building
-To build the website, run `zona build`. The project root is discovered according
-to the location of `config.yml`. By default, the output directory is called
-`public`, and saved inside the root directory.
+To build the website, run `zona build`. The project root is discovered
+according to the location of `config.yml`. By default, the output
+directory is called `public`, and saved inside the root directory.
If you don't want discovery, you can specify the project root as the first
argument to `zona build`. You may specify a path for the output using the
-`--output/-o` flag. The `--draft/-d` flag includes draft posts in the output.
+`--output/-o` flag. The `--draft/-d` flag includes draft posts in the
+output.
-_Note: the previous build is _not_ cleaned before the new site is built. If
-you've deleted some pages, you may need to remove the output directory before
-rebuilding._
+_Note: the previous build is _not_ cleaned before the new site is built.
+If you've deleted some pages, you may need to remove the output directory
+before rebuilding._
### Live Preview
-To make the writing process as frictionless as possible, zona ships with a live
-preview server. It spins up an HTTP server, meaning that internal links work
-properly (this is not the case if you simply open the `.html` files in your
-browser.)
+To make the writing process as frictionless as possible, zona ships with a
+live preview server. It spins up an HTTP server, meaning that internal
+links work properly (this is not the case if you simply open the `.html`
+files in your browser.)
-Additionally, the server watches for changes to all source files, and rebuilds
-the website when they're modified. _Note: the entire website is rebuilt — this
-ensures that links are properly resolved._
+Additionally, the server watches for changes to all source files, and
+rebuilds the website when they're modified. _Note: the entire website is
+rebuilt — this ensures that links are properly resolved._
-Drafts are enabled by default in live preview. Use `--final/-f` to disable them.
-By default, the build outputs to a temporary directory. Use `-o/--output` to
-override this.
+Optionally, live reloading of the browser is also provided. With this
+feature (enabled by default), your browser will automatically refresh open
+pages whenever the site is rebuilt. The live reloading requires JavaScript
+support from the browser — this is why the feature is optional.
-**Note**: if the live preview isn't working as expected, try restarting the
-server. If you change the configuration or any templates, the server must also
-be restarted. The live preview uses the same function as `zona build`
-internally; this means that the output is also written to disk.
+To start a preview server, use `zona serve`. You can specify the root
+directory as its first argument. Use the `--host` to specify a host name
+(`localhost` by default) and `--port/-p` to specify a port (default:
+`8000`). The `--no-live-reload/-n` disables the live browser reloading
+(_automatic site rebuilds are not disabled_).
-#### Live Reload
+Drafts are enabled by default in live preview. Use `--final/-f` to disable
+them. By default, the build outputs to a temporary directory. Use
+`-o/--output` to override this.
-Optionally, live reloading of the browser is also provided. With this feature
-(enabled by default), your browser will automatically refresh open pages
-whenever the site is rebuilt. The live reloading requires JavaScript support
-from the browser — this is why the feature is optional.
-
-To start a preview server, use `zona serve`. You can specify the root directory
-as its first argument. Use the `--host` to specify a host name (`localhost` by
-default) and `--port/-p` to specify a port (default: `8000`).
-
-The `--live-reload/--no-live-reload` option overrides the value set in the
-[config](#configuration) (`true` by default). _Automatic site rebuilds are not
-affected_.
-
-If you are scrolled to the bottom of the page in the browser, and you extend the
-height of the page by adding new content, you will automatically be scrolled to
-the _new_ bottom after reloading. You may tune the tolerance threshold in the
-[configuration](#configuration).
+**Note**: if the live preview isn't working as expected, try restarting
+the server. If you change the configuration or any templates, the server
+must also be restarted. The live preview uses the same function as
+`zona build` internally; this means that the output is also written to
+disk.
#### How It Works
-The basic idea is this: after a rebuild, the server needs to notify your browser
-to refresh the open pages. We implement this using a small amount of JavaScript.
-The server injects a tiny script into any HTML page it serves; which causes your
-browser to open a WebSocket connection with the server. When the site is
-rebuilt, the server notifies your browser via the WebSocket, which reloads the
-page.
+The basic idea is this: after a rebuild, the server needs to notify your
+browser to refresh the open pages. We implement this using a small amount
+of JavaScript. The server injects a tiny script into any HTML page it
+serves; which causes your browser to open a WebSocket connection with the
+server. When the site is rebuilt, the server notifies your browser via the
+WebSocket, which reloads the page.
Unfortunately, there is no way to implement this feature without using
-JavaScript. **JavaScript is _only_ used for the live preview feature. The script
-is injected by the server, and never written to the HTML files in the output
-directory.**
+JavaScript. **JavaScript is _only_ used for the live preview feature. The
+script is injected by the server, and never written to the HTML files in
+the output directory.**
### Site Layout
@@ -170,30 +164,32 @@ templates/
public/
```
-The **root** of the zona **project** _must_ contain the configuration file,
-`config.yml`, and a directory called `content`. A directory called `templates`
-is optional, and prioritized if it exists. `public` is the built site output —
-it's recommended to add this path to your `.gitignore`.
+The **root** of the zona **project** _must_ contain the configuration
+file, `config.yml`, and a directory called `content`. A directory called
+`templates` is optional, and prioritized if it exists. `public` is the
+built site output — it's recommended to add this path to your
+`.gitignore`.
The `content` directory is the **root of the website**. Think of it as the
-**content root**. For example, suppose your website is hosted at `example.com`.
-`content/blog/index.md` corresponds to `example.com/blog`,
+**content root**. For example, suppose your website is hosted at
+`example.com`. `content/blog/index.md` corresponds to `example.com/blog`,
`content/blog/my-post.md` becomes `example.com/blog/my-post`, etc.
- Internal links are resolved **relative to the `content` directory.**
- Templates are resolved relative to the `template` directory.
Markdown files inside a certain directory (`content/blog` by default) are
-automatically treated as _blog posts_. This means they are rendered with the
-`page` template, and included in the `post_list`, which can be included in your
-site using the `post_list` template.
+automatically treated as _blog posts_. This means they are rendered with
+the `page` template, and included in the `post_list`, which can be
+included in your site using the `post_list` template.
### Templates
The `templates` directory may contain any `jinja2` template files. You may
-modify the existing templates or create your own. To apply a certain template to
-a page, set the `template` option in its [frontmatter](#frontmatter). The
-following public variables are made available to the template engine:
+modify the existing templates or create your own. To apply a certain
+template to a page, set the `template` option in its
+[frontmatter](#frontmatter). The following public variables are made
+available to the template engine:
| Name | Description |
| ---------- | ------------------------------------------------------ |
@@ -205,40 +201,43 @@ following public variables are made available to the template engine:
#### Markdown Footer
-The `templates` directory can contain a file called `footer.md`. If it exists,
-it's parsed and rendered into HTML, then made available to other templates as
-the `footer` variable. If `footer.md` is missing but `footer.html` exists, then
-it's used instead. **Note: links are _not_ resolved in the footer.**
+The `templates` directory can contain a file called `footer.md`. If it
+exists, it's parsed and rendered into HTML, then made available to other
+templates as the `footer` variable. If `footer.md` is missing but
+`footer.html` exists, then it's used instead. **Note: links are _not_
+resolved in the footer.**
### Internal Link Resolution
-When zona encounters links in Markdown documents, it attempts to resolve them as
-internal links. Links beginning with `/` are resolved relative to the content
-root; otherwise, they are resolved relative to the Markdown file. If the link
-resolves to an existing file that is part of the website, it's replaced with an
-appropriate web-server-friendly link. Otherwise, the link isn't changed.
+When zona encounters links in Markdown documents, it attempts to resolve
+them as internal links. Links beginning with `/` are resolved relative to
+the content root; otherwise, they are resolved relative to the Markdown
+file. If the link resolves to an existing file that is part of the
+website, it's replaced with an appropriate web-server-friendly link.
+Otherwise, the link isn't changed.
-For example, suppose the file `blog/post1.md` has a link `./post2.md`. The HTML
-output will contain the link `/blog/post2` (which corresponds to
-`/blog/post2/index.html`). Link resolution is applied to _all_ internal links,
-including those pointing to static resources like images. Links are only
-modified if they point to a real file that's not included in the ignore list.
+For example, suppose the file `blog/post1.md` has a link `./post2.md`. The
+HTML output will contain the link `/blog/post2` (which corresponds to
+`/blog/post2/index.html`). Link resolution is applied to _all_ internal
+links, including those pointing to static resources like images. Links are
+only modified if they point to a real file that's not included in the
+ignore list.
### Syntax Highlighting
-Zona uses [Pygments] to provide syntax highlighting for fenced code blocks. The
-following Pygments plugins are included:
+Zona uses [Pygments] to provide syntax highlighting for fenced code
+blocks. The following Pygments plugins are included:
-- [pygments-kakoune](https://codeberg.com/ficd/pygments-kakoune)
- - A lexer providing for highlighting Kakoune code. Available under the `kak`
- and `kakrc` aliases.
-- [pygments-ashen](https://codeberg.com/ficd/ashen/tree/main/item/pygments/README.md)
- - An implementation of the [Ashen](https://codeberg.com/ficd/ashen) theme for
- Pygments.
+- [pygments-kakoune](https://git.sr.ht/~ficd/pygments-kakoune)
+ - A lexer providing for highlighting Kakoune code. Available under the
+ `kak` and `kakrc` aliases.
+- [pygments-ashen](https://git.sr.ht/~ficd/ashen/tree/main/item/pygments/README.md)
+ - An implementation of the [Ashen](https://git.sr.ht/~ficd/ashen) theme
+ for Pygments.
If you want to use any external Pygments styles or lexers, they must be
-available in zona's Python environment. For example, you can give zona access to
-[Catppucin](https://github.com/catppuccin/python):
+available in zona's Python environment. For example, you can give zona
+access to [Catppucin](https://github.com/catppuccin/python):
```yaml
# config.yml
@@ -253,9 +252,9 @@ Then, run zona with the following `uv` command:
uvx --with catppucin zona build
```
-Inline syntax highlighting is also provided via a `python-markdown` extension.
-If you prefix inline code with a shebang followed by the language identifier, it
-will be highlighted. For example:
+Inline syntax highlighting is also provided via a `python-markdown`
+extension. If you prefix inline code with a shebang followed by the
+language identifier, it will be highlighted. For example:
```
`#!python print(f"I love {foobar}!", end="")`
@@ -281,9 +280,10 @@ will be rendered as
### Image Labels
-A feature unique to zona is **image labels**. They make it easy to annotate
-images in your Markdown documents. The alt text Markdown element is rendered as
-the label — with support for inline Markdown. Consider this example:
+A feature unique to zona is **image labels**. They make it easy to
+annotate images in your Markdown documents. The alt text Markdown element
+is rendered as the label — with support for inline Markdown. Consider this
+example:
```markdown

@@ -298,14 +298,14 @@ The above results in the following HTML:
```
The `image-container` class is provided as a convenience for styling. The
-default stylesheet centers the label under the image. Note: _links_ inside image
-captions are not currently supported. I am looking into a solution.
+default stylesheet centers the label under the image. Note: _links_ inside
+image captions are not currently supported. I am looking into a solution.
### Frontmatter
-YAML frontmatter can be used to configure the metadata of documents. All of them
-are optional. `none` is used when the option is unset. The following options are
-available:
+YAML frontmatter can be used to configure the metadata of documents. All
+of them are optional. `none` is used when the option is unset. The
+following options are available:
| Key | Type & Default | Description |
| ------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------ |
@@ -338,9 +338,10 @@ template: post_list
Welcome to my blog! Please find a list of my posts below.
```
-Setting `post: false` is necessary because, by default, all documents inside
-`content/blog` are considered to be posts unless explicitly disabled in the
-frontmatter. We don't want the post list to list _itself_ as a post.
+Setting `post: false` is necessary because, by default, all documents
+inside `content/blog` are considered to be posts unless explicitly
+disabled in the frontmatter. We don't want the post list to list _itself_
+as a post.
Then, you'd create `content/blog/my-post.md` and populate it:
@@ -351,32 +352,32 @@ date: July 5, 2025
---
```
-Because `my-post` is inside the `blog` directory, `post: true` is implied. If
-you wanted to put it somewhere outside `blog`, you would need to set
+Because `my-post` is inside the `blog` directory, `post: true` is implied.
+If you wanted to put it somewhere outside `blog`, you would need to set
`post: true` for it to be included in the post list.
## Configuration
-Zona is configured in YAML format. The configuration file is called `config.yml`
-and it **must** be located in the root of the project — in the same directory as
-`content` and `templates`.
+Zona is configured in YAML format. The configuration file is called
+`config.yml` and it **must** be located in the root of the project — in
+the same directory as `content` and `templates`.
-Your configuration will be merged with the defaults. `zona init` also writes a
-copy of the default configuration to the correct location. If it exists, you'll
-be prompted before overwriting it.
+Your configuration will be merged with the defaults. `zona init` also
+writes a copy of the default configuration to the correct location. If it
+exists, you'll be prompted before overwriting it.
-**Note:** Currently, not every configuration value is actually used. Only the
-useful settings are listed here.
+**Note:** Currently, not every configuration value is actually used. Only
+the useful settings are listed here.
Please see the default configuration:
```yaml
-base_url: /
sitemap:
Home: /
ignore:
- .marksman.toml
markdown:
+ image_labels: true
tab_length: 2
syntax_highlighting:
enabled: true
@@ -384,60 +385,49 @@ markdown:
wrap: false
links:
external_new_tab: true
-build:
- clean_output_dir: true
- include_drafts: false
blog:
dir: blog
-server:
- reload:
- enabled: true
- scroll_tolerance: 100
```
-| Name | Description |
-| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
-| `sitemap` | Sitemap dictionary. See [Sitemap](#sitemap). |
-| `ignore` | List of paths to ignore. See [Ignore List](#ignore-list). |
-| `markdown.tab_length` | How many spaces should be considered an indentation level. |
-| `markdown.syntax_highlighting.enabled` | Whether code should be highlighted. |
-| `markdown.syntax_highlighting.theme` | [Pygments] style for highlighting. |
-| `markdown.syntax_highlighting.wrap` | Whether the resulting code block should be word wrapped. |
-| `markdown.links.external_new_tab` | Whether external links should be opened in a new tab. |
-| `build.clean_output_dir` | Whether previous build artifacts should be cleared when building. Recommended to leave this on. |
-| `build.include_drafts` | Whether drafts should be included by default. |
-| `blog.dir` | Name of a directory relative to `content/` whose children are automatically considered posts. |
-| `server.reload.enabled` | Whether the preview server should use [live reload](#live-preview). |
-| `server.reload.scroll_tolerance` | The distance, in pixels, from the bottom to still count as "scrolled to bottom". |
+| Name | Description |
+| -------------------------------------- | --------------------------------------------------------------------------------------------- |
+| `sitemap` | Sitemap dictionary. See [Sitemap](#sitemap). |
+| `ignore` | List of paths to ignore. See [Ignore List](#ignore-list). |
+| `markdown.tab_length` | How many spaces should be considered an indentation level. |
+| `markdown.syntax_highlighting.enabled` | Whether code should be highlighted. |
+| `markdown.syntax_highlighting.theme` | [Pygments] style for highlighting. |
+| `markdown.syntax_highlighting.wrap` | Whether the resulting code block should be word wrapped. |
+| `markdown.links.external_new_tab` | Whether external links should be opened in a new tab. |
+| `blog.dir` | Name of a directory relative to `content/` whose children are automatically considered posts. |
### Sitemap
-You can define a sitemap in the configuration file. This is a list of links that
-will be rendered at the top of every page. The `sitemap` is a dictionary of
-`string` to `string` pairs, where each key is the displayed text of the link,
-and the value if the `href`. Consider this example:
+You can define a sitemap in the configuration file. This is a list of
+links that will be rendered at the top of every page. The `sitemap` is a
+dictionary of `string` to `string` pairs, where each key is the displayed
+text of the link, and the value if the `href`. Consider this example:
```yaml
sitemap:
Home: /
About: /about
Blog: /blog
- Git: https://git.ficd.sh/ficd
+ Git: https://git.sr.ht/~ficd
```
### Ignore List
-You can set a list of glob patterns in the [configuration](#configuration) that
-should be ignored by zona. This is useful because zona makes a copy of _every_
-file it encounters inside the `content` directory, regardless of its type. The
-paths must be relative to the `content` directory.
+You can set a list of glob patterns in the [configuration](#configuration)
+that should be ignored by zona. This is useful because zona makes a copy
+of _every_ file it encounters inside the `content` directory, regardless
+of its type. The paths must be relative to the `content` directory.
### Drafts
-zona allows you to begin writing content without including it in the final build
-output. If you set `draft: true` in a page's frontmatter, it will be marked as a
-draft. Drafts are completely excluded from `zona build` and `zona serve` unless
-the `--draft` flag is specified.
+zona allows you to begin writing content without including it in the final
+build output. If you set `draft: true` in a page's frontmatter, it will be
+marked as a draft. Drafts are completely excluded from `zona build` and
+`zona serve` unless the `--draft` flag is specified.
-[Ashen]: https://codeberg.com/ficd/ashen
+[Ashen]: https://sr.ht/~ficd/ashen
[Pygments]: https://pygments.org/
diff --git a/src/zona/cli.py b/src/zona/cli.py
index a7e2dd5..1d32c4c 100644
--- a/src/zona/cli.py
+++ b/src/zona/cli.py
@@ -95,15 +95,14 @@ def serve(
bool,
typer.Option("--final", "-f", help="Don't include drafts."),
] = False,
- live_reload: Annotated[
- bool | None,
+ no_live_reload: Annotated[
+ bool,
typer.Option(
- "--live-reload/--no-live-reload",
- "-l/-L",
- help="Automatically reload web preview. Overrides config.",
- show_default=False,
+ "--no-live-reload",
+ "-n",
+ help="Don't automatically reload web preview.",
),
- ] = None,
+ ] = False,
):
"""
Build the website and start a live preview server.
@@ -116,17 +115,13 @@ def serve(
print("Preview without drafts.")
else:
print("Preview with drafts.")
- if live_reload is None:
- reload = None
- else:
- reload = live_reload
server.serve(
root=root,
output=output,
draft=not final,
host=host,
port=port,
- user_reload=reload,
+ live_reload=not no_live_reload,
)
diff --git a/src/zona/config.py b/src/zona/config.py
index cc56ec2..4bd7a42 100644
--- a/src/zona/config.py
+++ b/src/zona/config.py
@@ -58,17 +58,6 @@ class BuildConfig:
include_drafts: bool = False
-@dataclass
-class ReloadConfig:
- enabled: bool = True
- scroll_tolerance: int = 100
-
-
-@dataclass
-class ServerConfig:
- reload: ReloadConfig = field(default_factory=ReloadConfig)
-
-
IGNORELIST = [".marksman.toml"]
@@ -82,7 +71,6 @@ class ZonaConfig:
markdown: MarkdownConfig = field(default_factory=MarkdownConfig)
build: BuildConfig = field(default_factory=BuildConfig)
blog: BlogConfig = field(default_factory=BlogConfig)
- server: ServerConfig = field(default_factory=ServerConfig)
@classmethod
def from_file(cls, path: Path) -> "ZonaConfig":
diff --git a/src/zona/data/server/inject.js b/src/zona/data/server/inject.js
deleted file mode 100644
index bc00dde..0000000
--- a/src/zona/data/server/inject.js
+++ /dev/null
@@ -1,25 +0,0 @@
-(() => {
- // if user at the bottom before reload, scroll to new bottom
- if (localStorage.getItem("wasAtBottom") === "1") {
- localStorage.removeItem("wasAtBottom");
- window.addEventListener("load", () => {
- requestAnimationFrame(() => {
- window.scrollTo(0, document.body.scrollHeight);
- });
- });
- }
-
- const ws = new WebSocket("__SOCKET_ADDRESS__");
- const tol = __SCROLL_TOLERANCE__;
- ws.onmessage = event => {
- if (event.data === "reload") {
- // store flag if user currently at bottom
- const nearBottom = window.innerHeight + window.scrollY
- >= document.body.scrollHeight - tol;
- if (nearBottom) {
- localStorage.setItem("wasAtBottom", "1");
- }
- location.reload();
- }
- };
-})();
diff --git a/src/zona/server.py b/src/zona/server.py
index 23c4c0b..fa0c033 100644
--- a/src/zona/server.py
+++ b/src/zona/server.py
@@ -13,7 +13,6 @@ from rich import print
from watchdog.events import FileSystemEvent, FileSystemEventHandler
from watchdog.observers import Observer
-from zona import util
from zona.builder import ZonaBuilder
from zona.log import get_logger
from zona.websockets import WebSocketServer
@@ -21,23 +20,18 @@ from zona.websockets import WebSocketServer
logger = get_logger()
-def make_reload_script(
- host: str, port: int, scroll_tolerance: int
-) -> str:
+def make_reload_script(host: str, port: int) -> str:
"""Generates the JavaScript that must be injected into HTML pages for the live reloading to work."""
- js = util.get_resource("server/inject.js").contents
- js = util.minify_js(js)
- address = f"ws://{host}:{port}"
- for placeholder, value in (
- ("__SOCKET_ADDRESS__", address),
- ("__SCROLL_TOLERANCE__", scroll_tolerance),
- ):
- if placeholder not in js:
- raise ValueError(
- f"{placeholder} missing from reload script template!"
- )
- js = js.replace(placeholder, str(value))
- return f""
+ return f"""
+
+"""
def make_handler_class(script: str):
@@ -177,13 +171,12 @@ def serve(
draft: bool = True,
host: str = "localhost",
port: int = 8000,
- user_reload: bool | None = None,
+ live_reload: bool = True,
):
"""Serve preview website with live reload and automatic rebuild."""
# create temp dir, automatic cleanup
with tempfile.TemporaryDirectory() as tmp:
builder = ZonaBuilder(root, Path(tmp), draft)
- config = builder.config
# initial site build
builder.build()
# use discovered paths if none provided
@@ -192,21 +185,13 @@ def serve(
if root is None:
root = builder.layout.root
- # use config value unless overridden by user
- reload = config.server.reload.enabled
- if user_reload is not None:
- reload = user_reload
- if reload:
- print("Live reloading is enabled.")
- # spin up websocket server for live reloading
+ # spin up websocket server for live reloading
+ if live_reload:
ws_port = port + 1
ws_server = WebSocketServer(host, ws_port)
ws_server.start()
# generate reload script for injection
- scroll_tolerance = config.server.reload.scroll_tolerance
- reload_script = make_reload_script(
- host, ws_port, scroll_tolerance
- )
+ reload_script = make_reload_script(host, ws_port)
# generate handler with reload script as attribute
handler = make_handler_class(reload_script)
else:
diff --git a/src/zona/util.py b/src/zona/util.py
index 2d5c514..7e80500 100644
--- a/src/zona/util.py
+++ b/src/zona/util.py
@@ -1,5 +1,4 @@
import fnmatch
-import re
import string
from importlib import resources
from importlib.resources.abc import Traversable
@@ -13,15 +12,6 @@ class ZonaResource(NamedTuple):
contents: str
-def get_resource(path: str) -> ZonaResource:
- """Load the packaged resource in data/path"""
- file = resources.files("zona").joinpath("data", path)
- if file.is_file():
- return ZonaResource(name=path, contents=file.read_text())
- else:
- raise FileNotFoundError(f"{path} is not a valid Zona resource!")
-
-
def get_resources(subdir: str) -> list[ZonaResource]:
"""Load the packaged resources in data/subdir"""
out: list[ZonaResource] = []
@@ -75,28 +65,11 @@ def normalize_url(url: str) -> str:
return url
-def should_ignore(path: Path, patterns: list[str], base: Path) -> bool:
+def should_ignore(
+ path: Path, patterns: list[str], base: Path
+) -> bool:
rel_path = path.relative_to(base)
return any(
- fnmatch.fnmatch(str(rel_path), pattern) for pattern in patterns
+ fnmatch.fnmatch(str(rel_path), pattern)
+ for pattern in patterns
)
-
-
-MINIFY_JS_PATTERN = re.compile(
- r"""
- //.*?$ |
- /\*.*?\*/ |
- \s+
- """,
- re.MULTILINE | re.DOTALL | re.VERBOSE,
-)
-
-
-def minify_js(js: str) -> str:
- """Naively minifies JavaScript by stripping comments and whitespace."""
- return MINIFY_JS_PATTERN.sub(
- # replace whitespace with single space,
- # strip comments
- lambda m: " " if m.group(0).isspace() else "",
- js,
- ).strip()