v1.1.0: pooled runtime, 959 tests, production hardening (0 squash)
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* World builder for Playwright-extracted elements.
|
||||
*
|
||||
* Converts raw extracted element data (from page.evaluate bounding boxes)
|
||||
* into a solver-compatible GeometryWorld. All rect math lives here —
|
||||
* public.ts delegates to this module so that coordinate arithmetic is
|
||||
* isolated from the FOL compilation path.
|
||||
*/
|
||||
|
||||
import type { GeometryWorld } from 'imhotep-solver'
|
||||
|
||||
export interface ExtractedElement {
|
||||
tagName: string
|
||||
rect: { x: number; y: number; width: number; height: number }
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a GeometryWorld from a flat list of extracted elements.
|
||||
*
|
||||
* Each element receives a sequential subject ID starting at 1.
|
||||
* Boxes, rects, and subject tables are populated from the visual rects.
|
||||
*/
|
||||
export function buildGeometryWorld(elements: ExtractedElement[]): GeometryWorld {
|
||||
const ids: number[] = []
|
||||
const borderLeft: number[] = []
|
||||
const borderTop: number[] = []
|
||||
const borderRight: number[] = []
|
||||
const borderBottom: number[] = []
|
||||
const paddingLeft: number[] = []
|
||||
const paddingTop: number[] = []
|
||||
const paddingRight: number[] = []
|
||||
const paddingBottom: number[] = []
|
||||
const contentLeft: number[] = []
|
||||
const contentTop: number[] = []
|
||||
const contentRight: number[] = []
|
||||
const contentBottom: number[] = []
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const id = i + 1
|
||||
const el = elements[i]
|
||||
const r = el.rect
|
||||
|
||||
ids.push(id)
|
||||
borderLeft.push(r.x)
|
||||
borderTop.push(r.y)
|
||||
borderRight.push(r.x + r.width)
|
||||
borderBottom.push(r.y + r.height)
|
||||
paddingLeft.push(0)
|
||||
paddingTop.push(0)
|
||||
paddingRight.push(0)
|
||||
paddingBottom.push(0)
|
||||
contentLeft.push(r.x)
|
||||
contentTop.push(r.y)
|
||||
contentRight.push(r.x + r.width)
|
||||
contentBottom.push(r.y + r.height)
|
||||
}
|
||||
|
||||
return {
|
||||
sceneId: 'scene',
|
||||
snapshotId: 'snapshot',
|
||||
env: {
|
||||
viewportWidth: 800,
|
||||
viewportHeight: 600,
|
||||
deviceScaleFactor: 1,
|
||||
colorScheme: 'light',
|
||||
pointer: 'fine',
|
||||
hover: false,
|
||||
reducedMotion: false,
|
||||
locale: 'en',
|
||||
writingMode: 'horizontal-tb',
|
||||
},
|
||||
strings: { values: [] },
|
||||
subjects: {
|
||||
ids,
|
||||
domNodeId: [...ids],
|
||||
subjectKind: ids.map(() => 0),
|
||||
primaryBoxId: [...ids],
|
||||
firstFragmentId: ids.map(() => 0),
|
||||
fragmentCount: ids.map(() => 0),
|
||||
},
|
||||
dom: {
|
||||
nodeId: [],
|
||||
parentNodeId: [],
|
||||
childCount: [],
|
||||
tagNameStringId: [],
|
||||
},
|
||||
boxes: {
|
||||
boxId: [...ids],
|
||||
subjectId: [...ids],
|
||||
frameId: ids.map(() => 0),
|
||||
borderLeft,
|
||||
borderTop,
|
||||
borderRight,
|
||||
borderBottom,
|
||||
paddingLeft,
|
||||
paddingTop,
|
||||
paddingRight,
|
||||
paddingBottom,
|
||||
contentLeft,
|
||||
contentTop,
|
||||
contentRight,
|
||||
contentBottom,
|
||||
},
|
||||
visualBoxes: {
|
||||
boxId: [...ids],
|
||||
subjectId: [...ids],
|
||||
frameId: ids.map(() => 0),
|
||||
borderLeft: [...borderLeft],
|
||||
borderTop: [...borderTop],
|
||||
borderRight: [...borderRight],
|
||||
borderBottom: [...borderBottom],
|
||||
paddingLeft: [...paddingLeft],
|
||||
paddingTop: [...paddingTop],
|
||||
paddingRight: [...paddingRight],
|
||||
paddingBottom: [...paddingBottom],
|
||||
contentLeft: [...contentLeft],
|
||||
contentTop: [...contentTop],
|
||||
contentRight: [...contentRight],
|
||||
contentBottom: [...contentBottom],
|
||||
},
|
||||
transforms: {
|
||||
transformId: [],
|
||||
subjectId: [],
|
||||
matrixStart: [],
|
||||
matrixLength: [],
|
||||
originX: [],
|
||||
originY: [],
|
||||
},
|
||||
matrices: {
|
||||
values: [],
|
||||
},
|
||||
rects: {
|
||||
rectId: [...ids],
|
||||
left: [...borderLeft],
|
||||
top: [...borderTop],
|
||||
right: [...borderRight],
|
||||
bottom: [...borderBottom],
|
||||
},
|
||||
topology: {
|
||||
containingBlockOf: [],
|
||||
nearestPositionedAncestorOf: [],
|
||||
scrollContainerOf: [],
|
||||
stackingContextOf: [],
|
||||
formattingContextOf: [],
|
||||
clippingRootOf: [],
|
||||
paintOrderBucket: [],
|
||||
paintOrderIndex: [],
|
||||
},
|
||||
scroll: {
|
||||
containerId: [],
|
||||
scrollLeft: [],
|
||||
scrollTop: [],
|
||||
scrollWidth: [],
|
||||
scrollHeight: [],
|
||||
clientWidth: [],
|
||||
clientHeight: [],
|
||||
},
|
||||
clipping: {
|
||||
clipNodeId: [],
|
||||
subjectId: [],
|
||||
clipKind: [],
|
||||
clipLeft: [],
|
||||
clipTop: [],
|
||||
clipRight: [],
|
||||
clipBottom: [],
|
||||
parentClipNodeId: [],
|
||||
},
|
||||
visibility: {
|
||||
subjectId: [],
|
||||
isRendered: [],
|
||||
isVisible: [],
|
||||
visibleArea: [],
|
||||
clippedArea: [],
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user