Skip to content

refactor(examples): add shared ESM demo helpers, convert 2 pilots (refs #79)#98

Merged
kalwalt merged 1 commit into
devfrom
refactor/79-examples-esm-helpers
Jul 25, 2026
Merged

refactor(examples): add shared ESM demo helpers, convert 2 pilots (refs #79)#98
kalwalt merged 1 commit into
devfrom
refactor/79-examples-esm-helpers

Conversation

@kalwalt

@kalwalt kalwalt commented Jul 25, 2026

Copy link
Copy Markdown
Member

Phase 1 of #79 — creates the shared helper modules and proves them on two representative examples before applying the pattern to the remaining 15. (Plan is in #79.)

New shared modules

examples/js/demo-utils.mjs — kills the real duplication:

Helper Replaces
loadCamera() / stopCamera() ~50 lines of camera/retry/error boilerplate per demo
renderCorners() code duplicated verbatim in 5 demos
renderMonoImage() code duplicated verbatim in 3 demos
showCameraError() the jQuery-hand-rolled "WebRTC not available" path

examples/js/profiler.mjs — a thin wrapper that loads the legacy global-IIFE profiler.js once and re-exports it, so ESM examples can import the profiler without duplicating its ~140 lines. Single source of truth for both UMD and ESM examples.

Pilots converted (ESM + de-jQuery in one pass, behaviour unchanged)

  • grayscale.html — the simple case (already jQuery-free)
  • sample_fast_corners.html — the full case (jQuery + compatibility.js + profiler + dat.GUI), so it exercises the entire helper surface. It sheds ~120 net lines of boilerplate.

Why compatibility.js is dropped here

Audited — it's obsolete: its getUserMedia only tries the removed callback-style API + vendor prefixes (so it falls through to its own error stub on any current browser), rAF/URL have been universal for a decade, and detectEndian/isLittleEndian are referenced by zero examples. grayscale.html already bypassed it. The file stays in the repo so the UMD examples and external links keep working.

The 5 UMD examples stay as-is — deliberately

browser, linalg_example, mat_math_example, matrix_t_example, orb_test keep the UMD script tag, so examples/ documents both consumption paths — and they still open straight from file:// (ES modules require http://).

Verification

Served over a local HTTP server and checked in a real browser:

  • both pilots load with no module/import errors
  • profiler.mjs loads and log() works · dat.GUI works · jQuery and the compatibility shim are gone
  • showCameraError() correctly handles a denied camera
  • browser.html still works unchanged via the UMD global (v0.10.0, matrix_t + singletons OK)
  • Confirmed working with a real webcam by @kalwalt · prettier clean

Next

Phase 2+: convert the remaining 15 camera examples in batches, now that the helper API is validated.

🤖 Generated with Claude Code

#79)

Phase 1 of #79: create the shared helper modules and prove them on two
representative examples before applying the pattern to the remaining 15.

New `examples/js/demo-utils.mjs`:
- `loadCamera()` / `stopCamera()` — modern `navigator.mediaDevices.getUserMedia`
  + `srcObject`, replacing the ~50 lines of camera/retry/error boilerplate each
  demo carried.
- `renderCorners()` — was duplicated verbatim in 5 demos.
- `renderMonoImage()` — was duplicated verbatim in 3 demos.
- `showCameraError()` — the "WebRTC not available" path, previously hand-rolled
  with jQuery in every demo.

New `examples/js/profiler.mjs`: a thin ES-module wrapper that loads the legacy
global-IIFE `profiler.js` once and re-exports it, so ESM examples can import the
profiler without duplicating its ~140 lines. Unlike compatibility.js the
profiler is not obsolete — it is the working stopwatch/FPS readout.

Converted pilots (ESM + de-jQuery in one pass, behaviour unchanged):
- `grayscale.html` — simple case (was already jQuery-free)
- `sample_fast_corners.html` — full case: jQuery + compatibility.js + profiler +
  dat.GUI, so it exercises the whole helper surface

Both now use `<script type="module">` with `import jsfeatNext from
'../dist/jsfeatNext.mjs'`, and no longer load jQuery or `js/compatibility.js`.
That shim was audited and is obsolete: its `getUserMedia` only tries the removed
callback-style API + vendor prefixes (falling through to its own error stub),
its rAF/URL helpers are long-universal, and `detectEndian`/`isLittleEndian` are
referenced by zero examples. The file stays in the repo for the UMD examples.

Per the plan the 5 API-demo examples (browser, linalg_example, mat_math_example,
matrix_t_example, orb_test) deliberately stay on the UMD script tag, so the
folder documents both consumption paths — and they keep working from file://
(ES modules require http://).

Verified in a real browser over a local HTTP server: both pilots load with no
module/import errors; `profiler.mjs` loads and its `log()` works; jQuery and the
compatibility shim are absent; dat.GUI still works; and `browser.html` still
works unchanged via the UMD global (v0.10.0, matrix_t + singletons OK). Both
pilots additionally confirmed working with a real webcam by the maintainer.
Prettier clean.
@kalwalt kalwalt added this to the 1.0.0 milestone Jul 25, 2026
@kalwalt kalwalt self-assigned this Jul 25, 2026
@kalwalt
kalwalt merged commit aac4674 into dev Jul 25, 2026
4 checks passed
kalwalt added a commit that referenced this pull request Jul 25, 2026
Phase 2 of #79: applies the helper API validated in phase 1 (#98) to the
simple and medium tiers — 13 of the remaining 15 camera examples.

Converted (ESM + de-jQuery in one pass, behaviour unchanged):
- simple: boxblur, canny_edge, equalize_hist, gaussblur, scharr, sobel,
  warp_affine, warp_perspective
- medium: oflow_lk, pyrdown, sobel_edge, yape, yape06

Each now uses `<script type="module">` with `import jsfeatNext from
'../dist/jsfeatNext.mjs'`, `loadCamera()`/`stopCamera()`/`showCameraError()`
from `demo-utils.mjs`, and the profiler via `profiler.mjs`. jQuery and
`js/compatibility.js` are gone from all of them; the inline grayscale->RGBA
expansion loops and the duplicated `render_corners`/`render_mono_image`
functions are replaced by the shared `renderMonoImage()`/`renderCorners()`.

Net -684 lines (364 insertions, 1048 deletions) — all boilerplate.

Note on a bug caught during conversion: the mechanical pass initially left
`var ctx, canvasWidth, canvasHeight;` in 10 files. That would have shadowed
the module-level `ctx` with `undefined` and left `canvasWidth`/`canvasHeight`
undefined — `sample_yape.html` passes those straight into
`jsfeatNext.yape.init(...)`. The stale declarations are removed and the two
variables mapped to the `WIDTH`/`HEIGHT` constants (the canvas is 640x480,
so they are identical).

`sample_orb.html` and `sample_orb_pinball.html` are deliberately NOT in this
batch: at ~556/586 lines with four render helpers each plus pattern-training
logic, they are a different risk profile and get their own focused PR.

Verified with an iframe harness loading all 15 ESM examples (these 13 plus
the two phase-1 pilots): every one has a module script, zero jQuery, zero
compatibility shim, and zero non-camera errors. The harness was removed
afterwards. Prettier clean. All 13 additionally confirmed working with a real
webcam by the maintainer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant