Also make 'relative_to_docs' work for nav validation

This commit is contained in:
Oleh Prypin
2023-12-09 18:06:22 +01:00
parent a42ab62311
commit 7245a636cc
4 changed files with 57 additions and 9 deletions

View File

@@ -417,7 +417,7 @@ The defaults of some of the behaviors already differ from MkDocs 1.4 and below -
> ```yaml
> validation:
> omitted_files: warn
> absolute_links: warn
> absolute_links: warn # Or 'relative_to_docs' - new in MkDocs 1.6
> unrecognized_links: warn
> anchors: warn # New in MkDocs 1.6
> ```
@@ -429,7 +429,7 @@ Full list of values and examples of log messages that they can hide or make more
* `validation.nav.omitted_files`
* > The following pages exist in the docs directory, but are not included in the "nav" configuration: ...
* `validation.nav.not_found`
* > A relative path to 'foo/bar.md' is included in the 'nav' configuration, which is not found in the documentation files.
* > A reference to 'foo/bar.md' is included in the 'nav' configuration, which is not found in the documentation files.
* > A reference to 'foo/bar.md' is included in the 'nav' configuration, but this file is excluded from the built site.
* `validation.nav.absolute_links`
* > An absolute path to '/foo/bar.html' is included in the 'nav' configuration, which presumably points to an external resource.

View File

@@ -175,7 +175,7 @@ class MkDocsConfig(base.Config):
not_found = _LogLevel(default='warn')
"""Warning level for when the navigation links to a relative path that isn't an existing page on the site."""
absolute_links = _LogLevel(default='info')
absolute_links = _AbsoluteLinksValidation(default='info')
"""Warning level for when the navigation links to an absolute path (starting with `/`)."""
nav = c.SubConfig(NavValidation)

View File

@@ -6,7 +6,7 @@ from urllib.parse import urlsplit
from mkdocs.exceptions import BuildError
from mkdocs.structure import StructureItem
from mkdocs.structure.pages import Page
from mkdocs.structure.pages import Page, _AbsoluteLinksValidationValue
from mkdocs.utils import nest_paths
if TYPE_CHECKING:
@@ -164,7 +164,11 @@ def get_navigation(files: Files, config: MkDocsConfig) -> Navigation:
scheme, netloc, path, query, fragment = urlsplit(link.url)
if scheme or netloc:
log.debug(f"An external link to '{link.url}' is included in the 'nav' configuration.")
elif link.url.startswith('/'):
elif (
link.url.startswith('/')
and config.validation.nav.absolute_links
is not _AbsoluteLinksValidationValue.RELATIVE_TO_DOCS
):
log.log(
config.validation.nav.absolute_links,
f"An absolute path to '{link.url}' is included in the 'nav' "
@@ -173,7 +177,7 @@ def get_navigation(files: Files, config: MkDocsConfig) -> Navigation:
else:
log.log(
config.validation.nav.not_found,
f"A relative path to '{link.url}' is included in the 'nav' "
f"A reference to '{link.url}' is included in the 'nav' "
"configuration, which is not found in the documentation files.",
)
return Navigation(items, pages)
@@ -195,7 +199,13 @@ def _data_to_navigation(data, files: Files, config: MkDocsConfig):
for item in data
]
title, path = data if isinstance(data, tuple) else (None, data)
if file := files.get_file_from_path(path):
lookup_path = path
if (
lookup_path.startswith('/')
and config.validation.nav.absolute_links is _AbsoluteLinksValidationValue.RELATIVE_TO_DOCS
):
lookup_path = lookup_path.lstrip('/')
if file := files.get_file_from_path(lookup_path):
if file.inclusion.is_excluded():
log.log(
min(logging.INFO, config.validation.nav.not_found),

View File

@@ -131,6 +131,44 @@ class SiteNavigationTests(unittest.TestCase):
self.assertEqual(len(site_navigation.items), 3)
self.assertEqual(len(site_navigation.pages), 1)
def test_nav_absolute_links_with_validation(self):
nav_cfg = [
{'Home': 'index.md'},
{'Local page': '/foo/bar.md'},
{'Local link': '/local.md'},
{'External': 'http://example.com/external.html'},
]
expected = dedent(
"""
Page(title='Home', url='/')
Page(title='Local page', url='/foo/bar/')
Link(title='Local link', url='/local.md')
Link(title='External', url='http://example.com/external.html')
"""
)
cfg = load_config(
nav=nav_cfg,
site_url='http://example.com/',
validation=dict(nav=dict(absolute_links='relative_to_docs')),
)
fs = [
File('index.md', cfg.docs_dir, cfg.site_dir, cfg.use_directory_urls),
File('foo/bar.md', cfg.docs_dir, cfg.site_dir, cfg.use_directory_urls),
]
files = Files(fs)
with self.assertLogs('mkdocs', level='DEBUG') as cm:
site_navigation = get_navigation(files, cfg)
self.assertEqual(
cm.output,
[
"WARNING:mkdocs.structure.nav:A reference to '/local.md' is included in the 'nav' configuration, which is not found in the documentation files.",
"DEBUG:mkdocs.structure.nav:An external link to 'http://example.com/external.html' is included in the 'nav' configuration.",
],
)
self.assertEqual(str(site_navigation).strip(), expected)
self.assertEqual(len(site_navigation.items), 4)
self.assertEqual(len(site_navigation.pages), 2)
def test_nav_bad_links(self):
nav_cfg = [
{'Home': 'index.md'},
@@ -152,8 +190,8 @@ class SiteNavigationTests(unittest.TestCase):
self.assertEqual(
cm.output,
[
"WARNING:mkdocs.structure.nav:A relative path to 'missing.html' is included in the 'nav' configuration, which is not found in the documentation files.",
"WARNING:mkdocs.structure.nav:A relative path to 'example.com' is included in the 'nav' configuration, which is not found in the documentation files.",
"WARNING:mkdocs.structure.nav:A reference to 'missing.html' is included in the 'nav' configuration, which is not found in the documentation files.",
"WARNING:mkdocs.structure.nav:A reference to 'example.com' is included in the 'nav' configuration, which is not found in the documentation files.",
],
)
self.assertEqual(str(site_navigation).strip(), expected)