# `MishkaCmsCore.Runtime.PageBuilder.Ids`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/page_builder/ids.ex#L5)

One DOM id per element, and the references inside a snippet follow when one has to change.

## Why a second copy is not the same document twice

Everything the palette offers is a worked EXAMPLE, and an example names things: the kit's delete
dialog ships `id="modal-delete-page"` with `id="btn-delete-cancel"` beside it, and its newsletter
dialog ships an `<input id="modal-newsletter-email">` with a `<label for="modal-newsletter-email">`
pointing at it. Those names are most of what makes an example readable. Placing one twice — which
is the ordinary way to build a second dialog — put two elements in the document answering to one
id, and a duplicate id is not a cosmetic fault:

  * `JS.exec("data-pb-open", to: "#modal-delete-page")` reaches whichever came first, so the
    author's second button opens the first dialog
  * `document.getElementById` and every `phx-target` behave the same way
  * LiveView refuses to patch a container it cannot tell apart and raises

## The arrival yields

`arrived` is the node ids the op just created, and they are the ones renamed — the same rule, and
for the same reason, that `MishkaCmsCore.Runtime.PageBuilder.PageForms.Naming.dedupe/2` follows.
Renaming in document order would rewrite the dialog already on the page whenever the new one was
dropped above it, and that dialog is the one whose id an author has already written a handler,
a link or an interaction against.

Numbering fills gaps rather than counting: `modal-delete-page` beside `modal-delete-page-3` mints
`modal-delete-page-2`, so deleting the second of three copies does not push the next to `-4`.

## References move with the name

Renaming the copy's dialog and leaving the copy's button pointing at the original would be worse
than the collision — the author would have two buttons that both open the first dialog and no
visible reason why. So every reference to the old id is rewritten, in three shapes, and only
WITHIN the nodes that arrived:

  * a selector anywhere in a value, string or expression — `to: "#modal-delete-page"`, `href`,
    `data-cancel`
  * a quoted literal inside an expression — `show_modal("modal-delete-page")`
  * a bare id in an attribute that takes one — `for`, `aria-controls`, `headers` and friends,
    including the space-separated lists three of them accept

Nodes that were already on the page are never touched: they point at the original id, the original
still has it, and they are right.

# `dedupe`

```elixir
@spec dedupe(MishkaCmsCore.Runtime.PageBuilder.Tree.t(), Enumerable.t()) ::
  MishkaCmsCore.Runtime.PageBuilder.Tree.t()
```

Renames every arrived element that claimed an id something else already answers to, rewriting the
arrivals' own references to it in the same pass.

With nothing arrived there is nothing to rename: a document that came in whole — a hand edit in
the code drawer, a draft restore — is the author's own text, and silently renumbering ids they
typed is a rewrite they did not ask for. The collision is theirs to see and theirs to fix.

---

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