Initial release.
Added
- Two mutator families over the phoenix_swoosh template-rendering surface,
each reported under its own name and independently enable-able:Mutare.Phoenix.Swoosh.RenderBody(:render_body) — the "which body
parts render" seam. Removes arender_body/2,3call, collapsing to the
email (remove— the email ships with no rendered body); narrows a
literal atom template to each of its string forms (html_only/
text_only— only the.html/ only the.textbody renders, the "one
body part broke and nobody noticed" gap); and drops one entry per mutant
from a literalput_new_formats/2map (format— that extension stops
rendering, the custom-formats form of the same gap). Both wrapper arities
fire, theuse-injected default-assigns/2form included; a string or
computed template gets the removal mutant alone, and a single-entry format
map produces no drop (that is theremovemutant's diff).Mutare.Phoenix.Swoosh.Layout(:mail_layout) — the "which layout wraps
the body" seam. Removes a layout setter, collapsing to the email:
put_layout/2(put— the previous layout stays) andput_new_layout/2
(put_new— the layout stays unset and the body renders bare); and
suppresses the layout at the render site by writinglayout: falseinto
render_body's assigns (off), which is where ause-configured layout
can be reached at runtime at all.offfires only where a layout is
demonstrably in effect — the mailer'suseline configured one, or the
call's own assigns carry a truthylayout:— so it never mints an
equivalent mutant. Literal map and keyword assigns gain the entry
in place, an existinglayout:entry is turned off rather than
duplicated, a computed assigns argument is normalised the way
phoenix_swoosh normalises it (Enum.into/2thenMap.put/3), and the
default-assigns/2form gains its assigns map without requalifying the
bare call (which would skip theusewrapper'sput_new_view).
- Structural pins on phoenix_swoosh's identifier positions, via call-routing
registry:rawroutes covering the whole argument subtree: the template
name, the layout value (tuple interior included), andput_new_formats/2's
extension→field map — a perturbed value there is a missing-template crash
at render, so core's value families never mint mutants in those positions.
The format map's owner then mints the one safe mutation there itself. - A
Mutare.UseExpansionextension (Mutare.Phoenix.Swooshunder
:extensions) that takes overuse Phoenix.Swooshand surfaces a whole
import Phoenix.Swooshin place of the real injected
except: [render_body: 3]import + local wrapper pair — the piece that
makes barerender_bodycalls resolvable (and their witness safe) at all.
The standalonetemplate_root:style additionally surfaces the
import Phoenix.Viewits nestedusewould inject. The same expansion
reports whether theuseline configured a layout, as the
Mutare.Phoenix.Swoosh.LayoutConfiguredmarker — the one channel ause
expansion has into a mutator's context, and how a compile-time option gates
a runtime mutant. - Every family matches its call written qualified, aliased, bare-imported, or
piped (a piped removal becomes theFunction.identity()no-op stage). - Ignore-variant labels throughout, so
# mutare:ignore[family:label]can
suppress one kind of mutant (e.g.[render_body:text_only],
[render_body:format],[mail_layout:put],[mail_layout:off]). Mutare.Phoenix.Swoosh.all/0for splicing both families into a:mutators
list, composing with the baseMutare.Swoosh.all/1preset from
mutare_swoosh(a dependency of this package).- Documented scope: the
use Phoenix.Swooshline's own options are
compile-time configuration Mutare prunes whole, so only the runtime calls
that configuration flows through are mutable; layout-name narrowing and the
put_new_layout↔put_layoutswap are written down as deferrals with
their reasons; and the README carries a verified recipe for pinning core's
whole-assigns-map collapse per project.