Repository: mkdocs/mkdocs

Issue:
V.1.2: Markdown links earlier processed as html files, are now processed as directories
The new version brings a curious issue. With versions < 1.2, I used internal links in this way, to make a call to page `bar.md`, from page `foo.md`:

```markdown
[linking to content in bar](../bar#content)
```

Which was transformed correctly into:

```html
<a href="../bar/#content">linking to content in bar</a>
```

Since version 1.2, the `bar` is intepreted differently by `mkdocs serve`, which breaks all such links.  I realize this is highly irregular and correct call should have been:

```markdown
[linking to content in bar](bar.md#content)
```

So please dont throw rotten tomatoes at me 🍅 .

But just to help me fix this: why this change of behavior? Has some part been reimplemented? Or has this been intentional, to prevent that kind of error in the future?


Discussion:
oprypin: In https://github.com/mkdocs/mkdocs/issues/2456#issuecomment-881876681 I see that people can perceive this as a blocker even regardless of the fact that it used to work before. So I decided to finally tackle it.

@ultrabug Any objections? Otherwise, merging this tomorrow

Patch:
diff --git a/mkdocs/livereload/__init__.py b/mkdocs/livereload/__init__.py
index 83803e0a..c9f7afa8 100644
--- a/mkdocs/livereload/__init__.py
+++ b/mkdocs/livereload/__init__.py
@@ -183,10 +183,10 @@ class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGISe
         if path == "/js/livereload.js":
             file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "livereload.js")
         elif path.startswith(self.mount_path):
+            rel_file_path = path[len(self.mount_path):].lstrip("/")
             if path.endswith("/"):
-                path += "index.html"
-            path = path[len(self.mount_path):]
-            file_path = os.path.join(self.root, path.lstrip("/"))
+                rel_file_path += "index.html"
+            file_path = os.path.join(self.root, rel_file_path)
         elif path == "/":
             start_response("302 Found", [("Location", self.mount_path)])
             return []
@@ -201,9 +201,12 @@ class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGISe
         try:
             file = open(file_path, "rb")
         except OSError:
+            if not path.endswith("/") and os.path.isfile(os.path.join(file_path, "index.html")):
+                start_response("302 Found", [("Location", path + "/")])
+                return []
             return None  # Not found
 
-        if path.endswith(".html"):
+        if file_path.endswith(".html"):
             with file:
                 content = file.read()
             content = self._inject_js_into_html(content, epoch)


Test patch:
diff --git a/mkdocs/tests/livereload_tests.py b/mkdocs/tests/livereload_tests.py
index cafa21dc..6ec81fda 100644
--- a/mkdocs/tests/livereload_tests.py
+++ b/mkdocs/tests/livereload_tests.py
@@ -293,7 +293,7 @@ class BuildTests(unittest.TestCase):
             self.assertRegex(output, fr"^<body>foo</body><body>bar{SCRIPT_REGEX}</body>$")
 
     @tempdir({"index.html": "<body>aaa</body>", "foo/index.html": "<body>bbb</body>"})
-    def test_serves_modified_index(self, site_dir):
+    def test_serves_directory_index(self, site_dir):
         with testing_server(site_dir) as server:
             headers, output = do_request(server, "GET /")
             self.assertRegex(output, fr"^<body>aaa{SCRIPT_REGEX}</body>$")
@@ -301,8 +301,21 @@ class BuildTests(unittest.TestCase):
             self.assertEqual(headers.get("content-type"), "text/html")
             self.assertEqual(headers.get("content-length"), str(len(output)))
 
-            _, output = do_request(server, "GET /foo/")
-            self.assertRegex(output, fr"^<body>bbb{SCRIPT_REGEX}</body>$")
+            for path in "/foo/", "/foo/index.html":
+                _, output = do_request(server, "GET /foo/")
+                self.assertRegex(output, fr"^<body>bbb{SCRIPT_REGEX}</body>$")
+
+            with self.assertLogs("mkdocs.livereload"):
+                headers, _ = do_request(server, "GET /foo/index.html/")
+            self.assertEqual(headers["_status"], "404 Not Found")
+
+    @tempdir({"foo/bar/index.html": "<body>aaa</body>"})
+    def test_redirects_to_directory(self, site_dir):
+        with testing_server(site_dir, mount_path="/sub") as server:
+            with self.assertLogs("mkdocs.livereload"):
+                headers, _ = do_request(server, "GET /sub/foo/bar")
+            self.assertEqual(headers["_status"], "302 Found")
+            self.assertEqual(headers.get("location"), "/sub/foo/bar/")
 
     @tempdir({"я.html": "<body>aaa</body>", "测试2/index.html": "<body>bbb</body>"})
     def test_serves_with_unicode_characters(self, site_dir):