First off, thank you for taking the time to contribute! 🎉
This document provides guidelines and instructions for contributing to Haiilo Enhancer. Following these guidelines helps ensure a smooth process for everyone involved and keeps the extension fast, secure, and compatible across all supported platforms.
By participating in this project, you agree to maintain a respectful, welcoming, and collaborative environment.
- Node.js (for running hooks and linters)
- A Chromium-based browser (Chrome, Edge, Brave, etc.) and/or Firefox
- Clone this repository.
- Install the Git pre-commit hooks to automatically check code style, localization, and unit tests before committing:
sh scripts/install-hooks.sh
The build scripts compile browser packages and write them to the dist/ directory.
Cross-platform shortcut: npm run build delegates to the correct script for your OS
(npm run build:chrome / npm run build:firefox for single targets).
-
On Windows (PowerShell):
.\build.ps1 # Build for both Chrome and Firefox .\build.ps1 -Firefox # Build Firefox package only .\build.ps1 -Chrome # Build Chrome package only
Note: If you run into script execution issues, you may need to run
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSignedin PowerShell once. -
On macOS / Linux (Bash):
./build.sh # Build for both Chrome and Firefox ./build.sh -Firefox # Build Firefox package only ./build.sh -Chrome # Build Chrome package only
-
Chromium-based browsers (Chrome, Edge, etc.):
- Open the Extensions management page (e.g.,
chrome://extensions/). - Enable Developer mode in the top-right corner.
- Click Load unpacked in the top-left corner.
- Select the project root folder.
- Open the Extensions management page (e.g.,
-
Firefox:
- Run the build command above to generate the Firefox distribution package.
- Open the Firefox debugging page (
about:debugging). - Click This Firefox on the left menu.
- Click Load Temporary Add-on... under Temporary Extensions.
- Select the
dist/firefox/manifest.jsonfile.
To maintain compatibility and prevent regressions, all contributions must adhere to the following rules:
The extension must run seamlessly on both Chromium (Chrome Manifest V3) and Firefox (Firefox Manifest V3).
- All browser API calls must route through the compatibility wrappers defined at the top of the JS files:
const browserAPI = typeof browser !== 'undefined' ? browser : chrome; const badgeAPI = (typeof browser !== 'undefined' && browser.action) ? browser.action : (browserAPI.action || chrome.action);
- Never hardcode
chrome.*directly for API calls. Doing so can cause silent failures (returningundefinedinstead of Promises) on Firefox. - Keep the
manifest.json(Chrome) andmanifest.firefox.json(Firefox) synced. Do not hardcode version numbers in popup or options HTML files; they are dynamically injected at runtime.
To keep the browser developer console clean in production:
- Do not use
console.log,console.warn,console.info, orconsole.debugdirectly. - Wrap all informational logs inside a function named
debugLog()(which respects the user's debug mode setting). console.erroris the only method allowed unconditionally for genuine error reports.- You can manually run the log linter via:
node scripts/lint-console.mjs
If you introduce a new settings key or storage attribute in browserAPI.storage.local:
- You must list this key in the initial
browserAPI.storage.local.get([...])call inside theonInstalledlistener in background.js. - Failing to list the key will cause it to resolve as
undefinedon updates, triggering the initialization check and wiping the user's saved data.
- Double Injection Guard: Firefox may inject
content.jsmultiple times. Keep the double-injection guard at the top of content.js intact:if (window.__haiiloEnhancerLoaded) return; window.__haiiloEnhancerLoaded = true;
- Orphaned Scripts: Check that the extension context is active before calling browser APIs inside async event handlers or observers using the
isExtensionContextValid()helper. Wrap API accesses in atry...catchblock where appropriate. - Exception-Safe URLs: Always wrap
new URL()operations intry...catchblocks to prevent malformed or special URLs (e.g.about:blank, relative links) from throwing unhandled exceptions and crashing the main extension execution flow.
When targeting Angular backdrops or overlay dialogs:
- Angular overlay backdrops do not have standard CSS classes; they are created with inline styles. Always target them using the attribute selector:
div[style*="position: fixed"][style*="background: rgba"][style*="width: 100%"]
- Avoid registering capture-phase click listeners on the
documentlevel to keep the messenger expanded, as it blocks normal page interaction. Use observers to monitor classes and state instead. - For new features that react to added DOM nodes, register a handler on the shared
domMutationdispatcher incontent.jsrather than creating your own document-wideMutationObserver(the messenger feature is the exception: it keeps dedicatedclass/styleattribute observers).
- All colors are configured in colors.css using CSS Custom Properties (variables).
- Avoid writing ad-hoc colors or inline color styles. Update
colors.cssif custom styling needs to be adjusted.
Translations are welcome and managed through the public POEditor project, then shipped
as native WebExtension catalogs in _locales/<locale>/messages.json.
- Translators: follow LOCALIZATION.md for the full POEditor workflow.
Keep message IDs and
$PLACEHOLDER$names unchanged when translating. - Developers: never remove or rename message IDs — every catalog must contain every
English key so missing translations fall back safely. Validate catalogs deterministically
before committing:
The pre-commit hook runs this automatically whenever a
node scripts/check-locales.mjs
_locales/catalog is staged.
- Format & Quality Check: Ensure there are no console log violations or syntax errors. If you changed any translation catalog, run
node scripts/check-locales.mjs. Make sure your pre-commit hooks have run successfully. - Cross-Browser Verification: Manually test your changes in both Chrome (or a Chromium-based browser) and Firefox.
- Commit Messages: Write clear, descriptive commit messages.
- Push & PR: Open a Pull Request on GitHub. Detail the changes you've made, why you made them, and how you tested them. Reference any related issues.