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:
程序员阿江(Relakkes) 2026-05-29 13:21:58 +08:00
parent acbdd7f274
commit 7e417219df
2 changed files with 53 additions and 0 deletions

View 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\)$/)
})
})

View 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(' > ')
}