Mermaid Diagram Extension: ChatGPT

3 min read
摘要
這是一個瀏覽器擴充功能,用於增強 ChatGPT 網頁上的 Mermaid 圖表功能。主要特點包括自動渲染、放大鏡功能和編輯器整合。
技術架構
擴充功能由以下核心檔案組成:
- manifest.json: 擴充功能配置檔案,定義版本、權限和功能
- content.js: 注入到目標網頁的內容腳本,負責初始化擴充功能
- injected.js: 處理 Mermaid 轉換和渲染邏輯的主要腳本
- pako.min.js: 資料壓縮庫,用於處理圖表代碼的壓縮和編碼
檔案關係
manifest.json <-- 瀏覽器讀取的入口檔案
|
+--> content.js <-- 注入到網頁
|
+--> injected.js <-- 核心功能實現
|
+--> pako.min.js <-- 壓縮庫依賴
運作流程
初始化:
- content.js 將 injected.js 注入到 ChatGPT 頁面
- 添加自定義 CSS 樣式,包括放大鏡和按鈕樣式
- 載入 pako 壓縮庫
- 設置事件攔截器,隱藏原始 Mermaid 代碼區塊
圖表轉換:
- 識別頁面中的 Mermaid 代碼區塊 (
.language-mermaid
) - 使用 pako 壓縮代碼並轉為 Base64 編碼
- 透過 mermaid.ink 服務生成圖片 URL
- 建立圖片元素替換原始代碼區塊
- 識別頁面中的 Mermaid 代碼區塊 (
用戶界面增強:
- 替換原始代碼區塊為圖片
- 添加放大鏡功能,支援 1.5 倍放大
- 提供編輯器鏈接按鈕,直接跳轉到 mermaid.live 進行編輯
- 添加錯誤處理和錯誤提示
DOM 監控:
- 使用 MutationObserver 監控頁面變化
- 當新的 Mermaid 區塊出現時自動進行轉換
- 實現即時轉換無需頁面重載
安裝方法
- 下載專案程式碼
- 開啟 Chrome/Edge/Firefox 的擴充功能頁面
- 啟用開發者模式
- 點擊「載入未封裝的擴充功能」或「載入臨時附加元件」
- 選擇專案資料夾
- 前往 ChatGPT 網站進行測試
關鍵技術點
代碼轉換流程
// 壓縮並編碼 Mermaid 代碼
function getEncodedPayload(mermaidCode) {
// 添加灰色主題設定
if (!mermaidCode.includes('%%{init:')) {
mermaidCode = `%%{init: {'theme': 'default', 'themeVariables': { 'nodeBorder': '#c0c0c0', 'nodeBkg': '#e0e0e0' }}}%%\n${mermaidCode}`;
}
const payload = {
code: mermaidCode,
mermaid: { theme: "default" },
updateEditor: true,
autoSync: true
};
// 壓縮轉換
const jsonStr = JSON.stringify(payload);
const jsonUint8 = new TextEncoder().encode(jsonStr);
const compressed = pako.deflate(jsonUint8);
const binaryStr = Array.from(compressed)
.map(byte => String.fromCharCode(byte))
.join('');
return btoa(binaryStr)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
// 取得圖片 URL
function getMermaidImageUrl(mermaidCode) {
return "https://mermaid.ink/img/pako:" + getEncodedPayload(mermaidCode);
}
// 取得編輯器 URL
function getMermaidEditorUrl(mermaidCode) {
return "https://mermaid.live/edit#pako:" + getEncodedPayload(mermaidCode);
}
放大鏡實現
擴充功能支援圖片放大鏡功能,可精確顯示游標位置的放大內容:
- 使用 CSS
background-position
和background-size
屬性控制顯示區域 - 通過鼠標事件 (mousemove) 計算放大區域位置
- 設置放大倍率為 1.5 倍
- 放大鏡大小為原圖的 50%
// 放大鏡功能實現摘要
function setupMagnifier(imgElement, imgContainer) {
const magnifier = document.createElement('div');
magnifier.className = 'magnifier-glass';
imgContainer.appendChild(magnifier);
// 設置放大鏡樣式
magnifier.style.backgroundImage = `url(${imgElement.src})`;
magnifier.style.backgroundRepeat = 'no-repeat';
magnifier.style.backgroundSize = `${imgElement.width * 1.5}px ${imgElement.height * 1.5}px`;
// 鼠標移動時更新放大鏡位置
imgElement.addEventListener('mousemove', function(e) {
const rect = imgElement.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// 計算放大鏡位置和背景位置
const magnifierWidth = magnifier.offsetWidth;
const magnifierHeight = magnifier.offsetHeight;
let left = x - magnifierWidth / 2;
let top = y - magnifierHeight / 2;
// 限制在圖片範圍內
left = Math.max(0, Math.min(left, imgElement.width - magnifierWidth));
top = Math.max(0, Math.min(top, imgElement.height - magnifierHeight));
magnifier.style.left = `${left}px`;
magnifier.style.top = `${top}px`;
// 計算背景位置
const bgX = -(x * 1.5 - magnifierWidth / 2);
const bgY = -(y * 1.5 - magnifierHeight / 2);
magnifier.style.backgroundPosition = `${bgX}px ${bgY}px`;
});
}
DOM 監控與動態渲染
使用 MutationObserver 實現對頁面 DOM 變化的監控,當檢測到新的 Mermaid 代碼塊時自動執行轉換:
// 設置 DOM 監控
function setupMutationObserver() {
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
// 處理新增的節點
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
// 查找並處理 Mermaid 代碼塊
const mermaidBlocks = node.querySelectorAll('pre code.language-mermaid, .language-mermaid');
if (mermaidBlocks.length > 0) {
processMermaidBlocks(mermaidBlocks);
}
}
});
}
});
});
// 開始監控整個文檔
observer.observe(document.body, {
childList: true,
subtree: true
});
}
Mermaid 圖表範例
以下是可透過此擴充功能渲染的圖表範例:
流程圖
graph TD
A[開始] --> B{是否安裝擴充功能?}
B -- 是 --> C[顯示圖表]
B -- 否 --> D[顯示原始碼]
C --> E[啟用放大鏡功能]
D --> F[安裝擴充功能]
F --> B
E --> G[結束]
時序圖
sequenceDiagram
participant User
participant Extension
participant ChatGPT
participant MermaidInk
User->>ChatGPT: 請求包含圖表的回應
ChatGPT->>User: 返回包含Mermaid代碼的回應
Extension->>Extension: 檢測Mermaid代碼塊
Extension->>MermaidInk: 發送壓縮後的代碼
MermaidInk->>Extension: 返回渲染的圖片URL
Extension->>User: 顯示圖表及放大鏡功能
使用限制
- 僅支援 ChatGPT 網站 (chatgpt.com 及其子域名)
- 需依賴 mermaid.ink 服務進行圖表渲染,無法離線使用
- 放大鏡功能僅適用於已渲染的圖表
- 不支援交互式圖表功能
- 受限於 manifest v3 的網頁資源限制
常見問題排除
圖表無法顯示
- 檢查網路連接是否正常
- 確認 mermaid.ink 服務是否可用
- 檢查 Mermaid 語法是否正確
放大鏡功能無效
- 重新點擊圖表啟用放大功能
- 刷新頁面後重試
- 檢查瀏覽器擴充功能權限
圖表顯示錯誤
- 點擊「在編輯器中開啟」按鈕檢查語法
- 調整 Mermaid 語法後重新渲染
後續開發方向
- 增加離線渲染支援,減少對 mermaid.ink 的依賴
- 提供更多自定義選項,如圖表主題、顏色和字體大小
- 支援更多網站和平台,如 Gmail、Google Docs 等
- 優化圖表樣式和主題,提供暗色模式支援
- 添加本地圖表儲存和匯出功能
- 整合更多圖表類型和進階功能
- 提供圖表編輯歷史記錄功能
相關資源
0
Subscribe to my newsletter
Read articles from Aldo Yang directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
