From 6e67083aad1ce97fedf4bfb9b054569093f11547 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Tue, 28 Apr 2026 03:10:30 +0300 Subject: [PATCH] Expose page.content_title property for plugin authors Add a public content_title property to the Page class that exposes the previously private _title_from_render attribute. This gives plugin authors access to the heading text extracted from the first

tag in the page content, with HTML tags stripped and entities unescaped, without reaching into private API. Fixes #3533 --- mkdocs/structure/pages.py | 13 +++++++++++++ mkdocs/tests/structure/page_tests.py | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/mkdocs/structure/pages.py b/mkdocs/structure/pages.py index 74fe872a..e8eaf61c 100644 --- a/mkdocs/structure/pages.py +++ b/mkdocs/structure/pages.py @@ -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 `

` 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 `

` 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`.""" diff --git a/mkdocs/tests/structure/page_tests.py b/mkdocs/tests/structure/page_tests.py index 53af9c75..29bcf5ee 100644 --- a/mkdocs/tests/structure/page_tests.py +++ b/mkdocs/tests/structure/page_tests.py @@ -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(