@spotpatch/runtime 1.3.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 +21 -7
- package/dist/index.cjs +603 -376
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -15
- package/dist/index.d.ts +2 -15
- package/dist/index.js +601 -374
- 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}`;
|
|
@@ -4118,7 +4256,7 @@ function sourceLocation2(resolution, context, messages) {
|
|
|
4118
4256
|
function createSelectionSummary(input, messages) {
|
|
4119
4257
|
const lines = [
|
|
4120
4258
|
`SpotPatch: ${input.spotPatchVersion}`,
|
|
4121
|
-
|
|
4259
|
+
`${input.framework === "next" ? "Next.js" : "Vite"}: ${input.frameworkVersion}`,
|
|
4122
4260
|
`${messages.source}: ${sourceLocation2(input.resolution, input.code, messages)}`,
|
|
4123
4261
|
`${messages.confidence}: ${input.resolution.source.confidence} (${messages.confidenceLabels[input.resolution.source.confidence]})`,
|
|
4124
4262
|
`${messages.origin}: ${input.resolution.source.origin}`
|
|
@@ -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,50 +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:
|
|
4658
|
-
|
|
4659
|
-
|
|
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,
|
|
4847
|
+
framework: config.framework,
|
|
4848
|
+
frameworkVersion: config.frameworkVersion,
|
|
4849
|
+
spotPatchVersion: config.spotPatchVersion
|
|
4660
4850
|
},
|
|
4661
4851
|
messages
|
|
4662
4852
|
);
|
|
4663
|
-
return `${messages.target(index + 1,
|
|
4853
|
+
return `${messages.target(index + 1, target2.id === activeTargetId)}
|
|
4664
4854
|
${summary}`;
|
|
4665
4855
|
}).join("\n\n");
|
|
4666
4856
|
}
|
|
4667
4857
|
function refreshHighlights() {
|
|
4668
|
-
const highlights = targets.flatMap((
|
|
4669
|
-
if (!
|
|
4858
|
+
const highlights = targets.flatMap((target2) => {
|
|
4859
|
+
if (!target2.element?.isConnected) {
|
|
4670
4860
|
return [];
|
|
4671
4861
|
}
|
|
4672
4862
|
return [
|
|
4673
4863
|
{
|
|
4674
|
-
id:
|
|
4675
|
-
label: elementLabel(
|
|
4676
|
-
rect: getElementRect(
|
|
4677
|
-
active:
|
|
4864
|
+
id: target2.id,
|
|
4865
|
+
label: elementLabel(target2.element),
|
|
4866
|
+
rect: getElementRect(target2.element, browser.window),
|
|
4867
|
+
active: target2.id === activeTargetId
|
|
4678
4868
|
}
|
|
4679
4869
|
];
|
|
4680
4870
|
});
|
|
@@ -4689,14 +4879,14 @@ ${summary}`;
|
|
|
4689
4879
|
return;
|
|
4690
4880
|
}
|
|
4691
4881
|
view.renderTargets(
|
|
4692
|
-
targets.map((
|
|
4693
|
-
id:
|
|
4694
|
-
label:
|
|
4695
|
-
source: sourceLabel(
|
|
4696
|
-
canOpenEditor:
|
|
4697
|
-
status: targetStatus(
|
|
4698
|
-
active:
|
|
4699
|
-
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
|
|
4700
4890
|
})),
|
|
4701
4891
|
config.maxTargets
|
|
4702
4892
|
);
|
|
@@ -4714,21 +4904,22 @@ ${summary}`;
|
|
|
4714
4904
|
if (!canPreview()) {
|
|
4715
4905
|
return void 0;
|
|
4716
4906
|
}
|
|
4717
|
-
const annotationTargets = targets.map((
|
|
4718
|
-
if (
|
|
4907
|
+
const annotationTargets = targets.map((target2) => {
|
|
4908
|
+
if (target2.elementContext === void 0 || target2.styles === void 0) {
|
|
4719
4909
|
throw new Error("SpotPatch attempted to compose an incomplete target.");
|
|
4720
4910
|
}
|
|
4721
4911
|
const warnings = [
|
|
4722
|
-
...
|
|
4723
|
-
...
|
|
4912
|
+
...target2.apiStatus === "failed" ? ["Source context could not be loaded."] : [],
|
|
4913
|
+
...target2.collectionStatus === "failed" ? ["Part of the browser context could not be collected."] : []
|
|
4724
4914
|
];
|
|
4725
4915
|
return {
|
|
4726
|
-
instruction:
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
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 },
|
|
4732
4923
|
warnings
|
|
4733
4924
|
};
|
|
4734
4925
|
});
|
|
@@ -4740,8 +4931,8 @@ ${summary}`;
|
|
|
4740
4931
|
targets: annotationTargets
|
|
4741
4932
|
});
|
|
4742
4933
|
}
|
|
4743
|
-
function showElementHighlight(
|
|
4744
|
-
view.showHighlight(getElementRect(
|
|
4934
|
+
function showElementHighlight(element2) {
|
|
4935
|
+
view.showHighlight(getElementRect(element2, browser.window), elementLabel(element2));
|
|
4745
4936
|
}
|
|
4746
4937
|
function restoreFocus() {
|
|
4747
4938
|
if (previousFocus?.isConnected === true) {
|
|
@@ -4763,10 +4954,13 @@ ${summary}`;
|
|
|
4763
4954
|
resizeObserver?.disconnect();
|
|
4764
4955
|
targets = [];
|
|
4765
4956
|
activeTargetId = void 0;
|
|
4957
|
+
selectionOpen = false;
|
|
4958
|
+
workflowSelectionActive = false;
|
|
4766
4959
|
addingTarget = false;
|
|
4767
4960
|
previewPrompt = "";
|
|
4768
4961
|
view.hideSelection();
|
|
4769
4962
|
view.hideSelectionHighlights();
|
|
4963
|
+
selectionSession.clear();
|
|
4770
4964
|
restoreFocus();
|
|
4771
4965
|
}
|
|
4772
4966
|
function close() {
|
|
@@ -4778,7 +4972,11 @@ ${summary}`;
|
|
|
4778
4972
|
transition({ type: "BACK" });
|
|
4779
4973
|
transition({ type: "CLOSE" });
|
|
4780
4974
|
}
|
|
4781
|
-
|
|
4975
|
+
selectionOpen = false;
|
|
4976
|
+
persistSelection();
|
|
4977
|
+
view.hideSelection();
|
|
4978
|
+
view.hideSelectionHighlights();
|
|
4979
|
+
restoreFocus();
|
|
4782
4980
|
view.hideHighlight();
|
|
4783
4981
|
}
|
|
4784
4982
|
function cancelAddTarget() {
|
|
@@ -4802,6 +5000,18 @@ ${summary}`;
|
|
|
4802
5000
|
close();
|
|
4803
5001
|
return;
|
|
4804
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
|
+
}
|
|
4805
5015
|
transition({ type: "ACTIVATE" });
|
|
4806
5016
|
view.hideSelection();
|
|
4807
5017
|
view.announce(view.messages().announcements.selectionEnabled);
|
|
@@ -4835,12 +5045,13 @@ ${summary}`;
|
|
|
4835
5045
|
sessionRevision += 1;
|
|
4836
5046
|
clearCollectionTimers();
|
|
4837
5047
|
resizeObserver?.disconnect();
|
|
4838
|
-
for (const
|
|
4839
|
-
|
|
5048
|
+
for (const target2 of targets) {
|
|
5049
|
+
target2.element = void 0;
|
|
4840
5050
|
}
|
|
4841
5051
|
view.hideHighlight();
|
|
4842
5052
|
view.hideSelectionHighlights();
|
|
4843
5053
|
refreshSelectionView();
|
|
5054
|
+
selectionSession.clear();
|
|
4844
5055
|
view.announce(view.messages().announcements.appliedTargetsDetached);
|
|
4845
5056
|
}
|
|
4846
5057
|
const agentWorkflow = createAgentWorkflow({
|
|
@@ -4853,8 +5064,8 @@ ${summary}`;
|
|
|
4853
5064
|
},
|
|
4854
5065
|
view
|
|
4855
5066
|
});
|
|
4856
|
-
async function loadSourceContext(
|
|
4857
|
-
const marker =
|
|
5067
|
+
async function loadSourceContext(target2, revision) {
|
|
5068
|
+
const marker = target2.marker;
|
|
4858
5069
|
if (marker === void 0) {
|
|
4859
5070
|
return;
|
|
4860
5071
|
}
|
|
@@ -4865,16 +5076,18 @@ ${summary}`;
|
|
|
4865
5076
|
column: marker.column,
|
|
4866
5077
|
maxLines: config.budget.maxCodeLines
|
|
4867
5078
|
});
|
|
4868
|
-
if (targetIsCurrent(
|
|
4869
|
-
|
|
4870
|
-
|
|
5079
|
+
if (targetIsCurrent(target2, revision)) {
|
|
5080
|
+
target2.code = context;
|
|
5081
|
+
target2.apiStatus = "connected";
|
|
5082
|
+
persistSelection();
|
|
4871
5083
|
refreshSelectionView();
|
|
4872
5084
|
view.announce(view.messages().announcements.sourceLoaded);
|
|
4873
5085
|
}
|
|
4874
5086
|
} catch (error) {
|
|
4875
|
-
if (targetIsCurrent(
|
|
4876
|
-
|
|
4877
|
-
|
|
5087
|
+
if (targetIsCurrent(target2, revision)) {
|
|
5088
|
+
target2.code = void 0;
|
|
5089
|
+
target2.apiStatus = "failed";
|
|
5090
|
+
persistSelection();
|
|
4878
5091
|
refreshSelectionView();
|
|
4879
5092
|
view.announce(view.messages().announcements.sourceFailed);
|
|
4880
5093
|
if (config.debug && !(error instanceof DOMException && error.name === "AbortError")) {
|
|
@@ -4883,61 +5096,62 @@ ${summary}`;
|
|
|
4883
5096
|
}
|
|
4884
5097
|
}
|
|
4885
5098
|
}
|
|
4886
|
-
function scheduleBrowserContextCollection(
|
|
4887
|
-
const
|
|
4888
|
-
if (
|
|
5099
|
+
function scheduleBrowserContextCollection(target2, revision) {
|
|
5100
|
+
const element2 = target2.element;
|
|
5101
|
+
if (element2 === void 0) {
|
|
4889
5102
|
return;
|
|
4890
5103
|
}
|
|
4891
5104
|
const timer = browser.window.setTimeout(() => {
|
|
4892
|
-
collectionTimers.delete(
|
|
4893
|
-
if (!targetIsCurrent(
|
|
5105
|
+
collectionTimers.delete(target2.id);
|
|
5106
|
+
if (!targetIsCurrent(target2, revision)) {
|
|
4894
5107
|
return;
|
|
4895
5108
|
}
|
|
4896
5109
|
let failed = false;
|
|
4897
5110
|
try {
|
|
4898
|
-
|
|
4899
|
-
element,
|
|
5111
|
+
target2.elementContext = collectElementContext({
|
|
5112
|
+
element: element2,
|
|
4900
5113
|
maxCharacters: config.budget.domCharacters
|
|
4901
5114
|
});
|
|
4902
5115
|
} catch {
|
|
4903
|
-
|
|
5116
|
+
target2.elementContext = void 0;
|
|
4904
5117
|
failed = true;
|
|
4905
5118
|
}
|
|
4906
5119
|
try {
|
|
4907
|
-
|
|
5120
|
+
target2.styles = collectStyleContext({
|
|
4908
5121
|
document: browser.document,
|
|
4909
|
-
element,
|
|
5122
|
+
element: element2,
|
|
4910
5123
|
maxCharacters: config.budget.cssCharacters
|
|
4911
5124
|
});
|
|
4912
5125
|
} catch {
|
|
4913
|
-
|
|
5126
|
+
target2.styles = EMPTY_STYLE_CONTEXT;
|
|
4914
5127
|
failed = true;
|
|
4915
5128
|
}
|
|
4916
|
-
|
|
5129
|
+
target2.collectionStatus = failed ? "failed" : "ready";
|
|
5130
|
+
persistSelection();
|
|
4917
5131
|
refreshSelectionView();
|
|
4918
5132
|
view.announce(
|
|
4919
5133
|
failed ? view.messages().announcements.contextWarning : view.messages().announcements.contextCollected
|
|
4920
5134
|
);
|
|
4921
|
-
if (config.debug &&
|
|
5135
|
+
if (config.debug && target2.styles.warnings.length > 0) {
|
|
4922
5136
|
console.warn(
|
|
4923
|
-
`[spotpatch:runtime] CSS collection completed with ${String(
|
|
5137
|
+
`[spotpatch:runtime] CSS collection completed with ${String(target2.styles.warnings.length)} warning(s).`
|
|
4924
5138
|
);
|
|
4925
5139
|
}
|
|
4926
5140
|
}, 0);
|
|
4927
|
-
collectionTimers.set(
|
|
5141
|
+
collectionTimers.set(target2.id, timer);
|
|
4928
5142
|
}
|
|
4929
|
-
function duplicateTarget(
|
|
5143
|
+
function duplicateTarget(element2, marker) {
|
|
4930
5144
|
if (marker !== void 0) {
|
|
4931
5145
|
return targets.find(
|
|
4932
|
-
(
|
|
5146
|
+
(target2) => target2.marker?.fileId === marker.fileId && target2.marker.line === marker.line && target2.marker.column === marker.column
|
|
4933
5147
|
);
|
|
4934
5148
|
}
|
|
4935
|
-
return targets.find((
|
|
5149
|
+
return targets.find((target2) => target2.element === element2);
|
|
4936
5150
|
}
|
|
4937
|
-
function selectElement(
|
|
4938
|
-
const resolution = sourceResolver.resolve(
|
|
5151
|
+
function selectElement(element2) {
|
|
5152
|
+
const resolution = sourceResolver.resolve(element2);
|
|
4939
5153
|
const marker = sourceRefToMarker(resolution.source);
|
|
4940
|
-
const duplicate = duplicateTarget(
|
|
5154
|
+
const duplicate = duplicateTarget(element2, marker);
|
|
4941
5155
|
if (duplicate !== void 0) {
|
|
4942
5156
|
activeTargetId = duplicate.id;
|
|
4943
5157
|
addingTarget = false;
|
|
@@ -4961,13 +5175,15 @@ ${summary}`;
|
|
|
4961
5175
|
previousFocus = browser.document.activeElement instanceof HTMLElement ? browser.document.activeElement : void 0;
|
|
4962
5176
|
previewPrompt = "";
|
|
4963
5177
|
agentWorkflow.beginSelection();
|
|
5178
|
+
workflowSelectionActive = true;
|
|
4964
5179
|
}
|
|
4965
5180
|
targetSequence += 1;
|
|
4966
|
-
const
|
|
5181
|
+
const target2 = {
|
|
4967
5182
|
id: `target-${String(targetSequence)}`,
|
|
4968
|
-
element,
|
|
5183
|
+
element: element2,
|
|
4969
5184
|
resolution,
|
|
4970
5185
|
marker,
|
|
5186
|
+
page: collectPageContext(browser.document, browser.window),
|
|
4971
5187
|
code: void 0,
|
|
4972
5188
|
elementContext: void 0,
|
|
4973
5189
|
styles: void 0,
|
|
@@ -4975,18 +5191,19 @@ ${summary}`;
|
|
|
4975
5191
|
apiStatus: marker === void 0 ? "not-required" : "loading",
|
|
4976
5192
|
collectionStatus: "loading"
|
|
4977
5193
|
};
|
|
4978
|
-
targets.push(
|
|
4979
|
-
activeTargetId =
|
|
5194
|
+
targets.push(target2);
|
|
5195
|
+
activeTargetId = target2.id;
|
|
4980
5196
|
addingTarget = false;
|
|
4981
5197
|
const revision = sessionRevision;
|
|
4982
5198
|
transition({ type: "SELECT" });
|
|
4983
5199
|
view.hideHighlight();
|
|
4984
|
-
resizeObserver?.observe(
|
|
5200
|
+
resizeObserver?.observe(element2);
|
|
4985
5201
|
refreshSelectionView(true);
|
|
4986
|
-
|
|
4987
|
-
|
|
5202
|
+
selectionOpen = true;
|
|
5203
|
+
view.focusTargetInstruction(target2.id);
|
|
5204
|
+
scheduleBrowserContextCollection(target2, revision);
|
|
4988
5205
|
if (marker !== void 0) {
|
|
4989
|
-
void loadSourceContext(
|
|
5206
|
+
void loadSourceContext(target2, revision);
|
|
4990
5207
|
} else {
|
|
4991
5208
|
view.announce(
|
|
4992
5209
|
resolution.source.confidence === "probable" ? view.messages().announcements.sourceProbable : view.messages().announcements.sourceMissing
|
|
@@ -5060,7 +5277,7 @@ ${summary}`;
|
|
|
5060
5277
|
if (state.status !== "selected" && state.status !== "inspecting") {
|
|
5061
5278
|
return;
|
|
5062
5279
|
}
|
|
5063
|
-
const index = targets.findIndex((
|
|
5280
|
+
const index = targets.findIndex((target2) => target2.id === targetId);
|
|
5064
5281
|
if (index < 0) {
|
|
5065
5282
|
return;
|
|
5066
5283
|
}
|
|
@@ -5086,10 +5303,12 @@ ${summary}`;
|
|
|
5086
5303
|
}
|
|
5087
5304
|
view.hideSelectionTemporarily();
|
|
5088
5305
|
view.hideSelectionHighlights();
|
|
5306
|
+
selectionSession.clear();
|
|
5089
5307
|
view.announce(view.messages().announcements.allTargetsRemoved);
|
|
5090
5308
|
return;
|
|
5091
5309
|
}
|
|
5092
5310
|
refreshSelectionView();
|
|
5311
|
+
persistSelection();
|
|
5093
5312
|
view.announce(view.messages().announcements.targetRemoved);
|
|
5094
5313
|
}
|
|
5095
5314
|
function refreshSelectedGeometry() {
|
|
@@ -5097,24 +5316,24 @@ ${summary}`;
|
|
|
5097
5316
|
return;
|
|
5098
5317
|
}
|
|
5099
5318
|
const disconnected = targets.filter(
|
|
5100
|
-
(
|
|
5319
|
+
(target2) => target2.element !== void 0 && !target2.element.isConnected
|
|
5101
5320
|
);
|
|
5102
5321
|
if (disconnected.length > 0) {
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
}
|
|
5109
|
-
if (targets.length > 0) {
|
|
5110
|
-
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
|
+
}
|
|
5111
5327
|
}
|
|
5328
|
+
refreshSelectionView();
|
|
5329
|
+
persistSelection();
|
|
5330
|
+
view.announce(view.messages().announcements.detachedTargetPreserved);
|
|
5112
5331
|
return;
|
|
5113
5332
|
}
|
|
5114
5333
|
refreshHighlights();
|
|
5115
5334
|
}
|
|
5116
5335
|
function handleOpenEditor(targetId) {
|
|
5117
|
-
const current = targetId === void 0 ? activeTarget() : targets.find((
|
|
5336
|
+
const current = targetId === void 0 ? activeTarget() : targets.find((target2) => target2.id === targetId);
|
|
5118
5337
|
if (state.status !== "selected" || current?.marker === void 0) {
|
|
5119
5338
|
return;
|
|
5120
5339
|
}
|
|
@@ -5146,13 +5365,14 @@ ${summary}`;
|
|
|
5146
5365
|
return;
|
|
5147
5366
|
}
|
|
5148
5367
|
const targetId = event.target.dataset.targetInstructionId;
|
|
5149
|
-
const
|
|
5150
|
-
if (
|
|
5368
|
+
const target2 = targets.find((candidate) => candidate.id === targetId);
|
|
5369
|
+
if (target2 === void 0) {
|
|
5151
5370
|
return;
|
|
5152
5371
|
}
|
|
5153
|
-
|
|
5154
|
-
view.updateTargetInstruction(
|
|
5372
|
+
target2.instruction = event.target.value;
|
|
5373
|
+
view.updateTargetInstruction(target2.id, target2.instruction);
|
|
5155
5374
|
view.setPreviewEnabled(canPreview());
|
|
5375
|
+
persistSelection();
|
|
5156
5376
|
}
|
|
5157
5377
|
function handleOpenEditorButtonClick() {
|
|
5158
5378
|
handleOpenEditor();
|
|
@@ -5245,7 +5465,7 @@ ${summary}`;
|
|
|
5245
5465
|
"button[data-activate-target-id]"
|
|
5246
5466
|
);
|
|
5247
5467
|
const targetId = activateButton?.dataset.activateTargetId;
|
|
5248
|
-
if (state.status !== "selected" || targetId === void 0 || !targets.some((
|
|
5468
|
+
if (state.status !== "selected" || targetId === void 0 || !targets.some((target2) => target2.id === targetId)) {
|
|
5249
5469
|
return;
|
|
5250
5470
|
}
|
|
5251
5471
|
activeTargetId = targetId;
|
|
@@ -5303,6 +5523,12 @@ ${summary}`;
|
|
|
5303
5523
|
subtree: true
|
|
5304
5524
|
});
|
|
5305
5525
|
}
|
|
5526
|
+
if (selectionOpen && targets.length > 0) {
|
|
5527
|
+
transition({ type: "RESTORE" });
|
|
5528
|
+
agentWorkflow.beginSelection();
|
|
5529
|
+
workflowSelectionActive = true;
|
|
5530
|
+
refreshSelectionView(true);
|
|
5531
|
+
}
|
|
5306
5532
|
if (config.debug) {
|
|
5307
5533
|
console.info(`[spotpatch:runtime] Mounted. Shortcut: ${config.shortcut}.`);
|
|
5308
5534
|
}
|
|
@@ -5360,6 +5586,7 @@ ${summary}`;
|
|
|
5360
5586
|
animationFrame = void 0;
|
|
5361
5587
|
}
|
|
5362
5588
|
clearCollectionTimers();
|
|
5589
|
+
persistSelection();
|
|
5363
5590
|
resizeObserver?.disconnect();
|
|
5364
5591
|
mutationObserver?.disconnect();
|
|
5365
5592
|
resizeObserver = void 0;
|
|
@@ -5382,10 +5609,10 @@ ${summary}`;
|
|
|
5382
5609
|
// src/controller/bootstrap.ts
|
|
5383
5610
|
var RUNTIME_INSTANCE_KEY = "__spotpatchRuntime__";
|
|
5384
5611
|
function bootstrapSpotPatch(config) {
|
|
5385
|
-
const
|
|
5386
|
-
|
|
5612
|
+
const target2 = globalThis;
|
|
5613
|
+
target2[RUNTIME_INSTANCE_KEY]?.dispose();
|
|
5387
5614
|
const controller = createController(config);
|
|
5388
|
-
|
|
5615
|
+
target2[RUNTIME_INSTANCE_KEY] = controller;
|
|
5389
5616
|
controller.mount();
|
|
5390
5617
|
}
|
|
5391
5618
|
export {
|