From df2dffd8a62f312e98987998af3114f3e1e552fb Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Sun, 3 Dec 2023 22:00:13 +0100 Subject: [PATCH] New flag `serve --open` to open the site in a browser (#3500) After the first build is finished, the default webbrowser will open the home page of the site. --- mkdocs/__main__.py | 2 ++ mkdocs/commands/serve.py | 4 +++- mkdocs/livereload/__init__.py | 10 ++++++++-- mkdocs/tests/cli_tests.py | 10 ++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/mkdocs/__main__.py b/mkdocs/__main__.py index 0df2069b..41377cf5 100644 --- a/mkdocs/__main__.py +++ b/mkdocs/__main__.py @@ -110,6 +110,7 @@ config_help = ( "Provide a specific MkDocs config. This can be a file name, or '-' to read from stdin." ) dev_addr_help = "IP address and port to serve documentation locally (default: localhost:8000)" +serve_open_help = "Open the website in a Web browser after the initial build finishes." strict_help = "Enable strict mode. This will cause MkDocs to abort the build on any warnings." theme_help = "The theme to use when building your documentation." theme_choices = sorted(utils.get_theme_names()) @@ -249,6 +250,7 @@ def cli(): @cli.command(name="serve") @click.option('-a', '--dev-addr', help=dev_addr_help, metavar='') +@click.option('-o', '--open', 'open_in_browser', help=serve_open_help, is_flag=True) @click.option('--no-livereload', 'livereload', flag_value=False, help=no_reload_help) @click.option('--livereload', 'livereload', flag_value=True, default=True, hidden=True) @click.option('--dirtyreload', 'build_type', flag_value='dirty', hidden=True) diff --git a/mkdocs/commands/serve.py b/mkdocs/commands/serve.py index d6e73b16..889d8066 100644 --- a/mkdocs/commands/serve.py +++ b/mkdocs/commands/serve.py @@ -23,6 +23,8 @@ def serve( build_type: str | None = None, watch_theme: bool = False, watch: list[str] = [], + *, + open_in_browser: bool = False, **kwargs, ) -> None: """ @@ -99,7 +101,7 @@ def serve( server.watch(item) try: - server.serve() + server.serve(open_in_browser=open_in_browser) except KeyboardInterrupt: log.info("Shutting down...") finally: diff --git a/mkdocs/livereload/__init__.py b/mkdocs/livereload/__init__.py index e1d7db31..70d44ba2 100644 --- a/mkdocs/livereload/__init__.py +++ b/mkdocs/livereload/__init__.py @@ -18,6 +18,7 @@ import threading import time import traceback import urllib.parse +import webbrowser import wsgiref.simple_server import wsgiref.util from typing import Any, BinaryIO, Callable, Iterable @@ -168,7 +169,7 @@ class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGISe self._watched_paths.pop(path) self.observer.unschedule(self._watch_refs.pop(path)) - def serve(self): + def serve(self, *, open_in_browser=False): self.server_bind() self.server_activate() @@ -178,8 +179,13 @@ class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGISe paths_str = ", ".join(f"'{_try_relativize_path(path)}'" for path in self._watched_paths) log.info(f"Watching paths for changes: {paths_str}") - log.info(f"Serving on {self.url}") + if open_in_browser: + log.info(f"Serving on {self.url} and opening it in a browser") + else: + log.info(f"Serving on {self.url}") self.serve_thread.start() + if open_in_browser: + webbrowser.open(self.url) self._build_loop() diff --git a/mkdocs/tests/cli_tests.py b/mkdocs/tests/cli_tests.py index 6ce03db1..abd1286e 100644 --- a/mkdocs/tests/cli_tests.py +++ b/mkdocs/tests/cli_tests.py @@ -21,6 +21,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type=None, config_file=None, @@ -53,6 +54,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr='0.0.0.0:80', + open_in_browser=False, livereload=True, build_type=None, config_file=None, @@ -70,6 +72,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type=None, config_file=None, @@ -89,6 +92,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type=None, config_file=None, @@ -108,6 +112,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type=None, config_file=None, @@ -127,6 +132,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type=None, config_file=None, @@ -144,6 +150,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type=None, config_file=None, @@ -161,6 +168,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=False, build_type=None, config_file=None, @@ -178,6 +186,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type='dirty', config_file=None, @@ -195,6 +204,7 @@ class CLITests(unittest.TestCase): self.assertEqual(result.exit_code, 0) mock_serve.assert_called_once_with( dev_addr=None, + open_in_browser=False, livereload=True, build_type=None, config_file=None,