This package provides one typed CSS insertion and removal contract across Manifest V2 and Manifest V3. Contributions should preserve that boundary, keep unsupported capabilities explicit, and include verification for every affected adapter. By participating, you agree to abide by the project’s Code of Conduct.
- Reporting Bugs
- Suggesting Enhancements
- Development Setup
- Scripts
- Contract Guidelines
- Pull Request Workflow
- Code Style & Quality
- Commit Messages
- Versioning Policy
- Automated Dependency Updates
- Code of Conduct
- License
To file a clear and actionable bug report:
- Search existing issues to see if the bug has already been reported.
- If not, open a new issue at https://github.com/addon-stack/inject-css/issues and include:
- A descriptive title.
- Steps to reproduce the problem.
- Expected vs. actual behavior.
- Environment details (OS, browser, Node.js/npm versions).
- Any relevant stack traces or screenshots.
For feature requests or enhancements:
- Check open issues for similar proposals.
- Open a new issue with:
- A clear use case or motivation.
- Proposed API or code examples (if available).
- Any alternatives you considered.
- Fork this repository.
- Clone your fork:
git clone git@github.com:<your-username>/inject-css.git cd inject-css
- Add the upstream remote (optional):
git remote add upstream git@github.com:addon-stack/inject-css.git
- Use Node.js 22.23.3 and install the committed npm lockfile:
Keep
npm ci
package-lock.jsonin sync withpackage.json; CI and Renovate use npm.
The following scripts are available and should be used during development:
npm run build— build the project with tsupnpm run build:watch— build in watch modenpm run dev— build in watch modenpm run format— format code with Biomenpm run format:check— check formatting onlynpm run lint— lint code with Biomenpm run lint:fix— attempt to automatically fix lint issuesnpm run lint:fix:aggressive— fix lint issues using unsafe rulesnpm run lint:fix:unsafe— fix lint issues using unsafe rulesnpm run typecheck— run TypeScript type checksnpm run test:types— type-check public API contract fixturesnpm run test— type-check fixtures, build the package, and run Jest and release tooling testsnpm run test:ci— type-check fixtures, build, and run Jest with coverage; CI runs release tooling separately on Node.js 22.23.3npm run test:tooling— check Renovate commits, commitlint, release parsing, and generated dependency release notesnpm run release— trigger release via release-it
Note: Husky hooks are configured. Commit messages are validated with commitlint, pre-commit runs lint-staged, and pre-push runs the full type/test/build path.
- Every operation has one explicit
target. allFrames,frameIds, anddocumentIdsremain mutually exclusive.- Unsupported targets and options fail explicitly; they are never removed silently or replaced with a broader target.
insert(),file(),remove(), andremoveFile()remain strictPromise<void>operations because native CSS APIs expose no portable per-frame result.- File order is part of the CSS cascade contract and must be preserved.
- Omitted options preserve native defaults.
- Explicit
undefinedvalues passed tooptions()reset the corresponding option. - Removal must preserve the caller's exact source, target, and origin; the package does not track prior insertions.
- Frame enumeration, document discovery, and application-specific result aggregation remain outside this package.
- Create a feature branch:
git checkout -b feature/your-feature-name
- Make your changes in TypeScript under
src/. - Ensure local checks pass before opening a PR:
npm run format npm run lint npm run typecheck npm run build npm run test - Commit changes using Conventional Commits.
- Push to your fork and open a Pull Request against the
developbranch. - Provide a clear title and description, referencing related issues (e.g.,
Closes #123).
- Language: TypeScript
- Formatting & Linting: Biome (see
biome.json)
Please run npm run format and npm run lint before submitting code. Type safety is enforced via npm run typecheck.
GitHub Actions runs lint, source and public API type checks, tests, coverage, and a production build. Pull requests into main and release runs use Ubuntu 24.04 and Windows with Node.js 18, 20, and 22. Pushes to develop use Ubuntu 24.04 with Node.js 20. Release tooling runs in a separate Node.js 22.23.3 job on every CI run. The aggregate CI passed check also requires release tooling tests and strict Renovate configuration validation; failed, cancelled, or skipped prerequisites fail this check.
We follow the Conventional Commits specification. Commit messages are validated by commitlint.
Format:
<type>[optional scope]: <description>
Common types:
feat: a new featurefix: a bug fixdeps: dependency updatesci: workflow and CI configuration changesdocs: documentation only changesstyle: formatting, missing semicolons, etcrefactor: code change that neither fixes a bug nor adds a featuretest: adding missing tests or correcting existing testschore: updating build tasks, package manager configs, etc
Example:
feat(core): add new API method for X
Release versions are derived from commit history by release-it and @release-it/conventional-changelog:
- A breaking change increments major at
1.xand newer. - A breaking change increments minor while the package is on
0.x. featandrevertincrement minor.fix,deps,perf, andrefactorincrement patch.docs,test,build,chore,ci, andstyledo not trigger a release by themselves.- When several changes are present, the highest applicable increment wins.
Do not edit released changelog entries manually. CHANGELOG.md is generated from Conventional Commits during release.
The Update Dependencies workflow runs every Sunday at 02:15 America/Los_Angeles and can also be started from Actions → Update Dependencies → Run workflow. The time follows Los Angeles daylight saving rules.
Renovate reads renovate.json from main and updates only @addon-core/browser and @types/chrome, together with their required lockfile changes. Stable updates of any size are grouped in one deps/update-dependencies branch and one PR into main, including Chrome-types-only updates. Other direct dependencies and standalone lockfile maintenance are disabled.
On each run, Renovate refreshes its branch from the current main when needed. An open bot-managed PR is updated in place. After merging, a future update can recreate the same branch name. No available update means no empty PR. Manually committing to an open bot branch pauses automatic updates to protect those commits.
The bot creates deps: update dependencies commits. Ordinary dependency-only changes trigger a patch release and appear under 📦 Dependencies in the changelog and GitHub release notes. Keep the deps: ... title when squashing. Breaking markers and other commits still follow the normal release policy.
The App token triggers the normal PR checks: lint, source and public API type checks, build, tests, and strict Renovate configuration validation. Merging remains manual. Failed checks leave the PR open and do not publish a release. After merge, the existing Release workflow repeats the full checks, publishes the package, and syncs main back into develop.
Keep conventional-commits-parser 7.x as an explicit development dependency. The release tooling uses parser 7.x, while commitlint keeps its own parser 5.x. The explicit dependency also makes the release integration tests independent of transitive hoisting. After changing it, regenerate the lockfile in a clean directory and verify npm ci and the release tooling tests.
The release setup uses release-it 21.x, @release-it/conventional-changelog 12.x, and conventional-commits-parser 7.x. Use Node.js 22.23.3 for development and releases; the release tools require at least 22.22.2 in the Node.js 22 line. CI still checks the library on Node.js 18, 20, and 22, but runs the newer release tools separately. The changelog uses the writer's template(context) function API, preserving sections, breaking notes, commit links and bodies, contributors, and the deps/ci version policy.
There are no npm overrides. Review both npm audit and npm audit --omit=dev after dependency updates, and rerun the checks plus a release dry-run with publishing disabled.
As of 2026-10-14, the latest upstream releases still contain two affected development-tool dependency chains:
release-it→proxy-agent→pac-proxy-agent→get-uri→basic-ftp5.3.1: high-severity FTP directory-listing denial of service. The fix exists in Basic FTP 6.2.1+, but even get-uri 8.0.1 still requests 5.x. This requires an attacker-controlled FTP listing; it does not establish that ordinary HTTPS publishing is affected.- Jest → babel-plugin-istanbul → @istanbuljs/load-nyc-config → js-yaml 3 → argparse 1 → sprintf-js: moderate-severity denial of service. No patched sprintf-js release is available. Exploitation requires control over a format string.
These advisories also mark their parent packages, so the full audit reports 6 high and 19 moderate affected entries, not 25 independent root vulnerabilities. The production-only audit is clean. Keep these limitations explicit until upstream releases fix the chains; do not silently restore overrides or use npm audit fix --force to hide the remaining warnings.
Reuse the existing organization App addon-stack-dependency-updates; each package keeps its own workflow and dependency rules.
- In the
addon-stackorganization settings, open GitHub Apps → Configure for the existing installation and add inject-css under Only select repositories. Keep existing repositories selected. The existing App permissions are sufficient; no new App or key is needed. - Under Secrets and variables → Actions, ensure
inject-cssis selected for both the organization variableRENOVATE_APP_CLIENT_IDand the organization secretRENOVATE_APP_PRIVATE_KEY. The workflow creates a short-lived token scoped to this repository only. Renovate does not need an npm publishing token. - Merge the setup from
developintomain. Both scheduled runs and the manual workflow entry need the workflow file on the default branch. - Run Update Dependencies manually and inspect the first PR. Configure the PR check CI passed as required for
mainand require an up-to-date branch. Do not give the dependency App a branch-protection bypass. - Account for release automation before enforcing branch rules:
release-itpushes version/changelog commits tomain, and the sync step writes todevelop. Rules requiring PRs for all writes need a suitable exception for the release writer; the dependency App is not the release writer.
For another package, repeat the installation and organization-variable/secret access steps, then add its workflow, dependency allowlist, release policy, tests, and documentation. GitHub supports changing the repositories available to an installed App and sharing organization secrets with selected repositories.
Please read and follow our Code of Conduct in all interactions.
By contributing, you agree that your changes will be licensed under the project’s MIT License.