Files
computer-playbook/docs/agents/files/role/javascript.js.md
kevinveenbirkenbachandClaude Opus 5 575a5a87ac refactor(layout): sort shipped scripts by language and split the unit suite
Every script a role ships now lives under `files/<language>/`, and the unit
suite is split the same way: `tests/unit/python/` beside new sibling trees for
the other languages. `tests/lint/filesystem/test_role_files_layout.py` keeps it
that way; directories whose shape is dictated from outside carry a `.nocheck`
naming the constraint (Docker build contexts, WordPress mu-plugins, the Joomla
extension, Odoo addons, Playwright suites, the `files/test/test.sh` harness
that `test-e2e-cli` resolves generically).

This cannot be applied in halves. Moving a file and repointing what names it
are the same change: 14 references resolve only at deploy time, so the tree is
green either before or after, never between.

Those 14 were found by static resolution over every reference class, not by the
test suite -- a full `make quality-high` was green while all of them were
broken:

  * 7 `src:` values built from a role variable holding a bare filename
    (svc-bkp-remote-2-local, decidim, espocrm, friendica, joomla, pixelfed x2).
    The variable doubles as the destination name inside the container, so the
    language segment belongs at the call site, not in the variable.
  * `sys-service/tasks/04_base.yml` resolved every consumer's systemd script
    through `first_found(..., errors='strict')` over `files/script.{sh,py}`.
    18 roles ship exactly that and have no template fallback: the play would
    have died on each.
  * `sys-front-inj-javascript` fell back to `<role>/files/javascript.js`; the
    interface now reads `files/javascript/javascript.js`.
  * `sys-front-inj-logout/templates/head_sub.j2` built the cache-busting mtime
    path through `path_absolute(... 'files', ...)`.
  * 4 `ansible.builtin.script:` invocations naming a bare command
    (pull.py, prune.sh, set_postgres_superuser_password.sh, ganesha-serve.sh).
  * `dev-python/files/shell/install.sh` pointed at a sibling role's script.

Depth-dependent paths inside the moved trees were bumped accordingly: 59
`parents[N]` computations, 12 relative climbs, and the per-role recover CLI,
whose path `cli/administration/recover/recoverers.py` still assembled from the
pre-move location.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 01:31:09 +02:00

2.9 KiB

javascript.js

This page covers automatically generating and updating role-local javascript.js, javascript.js.j2, and equivalent injected browser entry files. Use this page for implementation scope, DOM strategy, and live review. For injector wiring, activation, and repository-wide behavior rules, see Contributing javascript.js.

Goal

  • You MUST use role-local JavaScript only for browser-side gaps that cannot be solved cleanly through app configuration, server configuration, or CSS alone.
  • Keep injected scripts small, explicit, and tightly scoped to the role's real integration need.
  • Write the result so it adapts the upstream UI without turning the injected script into a fork of the application's frontend.

Implement

  • You MUST use templates/javascript.js.j2 when runtime values from the inventory or role variables must be rendered into the browser code.
  • You MUST use files/javascript/javascript.js when the script is static and does not depend on templating.
  • You MUST wait for the DOM before touching elements, and guard missing elements so unrelated pages do not break.
  • You MUST keep event handlers, observers, and DOM mutations idempotent because injected scripts may run on dynamic pages or be triggered repeatedly.
  • You MUST prefer stable selectors and narrow hooks over text matching or timing-based hacks.

Avoid

  • Do NOT reimplement server-side logic, authentication protocols, or business rules in injected JavaScript.
  • Do NOT rewrite large parts of the frontend when a focused event handler, DOM adjustment, or configuration change is enough.
  • Do NOT rely on fragile selectors, broad text matching, or timing hacks when more stable hooks exist.
  • Do NOT introduce noisy debug logging, uncaught errors, duplicate event handlers, or endless observers into injected scripts.
  • Do NOT break native login, logout, navigation, or form flows unless the role explicitly requires that change and the new behavior is verified end to end.

Review

  • You MUST check the result with live inspection in the running application, not only by reading the JavaScript file.
  • You MUST compare the implemented behavior against the rendered UI so missing hooks, duplicate handlers, broken selectors, and unexpected side effects become visible.
  • You MUST at minimum inspect and compare the start page and the login page because these pages usually expose the most important navigation, authentication, and first-load behavior.
  • You MUST check the browser console for JavaScript errors or repeated side effects after the script is injected.
  • If the change affects user-visible behavior, you MUST add or update the matching end-to-end coverage in Role playwright.spec.js.
  • You MUST check that the final JavaScript still feels like a small role-local adaptation of the target application, not a forked frontend implementation.