We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Unexpected behaviour with page.is_homepage
Starting a new site and rolling my own theme. Came across some slightly odd behaviour.

Mkdocs version 1.0.4
Python version 3.7.1

**Expected:**
`page.is_homepage` evaluates to True on the home (index.md) of the site, and false on all other pages.

**Actual:**
`page.is_homepage` evaluates to True on the home (index.md), and on any other index.md that is included in the nav object without nesting.

**Examples:**

The unexpected result:

```
nav:
  - Home: index.md  <--- page.is_homepage evaluates to True
  - About: about.md <--- page.is_homepage evaluates to False
  - Projects: projects/index.md <--- page.is_homepage evaluates to True
```

Changing the filename causes it to evaluate to false:

```
nav:
  - Home: index.md  <--- page.is_homepage evaluates to True
  - About: about.md <--- page.is_homepage evaluates to False
  - Projects: projects/test.md <--- page.is_homepage evaluates to False
```

If I tweak it a bit, so that the sections are nested, then it evaluates to false as I'd expect:

```
nav:
  - About: 
      - About: about.md <--- page.is_homepage evaluates to False
  - Projects: 
       - Project home: projects/index.md <--- page.is_homepage evaluates to False
```

This feels like a bug - especially as simply changing the markdown file name causes the behaviour to change.



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mkdocs/structure/pages.py`
Content:
```
1 # coding: utf-8
2 
3 from __future__ import unicode_literals
4 
5 import os
6 import io
7 import datetime
8 import logging
9 
10 import markdown
11 from markdown.extensions import Extension
12 from markdown.treeprocessors import Treeprocessor
13 from markdown.util import AMP_SUBSTITUTE
14 
15 from mkdocs.structure.toc import get_toc
16 from mkdocs.utils import meta, urlparse, urlunparse, urljoin, urlunquote, get_markdown_title, warning_filter
17 
18 log = logging.getLogger(__name__)
19 log.addFilter(warning_filter)
20 
21 
22 class Page(object):
23     def __init__(self, title, file, config):
24         file.page = self
25         self.file = file
26         self.title = title
27 
28         # Navigation attributes
29         self.parent = None
30         self.children = None
31         self.previous_page = None
32         self.next_page = None
33         self.active = False
34 
35         self.is_section = False
36         self.is_page = True
37         self.is_link = False
38 
39         # Support SOURCE_DATE_EPOCH environment variable for "reproducible" builds.
40         # See https://reproducible-builds.org/specs/source-date-epoch/
41         if 'SOURCE_DATE_EPOCH' in os.environ:
42             self.update_date = datetime.datetime.utcfromtimestamp(
43                 int(os.environ['SOURCE_DATE_EPOCH'])
44             ).strftime("%Y-%m-%d")
45         else:
46             self.update_date = datetime.datetime.now().strftime("%Y-%m-%d")
47 
48         self._set_canonical_url(config.get('site_url', None))
49         self._set_edit_url(config.get('repo_url', None), config.get('edit_uri', None))
50 
51         # Placeholders to be filled in later in the build process.
52         self.markdown = None
53         self.content = None
54         self.toc = []
55         self.meta = {}
56 
57     def __eq__(self, other):
58 
59         def sub_dict(d):
60             return dict((key, value) for key, value in d.items() if key in ['title', 'file'])
61 
62         return (isinstance(other, self.__class__) and sub_dict(self.__dict__) == sub_dict(other.__dict__))
63 
64     def __ne__(self, other):
65         return not self.__eq__(other)
66 
67     def __repr__(self):
68         title = "'{}'".format(self.title) if (self.title is not None) else '[blank]'
69         return "Page(title={}, url='{}')".format(title, self.abs_url or self.file.url)
70 
71     def _indent_print(self, depth=0):
72         return '{}{}'.format('    ' * depth, repr(self))
73 
74     def _get_active(self):
75         """ Return active status of page. """
76         return self.__active
77 
78     def _set_active(self, value):
79         """ Set active status of page and ancestors. """
80         self.__active = bool(value)
81         if self.parent is not None:
82             self.parent.active = bool(value)
83 
84     active = property(_get_active, _set_active)
85 
86     @property
87     def is_index(self):
88         return self.file.name == 'index'
89 
90     @property
91     def is_top_level(self):
92         return self.parent is None
93 
94     @property
95     def is_homepage(self):
96         return self.is_top_level and self.is_index
97 
98     @property
99     def url(self):
100         return '' if self.file.url == '.' else self.file.url
101 
102     @property
103     def ancestors(self):
104         if self.parent is None:
105             return []
106         return [self.parent] + self.parent.ancestors
107 
108     def _set_canonical_url(self, base):
109         if base:
110             if not base.endswith('/'):
111                 base += '/'
112             self.canonical_url = urljoin(base, self.url)
113             self.abs_url = urlparse(self.canonical_url).path
114         else:
115             self.canonical_url = None
116             self.abs_url = None
117 
118     def _set_edit_url(self, repo_url, edit_uri):
119         if repo_url and edit_uri:
120             src_path = self.file.src_path.replace('\\', '/')
121             self.edit_url = urljoin(repo_url, edit_uri + src_path)
122         else:
123             self.edit_url = None
124 
125     def read_source(self, config):
126         source = config['plugins'].run_event(
127             'page_read_source', page=self, config=config
128         )
129         if source is None:
130             try:
131                 with io.open(self.file.abs_src_path, 'r', encoding='utf-8-sig', errors='strict') as f:
132                     source = f.read()
133             except IOError:
134                 log.error('File not found: {}'.format(self.file.src_path))
135                 raise
136             except ValueError:
137                 log.error('Encoding error reading file: {}'.format(self.file.src_path))
138                 raise
139 
140         self.markdown, self.meta = meta.get_data(source)
141         self._set_title()
142 
143     def _set_title(self):
144         """
145         Set the title for a Markdown document.
146 
147         Check these in order and use the first that returns a valid title:
148         - value provided on init (passed in from config)
149         - value of metadata 'title'
150         - content of the first H1 in Markdown content
151         - convert filename to title
152         """
153         if self.title is not None:
154             return
155 
156         if 'title' in self.meta:
157             self.title = self.meta['title']
158             return
159 
160         title = get_markdown_title(self.markdown)
161 
162         if title is None:
163             if self.is_homepage:
164                 title = 'Home'
165             else:
166                 title = self.file.name.replace('-', ' ').replace('_', ' ')
167                 # Capitalize if the filename was all lowercase, otherwise leave it as-is.
168                 if title.lower() == title:
169                     title = title.capitalize()
170 
171         self.title = title
172 
173     def render(self, config, files):
174         """
175         Convert the Markdown source file to HTML as per the config.
176         """
177 
178         extensions = [
179             _RelativePathExtension(self.file, files)
180         ] + config['markdown_extensions']
181 
182         md = markdown.Markdown(
183             extensions=extensions,
184             extension_configs=config['mdx_configs'] or {}
185         )
186         self.content = md.convert(self.markdown)
187         self.toc = get_toc(getattr(md, 'toc', ''))
188 
189 
190 class _RelativePathTreeprocessor(Treeprocessor):
191     def __init__(self, file, files):
192         self.file = file
193         self.files = files
194 
195     def run(self, root):
196         """
197         Update urls on anchors and images to make them relative
198 
199         Iterates through the full document tree looking for specific
200         tags and then makes them relative based on the site navigation
201         """
202         for element in root.iter():
203             if element.tag == 'a':
204                 key = 'href'
205             elif element.tag == 'img':
206                 key = 'src'
207             else:
208                 continue
209 
210             url = element.get(key)
211             new_url = self.path_to_url(url)
212             element.set(key, new_url)
213 
214         return root
215 
216     def path_to_url(self, url):
217         scheme, netloc, path, params, query, fragment = urlparse(url)
218 
219         if (scheme or netloc or not path or url.startswith('/')
220                 or AMP_SUBSTITUTE in url or '.' not in os.path.split(path)[-1]):
221             # Ignore URLs unless they are a relative link to a source file.
222             # AMP_SUBSTITUTE is used internally by Markdown only for email.
223             # No '.' in the last part of a path indicates path does not point to a file.
224             return url
225 
226         # Determine the filepath of the target.
227         target_path = os.path.join(os.path.dirname(self.file.src_path), urlunquote(path))
228         target_path = os.path.normpath(target_path).lstrip(os.sep)
229 
230         # Validate that the target exists in files collection.
231         if target_path not in self.files:
232             log.warning(
233                 "Documentation file '{}' contains a link to '{}' which is not found "
234                 "in the documentation files.".format(self.file.src_path, target_path)
235             )
236             return url
237         target_file = self.files.get_file_from_path(target_path)
238         path = target_file.url_relative_to(self.file)
239         components = (scheme, netloc, path, params, query, fragment)
240         return urlunparse(components)
241 
242 
243 class _RelativePathExtension(Extension):
244     """
245     The Extension class is what we pass to markdown, it then
246     registers the Treeprocessor.
247     """
248 
249     def __init__(self, file, files):
250         self.file = file
251         self.files = files
252 
253     def extendMarkdown(self, md, md_globals):
254         relpath = _RelativePathTreeprocessor(self.file, self.files)
255         md.treeprocessors.add("relpath", relpath, "_end")
256
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mkdocs/structure/pages.py b/mkdocs/structure/pages.py
--- a/mkdocs/structure/pages.py
+++ b/mkdocs/structure/pages.py
@@ -93,7 +93,7 @@
 
     @property
     def is_homepage(self):
-        return self.is_top_level and self.is_index
+        return self.is_top_level and self.is_index and self.file.url == '.'
 
     @property
     def url(self):

{"golden_diff": "diff --git a/mkdocs/structure/pages.py b/mkdocs/structure/pages.py\n--- a/mkdocs/structure/pages.py\n+++ b/mkdocs/structure/pages.py\n@@ -93,7 +93,7 @@\n \n     @property\n     def is_homepage(self):\n-        return self.is_top_level and self.is_index\n+        return self.is_top_level and self.is_index and self.file.url == '.'\n \n     @property\n     def url(self):\n", "issue": "Unexpected behaviour with page.is_homepage\nStarting a new site and rolling my own theme. Came across some slightly odd behaviour.\r\n\r\nMkdocs version 1.0.4\r\nPython version 3.7.1\r\n\r\n**Expected:**\r\n`page.is_homepage` evaluates to True on the home (index.md) of the site, and false on all other pages.\r\n\r\n**Actual:**\r\n`page.is_homepage` evaluates to True on the home (index.md), and on any other index.md that is included in the nav object without nesting.\r\n\r\n**Examples:**\r\n\r\nThe unexpected result:\r\n\r\n```\r\nnav:\r\n  - Home: index.md  <--- page.is_homepage evaluates to True\r\n  - About: about.md <--- page.is_homepage evaluates to False\r\n  - Projects: projects/index.md <--- page.is_homepage evaluates to True\r\n```\r\n\r\nChanging the filename causes it to evaluate to false:\r\n\r\n```\r\nnav:\r\n  - Home: index.md  <--- page.is_homepage evaluates to True\r\n  - About: about.md <--- page.is_homepage evaluates to False\r\n  - Projects: projects/test.md <--- page.is_homepage evaluates to False\r\n```\r\n\r\nIf I tweak it a bit, so that the sections are nested, then it evaluates to false as I'd expect:\r\n\r\n```\r\nnav:\r\n  - About: \r\n      - About: about.md <--- page.is_homepage evaluates to False\r\n  - Projects: \r\n       - Project home: projects/index.md <--- page.is_homepage evaluates to False\r\n```\r\n\r\nThis feels like a bug - especially as simply changing the markdown file name causes the behaviour to change.\r\n\r\n\n", "before_files": [{"content": "# coding: utf-8\n\nfrom __future__ import unicode_literals\n\nimport os\nimport io\nimport datetime\nimport logging\n\nimport markdown\nfrom markdown.extensions import Extension\nfrom markdown.treeprocessors import Treeprocessor\nfrom markdown.util import AMP_SUBSTITUTE\n\nfrom mkdocs.structure.toc import get_toc\nfrom mkdocs.utils import meta, urlparse, urlunparse, urljoin, urlunquote, get_markdown_title, warning_filter\n\nlog = logging.getLogger(__name__)\nlog.addFilter(warning_filter)\n\n\nclass Page(object):\n    def __init__(self, title, file, config):\n        file.page = self\n        self.file = file\n        self.title = title\n\n        # Navigation attributes\n        self.parent = None\n        self.children = None\n        self.previous_page = None\n        self.next_page = None\n        self.active = False\n\n        self.is_section = False\n        self.is_page = True\n        self.is_link = False\n\n        # Support SOURCE_DATE_EPOCH environment variable for \"reproducible\" builds.\n        # See https://reproducible-builds.org/specs/source-date-epoch/\n        if 'SOURCE_DATE_EPOCH' in os.environ:\n            self.update_date = datetime.datetime.utcfromtimestamp(\n                int(os.environ['SOURCE_DATE_EPOCH'])\n            ).strftime(\"%Y-%m-%d\")\n        else:\n            self.update_date = datetime.datetime.now().strftime(\"%Y-%m-%d\")\n\n        self._set_canonical_url(config.get('site_url', None))\n        self._set_edit_url(config.get('repo_url', None), config.get('edit_uri', None))\n\n        # Placeholders to be filled in later in the build process.\n        self.markdown = None\n        self.content = None\n        self.toc = []\n        self.meta = {}\n\n    def __eq__(self, other):\n\n        def sub_dict(d):\n            return dict((key, value) for key, value in d.items() if key in ['title', 'file'])\n\n        return (isinstance(other, self.__class__) and sub_dict(self.__dict__) == sub_dict(other.__dict__))\n\n    def __ne__(self, other):\n        return not self.__eq__(other)\n\n    def __repr__(self):\n        title = \"'{}'\".format(self.title) if (self.title is not None) else '[blank]'\n        return \"Page(title={}, url='{}')\".format(title, self.abs_url or self.file.url)\n\n    def _indent_print(self, depth=0):\n        return '{}{}'.format('    ' * depth, repr(self))\n\n    def _get_active(self):\n        \"\"\" Return active status of page. \"\"\"\n        return self.__active\n\n    def _set_active(self, value):\n        \"\"\" Set active status of page and ancestors. \"\"\"\n        self.__active = bool(value)\n        if self.parent is not None:\n            self.parent.active = bool(value)\n\n    active = property(_get_active, _set_active)\n\n    @property\n    def is_index(self):\n        return self.file.name == 'index'\n\n    @property\n    def is_top_level(self):\n        return self.parent is None\n\n    @property\n    def is_homepage(self):\n        return self.is_top_level and self.is_index\n\n    @property\n    def url(self):\n        return '' if self.file.url == '.' else self.file.url\n\n    @property\n    def ancestors(self):\n        if self.parent is None:\n            return []\n        return [self.parent] + self.parent.ancestors\n\n    def _set_canonical_url(self, base):\n        if base:\n            if not base.endswith('/'):\n                base += '/'\n            self.canonical_url = urljoin(base, self.url)\n            self.abs_url = urlparse(self.canonical_url).path\n        else:\n            self.canonical_url = None\n            self.abs_url = None\n\n    def _set_edit_url(self, repo_url, edit_uri):\n        if repo_url and edit_uri:\n            src_path = self.file.src_path.replace('\\\\', '/')\n            self.edit_url = urljoin(repo_url, edit_uri + src_path)\n        else:\n            self.edit_url = None\n\n    def read_source(self, config):\n        source = config['plugins'].run_event(\n            'page_read_source', page=self, config=config\n        )\n        if source is None:\n            try:\n                with io.open(self.file.abs_src_path, 'r', encoding='utf-8-sig', errors='strict') as f:\n                    source = f.read()\n            except IOError:\n                log.error('File not found: {}'.format(self.file.src_path))\n                raise\n            except ValueError:\n                log.error('Encoding error reading file: {}'.format(self.file.src_path))\n                raise\n\n        self.markdown, self.meta = meta.get_data(source)\n        self._set_title()\n\n    def _set_title(self):\n        \"\"\"\n        Set the title for a Markdown document.\n\n        Check these in order and use the first that returns a valid title:\n        - value provided on init (passed in from config)\n        - value of metadata 'title'\n        - content of the first H1 in Markdown content\n        - convert filename to title\n        \"\"\"\n        if self.title is not None:\n            return\n\n        if 'title' in self.meta:\n            self.title = self.meta['title']\n            return\n\n        title = get_markdown_title(self.markdown)\n\n        if title is None:\n            if self.is_homepage:\n                title = 'Home'\n            else:\n                title = self.file.name.replace('-', ' ').replace('_', ' ')\n                # Capitalize if the filename was all lowercase, otherwise leave it as-is.\n                if title.lower() == title:\n                    title = title.capitalize()\n\n        self.title = title\n\n    def render(self, config, files):\n        \"\"\"\n        Convert the Markdown source file to HTML as per the config.\n        \"\"\"\n\n        extensions = [\n            _RelativePathExtension(self.file, files)\n        ] + config['markdown_extensions']\n\n        md = markdown.Markdown(\n            extensions=extensions,\n            extension_configs=config['mdx_configs'] or {}\n        )\n        self.content = md.convert(self.markdown)\n        self.toc = get_toc(getattr(md, 'toc', ''))\n\n\nclass _RelativePathTreeprocessor(Treeprocessor):\n    def __init__(self, file, files):\n        self.file = file\n        self.files = files\n\n    def run(self, root):\n        \"\"\"\n        Update urls on anchors and images to make them relative\n\n        Iterates through the full document tree looking for specific\n        tags and then makes them relative based on the site navigation\n        \"\"\"\n        for element in root.iter():\n            if element.tag == 'a':\n                key = 'href'\n            elif element.tag == 'img':\n                key = 'src'\n            else:\n                continue\n\n            url = element.get(key)\n            new_url = self.path_to_url(url)\n            element.set(key, new_url)\n\n        return root\n\n    def path_to_url(self, url):\n        scheme, netloc, path, params, query, fragment = urlparse(url)\n\n        if (scheme or netloc or not path or url.startswith('/')\n                or AMP_SUBSTITUTE in url or '.' not in os.path.split(path)[-1]):\n            # Ignore URLs unless they are a relative link to a source file.\n            # AMP_SUBSTITUTE is used internally by Markdown only for email.\n            # No '.' in the last part of a path indicates path does not point to a file.\n            return url\n\n        # Determine the filepath of the target.\n        target_path = os.path.join(os.path.dirname(self.file.src_path), urlunquote(path))\n        target_path = os.path.normpath(target_path).lstrip(os.sep)\n\n        # Validate that the target exists in files collection.\n        if target_path not in self.files:\n            log.warning(\n                \"Documentation file '{}' contains a link to '{}' which is not found \"\n                \"in the documentation files.\".format(self.file.src_path, target_path)\n            )\n            return url\n        target_file = self.files.get_file_from_path(target_path)\n        path = target_file.url_relative_to(self.file)\n        components = (scheme, netloc, path, params, query, fragment)\n        return urlunparse(components)\n\n\nclass _RelativePathExtension(Extension):\n    \"\"\"\n    The Extension class is what we pass to markdown, it then\n    registers the Treeprocessor.\n    \"\"\"\n\n    def __init__(self, file, files):\n        self.file = file\n        self.files = files\n\n    def extendMarkdown(self, md, md_globals):\n        relpath = _RelativePathTreeprocessor(self.file, self.files)\n        md.treeprocessors.add(\"relpath\", relpath, \"_end\")\n", "path": "mkdocs/structure/pages.py"}], "after_files": [{"content": "# coding: utf-8\n\nfrom __future__ import unicode_literals\n\nimport os\nimport io\nimport datetime\nimport logging\n\nimport markdown\nfrom markdown.extensions import Extension\nfrom markdown.treeprocessors import Treeprocessor\nfrom markdown.util import AMP_SUBSTITUTE\n\nfrom mkdocs.structure.toc import get_toc\nfrom mkdocs.utils import meta, urlparse, urlunparse, urljoin, urlunquote, get_markdown_title, warning_filter\n\nlog = logging.getLogger(__name__)\nlog.addFilter(warning_filter)\n\n\nclass Page(object):\n    def __init__(self, title, file, config):\n        file.page = self\n        self.file = file\n        self.title = title\n\n        # Navigation attributes\n        self.parent = None\n        self.children = None\n        self.previous_page = None\n        self.next_page = None\n        self.active = False\n\n        self.is_section = False\n        self.is_page = True\n        self.is_link = False\n\n        # Support SOURCE_DATE_EPOCH environment variable for \"reproducible\" builds.\n        # See https://reproducible-builds.org/specs/source-date-epoch/\n        if 'SOURCE_DATE_EPOCH' in os.environ:\n            self.update_date = datetime.datetime.utcfromtimestamp(\n                int(os.environ['SOURCE_DATE_EPOCH'])\n            ).strftime(\"%Y-%m-%d\")\n        else:\n            self.update_date = datetime.datetime.now().strftime(\"%Y-%m-%d\")\n\n        self._set_canonical_url(config.get('site_url', None))\n        self._set_edit_url(config.get('repo_url', None), config.get('edit_uri', None))\n\n        # Placeholders to be filled in later in the build process.\n        self.markdown = None\n        self.content = None\n        self.toc = []\n        self.meta = {}\n\n    def __eq__(self, other):\n\n        def sub_dict(d):\n            return dict((key, value) for key, value in d.items() if key in ['title', 'file'])\n\n        return (isinstance(other, self.__class__) and sub_dict(self.__dict__) == sub_dict(other.__dict__))\n\n    def __ne__(self, other):\n        return not self.__eq__(other)\n\n    def __repr__(self):\n        title = \"'{}'\".format(self.title) if (self.title is not None) else '[blank]'\n        return \"Page(title={}, url='{}')\".format(title, self.abs_url or self.file.url)\n\n    def _indent_print(self, depth=0):\n        return '{}{}'.format('    ' * depth, repr(self))\n\n    def _get_active(self):\n        \"\"\" Return active status of page. \"\"\"\n        return self.__active\n\n    def _set_active(self, value):\n        \"\"\" Set active status of page and ancestors. \"\"\"\n        self.__active = bool(value)\n        if self.parent is not None:\n            self.parent.active = bool(value)\n\n    active = property(_get_active, _set_active)\n\n    @property\n    def is_index(self):\n        return self.file.name == 'index'\n\n    @property\n    def is_top_level(self):\n        return self.parent is None\n\n    @property\n    def is_homepage(self):\n        return self.is_top_level and self.is_index and self.file.url == '.'\n\n    @property\n    def url(self):\n        return '' if self.file.url == '.' else self.file.url\n\n    @property\n    def ancestors(self):\n        if self.parent is None:\n            return []\n        return [self.parent] + self.parent.ancestors\n\n    def _set_canonical_url(self, base):\n        if base:\n            if not base.endswith('/'):\n                base += '/'\n            self.canonical_url = urljoin(base, self.url)\n            self.abs_url = urlparse(self.canonical_url).path\n        else:\n            self.canonical_url = None\n            self.abs_url = None\n\n    def _set_edit_url(self, repo_url, edit_uri):\n        if repo_url and edit_uri:\n            src_path = self.file.src_path.replace('\\\\', '/')\n            self.edit_url = urljoin(repo_url, edit_uri + src_path)\n        else:\n            self.edit_url = None\n\n    def read_source(self, config):\n        source = config['plugins'].run_event(\n            'page_read_source', page=self, config=config\n        )\n        if source is None:\n            try:\n                with io.open(self.file.abs_src_path, 'r', encoding='utf-8-sig', errors='strict') as f:\n                    source = f.read()\n            except IOError:\n                log.error('File not found: {}'.format(self.file.src_path))\n                raise\n            except ValueError:\n                log.error('Encoding error reading file: {}'.format(self.file.src_path))\n                raise\n\n        self.markdown, self.meta = meta.get_data(source)\n        self._set_title()\n\n    def _set_title(self):\n        \"\"\"\n        Set the title for a Markdown document.\n\n        Check these in order and use the first that returns a valid title:\n        - value provided on init (passed in from config)\n        - value of metadata 'title'\n        - content of the first H1 in Markdown content\n        - convert filename to title\n        \"\"\"\n        if self.title is not None:\n            return\n\n        if 'title' in self.meta:\n            self.title = self.meta['title']\n            return\n\n        title = get_markdown_title(self.markdown)\n\n        if title is None:\n            if self.is_homepage:\n                title = 'Home'\n            else:\n                title = self.file.name.replace('-', ' ').replace('_', ' ')\n                # Capitalize if the filename was all lowercase, otherwise leave it as-is.\n                if title.lower() == title:\n                    title = title.capitalize()\n\n        self.title = title\n\n    def render(self, config, files):\n        \"\"\"\n        Convert the Markdown source file to HTML as per the config.\n        \"\"\"\n\n        extensions = [\n            _RelativePathExtension(self.file, files)\n        ] + config['markdown_extensions']\n\n        md = markdown.Markdown(\n            extensions=extensions,\n            extension_configs=config['mdx_configs'] or {}\n        )\n        self.content = md.convert(self.markdown)\n        self.toc = get_toc(getattr(md, 'toc', ''))\n\n\nclass _RelativePathTreeprocessor(Treeprocessor):\n    def __init__(self, file, files):\n        self.file = file\n        self.files = files\n\n    def run(self, root):\n        \"\"\"\n        Update urls on anchors and images to make them relative\n\n        Iterates through the full document tree looking for specific\n        tags and then makes them relative based on the site navigation\n        \"\"\"\n        for element in root.iter():\n            if element.tag == 'a':\n                key = 'href'\n            elif element.tag == 'img':\n                key = 'src'\n            else:\n                continue\n\n            url = element.get(key)\n            new_url = self.path_to_url(url)\n            element.set(key, new_url)\n\n        return root\n\n    def path_to_url(self, url):\n        scheme, netloc, path, params, query, fragment = urlparse(url)\n\n        if (scheme or netloc or not path or url.startswith('/')\n                or AMP_SUBSTITUTE in url or '.' not in os.path.split(path)[-1]):\n            # Ignore URLs unless they are a relative link to a source file.\n            # AMP_SUBSTITUTE is used internally by Markdown only for email.\n            # No '.' in the last part of a path indicates path does not point to a file.\n            return url\n\n        # Determine the filepath of the target.\n        target_path = os.path.join(os.path.dirname(self.file.src_path), urlunquote(path))\n        target_path = os.path.normpath(target_path).lstrip(os.sep)\n\n        # Validate that the target exists in files collection.\n        if target_path not in self.files:\n            log.warning(\n                \"Documentation file '{}' contains a link to '{}' which is not found \"\n                \"in the documentation files.\".format(self.file.src_path, target_path)\n            )\n            return url\n        target_file = self.files.get_file_from_path(target_path)\n        path = target_file.url_relative_to(self.file)\n        components = (scheme, netloc, path, params, query, fragment)\n        return urlunparse(components)\n\n\nclass _RelativePathExtension(Extension):\n    \"\"\"\n    The Extension class is what we pass to markdown, it then\n    registers the Treeprocessor.\n    \"\"\"\n\n    def __init__(self, file, files):\n        self.file = file\n        self.files = files\n\n    def extendMarkdown(self, md, md_globals):\n        relpath = _RelativePathTreeprocessor(self.file, self.files)\n        md.treeprocessors.add(\"relpath\", relpath, \"_end\")\n", "path": "mkdocs/structure/pages.py"}]}