diff --git a/scripts/snippets/model.py b/scripts/snippets/model.py
index c09ffefef..7ab2b3608 100644
--- a/scripts/snippets/model.py
+++ b/scripts/snippets/model.py
@@ -220,3 +220,10 @@ class DirectiveSyntaxRule(str, Enum):
ELSE_SELF_CLOSING = "else_self_closing"
CLOSING_ATTRIBUTES = "closing_attributes"
ELSE_ATTRIBUTES = "else_attributes"
+
+
+@dataclass(frozen=True)
+class ConditionPageValidation:
+ tags: tuple[IfVersionTag | ElseTag, ...]
+ conditions: tuple[IfVersionCondition, ...]
+ diagnostics: tuple[Diagnostic, ...]
diff --git a/scripts/snippets/page_validation.py b/scripts/snippets/page_validation.py
new file mode 100644
index 000000000..10afe3aec
--- /dev/null
+++ b/scripts/snippets/page_validation.py
@@ -0,0 +1,50 @@
+from __future__ import annotations
+
+from pathlib import Path
+
+from .diagnostics import (
+ directive_syntax_diagnostic,
+ if_version_attribute_diagnostics,
+ if_version_structure_diagnostics,
+)
+from .model import ConditionPageValidation, IfVersionTag
+from .registry import RepositoryRegistry
+from .syntax import DirectiveSyntaxError, parse_if_version_tags
+from .validation import (
+ validate_if_version_attributes,
+ validate_if_version_structure,
+)
+
+
+def validate_condition_page(
+ text: str, *, path: Path, registry: RepositoryRegistry
+) -> ConditionPageValidation:
+ """Parse and validate conditional declarations without inspecting snippets."""
+
+ try:
+ tags = parse_if_version_tags(text)
+ except DirectiveSyntaxError as error:
+ return ConditionPageValidation(
+ tags=(),
+ conditions=(),
+ diagnostics=(directive_syntax_diagnostic(path, error),),
+ )
+
+ diagnostics = list(
+ if_version_structure_diagnostics(
+ path, validate_if_version_structure(text, tags)
+ )
+ )
+ conditions = []
+ for tag in tags:
+ if not isinstance(tag, IfVersionTag) or tag.closing:
+ continue
+ result = validate_if_version_attributes(tag, registry)
+ diagnostics.extend(if_version_attribute_diagnostics(path, result.issues))
+ if result.condition is not None:
+ conditions.append(result.condition)
+ return ConditionPageValidation(
+ tags=tags,
+ conditions=tuple(conditions),
+ diagnostics=tuple(diagnostics),
+ )
diff --git a/tests/test_condition_page_validation.py b/tests/test_condition_page_validation.py
new file mode 100644
index 000000000..e60cae31e
--- /dev/null
+++ b/tests/test_condition_page_validation.py
@@ -0,0 +1,68 @@
+from __future__ import annotations
+
+from pathlib import Path
+
+from scripts.snippets.model import ConditionPageValidation
+from scripts.snippets.page_validation import validate_condition_page
+from scripts.snippets.registry import (
+ RepositoryConfig,
+ RepositoryRegistry,
+ RepositoryVisibility,
+)
+
+PATH = Path("docs-main/validator.source.mdx")
+REGISTRY = RepositoryRegistry(
+ (
+ RepositoryConfig(
+ name="canton-network/splice",
+ url="https://github.com/canton-network/splice",
+ default_branch="main",
+ visibility=RepositoryVisibility.PUBLIC,
+ ),
+ )
+)
+
+
+def validate(text: str) -> ConditionPageValidation:
+ return validate_condition_page(text, path=PATH, registry=REGISTRY)
+
+
+def test_returns_validated_condition() -> None:
+ result = validate(
+ """
+new
+"""
+ )
+
+ assert result.diagnostics == ()
+ assert len(result.conditions) == 1
+ assert result.conditions[0].repository == "canton-network/splice"
+
+
+def test_reports_conditional_syntax_error() -> None:
+ result = validate(
+ ''
+ )
+
+ assert [diagnostic.code for diagnostic in result.diagnostics] == [
+ "SNIP019"
+ ]
+
+
+def test_reports_conditional_structure_error() -> None:
+ result = validate("orphan")
+
+ assert "SNIP025" in {
+ diagnostic.code for diagnostic in result.diagnostics
+ }
+
+
+def test_reports_condition_attribute_error() -> None:
+ result = validate(
+ ''
+ "new"
+ )
+
+ assert "SNIP021" in {
+ diagnostic.code for diagnostic in result.diagnostics
+ }