tux-review 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/tux-review.js +37 -23
- package/package.json +1 -1
package/client/tux-review.js
CHANGED
|
@@ -131,14 +131,6 @@
|
|
|
131
131
|
}
|
|
132
132
|
function locate(target) {
|
|
133
133
|
if (!target) return null;
|
|
134
|
-
if (target.tux_id) {
|
|
135
|
-
const el = document.querySelector(`[data-tux-id="${cssEscape(target.tux_id)}"]`);
|
|
136
|
-
if (el) return el;
|
|
137
|
-
}
|
|
138
|
-
if (target.test_id) {
|
|
139
|
-
const el = document.querySelector(`[data-testid="${cssEscape(target.test_id)}"], [data-test-id="${cssEscape(target.test_id)}"]`);
|
|
140
|
-
if (el) return el;
|
|
141
|
-
}
|
|
142
134
|
// Fingerprint validation: when a resolution strategy yields several
|
|
143
135
|
// candidates (nth-child paths drift after DOM changes), pick the one
|
|
144
136
|
// that best matches the stored fingerprint — component/instance scope,
|
|
@@ -163,23 +155,45 @@
|
|
|
163
155
|
}
|
|
164
156
|
return best;
|
|
165
157
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
158
|
+
function resolveByPath() {
|
|
159
|
+
if (target.css_selector) {
|
|
160
|
+
try {
|
|
161
|
+
const nodes = document.querySelectorAll(target.css_selector);
|
|
162
|
+
if (nodes.length) return pickBest(nodes);
|
|
163
|
+
} catch (e) { /* invalid selector */ }
|
|
164
|
+
}
|
|
165
|
+
if (target.dom_path) {
|
|
166
|
+
try {
|
|
167
|
+
const snapshot = document.evaluate(target.dom_path, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
168
|
+
if (snapshot.snapshotLength) {
|
|
169
|
+
const nodes = [];
|
|
170
|
+
for (let i = 0; i < snapshot.snapshotLength; i++) nodes.push(snapshot.snapshotItem(i));
|
|
171
|
+
return pickBest(nodes);
|
|
172
|
+
}
|
|
173
|
+
} catch (e) { /* invalid path */ }
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
171
176
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
|
|
178
|
+
const byTest = target.test_id
|
|
179
|
+
? document.querySelector(`[data-testid="${cssEscape(target.test_id)}"], [data-test-id="${cssEscape(target.test_id)}"]`)
|
|
180
|
+
: null;
|
|
181
|
+
if (byTest) return byTest; // explicit test hook: exact element (SPC 16)
|
|
182
|
+
|
|
183
|
+
const byPath = resolveByPath();
|
|
184
|
+
const byId = target.tux_id
|
|
185
|
+
? document.querySelector(`[data-tux-id="${cssEscape(target.tux_id)}"]`)
|
|
186
|
+
: null;
|
|
187
|
+
|
|
188
|
+
// A tux_id on a CONTAINER must not coarsen the target: when the path
|
|
189
|
+
// resolves to an element inside the id element, the path is the finer,
|
|
190
|
+
// correct target. Only trust the id over a path that drifted outside
|
|
191
|
+
// of it (SPC 16: multiple independent signals, finest wins).
|
|
192
|
+
if (byId) {
|
|
193
|
+
if (byPath && (byId === byPath || byId.contains(byPath))) return byPath;
|
|
194
|
+
return byId;
|
|
181
195
|
}
|
|
182
|
-
return
|
|
196
|
+
return byPath;
|
|
183
197
|
}
|
|
184
198
|
|
|
185
199
|
// ─── route + state tracking (SPC 13–15, 59) ───
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tux-review",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "TUX - TUX UIX review system: attach structured, machine-readable feedback directly to running web UIs (pages, routes, components, elements, states) with a deterministic CLI, canonical JSON and LLM-friendly skills.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|