Skip to content

Commit 17f0014

Browse files
committed
Added prefix input and tests
1 parent 4caef2b commit 17f0014

File tree

3 files changed

+179
-23
lines changed

3 files changed

+179
-23
lines changed

mkdocs_site_urls/__init__.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,40 @@
88
logger = mkdocs.plugins.get_plugin_logger(__name__)
99

1010

11-
class SiteUrlsConfig(mkdocs.config.base.Config):
11+
class Config(mkdocs.config.base.Config):
1212
attributes = c.Type(list, default=["href", "src", "data"])
13-
14-
15-
class SiteUrlsPlugin(mkdocs.plugins.BasePlugin[SiteUrlsConfig]):
16-
def on_pre_build(self, *, config: MkDocsConfig) -> None:
17-
self._regex = re.compile(
18-
r"(" + "|".join(self.config["attributes"]) + r')="site:([^"]+)"',
19-
re.IGNORECASE,
20-
)
13+
prefix = c.Type(str, default="site:")
14+
15+
16+
class SiteUrlsPlugin(mkdocs.plugins.BasePlugin[Config]):
17+
def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
18+
attributes = (re.escape(attr) for attr in self.config["attributes"])
19+
self.prefix = re.escape(self.config["prefix"])
20+
regex_parts = [
21+
r"(", # capturing group 1
22+
"|".join(attributes), # attributes
23+
r")", # end of capturing group 1
24+
r"\s*=\s*", # equals sign with optional whitespace
25+
r"([\"'])", # quote with capturing group 2
26+
self.prefix, # url prefix
27+
r"([^\"']*)", # remainder of the url with capturing group 3
28+
r"\2", # matching quote
29+
]
30+
regex = "".join(regex_parts)
31+
self._regex = re.compile(regex, re.IGNORECASE)
32+
return config
2133

2234
@mkdocs.plugins.event_priority(50)
2335
def on_page_content(self, html, page, config, files):
2436
site_url = config["site_url"]
37+
if not site_url.endswith("/"):
38+
site_url += "/"
2539
path = urllib.parse.urlparse(site_url).path
40+
def _replacer(match):
41+
attribute = match.group(1)
42+
url = match.group(3)
2643

27-
if not path:
28-
path = "/"
29-
if not path.endswith("/"):
30-
path += "/"
31-
32-
def _replace(match):
33-
param = match.group(1)
34-
url = match.group(2)
35-
if url.startswith("/"):
36-
url = url[1:]
37-
38-
logger.info(f"Replacing site:{match.group(2)} with {path}{url}")
39-
return f'{param}="{path}{url}"'
44+
logger.info(f"Replacing absolute url '{self.prefix}{url}' with '{path}{url}'")
45+
return f'{attribute}="{path}{url}"'
4046

41-
return self._regex.sub(_replace, html)
47+
return self._regex.sub(_replacer, html)

tests/__init__.py

Whitespace-only changes.

tests/test_mkdocs_site_urls.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import re
2+
3+
import pytest
4+
5+
from unittest.mock import MagicMock
6+
from resolve_absolute_urls.plugin import ResolveAbsoluteUrlsPlugin
7+
8+
@pytest.fixture
9+
def mock_plugin_config():
10+
return {"attributes": ["src", "href"], "prefix": "site:"}
11+
12+
13+
@pytest.fixture
14+
def create_plugin(mock_plugin_config):
15+
"""Factory function to create the plugin with the prescribed configuration options."""
16+
17+
def _plugin(config=mock_plugin_config, **kwargs):
18+
plugin = ResolveAbsoluteUrlsPlugin()
19+
plugin.load_config(config)
20+
for key, value in kwargs.items():
21+
setattr(plugin, key, value)
22+
return plugin
23+
24+
return _plugin
25+
26+
27+
@pytest.mark.parametrize(
28+
"attributes, prefix, string_to_match, match_group1, match_group3, should_match",
29+
[
30+
(
31+
["href", "src"],
32+
"/docs/",
33+
'src = "/docs/image.png"',
34+
"src",
35+
"image.png",
36+
True,
37+
), # valid1
38+
(
39+
["href", "src"],
40+
"/",
41+
"href ='/docs/image.png'",
42+
"href",
43+
"docs/image.png",
44+
True,
45+
), # valid2
46+
(
47+
["data"],
48+
"site:",
49+
"data= 'site:image.png'",
50+
"data",
51+
"image.png",
52+
True,
53+
), # valid3
54+
(
55+
["href", "src"],
56+
"/docs/",
57+
'src = "/image.png"',
58+
None,
59+
None,
60+
False,
61+
), # invalid_different_prefix
62+
(
63+
["href", "src"],
64+
"/",
65+
"href ='site:docs/image.png'",
66+
None,
67+
None,
68+
False,
69+
), # invalid_different_prefix2
70+
(
71+
["data"],
72+
"/",
73+
"href='/image.png'",
74+
None,
75+
None,
76+
False,
77+
), # invalid_different_attribute
78+
],
79+
ids=[
80+
"valid1",
81+
"valid2",
82+
"valid3",
83+
"invalid_different_prefix",
84+
"invalid_different_prefix2",
85+
"invalid_different_attribute",
86+
],
87+
)
88+
def test_on_config_sets_regex(
89+
create_plugin,
90+
attributes,
91+
prefix,
92+
string_to_match,
93+
match_group1,
94+
match_group3,
95+
should_match,
96+
):
97+
"""Test the on_config method of the ResolveAbsoluteUrlsPlugin."""
98+
plugin_config = {
99+
"attributes": attributes,
100+
"prefix": prefix,
101+
}
102+
plugin = create_plugin(plugin_config)
103+
plugin.on_config(MagicMock())
104+
105+
# Check that the regex is compiled
106+
assert isinstance(plugin._regex, re.Pattern)
107+
match = plugin._regex.search(string_to_match)
108+
109+
# Check regex is correct
110+
if should_match:
111+
assert match is not None
112+
assert match.group(1) == match_group1
113+
assert match.group(3) == match_group3
114+
else:
115+
assert match is None
116+
117+
@pytest.mark.parametrize(
118+
"site_url",
119+
[
120+
"https://example.com/docs/subpage/",
121+
"https://example.com/docs/subpage",
122+
],
123+
ids=["trailing_slash", "no_trailing_slash"],
124+
)
125+
def test_on_page_content(create_plugin, site_url):
126+
"""Test the on_page_content method of the ResolveAbsoluteUrlsPlugin."""
127+
plugin = create_plugin({
128+
"attributes": ["src", "data"],
129+
"prefix": "prefix",
130+
})
131+
page = MagicMock()
132+
config = MagicMock()
133+
config.__getitem__.side_effect = lambda key: site_url if key == "site_url" else None
134+
files = MagicMock()
135+
html = '''
136+
<img src ="prefixexample.png" alt="Image">
137+
<img data = \'prefix/image.png\'>
138+
<img data="site:docs/image.svg" class="example">
139+
<img attr ="prefix/docs/image.png" >
140+
'''
141+
142+
plugin.on_config(config)
143+
result = plugin.on_page_content(html, page, config, files)
144+
expected_result = '''
145+
<img src="/docs/subpage/example.png" alt="Image">
146+
<img data="/docs/subpage//image.png">
147+
<img data="site:docs/image.svg" class="example">
148+
<img attr ="prefix/docs/image.png" >
149+
'''
150+
assert result == expected_result

0 commit comments

Comments
 (0)