Skip to content

feat(core): ensureHfIds node-id pass + shared hf- mint helper (R1)#1269

Open
vanceingalls wants to merge 1 commit into
mainfrom
06-07-feat_core_ensurehfids_node-id_pass_shared_hf-_mint_helper_r1_
Open

feat(core): ensureHfIds node-id pass + shared hf- mint helper (R1)#1269
vanceingalls wants to merge 1 commit into
mainfrom
06-07-feat_core_ensurehfids_node-id_pass_shared_hf-_mint_helper_r1_

Conversation

@vanceingalls
Copy link
Copy Markdown
Collaborator

@vanceingalls vanceingalls commented Jun 8, 2026

What

Adds ensureHfIds(html: string): string in packages/core/src/parsers/hfIds.ts. Single DOM pass (via linkedom) that mints a data-hf-id attribute on every eligible element before the caller sees the markup.

Id derivation: FNV-1a 32-bit hash of tagName | sorted-attrs(\x00/\x01 separated) | ownText, last 4 chars of base-36, hf- prefix. Collision resolution appends a sibling counter and re-hashes. Preserves existing ids (elements with data-hf-id already set are skipped). Excludes non-visual tags: script, style, template, meta, link, noscript, base.

Fragment handling: detects bare HTML fragments (no <!doctype / <html) and wraps in a full document shell before parsing, then returns body.innerHTML — matching the pattern used by parseSourceDocument in sourceMutation.

Why

Counter-based ids (element-0, element-1, …) are positional. Inserting a new layer at position 0 shifts every id below it. The R1 milestone requires content-based, stable ids so that targeting operations (split, patch, probe) stay valid across re-parses and element insertions. T2 spec (stableIds.test.ts) defines the contract: same content → same id, adding a sibling doesn't change other ids, format matches /^hf-[a-z0-9]{4}$/.

How

  • toHfId(hash)slice(-4) of hash.toString(36) for better distribution across the suffix space
  • data-hf-id is excluded from the hash input (prevents circular dependency on the attribute being set)
  • Already-assigned ids tracked in a Set; duplicates get a counter suffix before re-hashing
  • Fragment detection: /<!doctype|<html[\s>]/i.test(html) — if bare, wrap→parse→body.innerHTML

Test plan

Copy link
Copy Markdown
Collaborator Author

vanceingalls commented Jun 8, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant