{% extends "public_base.html" %} {% import "marketplace/_macros.html" as mk %} {% block title %}{{ feature.short }}{% endblock %} {% block content %} {#- Every section below reads one part of the sheet (MarketplaceService.sheet) and is left out when the index entry carries nothing for it, so a sheet built from an older index is shorter, never broken. -#} {% set provides = feature.provides %} {% set deps = sheet.dependencies %} {% set known = known_shorts %}
{{ mk.monogram(feature.short, large=true) }}

{{ feature.short }}

{{ feature.org }}/{{ feature.repo }}

{{ mk.version_pill(feature) }} {{ mk.archetype_badge(feature.archetype) }} {% if feature.category %}{{ feature.category }}{% endif %} {% if install_env == "dev" %}{{ _("Development only") }} {% elif install_env == "prod" %}{{ _("Production only") }}{% endif %} {% if sheet.refinement %}{{ _("Refines %(feature)s", feature=sheet.refinement.base) }}{% endif %}
{# ── Main column ───────────────────────────────────────────────── #}

{{ mk.icon("info") }}{{ _("About") }}

{{ feature.description or _("No description yet.") }}

{% set rf = sheet.refinement %} {% if rf %}

{{ mk.icon("git-merge") }}{{ _("Refinement") }}

{{ mk.chip_row(_("Refines"), [rf.base], known) }} {% if rf.models %}
{{ _("Extends models") }}
{% for m in rf.models %}{{ m.target }} {{ _("with") }} {{ m.mixin }}{% endfor %}
{% endif %} {% if rf.routes %}
{{ _("Adds routes") }}
{% for r in rf.routes %}{{ r.module }} {{ _("to") }} {{ r.blueprint }}{% endfor %}
{% endif %} {% for kind, label in [("templates", _("Overrides templates")), ("services", _("Overrides services")), ("hooks", _("Overrides hooks"))] %} {% if rf[kind] %}
{{ label }}
{% for o in rf[kind] %}{% if o.replacement %}{{ o.target }} {{ _("with") }} {{ o.replacement }}{% else %}{{ o.target }}{% endif %}{% endfor %}
{% endif %} {% endfor %}

{{ _("It changes %(feature)s in place, without a fork, so the product installs both.", feature=rf.base) }}

{% endif %} {% set has_provides = provides.models or provides.services or provides.routes or provides.hooks or provides.signals or provides.translations %} {% if has_provides or not sheet.commands %}

{{ mk.icon("box") }}{{ _("Provides") }}

{% if has_provides %}
{{ mk.contract_row(_("Models"), provides.models) }} {{ mk.contract_row(_("Services"), provides.services) }} {{ mk.contract_row(_("Routes"), provides.routes) }} {{ mk.contract_row(_("Hooks filled"), provides.hooks) }} {{ mk.contract_row(_("Signals"), provides.signals) }} {{ mk.contract_row(_("Translations"), provides.translations) }}
{% else %}

{{ _("This feature declares no public contract surface.") }}

{% endif %}
{% endif %} {% if sheet.commands %}

{{ mk.icon("terminal") }}{{ _("Commands") }}

    {% for cmd in sheet.commands %}
  • $ {{ mk.command(cmd.invocation) }} {{ mk.copy_button("mk-cmd-" ~ loop.index, _("Copy the %(command)s command", command=cmd.name)) }}
    {% if cmd.help %}

    {{ cmd.help }}

    {% endif %}
  • {% endfor %}

{{ _("Run them in your workspace once the feature is installed in the selected product.") }}

{% endif %} {% set settings = sheet.settings %} {% if settings.settings %}
{% if settings.declared %}

{{ mk.icon("settings") }}{{ _("Configuration") }}

{% for s in settings.settings %} {% endfor %}
{{ _("Setting") }} {{ _("Default") }} {{ _("What it does") }}
{{ s.key }} {% if s.required %}{{ _("Required") }} {% elif s.default %}{{ s.default }} {% else %}{{ _("empty") }}{% endif %} {% if s.help %}{{ s.help }}{% else %}{{ _("No description yet.") }}{% endif %} {% if s.required %}{{ _("Has no default, so the product must set a value.") }}{% endif %}

{{ _("These are the defaults. A product changes them in its own pyproject.toml, under [tool.splent.config], or in .env.deploy in production.") }}{% if settings.per_product %} {{ _("%(name)s stands for the name of the product that takes the feature.", name="") }}{% endif %}

{% else %}

{{ mk.icon("settings") }}{{ _("Settings it reads") }}

{{ mk.contract_row(_("Variables"), settings.settings | map(attribute="key") | list) }}

{{ _("The code reads these variables. This version publishes no defaults or descriptions for them, so check the feature's documentation before relying on one.") }}

{% endif %}
{% endif %} {% set dk = sheet.docker %} {% if dk %}

{{ mk.icon("server") }}{{ _("Services and ports") }} {% if install_env == "dev" %}{{ _("Development only") }} {% elif install_env == "prod" %}{{ _("Production only") }}{% endif %}

{{ mk.contract_row(_("Containers"), dk.services) }} {% if dk.ports %}
{{ _("Ports") }}
{% for port in dk.ports %} {{ port.container }} {% if port.host_var %}{{ _("on the host port set in") }} {{ port.host_var }} {% elif port.host %}{{ _("on host port") }} {{ port.host }}{% endif %} {% endfor %}
{% endif %} {{ mk.contract_row(_("Volumes"), dk.volumes) }}
{{ _("Image") }}
{% if dk.build %}{{ _("Built from the feature's own Dockerfile") }}{% else %}{{ _("A published image, pulled as it is") }}{% endif %}
{{ _("Health check") }}
{% if dk.healthcheck %}{{ mk.icon("check-circle", 14) }} {{ _("Declared") }}{% else %}{{ _("None declared") }}{% endif %}
{{ mk.contract_row(_("Starts after"), dk.depends_on) }} {{ mk.contract_row(_("Compose files"), dk.compose_files) }}
{% if install_env == "dev" %}

{{ _("These containers start with the product in development only. A production build leaves the feature and its containers out.") }}

{% elif install_env == "prod" %}

{{ _("These containers run in production builds only.") }}

{% else %}

{{ _("They start with the product. Host ports come from variables, so two products on one machine never collide.") }}

{% endif %}
{% endif %}

{{ mk.icon("git-branch") }}{{ _("Dependencies") }}

{% if deps.requires or deps.optional or deps.used_by or deps.signals %}
{{ mk.chip_row(_("Requires"), deps.requires, known) }} {{ mk.chip_row(_("Works better with"), deps.optional, known) }} {{ mk.chip_row(_("Used by"), deps.used_by, known) }} {{ mk.contract_row(_("Listens to"), deps.signals) }}
{% else %}

{{ _("No hard dependencies.") }}

{% endif %}
{% if collisions %}

{{ mk.icon("alert-triangle") }}{{ _("Collisions") }}

    {% for c in collisions %}
  • {{ c.item }} ({{ c.kind }}) {{ _("also provided by") }} {% for other in c.features if other != feature.short %}{{ mk.feature_chip(other, external=other not in known) }}{% endfor %}
  • {% endfor %}
{% endif %} {% if sheet.lines %}

{{ mk.icon("layers") }}{{ _("In product lines") }}

    {% for line in sheet.lines %}
  • {{ line.name }} {% if line.role == "mandatory" %}{{ _("In every product") }} {% elif line.role == "optional" %}{{ _("Optional in this line") }} {% else %}{{ _("In a group") }}{% endif %} {% if line.group %} {% if line.role == "alternative" and line.group_required %}{{ _("Exactly one of the %(group)s group", group=line.group) }} {% elif line.role == "alternative" %}{{ _("Exactly one of the %(group)s group, when a product takes that group", group=line.group) }} {% elif line.group_required %}{{ _("One or more of the %(group)s group", group=line.group) }} {% else %}{{ _("One or more of the %(group)s group, when a product takes that group", group=line.group) }}{% endif %} {% endif %} {% if line.needs %} {{ _("Needs") }} {% for other in line.needs %}{{ other }}{% if not loop.last %} {% endif %}{% endfor %} {% endif %}
  • {% endfor %}
{% endif %} {% set ext = sheet.extension %} {% if ext or sheet.refined_by %}

{{ mk.icon("link") }}{{ _("Extension points") }}

{% if ext %} {{ mk.contract_row(_("Hook slots"), ext.hooks) }} {{ mk.contract_row(_("Templates"), ext.templates) }} {{ mk.contract_row(_("Services"), ext.services) }} {{ mk.contract_row(_("Models"), ext.models) }} {% if ext.routes %}
{{ _("Routes") }}
{{ _("A refinement can add routes to its blueprint") }}
{% endif %} {% endif %} {{ mk.chip_row(_("Refined by"), sheet.refined_by, known) }}

{{ _("Other features fill its hook slots. A refinement can override its templates and services or extend its models without forking it.") }}

{% endif %} {% set cp = sheet.compatibility %} {% if cp %}

{{ mk.icon("check-square") }}{{ _("Compatibility") }}

{% if cp.python %}{{ mk.contract_row("Python", [cp.python]) }}{% endif %}
{{ _("SPLENT framework") }}
{% if cp.framework == "*" %}{{ _("Any version") }} {% elif cp.framework %}{{ cp.framework }} {% else %}{{ _("No range declared") }}{% endif %}
{{ mk.contract_row(_("Python packages"), cp.packages | map(attribute="raw") | list) }}
{% endif %}
{# ── Side column: install first, then the facts ────────────────── #}
{% endblock %} {% block scripts %} {% endblock %}