@spotpatch/runtime 1.4.0 → 1.5.0
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/README.md +3 -7
- package/dist/index.cjs +599 -373
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +597 -371
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -10,45 +10,46 @@ import {
|
|
|
10
10
|
MAX_ANNOTATION_TARGETS,
|
|
11
11
|
MAX_TARGET_INSTRUCTION_CHARACTERS
|
|
12
12
|
} from "@spotpatch/shared";
|
|
13
|
-
function freezeSource(
|
|
13
|
+
function freezeSource(source2, code2) {
|
|
14
14
|
return Object.freeze({
|
|
15
|
-
...
|
|
16
|
-
...
|
|
15
|
+
...source2,
|
|
16
|
+
...source2.relativePath === void 0 && code2 !== void 0 ? { relativePath: code2.relativePath } : {}
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
function freezeReact(
|
|
19
|
+
function freezeReact(react2) {
|
|
20
20
|
return Object.freeze({
|
|
21
|
-
...
|
|
22
|
-
componentStack: Object.freeze([...
|
|
23
|
-
...
|
|
21
|
+
...react2,
|
|
22
|
+
componentStack: Object.freeze([...react2.componentStack]),
|
|
23
|
+
...react2.source === void 0 ? {} : { source: freezeSource(react2.source) }
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
-
function freezeElement(
|
|
26
|
+
function freezeElement(element2) {
|
|
27
27
|
return Object.freeze({
|
|
28
|
-
...
|
|
29
|
-
rect: Object.freeze({ ...
|
|
28
|
+
...element2,
|
|
29
|
+
rect: Object.freeze({ ...element2.rect })
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
function freezeStyles(
|
|
32
|
+
function freezeStyles(styles2) {
|
|
33
33
|
return Object.freeze({
|
|
34
|
-
...
|
|
35
|
-
classNames: Object.freeze([...
|
|
34
|
+
...styles2,
|
|
35
|
+
classNames: Object.freeze([...styles2.classNames]),
|
|
36
36
|
matchedRules: Object.freeze(
|
|
37
|
-
|
|
37
|
+
styles2.matchedRules.map((rule) => Object.freeze({ ...rule }))
|
|
38
38
|
),
|
|
39
|
-
computed: Object.freeze({ ...
|
|
40
|
-
warnings: Object.freeze([...
|
|
39
|
+
computed: Object.freeze({ ...styles2.computed }),
|
|
40
|
+
warnings: Object.freeze([...styles2.warnings])
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
function freezeTarget(
|
|
43
|
+
function freezeTarget(target2) {
|
|
44
44
|
return Object.freeze({
|
|
45
|
-
instruction:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
instruction: target2.instruction.trim(),
|
|
46
|
+
...target2.page === void 0 ? {} : { page: Object.freeze({ ...target2.page }) },
|
|
47
|
+
source: freezeSource(target2.source, target2.code),
|
|
48
|
+
react: freezeReact(target2.react),
|
|
49
|
+
element: freezeElement(target2.element),
|
|
50
|
+
styles: freezeStyles(target2.styles),
|
|
51
|
+
...target2.code === void 0 ? {} : { code: Object.freeze({ ...target2.code }) },
|
|
52
|
+
warnings: Object.freeze([...target2.warnings])
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
55
|
function createAnnotation(input) {
|
|
@@ -57,7 +58,7 @@ function createAnnotation(input) {
|
|
|
57
58
|
`SpotPatch annotations require between 1 and ${String(MAX_ANNOTATION_TARGETS)} targets.`
|
|
58
59
|
);
|
|
59
60
|
}
|
|
60
|
-
const instructions = input.targets.map((
|
|
61
|
+
const instructions = input.targets.map((target2) => target2.instruction.trim());
|
|
61
62
|
if (instructions.some(
|
|
62
63
|
(instruction) => instruction.length === 0 || instruction.length > MAX_TARGET_INSTRUCTION_CHARACTERS
|
|
63
64
|
) || instructions.reduce((total, instruction) => total + instruction.length, 0) > MAX_ANNOTATION_INSTRUCTION_CHARACTERS) {
|
|
@@ -254,10 +255,10 @@ var MAX_EVENT_LINE_BYTES = 1e5;
|
|
|
254
255
|
var MAX_EVENT_STREAM_BYTES = 4e6;
|
|
255
256
|
var RuntimeApiError = class extends Error {
|
|
256
257
|
code;
|
|
257
|
-
constructor(
|
|
258
|
+
constructor(code2) {
|
|
258
259
|
super("SpotPatch local API request failed.");
|
|
259
260
|
this.name = "RuntimeApiError";
|
|
260
|
-
this.code =
|
|
261
|
+
this.code = code2;
|
|
261
262
|
}
|
|
262
263
|
};
|
|
263
264
|
function isRecord2(value) {
|
|
@@ -329,9 +330,9 @@ async function readBoundedText(response, maximumBytes) {
|
|
|
329
330
|
reader.releaseLock();
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
|
-
function parseJson(
|
|
333
|
+
function parseJson(text2) {
|
|
333
334
|
try {
|
|
334
|
-
return JSON.parse(
|
|
335
|
+
return JSON.parse(text2);
|
|
335
336
|
} catch {
|
|
336
337
|
throw new RuntimeApiError();
|
|
337
338
|
}
|
|
@@ -374,13 +375,13 @@ function omitBrowserCodeContext(request) {
|
|
|
374
375
|
...request,
|
|
375
376
|
annotation: {
|
|
376
377
|
...request.annotation,
|
|
377
|
-
targets: request.annotation.targets.map((
|
|
378
|
-
instruction:
|
|
379
|
-
source:
|
|
380
|
-
react:
|
|
381
|
-
element:
|
|
382
|
-
styles:
|
|
383
|
-
warnings:
|
|
378
|
+
targets: request.annotation.targets.map((target2) => ({
|
|
379
|
+
instruction: target2.instruction,
|
|
380
|
+
source: target2.source,
|
|
381
|
+
react: target2.react,
|
|
382
|
+
element: target2.element,
|
|
383
|
+
styles: target2.styles,
|
|
384
|
+
warnings: target2.warnings
|
|
384
385
|
}))
|
|
385
386
|
}
|
|
386
387
|
};
|
|
@@ -671,12 +672,12 @@ function contextCharacterCount(classNames, inlineStyle, rules, computed, warning
|
|
|
671
672
|
function stylesheetSource(sheet, baseUrl) {
|
|
672
673
|
return sheet.href === null ? void 0 : sanitizeUrl(sheet.href, baseUrl);
|
|
673
674
|
}
|
|
674
|
-
function collectMatchedRules(
|
|
675
|
+
function collectMatchedRules(element2, rules, source2, inheritedConditions, output, warnings) {
|
|
675
676
|
for (const rule of rules) {
|
|
676
677
|
if (isStyleRule(rule)) {
|
|
677
678
|
let matches = false;
|
|
678
679
|
try {
|
|
679
|
-
matches =
|
|
680
|
+
matches = element2.matches(rule.selectorText);
|
|
680
681
|
} catch {
|
|
681
682
|
warnings.add(CSS_COLLECTION_WARNINGS.selector);
|
|
682
683
|
continue;
|
|
@@ -686,7 +687,7 @@ function collectMatchedRules(element, rules, source, inheritedConditions, output
|
|
|
686
687
|
Object.freeze({
|
|
687
688
|
selector: sanitizeCssText(rule.selectorText),
|
|
688
689
|
declarations: sanitizeCssText(rule.style.cssText),
|
|
689
|
-
...
|
|
690
|
+
...source2 === void 0 ? {} : { source: source2 },
|
|
690
691
|
...inheritedConditions.length === 0 ? {} : { media: inheritedConditions.join(" and ") }
|
|
691
692
|
})
|
|
692
693
|
);
|
|
@@ -696,9 +697,9 @@ function collectMatchedRules(element, rules, source, inheritedConditions, output
|
|
|
696
697
|
if (isGroupingRule(rule)) {
|
|
697
698
|
const condition = groupingCondition(rule);
|
|
698
699
|
collectMatchedRules(
|
|
699
|
-
|
|
700
|
+
element2,
|
|
700
701
|
rule.cssRules,
|
|
701
|
-
|
|
702
|
+
source2,
|
|
702
703
|
condition === void 0 ? inheritedConditions : [...inheritedConditions, condition],
|
|
703
704
|
output,
|
|
704
705
|
warnings
|
|
@@ -706,11 +707,11 @@ function collectMatchedRules(element, rules, source, inheritedConditions, output
|
|
|
706
707
|
}
|
|
707
708
|
}
|
|
708
709
|
}
|
|
709
|
-
function collectComputedStyle(
|
|
710
|
+
function collectComputedStyle(element2, getComputedStyle) {
|
|
710
711
|
if (getComputedStyle === void 0) {
|
|
711
712
|
return {};
|
|
712
713
|
}
|
|
713
|
-
const declaration = getComputedStyle(
|
|
714
|
+
const declaration = getComputedStyle(element2);
|
|
714
715
|
const computed = {};
|
|
715
716
|
for (const property of COMPUTED_STYLE_PROPERTIES) {
|
|
716
717
|
const value = sanitizeCssText(declaration.getPropertyValue(property).trim());
|
|
@@ -848,11 +849,11 @@ function escapeHtml(value) {
|
|
|
848
849
|
function isPreservedAttribute(name) {
|
|
849
850
|
return SAFE_ATTRIBUTE_NAMES.has(name) || name.startsWith("aria-") || name === "data-testid";
|
|
850
851
|
}
|
|
851
|
-
function openingTag(
|
|
852
|
-
const tagName =
|
|
852
|
+
function openingTag(element2) {
|
|
853
|
+
const tagName = element2.tagName.toLowerCase();
|
|
853
854
|
const attributes = [];
|
|
854
|
-
const baseUrl =
|
|
855
|
-
for (const attribute of
|
|
855
|
+
const baseUrl = element2.ownerDocument.baseURI;
|
|
856
|
+
for (const attribute of element2.attributes) {
|
|
856
857
|
const name = attribute.name.toLowerCase();
|
|
857
858
|
if (!isPreservedAttribute(name)) {
|
|
858
859
|
continue;
|
|
@@ -867,28 +868,28 @@ function openingTag(element) {
|
|
|
867
868
|
function normalizedText(value) {
|
|
868
869
|
return redactSensitiveText(value).replaceAll(/\s+/gu, " ").trim();
|
|
869
870
|
}
|
|
870
|
-
function serializeElement(
|
|
871
|
+
function serializeElement(element2, depth, state, lines) {
|
|
871
872
|
if (state.nodeCount >= DOM_COLLECTION_LIMITS.maxNodes) {
|
|
872
873
|
state.truncated = true;
|
|
873
874
|
return;
|
|
874
875
|
}
|
|
875
876
|
state.nodeCount += 1;
|
|
876
877
|
const indent = " ".repeat(depth);
|
|
877
|
-
const tagName =
|
|
878
|
-
lines.push(`${indent}${openingTag(
|
|
878
|
+
const tagName = element2.tagName.toLowerCase();
|
|
879
|
+
lines.push(`${indent}${openingTag(element2)}`);
|
|
879
880
|
if (VOID_ELEMENT_NAMES.has(tagName)) {
|
|
880
881
|
return;
|
|
881
882
|
}
|
|
882
|
-
for (const child of
|
|
883
|
+
for (const child of element2.childNodes) {
|
|
883
884
|
if (state.nodeCount >= DOM_COLLECTION_LIMITS.maxNodes) {
|
|
884
885
|
state.truncated = true;
|
|
885
886
|
break;
|
|
886
887
|
}
|
|
887
888
|
if (child.nodeType === 3) {
|
|
888
|
-
const
|
|
889
|
-
if (
|
|
889
|
+
const text2 = normalizedText(child.textContent ?? "");
|
|
890
|
+
if (text2.length > 0) {
|
|
890
891
|
state.nodeCount += 1;
|
|
891
|
-
const truncated =
|
|
892
|
+
const truncated = text2.length <= DOM_COLLECTION_LIMITS.maxTextCharacters ? text2 : `${text2.slice(0, DOM_COLLECTION_LIMITS.maxTextCharacters)}\u2026`;
|
|
892
893
|
lines.push(`${" ".repeat(depth + 1)}${escapeHtml(truncated)}`);
|
|
893
894
|
}
|
|
894
895
|
continue;
|
|
@@ -907,9 +908,9 @@ function serializeElement(element, depth, state, lines) {
|
|
|
907
908
|
}
|
|
908
909
|
lines.push(`${indent}</${tagName}>`);
|
|
909
910
|
}
|
|
910
|
-
function parentContext(
|
|
911
|
+
function parentContext(element2) {
|
|
911
912
|
const parents = [];
|
|
912
|
-
let parent =
|
|
913
|
+
let parent = element2.parentElement;
|
|
913
914
|
while (parent !== null && parents.length < DOM_COLLECTION_LIMITS.maxParentDepth) {
|
|
914
915
|
parents.push(openingTag(parent));
|
|
915
916
|
parent = parent.parentElement;
|
|
@@ -930,26 +931,26 @@ function escapeCssIdentifier(value) {
|
|
|
930
931
|
function escapeCssAttribute(value) {
|
|
931
932
|
return value.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
|
|
932
933
|
}
|
|
933
|
-
function selectorSegment(
|
|
934
|
-
const tagName =
|
|
935
|
-
if (
|
|
936
|
-
return `${tagName}#${escapeCssIdentifier(
|
|
934
|
+
function selectorSegment(element2) {
|
|
935
|
+
const tagName = element2.tagName.toLowerCase();
|
|
936
|
+
if (element2.id.length > 0) {
|
|
937
|
+
return `${tagName}#${escapeCssIdentifier(element2.id)}`;
|
|
937
938
|
}
|
|
938
|
-
const testId =
|
|
939
|
+
const testId = element2.getAttribute("data-testid");
|
|
939
940
|
if (testId !== null && testId.length > 0) {
|
|
940
941
|
return `${tagName}[data-testid="${escapeCssAttribute(testId)}"]`;
|
|
941
942
|
}
|
|
942
|
-
const classes = Array.from(
|
|
943
|
-
const sameTagSiblings =
|
|
944
|
-
(sibling) => sibling.tagName ===
|
|
943
|
+
const classes = Array.from(element2.classList).slice(0, 2).map((name) => `.${escapeCssIdentifier(name)}`).join("");
|
|
944
|
+
const sameTagSiblings = element2.parentElement === null ? [] : Array.from(element2.parentElement.children).filter(
|
|
945
|
+
(sibling) => sibling.tagName === element2.tagName
|
|
945
946
|
);
|
|
946
|
-
const position = sameTagSiblings.indexOf(
|
|
947
|
+
const position = sameTagSiblings.indexOf(element2);
|
|
947
948
|
const nth = sameTagSiblings.length > 1 && position >= 0 ? `:nth-of-type(${String(position + 1)})` : "";
|
|
948
949
|
return `${tagName}${classes}${nth}`;
|
|
949
950
|
}
|
|
950
|
-
function createSelector(
|
|
951
|
+
function createSelector(element2) {
|
|
951
952
|
const segments = [];
|
|
952
|
-
let current =
|
|
953
|
+
let current = element2;
|
|
953
954
|
while (current !== null && segments.length < 5) {
|
|
954
955
|
const segment = selectorSegment(current);
|
|
955
956
|
segments.unshift(segment);
|
|
@@ -968,15 +969,15 @@ function collectElementContext(options) {
|
|
|
968
969
|
if (parents.length > 0) {
|
|
969
970
|
lines.push("<!-- Parent context: nearest first -->", ...parents);
|
|
970
971
|
}
|
|
971
|
-
const
|
|
972
|
+
const text2 = normalizedText(options.element.textContent);
|
|
972
973
|
const rect = options.element.getBoundingClientRect();
|
|
973
974
|
const role = options.element.getAttribute("role");
|
|
974
975
|
return Object.freeze({
|
|
975
976
|
tagName: options.element.tagName.toLowerCase(),
|
|
976
977
|
selector: createSelector(options.element),
|
|
977
978
|
sanitizedHtml: truncateContext(lines.join("\n"), options.maxCharacters),
|
|
978
|
-
...
|
|
979
|
-
textPreview:
|
|
979
|
+
...text2.length === 0 ? {} : {
|
|
980
|
+
textPreview: text2.length <= DOM_COLLECTION_LIMITS.maxTextCharacters ? text2 : `${text2.slice(0, DOM_COLLECTION_LIMITS.maxTextCharacters)}\u2026`
|
|
980
981
|
},
|
|
981
982
|
...role === null ? {} : { role },
|
|
982
983
|
rect: Object.freeze({
|
|
@@ -995,11 +996,11 @@ function isApplePlatform(platform) {
|
|
|
995
996
|
function normalizedKey(key) {
|
|
996
997
|
return key.toLowerCase();
|
|
997
998
|
}
|
|
998
|
-
function isTextEntryTarget(
|
|
999
|
-
if (!(
|
|
999
|
+
function isTextEntryTarget(target2) {
|
|
1000
|
+
if (!(target2 instanceof Element)) {
|
|
1000
1001
|
return false;
|
|
1001
1002
|
}
|
|
1002
|
-
return
|
|
1003
|
+
return target2 instanceof HTMLInputElement || target2 instanceof HTMLTextAreaElement || target2 instanceof HTMLSelectElement || target2.closest("[contenteditable]:not([contenteditable='false'])") !== null;
|
|
1003
1004
|
}
|
|
1004
1005
|
function matchesShortcut(event, shortcut, platform) {
|
|
1005
1006
|
const tokens = shortcut.split("+").map((token) => token.trim().toLowerCase()).filter((token) => token.length > 0);
|
|
@@ -1049,15 +1050,15 @@ function unionRects(rects) {
|
|
|
1049
1050
|
height: bottom - top
|
|
1050
1051
|
});
|
|
1051
1052
|
}
|
|
1052
|
-
function getElementRect(
|
|
1053
|
-
const display = view.getComputedStyle(
|
|
1053
|
+
function getElementRect(element2, view) {
|
|
1054
|
+
const display = view.getComputedStyle(element2).display;
|
|
1054
1055
|
if (display.startsWith("inline")) {
|
|
1055
|
-
const lineBoxRect = unionRects(Array.from(
|
|
1056
|
+
const lineBoxRect = unionRects(Array.from(element2.getClientRects()));
|
|
1056
1057
|
if (lineBoxRect !== void 0) {
|
|
1057
1058
|
return lineBoxRect;
|
|
1058
1059
|
}
|
|
1059
1060
|
}
|
|
1060
|
-
return toElementRect(
|
|
1061
|
+
return toElementRect(element2.getBoundingClientRect());
|
|
1061
1062
|
}
|
|
1062
1063
|
|
|
1063
1064
|
// src/ui/ui-constants.ts
|
|
@@ -1068,32 +1069,32 @@ var UI_Z_INDEX = Object.freeze({
|
|
|
1068
1069
|
});
|
|
1069
1070
|
|
|
1070
1071
|
// src/picker/hit-test.ts
|
|
1071
|
-
function isInsideSpotPatchUI(
|
|
1072
|
-
if (
|
|
1072
|
+
function isInsideSpotPatchUI(element2) {
|
|
1073
|
+
if (element2.closest(`[${UI_MARKER_ATTRIBUTE}]`) !== null) {
|
|
1073
1074
|
return true;
|
|
1074
1075
|
}
|
|
1075
|
-
const root =
|
|
1076
|
+
const root = element2.getRootNode();
|
|
1076
1077
|
return root instanceof ShadowRoot && root.host.hasAttribute(UI_MARKER_ATTRIBUTE);
|
|
1077
1078
|
}
|
|
1078
|
-
function hasVisibleArea(
|
|
1079
|
-
const style = view.getComputedStyle(
|
|
1079
|
+
function hasVisibleArea(element2, view) {
|
|
1080
|
+
const style = view.getComputedStyle(element2);
|
|
1080
1081
|
if (style.display === "none" || style.visibility === "hidden") {
|
|
1081
1082
|
return false;
|
|
1082
1083
|
}
|
|
1083
|
-
const rect =
|
|
1084
|
+
const rect = element2.getBoundingClientRect();
|
|
1084
1085
|
return rect.width > 0 && rect.height > 0;
|
|
1085
1086
|
}
|
|
1086
|
-
function isDocumentRoot(
|
|
1087
|
-
return
|
|
1087
|
+
function isDocumentRoot(element2) {
|
|
1088
|
+
return element2.tagName === "HTML" || element2.tagName === "BODY";
|
|
1088
1089
|
}
|
|
1089
1090
|
function pickElementAt(document, view, clientX, clientY) {
|
|
1090
1091
|
const visibleCandidates = document.elementsFromPoint(clientX, clientY).filter(
|
|
1091
|
-
(
|
|
1092
|
+
(element2) => !isInsideSpotPatchUI(element2) && hasVisibleArea(element2, view)
|
|
1092
1093
|
);
|
|
1093
|
-
return visibleCandidates.find((
|
|
1094
|
+
return visibleCandidates.find((element2) => !isDocumentRoot(element2)) ?? visibleCandidates[0];
|
|
1094
1095
|
}
|
|
1095
|
-
function isSpotPatchUIEventTarget(
|
|
1096
|
-
return
|
|
1096
|
+
function isSpotPatchUIEventTarget(target2) {
|
|
1097
|
+
return target2 instanceof Element && isInsideSpotPatchUI(target2);
|
|
1097
1098
|
}
|
|
1098
1099
|
|
|
1099
1100
|
// src/prompt/prompt-composer.ts
|
|
@@ -1172,10 +1173,10 @@ function fenced(language, value) {
|
|
|
1172
1173
|
${value}
|
|
1173
1174
|
${fence}`;
|
|
1174
1175
|
}
|
|
1175
|
-
function sourceLocation(
|
|
1176
|
-
const path =
|
|
1177
|
-
const line =
|
|
1178
|
-
const column =
|
|
1176
|
+
function sourceLocation(target2, messages) {
|
|
1177
|
+
const path = target2.code?.relativePath ?? target2.source.relativePath;
|
|
1178
|
+
const line = target2.source.line;
|
|
1179
|
+
const column = target2.source.column;
|
|
1179
1180
|
if (path === void 0) {
|
|
1180
1181
|
return messages.unavailable;
|
|
1181
1182
|
}
|
|
@@ -1194,10 +1195,10 @@ function renderRule(rule) {
|
|
|
1194
1195
|
}`;
|
|
1195
1196
|
return [...metadata, body].join("\n");
|
|
1196
1197
|
}
|
|
1197
|
-
function renderStyles(
|
|
1198
|
+
function renderStyles(target2, rules, messages) {
|
|
1198
1199
|
const metadata = [
|
|
1199
|
-
|
|
1200
|
-
|
|
1200
|
+
target2.styles.classNames.length === 0 ? void 0 : `/* classes: ${target2.styles.classNames.map(sanitizeCssText).join(" ")} */`,
|
|
1201
|
+
target2.styles.inlineStyle === void 0 ? void 0 : `/* inline: ${sanitizeCssText(target2.styles.inlineStyle)} */`
|
|
1201
1202
|
].filter((line) => line !== void 0);
|
|
1202
1203
|
const blocks = [...metadata, ...rules.map(renderRule)];
|
|
1203
1204
|
return blocks.length === 0 ? messages.unavailable : fenced("css", blocks.join("\n\n"));
|
|
@@ -1210,41 +1211,47 @@ function renderComputed(entries, messages) {
|
|
|
1210
1211
|
).join("\n")
|
|
1211
1212
|
);
|
|
1212
1213
|
}
|
|
1213
|
-
function renderTarget(
|
|
1214
|
+
function renderTarget(target2, draft, index, messages) {
|
|
1214
1215
|
const reactLines = [
|
|
1215
|
-
`- ${messages.adapter}: ${
|
|
1216
|
-
...
|
|
1217
|
-
...
|
|
1218
|
-
`- ${messages.component}: ${redactSensitiveText(
|
|
1216
|
+
`- ${messages.adapter}: ${target2.react.supported ? messages.supported : messages.unsupported}`,
|
|
1217
|
+
...target2.react.version === void 0 ? [] : [`- ${messages.reactVersion}: ${redactSensitiveText(target2.react.version)}`],
|
|
1218
|
+
...target2.react.componentName === void 0 ? [] : [
|
|
1219
|
+
`- ${messages.component}: ${redactSensitiveText(target2.react.componentName)}`
|
|
1219
1220
|
],
|
|
1220
1221
|
...draft.reactStack.length === 0 ? [] : [
|
|
1221
1222
|
`- ${messages.stack}: ${draft.reactStack.map(redactSensitiveText).join(" > ")}`
|
|
1222
1223
|
]
|
|
1223
1224
|
];
|
|
1224
|
-
const
|
|
1225
|
+
const code2 = target2.code === void 0 || draft.codeLines.length === 0 ? messages.unavailable : `- ${messages.boundary}: ${target2.code.boundary}
|
|
1225
1226
|
|
|
1226
1227
|
${fenced(
|
|
1227
|
-
|
|
1228
|
+
target2.code.language,
|
|
1228
1229
|
redactSensitiveText(draft.codeLines.join("\n"))
|
|
1229
1230
|
)}`;
|
|
1230
1231
|
return [
|
|
1231
1232
|
`### ${messages.target(index + 1)}`,
|
|
1232
1233
|
`#### ${messages.requestedChange}`,
|
|
1233
1234
|
draft.instruction,
|
|
1235
|
+
...target2.page === void 0 ? [] : [
|
|
1236
|
+
`#### ${messages.pageEnvironment}`,
|
|
1237
|
+
`- ${messages.url}: <${sanitizeUrl(target2.page.url, target2.page.url)}>
|
|
1238
|
+
- ${messages.pathname}: ${redactSensitiveText(target2.page.pathname)}
|
|
1239
|
+
- ${messages.title}: ${redactSensitiveText(target2.page.title) || messages.unavailable}`
|
|
1240
|
+
],
|
|
1234
1241
|
`#### ${messages.reactContext}`,
|
|
1235
1242
|
reactLines.join("\n"),
|
|
1236
1243
|
`#### ${messages.source}`,
|
|
1237
|
-
`- ${messages.file}: ${sourceLocation(
|
|
1238
|
-
- ${messages.origin}: ${
|
|
1239
|
-
- ${messages.confidence}: ${
|
|
1244
|
+
`- ${messages.file}: ${sourceLocation(target2, messages)}
|
|
1245
|
+
- ${messages.origin}: ${target2.source.origin}
|
|
1246
|
+
- ${messages.confidence}: ${target2.source.confidence}`,
|
|
1240
1247
|
`#### ${messages.element}`,
|
|
1241
1248
|
fenced("html", redactSensitiveText(draft.dom)),
|
|
1242
1249
|
`#### ${messages.styles}`,
|
|
1243
|
-
renderStyles(
|
|
1250
|
+
renderStyles(target2, draft.matchedRules, messages),
|
|
1244
1251
|
`#### ${messages.computedStyles}`,
|
|
1245
1252
|
renderComputed(draft.computedEntries, messages),
|
|
1246
1253
|
`#### ${messages.code}`,
|
|
1247
|
-
|
|
1254
|
+
code2,
|
|
1248
1255
|
`#### ${messages.warnings}`,
|
|
1249
1256
|
draft.warnings.length === 0 ? `- ${messages.none}` : draft.warnings.map((warning) => `- ${redactSensitiveText(warning)}`).join("\n")
|
|
1250
1257
|
].join("\n\n");
|
|
@@ -1260,19 +1267,19 @@ function renderPrompt(annotation, draft) {
|
|
|
1260
1267
|
- ${messages.viewport}: ${String(annotation.page.viewportWidth)} \xD7 ${String(annotation.page.viewportHeight)}
|
|
1261
1268
|
- ${messages.devicePixelRatio}: ${String(annotation.page.devicePixelRatio)}`,
|
|
1262
1269
|
`## ${messages.selectedTargets(annotation.targets.length)}`,
|
|
1263
|
-
annotation.targets.map((
|
|
1270
|
+
annotation.targets.map((target2, index) => {
|
|
1264
1271
|
const targetDraft = draft.targets[index];
|
|
1265
1272
|
if (targetDraft === void 0) {
|
|
1266
1273
|
throw new RangeError("Prompt target draft is missing.");
|
|
1267
1274
|
}
|
|
1268
|
-
return renderTarget(
|
|
1275
|
+
return renderTarget(target2, targetDraft, index, messages);
|
|
1269
1276
|
}).join("\n\n"),
|
|
1270
1277
|
`## ${messages.modificationRequirements}`,
|
|
1271
1278
|
messages.modificationConstraint
|
|
1272
1279
|
].join("\n\n");
|
|
1273
1280
|
}
|
|
1274
|
-
function shrinkCode(
|
|
1275
|
-
if (draft.codeLines.length === 0 ||
|
|
1281
|
+
function shrinkCode(target2, draft) {
|
|
1282
|
+
if (draft.codeLines.length === 0 || target2.code === void 0) {
|
|
1276
1283
|
return false;
|
|
1277
1284
|
}
|
|
1278
1285
|
if (draft.codeLines.length === 1) {
|
|
@@ -1284,9 +1291,9 @@ function shrinkCode(target, draft) {
|
|
|
1284
1291
|
}
|
|
1285
1292
|
return true;
|
|
1286
1293
|
}
|
|
1287
|
-
const selectedLine =
|
|
1288
|
-
const firstDistance = Math.abs(
|
|
1289
|
-
const lastLine =
|
|
1294
|
+
const selectedLine = target2.source.line ?? target2.code.startLine;
|
|
1295
|
+
const firstDistance = Math.abs(target2.code.startLine - selectedLine);
|
|
1296
|
+
const lastLine = target2.code.startLine + draft.codeLines.length - 1;
|
|
1290
1297
|
const lastDistance = Math.abs(lastLine - selectedLine);
|
|
1291
1298
|
if (lastDistance >= firstDistance) {
|
|
1292
1299
|
draft.codeLines.pop();
|
|
@@ -1295,15 +1302,15 @@ function shrinkCode(target, draft) {
|
|
|
1295
1302
|
}
|
|
1296
1303
|
return true;
|
|
1297
1304
|
}
|
|
1298
|
-
function createTargetDraft(
|
|
1305
|
+
function createTargetDraft(target2) {
|
|
1299
1306
|
return {
|
|
1300
|
-
instruction: redactSensitiveText(
|
|
1301
|
-
reactStack: [...
|
|
1302
|
-
dom:
|
|
1303
|
-
matchedRules: [...
|
|
1304
|
-
computedEntries: Object.entries(
|
|
1305
|
-
codeLines:
|
|
1306
|
-
warnings: Array.from(/* @__PURE__ */ new Set([...
|
|
1307
|
+
instruction: redactSensitiveText(target2.instruction.trim()),
|
|
1308
|
+
reactStack: [...target2.react.componentStack],
|
|
1309
|
+
dom: target2.element.sanitizedHtml,
|
|
1310
|
+
matchedRules: [...target2.styles.matchedRules],
|
|
1311
|
+
computedEntries: Object.entries(target2.styles.computed),
|
|
1312
|
+
codeLines: target2.code?.excerpt.split(/\r?\n/u) ?? [],
|
|
1313
|
+
warnings: Array.from(/* @__PURE__ */ new Set([...target2.styles.warnings, ...target2.warnings]))
|
|
1307
1314
|
};
|
|
1308
1315
|
}
|
|
1309
1316
|
function createDraft(annotation) {
|
|
@@ -1332,9 +1339,9 @@ function shrinkTargetsFairly(annotation, draft, cursor) {
|
|
|
1332
1339
|
for (const operation of operations) {
|
|
1333
1340
|
for (let offset = 0; offset < annotation.targets.length; offset += 1) {
|
|
1334
1341
|
const index = (cursor + offset) % annotation.targets.length;
|
|
1335
|
-
const
|
|
1342
|
+
const target2 = annotation.targets[index];
|
|
1336
1343
|
const targetDraft = draft.targets[index];
|
|
1337
|
-
if (
|
|
1344
|
+
if (target2 !== void 0 && targetDraft !== void 0 && operation(target2, targetDraft)) {
|
|
1338
1345
|
return (index + 1) % annotation.targets.length;
|
|
1339
1346
|
}
|
|
1340
1347
|
}
|
|
@@ -1343,15 +1350,15 @@ function shrinkTargetsFairly(annotation, draft, cursor) {
|
|
|
1343
1350
|
}
|
|
1344
1351
|
function renderCompactPrompt(annotation, draft) {
|
|
1345
1352
|
const messages = PROMPT_MESSAGES[annotation.locale];
|
|
1346
|
-
const targets = annotation.targets.map((
|
|
1353
|
+
const targets = annotation.targets.map((target2, index) => {
|
|
1347
1354
|
const targetDraft = draft.targets[index];
|
|
1348
|
-
const component =
|
|
1355
|
+
const component = target2.react.componentName;
|
|
1349
1356
|
return [
|
|
1350
1357
|
`### ${messages.target(index + 1)}`,
|
|
1351
|
-
`- ${messages.requestedChange}: ${targetDraft?.instruction ?? redactSensitiveText(
|
|
1352
|
-
`- ${messages.file}: ${sourceLocation(
|
|
1358
|
+
`- ${messages.requestedChange}: ${targetDraft?.instruction ?? redactSensitiveText(target2.instruction)}`,
|
|
1359
|
+
`- ${messages.file}: ${sourceLocation(target2, messages)}`,
|
|
1353
1360
|
...component === void 0 ? [] : [`- ${messages.component}: ${redactSensitiveText(component)}`],
|
|
1354
|
-
`- ${messages.element}: ${redactSensitiveText(openingTag2(targetDraft?.dom ??
|
|
1361
|
+
`- ${messages.element}: ${redactSensitiveText(openingTag2(targetDraft?.dom ?? target2.element.sanitizedHtml, messages.unavailable))}`
|
|
1355
1362
|
].join("\n");
|
|
1356
1363
|
});
|
|
1357
1364
|
return [
|
|
@@ -1409,7 +1416,10 @@ var STATES = Object.freeze({
|
|
|
1409
1416
|
});
|
|
1410
1417
|
var INITIAL_RUNTIME_STATE = STATES.idle;
|
|
1411
1418
|
function reduceIdle(event) {
|
|
1412
|
-
|
|
1419
|
+
if (event.type === "ACTIVATE") {
|
|
1420
|
+
return STATES.inspecting;
|
|
1421
|
+
}
|
|
1422
|
+
return event.type === "RESTORE" ? STATES.selected : STATES.idle;
|
|
1413
1423
|
}
|
|
1414
1424
|
function reduceInspecting(event) {
|
|
1415
1425
|
switch (event.type) {
|
|
@@ -1461,6 +1471,121 @@ function reduceRuntimeState(state, event) {
|
|
|
1461
1471
|
}
|
|
1462
1472
|
}
|
|
1463
1473
|
|
|
1474
|
+
// src/state/selection-session.ts
|
|
1475
|
+
var STORAGE_PREFIX = "spotpatch:selection:";
|
|
1476
|
+
var SNAPSHOT_VERSION = 1;
|
|
1477
|
+
var MAX_SNAPSHOT_CHARACTERS = 1e6;
|
|
1478
|
+
function record(value) {
|
|
1479
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
1480
|
+
}
|
|
1481
|
+
function text(value) {
|
|
1482
|
+
return typeof value === "string";
|
|
1483
|
+
}
|
|
1484
|
+
function optionalText(value) {
|
|
1485
|
+
return value === void 0 || text(value);
|
|
1486
|
+
}
|
|
1487
|
+
function strings(value) {
|
|
1488
|
+
return Array.isArray(value) && value.length <= 256 && value.every(text);
|
|
1489
|
+
}
|
|
1490
|
+
function finiteNumber(value) {
|
|
1491
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
1492
|
+
}
|
|
1493
|
+
function optionalNumber(value) {
|
|
1494
|
+
return value === void 0 || finiteNumber(value);
|
|
1495
|
+
}
|
|
1496
|
+
function source(value) {
|
|
1497
|
+
const item = record(value);
|
|
1498
|
+
return item !== void 0 && text(item.origin) && text(item.confidence) && optionalText(item.fileId) && optionalText(item.relativePath) && optionalNumber(item.line) && optionalNumber(item.column);
|
|
1499
|
+
}
|
|
1500
|
+
function react(value) {
|
|
1501
|
+
const item = record(value);
|
|
1502
|
+
return item !== void 0 && typeof item.supported === "boolean" && optionalText(item.version) && optionalText(item.componentName) && strings(item.componentStack) && (item.source === void 0 || source(item.source));
|
|
1503
|
+
}
|
|
1504
|
+
function page(value) {
|
|
1505
|
+
const item = record(value);
|
|
1506
|
+
return item !== void 0 && text(item.url) && text(item.pathname) && text(item.title) && finiteNumber(item.viewportWidth) && finiteNumber(item.viewportHeight) && finiteNumber(item.devicePixelRatio);
|
|
1507
|
+
}
|
|
1508
|
+
function element(value) {
|
|
1509
|
+
const item = record(value);
|
|
1510
|
+
const rect = record(item?.rect);
|
|
1511
|
+
return item !== void 0 && text(item.tagName) && text(item.selector) && text(item.sanitizedHtml) && optionalText(item.textPreview) && optionalText(item.role) && rect !== void 0 && finiteNumber(rect.x) && finiteNumber(rect.y) && finiteNumber(rect.width) && finiteNumber(rect.height);
|
|
1512
|
+
}
|
|
1513
|
+
function styles(value) {
|
|
1514
|
+
const item = record(value);
|
|
1515
|
+
const computed = record(item?.computed);
|
|
1516
|
+
return item !== void 0 && strings(item.classNames) && optionalText(item.inlineStyle) && Array.isArray(item.matchedRules) && item.matchedRules.length <= 256 && item.matchedRules.every((value2) => {
|
|
1517
|
+
const rule = record(value2);
|
|
1518
|
+
return rule !== void 0 && text(rule.selector) && text(rule.declarations) && optionalText(rule.source) && optionalText(rule.media);
|
|
1519
|
+
}) && computed !== void 0 && Object.values(computed).every(text) && strings(item.warnings);
|
|
1520
|
+
}
|
|
1521
|
+
function code(value) {
|
|
1522
|
+
const item = record(value);
|
|
1523
|
+
return item !== void 0 && text(item.relativePath) && text(item.language) && finiteNumber(item.startLine) && finiteNumber(item.endLine) && text(item.excerpt) && text(item.boundary);
|
|
1524
|
+
}
|
|
1525
|
+
function target(value) {
|
|
1526
|
+
const item = record(value);
|
|
1527
|
+
return item !== void 0 && text(item.id) && text(item.instruction) && page(item.page) && source(item.source) && react(item.react) && element(item.element) && styles(item.styles) && (item.code === void 0 || code(item.code));
|
|
1528
|
+
}
|
|
1529
|
+
function parseSnapshot(value, maximumTargets) {
|
|
1530
|
+
const item = record(value);
|
|
1531
|
+
if (item?.version !== SNAPSHOT_VERSION || typeof item.open !== "boolean" || !Number.isSafeInteger(item.sequence) || Number(item.sequence) < 0 || item.activeTargetId !== void 0 && typeof item.activeTargetId !== "string" || !Array.isArray(item.targets) || item.targets.length === 0 || item.targets.length > maximumTargets || !item.targets.every(target)) {
|
|
1532
|
+
return void 0;
|
|
1533
|
+
}
|
|
1534
|
+
const targets = item.targets;
|
|
1535
|
+
const ids = targets.map(({ id }) => id);
|
|
1536
|
+
if (new Set(ids).size !== ids.length || item.activeTargetId !== void 0 && !ids.includes(item.activeTargetId)) {
|
|
1537
|
+
return void 0;
|
|
1538
|
+
}
|
|
1539
|
+
return {
|
|
1540
|
+
...item.activeTargetId === void 0 ? {} : { activeTargetId: item.activeTargetId },
|
|
1541
|
+
open: item.open,
|
|
1542
|
+
sequence: Number(item.sequence),
|
|
1543
|
+
targets
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
function createSelectionSession(window, sessionId, maximumTargets) {
|
|
1547
|
+
const key = `${STORAGE_PREFIX}${sessionId}`;
|
|
1548
|
+
let storage;
|
|
1549
|
+
try {
|
|
1550
|
+
storage = window.sessionStorage;
|
|
1551
|
+
} catch {
|
|
1552
|
+
storage = void 0;
|
|
1553
|
+
}
|
|
1554
|
+
return Object.freeze({
|
|
1555
|
+
clear() {
|
|
1556
|
+
try {
|
|
1557
|
+
storage?.removeItem(key);
|
|
1558
|
+
} catch {
|
|
1559
|
+
}
|
|
1560
|
+
},
|
|
1561
|
+
load() {
|
|
1562
|
+
let serialized;
|
|
1563
|
+
try {
|
|
1564
|
+
serialized = storage?.getItem(key) ?? null;
|
|
1565
|
+
} catch {
|
|
1566
|
+
return void 0;
|
|
1567
|
+
}
|
|
1568
|
+
if (serialized === null || serialized.length > MAX_SNAPSHOT_CHARACTERS) {
|
|
1569
|
+
return void 0;
|
|
1570
|
+
}
|
|
1571
|
+
try {
|
|
1572
|
+
return parseSnapshot(JSON.parse(serialized), maximumTargets);
|
|
1573
|
+
} catch {
|
|
1574
|
+
return void 0;
|
|
1575
|
+
}
|
|
1576
|
+
},
|
|
1577
|
+
save(snapshot) {
|
|
1578
|
+
try {
|
|
1579
|
+
storage?.setItem(
|
|
1580
|
+
key,
|
|
1581
|
+
JSON.stringify({ version: SNAPSHOT_VERSION, ...snapshot })
|
|
1582
|
+
);
|
|
1583
|
+
} catch {
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1464
1589
|
// src/source/source-resolver.ts
|
|
1465
1590
|
import {
|
|
1466
1591
|
parseSourceMarker,
|
|
@@ -1470,11 +1595,11 @@ var EMPTY_REACT_CONTEXT = Object.freeze({
|
|
|
1470
1595
|
supported: false,
|
|
1471
1596
|
componentStack: Object.freeze([])
|
|
1472
1597
|
});
|
|
1473
|
-
function directMarker(
|
|
1474
|
-
return parseSourceMarker(
|
|
1598
|
+
function directMarker(element2) {
|
|
1599
|
+
return parseSourceMarker(element2.getAttribute(SOURCE_MARKER_ATTRIBUTE));
|
|
1475
1600
|
}
|
|
1476
|
-
function ancestorMarker(
|
|
1477
|
-
let ancestor =
|
|
1601
|
+
function ancestorMarker(element2) {
|
|
1602
|
+
let ancestor = element2.parentElement;
|
|
1478
1603
|
while (ancestor !== null) {
|
|
1479
1604
|
const marker = directMarker(ancestor);
|
|
1480
1605
|
if (marker !== void 0) {
|
|
@@ -1496,21 +1621,21 @@ function markerSource(marker, origin, confidence) {
|
|
|
1496
1621
|
function unknownSource() {
|
|
1497
1622
|
return Object.freeze({ origin: "none", confidence: "unknown" });
|
|
1498
1623
|
}
|
|
1499
|
-
function sourceRefToMarker(
|
|
1500
|
-
return
|
|
1501
|
-
fileId:
|
|
1502
|
-
line:
|
|
1503
|
-
column:
|
|
1624
|
+
function sourceRefToMarker(source2) {
|
|
1625
|
+
return source2.fileId === void 0 || source2.line === void 0 || source2.column === void 0 ? void 0 : Object.freeze({
|
|
1626
|
+
fileId: source2.fileId,
|
|
1627
|
+
line: source2.line,
|
|
1628
|
+
column: source2.column
|
|
1504
1629
|
});
|
|
1505
1630
|
}
|
|
1506
1631
|
function createSourceResolver(options) {
|
|
1507
1632
|
let adapterEnabled = true;
|
|
1508
|
-
function inspectReact(
|
|
1633
|
+
function inspectReact(element2) {
|
|
1509
1634
|
if (!adapterEnabled) {
|
|
1510
1635
|
return EMPTY_REACT_CONTEXT;
|
|
1511
1636
|
}
|
|
1512
1637
|
try {
|
|
1513
|
-
return options.adapter.inspect(
|
|
1638
|
+
return options.adapter.inspect(element2);
|
|
1514
1639
|
} catch {
|
|
1515
1640
|
adapterEnabled = false;
|
|
1516
1641
|
options.onAdapterError?.();
|
|
@@ -1518,26 +1643,26 @@ function createSourceResolver(options) {
|
|
|
1518
1643
|
}
|
|
1519
1644
|
}
|
|
1520
1645
|
return Object.freeze({
|
|
1521
|
-
resolve(
|
|
1522
|
-
const marker = directMarker(
|
|
1523
|
-
const
|
|
1646
|
+
resolve(element2) {
|
|
1647
|
+
const marker = directMarker(element2);
|
|
1648
|
+
const react2 = inspectReact(element2);
|
|
1524
1649
|
if (marker !== void 0) {
|
|
1525
1650
|
return Object.freeze({
|
|
1526
|
-
react,
|
|
1651
|
+
react: react2,
|
|
1527
1652
|
source: markerSource(marker, "jsx-host", "exact")
|
|
1528
1653
|
});
|
|
1529
1654
|
}
|
|
1530
|
-
if (
|
|
1531
|
-
return Object.freeze({ react, source:
|
|
1655
|
+
if (react2.source !== void 0) {
|
|
1656
|
+
return Object.freeze({ react: react2, source: react2.source });
|
|
1532
1657
|
}
|
|
1533
|
-
const nearestAncestor = ancestorMarker(
|
|
1658
|
+
const nearestAncestor = ancestorMarker(element2);
|
|
1534
1659
|
if (nearestAncestor !== void 0) {
|
|
1535
1660
|
return Object.freeze({
|
|
1536
|
-
react,
|
|
1661
|
+
react: react2,
|
|
1537
1662
|
source: markerSource(nearestAncestor, "dom-ancestor", "approximate")
|
|
1538
1663
|
});
|
|
1539
1664
|
}
|
|
1540
|
-
return Object.freeze({ react, source: unknownSource() });
|
|
1665
|
+
return Object.freeze({ react: react2, source: unknownSource() });
|
|
1541
1666
|
},
|
|
1542
1667
|
dispose() {
|
|
1543
1668
|
adapterEnabled = false;
|
|
@@ -1555,9 +1680,9 @@ import {
|
|
|
1555
1680
|
|
|
1556
1681
|
// src/ui/dom.ts
|
|
1557
1682
|
function createMarkedElement(document, tagName) {
|
|
1558
|
-
const
|
|
1559
|
-
|
|
1560
|
-
return
|
|
1683
|
+
const element2 = document.createElement(tagName);
|
|
1684
|
+
element2.setAttribute(UI_MARKER_ATTRIBUTE, "");
|
|
1685
|
+
return element2;
|
|
1561
1686
|
}
|
|
1562
1687
|
function createButton(document, label, className = "") {
|
|
1563
1688
|
const button = createMarkedElement(document, "button");
|
|
@@ -2174,68 +2299,81 @@ function createAgentPanel(document, ai, localizer) {
|
|
|
2174
2299
|
});
|
|
2175
2300
|
}
|
|
2176
2301
|
|
|
2302
|
+
// src/ui/brand-mark-content.ts
|
|
2303
|
+
var BRAND_MARK_CONTENT = `
|
|
2304
|
+
<defs>
|
|
2305
|
+
<linearGradient id="locator-gradient" x1="76" y1="92" x2="436" y2="374" gradientUnits="userSpaceOnUse">
|
|
2306
|
+
<stop offset="0" stop-color="#B61CFF" />
|
|
2307
|
+
<stop offset="0.38" stop-color="#6D35FF" />
|
|
2308
|
+
<stop offset="0.72" stop-color="#168EFF" />
|
|
2309
|
+
<stop offset="1" stop-color="#00D9E9" />
|
|
2310
|
+
</linearGradient>
|
|
2311
|
+
<linearGradient id="left-code-gradient" x1="165" y1="166" x2="236" y2="258" gradientUnits="userSpaceOnUse">
|
|
2312
|
+
<stop stop-color="#A51EFF" />
|
|
2313
|
+
<stop offset="1" stop-color="#653BFF" />
|
|
2314
|
+
</linearGradient>
|
|
2315
|
+
<linearGradient id="right-code-gradient" x1="276" y1="166" x2="347" y2="258" gradientUnits="userSpaceOnUse">
|
|
2316
|
+
<stop stop-color="#158DFF" />
|
|
2317
|
+
<stop offset="1" stop-color="#00D8E9" />
|
|
2318
|
+
</linearGradient>
|
|
2319
|
+
<linearGradient id="bolt-gradient" x1="270" y1="111" x2="252" y2="365" gradientUnits="userSpaceOnUse">
|
|
2320
|
+
<stop stop-color="#6840FF" />
|
|
2321
|
+
<stop offset="0.48" stop-color="#257BFF" />
|
|
2322
|
+
<stop offset="1" stop-color="#00CBEF" />
|
|
2323
|
+
</linearGradient>
|
|
2324
|
+
</defs>
|
|
2325
|
+
<path
|
|
2326
|
+
fill="url(#locator-gradient)"
|
|
2327
|
+
fill-rule="evenodd"
|
|
2328
|
+
clip-rule="evenodd"
|
|
2329
|
+
d="M256 52C345.47 52 418 124.53 418 214C418 267.55 391.98 316.24 354.04 348.02L256 468L157.96 348.02C120.02 316.24 94 267.55 94 214C94 124.53 166.53 52 256 52ZM256 88C186.41 88 130 144.41 130 214C130 258.2 152.76 297.08 187.2 319.57L256 403.8L324.8 319.57C359.24 297.08 382 258.2 382 214C382 144.41 325.59 88 256 88Z"
|
|
2330
|
+
/>
|
|
2331
|
+
<rect x="238" y="20" width="36" height="84" rx="4" fill="url(#locator-gradient)" />
|
|
2332
|
+
<rect x="62" y="196" width="84" height="36" rx="4" fill="url(#locator-gradient)" />
|
|
2333
|
+
<rect x="366" y="196" width="84" height="36" rx="4" fill="url(#locator-gradient)" />
|
|
2334
|
+
<path
|
|
2335
|
+
d="M213.5 160L158 211.5L213.5 263L238 236.5L211 211.5L238 186.5L213.5 160Z"
|
|
2336
|
+
fill="url(#left-code-gradient)"
|
|
2337
|
+
/>
|
|
2338
|
+
<path
|
|
2339
|
+
d="M298.5 160L354 211.5L298.5 263L274 236.5L301 211.5L274 186.5L298.5 160Z"
|
|
2340
|
+
fill="url(#right-code-gradient)"
|
|
2341
|
+
/>
|
|
2342
|
+
<path
|
|
2343
|
+
d="M283 108L232 212L266 253L238 369L302 237L267 198L283 108Z"
|
|
2344
|
+
fill="url(#bolt-gradient)"
|
|
2345
|
+
/>
|
|
2346
|
+
`;
|
|
2347
|
+
|
|
2177
2348
|
// src/ui/brand-mark.ts
|
|
2178
2349
|
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
2350
|
+
function resolveBrandMarkContent(override) {
|
|
2351
|
+
if (override !== void 0) {
|
|
2352
|
+
return { content: override, viewBox: "0 0 512 512" };
|
|
2353
|
+
}
|
|
2354
|
+
const injected = typeof __SPOTPATCH_BRAND_MARK_CONTENT__ === "string" ? __SPOTPATCH_BRAND_MARK_CONTENT__ : void 0;
|
|
2355
|
+
if (typeof injected === "string") {
|
|
2356
|
+
return { content: injected, viewBox: "0 0 512 512" };
|
|
2357
|
+
}
|
|
2358
|
+
return true ? { content: BRAND_MARK_CONTENT, viewBox: "0 0 512 512" } : { content: FALLBACK_BRAND_MARK_CONTENT, viewBox: "0 0 1 1" };
|
|
2359
|
+
}
|
|
2179
2360
|
function svgElement(document, tagName, attributes) {
|
|
2180
|
-
const
|
|
2361
|
+
const element2 = document.createElementNS(SVG_NAMESPACE, tagName);
|
|
2181
2362
|
for (const [name, value] of Object.entries(attributes)) {
|
|
2182
|
-
|
|
2363
|
+
element2.setAttribute(name, value);
|
|
2183
2364
|
}
|
|
2184
|
-
return
|
|
2365
|
+
return element2;
|
|
2185
2366
|
}
|
|
2186
|
-
function createBrandMark(document) {
|
|
2367
|
+
function createBrandMark(document, content) {
|
|
2368
|
+
const resolved = resolveBrandMarkContent(content);
|
|
2187
2369
|
const svg = svgElement(document, "svg", {
|
|
2370
|
+
xmlns: SVG_NAMESPACE,
|
|
2188
2371
|
class: "spotpatch-brand-mark",
|
|
2189
|
-
viewBox:
|
|
2372
|
+
viewBox: resolved.viewBox,
|
|
2190
2373
|
"aria-hidden": "true",
|
|
2191
2374
|
focusable: "false"
|
|
2192
2375
|
});
|
|
2193
|
-
|
|
2194
|
-
const gradient = svgElement(document, "linearGradient", {
|
|
2195
|
-
id: "spotpatch-brand-gradient",
|
|
2196
|
-
x1: "35",
|
|
2197
|
-
y1: "42",
|
|
2198
|
-
x2: "184",
|
|
2199
|
-
y2: "176",
|
|
2200
|
-
gradientUnits: "userSpaceOnUse"
|
|
2201
|
-
});
|
|
2202
|
-
gradient.append(
|
|
2203
|
-
svgElement(document, "stop", { offset: "0", "stop-color": "#7c22ff" }),
|
|
2204
|
-
svgElement(document, "stop", { offset: ".52", "stop-color": "#4a69ff" }),
|
|
2205
|
-
svgElement(document, "stop", { offset: "1", "stop-color": "#06d9ef" })
|
|
2206
|
-
);
|
|
2207
|
-
definitions.append(gradient);
|
|
2208
|
-
const commonStroke = {
|
|
2209
|
-
fill: "none",
|
|
2210
|
-
stroke: "url(#spotpatch-brand-gradient)",
|
|
2211
|
-
"stroke-linecap": "square",
|
|
2212
|
-
"stroke-linejoin": "miter"
|
|
2213
|
-
};
|
|
2214
|
-
const outer = svgElement(document, "path", {
|
|
2215
|
-
d: "M106 42C67 42 43 68 43 105c0 36 24 61 63 96 39-35 63-60 63-96 0-37-24-63-63-63Z",
|
|
2216
|
-
...commonStroke,
|
|
2217
|
-
"stroke-width": "14"
|
|
2218
|
-
});
|
|
2219
|
-
const topStem = svgElement(document, "path", {
|
|
2220
|
-
d: "M106 25v42",
|
|
2221
|
-
...commonStroke,
|
|
2222
|
-
"stroke-width": "14"
|
|
2223
|
-
});
|
|
2224
|
-
const sideStems = svgElement(document, "path", {
|
|
2225
|
-
d: "M35 109h20m102 0h38",
|
|
2226
|
-
...commonStroke,
|
|
2227
|
-
"stroke-width": "13"
|
|
2228
|
-
});
|
|
2229
|
-
const brackets = svgElement(document, "path", {
|
|
2230
|
-
d: "m94 89-18 19 18 17m39-36 18 19-18 17",
|
|
2231
|
-
...commonStroke,
|
|
2232
|
-
"stroke-width": "9"
|
|
2233
|
-
});
|
|
2234
|
-
const bolt = svgElement(document, "path", {
|
|
2235
|
-
d: "m119 61-20 45 15 11-13 47 30-56-16-12 4-35Z",
|
|
2236
|
-
fill: "url(#spotpatch-brand-gradient)"
|
|
2237
|
-
});
|
|
2238
|
-
svg.append(definitions, outer, topStem, sideStems, brackets, bolt);
|
|
2376
|
+
svg.innerHTML = resolved.content;
|
|
2239
2377
|
return svg;
|
|
2240
2378
|
}
|
|
2241
2379
|
|
|
@@ -2250,32 +2388,32 @@ function clamp(value, minimum, maximum) {
|
|
|
2250
2388
|
function calculateDialogPlacement({
|
|
2251
2389
|
dialogHeight,
|
|
2252
2390
|
dialogWidth,
|
|
2253
|
-
target,
|
|
2391
|
+
target: target2,
|
|
2254
2392
|
viewportHeight,
|
|
2255
2393
|
viewportWidth
|
|
2256
2394
|
}) {
|
|
2257
2395
|
const maxLeft = viewportWidth - dialogWidth - VIEWPORT_MARGIN;
|
|
2258
2396
|
const maxTop = viewportHeight - dialogHeight - VIEWPORT_MARGIN;
|
|
2259
|
-
const targetCenterX =
|
|
2260
|
-
const targetCenterY =
|
|
2397
|
+
const targetCenterX = target2.x + target2.width / 2;
|
|
2398
|
+
const targetCenterY = target2.y + target2.height / 2;
|
|
2261
2399
|
const centeredLeft = clamp(targetCenterX - dialogWidth / 2, VIEWPORT_MARGIN, maxLeft);
|
|
2262
2400
|
const centeredTop = clamp(targetCenterY - dialogHeight / 2, VIEWPORT_MARGIN, maxTop);
|
|
2263
2401
|
let left = centeredLeft;
|
|
2264
2402
|
let top = centeredTop;
|
|
2265
2403
|
let mode = "viewport";
|
|
2266
|
-
if (
|
|
2404
|
+
if (target2.width >= dialogWidth + TARGET_INSET * 2 && target2.height >= dialogHeight + TARGET_INSET * 2) {
|
|
2267
2405
|
mode = "center";
|
|
2268
|
-
} else if (
|
|
2269
|
-
top =
|
|
2406
|
+
} else if (target2.y - dialogHeight - TARGET_GAP >= VIEWPORT_MARGIN) {
|
|
2407
|
+
top = target2.y - dialogHeight - TARGET_GAP;
|
|
2270
2408
|
mode = "above";
|
|
2271
|
-
} else if (
|
|
2272
|
-
top =
|
|
2409
|
+
} else if (target2.y + target2.height + TARGET_GAP + dialogHeight <= viewportHeight - VIEWPORT_MARGIN) {
|
|
2410
|
+
top = target2.y + target2.height + TARGET_GAP;
|
|
2273
2411
|
mode = "below";
|
|
2274
|
-
} else if (
|
|
2275
|
-
left =
|
|
2412
|
+
} else if (target2.x + target2.width + TARGET_GAP + dialogWidth <= viewportWidth - VIEWPORT_MARGIN) {
|
|
2413
|
+
left = target2.x + target2.width + TARGET_GAP;
|
|
2276
2414
|
mode = "right";
|
|
2277
|
-
} else if (
|
|
2278
|
-
left =
|
|
2415
|
+
} else if (target2.x - dialogWidth - TARGET_GAP >= VIEWPORT_MARGIN) {
|
|
2416
|
+
left = target2.x - dialogWidth - TARGET_GAP;
|
|
2279
2417
|
mode = "left";
|
|
2280
2418
|
}
|
|
2281
2419
|
return Object.freeze({
|
|
@@ -2594,7 +2732,7 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2594
2732
|
noSelectable: "No selectable element was found.",
|
|
2595
2733
|
allTargetsRemoved: "All targets were removed. Choose an element to continue.",
|
|
2596
2734
|
targetRemoved: "Selected target removed.",
|
|
2597
|
-
|
|
2735
|
+
detachedTargetPreserved: "The page element was unloaded; its collected context remains selected.",
|
|
2598
2736
|
contextWarning: "Browser context collection completed with a warning.",
|
|
2599
2737
|
contextCollected: "Browser context collected.",
|
|
2600
2738
|
editorOpening: "Opening source\u2026",
|
|
@@ -2730,7 +2868,7 @@ var UI_MESSAGES = Object.freeze({
|
|
|
2730
2868
|
noSelectable: "\u5F53\u524D\u4F4D\u7F6E\u6CA1\u6709\u53EF\u9009\u62E9\u7684\u5143\u7D20\u3002",
|
|
2731
2869
|
allTargetsRemoved: "\u5DF2\u79FB\u9664\u5168\u90E8\u76EE\u6807\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u5143\u7D20\u3002",
|
|
2732
2870
|
targetRemoved: "\u5DF2\u79FB\u9664\u9009\u4E2D\u76EE\u6807\u3002",
|
|
2733
|
-
|
|
2871
|
+
detachedTargetPreserved: "\u9875\u9762\u5143\u7D20\u5DF2\u5378\u8F7D\uFF0C\u5DF2\u91C7\u96C6\u7684\u4E0A\u4E0B\u6587\u4ECD\u4FDD\u7559\u5728\u9009\u62E9\u4E2D\u3002",
|
|
2734
2872
|
contextWarning: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\uFF0C\u4F46\u5B58\u5728\u8B66\u544A\u3002",
|
|
2735
2873
|
contextCollected: "\u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u91C7\u96C6\u5B8C\u6210\u3002",
|
|
2736
2874
|
editorOpening: "\u6B63\u5728\u6253\u5F00\u6E90\u7801\u2026\u2026",
|
|
@@ -3625,11 +3763,11 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3625
3763
|
editorFeedback.textContent = state === "opening" ? messages.announcements.editorOpening : state === "success" ? messages.announcements.editorOpened : state === "error" ? messages.announcements.editorFailed : "";
|
|
3626
3764
|
placeDialog();
|
|
3627
3765
|
}
|
|
3628
|
-
function statusText(
|
|
3629
|
-
if (
|
|
3766
|
+
function statusText(target2) {
|
|
3767
|
+
if (target2.status === "ready") {
|
|
3630
3768
|
return messages.targets.statusReady;
|
|
3631
3769
|
}
|
|
3632
|
-
return
|
|
3770
|
+
return target2.status === "warning" ? messages.targets.statusPartial : messages.targets.statusCollecting;
|
|
3633
3771
|
}
|
|
3634
3772
|
function instructionInput(targetId) {
|
|
3635
3773
|
const inputs = targetList.querySelectorAll(
|
|
@@ -3646,14 +3784,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3646
3784
|
const focusedTargetId = focusedInstruction?.dataset.targetInstructionId;
|
|
3647
3785
|
const selectionStart = focusedInstruction?.selectionStart;
|
|
3648
3786
|
const selectionEnd = focusedInstruction?.selectionEnd;
|
|
3649
|
-
currentTargets = targets.map((
|
|
3787
|
+
currentTargets = targets.map((target2) => Object.freeze({ ...target2 }));
|
|
3650
3788
|
currentMaximum = maximum;
|
|
3651
3789
|
targetList.replaceChildren();
|
|
3652
3790
|
const completeCount = targets.filter(
|
|
3653
|
-
(
|
|
3791
|
+
(target2) => target2.instruction.trim().length > 0
|
|
3654
3792
|
).length;
|
|
3655
3793
|
const instructionCharacters = targets.reduce(
|
|
3656
|
-
(total,
|
|
3794
|
+
(total, target2) => total + target2.instruction.trim().length,
|
|
3657
3795
|
0
|
|
3658
3796
|
);
|
|
3659
3797
|
targetCount.textContent = messages.targets.count(targets.length, maximum);
|
|
@@ -3673,18 +3811,18 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3673
3811
|
addTargetButton.disabled = !editingEnabled || targets.length >= maximum;
|
|
3674
3812
|
addTargetButton.title = targets.length >= maximum ? messages.targets.limitTitle(maximum) : messages.targets.addTitle;
|
|
3675
3813
|
targetLabel.textContent = targets.length === 1 ? targets[0]?.label ?? messages.context.selectedElement : messages.context.selectedCount(targets.length);
|
|
3676
|
-
for (const [index,
|
|
3814
|
+
for (const [index, target2] of targets.entries()) {
|
|
3677
3815
|
const item = createMarkedElement(document, "div");
|
|
3678
3816
|
item.className = "spotpatch-target-item";
|
|
3679
|
-
item.dataset.active = String(
|
|
3680
|
-
item.dataset.status =
|
|
3681
|
-
item.dataset.targetId =
|
|
3817
|
+
item.dataset.active = String(target2.active);
|
|
3818
|
+
item.dataset.status = target2.status;
|
|
3819
|
+
item.dataset.targetId = target2.id;
|
|
3682
3820
|
const targetSummary = createMarkedElement(document, "div");
|
|
3683
3821
|
targetSummary.className = "spotpatch-target-summary";
|
|
3684
3822
|
const select = createButton(document, "", "spotpatch-target-select");
|
|
3685
|
-
select.dataset.activateTargetId =
|
|
3823
|
+
select.dataset.activateTargetId = target2.id;
|
|
3686
3824
|
select.setAttribute("aria-label", messages.targets.activate(index + 1));
|
|
3687
|
-
select.setAttribute("aria-expanded", String(
|
|
3825
|
+
select.setAttribute("aria-expanded", String(target2.active));
|
|
3688
3826
|
const number = createMarkedElement(document, "span");
|
|
3689
3827
|
number.className = "spotpatch-target-index";
|
|
3690
3828
|
number.textContent = String(index + 1);
|
|
@@ -3692,54 +3830,54 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3692
3830
|
copy.className = "spotpatch-target-copy";
|
|
3693
3831
|
const name = createMarkedElement(document, "span");
|
|
3694
3832
|
name.className = "spotpatch-target-name";
|
|
3695
|
-
name.textContent =
|
|
3696
|
-
const
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
copy.append(name,
|
|
3700
|
-
const instructionComplete =
|
|
3833
|
+
name.textContent = target2.label;
|
|
3834
|
+
const source2 = createMarkedElement(document, "span");
|
|
3835
|
+
source2.className = "spotpatch-target-source";
|
|
3836
|
+
source2.textContent = `${statusText(target2)} \xB7 ${target2.source}`;
|
|
3837
|
+
copy.append(name, source2);
|
|
3838
|
+
const instructionComplete = target2.instruction.trim().length > 0;
|
|
3701
3839
|
const state = createMarkedElement(document, "span");
|
|
3702
3840
|
state.className = "spotpatch-target-state";
|
|
3703
3841
|
state.dataset.complete = String(instructionComplete);
|
|
3704
3842
|
state.textContent = instructionComplete ? messages.targets.instructionReady : messages.targets.instructionMissing;
|
|
3705
3843
|
select.append(number, copy, state);
|
|
3706
3844
|
const open = createButton(document, "\u2197", "spotpatch-target-open");
|
|
3707
|
-
open.dataset.openTargetId =
|
|
3708
|
-
open.disabled = !
|
|
3845
|
+
open.dataset.openTargetId = target2.id;
|
|
3846
|
+
open.disabled = !target2.canOpenEditor;
|
|
3709
3847
|
open.setAttribute("aria-label", messages.actions.openTarget(index + 1));
|
|
3710
3848
|
open.title = messages.actions.openTarget(index + 1);
|
|
3711
3849
|
const remove = createButton(document, "\xD7", "spotpatch-target-remove");
|
|
3712
|
-
remove.dataset.removeTargetId =
|
|
3850
|
+
remove.dataset.removeTargetId = target2.id;
|
|
3713
3851
|
remove.disabled = !editingEnabled;
|
|
3714
3852
|
remove.setAttribute("aria-label", messages.targets.remove(index + 1));
|
|
3715
3853
|
remove.title = messages.targets.removeTitle;
|
|
3716
3854
|
targetSummary.append(select, open, remove);
|
|
3717
3855
|
item.append(targetSummary);
|
|
3718
|
-
if (
|
|
3856
|
+
if (target2.active) {
|
|
3719
3857
|
const editor = createMarkedElement(document, "label");
|
|
3720
3858
|
editor.className = "spotpatch-target-editor";
|
|
3721
3859
|
const editorHead = createMarkedElement(document, "span");
|
|
3722
3860
|
editorHead.className = "spotpatch-target-editor-head";
|
|
3723
3861
|
const editorLabel = createMarkedElement(document, "span");
|
|
3724
3862
|
editorLabel.className = "spotpatch-target-editor-label";
|
|
3725
|
-
editorLabel.textContent = messages.targets.instructionLabel(
|
|
3863
|
+
editorLabel.textContent = messages.targets.instructionLabel(target2.label);
|
|
3726
3864
|
const characterCount = createMarkedElement(document, "span");
|
|
3727
3865
|
characterCount.className = "spotpatch-target-editor-count";
|
|
3728
3866
|
characterCount.textContent = messages.targets.instructionCount(
|
|
3729
|
-
|
|
3867
|
+
target2.instruction.length,
|
|
3730
3868
|
MAX_TARGET_INSTRUCTION_CHARACTERS2
|
|
3731
3869
|
);
|
|
3732
3870
|
editorHead.append(editorLabel, characterCount);
|
|
3733
3871
|
const input = createMarkedElement(document, "textarea");
|
|
3734
3872
|
input.rows = 4;
|
|
3735
3873
|
input.maxLength = MAX_TARGET_INSTRUCTION_CHARACTERS2;
|
|
3736
|
-
input.value =
|
|
3874
|
+
input.value = target2.instruction;
|
|
3737
3875
|
input.placeholder = messages.targets.instructionPlaceholder;
|
|
3738
3876
|
input.disabled = !editingEnabled;
|
|
3739
|
-
input.dataset.targetInstructionId =
|
|
3877
|
+
input.dataset.targetInstructionId = target2.id;
|
|
3740
3878
|
input.setAttribute(
|
|
3741
3879
|
"aria-label",
|
|
3742
|
-
messages.targets.instructionLabel(
|
|
3880
|
+
messages.targets.instructionLabel(target2.label)
|
|
3743
3881
|
);
|
|
3744
3882
|
editor.append(editorHead, input);
|
|
3745
3883
|
item.append(editor);
|
|
@@ -3756,7 +3894,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3756
3894
|
}
|
|
3757
3895
|
function updateTargetInstruction(targetId, instruction) {
|
|
3758
3896
|
currentTargets = currentTargets.map(
|
|
3759
|
-
(
|
|
3897
|
+
(target2) => target2.id === targetId ? Object.freeze({ ...target2, instruction }) : target2
|
|
3760
3898
|
);
|
|
3761
3899
|
const item = Array.from(
|
|
3762
3900
|
targetList.querySelectorAll(".spotpatch-target-item")
|
|
@@ -3778,11 +3916,11 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3778
3916
|
);
|
|
3779
3917
|
}
|
|
3780
3918
|
targetComplete.textContent = messages.targets.complete(
|
|
3781
|
-
currentTargets.filter((
|
|
3919
|
+
currentTargets.filter((target2) => target2.instruction.trim().length > 0).length,
|
|
3782
3920
|
currentTargets.length
|
|
3783
3921
|
);
|
|
3784
3922
|
const instructionCharacters = currentTargets.reduce(
|
|
3785
|
-
(total,
|
|
3923
|
+
(total, target2) => total + target2.instruction.trim().length,
|
|
3786
3924
|
0
|
|
3787
3925
|
);
|
|
3788
3926
|
const instructionLimitExceeded = instructionCharacters > MAX_ANNOTATION_INSTRUCTION_CHARACTERS2;
|
|
@@ -3797,18 +3935,18 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3797
3935
|
}
|
|
3798
3936
|
function showSelectionHighlights(targets) {
|
|
3799
3937
|
selectionHighlights.replaceChildren();
|
|
3800
|
-
activeSelectionRect = targets.find((
|
|
3938
|
+
activeSelectionRect = targets.find((target2) => target2.active)?.rect;
|
|
3801
3939
|
currentRect = activeSelectionRect;
|
|
3802
|
-
for (const [index,
|
|
3940
|
+
for (const [index, target2] of targets.entries()) {
|
|
3803
3941
|
const box = createMarkedElement(document, "div");
|
|
3804
3942
|
box.className = "spotpatch-selection-highlight";
|
|
3805
|
-
box.dataset.targetId =
|
|
3806
|
-
box.dataset.active = String(
|
|
3807
|
-
box.style.transform = `translate(${String(
|
|
3808
|
-
box.style.width = `${String(
|
|
3809
|
-
box.style.height = `${String(
|
|
3943
|
+
box.dataset.targetId = target2.id;
|
|
3944
|
+
box.dataset.active = String(target2.active);
|
|
3945
|
+
box.style.transform = `translate(${String(target2.rect.x)}px, ${String(target2.rect.y)}px)`;
|
|
3946
|
+
box.style.width = `${String(target2.rect.width)}px`;
|
|
3947
|
+
box.style.height = `${String(target2.rect.height)}px`;
|
|
3810
3948
|
const label = createMarkedElement(document, "span");
|
|
3811
|
-
label.textContent = `${String(index + 1)} \xB7 ${
|
|
3949
|
+
label.textContent = `${String(index + 1)} \xB7 ${target2.label}`;
|
|
3812
3950
|
box.append(label);
|
|
3813
3951
|
selectionHighlights.append(box);
|
|
3814
3952
|
}
|
|
@@ -3840,8 +3978,8 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
|
|
|
3840
3978
|
}
|
|
3841
3979
|
function updateContextOverview(summaryText) {
|
|
3842
3980
|
const summaryMessages = messages.summary;
|
|
3843
|
-
const
|
|
3844
|
-
sourcePeek.textContent =
|
|
3981
|
+
const source2 = summaryLine(summaryText, summaryMessages.source);
|
|
3982
|
+
sourcePeek.textContent = source2 ?? messages.diagnostics.noExactSource;
|
|
3845
3983
|
const browserReady = `${summaryMessages.browserContext}: ${summaryMessages.collectionStatuses.ready}`;
|
|
3846
3984
|
const browserLoading = `${summaryMessages.browserContext}: ${summaryMessages.collectionStatuses.loading}`;
|
|
3847
3985
|
const browserFailed = `${summaryMessages.browserContext}: ${summaryMessages.collectionStatuses.failed}`;
|
|
@@ -4552,25 +4690,25 @@ var EMPTY_STYLE_CONTEXT = Object.freeze({
|
|
|
4552
4690
|
computed: Object.freeze({}),
|
|
4553
4691
|
warnings: Object.freeze(["CSS context collection failed."])
|
|
4554
4692
|
});
|
|
4555
|
-
function elementLabel(
|
|
4556
|
-
const id =
|
|
4557
|
-
const className = Array.from(
|
|
4558
|
-
return `<${
|
|
4559
|
-
}
|
|
4560
|
-
function sourceLabel(
|
|
4561
|
-
const path =
|
|
4562
|
-
const line =
|
|
4563
|
-
const column =
|
|
4693
|
+
function elementLabel(element2) {
|
|
4694
|
+
const id = element2.id.length > 0 ? `#${element2.id}` : "";
|
|
4695
|
+
const className = Array.from(element2.classList).slice(0, 2).map((name) => `.${name}`).join("");
|
|
4696
|
+
return `<${element2.tagName.toLowerCase()}${id}${className}>`;
|
|
4697
|
+
}
|
|
4698
|
+
function sourceLabel(target2, unavailable) {
|
|
4699
|
+
const path = target2.code?.relativePath ?? target2.resolution.source.relativePath;
|
|
4700
|
+
const line = target2.resolution.source.line;
|
|
4701
|
+
const column = target2.resolution.source.column;
|
|
4564
4702
|
if (path === void 0) {
|
|
4565
4703
|
return unavailable;
|
|
4566
4704
|
}
|
|
4567
4705
|
return `${path}${line === void 0 ? "" : `:${String(line)}`}${column === void 0 ? "" : `:${String(column)}`}`;
|
|
4568
4706
|
}
|
|
4569
|
-
function targetStatus(
|
|
4570
|
-
if (
|
|
4707
|
+
function targetStatus(target2) {
|
|
4708
|
+
if (target2.apiStatus === "failed" || target2.collectionStatus === "failed") {
|
|
4571
4709
|
return "warning";
|
|
4572
4710
|
}
|
|
4573
|
-
if (
|
|
4711
|
+
if (target2.apiStatus === "loading" || target2.collectionStatus === "loading") {
|
|
4574
4712
|
return "loading";
|
|
4575
4713
|
}
|
|
4576
4714
|
return "ready";
|
|
@@ -4597,6 +4735,8 @@ function createController(config, dependencies = {}) {
|
|
|
4597
4735
|
const clipboard = dependencies.clipboard ?? resolveClipboardWriter(browser.window.navigator);
|
|
4598
4736
|
const createId = dependencies.createId ?? (() => createBrowserAnnotationId(browser.window));
|
|
4599
4737
|
const now = dependencies.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
4738
|
+
const selectionSession = dependencies.selectionSession ?? createSelectionSession(browser.window, config.sessionId, config.maxTargets);
|
|
4739
|
+
const restoredSelection = selectionSession.load();
|
|
4600
4740
|
const sourceResolver = createSourceResolver({
|
|
4601
4741
|
adapter: dependencies.reactAdapter ?? createReact18Adapter({
|
|
4602
4742
|
maxComponentDepth: config.budget.maxComponentDepth
|
|
@@ -4614,9 +4754,26 @@ function createController(config, dependencies = {}) {
|
|
|
4614
4754
|
let mounted = false;
|
|
4615
4755
|
let animationFrame;
|
|
4616
4756
|
let lastPointer;
|
|
4617
|
-
let targets =
|
|
4618
|
-
|
|
4619
|
-
|
|
4757
|
+
let targets = restoredSelection?.targets.map((target2) => {
|
|
4758
|
+
const marker = sourceRefToMarker(target2.source);
|
|
4759
|
+
return {
|
|
4760
|
+
id: target2.id,
|
|
4761
|
+
resolution: Object.freeze({ source: target2.source, react: target2.react }),
|
|
4762
|
+
apiStatus: marker === void 0 ? "not-required" : target2.code === void 0 ? "failed" : "connected",
|
|
4763
|
+
code: target2.code,
|
|
4764
|
+
collectionStatus: "ready",
|
|
4765
|
+
element: void 0,
|
|
4766
|
+
elementContext: target2.element,
|
|
4767
|
+
instruction: target2.instruction,
|
|
4768
|
+
marker,
|
|
4769
|
+
page: target2.page,
|
|
4770
|
+
styles: target2.styles
|
|
4771
|
+
};
|
|
4772
|
+
}) ?? [];
|
|
4773
|
+
let activeTargetId = restoredSelection?.activeTargetId;
|
|
4774
|
+
let targetSequence = restoredSelection?.sequence ?? 0;
|
|
4775
|
+
let selectionOpen = restoredSelection?.open ?? false;
|
|
4776
|
+
let workflowSelectionActive = false;
|
|
4620
4777
|
let sessionRevision = 0;
|
|
4621
4778
|
let editorRequestRevision = 0;
|
|
4622
4779
|
let addingTarget = false;
|
|
@@ -4631,51 +4788,83 @@ function createController(config, dependencies = {}) {
|
|
|
4631
4788
|
view.renderStatus(state.status);
|
|
4632
4789
|
}
|
|
4633
4790
|
function activeTarget() {
|
|
4634
|
-
return targets.find((
|
|
4791
|
+
return targets.find((target2) => target2.id === activeTargetId) ?? targets.at(-1);
|
|
4792
|
+
}
|
|
4793
|
+
function snapshotTarget(target2) {
|
|
4794
|
+
if (target2.elementContext === void 0 || target2.styles === void 0) {
|
|
4795
|
+
return void 0;
|
|
4796
|
+
}
|
|
4797
|
+
return {
|
|
4798
|
+
id: target2.id,
|
|
4799
|
+
instruction: target2.instruction,
|
|
4800
|
+
page: target2.page,
|
|
4801
|
+
source: target2.resolution.source,
|
|
4802
|
+
react: target2.resolution.react,
|
|
4803
|
+
element: target2.elementContext,
|
|
4804
|
+
styles: target2.styles,
|
|
4805
|
+
...target2.code === void 0 ? {} : { code: target2.code }
|
|
4806
|
+
};
|
|
4635
4807
|
}
|
|
4636
|
-
function
|
|
4637
|
-
|
|
4808
|
+
function persistSelection() {
|
|
4809
|
+
const persistedTargets = targets.flatMap((target2) => {
|
|
4810
|
+
const snapshot = snapshotTarget(target2);
|
|
4811
|
+
return snapshot === void 0 ? [] : [snapshot];
|
|
4812
|
+
});
|
|
4813
|
+
if (persistedTargets.length === 0) {
|
|
4814
|
+
selectionSession.clear();
|
|
4815
|
+
return;
|
|
4816
|
+
}
|
|
4817
|
+
const persistedIds = new Set(persistedTargets.map(({ id }) => id));
|
|
4818
|
+
selectionSession.save({
|
|
4819
|
+
...activeTargetId !== void 0 && persistedIds.has(activeTargetId) ? { activeTargetId } : {},
|
|
4820
|
+
open: selectionOpen,
|
|
4821
|
+
sequence: targetSequence,
|
|
4822
|
+
targets: persistedTargets
|
|
4823
|
+
});
|
|
4824
|
+
}
|
|
4825
|
+
function targetIsCurrent(target2, revision) {
|
|
4826
|
+
return mounted && revision === sessionRevision && state.status !== "idle" && targets.includes(target2);
|
|
4638
4827
|
}
|
|
4639
4828
|
function canPreview() {
|
|
4640
4829
|
const instructionCharacters = targets.reduce(
|
|
4641
|
-
(total,
|
|
4830
|
+
(total, target2) => total + target2.instruction.trim().length,
|
|
4642
4831
|
0
|
|
4643
4832
|
);
|
|
4644
4833
|
return targets.length > 0 && instructionCharacters <= MAX_ANNOTATION_INSTRUCTION_CHARACTERS3 && targets.every(
|
|
4645
|
-
(
|
|
4834
|
+
(target2) => target2.instruction.trim().length > 0 && target2.elementContext !== void 0 && target2.styles !== void 0 && target2.apiStatus !== "loading"
|
|
4646
4835
|
);
|
|
4647
4836
|
}
|
|
4648
4837
|
function selectionSummary() {
|
|
4649
4838
|
const messages = view.messages().summary;
|
|
4650
|
-
return targets.map((
|
|
4839
|
+
return targets.map((target2, index) => {
|
|
4651
4840
|
const summary = createSelectionSummary(
|
|
4652
4841
|
{
|
|
4653
|
-
resolution:
|
|
4654
|
-
...
|
|
4655
|
-
...
|
|
4656
|
-
apiStatus:
|
|
4657
|
-
collectionStatus:
|
|
4842
|
+
resolution: target2.resolution,
|
|
4843
|
+
...target2.code === void 0 ? {} : { code: target2.code },
|
|
4844
|
+
...target2.styles === void 0 ? {} : { styles: target2.styles },
|
|
4845
|
+
apiStatus: target2.apiStatus,
|
|
4846
|
+
collectionStatus: target2.collectionStatus,
|
|
4658
4847
|
framework: config.framework,
|
|
4659
4848
|
frameworkVersion: config.frameworkVersion,
|
|
4660
4849
|
spotPatchVersion: config.spotPatchVersion
|
|
4661
4850
|
},
|
|
4662
4851
|
messages
|
|
4663
4852
|
);
|
|
4664
|
-
return `${messages.target(index + 1,
|
|
4853
|
+
return `${messages.target(index + 1, target2.id === activeTargetId)}
|
|
4665
4854
|
${summary}`;
|
|
4666
4855
|
}).join("\n\n");
|
|
4667
4856
|
}
|
|
4668
4857
|
function refreshHighlights() {
|
|
4669
|
-
const highlights = targets.flatMap((
|
|
4670
|
-
if (!
|
|
4858
|
+
const highlights = targets.flatMap((target2) => {
|
|
4859
|
+
if (!target2.element?.isConnected) {
|
|
4671
4860
|
return [];
|
|
4672
4861
|
}
|
|
4673
4862
|
return [
|
|
4674
4863
|
{
|
|
4675
|
-
id:
|
|
4676
|
-
label: elementLabel(
|
|
4677
|
-
rect: getElementRect(
|
|
4678
|
-
active:
|
|
4864
|
+
id: target2.id,
|
|
4865
|
+
label: elementLabel(target2.element),
|
|
4866
|
+
rect: getElementRect(target2.element, browser.window),
|
|
4867
|
+
active: target2.id === activeTargetId
|
|
4679
4868
|
}
|
|
4680
4869
|
];
|
|
4681
4870
|
});
|
|
@@ -4690,14 +4879,14 @@ ${summary}`;
|
|
|
4690
4879
|
return;
|
|
4691
4880
|
}
|
|
4692
4881
|
view.renderTargets(
|
|
4693
|
-
targets.map((
|
|
4694
|
-
id:
|
|
4695
|
-
label:
|
|
4696
|
-
source: sourceLabel(
|
|
4697
|
-
canOpenEditor:
|
|
4698
|
-
status: targetStatus(
|
|
4699
|
-
active:
|
|
4700
|
-
instruction:
|
|
4882
|
+
targets.map((target2) => ({
|
|
4883
|
+
id: target2.id,
|
|
4884
|
+
label: target2.resolution.react.componentName ?? (target2.element === void 0 ? target2.elementContext?.tagName ?? "Element" : elementLabel(target2.element)),
|
|
4885
|
+
source: sourceLabel(target2, view.messages().context.sourceUnavailable),
|
|
4886
|
+
canOpenEditor: target2.marker !== void 0,
|
|
4887
|
+
status: targetStatus(target2),
|
|
4888
|
+
active: target2.id === activeTargetId,
|
|
4889
|
+
instruction: target2.instruction
|
|
4701
4890
|
})),
|
|
4702
4891
|
config.maxTargets
|
|
4703
4892
|
);
|
|
@@ -4715,21 +4904,22 @@ ${summary}`;
|
|
|
4715
4904
|
if (!canPreview()) {
|
|
4716
4905
|
return void 0;
|
|
4717
4906
|
}
|
|
4718
|
-
const annotationTargets = targets.map((
|
|
4719
|
-
if (
|
|
4907
|
+
const annotationTargets = targets.map((target2) => {
|
|
4908
|
+
if (target2.elementContext === void 0 || target2.styles === void 0) {
|
|
4720
4909
|
throw new Error("SpotPatch attempted to compose an incomplete target.");
|
|
4721
4910
|
}
|
|
4722
4911
|
const warnings = [
|
|
4723
|
-
...
|
|
4724
|
-
...
|
|
4912
|
+
...target2.apiStatus === "failed" ? ["Source context could not be loaded."] : [],
|
|
4913
|
+
...target2.collectionStatus === "failed" ? ["Part of the browser context could not be collected."] : []
|
|
4725
4914
|
];
|
|
4726
4915
|
return {
|
|
4727
|
-
instruction:
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4916
|
+
instruction: target2.instruction.trim(),
|
|
4917
|
+
page: target2.page,
|
|
4918
|
+
source: target2.resolution.source,
|
|
4919
|
+
react: target2.resolution.react,
|
|
4920
|
+
element: target2.elementContext,
|
|
4921
|
+
styles: target2.styles,
|
|
4922
|
+
...target2.code === void 0 ? {} : { code: target2.code },
|
|
4733
4923
|
warnings
|
|
4734
4924
|
};
|
|
4735
4925
|
});
|
|
@@ -4741,8 +4931,8 @@ ${summary}`;
|
|
|
4741
4931
|
targets: annotationTargets
|
|
4742
4932
|
});
|
|
4743
4933
|
}
|
|
4744
|
-
function showElementHighlight(
|
|
4745
|
-
view.showHighlight(getElementRect(
|
|
4934
|
+
function showElementHighlight(element2) {
|
|
4935
|
+
view.showHighlight(getElementRect(element2, browser.window), elementLabel(element2));
|
|
4746
4936
|
}
|
|
4747
4937
|
function restoreFocus() {
|
|
4748
4938
|
if (previousFocus?.isConnected === true) {
|
|
@@ -4764,10 +4954,13 @@ ${summary}`;
|
|
|
4764
4954
|
resizeObserver?.disconnect();
|
|
4765
4955
|
targets = [];
|
|
4766
4956
|
activeTargetId = void 0;
|
|
4957
|
+
selectionOpen = false;
|
|
4958
|
+
workflowSelectionActive = false;
|
|
4767
4959
|
addingTarget = false;
|
|
4768
4960
|
previewPrompt = "";
|
|
4769
4961
|
view.hideSelection();
|
|
4770
4962
|
view.hideSelectionHighlights();
|
|
4963
|
+
selectionSession.clear();
|
|
4771
4964
|
restoreFocus();
|
|
4772
4965
|
}
|
|
4773
4966
|
function close() {
|
|
@@ -4779,7 +4972,11 @@ ${summary}`;
|
|
|
4779
4972
|
transition({ type: "BACK" });
|
|
4780
4973
|
transition({ type: "CLOSE" });
|
|
4781
4974
|
}
|
|
4782
|
-
|
|
4975
|
+
selectionOpen = false;
|
|
4976
|
+
persistSelection();
|
|
4977
|
+
view.hideSelection();
|
|
4978
|
+
view.hideSelectionHighlights();
|
|
4979
|
+
restoreFocus();
|
|
4783
4980
|
view.hideHighlight();
|
|
4784
4981
|
}
|
|
4785
4982
|
function cancelAddTarget() {
|
|
@@ -4803,6 +5000,18 @@ ${summary}`;
|
|
|
4803
5000
|
close();
|
|
4804
5001
|
return;
|
|
4805
5002
|
}
|
|
5003
|
+
if (targets.length > 0) {
|
|
5004
|
+
selectionOpen = true;
|
|
5005
|
+
transition({ type: "RESTORE" });
|
|
5006
|
+
if (!workflowSelectionActive) {
|
|
5007
|
+
agentWorkflow.beginSelection();
|
|
5008
|
+
workflowSelectionActive = true;
|
|
5009
|
+
}
|
|
5010
|
+
refreshSelectionView(true);
|
|
5011
|
+
view.focusTargetInstruction(activeTargetId);
|
|
5012
|
+
persistSelection();
|
|
5013
|
+
return;
|
|
5014
|
+
}
|
|
4806
5015
|
transition({ type: "ACTIVATE" });
|
|
4807
5016
|
view.hideSelection();
|
|
4808
5017
|
view.announce(view.messages().announcements.selectionEnabled);
|
|
@@ -4836,12 +5045,13 @@ ${summary}`;
|
|
|
4836
5045
|
sessionRevision += 1;
|
|
4837
5046
|
clearCollectionTimers();
|
|
4838
5047
|
resizeObserver?.disconnect();
|
|
4839
|
-
for (const
|
|
4840
|
-
|
|
5048
|
+
for (const target2 of targets) {
|
|
5049
|
+
target2.element = void 0;
|
|
4841
5050
|
}
|
|
4842
5051
|
view.hideHighlight();
|
|
4843
5052
|
view.hideSelectionHighlights();
|
|
4844
5053
|
refreshSelectionView();
|
|
5054
|
+
selectionSession.clear();
|
|
4845
5055
|
view.announce(view.messages().announcements.appliedTargetsDetached);
|
|
4846
5056
|
}
|
|
4847
5057
|
const agentWorkflow = createAgentWorkflow({
|
|
@@ -4854,8 +5064,8 @@ ${summary}`;
|
|
|
4854
5064
|
},
|
|
4855
5065
|
view
|
|
4856
5066
|
});
|
|
4857
|
-
async function loadSourceContext(
|
|
4858
|
-
const marker =
|
|
5067
|
+
async function loadSourceContext(target2, revision) {
|
|
5068
|
+
const marker = target2.marker;
|
|
4859
5069
|
if (marker === void 0) {
|
|
4860
5070
|
return;
|
|
4861
5071
|
}
|
|
@@ -4866,16 +5076,18 @@ ${summary}`;
|
|
|
4866
5076
|
column: marker.column,
|
|
4867
5077
|
maxLines: config.budget.maxCodeLines
|
|
4868
5078
|
});
|
|
4869
|
-
if (targetIsCurrent(
|
|
4870
|
-
|
|
4871
|
-
|
|
5079
|
+
if (targetIsCurrent(target2, revision)) {
|
|
5080
|
+
target2.code = context;
|
|
5081
|
+
target2.apiStatus = "connected";
|
|
5082
|
+
persistSelection();
|
|
4872
5083
|
refreshSelectionView();
|
|
4873
5084
|
view.announce(view.messages().announcements.sourceLoaded);
|
|
4874
5085
|
}
|
|
4875
5086
|
} catch (error) {
|
|
4876
|
-
if (targetIsCurrent(
|
|
4877
|
-
|
|
4878
|
-
|
|
5087
|
+
if (targetIsCurrent(target2, revision)) {
|
|
5088
|
+
target2.code = void 0;
|
|
5089
|
+
target2.apiStatus = "failed";
|
|
5090
|
+
persistSelection();
|
|
4879
5091
|
refreshSelectionView();
|
|
4880
5092
|
view.announce(view.messages().announcements.sourceFailed);
|
|
4881
5093
|
if (config.debug && !(error instanceof DOMException && error.name === "AbortError")) {
|
|
@@ -4884,61 +5096,62 @@ ${summary}`;
|
|
|
4884
5096
|
}
|
|
4885
5097
|
}
|
|
4886
5098
|
}
|
|
4887
|
-
function scheduleBrowserContextCollection(
|
|
4888
|
-
const
|
|
4889
|
-
if (
|
|
5099
|
+
function scheduleBrowserContextCollection(target2, revision) {
|
|
5100
|
+
const element2 = target2.element;
|
|
5101
|
+
if (element2 === void 0) {
|
|
4890
5102
|
return;
|
|
4891
5103
|
}
|
|
4892
5104
|
const timer = browser.window.setTimeout(() => {
|
|
4893
|
-
collectionTimers.delete(
|
|
4894
|
-
if (!targetIsCurrent(
|
|
5105
|
+
collectionTimers.delete(target2.id);
|
|
5106
|
+
if (!targetIsCurrent(target2, revision)) {
|
|
4895
5107
|
return;
|
|
4896
5108
|
}
|
|
4897
5109
|
let failed = false;
|
|
4898
5110
|
try {
|
|
4899
|
-
|
|
4900
|
-
element,
|
|
5111
|
+
target2.elementContext = collectElementContext({
|
|
5112
|
+
element: element2,
|
|
4901
5113
|
maxCharacters: config.budget.domCharacters
|
|
4902
5114
|
});
|
|
4903
5115
|
} catch {
|
|
4904
|
-
|
|
5116
|
+
target2.elementContext = void 0;
|
|
4905
5117
|
failed = true;
|
|
4906
5118
|
}
|
|
4907
5119
|
try {
|
|
4908
|
-
|
|
5120
|
+
target2.styles = collectStyleContext({
|
|
4909
5121
|
document: browser.document,
|
|
4910
|
-
element,
|
|
5122
|
+
element: element2,
|
|
4911
5123
|
maxCharacters: config.budget.cssCharacters
|
|
4912
5124
|
});
|
|
4913
5125
|
} catch {
|
|
4914
|
-
|
|
5126
|
+
target2.styles = EMPTY_STYLE_CONTEXT;
|
|
4915
5127
|
failed = true;
|
|
4916
5128
|
}
|
|
4917
|
-
|
|
5129
|
+
target2.collectionStatus = failed ? "failed" : "ready";
|
|
5130
|
+
persistSelection();
|
|
4918
5131
|
refreshSelectionView();
|
|
4919
5132
|
view.announce(
|
|
4920
5133
|
failed ? view.messages().announcements.contextWarning : view.messages().announcements.contextCollected
|
|
4921
5134
|
);
|
|
4922
|
-
if (config.debug &&
|
|
5135
|
+
if (config.debug && target2.styles.warnings.length > 0) {
|
|
4923
5136
|
console.warn(
|
|
4924
|
-
`[spotpatch:runtime] CSS collection completed with ${String(
|
|
5137
|
+
`[spotpatch:runtime] CSS collection completed with ${String(target2.styles.warnings.length)} warning(s).`
|
|
4925
5138
|
);
|
|
4926
5139
|
}
|
|
4927
5140
|
}, 0);
|
|
4928
|
-
collectionTimers.set(
|
|
5141
|
+
collectionTimers.set(target2.id, timer);
|
|
4929
5142
|
}
|
|
4930
|
-
function duplicateTarget(
|
|
5143
|
+
function duplicateTarget(element2, marker) {
|
|
4931
5144
|
if (marker !== void 0) {
|
|
4932
5145
|
return targets.find(
|
|
4933
|
-
(
|
|
5146
|
+
(target2) => target2.marker?.fileId === marker.fileId && target2.marker.line === marker.line && target2.marker.column === marker.column
|
|
4934
5147
|
);
|
|
4935
5148
|
}
|
|
4936
|
-
return targets.find((
|
|
5149
|
+
return targets.find((target2) => target2.element === element2);
|
|
4937
5150
|
}
|
|
4938
|
-
function selectElement(
|
|
4939
|
-
const resolution = sourceResolver.resolve(
|
|
5151
|
+
function selectElement(element2) {
|
|
5152
|
+
const resolution = sourceResolver.resolve(element2);
|
|
4940
5153
|
const marker = sourceRefToMarker(resolution.source);
|
|
4941
|
-
const duplicate = duplicateTarget(
|
|
5154
|
+
const duplicate = duplicateTarget(element2, marker);
|
|
4942
5155
|
if (duplicate !== void 0) {
|
|
4943
5156
|
activeTargetId = duplicate.id;
|
|
4944
5157
|
addingTarget = false;
|
|
@@ -4962,13 +5175,15 @@ ${summary}`;
|
|
|
4962
5175
|
previousFocus = browser.document.activeElement instanceof HTMLElement ? browser.document.activeElement : void 0;
|
|
4963
5176
|
previewPrompt = "";
|
|
4964
5177
|
agentWorkflow.beginSelection();
|
|
5178
|
+
workflowSelectionActive = true;
|
|
4965
5179
|
}
|
|
4966
5180
|
targetSequence += 1;
|
|
4967
|
-
const
|
|
5181
|
+
const target2 = {
|
|
4968
5182
|
id: `target-${String(targetSequence)}`,
|
|
4969
|
-
element,
|
|
5183
|
+
element: element2,
|
|
4970
5184
|
resolution,
|
|
4971
5185
|
marker,
|
|
5186
|
+
page: collectPageContext(browser.document, browser.window),
|
|
4972
5187
|
code: void 0,
|
|
4973
5188
|
elementContext: void 0,
|
|
4974
5189
|
styles: void 0,
|
|
@@ -4976,18 +5191,19 @@ ${summary}`;
|
|
|
4976
5191
|
apiStatus: marker === void 0 ? "not-required" : "loading",
|
|
4977
5192
|
collectionStatus: "loading"
|
|
4978
5193
|
};
|
|
4979
|
-
targets.push(
|
|
4980
|
-
activeTargetId =
|
|
5194
|
+
targets.push(target2);
|
|
5195
|
+
activeTargetId = target2.id;
|
|
4981
5196
|
addingTarget = false;
|
|
4982
5197
|
const revision = sessionRevision;
|
|
4983
5198
|
transition({ type: "SELECT" });
|
|
4984
5199
|
view.hideHighlight();
|
|
4985
|
-
resizeObserver?.observe(
|
|
5200
|
+
resizeObserver?.observe(element2);
|
|
4986
5201
|
refreshSelectionView(true);
|
|
4987
|
-
|
|
4988
|
-
|
|
5202
|
+
selectionOpen = true;
|
|
5203
|
+
view.focusTargetInstruction(target2.id);
|
|
5204
|
+
scheduleBrowserContextCollection(target2, revision);
|
|
4989
5205
|
if (marker !== void 0) {
|
|
4990
|
-
void loadSourceContext(
|
|
5206
|
+
void loadSourceContext(target2, revision);
|
|
4991
5207
|
} else {
|
|
4992
5208
|
view.announce(
|
|
4993
5209
|
resolution.source.confidence === "probable" ? view.messages().announcements.sourceProbable : view.messages().announcements.sourceMissing
|
|
@@ -5061,7 +5277,7 @@ ${summary}`;
|
|
|
5061
5277
|
if (state.status !== "selected" && state.status !== "inspecting") {
|
|
5062
5278
|
return;
|
|
5063
5279
|
}
|
|
5064
|
-
const index = targets.findIndex((
|
|
5280
|
+
const index = targets.findIndex((target2) => target2.id === targetId);
|
|
5065
5281
|
if (index < 0) {
|
|
5066
5282
|
return;
|
|
5067
5283
|
}
|
|
@@ -5087,10 +5303,12 @@ ${summary}`;
|
|
|
5087
5303
|
}
|
|
5088
5304
|
view.hideSelectionTemporarily();
|
|
5089
5305
|
view.hideSelectionHighlights();
|
|
5306
|
+
selectionSession.clear();
|
|
5090
5307
|
view.announce(view.messages().announcements.allTargetsRemoved);
|
|
5091
5308
|
return;
|
|
5092
5309
|
}
|
|
5093
5310
|
refreshSelectionView();
|
|
5311
|
+
persistSelection();
|
|
5094
5312
|
view.announce(view.messages().announcements.targetRemoved);
|
|
5095
5313
|
}
|
|
5096
5314
|
function refreshSelectedGeometry() {
|
|
@@ -5098,24 +5316,24 @@ ${summary}`;
|
|
|
5098
5316
|
return;
|
|
5099
5317
|
}
|
|
5100
5318
|
const disconnected = targets.filter(
|
|
5101
|
-
(
|
|
5319
|
+
(target2) => target2.element !== void 0 && !target2.element.isConnected
|
|
5102
5320
|
);
|
|
5103
5321
|
if (disconnected.length > 0) {
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
}
|
|
5110
|
-
if (targets.length > 0) {
|
|
5111
|
-
view.announce(view.messages().announcements.detachedTargetRemoved);
|
|
5322
|
+
for (const target2 of disconnected) {
|
|
5323
|
+
if (target2.element !== void 0) {
|
|
5324
|
+
resizeObserver?.unobserve(target2.element);
|
|
5325
|
+
target2.element = void 0;
|
|
5326
|
+
}
|
|
5112
5327
|
}
|
|
5328
|
+
refreshSelectionView();
|
|
5329
|
+
persistSelection();
|
|
5330
|
+
view.announce(view.messages().announcements.detachedTargetPreserved);
|
|
5113
5331
|
return;
|
|
5114
5332
|
}
|
|
5115
5333
|
refreshHighlights();
|
|
5116
5334
|
}
|
|
5117
5335
|
function handleOpenEditor(targetId) {
|
|
5118
|
-
const current = targetId === void 0 ? activeTarget() : targets.find((
|
|
5336
|
+
const current = targetId === void 0 ? activeTarget() : targets.find((target2) => target2.id === targetId);
|
|
5119
5337
|
if (state.status !== "selected" || current?.marker === void 0) {
|
|
5120
5338
|
return;
|
|
5121
5339
|
}
|
|
@@ -5147,13 +5365,14 @@ ${summary}`;
|
|
|
5147
5365
|
return;
|
|
5148
5366
|
}
|
|
5149
5367
|
const targetId = event.target.dataset.targetInstructionId;
|
|
5150
|
-
const
|
|
5151
|
-
if (
|
|
5368
|
+
const target2 = targets.find((candidate) => candidate.id === targetId);
|
|
5369
|
+
if (target2 === void 0) {
|
|
5152
5370
|
return;
|
|
5153
5371
|
}
|
|
5154
|
-
|
|
5155
|
-
view.updateTargetInstruction(
|
|
5372
|
+
target2.instruction = event.target.value;
|
|
5373
|
+
view.updateTargetInstruction(target2.id, target2.instruction);
|
|
5156
5374
|
view.setPreviewEnabled(canPreview());
|
|
5375
|
+
persistSelection();
|
|
5157
5376
|
}
|
|
5158
5377
|
function handleOpenEditorButtonClick() {
|
|
5159
5378
|
handleOpenEditor();
|
|
@@ -5246,7 +5465,7 @@ ${summary}`;
|
|
|
5246
5465
|
"button[data-activate-target-id]"
|
|
5247
5466
|
);
|
|
5248
5467
|
const targetId = activateButton?.dataset.activateTargetId;
|
|
5249
|
-
if (state.status !== "selected" || targetId === void 0 || !targets.some((
|
|
5468
|
+
if (state.status !== "selected" || targetId === void 0 || !targets.some((target2) => target2.id === targetId)) {
|
|
5250
5469
|
return;
|
|
5251
5470
|
}
|
|
5252
5471
|
activeTargetId = targetId;
|
|
@@ -5304,6 +5523,12 @@ ${summary}`;
|
|
|
5304
5523
|
subtree: true
|
|
5305
5524
|
});
|
|
5306
5525
|
}
|
|
5526
|
+
if (selectionOpen && targets.length > 0) {
|
|
5527
|
+
transition({ type: "RESTORE" });
|
|
5528
|
+
agentWorkflow.beginSelection();
|
|
5529
|
+
workflowSelectionActive = true;
|
|
5530
|
+
refreshSelectionView(true);
|
|
5531
|
+
}
|
|
5307
5532
|
if (config.debug) {
|
|
5308
5533
|
console.info(`[spotpatch:runtime] Mounted. Shortcut: ${config.shortcut}.`);
|
|
5309
5534
|
}
|
|
@@ -5361,6 +5586,7 @@ ${summary}`;
|
|
|
5361
5586
|
animationFrame = void 0;
|
|
5362
5587
|
}
|
|
5363
5588
|
clearCollectionTimers();
|
|
5589
|
+
persistSelection();
|
|
5364
5590
|
resizeObserver?.disconnect();
|
|
5365
5591
|
mutationObserver?.disconnect();
|
|
5366
5592
|
resizeObserver = void 0;
|
|
@@ -5383,10 +5609,10 @@ ${summary}`;
|
|
|
5383
5609
|
// src/controller/bootstrap.ts
|
|
5384
5610
|
var RUNTIME_INSTANCE_KEY = "__spotpatchRuntime__";
|
|
5385
5611
|
function bootstrapSpotPatch(config) {
|
|
5386
|
-
const
|
|
5387
|
-
|
|
5612
|
+
const target2 = globalThis;
|
|
5613
|
+
target2[RUNTIME_INSTANCE_KEY]?.dispose();
|
|
5388
5614
|
const controller = createController(config);
|
|
5389
|
-
|
|
5615
|
+
target2[RUNTIME_INSTANCE_KEY] = controller;
|
|
5390
5616
|
controller.mount();
|
|
5391
5617
|
}
|
|
5392
5618
|
export {
|