* Fix Live accept for Elixir templates in lib/
Wrap and accept search the repo for impeccable variant markers. That
search skipped .ex files and the lib/ tree, so Phoenix LiveView markup
inside ~H""" blocks never matched and browser Accept returned
"Session markers not found".
Extend the same EXTENSIONS and searchDirs in live-accept.mjs and
live-wrap.mjs. Add a regression test that accepts from
lib/my_app_web/components/layouts.ex.
* Live: give the source search one owner for template extensions
The #374 fix had to patch the same hardcoded EXTENSIONS array in two
files because live-wrap.mjs and live-accept.mjs each carried their own
copy of the project source walk. The copies had already drifted: same
extension list twice, same searchDirs twice, and one realpathSync
guarded by try/catch while the other was not.
Meanwhile hook-lib.mjs had solved this properly for the design hook in
#316/#347 with a configurable `detector.extensions` and suffix matching
that handles .blade.php and .html.erb. Live never read it, so a project
that taught the hook about .heex still got 'Session markers not found'
on Accept.
- lib/template-extensions.mjs is the single owner. It holds Live's
built-in markup list, the suffix matcher, and the detector.extensions
config reader. hook-lib.mjs now imports its normalize/merge/match
helpers from here instead of duplicating them, and re-exports
matchConfiguredExtension for its existing callers.
- Live resolves built-ins PLUS detector.extensions, so teaching the hook
about a server template teaches wrap and accept at the same time.
- live/source-search.mjs holds the walk both scripts share. Callers pass
the one thing that actually differs (skipDirs, fileFilter). Unifying
gives live-wrap the guarded realpathSync, so a dangling symlink in the
tree no longer throws out of the whole wrap, and makes it skip
.impeccable artifacts the way accept already did.
- Extensions are matched on filename suffix rather than path.extname, so
root.html.heex and show.html.erb resolve.
- Drop .exs. Those are Elixir scripts (mix.exs, config/*.exs), never
markup, and including them only lets a wrap query match build config.
- Fill the Elixir gap in the manual-edit paths, which kept their own
allowlists and would have left Live half-working for Phoenix:
live-commit-manual-edits.mjs and live-manual-edit-evidence.mjs.
Verified the round trip by hand against a Phoenix layout: wrap injects
markers into a ~H""" block in lib/**/*.ex, accept carbonizes the chosen
variant back out.
AI assistance: written with Claude Code.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Nils Kanevad <heliumbrain@users.noreply.github.com>
Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>