mirror of
https://git.zavage.net/Zavage-Software/search-with-chatgpt-powered-by-openai-extension.git
synced 2026-08-10 13:40:29 -06:00
doc: record the $-pattern and frame-focus corrections
The spec prescribed replaceAll's string form and the plan hard-coded it, so the $-substitution defect originated in the design documents rather than in execution. Both now specify the function replacer. Also replaces the spec's frame-reporting idea with the document.hasFocus() gate that shipped; frame provenance was only ever needed for auto-submit, which Appendix B rejects.
This commit is contained in:
parent
51bf4d5c01
commit
8fcc93c541
@ -486,7 +486,12 @@ function applyTemplate(template, query) {
|
|||||||
}
|
}
|
||||||
const tpl = typeof template === "string" ? template : "";
|
const tpl = typeof template === "string" ? template : "";
|
||||||
if (tpl.includes("{query}")) {
|
if (tpl.includes("{query}")) {
|
||||||
return tpl.replaceAll("{query}", query);
|
// Corrected during execution: the replacer MUST be a function. In the
|
||||||
|
// string form, $&, $`, $' and $$ are substitution patterns in the
|
||||||
|
// replacement — and the replacement is arbitrary page-selected text.
|
||||||
|
// Measured on the default {query} template: "awk print $& here" produced
|
||||||
|
// "awk print {query} here".
|
||||||
|
return tpl.replaceAll("{query}", () => query);
|
||||||
}
|
}
|
||||||
const trimmed = tpl.trim();
|
const trimmed = tpl.trim();
|
||||||
return trimmed === "" ? query : `${trimmed} ${query}`;
|
return trimmed === "" ? query : `${trimmed} ${query}`;
|
||||||
@ -704,7 +709,11 @@ async function readSelection() {
|
|||||||
let results;
|
let results;
|
||||||
try {
|
try {
|
||||||
results = await browser.tabs.executeScript(tabId, {
|
results = await browser.tabs.executeScript(tabId, {
|
||||||
code: "window.getSelection().toString()",
|
// Corrected during execution: gated on document.hasFocus(). Each frame
|
||||||
|
// owns an independent Selection that is not cleared when the user
|
||||||
|
// selects elsewhere, so an unfocused (possibly cross-origin) frame's
|
||||||
|
// stale selection could otherwise win on unspecified result ordering.
|
||||||
|
code: "document.hasFocus() ? window.getSelection().toString() : ''",
|
||||||
allFrames: true,
|
allFrames: true,
|
||||||
matchAboutBlank: true,
|
matchAboutBlank: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -293,7 +293,14 @@ mid-2025; the root form is what OpenAI's own extension uses.
|
|||||||
1. **Build the prompt.** Let `q = String(rawQuery ?? "").trim()`.
|
1. **Build the prompt.** Let `q = String(rawQuery ?? "").trim()`.
|
||||||
- If `q === ""` → `prompt = ""` (the template is ignored entirely).
|
- If `q === ""` → `prompt = ""` (the template is ignored entirely).
|
||||||
- Else if the template contains `{query}` → replace **every** occurrence
|
- Else if the template contains `{query}` → replace **every** occurrence
|
||||||
(`replaceAll`).
|
(`replaceAll`). Pass a **replacer function**, not the string:
|
||||||
|
`tpl.replaceAll("{query}", () => q)`. In the string form, `$&`, `` $` ``,
|
||||||
|
`$'`, and `$$` are substitution patterns *in the replacement*, and the
|
||||||
|
replacement here is arbitrary page-selected text. Corrected during
|
||||||
|
execution after this was measured on the default `{query}` template:
|
||||||
|
selecting `awk print $& here` produced `awk print {query} here`, and
|
||||||
|
`PID is $$ in bash` produced `PID is $ in bash`. Shell and regex snippets
|
||||||
|
are a headline use case, so this fired on ordinary input for every user.
|
||||||
- Else if the trimmed template is empty → `prompt = q`.
|
- Else if the trimmed template is empty → `prompt = q`.
|
||||||
- Else → `prompt = trimmedTemplate + " " + q` (template treated as a prefix;
|
- Else → `prompt = trimmedTemplate + " " + q` (template treated as a prefix;
|
||||||
the selection is never silently discarded).
|
the selection is never silently discarded).
|
||||||
@ -345,8 +352,20 @@ both.
|
|||||||
|
|
||||||
Pass **both** `allFrames: true` (a selection inside an iframe is invisible
|
Pass **both** `allFrames: true` (a selection inside an iframe is invisible
|
||||||
to the top frame) and `matchAboutBlank: true` (needed for `about:blank`
|
to the top frame) and `matchAboutBlank: true` (needed for `about:blank`
|
||||||
frames). Have the injected snippet report which frame it came from, and
|
frames), then take the first non-empty result.
|
||||||
take the first non-empty result.
|
|
||||||
|
Corrected during execution: gate the injected snippet on
|
||||||
|
`document.hasFocus()` —
|
||||||
|
`"document.hasFocus() ? window.getSelection().toString() : ''"`. Each frame
|
||||||
|
owns an independent `Selection`, and a selection made in a frame is *not*
|
||||||
|
cleared when the user selects elsewhere, so without the gate a stale
|
||||||
|
selection in an unfocused (possibly cross-origin) frame can win, decided by
|
||||||
|
an `executeScript` result ordering that is not specified. `hasFocus()` is
|
||||||
|
true for the focused document and all its ancestors, so the top frame wins
|
||||||
|
when the user selected there and an iframe is used only when it is itself
|
||||||
|
focused. This supersedes the earlier idea of having the snippet report its
|
||||||
|
own frame — that was only ever needed to establish provenance for
|
||||||
|
auto-submit, which Appendix B rejects.
|
||||||
|
|
||||||
**Null-check every element of the result array.** `executeScript` does not
|
**Null-check every element of the result array.** `executeScript` does not
|
||||||
only throw — on parent-process `about:` pages such as `about:addons` and
|
only throw — on parent-process `about:` pages such as `about:addons` and
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user