Skip to content

Commit 543d92c

Browse files
lukemerrettclaude
andcommitted
feat(cohort): let callers suppress inlined assets; test the vendor path
Add an `include_assets` flag to render_html_form() (default True). When a page renders more than one cohort form, or already loads Tom Select itself, callers can pass include_assets=False on the later forms so the ~50KB library isn't inlined more than once; the form markup and the initializer are still emitted and bind to the page-level Tom Select. Add tests covering the vendored-asset path: one asserts the library is inlined and the event selects are tagged (guarding against the assets being dropped from the wheel or the template variables drifting), and one asserts include_assets=False suppresses the library while keeping the form and initializer. Also correct an over-claim: inlining removes third-party runtime calls (the production-readiness requirement) but does not by itself satisfy a strict self-only CSP, which still blocks inline tags without a nonce. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent b18a535 commit 543d92c

3 files changed

Lines changed: 59 additions & 8 deletions

File tree

bitmapist/cohort/__init__.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,11 @@
8282
# --- HTML rendering
8383

8484
# Tom Select is vendored (not loaded from a CDN) so the cohort form makes no
85-
# third-party network calls at runtime and works in offline / CSP-restricted
86-
# deployments. The assets are inlined into the fragment because the library has
87-
# no static-serving mechanism of its own -- consumers just embed the string
88-
# returned by render_html_form().
85+
# third-party network calls at runtime and works offline. The assets are inlined
86+
# into the fragment because the library has no static-serving mechanism of its
87+
# own -- consumers just embed the string returned by render_html_form(). Note
88+
# that inline tags still require the host's CSP to permit inline script/style
89+
# (or that callers pass include_assets=False and load Tom Select themselves).
8990
_TOM_SELECT_CSS = "tmpl/vendor/tom-select-2.3.1.default.min.css"
9091
_TOM_SELECT_JS = "tmpl/vendor/tom-select-2.3.1.complete.min.js"
9192

@@ -115,6 +116,7 @@ def render_html_form(
115116
num_results: int = 31,
116117
num_of_rows: int = 12,
117118
start_date: Optional[str] = None,
119+
include_assets: bool = True,
118120
):
119121
"""
120122
Render a HTML form that can be used to query the data in bitmapist.
@@ -129,6 +131,11 @@ def render_html_form(
129131
:param :select1b What is the current selected filter (extra, optional)
130132
:param :select2 What is the current selected filter (second)
131133
:param :select2b What is the current selected filter (extra, optional)
134+
:param :include_assets Whether to inline the vendored Tom Select CSS/JS into
135+
the fragment. Defaults to `True`. Set to `False` when rendering more than
136+
one form on a page, or when the host page already loads Tom Select, to
137+
avoid shipping the library more than once. The searchable dropdowns still
138+
initialize as long as Tom Select is available on the page.
132139
133140
"""
134141
# mandatory
@@ -159,8 +166,11 @@ def render_html_form(
159166
num_results=int(num_results),
160167
num_of_rows=int(num_of_rows),
161168
start_date=start_date,
162-
tom_select_css=_read_vendor_asset(_TOM_SELECT_CSS),
163-
tom_select_js=_read_vendor_asset(_TOM_SELECT_JS),
169+
include_assets=include_assets,
170+
tom_select_css=_read_vendor_asset(_TOM_SELECT_CSS)
171+
if include_assets
172+
else "",
173+
tom_select_js=_read_vendor_asset(_TOM_SELECT_JS) if include_assets else "",
164174
)
165175
)
166176

bitmapist/cohort/tmpl/form_data.mako

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
<%doc>
22
Tom Select 2.3.1 is vendored and inlined (see bitmapist/cohort/tmpl/vendor/)
33
rather than loaded from a CDN, so the cohort form makes no third-party
4-
network calls at runtime and works in offline / CSP-restricted deployments.
4+
network calls at runtime and works offline.
5+
6+
Emitting the library is gated on `include_assets` so a caller that renders
7+
more than one cohort form on a page (or already loads Tom Select itself)
8+
can suppress the duplicated CSS/JS by passing include_assets=False on the
9+
later forms. The small initializer below is always emitted and no-ops if
10+
the library isn't present.
511
</%doc>
12+
%if include_assets:
613
<style>${ tom_select_css | n }</style>
14+
%endif
715

816
<style>
917
.cohort_form dd {
@@ -102,7 +110,9 @@
102110
The library is inlined here, after the form markup, so the browser can
103111
render the form before parsing/executing ~50KB of JS.
104112
</%doc>
113+
%if include_assets:
105114
<script>${ tom_select_js | n }</script>
115+
%endif
106116

107117
<script>
108118
// Turn the event dropdowns into searchable selects. With hundreds of

test/test_cohort.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
from bitmapist import mark_event
6-
from bitmapist.cohort import _weeks_events_fn, get_dates_data
6+
from bitmapist.cohort import _weeks_events_fn, get_dates_data, render_html_form
77

88

99
@pytest.fixture
@@ -88,3 +88,34 @@ def test_weeks_events_fn_iso_year_boundary():
8888

8989
# Both dates should produce the same week event
9090
assert event.redis_key == event2.redis_key
91+
92+
93+
def test_render_html_form_inlines_vendored_assets():
94+
"""The vendored Tom Select library ships in the package and is inlined.
95+
96+
Guards against a silent packaging/integration regression: if the vendored
97+
assets are dropped from the wheel, the on-disk path resolution breaks, or
98+
the template variables stop lining up, this fails instead of the public
99+
API raising at call time.
100+
"""
101+
html = render_html_form(action_url="/", selections1=[("Active", "active")])
102+
assert "Tom Select v2.3.1" in html # vendored library JS inlined
103+
assert "cohort-event-select" in html # event selects tagged for enhancement
104+
assert "new TomSelect" in html # initializer present
105+
106+
107+
def test_render_html_form_can_suppress_assets():
108+
"""include_assets=False omits the bundled library so it isn't shipped twice.
109+
110+
Lets a caller rendering more than one cohort form on a page (or a host that
111+
already loads Tom Select) avoid duplicating the library, while the form and
112+
its initializer are still emitted.
113+
"""
114+
html = render_html_form(
115+
action_url="/",
116+
selections1=[("Active", "active")],
117+
include_assets=False,
118+
)
119+
assert "Tom Select v2.3.1" not in html # library not re-emitted
120+
assert "cohort-event-select" in html # form still rendered
121+
assert "new TomSelect" in html # initializer still present (uses page-level lib)

0 commit comments

Comments
 (0)