@@ -173,6 +173,7 @@ export function buildDefaultDomEditTextField(base?: Partial<DomEditTextField>):
173173// fallow-ignore-next-line complexity
174174export function resolveDomEditCapabilities ( args : {
175175 selector ?: string ;
176+ hfId ?: string ;
176177 tagName ?: string ;
177178 className ?: string ;
178179 inlineStyles : Record < string , string > ;
@@ -182,7 +183,7 @@ export function resolveDomEditCapabilities(args: {
182183 isMasterView : boolean ;
183184 existsInSource ?: boolean ;
184185} ) : DomEditCapabilities {
185- if ( ! args . selector || args . isInsideLockedComposition ) {
186+ if ( ( ! args . selector && ! args . hfId ) || args . isInsideLockedComposition ) {
186187 return {
187188 canSelect : ! args . isInsideLockedComposition ,
188189 canEditStyles : false ,
@@ -289,7 +290,7 @@ export function buildElementLabel(el: HTMLElement): string {
289290async function probeSourceElement (
290291 projectId : string ,
291292 sourceFile : string ,
292- target : { id ?: string ; selector ?: string ; selectorIndex ?: number } ,
293+ target : { id ?: string ; hfId ?: string ; selector ?: string ; selectorIndex ?: number } ,
293294) : Promise < boolean > {
294295 try {
295296 const response = await fetch (
@@ -321,7 +322,8 @@ export async function resolveDomEditSelection(
321322 let current : HTMLElement | null = getSelectionCandidate ( startEl , options ) ;
322323 while ( current && current !== doc . body && current !== doc . documentElement ) {
323324 const selector = buildStableSelector ( current ) ;
324- if ( ! selector ) {
325+ const hfId = readHfId ( current ) ;
326+ if ( ! selector && ! hfId ) {
325327 current = current . parentElement ;
326328 continue ;
327329 }
@@ -330,13 +332,9 @@ export async function resolveDomEditSelection(
330332 current ,
331333 options . activeCompositionPath ,
332334 ) ;
333- const selectorIndex = getSelectorIndex (
334- doc ,
335- current ,
336- selector ,
337- sourceFile ,
338- options . activeCompositionPath ,
339- ) ;
335+ const selectorIndex = selector
336+ ? getSelectorIndex ( doc , current , selector , sourceFile , options . activeCompositionPath )
337+ : undefined ;
340338 const compositionSrc =
341339 current . getAttribute ( "data-composition-src" ) ??
342340 current . getAttribute ( "data-composition-file" ) ??
@@ -346,15 +344,18 @@ export async function resolveDomEditSelection(
346344 const textFields = collectDomEditTextFields ( current ) ;
347345 const isInsideLocked = Boolean ( findClosestByAttribute ( current , [ "data-timeline-locked" ] ) ) ;
348346 let existsInSource : boolean | undefined ;
349- if ( ! options . skipSourceProbe && options . projectId && ( current . id || selector ) ) {
350- const probeTarget : { id ?: string ; selector ?: string ; selectorIndex ?: number } = { } ;
347+ if ( ! options . skipSourceProbe && options . projectId && ( current . id || selector || hfId ) ) {
348+ const probeTarget : { id ?: string ; hfId ?: string ; selector ?: string ; selectorIndex ?: number } =
349+ { } ;
351350 if ( current . id ) probeTarget . id = current . id ;
351+ if ( hfId ) probeTarget . hfId = hfId ;
352352 if ( selector ) probeTarget . selector = selector ;
353353 if ( selectorIndex != null ) probeTarget . selectorIndex = selectorIndex ;
354354 existsInSource = await probeSourceElement ( options . projectId , sourceFile , probeTarget ) ;
355355 }
356356 const capabilities = resolveDomEditCapabilities ( {
357357 selector,
358+ hfId,
358359 tagName : current . tagName . toLowerCase ( ) ,
359360 className : current . className ,
360361 inlineStyles,
@@ -369,7 +370,7 @@ export async function resolveDomEditSelection(
369370 return {
370371 element : current ,
371372 id : current . id || undefined ,
372- hfId : current . getAttribute ( "data-hf-id" ) ?? undefined ,
373+ hfId,
373374 selector,
374375 selectorIndex,
375376 sourceFile,
@@ -452,6 +453,7 @@ export function collectDomEditLayerItems(
452453 if ( ! root ) return [ ] ;
453454
454455 const items : DomEditLayerItem [ ] = [ ] ;
456+ // fallow-ignore-next-line complexity
455457 const visit = ( el : HTMLElement , depth : number ) => {
456458 if ( items . length >= maxItems ) return ;
457459
@@ -465,6 +467,7 @@ export function collectDomEditLayerItems(
465467 depth,
466468 childCount : getDirectLayerChildren ( el , options ) . length ,
467469 id : target . id ?? undefined ,
470+ hfId : target . hfId ?? undefined ,
468471 selector : target . selector ?? undefined ,
469472 selectorIndex : target . selectorIndex ,
470473 sourceFile : target . sourceFile ,
@@ -536,10 +539,11 @@ export function getDomEditNonEditableReason(
536539}
537540
538541export function getDomEditTargetKey (
539- selection : Pick < DomEditSelection , "id" | "selector" | "selectorIndex" | "sourceFile" > ,
542+ selection : Pick < DomEditSelection , "id" | "hfId" | " selector" | "selectorIndex" | "sourceFile" > ,
540543) : string {
541544 return [
542545 selection . sourceFile || "index.html" ,
546+ selection . hfId ?? "" ,
543547 selection . id ?? "" ,
544548 selection . selector ?? "" ,
545549 selection . selectorIndex ?? "" ,
@@ -556,6 +560,10 @@ export function isTextEditableSelection(selection: DomEditSelection): boolean {
556560
557561// buildElementAgentPrompt is in domEditingAgentPrompt.ts
558562
563+ export function readHfId ( element : Element ) : string | undefined {
564+ return element . getAttribute ( "data-hf-id" ) ?. trim ( ) || undefined ;
565+ }
566+
559567export function buildDomEditPatchTarget (
560568 selection : Pick < DomEditSelection , "id" | "hfId" | "selector" | "selectorIndex" > ,
561569) : { id ?: string | null ; hfId ?: string ; selector ?: string ; selectorIndex ?: number } {
0 commit comments