Repository: mkdocs/mkdocs

Issue:
Link to paragraph on index.md breaks
I try to link from a subpage to a paragraph on my root index.md:

`[MyLink](../index.md#contact)`

This results when clicking in a 404 trying to open the following URL:

`documentation#contact`

Correct would be to link to 

`documentation/#contact` (note the slash)

Just linking to the page itself works fine

`[MyLink](../index.md)`

`documentation/` (slash is in the link)

Anybody has a clue if I do anything wrong or if this is a bug?

I use mkdocs with Materials template. Can provide more if required.

Discussion:

Patch:
diff --git a/mkdocs/livereload/__init__.py b/mkdocs/livereload/__init__.py
index c2e52ab8..e136ff05 100644
--- a/mkdocs/livereload/__init__.py
+++ b/mkdocs/livereload/__init__.py
@@ -246,7 +246,7 @@ class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGISe
                         self._epoch_cond.wait_for(condition, timeout=self.poll_response_timeout)
                     return [b"%d" % self._visible_epoch]
 
-        if path.startswith(self.mount_path):
+        if (path + "/").startswith(self.mount_path):
             rel_file_path = path[len(self.mount_path) :]
 
             if path.endswith("/"):
diff --git a/mkdocs/structure/files.py b/mkdocs/structure/files.py
index e469c9e4..91679f82 100644
--- a/mkdocs/structure/files.py
+++ b/mkdocs/structure/files.py
@@ -230,10 +230,7 @@ class File:
         url = self.dest_uri
         dirname, filename = posixpath.split(url)
         if use_directory_urls and filename == 'index.html':
-            if dirname == '':
-                url = '.'
-            else:
-                url = dirname + '/'
+            url = (dirname or '.') + '/'
         return urlquote(url)
 
     def url_relative_to(self, other: File) -> str:
diff --git a/mkdocs/structure/pages.py b/mkdocs/structure/pages.py
index f24ad967..6592495b 100644
--- a/mkdocs/structure/pages.py
+++ b/mkdocs/structure/pages.py
@@ -88,7 +88,7 @@ class Page:
     @property
     def url(self) -> str:
         """The URL of the page relative to the MkDocs `site_dir`."""
-        return '' if self.file.url == '.' else self.file.url
+        return '' if self.file.url in ('.', './') else self.file.url
 
     file: File
     """The documentation [`File`][mkdocs.structure.files.File] that the page is being rendered from."""
@@ -133,7 +133,7 @@ class Page:
     @property
     def is_homepage(self) -> bool:
         """Evaluates to `True` for the homepage of the site and `False` for all other pages."""
-        return self.is_top_level and self.is_index and self.file.url in ['.', 'index.html']
+        return self.is_top_level and self.is_index and self.file.url in ('.', './', 'index.html')
 
     previous_page: Optional[Page]
     """The [page][mkdocs.structure.pages.Page] object for the previous page or `None`.


Test patch:
diff --git a/mkdocs/tests/structure/file_tests.py b/mkdocs/tests/structure/file_tests.py
index 7f5fd1ee..8d8257f0 100644
--- a/mkdocs/tests/structure/file_tests.py
+++ b/mkdocs/tests/structure/file_tests.py
@@ -168,7 +168,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
         self.assertPathsEqual(f.abs_src_path, '/path/to/docs/index.md')
         self.assertEqual(f.dest_uri, 'index.html')
         self.assertPathsEqual(f.abs_dest_path, '/path/to/site/index.html')
-        self.assertEqual(f.url, '.')
+        self.assertEqual(f.url, './')
         self.assertEqual(f.name, 'index')
         self.assertTrue(f.is_documentation_page())
         self.assertFalse(f.is_static_page())
@@ -182,7 +182,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
         self.assertPathsEqual(f.abs_src_path, '/path/to/docs/README.md')
         self.assertEqual(f.dest_uri, 'index.html')
         self.assertPathsEqual(f.abs_dest_path, '/path/to/site/index.html')
-        self.assertEqual(f.url, '.')
+        self.assertEqual(f.url, './')
         self.assertEqual(f.name, 'index')
         self.assertTrue(f.is_documentation_page())
         self.assertFalse(f.is_static_page())
@@ -446,7 +446,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
         ]
 
         to_file_urls = [
-            '.',
+            './',
             'foo/',
             'foo/bar/',
             'foo/bar/baz/',
@@ -493,18 +493,18 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
 
         from_file = File('index.html', '/path/to/docs', '/path/to/site', use_directory_urls=True)
         expected = [
-            '.',  # . relative to .
-            '..',  # . relative to foo/
-            '../..',  # . relative to foo/bar/
-            '../../..',  # . relative to foo/bar/baz/
-            '..',  # . relative to foo
-            '../..',  # . relative to foo/bar
-            '../../..',  # . relative to foo/bar/baz
+            './',  # . relative to .
+            '../',  # . relative to foo/
+            '../../',  # . relative to foo/bar/
+            '../../../',  # . relative to foo/bar/baz/
+            '../',  # . relative to foo
+            '../../',  # . relative to foo/bar
+            '../../../',  # . relative to foo/bar/baz
         ]
 
         for i, filename in enumerate(to_files):
             file = File(filename, '/path/to/docs', '/path/to/site', use_directory_urls=True)
-            self.assertEqual(from_file.url, '.')
+            self.assertEqual(from_file.url, './')
             self.assertEqual(file.url, to_file_urls[i])
             self.assertEqual(from_file.url_relative_to(file.url), expected[i])
             self.assertEqual(from_file.url_relative_to(file), expected[i])
diff --git a/mkdocs/tests/structure/page_tests.py b/mkdocs/tests/structure/page_tests.py
index 24b17a01..9ccd9ff8 100644
--- a/mkdocs/tests/structure/page_tests.py
+++ b/mkdocs/tests/structure/page_tests.py
@@ -659,7 +659,7 @@ class RelativePathExtensionTests(unittest.TestCase):
     def test_relative_html_link_index(self):
         self.assertEqual(
             self.get_rendered_result(['non-index.md', 'index.md']),
-            '<p><a href="..">link</a></p>',
+            '<p><a href="../">link</a></p>',
         )
 
     @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/index.md)'))
@@ -696,7 +696,7 @@ class RelativePathExtensionTests(unittest.TestCase):
     def test_relative_html_link_parent_index(self):
         self.assertEqual(
             self.get_rendered_result(['sub2/non-index.md', 'index.md']),
-            '<p><a href="../..">link</a></p>',
+            '<p><a href="../../">link</a></p>',
         )
 
     @mock.patch(