Files
search-with-chatgpt-powered…/lib/build-url.js
golemandClaude Opus 5.5 cc68fe98b5 refactor: remove the unused URL shortener
buildChatGptUrl and its fitToBudget helpers have had no production
caller since prepareAction took over routing; the 2026-10-05 plan kept
them only for existing tests until then. They also shortened silently,
against the ask-before-shortening rule, so they were a trap to reuse.

Port the tests that guard live code onto applyTemplate and
serializePrompt, including the $&, $`, $' and $$ regressions (checked to
fail against the string-replacement form), and cover prepareAction's
whole-word cut, which nothing tested before.

Also drop getContext's inputType password check. menus.OnClickData has
no inputType, so it never fired; Firefox already withholds password
fields from selectionText via mozIsTextField(true) in SelectionUtils
(bug 565717).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 02:13:06 -06:00

50 lines
1.9 KiB
JavaScript

// Pure URL construction. No browser APIs, so node:test imports this directly.
//
// Every ChatGPT parameter below is undocumented by OpenAI and has broken before.
// This module's contract is only that it emits a well-formed URL; whether
// ChatGPT honours temporary-chat / hints is out of our control, which is
// why each is independently omittable and every label is hint-strength.
//
// The root path is mandatory: chatgpt.com/search began returning 404 in
// mid-2025, and the root form is what OpenAI's own extension uses.
const BASE = "https://chatgpt.com/";
export const MAX_URL_CHARS = 8000;
export function applyTemplate(template, query) {
if (query === "") {
return "";
}
const tpl = typeof template === "string" ? template : "";
if (tpl.includes("{query}")) {
// Replacer function, not a replacement string: String.prototype.replaceAll
// gives $&, $`, $', and $$ special meaning in a replacement STRING, and
// `query` is arbitrary page-selected text that can contain any of those
// (shell one-liners routinely do). The function form disables that
// interpretation entirely. Do not "simplify" this back to the string form.
return tpl.replaceAll("{query}", () => query);
}
const trimmed = tpl.trim();
return trimmed === "" ? query : `${trimmed} ${query}`;
}
function addOptionalParams(url, settings) {
if (settings.temporaryChat) {
url.searchParams.set("temporary-chat", "true");
}
if (settings.webSearch) {
url.searchParams.set("hints", "search");
}
return url;
}
// Encode a complete prompt without silently shortening it; prepareAction owns
// the length budget and asks before shortening. q goes first, matching the
// most-cited working examples.
export function serializePrompt(settings, prompt) {
const url = new URL(BASE);
if (prompt) url.searchParams.set("q", prompt);
return addOptionalParams(url, settings).href;
}