TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
Chrome·Firefox·Firefox Android에서 웹 페이지 텍스트를 강조하고 관리하는 확장 기능
A cross-browser extension that allows you to highlight and manage text on web pages. Supports Chrome, Firefox, and Firefox for Android.
생산성JavaScript · HTMLGitHub @cuspymd온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A cross-browser extension that allows you to highlight and manage text on web pages. Supports Chrome, Firefox, and Firefox for Android.
storage.sync# Clone the repository
git clone https://github.com/yourusername/text-highlighter.git
cd text-highlighter
# Install dependencies
npm install
This extension supports:
On Firefox for Android, the following desktop-only APIs are unavailable and handled gracefully:
contextMenus): Not supported. Use the selection icon and color palette instead (always shown on mobile).commands): Not supported. Use the selection icon and color palette instead.windows): Not supported. The extension uses the Tabs API as a fallback.storage.sync): Sync currently works between Firefox desktop devices, but Firefox for Android does not sync highlight data.The Selection Controls feature (floating highlight icon on text selection) is automatically enabled on mobile devices, providing a touch-friendly alternative to context menus and keyboard shortcuts.
Repository skills live in .agents/skills/, which is tracked in git and shared across agent tools. Claude Code only discovers skills under .claude/skills/, so link the two rather than keeping a second copy:
npm run link-skills
This creates .claude/skills as a link to .agents/skills (a directory junction on Windows, which needs no elevation). Run it once per clone — .claude/ is gitignored, so the link is local to your machine. It is idempotent and safe to re-run. Restart Claude Code afterwards for the skills to be picked up.
Add new skills to .agents/skills/<name>/SKILL.md only; the link exposes them automatically.
Three suites, run separately:
# Unit and integration tests (Jest, jsdom)
npm test
# End-to-end tests on Chromium (Playwright)
npx playwright install # browsers, required before the first run
npx playwright test
# Firefox smoke tests (Selenium + geckodriver)
npm run test:e2e:firefox
npm test and the Playwright suite run in CI on every push. The Firefox suite
does not: it is three checks that confirm the Firefox build comes up, applies a
highlight, restores it after a reload, and opens its popup — run it by hand
before publishing a Firefox release. It needs Firefox installed locally
(geckodriver is downloaded automatically), builds dist-firefox/ itself, and
takes a few seconds.
# Watch it run instead of going headless
HEADFUL=1 npm run test:e2e:firefox
# Point at a Firefox that is not in the default location
FIREFOX_BINARY="/path/to/firefox" npm run test:e2e:firefox
To test the extension on a real Android device:
# Run on connected Android device
npx web-ext run -t firefox-android --adb-device <device-id> --firefox-apk org.mozilla.firefox -s dist-firefox
To find your device ID:
adb devices
about:configxpcom.debug.remote.enabled to trueabout:debugging > Setupdist-firefox/manifest.json# View extension logs from the Android device
adb logcat -s GeckoConsole
Run the deployment script to build both Chrome and Firefox extension files at once:
npm run deploy
To build a single browser instead, use npm run deploy:chrome or npm run deploy:firefox.
Run the Chrome-specific deployment script to copy only the required files to the dist directory for loading into Chrome:
npm run deploy:chrome
To load the deployed extension in Chrome:
chrome://extensions in Chrome browserdist directoryRun the Firefox-specific deployment script:
npm run deploy:firefox
To load the deployed extension in Firefox:
about:debugging in Firefox browsermanifest.json file from the generated dist-firefox directoryFor creating a production-ready extension package, you can now specify the target browser:
npm run version-deploy <version> [browser]
This command will:
manifest.json for Chrome, manifest-firefox.json for Firefox)DEBUG_MODE to false in all JavaScript filesdist/ for Chrome, dist-firefox/ for Firefox)outputs/ directorynpm run version-deploy 1.2.0
# or explicitly
npm run version-deploy 1.2.0 chrome
This creates outputs/text-highlighter-1.2.0-chrome.zip ready for submission to the Chrome Web Store.
npm run version-deploy 1.2.0 firefox
This creates outputs/text-highlighter-1.2.0-firefox.zip ready for submission to Firefox Add-ons (AMO).
Note: Each browser build uses its own manifest file and output directory, allowing you to maintain separate versions for each browser if needed.
The extension uses a browserAPI compatibility layer to support Chrome and Firefox:
chrome.* APIs directlybrowser.* APIs directlymanifest.json: Chrome-optimized (default)manifest-firefox.json: Firefox-optimized with gecko and gecko_android settings| API | Chrome | Firefox Desktop | Firefox Android |
|---|---|---|---|
| Storage | O | O | O |
| Sync Storage | O | O | X |
| Tabs | O | O | O |
| Runtime | O | O | O |
| Internationalization | O | O | O |
| Context Menus | O | O | X |
| Commands | O | O | X |
| Windows | O | O | X |
On Firefox Android, unavailable APIs are conditionally guarded using browser.runtime.getPlatformInfo() to detect the platform at runtime.
Cloud sync (background/cloud-sync-service.js) runs a pull-merge-push cycle on a 15-minute alarm. The PUT is skipped when the merged blob matches the one just fetched, so an idle cycle costs a single GET.
That guard rests on an invariant worth knowing before touching this code: the merge must be a pure function of the two blobs, giving the same answer on every device. A rule phrased as "prefer mine" breaks it, because each device resolves it in its own favour — neither ever adopts the other, and every cycle pushes. Nothing errors; the symptom is a setting that quietly never syncs, plus a KV write on every cycle from users who changed nothing.
Two rules in mergeBlobs still resolve ties that way:
updatedAt, local wins (strict >)title: local wins whenever it is non-empty, regardless of recencyAdoption has to be complete, too. applySettingsFromSync copies the sender's settings timestamp, so any field it declines to adopt leaves two devices claiming the same timestamp with different content — which is exactly the tie the rules above resolve badly. Treat null as a value, not as an absent field.
See #108 for a case that reached production, where a skipped null produced a PUT on roughly 20% of all sync cycles.
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)This project is licensed under the MIT License - see the LICENSE file for details.