Voyager「引用回覆」功能全解析:一鍵將選中文字轉為 Markdown 引用,精準追問與糾錯
【免费下载链接】voyagerEnhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用于任意网站,如 DeepSeek Harness。项目地址: https://gitcode.com/gh_mirrors/ge/voyager
「引用回覆(Quote Reply)」是 Voyager 為 Gemini 等 AI 對話頁面打造的精準追問利器:無需手動複製文字、手打>符號,只要用滑鼠選中對話中的任意段落,點擊懸浮的引用按鈕,文字便會以標準 Markdown 引用格式自動插入輸入框。本篇指南將完整講解該功能的三步操作流程、三大核心特性與實戰技巧,並深入 src/pages/content/quoteReply/index.ts 等原始碼,剖析上下文感知判定、多行引用格式化、LaTeX 公式保留、空輸入偵測與插入策略等底層實現,讓你能夠知其然更知其所以然,並掌握它的開關設定與可驗證的測試依據。
(示意圖原圖見 docs/public/assets/quote-reply.png)
功能介紹:選中即引,一鍵插入
在日常對話中,我們經常需要針對 AI 輸出中的某一段具體內容進行追問或反駁。傳統的做法是複製那段話,然後在輸入框裡手打>符號,非常繁瑣。Voyager 將整個流程簡化為三步:
- 選中即引:在對話頁面(無論是你的提問還是 Gemini 的回答)中,用滑鼠選中任意一段文字。
- 懸浮按鈕:選中文字附近會自動浮現一個「引用回覆」按鈕。
- 一鍵插入:點擊按鈕,選中的文字會自動以標準的 Markdown 引用格式(
> 內容)插入到你的輸入框中。
插入完成後,游標會停留在引用內容之後,你可以緊接著輸入追問或修正的內容,按下送出即可。從原始碼看,handleQuoteClick 是整個流程的核心入口:它先從當前選區提取文字,再定位輸入框(findChatInput),完成格式化與插入。插入還考慮了「輸入框摺疊」功能——如果輸入區被摺疊,會先呼叫 expandInputCollapseIfNeeded 展開,測試用例expands input collapse when using quote reply也明確驗證了這一行為。
特性一:上下文感知,避免誤觸發
Voyager 會智能識別對話內容,避免在無關區域(如輸入框本身、側邊欄、導覽列)誤觸發引用按鈕。從 handleSelectionChange 的實現可以看到一系列精細的守衛條件:
- 只在主內容區生效:若選區所在的元素不在頁面
main容器內,直接隱藏按鈕,排除導覽列、側邊欄等干擾。 - 顯式排除 UI 區域:
nav、[role="navigation"]、.sidebar、.mat-drawer等元素內的選區一律不觸發。 - 排除輸入框本身:選區若落在
[contenteditable="true"]內(即輸入框),不會彈出按鈕,避免在打字過程中被誤打擾。 - 僅限對話輪次:選區必須落在
QUOTEABLE_MESSAGE_SELECTOR(.conversation-container與使用者/模型輪次的選取器集合,定義於 index.ts)之內,同時要求選區的共同祖先也在其中,防止選區橫跨對話與非對話元素。 - 排除新對話歡迎語:Gemini 新對話頁面的歡迎問候語(greeting)與提示建議雖然也在
main內,但並非真正的訊息輪次,不會觸發引用。對應測試does not show Quote Reply for Gemini new-chat greeting text與does not show Quote Reply for a selection spanning message and greeting在 quoteReply.test.ts 中給出了完整覆蓋。
此外,選區的偵測採用250ms 防抖(SELECTION_DEBOUNCE_MS),並同時監聽mouseup與keyup(支援鍵盤選取),避免拖曳選取過程中頻繁觸發重繪。
特性二:標準 Markdown 格式,Gemini 完美理解
引用按鈕使用通用的 Markdown 語法,Gemini 可以完美理解這種引用結構,從而做出更精準的回應。格式化邏輯位於 handleQuoteClick:
const quoteBody = selectedText .split('\n') .map((line) => `> ${line}`) .join('\n');也就是每一行前面都加上>前綴。除了純文字,還有兩個值得關注的細節:
- 多行支持:如果選中了多行文本,Voyager 會自動為每一行添加引用符號,保持格式整潔(測試
preserves inline math等用例亦驗證多行結構下內容不失真)。 - LaTeX 公式保留:Gemini 對話中的數學公式是以視覺渲染形式呈現的,直接取選區文字會遺失 LaTeX 分隔符。Voyager 透過 extractTextWithLatex 將選區內部的
.math-inline、.math-block與[data-math]元素替換回$...$/$$...$$原始語法後再取文字,因此引用帶有公式的內容時,會得到可再度提交的 LaTeX 源碼,例如測試中驗證的$U \in [0, 1)$、$$E = mc^2$$與獨立的$x^2$。
特性三:智能輸入框處理與 IME 友好插入
「一鍵插入」並非簡單地往輸入框塞字串,原始碼針對 Gemini 基於 Quill 的 contenteditable 富文字輸入框與傳統<textarea>做了兩套路徑,並處理了大量邊界情況:
- 空輸入判定:透過 isChatInputEmpty 判斷輸入框是否為空。它會把
ql-blank視為空編輯器的標準標記,但若innerText中已有「非 placeholder 的真實文字」(即使ql-blank類別因 DOM 更新滯後仍存在),也會正確判定為非空。測試treats ql-blank editor as empty even if placeholder text exists與treats stale ql-blank with real user text as non-empty分別驗證了兩種情形。 - 分隔規則:引用內容與既有文字之間會自動插入空行——輸入框為空時不加前綴,非空時加入
\n\n,避免引用與正文黏連(測試adds a blank line when input has visible text驗證結果為Existing\n\n> Hello\n)。 - Firefox 特例:由於 Firefox 的 Quill contenteditable 對雙換行會渲染出額外的視覺空行,getContenteditableQuoteSeparator 在 Firefox 下改用單換行
\n作為分隔,測試uses single-line separator for Firefox contenteditable給出確切證據。 - execCommand 與 Range 雙保險:優先使用
document.execCommand('insertText')(對 Quill 最友好),若命令不可用或部分變更,則回退到 Range 手動插入文本節點,並把游標移動到插入內容之後。測試對「分隔符完全插入」「分隔符插入但內容未變」「僅視覺換行生效」等多種組合都有覆蓋。 - IME 友好:插入時以
focusChatInput盡量最小化焦點切換,避免輸入框失焦(測試does not blur or refocus the contenteditable input after quote insertion驗證了插入後輸入框仍保持焦點),讓中文等 IME 輸入法可以在下一次按鍵時立即開始組字。
使用技巧
- 追問細節:選中 Gemini 回答中不清楚的某個概念,點擊引用,然後輸入「請詳細解釋一下這個概念」。
- 糾正錯誤:選中回答中錯誤的程式碼或事實,引用後指出「這裡不對,應該是...」。
值得一提的是,引用送出後,Voyager 還會對已發送的引用區塊與輸入框內的引用行進行視覺修飾。renderedQuotes.ts 會將連續的>引用行包裝成<blockquote class="gv-rendered-quote">樣式,並在輸入框中為引用行標記gv-composer-quote-line等類別;整個過程以MutationObserver監聽 DOM 變化(80ms 防抖),清理時會完整還原原始 DOM(測試restores the original DOM on cleanup驗證)。這些樣式規則位於 public/contentStyle.css,使用--gv-pm-brand主題變數與border-inline-start等邏輯屬性,能同時適配深色/淺色主題與 RTL 版面。
設定與開關
引用回覆預設開啟,可透過彈出面板(Popup)中的「啟用引用回覆」開關控制,對應設定項定義如下:
- 儲存鍵:
gvQuoteReplyEnabled(常數StorageKeys.QUOTE_REPLY_ENABLED,見 src/core/types/common.ts)。 - 預設值:
true,在內容腳本初始化(src/pages/content/index.tsx)與設定備份服務(src/core/services/SettingsBackupService.ts)中均可確認。 - 設定介面:彈出面板的通用設定卡片透過
quote-reply-enabled開關列控制(見 src/pages/popup/components/GeneralSettingsCard.tsx),其狀態由useGeneralPopupSettings讀寫。 - 與高亮功能共用工具列:引用與「高亮標記」共用同一個懸浮選取工具列與選區監聽器,避免兩個浮動控制互相競爭;關閉引用後工具列仍可用於高亮操作(測試
uses the same selection toolbar for Highlight when Quote Reply is disabled驗證了僅有一個.gv-selection-toolbar,且引用按鈕隱藏、高亮按鈕可見)。
結語
Voyager 的「引用回覆」看似只是「選中 → 點擊 → 插入」三步,但底層卻是一套嚴謹的工程實現:從上下文感知的選區過濾,到逐行>格式化的多行支援,再到 Quill contenteditable、Firefox 換行差異、LaTeX 公式還原與 IME 焦點保護等細節,無一不為了讓「精準追問」這件事又快又準。結合 quoteReply.test.ts 與 renderedQuotes.test.ts 兩份測試套件,你可以完整追蹤這條功能鏈路的每一環節,甚至以此為範本理解 Voyager 其他對話增強功能(如高亮、輸入摺疊)的設計風格。
【免费下载链接】voyagerEnhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用于任意网站,如 DeepSeek Harness。项目地址: https://gitcode.com/gh_mirrors/ge/voyager
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考