# `GgenIgniter.Injection`
[🔗](https://github.com/seanchatmangpt/ggen_igniter/blob/v26.9.8/lib/ggen_igniter/injection.ex#L1)

Shared frontmatter-`inject:`-to-`GgenIgniter.Actuate.inject_content!/5`
conversion logic, extracted so `Mix.Tasks.GgenIgniter.Sync` (the original,
standalone pipeline) and `GgenIgniter.Reactors.ReconcileReactor` (the
opt-in Reactor pipeline) share exactly ONE real implementation instead of
two independently-drifting copies -- see this module's functions'
individual docs for the full mapping table (originally authored inline in
`Mix.Tasks.GgenIgniter.Sync`, moved here verbatim, behavior unchanged).

Two real entry points:

  * `resolve_injection!/1` -- converts a `GgenIgniter.Frontmatter.t()`'s
    `inject:`/`before:`/`after:`/`at_line:` fields into
    `{marker, insert_mode, insert_opts}`, `Actuate.inject_content!/5`'s
    real `marker`/`insert_mode`/`opts` args (minus `path`/`content`,
    which are call-site-specific). Requires exactly one of
    `before:`/`after:`/`at_line:` -- zero or more than one raises a
    clear, named `ArgumentError` (a template-authoring error, never a
    silent pick).
  * `strip_single_trailing_newline/1` -- strips exactly one trailing
    `"\n"` from a rendered injection body before it reaches
    `Actuate.inject_content!/5`, which otherwise splices in one real
    extra blank line (mirrors `Actuate`'s own trailing-newline handling
    for the TARGET file's lines).

# `resolve_injection!`

```elixir
@spec resolve_injection!(GgenIgniter.Frontmatter.t()) ::
  {String.t() | Regex.t() | nil, :before | :after | :at_line, keyword()}
```

Converts a template's `inject:`/`before:`/`after:`/`at_line:` frontmatter
fields into `Actuate.inject_content!/5`'s real args
(`{marker, insert_mode, insert_opts}`). Exactly one anchor is required --
`before` OR `after` OR `at_line`, never zero, never more than one.

# `strip_single_trailing_newline`

```elixir
@spec strip_single_trailing_newline(String.t()) :: String.t()
```

A rendered template body ends in a trailing `"\n"` as a plain
file-formatting convention -- but `Actuate.inject_content!/5` itself does
`String.split(content, "\n")` un-trimmed, so an un-stripped trailing
`"\n"` would splice in one real extra blank line at the end of the
injected block. Strips exactly one trailing `"\n"` (mirroring
`Actuate`'s own `drop_trailing_empty/1` for the TARGET file's lines),
without guessing at or discarding any blank lines the template author put
there deliberately (a second trailing blank line in the template body is
left fully intact).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
