Shared scan for the phx_*_without_id checks.
offending_tag_lines/2 returns the source line of every tag in the HEEx
templates of source_file that matches detect_attr.(text) but does not
carry an id= attribute. Each concrete check supplies its own attribute
detector and wraps these line numbers in a formatted issue.
Detection of open tags is intentionally restricted to standard and Phoenix
component tags (<Tag>, <.component>); closing tags (</...) and HEEx
interpolation (<%) are skipped because neither / nor % can follow <
in the required shape.