fix: relax search validation (#926)

Signed-off-by: Timothée Mazzucotelli <dev@pawamoy.fr>
This commit is contained in:
Timothée Mazzucotelli
2026-09-09 18:20:20 +02:00
committed by GitHub
parent 6f87afcc2d
commit 304e28054a
3 changed files with 68 additions and 2 deletions
+23
View File
@@ -33,6 +33,8 @@ import zensical
if TYPE_CHECKING:
from pathlib import Path
import pytest
_BUILD_OPTIONS: dict[str, Any] = {"clean": False, "strict": False}
@@ -149,6 +151,27 @@ def test_search_artifacts_match_mkdocs_contract(tmp_path: Path) -> None:
)
def test_unsupported_material_options_are_silently_ignored(
tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
"""Known Material options are ignored to keep migration frictionless."""
config = _write_project(
tmp_path,
plugins=(
" - material/search:\n"
" lang:\n"
" - de\n"
" pipeline:\n"
" - stemmer"
),
)
zensical.build(str(config), _BUILD_OPTIONS)
assert _read_index(tmp_path)["config"]["lang"] == ["en"]
assert capsys.readouterr().err == ""
def test_search_exclusion_and_disabled_output(tmp_path: Path) -> None:
"""Excluded pages contribute no items and disabled search stays valid."""
config = _write_project(tmp_path, plugins=" search:\n enabled: true")
+29
View File
@@ -146,6 +146,35 @@ def test_rejects_unknown_python_plugin_options(name: str) -> None:
_convert_plugins({name: {"unknown": True}})
@pytest.mark.parametrize("plugin", ["search", "material/search"])
def test_silently_discards_unsupported_search_options(
plugin: str, capsys: pytest.CaptureFixture[str]
) -> None:
unsupported = {
"fields": {"title": {"boost": 2}},
"indexing": "titles",
"jieba_dict": "dict.txt",
"jieba_dict_user": "user-dict.txt",
"lang": ["en", "de"],
"min_search_length": 2,
"pipeline": ["stemmer"],
"prebuild_index": True,
}
configured = {
"enabled": False,
"separator": "[\\s-]+",
**unsupported,
}
plugins = _convert_plugins({plugin: configured})
assert plugins["search"]["config"] == {
"enabled": False,
"separator": "[\\s-]+",
}
assert capsys.readouterr().err == ""
@pytest.mark.parametrize("name", SHIM_PLUGINS)
def test_normalizes_null_shim_configuration(name: str) -> None:
plugins = _convert_plugins({name: None})
+16 -2
View File
@@ -67,7 +67,6 @@ representation in Rust. Thus, we just keep the configuration on the Python
side, and use it directly when needed. It's a hack but will do for now.
"""
# ----------------------------------------------------------------------------
# Constants
# ----------------------------------------------------------------------------
@@ -1448,7 +1447,22 @@ def _convert_plugins(value: Any, config: dict) -> dict:
# Search is enabled by default, even when it isn't explicitly configured.
search = plugins.pop("search", {})
_reject_unknown_options("search", search, {"enabled", "separator"})
supported = {"enabled", "separator"}
# Keep recognized upstream options non-fatal during migration, but discard
# them before extracting the typed native search configuration in Rust.
unsupported = {
"fields",
"indexing",
"jieba_dict",
"jieba_dict_user",
"lang",
"min_search_length",
"pipeline",
"prebuild_index",
}
_reject_unknown_options("search", search, supported | unsupported)
for name in sorted(unsupported & search.keys()):
search.pop(name)
set_default(search, "enabled", True)
set_default(search, "separator", '[\\s\\-_,:!=\\[\\]()\\\\"`/]+|\\.(?!\\d)')
_validate_boolean_options("search", search, ("enabled",))