Cours/venv/lib/python3.12/site-packages/mkdocs/commands/serve.py

113 lines
3.3 KiB
Python

from __future__ import annotations
import logging
import shutil
import tempfile
from os.path import isdir, isfile, join
from typing import TYPE_CHECKING
from urllib.parse import urlsplit
from mkdocs.commands.build import build
from mkdocs.config import load_config
from mkdocs.livereload import LiveReloadServer, _serve_url
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
log = logging.getLogger(__name__)
def serve(
config_file: str | None = None,
livereload: bool = True,
build_type: str | None = None,
watch_theme: bool = False,
watch: list[str] = [],
*,
open_in_browser: bool = False,
**kwargs,
) -> None:
"""
Start the MkDocs development server.
By default it will serve the documentation on http://localhost:8000/ and
it will rebuild the documentation and refresh the page automatically
whenever a file is edited.
"""
# Create a temporary build directory, and set some options to serve it
# PY2 returns a byte string by default. The Unicode prefix ensures a Unicode
# string is returned. And it makes MkDocs temp dirs easier to identify.
site_dir = tempfile.mkdtemp(prefix='mkdocs_')
def get_config():
config = load_config(
config_file=config_file,
site_dir=site_dir,
**kwargs,
)
config.watch.extend(watch)
return config
is_clean = build_type == 'clean'
is_dirty = build_type == 'dirty'
config = get_config()
config.plugins.on_startup(command=('build' if is_clean else 'serve'), dirty=is_dirty)
host, port = config.dev_addr
mount_path = urlsplit(config.site_url or '/').path
config.site_url = serve_url = _serve_url(host, port, mount_path)
def builder(config: MkDocsConfig | None = None):
log.info("Building documentation...")
if config is None:
config = get_config()
config.site_url = serve_url
build(config, serve_url=None if is_clean else serve_url, dirty=is_dirty)
server = LiveReloadServer(
builder=builder, host=host, port=port, root=site_dir, mount_path=mount_path
)
def error_handler(code) -> bytes | None:
if code in (404, 500):
error_page = join(site_dir, f'{code}.html')
if isfile(error_page):
with open(error_page, 'rb') as f:
return f.read()
return None
server.error_handler = error_handler
try:
# Perform the initial build
builder(config)
if livereload:
# Watch the documentation files, the config file and the theme files.
server.watch(config.docs_dir)
if config.config_file_path:
server.watch(config.config_file_path)
if watch_theme:
for d in config.theme.dirs:
server.watch(d)
# Run `serve` plugin events.
server = config.plugins.on_serve(server, config=config, builder=builder)
for item in config.watch:
server.watch(item)
try:
server.serve(open_in_browser=open_in_browser)
except KeyboardInterrupt:
log.info("Shutting down...")
finally:
server.shutdown()
finally:
config.plugins.on_shutdown()
if isdir(site_dir):
shutil.rmtree(site_dir)