Conversation
依照 SIDEPANEL_UI_SPLIT_SPEC.md 規格,將 sidepanel.js(~991 行)
重構為兩個職責單一的模組。
新增檔案:
- sidepanel/sidepanelUI.js: 純 DOM 操作 UI 模組,不依賴 Chrome API
- 提供 getElements() 集中管理 DOM 元素快取
- 匯出 12 個 UI 純函數(showLoading/showEmpty/renderList 等)
- 提取 COLOR_MAP、PAGE_BATCH_SIZE 等模組級常數
- appendCards() 改為資料導向 API,回傳 {renderedCount, hasMore}
- showMessage/hideMessage 拆分,移除內部 timer 管理
修改檔案:
- sidepanel/sidepanel.js: 入口文件簡化為業務邏輯協調層
- 新增 showTimedMessage() 統一 statusMessageTimeoutId 管理
- 新增 refreshUnsyncedBadge() 統一 badge 資料抓取流程
- 新增 appendNextUnsyncedBatch() 統一分頁狀態協調
- handleViewTabClick 拆分 UI.switchView 與業務回調
- updateUnsyncedBadge 改為同步,資料由呼叫端傳入
- tests/unit/sidepanel/sidepanelUI.test.js: 新增 UI 層單元測試
- 28 個純 UI 測試,不需要 mock Chrome API
- 覆蓋所有導出函數的 DOM 行為驗證
驗證:
- 全量測試:3458/3458 通過(143 個套件)
- ESLint:0 errors, 0 new warnings
將 appendNextUnsyncedBatch 內的 onOpen 和 onDelete 回調改為使用 block functions,並加上 .catch(),避免隱式返回 Promise 導致的 linter 警告。
修正 sidepanelUI.test.js 中 IDE/linter 顯示的 'Move function \'makePage\' to the outer scope.' 警告, 避免在 describe 區塊內宣告函數影響作用域範圍。
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 本次變更主要針對 sidepanel 進行了架構重構,將原本耦合在入口文件中的 UI 渲染邏輯抽離至獨立的 UI 模組。此舉不僅簡化了業務邏輯的入口文件,還透過將 UI 函數改寫為純函數,大幅提升了 UI 元件的可測試性。同時,透過新增單元測試,確保了介面渲染與狀態切換的穩定性。 Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
| if (els.loadMoreBtn) { | ||
| els.loadMoreBtn.style.display = result.hasMore ? 'block' : 'none'; | ||
| } |
- 修改 appendCards 函數,將返回值從包含 renderedCount 和 hasMore 的物件改為僅返回 renderedCount。 - 在 sidepanel.js 中更新 appendNextUnsyncedBatch 函數,使用新的返回值並更新 loadMoreBtn 的顯示邏輯。 - 更新單元測試以反映這些變更,檢查 loadMoreBtn 的顯示狀態而非 hasMore 屬性。
當 viewTabs 屬性未定義時,isCurrentViewActive 現在會返回預設值 true,而不再讀取全域 DOM。這樣的改動提高了函數的穩定性和可測試性。
|
Kilo Code Review could not run — your account is out of credits. Add credits or switch to a free model to enable reviews on this change. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough本次变更将侧面板的 DOM/呈现逻辑提取到新模块 序列图sequenceDiagram
participant Sidepanel as Sidepanel 控制器
participant UI as sidepanelUI 模块
participant Storage as Storage (chrome.storage)
participant Chrome as Chrome Tabs
participant Logger as Logger
Sidepanel->>UI: getElements()
UI-->>Sidepanel: elements
Sidepanel->>UI: switchView(viewName)
UI-->>Sidepanel: view 切换完成
Sidepanel->>Storage: getUnsyncedPages()
Storage-->>Sidepanel: pages[]
Sidepanel->>UI: appendCards(pages, start, count, callbacks)
UI-->>Sidepanel: renderedCount
Sidepanel->>Chrome: chrome.tabs.create({url})
alt 打开成功
Chrome-->>Sidepanel: tab
else 打开失败
Chrome-->>Sidepanel: error
Sidepanel->>Logger: warn("[SidePanel] open unsynced failed", sanitize...)
end
Sidepanel->>Storage: deleteUnsyncedPage(storageKey)
alt 删除成功
Storage-->>Sidepanel: ok
else 删除失败
Storage-->>Sidepanel: error
Sidepanel->>Logger: error("[SidePanel] delete unsynced failed", sanitize...)
end
Sidepanel->>UI: showTimedMessage(text, type)
UI-->>Sidepanel: showMessage / hideMessage
估计代码审查工作量🎯 3 (Moderate) | ⏱️ ~25 minutes 可能相关的 PRs
建议标签
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@sidepanel/sidepanel.js`:
- Line 35: PAGE_BATCH_SIZE is just an alias for UI.PAGE_BATCH_SIZE; remove the
redundant constant declaration (const PAGE_BATCH_SIZE = UI.PAGE_BATCH_SIZE) and
update all uses of PAGE_BATCH_SIZE to reference UI.PAGE_BATCH_SIZE instead, or
if you prefer a centralized constant, move the value into a dedicated constants
module (e.g., export PAGE_BATCH_SIZE from a constants file) and import that
where needed; change references in sidepanel.js to use the chosen source
(UI.PAGE_BATCH_SIZE or the new constants export) and remove the old alias
declaration.
- Around line 53-59: The hard-coded 3000ms in showTimedMessage is a magic
number; extract it to a constant (e.g., MESSAGE_DISPLAY_DURATION_MS) in the
UI/constants module (suggested export in sidepanelUI.js) and replace the literal
in showTimedMessage with that constant; update any imports so sidepanel.js
imports MESSAGE_DISPLAY_DURATION_MS and uses it in the setTimeout call to
improve maintainability.
- Around line 77-88: The empty .catch handlers in appendNextUnsyncedBatch
silently swallow errors from chrome.tabs.create and deleteUnsyncedPage; update
the onOpen and onDelete callbacks passed to UI.appendCards to handle rejections
by logging a warning (e.g., console.warn or the repo's logger) including the
error and contextual info (URL for chrome.tabs.create, storageKey/card for
deleteUnsyncedPage) while preserving existing behavior, so failures are visible
for debugging without changing the success flow.
- Around line 624-627: The anonymous empty catch in the timer callback silently
swallows errors from refreshUnsyncedBadge; update the callback so
refreshUnsyncedBadge().catch(...) logs the caught error (including context like
"refreshUnsyncedBadge failed" and the error object) instead of doing nothing so
failures are visible; locate the timer block using unsyncedBadgeTimer and the
call to refreshUnsyncedBadge and replace the empty catch with a call to your
logger/console.error that includes the error details.
In `@sidepanel/sidepanelUI.js`:
- Around line 317-351: The current appendCards loop assumes template content
contains elements like '.page-title', '.page-meta', '.page-card-previews',
'.page-card-remaining', '.page-open-button' and '.page-delete-button' and will
throw TypeError if any are missing; update the loop in sidepanelUI.js to perform
defensive null checks after cloning (e.g., const titleEl =
card.querySelector('.page-title'); if (titleEl) titleEl.textContent =
page.title) for each queried element, only append preview rows when
'.page-card-previews' exists, only set remainingEl.textContent when remainingEl
is non-null, and only attach event listeners when the button elements exist
(guarding callbacks.onOpen and callbacks.onDelete usage); keep existing logic
and messages (extractDomain, UI_MESSAGES.SIDEPANEL.HIGHLIGHT_COUNT) but add
these presence checks to prevent runtime TypeError.
In `@tests/unit/sidepanel/sidepanelUI.test.js`:
- Around line 44-48: The fixture contains duplicate ID "unsynced-badge" which
breaks uniqueness and makes querySelector('#unsynced-badge') return the wrong
element; update the test fixture in tests/unit/sidepanel/sidepanelUI.test.js so
only one element has id="unsynced-badge" (e.g., remove the id from the
standalone <span id="unsynced-badge"> or change the second occurrence inside the
button to a class like class="unsynced-badge"), then ensure the tests that call
updateUnsyncedBadge and use document.querySelector('#unsynced-badge') still
target the intended element.
- Around line 84-88: Add an afterEach cleanup to the sidepanelUI test suite:
inside the describe('sidepanelUI', ...) add an afterEach that calls
jest.clearAllMocks() and restores/cleans global.chrome (e.g., delete
global.chrome) to prevent test pollution; locate the existing beforeEach that
calls buildDOM() and add the afterEach adjacent to it so mocks and any global
chrome stubs are cleared between tests.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 620e6b1a-d363-484c-b4aa-6dc33a2683fb
⛔ Files ignored due to path filters (1)
coverage/jest/lcov.infois excluded by!coverage/**
📒 Files selected for processing (3)
sidepanel/sidepanel.jssidepanel/sidepanelUI.jstests/unit/sidepanel/sidepanelUI.test.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
此專案為 Chrome Extension (Manifest V3),必須使用 Vanilla JavaScript (ES6+ Modules) 作為核心語言,CommonJS 用於 Node 腳本。
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
**/*.test.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Files:
tests/unit/sidepanel/sidepanelUI.test.js
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
禁止使用 TypeScript(除非明確要求)、React、Vue、Webpack。
Do not use console.log() statements in production code
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
Use Traditional Chinese (zh-TW) for all code comments, documentation, and string content, with strict enforcement except for technical terms and variable names
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}: Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Use a dedicated constants module for defining and exporting all constant values
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/security_rules.json)
**/*.{js,ts,jsx,tsx}: Force strict whitelisting for file downloads: appended files must be restricted to '.json' or '.txt' extensions with explicitly designated MIME types. Never use arbitrary user input for filenames to prevent Reflected File Download (RFD) attacks.
Always prefertextContentfor DOM operations. If SVG mixed content requires text updates, find the TEXT_NODE and update itstextContentrather than usinginnerHTMLon the parent.
Rely onLogSanitizerto strip sensitive properties (likesender,tab, PII) before emitting logs in production.Follow the project's ESLint configuration and do not emit DeepSource (skipcq) comments.
**/*.{js,ts,jsx,tsx}: Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Reject PR if introducing new core business logic without corresponding unit or E2E tests. Require TDD and ensure Codecov checks do not fail (< 50%).
Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{ts,tsx,js,jsx}: Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Use Logger.start(msg, ctx?) for process launch notifications in Notion Chrome Extension. Output prefix: [INFO] 🚀. The Logger class auto-manages the emoji icon.
Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Use Logger.info(msg, ctx?) for general informational messages in Notion Chrome Extension. Output prefix: [INFO]. No auto-managed emoji icon.
Use Logger.debug(msg, ctx?) for development debugging in Notion Chrome Extension. Output prefix: [DEBUG]. Controlled by enableDebugLogs switch.
Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN]⚠️ . The Logger class auto-manages the emoji icon.
Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Do NOT manually insert emoji icons (✅, 🚀, 📦,⚠️ , ❌) into log messages. The Logger class auto-manages these icons. Only manually use special semantic emoji like 🔍 (search) or 🗑️ (delete) when needed for semantic clarity.
Use 'action' field in Logger context to record public API function names (e.g., 'loadHighlights', 'savePage') for structured logging in Notion Chrome Extension.
Use 'operation' field in Logger context to record internal operation steps (e.g., 'parseLocalStorage', 'buildUrl') for structured logging in Notion Chrome Extension.
Use 'phase' field in Logger context (optional) to record execution stages (e.g., 'validation', 'apiCall') for structured logging in Notion Chrome Extension.
Use 'result' field in Logger context to record operation results (e.g., 'blocked', 'success', 'failed') for structured logging in Notion Chr...
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{test,spec}.{ts,tsx,js,jsx}: Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Files:
tests/unit/sidepanel/sidepanelUI.test.js
**/*.{test,spec}.{js,ts}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/testing_rules.json)
**/*.{test,spec}.{js,ts}: Always reference data structures (HTML snippets, Notion JSON responses) from .agents/.shared/references/ instead of hardcoding large payloads in test files.
Use .agents/.shared/references/notion_api/ for Notion block structures and database properties in test fixtures.
Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Files:
tests/unit/sidepanel/sidepanelUI.test.js
**/*.{js,ts,jsx,tsx,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/code_review_rules.json)
Maintain code comments and documentation in Traditional Chinese.
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
**/*
⚙️ CodeRabbit configuration file
**/*: # Project Specific Guidelines
- Language: All user-facing UI text, strings, and messages MUST be in Traditional Chinese (zh-TW).
- Architecture: Follow the defined storage structures and specs. Do not introduce unauthorized storage fields.
- Code Quality: Avoid N+1 issues, blocking operations, and ensure high code quality. Suggest optimizations that follow modern JavaScript/Chrome Extension best practices.
Files:
tests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanel.jssidepanel/sidepanelUI.js
🧠 Learnings (23)
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Always reference data structures (HTML snippets, Notion JSON responses) from .agents/.shared/references/ instead of hardcoding large payloads in test files.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if introducing new core business logic without corresponding unit or E2E tests. Require TDD and ensure Codecov checks do not fail (< 50%).
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Use .agents/.shared/references/notion_api/ for Notion block structures and database properties in test fixtures.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.test.js : 單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.spec.js : E2E 與整合測試使用 Playwright。
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.js : 此專案為 Chrome Extension (Manifest V3),必須使用 Vanilla JavaScript (ES6+ Modules) 作為核心語言,CommonJS 用於 Node 腳本。
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `page_{stableUrl}` key pattern to store unified page state containing Notion metadata and highlights in chrome.storage.local, with fields: notion (object | null), highlights (array), and metadata (object)
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, inspect local storage using 'chrome.storage.local.get(['highlights_${url}'])' and compare stored URL with current URL using normalizeUrl(window.location.href).
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When investigating highlight recovery failures in Notion Chrome Extension, verify URL consistency between stored highlights and current page, check for text content mutations on the source page, and confirm CSS Highlight API support exists.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store highlight content sync style in `highlightContentStyle` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store title template for saved pages in `titleTemplate` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, verify initialization completion by checking for '[INFO] ✅ 初始化完成' log message from Logger.success('初始化完成', { action: 'initialize' }) call.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : syncHighlights action must handle remote page deletion detection by returning PAGE_DELETION_PENDING status without clearing the Notion binding on first detection, and only return PAGE_DELETED and clear the binding after confirmation-window reoccurrence
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : CLEAR_HIGHLIGHTS action must clear local highlights through the canonical Background storage path and perform best-effort visual cleanup on the page
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Performance target for highlight sync in Notion Chrome Extension: < 500ms.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting functionality in Notion Chrome Extension, verify CSS.highlights API support by running 'highlights' in CSS in the target website's DevTools console.
Applied to files:
sidepanel/sidepanel.js
🔇 Additional comments (6)
tests/unit/sidepanel/sidepanelUI.test.js (2)
1-6: 測試結構良好,涵蓋了 UI 模組的主要功能測試涵蓋了所有導出的 UI 函數,包括工具函數、狀態切換、列表渲染和待同步視圖管理。測試邏輯清晰,使用 Traditional Chinese 註解符合專案規範。
49-65: 測試 fixture 的 template 結構與正式環境 HTML 結構不一致,但不影響測試可信度雖然正式 HTML (
sidepanel/sidepanel.html) 中的#highlight-card-template和#page-card-template確實包含嵌套包裝層(.highlight-content、.page-card-header、.page-title-row等),但查驗實際代碼後發現:
sidepanelUI.js使用的選擇器只針對特定類名:querySelector('.page-title')、querySelector('.page-meta')等- 代碼不依賴嵌套結構進行 DOM 遍歷
- 嵌套包裝層僅用於 CSS 樣式和佈局,不涉及 JavaScript 邏輯
測試 fixture 的扁平結構在功能上等價於正式環境,只要包含代碼實際查詢的類名,測試就能正確運行。此結構差異不會降低測試可信度。
sidepanel/sidepanel.js (1)
22-23: UI 模組分層重構結構良好將 UI 渲染邏輯抽取至
sidepanelUI.js,業務邏輯保留在sidepanel.js,提升了可測試性和可維護性。showTimedMessage、refreshUnsyncedBadge、appendNextUnsyncedBatch等協調層函數清晰地界定了兩層之間的職責。sidepanel/sidepanelUI.js (3)
99-108:buildPreviewHighlights防禦性檢查良好函數正確處理了
hl.text可能為非字串的情況,並提供'yellow'作為預設顏色。這種防禦性編程風格值得肯定。
1-9: UI 模組設計符合單一職責原則模組清楚地將 DOM 操作與業務邏輯分離,所有函數都是純 UI 操作,不依賴 Chrome API,便於單元測試。JSDoc 型別定義完整,有助於開發者理解介面契約。
57-75: 所有必要的 DOM 元素均已存在於 sidepanel.html 中驗證結果確認
getElements()中查詢的所有 15 個元素(#loading-state、#empty-state、#highlights-list 等)都存在於 sidepanel.html。因此 querySelector 返回 null 導致 TypeError 的情況不會發生。
- 在 sidepanel.js 中引入 sanitizeUrlForLogging 函數以增強日誌安全性 - 將 UI.MESSAGE_DISPLAY_DURATION_MS 用於顯示訊息的持續時間 - 在 appendNextUnsyncedBatch 函數中添加錯誤處理,並記錄相關錯誤 - 在 sidepanelUI.js 中修正卡片模板的元素選擇器,避免拋出錯誤 - 增加單元測試以確保在缺少可選元素時不會拋出錯誤
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@sidepanel/sidepanel.js`:
- Around line 85-92: The warning currently logs the raw storageKey (which
contains a full stable URL); remove storageKey from the Logger.warn context and
instead log a non-URL identifier such as page?.id or a key-type field (e.g.,
storageKeyType or storageKeyId) derived from cachedUnsyncedPages; keep the
sanitized URL via sanitizeUrlForLogging(page?.url) and include the caught error,
but never emit the full storageKey/URL in Logger.warn inside onDelete (refer to
onDelete, deleteUnsyncedPage, Logger.warn, cachedUnsyncedPages,
sanitizeUrlForLogging).
- Around line 252-253: Both call sites await
refreshUnsyncedBadge()/renderUnsyncedView without handling rejection, so
failures (e.g., chrome.storage.local.get rejecting) leave unhandled promise
rejections and an inconsistent UI; wrap the async entry points (the calls to
loadCurrentTab(); refreshUnsyncedBadge(); and the tab-switch path that calls
renderUnsyncedView()) in try/catch blocks that log the error via the existing
logging utility and set a safe fallback UI state, and ensure
refreshUnsyncedBadge and renderUnsyncedView themselves return a settled promise
on error (reject -> handled) so callers never leak unhandled rejections—apply
the same pattern to the other occurrence around the renderUnsyncedView flow
referenced (lines ~665–673).
In `@tests/unit/sidepanel/sidepanel.test.js`:
- Around line 19-24: The Logger mock only defines warn and error causing
failures if sidepanel.js calls other methods; update the jest.mock for Logger
(the default export mock) to include the full interface: success, start, ready,
info, debug in addition to warn and error, each set to jest.fn(), so tests that
invoke Logger.success/start/ready/info/debug will not fail due to missing
methods.
In `@tests/unit/sidepanel/sidepanelUI.test.js`:
- Around line 7-23: Add an explicit import for Jest globals by importing "jest"
from "@jest/globals" at the top of the test file so calls like jest.fn(),
jest.clearAllMocks(), etc. are unambiguous; update the top of
tests/unit/sidepanel/sidepanelUI.test.js to include the import statement
(matching the pattern used in sidepanel.test.js) and ensure existing usages of
jest.* remain unchanged but now reference the imported symbol.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0c2f10f9-60bf-4dd2-94fb-4e92b2eb135b
📒 Files selected for processing (4)
sidepanel/sidepanel.jssidepanel/sidepanelUI.jstests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
此專案為 Chrome Extension (Manifest V3),必須使用 Vanilla JavaScript (ES6+ Modules) 作為核心語言,CommonJS 用於 Node 腳本。
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
**/*.test.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
禁止使用 TypeScript(除非明確要求)、React、Vue、Webpack。
Do not use console.log() statements in production code
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
Use Traditional Chinese (zh-TW) for all code comments, documentation, and string content, with strict enforcement except for technical terms and variable names
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}: Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Use a dedicated constants module for defining and exporting all constant values
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/security_rules.json)
**/*.{js,ts,jsx,tsx}: Force strict whitelisting for file downloads: appended files must be restricted to '.json' or '.txt' extensions with explicitly designated MIME types. Never use arbitrary user input for filenames to prevent Reflected File Download (RFD) attacks.
Always prefertextContentfor DOM operations. If SVG mixed content requires text updates, find the TEXT_NODE and update itstextContentrather than usinginnerHTMLon the parent.
Rely onLogSanitizerto strip sensitive properties (likesender,tab, PII) before emitting logs in production.Follow the project's ESLint configuration and do not emit DeepSource (skipcq) comments.
**/*.{js,ts,jsx,tsx}: Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Reject PR if introducing new core business logic without corresponding unit or E2E tests. Require TDD and ensure Codecov checks do not fail (< 50%).
Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{ts,tsx,js,jsx}: Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Use Logger.start(msg, ctx?) for process launch notifications in Notion Chrome Extension. Output prefix: [INFO] 🚀. The Logger class auto-manages the emoji icon.
Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Use Logger.info(msg, ctx?) for general informational messages in Notion Chrome Extension. Output prefix: [INFO]. No auto-managed emoji icon.
Use Logger.debug(msg, ctx?) for development debugging in Notion Chrome Extension. Output prefix: [DEBUG]. Controlled by enableDebugLogs switch.
Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN]⚠️ . The Logger class auto-manages the emoji icon.
Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Do NOT manually insert emoji icons (✅, 🚀, 📦,⚠️ , ❌) into log messages. The Logger class auto-manages these icons. Only manually use special semantic emoji like 🔍 (search) or 🗑️ (delete) when needed for semantic clarity.
Use 'action' field in Logger context to record public API function names (e.g., 'loadHighlights', 'savePage') for structured logging in Notion Chrome Extension.
Use 'operation' field in Logger context to record internal operation steps (e.g., 'parseLocalStorage', 'buildUrl') for structured logging in Notion Chrome Extension.
Use 'phase' field in Logger context (optional) to record execution stages (e.g., 'validation', 'apiCall') for structured logging in Notion Chrome Extension.
Use 'result' field in Logger context to record operation results (e.g., 'blocked', 'success', 'failed') for structured logging in Notion Chr...
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{test,spec}.{ts,tsx,js,jsx}: Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
**/*.{test,spec}.{js,ts}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/testing_rules.json)
**/*.{test,spec}.{js,ts}: Always reference data structures (HTML snippets, Notion JSON responses) from .agents/.shared/references/ instead of hardcoding large payloads in test files.
Use .agents/.shared/references/notion_api/ for Notion block structures and database properties in test fixtures.
Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
**/*.{js,ts,jsx,tsx,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/code_review_rules.json)
Maintain code comments and documentation in Traditional Chinese.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
**/*
⚙️ CodeRabbit configuration file
**/*: # Project Specific Guidelines
- Language: All user-facing UI text, strings, and messages MUST be in Traditional Chinese (zh-TW).
- Architecture: Follow the defined storage structures and specs. Do not introduce unauthorized storage fields.
- Code Quality: Avoid N+1 issues, blocking operations, and ensure high code quality. Suggest optimizations that follow modern JavaScript/Chrome Extension best practices.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.jstests/unit/sidepanel/sidepanelUI.test.jssidepanel/sidepanelUI.js
🧠 Learnings (39)
📓 Common learnings
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: 修改檔案時,若重構現有程式碼(不新增功能也不修復 bug),Commit Message 類型應使用 `refactor`。
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/{storage,migration,highlight}/**/*.{js,ts} : Achieve 90%+ code coverage for Storage, Migration, and Highlighting algorithms in unit tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.test.js : 單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jstests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.start(msg, ctx?) for process launch notifications in Notion Chrome Extension. Output prefix: [INFO] 🚀. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, verify initialization completion by checking for '[INFO] ✅ 初始化完成' log message from Logger.success('初始化完成', { action: 'initialize' }) call.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN] ⚠️. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use 'action' field in Logger context to record public API function names (e.g., 'loadHighlights', 'savePage') for structured logging in Notion Chrome Extension.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, inspect local storage using 'chrome.storage.local.get(['highlights_${url}'])' and compare stored URL with current URL using normalizeUrl(window.location.href).
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to tests/e2e/specs/**/*.spec.{js,ts} : Do NOT use direct injection in e2e tests when testing Background Worker message routing logic. Instead, mock chrome.runtime.sendMessage.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-03T12:36:42.667Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/linter_rules.json:0-0
Timestamp: 2026-03-03T12:36:42.667Z
Learning: Applies to **/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php} : Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging background service worker save failures in Notion Chrome Extension, check for API 400/500 status codes and look for batch processing logs like '[INFO] [NotionService] 準備分批添加區塊'.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Log only necessary IDs and sanitized error messages in Notion Chrome Extension. Follow security best practices documented in docs/guides/SECURITY_BEST_PRACTICES.md.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : syncHighlights action must handle remote page deletion detection by returning PAGE_DELETION_PENDING status without clearing the Notion binding on first detection, and only return PAGE_DELETED and clear the binding after confirmation-window reoccurrence
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Do NOT log complete sender/tab objects, user content (title, highlight text), Schema structure (properties), or PII (email) in Notion Chrome Extension logs for security reasons.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `page_{stableUrl}` key pattern to store unified page state containing Notion metadata and highlights in chrome.storage.local, with fields: notion (object | null), highlights (array), and metadata (object)
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When investigating highlight recovery failures in Notion Chrome Extension, verify URL consistency between stored highlights and current page, check for text content mutations on the source page, and confirm CSS Highlight API support exists.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store highlight content sync style in `highlightContentStyle` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store title template for saved pages in `titleTemplate` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : CLEAR_HIGHLIGHTS action must clear local highlights through the canonical Background storage path and perform best-effort visual cleanup on the page
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Performance target for highlight sync in Notion Chrome Extension: < 500ms.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting functionality in Notion Chrome Extension, verify CSS.highlights API support by running 'highlights' in CSS in the target website's DevTools console.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Always reference data structures (HTML snippets, Notion JSON responses) from .agents/.shared/references/ instead of hardcoding large payloads in test files.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Use .agents/.shared/references/notion_api/ for Notion block structures and database properties in test fixtures.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to tests/e2e/specs/**/*.spec.{js,ts} : Reference tests/e2e/specs/highlight.spec.js and use serviceWorker.evaluate for direct injection testing in e2e tests.
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.spec.js : E2E 與整合測試使用 Playwright。
Applied to files:
tests/unit/sidepanel/sidepanelUI.test.js
| jest.mock('../../../scripts/utils/Logger.js', () => ({ | ||
| __esModule: true, | ||
| default: { | ||
| warn: jest.fn(), | ||
| error: jest.fn(), | ||
| }, |
There was a problem hiding this comment.
補齊 Logger mock 介面。
這裡只定義了 warn / error。如果 sidepanel.js 在初始化或後續重構時呼叫 success、start、ready、info 或 debug,這個 suite 會直接因為 mock 缺方法而失敗;既然這是共用 mock,建議一次補齊完整介面。
♻️ 建議修正
jest.mock('../../../scripts/utils/Logger.js', () => ({
__esModule: true,
default: {
+ success: jest.fn(),
+ start: jest.fn(),
+ ready: jest.fn(),
+ info: jest.fn(),
+ debug: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
},
}));Based on learnings: "When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/unit/sidepanel/sidepanel.test.js` around lines 19 - 24, The Logger mock
only defines warn and error causing failures if sidepanel.js calls other
methods; update the jest.mock for Logger (the default export mock) to include
the full interface: success, start, ready, info, debug in addition to warn and
error, each set to jest.fn(), so tests that invoke
Logger.success/start/ready/info/debug will not fail due to missing methods.
- 新增 getStorageKeyType 函數以壓縮 storage key。 - 改進 renderUnsyncedFallbackState 函數以顯示安全的 UI 狀態。 - 更新 refreshUnsyncedBadge 函數以處理錯誤並記錄日誌。 - 增強 renderUnsyncedView 函數的錯誤處理,並在失敗時顯示回退狀態。 - 更新單元測試以涵蓋新的錯誤處理邏輯。
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Overview
Files Reviewed
Reviewed by grok-code-fast-1:optimized:free · 57,316 tokens |
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
tests/unit/sidepanel/sidepanel.test.js (1)
19-25:⚠️ Potential issue | 🟡 Minor補齊
Loggermock 介面,避免共用測試替身過度脆弱。這個 suite 現在只 mock
warn/error。只要sidepanel.js或被它 import 的模組在初始化時改呼叫success、start、ready、info或debug,整個測試檔就會因為缺方法直接失敗;既然這是共用 mock,建議一次補齊完整介面。♻️ 建議補齊 mock
jest.mock('../../../scripts/utils/Logger.js', () => ({ __esModule: true, default: { + success: jest.fn(), + start: jest.fn(), + ready: jest.fn(), + info: jest.fn(), + debug: jest.fn(), warn: jest.fn(), error: jest.fn(), }, }));Based on learnings: "When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/sidepanel/sidepanel.test.js` around lines 19 - 25, The Logger mock in the test only defines warn and error which makes the shared test double brittle; update the jest.mock for '../../../scripts/utils/Logger.js' (the default export mock) to include the full interface by adding jest.fn() stubs for success, start, ready, info, and debug in addition to warn and error so any module initialization calls to Logger.success/ start/ ready/ info/ debug won't break tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@sidepanel/sidepanel.js`:
- Around line 619-625: The code is currently passing raw response.error into
showTimedMessage (from the chrome.runtime.sendMessage handlers for actions like
'savePage' and 'openNotionPage'), which exposes internal error details to the
UI; change the handlers to never display raw error text — instead map failure
cases to existing zh-TW UI_MESSAGES (e.g., UI_MESSAGES.SIDEPANEL.SYNC_FAILED) or
run the response through the existing user-message formatter before calling
showTimedMessage, and send the raw response.error only to logging (console.error
or the app logger) for debugging; update both the block handling savePage and
the similar block handling openNotionPage to follow this pattern and keep
success paths using UI_MESSAGES.SIDEPANEL.SYNC_SUCCESS.
- Around line 710-721: The tab-switch flow in handleViewTabClick calls
UI.switchView(...) then fire-and-forget async renderUnsyncedView(...) /
loadCurrentTab(...) without guarding against stale results; modify
renderUnsyncedView and loadCurrentTab (and any helper that calls
getUnsyncedPages()) to use an incrementing render token or check an activeView
identifier before applying DOM changes (e.g., compare a module-level
currentActiveView or renderId captured at call start) and early-return if it no
longer matches, and ensure UI.switchView updates that active marker; also add a
regression test that rapidly toggles current ↔ unsynced and asserts that
unsyncedToolbar/loadMoreBtn state only reflects the currently active tab.
---
Duplicate comments:
In `@tests/unit/sidepanel/sidepanel.test.js`:
- Around line 19-25: The Logger mock in the test only defines warn and error
which makes the shared test double brittle; update the jest.mock for
'../../../scripts/utils/Logger.js' (the default export mock) to include the full
interface by adding jest.fn() stubs for success, start, ready, info, and debug
in addition to warn and error so any module initialization calls to
Logger.success/ start/ ready/ info/ debug won't break tests.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: c4559963-0f26-49df-97e9-966ae1a0e1fd
📒 Files selected for processing (2)
sidepanel/sidepanel.jstests/unit/sidepanel/sidepanel.test.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
此專案為 Chrome Extension (Manifest V3),必須使用 Vanilla JavaScript (ES6+ Modules) 作為核心語言,CommonJS 用於 Node 腳本。
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.test.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
禁止使用 TypeScript(除非明確要求)、React、Vue、Webpack。
Do not use console.log() statements in production code
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
Use Traditional Chinese (zh-TW) for all code comments, documentation, and string content, with strict enforcement except for technical terms and variable names
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}: Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Use a dedicated constants module for defining and exporting all constant values
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/security_rules.json)
**/*.{js,ts,jsx,tsx}: Force strict whitelisting for file downloads: appended files must be restricted to '.json' or '.txt' extensions with explicitly designated MIME types. Never use arbitrary user input for filenames to prevent Reflected File Download (RFD) attacks.
Always prefertextContentfor DOM operations. If SVG mixed content requires text updates, find the TEXT_NODE and update itstextContentrather than usinginnerHTMLon the parent.
Rely onLogSanitizerto strip sensitive properties (likesender,tab, PII) before emitting logs in production.Follow the project's ESLint configuration and do not emit DeepSource (skipcq) comments.
**/*.{js,ts,jsx,tsx}: Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Reject PR if introducing new core business logic without corresponding unit or E2E tests. Require TDD and ensure Codecov checks do not fail (< 50%).
Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{ts,tsx,js,jsx}: Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Use Logger.start(msg, ctx?) for process launch notifications in Notion Chrome Extension. Output prefix: [INFO] 🚀. The Logger class auto-manages the emoji icon.
Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Use Logger.info(msg, ctx?) for general informational messages in Notion Chrome Extension. Output prefix: [INFO]. No auto-managed emoji icon.
Use Logger.debug(msg, ctx?) for development debugging in Notion Chrome Extension. Output prefix: [DEBUG]. Controlled by enableDebugLogs switch.
Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN]⚠️ . The Logger class auto-manages the emoji icon.
Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Do NOT manually insert emoji icons (✅, 🚀, 📦,⚠️ , ❌) into log messages. The Logger class auto-manages these icons. Only manually use special semantic emoji like 🔍 (search) or 🗑️ (delete) when needed for semantic clarity.
Use 'action' field in Logger context to record public API function names (e.g., 'loadHighlights', 'savePage') for structured logging in Notion Chrome Extension.
Use 'operation' field in Logger context to record internal operation steps (e.g., 'parseLocalStorage', 'buildUrl') for structured logging in Notion Chrome Extension.
Use 'phase' field in Logger context (optional) to record execution stages (e.g., 'validation', 'apiCall') for structured logging in Notion Chrome Extension.
Use 'result' field in Logger context to record operation results (e.g., 'blocked', 'success', 'failed') for structured logging in Notion Chr...
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{test,spec}.{ts,tsx,js,jsx}: Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{test,spec}.{js,ts}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/testing_rules.json)
**/*.{test,spec}.{js,ts}: Always reference data structures (HTML snippets, Notion JSON responses) from .agents/.shared/references/ instead of hardcoding large payloads in test files.
Use .agents/.shared/references/notion_api/ for Notion block structures and database properties in test fixtures.
Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{js,ts,jsx,tsx,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/code_review_rules.json)
Maintain code comments and documentation in Traditional Chinese.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*
⚙️ CodeRabbit configuration file
**/*: # Project Specific Guidelines
- Language: All user-facing UI text, strings, and messages MUST be in Traditional Chinese (zh-TW).
- Architecture: Follow the defined storage structures and specs. Do not introduce unauthorized storage fields.
- Code Quality: Avoid N+1 issues, blocking operations, and ensure high code quality. Suggest optimizations that follow modern JavaScript/Chrome Extension best practices.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
🧠 Learnings (38)
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/{storage,migration,highlight}/**/*.{js,ts} : Achieve 90%+ code coverage for Storage, Migration, and Highlighting algorithms in unit tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.test.js : 單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN] ⚠️. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, verify initialization completion by checking for '[INFO] ✅ 初始化完成' log message from Logger.success('初始化完成', { action: 'initialize' }) call.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.start(msg, ctx?) for process launch notifications in Notion Chrome Extension. Output prefix: [INFO] 🚀. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use 'action' field in Logger context to record public API function names (e.g., 'loadHighlights', 'savePage') for structured logging in Notion Chrome Extension.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, inspect local storage using 'chrome.storage.local.get(['highlights_${url}'])' and compare stored URL with current URL using normalizeUrl(window.location.href).
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to tests/e2e/specs/**/*.spec.{js,ts} : Do NOT use direct injection in e2e tests when testing Background Worker message routing logic. Instead, mock chrome.runtime.sendMessage.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-03T12:36:42.667Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/linter_rules.json:0-0
Timestamp: 2026-03-03T12:36:42.667Z
Learning: Applies to **/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php} : Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Log only necessary IDs and sanitized error messages in Notion Chrome Extension. Follow security best practices documented in docs/guides/SECURITY_BEST_PRACTICES.md.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging background service worker save failures in Notion Chrome Extension, check for API 400/500 status codes and look for batch processing logs like '[INFO] [NotionService] 準備分批添加區塊'.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : syncHighlights action must handle remote page deletion detection by returning PAGE_DELETION_PENDING status without clearing the Notion binding on first detection, and only return PAGE_DELETED and clear the binding after confirmation-window reoccurrence
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Do NOT log complete sender/tab objects, user content (title, highlight text), Schema structure (properties), or PII (email) in Notion Chrome Extension logs for security reasons.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-03T12:37:10.274Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/security_rules.json:0-0
Timestamp: 2026-03-03T12:37:10.274Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Rely on `LogSanitizer` to strip sensitive properties (like `sender`, `tab`, PII) before emitting logs in production.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `page_{stableUrl}` key pattern to store unified page state containing Notion metadata and highlights in chrome.storage.local, with fields: notion (object | null), highlights (array), and metadata (object)
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `url_alias_{normalizedUrl}` key pattern to map original URLs to stable URLs in chrome.storage.local to handle async race conditions
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Do not treat low-risk, ephemeral, self-recovering internal state hygiene issues as must-fix findings. Re-evaluate real user impact, persistence scope, and recovery behavior. Downgrade to a note or acceptable technical debt only if it causes no durable data corruption, user-facing inconsistency, blocked actions, or expanding side effects. CRITICAL or security-related findings must not be downgraded without citing specific source lines and a concrete reproduction or validation scenario.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When investigating highlight recovery failures in Notion Chrome Extension, verify URL consistency between stored highlights and current page, check for text content mutations on the source page, and confirm CSS Highlight API support exists.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store highlight content sync style in `highlightContentStyle` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store title template for saved pages in `titleTemplate` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : CLEAR_HIGHLIGHTS action must clear local highlights through the canonical Background storage path and perform best-effort visual cleanup on the page
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Performance target for highlight sync in Notion Chrome Extension: < 500ms.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting functionality in Notion Chrome Extension, verify CSS.highlights API support by running 'highlights' in CSS in the target website's DevTools console.
Applied to files:
sidepanel/sidepanel.js
- 新增 setActiveView、beginCurrentViewRequest 和 beginUnsyncedViewRequest 函數以管理當前視圖的請求序號。 - 更新 loadCurrentTab 和 renderHighlightsForUrl 函數以支持請求序號,確保非同步請求的安全性。 - 修改測試以驗證錯誤訊息不再顯示原始的 API 錯誤,並使用 UI_MESSAGES 進行顯示。 - 增加測試以確保快速切換視圖時忽略過期的渲染結果。
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
sidepanel/sidepanel.js (1)
397-401:⚠️ Potential issue | 🔴 Critical過期 request 仍會覆寫共享快取。
這兩段都在
is*RequestActive()檢查前先更新共享 state。舊請求晚回來時,雖然不再改 DOM,仍會把cachedStableUrl/cachedTabUrl或cachedUnsyncedPages汙染成過期快照;後續handleStorageChange的 fast path、loadMoreCards()、deleteAllUnsyncedPages()都可能因此操作到錯的資料。🛠️ 建議修正
- const stableUrl = await getStableUrlForTab(tab.id, tab.url); - - // 快取 URL 供 handleStorageChange 快速路徑使用 - cachedStableUrl = stableUrl; - cachedTabUrl = tab.url; + const stableUrl = await getStableUrlForTab(tab.id, tab.url); + if (!isCurrentViewRequestActive(requestId)) { + return; + } + + // 快取 URL 供 handleStorageChange 快速路徑使用 + cachedStableUrl = stableUrl; + cachedTabUrl = tab.url; @@ - cachedUnsyncedPages = await getUnsyncedPages(); - if (!isUnsyncedViewRequestActive(requestId)) { + const pages = await getUnsyncedPages(); + if (!isUnsyncedViewRequestActive(requestId)) { return; } + cachedUnsyncedPages = pages;也建議補一個「快速切兩個 tab 後再觸發 storage change」與「較舊 unsynced request 晚回來」的回歸測試。
Also applies to: 817-820
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sidepanel/sidepanel.js` around lines 397 - 401, The shared cache (cachedStableUrl/cachedTabUrl and cachedUnsyncedPages) is being updated before checking whether the async request is still the active one, so stale/late responses can overwrite the cache; fix by only writing to those shared variables after verifying the request is still active (use the existing is*RequestActive() check or a requestId/token captured before calling getStableUrlForTab()/the unsynced pages fetch and re-check it after await). Specifically, in the getStableUrlForTab flow (surrounding cachedStableUrl and cachedTabUrl) and the unsynced-pages fetch flow (cachedUnsyncedPages) capture a local request identifier or call is*RequestActive() after the await and only then update the shared cache; apply the same guard to the other occurrence noted (around lines 817-820) so handleStorageChange, loadMoreCards(), and deleteAllUnsyncedPages() won’t operate on stale snapshots.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@sidepanel/sidepanel.js`:
- Around line 21-23: The review requests that background-returned errors not be
logged raw: locate where response.error is passed into Logger (references:
sanitizeUrlForLogging is already imported, Logger is used, and occurrences
around the affected spots noted as lines handling response.error and the Logger
calls at the regions corresponding to "693-694" and "719-721"); import and use
sanitizeApiError(...) to clean response.error before logging (e.g., replace
direct Logger.error(response.error, ...) with
Logger.error(sanitizeApiError(response.error), ...) and ensure any URLs are
wrapped with sanitizeUrlForLogging(...) and only include sender/tab IDs when
logging sender or tab objects). Ensure sanitizeApiError is imported from the
same security utils module and update all three affected places consistently.
In `@tests/unit/sidepanel/sidepanel.test.js`:
- Around line 649-651: The test currently asserts Logger.error was called with
the raw error payload which locks in unsafe logging; update the assertion around
Logger.error in sidepanel.test.js so it no longer requires the raw error string
— either (a) assert Logger.error was called with the '[SidePanel] savePage
failed' message and a payload matching expect.objectContaining({ error:
expect.any(String) }) or expect.any(Object), or (b) if the implementation now
uses sanitizeApiError(), call sanitizeApiError(mockApiError) in the test and
assert Logger.error was called with the sanitized payload; reference
Logger.error and sanitizeApiError() and keep the existing '[SidePanel] savePage
failed' message assertion intact.
---
Outside diff comments:
In `@sidepanel/sidepanel.js`:
- Around line 397-401: The shared cache (cachedStableUrl/cachedTabUrl and
cachedUnsyncedPages) is being updated before checking whether the async request
is still the active one, so stale/late responses can overwrite the cache; fix by
only writing to those shared variables after verifying the request is still
active (use the existing is*RequestActive() check or a requestId/token captured
before calling getStableUrlForTab()/the unsynced pages fetch and re-check it
after await). Specifically, in the getStableUrlForTab flow (surrounding
cachedStableUrl and cachedTabUrl) and the unsynced-pages fetch flow
(cachedUnsyncedPages) capture a local request identifier or call
is*RequestActive() after the await and only then update the shared cache; apply
the same guard to the other occurrence noted (around lines 817-820) so
handleStorageChange, loadMoreCards(), and deleteAllUnsyncedPages() won’t operate
on stale snapshots.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 27837a7f-2ae3-4b1f-8b5d-ed43a7b3c1d6
📒 Files selected for processing (2)
sidepanel/sidepanel.jstests/unit/sidepanel/sidepanel.test.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
此專案為 Chrome Extension (Manifest V3),必須使用 Vanilla JavaScript (ES6+ Modules) 作為核心語言,CommonJS 用於 Node 腳本。
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.test.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
禁止使用 TypeScript(除非明確要求)、React、Vue、Webpack。
Do not use console.log() statements in production code
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
Use Traditional Chinese (zh-TW) for all code comments, documentation, and string content, with strict enforcement except for technical terms and variable names
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}: Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Use a dedicated constants module for defining and exporting all constant values
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/security_rules.json)
**/*.{js,ts,jsx,tsx}: Force strict whitelisting for file downloads: appended files must be restricted to '.json' or '.txt' extensions with explicitly designated MIME types. Never use arbitrary user input for filenames to prevent Reflected File Download (RFD) attacks.
Always prefertextContentfor DOM operations. If SVG mixed content requires text updates, find the TEXT_NODE and update itstextContentrather than usinginnerHTMLon the parent.
Rely onLogSanitizerto strip sensitive properties (likesender,tab, PII) before emitting logs in production.Follow the project's ESLint configuration and do not emit DeepSource (skipcq) comments.
**/*.{js,ts,jsx,tsx}: Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Reject PR if introducing new core business logic without corresponding unit or E2E tests. Require TDD and ensure Codecov checks do not fail (< 50%).
Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{ts,tsx,js,jsx}: Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Use Logger.start(msg, ctx?) for process launch notifications in Notion Chrome Extension. Output prefix: [INFO] 🚀. The Logger class auto-manages the emoji icon.
Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Use Logger.info(msg, ctx?) for general informational messages in Notion Chrome Extension. Output prefix: [INFO]. No auto-managed emoji icon.
Use Logger.debug(msg, ctx?) for development debugging in Notion Chrome Extension. Output prefix: [DEBUG]. Controlled by enableDebugLogs switch.
Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN]⚠️ . The Logger class auto-manages the emoji icon.
Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Do NOT manually insert emoji icons (✅, 🚀, 📦,⚠️ , ❌) into log messages. The Logger class auto-manages these icons. Only manually use special semantic emoji like 🔍 (search) or 🗑️ (delete) when needed for semantic clarity.
Use 'action' field in Logger context to record public API function names (e.g., 'loadHighlights', 'savePage') for structured logging in Notion Chrome Extension.
Use 'operation' field in Logger context to record internal operation steps (e.g., 'parseLocalStorage', 'buildUrl') for structured logging in Notion Chrome Extension.
Use 'phase' field in Logger context (optional) to record execution stages (e.g., 'validation', 'apiCall') for structured logging in Notion Chrome Extension.
Use 'result' field in Logger context to record operation results (e.g., 'blocked', 'success', 'failed') for structured logging in Notion Chr...
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{test,spec}.{ts,tsx,js,jsx}: Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{test,spec}.{js,ts}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/testing_rules.json)
**/*.{test,spec}.{js,ts}: Always reference data structures (HTML snippets, Notion JSON responses) from .agents/.shared/references/ instead of hardcoding large payloads in test files.
Use .agents/.shared/references/notion_api/ for Notion block structures and database properties in test fixtures.
Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{js,ts,jsx,tsx,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/code_review_rules.json)
Maintain code comments and documentation in Traditional Chinese.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*
⚙️ CodeRabbit configuration file
**/*: # Project Specific Guidelines
- Language: All user-facing UI text, strings, and messages MUST be in Traditional Chinese (zh-TW).
- Architecture: Follow the defined storage structures and specs. Do not introduce unauthorized storage fields.
- Code Quality: Avoid N+1 issues, blocking operations, and ensure high code quality. Suggest optimizations that follow modern JavaScript/Chrome Extension best practices.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
🧠 Learnings (42)
📓 Common learnings
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: 修改檔案時,若重構現有程式碼(不新增功能也不修復 bug),Commit Message 類型應使用 `refactor`。
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/{storage,migration,highlight}/**/*.{js,ts} : Achieve 90%+ code coverage for Storage, Migration, and Highlighting algorithms in unit tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.test.js : 單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN] ⚠️. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, verify initialization completion by checking for '[INFO] ✅ 初始化完成' log message from Logger.success('初始化完成', { action: 'initialize' }) call.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, inspect local storage using 'chrome.storage.local.get(['highlights_${url}'])' and compare stored URL with current URL using normalizeUrl(window.location.href).
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to tests/e2e/specs/**/*.spec.{js,ts} : Do NOT use direct injection in e2e tests when testing Background Worker message routing logic. Instead, mock chrome.runtime.sendMessage.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : Save action handlers must implement savePage, openNotionPage, checkNotionPageExists, and checkPageStatus message actions with specified payload and response types
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When investigating highlight recovery failures in Notion Chrome Extension, verify URL consistency between stored highlights and current page, check for text content mutations on the source page, and confirm CSS Highlight API support exists.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : syncHighlights action must handle remote page deletion detection by returning PAGE_DELETION_PENDING status without clearing the Notion binding on first detection, and only return PAGE_DELETED and clear the binding after confirmation-window reoccurrence
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-03T12:36:42.667Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/linter_rules.json:0-0
Timestamp: 2026-03-03T12:36:42.667Z
Learning: Applies to **/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php} : Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging background service worker save failures in Notion Chrome Extension, check for API 400/500 status codes and look for batch processing logs like '[INFO] [NotionService] 準備分批添加區塊'.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Log only necessary IDs and sanitized error messages in Notion Chrome Extension. Follow security best practices documented in docs/guides/SECURITY_BEST_PRACTICES.md.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Do NOT log complete sender/tab objects, user content (title, highlight text), Schema structure (properties), or PII (email) in Notion Chrome Extension logs for security reasons.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-03T12:37:10.274Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/security_rules.json:0-0
Timestamp: 2026-03-03T12:37:10.274Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Rely on `LogSanitizer` to strip sensitive properties (like `sender`, `tab`, PII) before emitting logs in production.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `page_{stableUrl}` key pattern to store unified page state containing Notion metadata and highlights in chrome.storage.local, with fields: notion (object | null), highlights (array), and metadata (object)
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `url_alias_{normalizedUrl}` key pattern to map original URLs to stable URLs in chrome.storage.local to handle async race conditions
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Do not treat low-risk, ephemeral, self-recovering internal state hygiene issues as must-fix findings. Re-evaluate real user impact, persistence scope, and recovery behavior. Downgrade to a note or acceptable technical debt only if it causes no durable data corruption, user-facing inconsistency, blocked actions, or expanding side effects. CRITICAL or security-related findings must not be downgraded without citing specific source lines and a concrete reproduction or validation scenario.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When investigating highlight recovery failures in Notion Chrome Extension, check for migration completion by verifying '遷移完成' log message exists in logs.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Chrome Extension storage.local has 5MB limit with unlimitedStorage permission; store authentication tokens, workspace metadata, data source selections, and per-page highlight data here
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Chrome Extension storage.sync has 100KB total limit with 8KB per item limit; store user preferences, settings, and configuration here
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store highlight content sync style in `highlightContentStyle` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store title template for saved pages in `titleTemplate` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Performance target for highlight sync in Notion Chrome Extension: < 500ms.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : CLEAR_HIGHLIGHTS action must clear local highlights through the canonical Background storage path and perform best-effort visual cleanup on the page
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting functionality in Notion Chrome Extension, verify CSS.highlights API support by running 'highlights' in CSS in the target website's DevTools console.
Applied to files:
sidepanel/sidepanel.js
- 將 sanitizeApiError 函數整合至 savePage 和 openNotionPage 的錯誤日誌中,以隱藏敏感資訊。 - 更新 loadCurrentTab 函數,確保不會用過期的穩定 URL 覆蓋快取的標籤 URL。 - 增加單元測試以驗證快取邏輯的正確性。
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
sidepanel/sidepanel.js (1)
708-710: 🧹 Nitpick | 🔵 TrivialMagic numbers 2000/1000 應抽取為常數
setTimeout中的 2000 和 1000 毫秒是 magic numbers,建議抽取到 UI 模組或常數模組中以提升可維護性。♻️ 建議抽取常數
在
sidepanelUI.js中新增:export const SYNC_BUTTON_DEBOUNCE_MS = 2000; export const OPEN_BUTTON_DEBOUNCE_MS = 1000;然後在
sidepanel.js中使用:} finally { setTimeout(() => { els.syncButton.disabled = false; - }, 2000); + }, UI.SYNC_BUTTON_DEBOUNCE_MS); } @@ } finally { setTimeout(() => { els.openNotionButton.disabled = false; - }, 1000); + }, UI.OPEN_BUTTON_DEBOUNCE_MS); }As per coding guidelines: "Do not use magic numbers in code; extract them to constants defined in a dedicated constants module."
Also applies to: 738-740
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sidepanel/sidepanel.js` around lines 708 - 710, Replace the magic numbers used in setTimeout calls (e.g., the 2000ms used with setTimeout that re-enables els.syncButton and the 1000ms used elsewhere) with named constants exported from the UI/constants module (for example export SYNC_BUTTON_DEBOUNCE_MS and OPEN_BUTTON_DEBOUNCE_MS from sidepanelUI.js), then import and use those constants in sidepanel.js in place of the literal numbers so the calls to setTimeout(...) reference SYNC_BUTTON_DEBOUNCE_MS and OPEN_BUTTON_DEBOUNCE_MS instead of 2000/1000.
♻️ Duplicate comments (1)
tests/unit/sidepanel/sidepanel.test.js (1)
21-27: 🧹 Nitpick | 🔵 TrivialLogger mock 介面不完整
此 mock 只定義了
warn和error。如果sidepanel.js在重構時呼叫success、start、ready、info或debug,測試會因為 mock 缺方法而失敗。建議補齊完整介面以提升測試穩定性。♻️ 建議補齊 Logger mock
jest.mock('../../../scripts/utils/Logger.js', () => ({ __esModule: true, default: { + success: jest.fn(), + start: jest.fn(), + ready: jest.fn(), + info: jest.fn(), + debug: jest.fn(), warn: jest.fn(), error: jest.fn(), }, }));Based on learnings: "When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/sidepanel/sidepanel.test.js` around lines 21 - 27, The Logger mock currently only defines warn and error; update the jest.mock of the default Logger export used in sidepanel.test.js so the mock includes all expected methods (success, start, ready, info, debug, warn, error) each set to jest.fn(); locate the existing jest.mock(...) for Logger.js and extend the default object to provide these additional jest.fn() methods to prevent missing-method failures when sidepanel.js is refactored.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/unit/sidepanel/sidepanel.test.js`:
- Around line 1077-1080: The test assertion uses the raw URL but
appendNextUnsyncedBatch calls Logger.warn with sanitizeUrlForLogging(url);
update the expectation to call sanitizeUrlForLogging('https://example.com/p')
(or use the mocked return value if sanitizeUrlForLogging is mocked) so the
expected logged payload matches the actual call to Logger.warn in
appendNextUnsyncedBatch; reference Logger.warn, appendNextUnsyncedBatch, and
sanitizeUrlForLogging to locate the code to change.
---
Outside diff comments:
In `@sidepanel/sidepanel.js`:
- Around line 708-710: Replace the magic numbers used in setTimeout calls (e.g.,
the 2000ms used with setTimeout that re-enables els.syncButton and the 1000ms
used elsewhere) with named constants exported from the UI/constants module (for
example export SYNC_BUTTON_DEBOUNCE_MS and OPEN_BUTTON_DEBOUNCE_MS from
sidepanelUI.js), then import and use those constants in sidepanel.js in place of
the literal numbers so the calls to setTimeout(...) reference
SYNC_BUTTON_DEBOUNCE_MS and OPEN_BUTTON_DEBOUNCE_MS instead of 2000/1000.
---
Duplicate comments:
In `@tests/unit/sidepanel/sidepanel.test.js`:
- Around line 21-27: The Logger mock currently only defines warn and error;
update the jest.mock of the default Logger export used in sidepanel.test.js so
the mock includes all expected methods (success, start, ready, info, debug,
warn, error) each set to jest.fn(); locate the existing jest.mock(...) for
Logger.js and extend the default object to provide these additional jest.fn()
methods to prevent missing-method failures when sidepanel.js is refactored.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 22ff0393-1d9b-4544-87bb-109343e047b8
📒 Files selected for processing (2)
sidepanel/sidepanel.jstests/unit/sidepanel/sidepanel.test.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
此專案為 Chrome Extension (Manifest V3),必須使用 Vanilla JavaScript (ES6+ Modules) 作為核心語言,CommonJS 用於 Node 腳本。
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.test.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
禁止使用 TypeScript(除非明確要求)、React、Vue、Webpack。
Do not use console.log() statements in production code
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
Use Traditional Chinese (zh-TW) for all code comments, documentation, and string content, with strict enforcement except for technical terms and variable names
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/linter_rules.json)
**/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php}: Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Use a dedicated constants module for defining and exporting all constant values
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/security_rules.json)
**/*.{js,ts,jsx,tsx}: Force strict whitelisting for file downloads: appended files must be restricted to '.json' or '.txt' extensions with explicitly designated MIME types. Never use arbitrary user input for filenames to prevent Reflected File Download (RFD) attacks.
Always prefertextContentfor DOM operations. If SVG mixed content requires text updates, find the TEXT_NODE and update itstextContentrather than usinginnerHTMLon the parent.
Rely onLogSanitizerto strip sensitive properties (likesender,tab, PII) before emitting logs in production.Follow the project's ESLint configuration and do not emit DeepSource (skipcq) comments.
**/*.{js,ts,jsx,tsx}: Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Reject PR if introducing new core business logic without corresponding unit or E2E tests. Require TDD and ensure Codecov checks do not fail (< 50%).
Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{ts,tsx,js,jsx}: Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Use Logger.start(msg, ctx?) for process launch notifications in Notion Chrome Extension. Output prefix: [INFO] 🚀. The Logger class auto-manages the emoji icon.
Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Use Logger.info(msg, ctx?) for general informational messages in Notion Chrome Extension. Output prefix: [INFO]. No auto-managed emoji icon.
Use Logger.debug(msg, ctx?) for development debugging in Notion Chrome Extension. Output prefix: [DEBUG]. Controlled by enableDebugLogs switch.
Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN]⚠️ . The Logger class auto-manages the emoji icon.
Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Do NOT manually insert emoji icons (✅, 🚀, 📦,⚠️ , ❌) into log messages. The Logger class auto-manages these icons. Only manually use special semantic emoji like 🔍 (search) or 🗑️ (delete) when needed for semantic clarity.
Use 'action' field in Logger context to record public API function names (e.g., 'loadHighlights', 'savePage') for structured logging in Notion Chrome Extension.
Use 'operation' field in Logger context to record internal operation steps (e.g., 'parseLocalStorage', 'buildUrl') for structured logging in Notion Chrome Extension.
Use 'phase' field in Logger context (optional) to record execution stages (e.g., 'validation', 'apiCall') for structured logging in Notion Chrome Extension.
Use 'result' field in Logger context to record operation results (e.g., 'blocked', 'success', 'failed') for structured logging in Notion Chr...
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/debugging_rules.json)
**/*.{test,spec}.{ts,tsx,js,jsx}: Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{test,spec}.{js,ts}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/testing_rules.json)
**/*.{test,spec}.{js,ts}: Always reference data structures (HTML snippets, Notion JSON responses) from .agents/.shared/references/ instead of hardcoding large payloads in test files.
Use .agents/.shared/references/notion_api/ for Notion block structures and database properties in test fixtures.
Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Files:
tests/unit/sidepanel/sidepanel.test.js
**/*.{js,ts,jsx,tsx,md}
📄 CodeRabbit inference engine (.agents/.shared/knowledge/code_review_rules.json)
Maintain code comments and documentation in Traditional Chinese.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
**/*
⚙️ CodeRabbit configuration file
**/*: # Project Specific Guidelines
- Language: All user-facing UI text, strings, and messages MUST be in Traditional Chinese (zh-TW).
- Architecture: Follow the defined storage structures and specs. Do not introduce unauthorized storage fields.
- Code Quality: Avoid N+1 issues, blocking operations, and ensure high code quality. Suggest optimizations that follow modern JavaScript/Chrome Extension best practices.
Files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
🧠 Learnings (45)
📓 Common learnings
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: 修改檔案時,若重構現有程式碼(不新增功能也不修復 bug),Commit Message 類型應使用 `refactor`。
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking Logger in Notion Chrome Extension tests, ensure all methods (success, start, ready, info, debug, warn, error) are defined as jest.fn() in the mock setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests, avoid vague string matching for Logger assertions. Use 'expect.objectContaining' to assert exact expected metadata objects for Logger calls.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : In Notion Chrome Extension tests using ErrorHandler.formatUserMessage, target assertions against Chinese strings (user-facing messages) rather than original English API messages for I18N awareness.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : When mocking objects in Notion Chrome Extension tests, ensure mock object depth is sufficient. For example, mocking an img tag requires including 'dataset: {}' property.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Run failing tests with command 'npx jest <path/to/test.js> --no-coverage' instead of full test suites in Notion Chrome Extension for faster feedback loops during logic fixes.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Do not mutate window.chrome directly. Override global.chrome for mocking Chrome API in tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Execute jest.clearAllMocks() and clean up global.chrome in afterEach to prevent test pollution.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/{storage,migration,highlight}/**/*.{js,ts} : Achieve 90%+ code coverage for Storage, Migration, and Highlighting algorithms in unit tests.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to tests/e2e/specs/**/*.spec.{js,ts} : Do NOT use direct injection in e2e tests when testing Background Worker message routing logic. Instead, mock chrome.runtime.sendMessage.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-10T08:21:13.819Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/testing_rules.json:0-0
Timestamp: 2026-03-10T08:21:13.819Z
Learning: Applies to **/*.{test,spec}.{js,ts} : Declare mock variables and spies at the top level and initialize them in beforeEach for Chrome API mocking setup.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.test.js : 單元測試邏輯使用 Jest,需要使用 Mocking patterns。
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.warn(msg, ctx?) for non-fatal warnings in Notion Chrome Extension. Output prefix: [WARN] ⚠️. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify all Logger.info/error calls correctly sanitize data with no PII and no raw HTML.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, verify initialization completion by checking for '[INFO] ✅ 初始化完成' log message from Logger.success('初始化完成', { action: 'initialize' }) call.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.success(msg, ctx?) for operation success confirmation in Notion Chrome Extension. Output prefix: [INFO] ✅. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.ready(msg, ctx?) for module or resource readiness notifications in Notion Chrome Extension. Output prefix: [INFO] 📦. The Logger class auto-manages the emoji icon.
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Logger.error(msg, ctx?) for error recording in Notion Chrome Extension. Output prefix: [ERROR] ❌. The Logger class auto-manages the emoji icon. Always displayed regardless of debug switch.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if attempting to log complete sender, tab, request objects or raw HTML content. Require using IDs only (e.g., sender?.id, tab?.id), and wrapping URLs with sanitizeUrlForLogging() and API errors with sanitizeApiError().
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Log only necessary IDs and sanitized error messages in Notion Chrome Extension. Follow security best practices documented in docs/guides/SECURITY_BEST_PRACTICES.md.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Avoid exposing internal-only, non-actionable, non-blocking cleanup/reconciliation/retry failures directly as user-facing errors. Keep the canonical user-facing state, log the internal failure, and handle retry/recovery inside the relevant service or canonical path unless the failure truly blocks the user's next action.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-03T12:37:10.274Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/security_rules.json:0-0
Timestamp: 2026-03-03T12:37:10.274Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Rely on `LogSanitizer` to strip sensitive properties (like `sender`, `tab`, PII) before emitting logs in production.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting in Notion Chrome Extension, inspect local storage using 'chrome.storage.local.get(['highlights_${url}'])' and compare stored URL with current URL using normalizeUrl(window.location.href).
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : Save action handlers must implement savePage, openNotionPage, checkNotionPageExists, and checkPageStatus message actions with specified payload and response types
Applied to files:
tests/unit/sidepanel/sidepanel.test.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When investigating highlight recovery failures in Notion Chrome Extension, verify URL consistency between stored highlights and current page, check for text content mutations on the source page, and confirm CSS Highlight API support exists.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : syncHighlights action must handle remote page deletion detection by returning PAGE_DELETION_PENDING status without clearing the Notion binding on first detection, and only return PAGE_DELETED and clear the binding after confirmation-window reoccurrence
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Verify cache and large data usage strictly targets chrome.storage.local rather than chrome.storage.sync.
Applied to files:
tests/unit/sidepanel/sidepanel.test.jssidepanel/sidepanel.js
📚 Learning: 2026-03-03T12:36:42.667Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/linter_rules.json:0-0
Timestamp: 2026-03-03T12:36:42.667Z
Learning: Applies to **/*.{js,ts,tsx,jsx,py,java,cs,rb,go,swift,kt,php} : Do not use magic numbers in code; extract them to constants defined in a dedicated constants module
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging background service worker save failures in Notion Chrome Extension, check for API 400/500 status codes and look for batch processing logs like '[INFO] [NotionService] 準備分批添加區塊'.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Do NOT log complete sender/tab objects, user content (title, highlight text), Schema structure (properties), or PII (email) in Notion Chrome Extension logs for security reasons.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reject PR if attempting to store large HTML content, Base64 images, or heavy payloads into chrome.storage.sync. Require storing large payloads in chrome.storage.local or IndexedDB.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `page_{stableUrl}` key pattern to store unified page state containing Notion metadata and highlights in chrome.storage.local, with fields: notion (object | null), highlights (array), and metadata (object)
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Use `url_alias_{normalizedUrl}` key pattern to map original URLs to stable URLs in chrome.storage.local to handle async race conditions
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-23T04:16:46.480Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/code_review_rules.json:0-0
Timestamp: 2026-03-23T04:16:46.480Z
Learning: Do not treat low-risk, ephemeral, self-recovering internal state hygiene issues as must-fix findings. Re-evaluate real user impact, persistence scope, and recovery behavior. Downgrade to a note or acceptable technical debt only if it causes no durable data corruption, user-facing inconsistency, blocked actions, or expanding side effects. CRITICAL or security-related findings must not be downgraded without citing specific source lines and a concrete reproduction or validation scenario.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When investigating highlight recovery failures in Notion Chrome Extension, check for migration completion by verifying '遷移完成' log message exists in logs.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use 'reason' field in Logger context to record reason codes (e.g., 'restricted_url', 'timeout') for structured logging in Notion Chrome Extension.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use 'error' field in Logger context to pass error objects. Logger automatically expands Stack Trace details in Notion Chrome Extension logs.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-02-26T20:59:55.454Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-26T20:59:55.454Z
Learning: Applies to **/*.js : 此專案為 Chrome Extension (Manifest V3),必須使用 Vanilla JavaScript (ES6+ Modules) 作為核心語言,CommonJS 用於 Node 腳本。
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Chrome Extension storage.local has 5MB limit with unlimitedStorage permission; store authentication tokens, workspace metadata, data source selections, and per-page highlight data here
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Chrome Extension storage.sync has 100KB total limit with 8KB per item limit; store user preferences, settings, and configuration here
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store highlight content sync style in `highlightContentStyle` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-14T15:55:36.020Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/storage_schema.json:0-0
Timestamp: 2026-03-14T15:55:36.020Z
Learning: Applies to scripts/background/services/StorageService.js : Store title template for saved pages in `titleTemplate` key (string) in chrome.storage.sync
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: Performance target for highlight sync in Notion Chrome Extension: < 500ms.
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-22T05:25:18.555Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/message_bus.json:0-0
Timestamp: 2026-03-22T05:25:18.555Z
Learning: Applies to scripts/background/handlers/*.js : CLEAR_HIGHLIGHTS action must clear local highlights through the canonical Background storage path and perform best-effort visual cleanup on the page
Applied to files:
sidepanel/sidepanel.js
📚 Learning: 2026-03-06T18:35:38.641Z
Learnt from: CR
Repo: cowcfj/save-to-notion PR: 0
File: .agents/.shared/knowledge/debugging_rules.json:0-0
Timestamp: 2026-03-06T18:35:38.641Z
Learning: When debugging content script highlighting functionality in Notion Chrome Extension, verify CSS.highlights API support by running 'highlights' in CSS in the target website's DevTools console.
Applied to files:
sidepanel/sidepanel.js
- 將同步按鈕和開啟按鈕的重新啟用延遲時間提取為常數,增強代碼可讀性與可維護性。 - 更新相關函數以使用這些常數,確保一致性。 - 增加單元測試以驗證按鈕重新啟用的行為。
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|



Pull Request
📋 變更描述
將 sidepanel.js 拆分為業務邏輯與 UI 渲染兩層,以提升可維護性和可測試性。
🎯 變更類型
🤖 提交者聲明
✅ 提交前檢查清單
feat:,fix:,refactor:),以確保release-please正常分析版本號。PR_WORKFLOW.md中的測試規範、代碼規範與安全性指引。🔗 相關 Issue
Closes #
變更
測試
全量測試通過,ESLint 無錯誤和新警告。