{% extends "base.html" %}
{% block title %}Index — Solidity Flow Navigator{% endblock %}
{% block body_class %}index-page{% endblock %}
{% block content %}
{# v0.15.0 bookmarks (spec §8.3): a ribbon toggle. Each is a real server-side link
to /bookmark// (works with no JavaScript — the fallback reloads and
returns to this row). index.js progressively enhances the click to toggle in
place without a reload, so the auditor stays exactly where they are. ``on``
picks filled (terracotta) vs outline. #}
{% macro bookmark_toggle(kind, ident, on) -%}
{% set anchor = ('e-' if kind == 'entry' else 'c-') ~ (ident | anchor_slug) -%}
{%- endmacro %}
Index
{# v0.10.4: native title tooltips on the stats and per-entry badges —
the d{N} / "N unr" shorthand was unexplained anywhere in the UI. #}
{# v0.11.0: labels pluralize with their counts; the repo-path subtitle
that duplicated the site header's path is gone (spec §8.3). #}
{{ total_contracts }}contract{{ 's' if total_contracts != 1 }}
{{ total_entry_points }}entry point{{ 's' if total_entry_points != 1 }}
{{ total_unresolved }}unresolved
{# v0.16.0 (spec §8.3): filter box. Server-rendered but `hidden` so no-JS users
never see a dead control; index.js reveals it on load and narrows the listing
below as the auditor types. The complete listing is always present server-side,
and the Bookmarked section above stays pinned (unfiltered). #}
Scope·excluded
{% for glob in scope.exclude_paths -%}
{{ glob }}{% if not loop.last %},{% endif %}
{% endfor %}
·stub
{%- if scope.stub_paths %}
{% for glob in scope.stub_paths -%}
{{ glob }}{% if not loop.last %},{% endif %}
{% endfor %}
{%- else %}
none
{%- endif %}
{# v0.12.0 (spec §8.3): chips legend — each key renders through the SAME
classes as the live chips so the legend stays self-verifying. Renders
unconditionally to keep page layout stable across targets. #}
Legend·modifiergate on a mutating entry, none = unguarded·2 unrunresolved call sites·d3max call depth
{# v0.18.0 (spec §8.3, §13.2): Bindings panel. One row per bindable interface;
each row is a real GET form to /bind/ with a "Set" submit, so picking a
concrete contract resolves that interface at every call site across every Flow
— and works with no JavaScript. "Save to solflow.toml" (POST /bindings/save)
persists the current bindings so they survive a restart (the one place solflow
writes to the working directory). index.js collapses a long list behind a
"Show all" toggle and auto-applies on change (hiding the per-row "Set"); with
JS off the full list and all controls render server-side. Renders only when at
least one interface is bindable. #}
{% if bindable %}
Bindings
{% if saved == 'ok' %}
Saved to solflow.toml.
{% elif saved == 'error' %}
Could not write solflow.toml — see the server log.
{% endif %}
Resolve an interface to a concrete contract across all Flows · Save to persist across sessions.
{% endif %}
{# v0.15.0 (spec §8.3): the Bookmarked section renders only when the cookie holds
ids matching this analysis. Contracts link to their block anchor; entries link
to their Flow page. Each carries the same toggle (already "on") to un-bookmark.
A fixed shortcut (.bookmark-jump, below) anchors here from anywhere on the page. #}
{% set bookmark_count = (bookmarked_contracts | length) + (bookmarked_entries | length) %}
{% if bookmark_count %}
{# Persistent shortcut: a fixed anchor, visible at any scroll position, that jumps
to the Bookmarked section. Server-rendered count; plain , no JavaScript. #}
{{ bookmark_count }}
{# v0.11.0 (spec §8.3): no Contract. prefix — the block heading
names the contract; modifier chips render on mutating rows
only (no chips = unprotected mutating entry point). #}
{{ bookmark_toggle('entry', ep.url_id, ('e:' + ep.url_id) in bookmarked_ids) }}
{{ ep.signature_html | safe }}
{%- for m in ep.modifier_names %}
{{ m }}
{%- endfor %}
{%- if ep.unresolved_count > 0 -%}
{{ ep.unresolved_count }} unr·
{%- endif -%}
d{{ ep.max_depth }}
{% endfor %}
{% endif %}
{% if contract.read_only_entry_points %}
Read-only · {{ contract.read_only_count }}
{% for ep in contract.read_only_entry_points %}
{# v0.11.0: read-only rows carry no modifier chips (deliberate
asymmetry, spec §8.3) but share the entry-main wrapper. #}
{{ bookmark_toggle('entry', ep.url_id, ('e:' + ep.url_id) in bookmarked_ids) }}
{{ ep.signature_html | safe }}
{%- if ep.unresolved_count > 0 -%}
{{ ep.unresolved_count }} unr·
{%- endif -%}
d{{ ep.max_depth }}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
All analysis local · code never uploaded · server bound to 127.0.0.1 · source
{% endblock %}
{# v0.15.0: progressive enhancement — bookmark toggles work as plain links above;
this script intercepts them to toggle in place (no reload), so the auditor's
scroll position is preserved (spec §8.3). #}
{% block scripts %}
{% endblock %}