mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
feat(desktop): add selector/nth-path builders for element picker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
acbdd7f274
commit
7e417219df
22
desktop/src/preview-agent/selector.test.ts
Normal file
22
desktop/src/preview-agent/selector.test.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { describe, expect, it, beforeEach } from 'vitest'
|
||||
import { buildSelector, buildNthPath } from './selector'
|
||||
|
||||
beforeEach(() => { document.body.innerHTML = `
|
||||
<main><section><h1 id="title">A</h1><p>x</p><p>y</p></section></main>` })
|
||||
|
||||
describe('buildSelector', () => {
|
||||
it('uses id when present', () => {
|
||||
expect(buildSelector(document.getElementById('title')!)).toBe('#title')
|
||||
})
|
||||
it('uses nth-of-type for ambiguous siblings, stopping at nearest id', () => {
|
||||
const secondP = document.querySelectorAll('p')[1]!
|
||||
expect(buildSelector(secondP)).toBe('main > section > p:nth-of-type(2)')
|
||||
})
|
||||
})
|
||||
|
||||
describe('buildNthPath', () => {
|
||||
it('builds a child-index path from root', () => {
|
||||
const secondP = document.querySelectorAll('p')[1]!
|
||||
expect(buildNthPath(secondP)).toMatch(/p:nth-child\(3\)$/)
|
||||
})
|
||||
})
|
||||
31
desktop/src/preview-agent/selector.ts
Normal file
31
desktop/src/preview-agent/selector.ts
Normal file
@ -0,0 +1,31 @@
|
||||
function cssTag(el: Element): string {
|
||||
const tag = el.tagName.toLowerCase()
|
||||
const parent = el.parentElement
|
||||
if (!parent) return tag
|
||||
const same = Array.from(parent.children).filter((c) => c.tagName === el.tagName)
|
||||
if (same.length <= 1) return tag
|
||||
return `${tag}:nth-of-type(${same.indexOf(el) + 1})`
|
||||
}
|
||||
|
||||
export function buildSelector(el: Element): string {
|
||||
if (el.id) return `#${el.id}`
|
||||
const parts: string[] = []
|
||||
let node: Element | null = el
|
||||
while (node && node.nodeType === 1 && node.tagName.toLowerCase() !== 'html' && node.tagName.toLowerCase() !== 'body') {
|
||||
if (node.id) { parts.unshift(`#${node.id}`); break }
|
||||
parts.unshift(cssTag(node))
|
||||
node = node.parentElement
|
||||
}
|
||||
return parts.join(' > ')
|
||||
}
|
||||
|
||||
export function buildNthPath(el: Element): string {
|
||||
const parts: string[] = []
|
||||
let node: Element | null = el
|
||||
while (node && node.parentElement) {
|
||||
const idx = Array.from(node.parentElement.children).indexOf(node) + 1
|
||||
parts.unshift(`${node.tagName.toLowerCase()}:nth-child(${idx})`)
|
||||
node = node.parentElement
|
||||
}
|
||||
return parts.join(' > ')
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user