Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions mkdocs/structure/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,19 @@ def __repr__(self):
meta: MutableMapping[str, Any]
"""A mapping of the metadata included at the top of the markdown page."""

@property
def content_title(self) -> str | None:
"""
The title of the page extracted from the first `<h1>` heading in the page content.

This is `None` until the page has been rendered. Unlike `title`,
this does not fall back to any other source — it reflects exactly
the `<h1>` text from the rendered Markdown, with HTML tags stripped
and entities unescaped. It is useful for plugins that need the raw
heading text as it appears in the page body.
"""
return self._title_from_render

@property
def url(self) -> str:
"""The URL of the page relative to the MkDocs `site_dir`."""
Expand Down
11 changes: 11 additions & 0 deletions mkdocs/tests/structure/page_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,17 @@ def test_page_title_from_markdown(self):
self.assertEqual(pg.title, "Welcome to MkDocs")
pg.render(cfg, Files([fl]))
self.assertEqual(pg.title, "Welcome to MkDocs")
self.assertEqual(pg.content_title, "Welcome to MkDocs")

def test_content_title_property(self):
"""content_title is None before rendering, set after."""
cfg = load_config()
fl = File("testing.md", cfg.docs_dir, cfg.site_dir, cfg.use_directory_urls)
pg = Page(None, fl, cfg)
pg.read_source(cfg)
self.assertIsNone(pg.content_title)
pg.render(cfg, Files([fl]))
self.assertEqual(pg.content_title, "Welcome to MkDocs")

def _test_extract_title(self, content, expected, extensions={}):
md = markdown.Markdown(
Expand Down
Loading