MCPcopy Create free account
hub / github.com/TanStack/devtools / createHeadChanges

Function createHeadChanges

packages/devtools/src/hooks/use-head-changes.ts:37–110  ·  view source on GitHub ↗
(
  onChange: (change: HeadChange, raw?: MutationRecord) => void,
  opts: UseHeadChangesOptions = {},
)

Source from the content-addressed store, hash-verified

35}
36
37export function createHeadChanges(
38 onChange: (change: HeadChange, raw?: MutationRecord) => void,
39 opts: UseHeadChangesOptions = {},
40) {
41 const {
42 attributes = true,
43 childList = true,
44 subtree = true,
45 observeTitle = true,
46 } = opts
47
48 onMount(() => {
49 const headObserver = new MutationObserver((mutations) => {
50 for (const m of mutations) {
51 if (m.type === 'childList') {
52 m.addedNodes.forEach((node) => onChange({ kind: 'added', node }, m))
53 m.removedNodes.forEach((node) =>
54 onChange({ kind: 'removed', node }, m),
55 )
56 } else if (m.type === 'attributes') {
57 const el = m.target as Element
58 onChange(
59 {
60 kind: 'attr',
61 target: el,
62 name: m.attributeName,
63 oldValue: m.oldValue ?? null,
64 },
65 m,
66 )
67 } else {
68 // If someone mutates a Text node inside <title>, surface it as a title change.
69 const isInTitle =
70 m.target.parentNode &&
71 (m.target.parentNode as Element).tagName.toLowerCase() === 'title'
72 if (isInTitle) onChange({ kind: 'title', title: document.title }, m)
73 }
74 }
75 })
76
77 headObserver.observe(document.head, {
78 childList,
79 attributes,
80 subtree,
81 attributeOldValue: attributes,
82 characterData: true, // helps catch <title> text node edits
83 characterDataOldValue: false,
84 })
85
86 // Extra explicit observer for <title>, since `document.title = "..."`
87 // may not always bubble as a head mutation in all setups.
88 let titleObserver: MutationObserver | undefined
89 if (observeTitle) {
90 const titleEl =
91 document.head.querySelector('title') ||
92 // create a <title> if missing so future changes are observable
93 document.head.appendChild(document.createElement('title'))
94

Callers 2

SerpPreviewSectionFunction · 0.90
SocialPreviewsSectionFunction · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected