Skip to content

feat(htmx): vendored htmx 2.0.6 loader + tests (tranche A of filter pilot)#7066

Draft
somethingwithproof wants to merge 15 commits into
Cacti:developfrom
somethingwithproof:feat/htmx-filters-develop
Draft

feat(htmx): vendored htmx 2.0.6 loader + tests (tranche A of filter pilot)#7066
somethingwithproof wants to merge 15 commits into
Cacti:developfrom
somethingwithproof:feat/htmx-filters-develop

Conversation

@somethingwithproof

Copy link
Copy Markdown
Contributor

Draft. Tranche A only: lands the loader, the feature flag, and full three-layer test coverage. No page migration yet.

Motivation

filters always sucked

@TheWitness

What this does

  • Vendors htmx.min.js 2.0.6 at include/js/ with SRI sha384 hash emitted by htmx_script_tag().
  • New lib/htmx.php with four helpers: cacti_htmx_enabled(), htmx_is_fragment_request(), htmx_script_tag(), htmx_version().
  • Loader fires from html_common_header after jquery, before plugin JS. Opt-in per element; no global hx-boost.
  • New setting htmx_enabled (default on) gates the loader site-wide.
  • Zero changes to draw_edit_form, form_start, form_area, or any form-rendering helper. Filter bars are unchanged in this tranche.

What this doesn't do yet

  • No pilot page migration. devices.php is the planned tranche B target but the filter bar still submits-and-reloads as it does today.
  • No hx-push-url, no fragment-rendering branches on any .php page, no plugin compatibility advisory.

Those land in the tranche B PR after this one passes review.

Tests

  • Unit (Pest, tests/Unit/HtmxTest.php): 11 tests. Nonce format, idempotency, flag-off/on, missing-version-file, HX-Request header detection, script-tag shape.
  • Integration (Pest + php -S, tests/integration/HtmxLoaderTest.php): 6 tests. Real HTTP response asserts on the emitted script tag and fragment-request detection.
  • E2E (Playwright, tests/e2e/tests/htmx-loader.spec.ts): 4 tests. Login page ships the tag, the file loads 200, window.htmx is defined, integrity attribute present.

All three layers land wired into .github/workflows/htmx-filters.yml with an Apache-based docker-compose stack for the E2E leg.

Out of scope

  • Any list-page filter migration.
  • AJAX endpoint refactor.
  • Plugin API changes.
  • Form rendering.
  • Authentication.
  • Theme / dark mode.

Rollback

Set htmx_enabled to off in settings; loader stops emitting the script tag on every page. No code revert needed.

@somethingwithproof somethingwithproof force-pushed the feat/htmx-filters-develop branch 3 times, most recently from c887cdc to f634148 Compare April 28, 2026 09:17
bmfmancini
bmfmancini previously approved these changes Apr 29, 2026
somethingwithproof and others added 10 commits June 12, 2026 17:08
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Improve IPv6 support in RRDtool proxy and ping utilities

- Fix RRDtool proxy to dynamically detect IPv6 addresses and use
  AF_INET6 sockets instead of hardcoded AF_INET (IPv4-only), enabling
  connections to IPv6 RRDtool proxy servers including backup servers
- Strip brackets from IPv6 addresses before passing to socket_connect
- Properly close failed sockets before creating new ones for failover
- Replace fragile str_contains(':') IPv6 detection in ping with
  filter_var(FILTER_FLAG_IPV6) for more robust address validation

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Fix JS code quality: implicit globals, deprecated APIs, loose equality

- Add var declarations to prevent implicit globals in install.js
  (element, enabled, button, buttonCheck)
- Remove console.log debug output left in production (install.js)
- Replace deprecated jQuery .unbind() with .off() (layout.js)
- Fix "depreciated" typo to "deprecated" in deprecation warnings
- Convert == / != to === / !== for null, boolean, string, typeof,
  and numeric comparisons across install.js and realtime.js

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Replace deprecated jQuery shorthand event methods in layout.js

Replace .click(), .keyup(), .keydown(), .mousedown(), .mouseenter(),
.mouseleave(), .submit(), .resize() with .on() equivalents. Replace
.focus(), .change() trigger calls with .trigger(). These shorthands
were deprecated in jQuery 3.5.

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Replace deprecated jQuery methods in realtime.js

Replace .bind() with .on() and .change() trigger calls with
.trigger('change'). .bind() was deprecated in jQuery 3.0 and
shorthand triggers in jQuery 3.5.

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Replace deprecated jQuery methods in install.js and fix ===/!== errors

Replace .click(), .change(), .focus() with .on()/.trigger() equivalents.
Also fix !=== and ==== operators that were incorrectly introduced by a
prior replace-all of == to === within existing !== and === expressions.

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Restore == null where needed to catch both null and undefined

In JavaScript, == null matches both null and undefined, which is an
intentional idiom. The prior === null conversion broke cases where
values come from jQuery .val(), .data(), $.urlParam(), or object
property access that may return undefined rather than null. Revert
those specific cases while keeping === null where variables are
explicitly initialized to null.

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Replace deprecated jQuery methods in all theme main.js files

Replace .unbind().click() with .off('click').on('click'), convert
.hover() to .on('mouseenter').on('mouseleave'), replace .change(),
.scroll(), .click() shorthands with .on() equivalents, and .blur()
with .trigger('blur') across all 10 theme files.

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Convert string concatenation to template literals

Replace 'str' + var + 'str' patterns with ES6 template literals
in realtime.js and install.js. Improves readability especially for
URL construction and HTML building. Also replace $.parseJSON() with
native JSON.parse() in realtime.js.

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

* Convert var to const for single-assignment variables

Replace var with const where the variable is assigned once and never
reassigned within its scope, in install.js and realtime.js. Keeps var
for variables that are conditionally reassigned (e.g. size, url).

https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo

---------

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
CLAUDE.md lists these as must-never-commit but .gitignore didn't
enforce it. Add the four entries so agent state cannot leak into a
PR diff by accident.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Ship include/js/htmx.min.js pinned to 2.0.6 with SRI sha384 hash
emitted by the new htmx_script_tag() helper in lib/htmx.php. Load
fires from html_common_header after jquery but before plugin JS,
so pages can opt into hx-* attributes without additional includes.
Setting htmx_enabled (default on) gates the loader site-wide.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Eleven Pest unit tests for cacti_htmx_enabled, htmx_is_fragment_request,
htmx_script_tag, htmx_version. Six integration tests exercising the
loader under a live php -S with the enabled/disabled flag and with/
without HX-Request. Four Playwright tests verifying the login page
emits the htmx script tag with SRI, the file loads 200, window.htmx
is defined, and the integrity attribute is present. CI workflow runs
all three layers on push/PR touching the loader surface.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
…cript

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
@somethingwithproof somethingwithproof force-pushed the feat/htmx-filters-develop branch from 86f36f8 to 3ba1a37 Compare June 13, 2026 00:18
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Clears the level 6 alreadyNarrowedType error on lib/data_query.php:2591 that
develop currently emits, matching the sibling narrowing identifiers already ignored.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants