From 5f3426553d46e38317e9f074bd2cb6ac0233087a Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 28 Apr 2026 03:04:46 +0300 Subject: [PATCH 1/3] Ignore hidden and editor temporary files in livereload file watcher Filter out files that match common editor temporary/backup file patterns in the livereload file watcher callback: - Files starting with '.' (dotfiles, vim swap files like .foo.md.swp) - Files ending with '~' (backup files) - Files matching '#*#' (Emacs auto-save files) This prevents live reload from being triggered repeatedly by editor temporary files, which was especially problematic for vim users where editing .md files creates .foo.md.swp files. Fixes #2519 --- mkdocs/livereload/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mkdocs/livereload/__init__.py b/mkdocs/livereload/__init__.py index 8c4af1c7..8da46dce 100644 --- a/mkdocs/livereload/__init__.py +++ b/mkdocs/livereload/__init__.py @@ -162,6 +162,17 @@ def watch(self, path: str, func: None = None, *, recursive: bool = True) -> None def callback(event): if event.is_directory: return + # Ignore hidden files and editor temporary/backup files: + # - .dotfiles (vim swap .foo.md.swp, .foo.md.swo, .foo.md.swn, etc.) + # - files ending with ~ (editor backup) + # - #files# matching Emacs auto-save pattern + name = os.path.basename(event.src_path) + if ( + name.startswith(".") + or name.endswith("~") + or (name.startswith("#") and name.endswith("#")) + ): + return log.debug(str(event)) with self._rebuild_cond: self._want_rebuild = True From 16dd693e24bdfc668a060e7732cf4c105fd0cf8c Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 28 Apr 2026 03:06:00 +0300 Subject: [PATCH 2/3] Add tests for livereload hidden/temp file filtering Add test cases for: - Dotfiles (.vim swap, .hidden) not triggering rebuild - Editor backup files (~ suffix) not triggering rebuild - Emacs auto-save files (#file#) not triggering rebuild Refs #2519 --- mkdocs/tests/livereload_tests.py | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/mkdocs/tests/livereload_tests.py b/mkdocs/tests/livereload_tests.py index 04594448..4f7d6cdf 100644 --- a/mkdocs/tests/livereload_tests.py +++ b/mkdocs/tests/livereload_tests.py @@ -619,6 +619,46 @@ def test_watches_through_relative_symlinks(self, origin_dir, site_dir): Path(origin_dir, "README.md").write_text("edited") self.assertTrue(started_building.wait(timeout=10)) + @tempdir({"foo.md": "original"}) + def test_ignores_dotfile_changes(self, docs_dir): + """Hidden files (starting with '.') should not trigger rebuild.""" + started_building = threading.Event() + with testing_server(docs_dir, started_building.set) as server: + server.watch(docs_dir) + time.sleep(0.01) + + # Vim swap file + Path(docs_dir, ".foo.md.swp").write_text("swap") + self.assertFalse(started_building.wait(timeout=0.5)) + + # Generic dotfile + Path(docs_dir, ".hidden").write_text("hidden") + self.assertFalse(started_building.wait(timeout=0.5)) + + @tempdir({"foo.md": "original"}) + def test_ignores_tilde_backup_files(self, docs_dir): + """Editor backup files (ending with '~') should not trigger rebuild.""" + started_building = threading.Event() + with testing_server(docs_dir, started_building.set) as server: + server.watch(docs_dir) + time.sleep(0.01) + + # Backup file created by editors + Path(docs_dir, "foo.md~").write_text("backup") + self.assertFalse(started_building.wait(timeout=0.5)) + + @tempdir({"foo.md": "original"}) + def test_ignores_emacs_autosave_files(self, docs_dir): + """Emacs auto-save files (#*#) should not trigger rebuild.""" + started_building = threading.Event() + with testing_server(docs_dir, started_building.set) as server: + server.watch(docs_dir) + time.sleep(0.01) + + # Emacs auto-save pattern + Path(docs_dir, "#foo.md#").write_text("autosave") + self.assertFalse(started_building.wait(timeout=0.5)) + @tempdir() def test_watch_with_broken_symlinks(self, docs_dir): Path(docs_dir, "subdir").mkdir() From eeef1ea13cc686c034eeefbd6b7cb03a83f8ace2 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Sat, 9 May 2026 19:51:00 +0300 Subject: [PATCH 3/3] Add release note for livereload temp file fix --- docs/about/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index 33bcf08e..e8a3afbe 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -31,6 +31,7 @@ The current members of the MkDocs-NG team. * Fix dropdown submenu arrow invisible in the navigation menu. #44 * Fix malformed URLs (e.g., unterminated IPv6 literals) crashing the entire build. #45 * Fix build crash caused by broken (dangling) symlinks in the docs directory. #46 +* Fix livereload triggering unnecessary rebuilds for editor temporary files (vim swap, tilde backups, Emacs auto-save). #55 ### Maintenance