Skip to content

Repository files navigation

PagePatch

English | 简体中文

PagePatch — Custom CSS & JS is a Manifest V3 Chrome extension for applying custom styles and user scripts to pages selected by URL rules.

PagePatch Options page

Features

  • Manage multiple independent page rules.
  • Match pages with standard Chrome Match Patterns.
  • Add multiple remote CSS and JavaScript links in a defined order.
  • Combine remote resources with inline CSS and JavaScript.
  • Enable or disable each rule directly from the rule list.
  • Edit a saved rule name from the pen icon beside its editor title; unnamed rules display the page domain.
  • Filter rules by name, page URL, or resource URL.
  • Request host permissions only for configured pages and remote JavaScript sources; CSS links load without extension access to their domains.
  • Preview newly required JavaScript source domains before Chrome requests access.
  • Use Command+S on macOS or Ctrl+S on Windows/Linux to save.
  • Switch the Options page between English and Chinese.
  • Click PagePatch in the top-left corner to switch between light and dark themes.
  • Choose an isolated or page JavaScript environment independently for each rule.

Requirements

  • Google Chrome 135 or later.
  • Developer mode enabled when loading the unpacked extension.
  • For JavaScript rules on Chrome 138 or later, enable Allow User Scripts on the extension details page.

Install from source

  1. Open chrome://extensions/.
  2. Enable Developer mode.
  3. Select Load unpacked.
  4. Choose this project directory.
  5. Click the PagePatch toolbar icon to open the Options page.

Reload the extension from chrome://extensions/ after updating its source files.

Create a rule

  1. Click the + button beside the rule list heading.

  2. Enter a Chrome Match Pattern, for example:

    • https://example.com/*
    • *://*.example.com/*
    • https://example.com/docs/*
  3. Optionally add any combination of:

    • Remote CSS links
    • Inline CSS
    • Remote JavaScript links
    • Inline JavaScript
  4. Save the rule and approve the requested site permissions. Rules with remote JavaScript show the ungranted source domains before Chrome opens its permission request.

New rules use the domain from the page match pattern as their display name. After saving, click the pen icon beside the editor title to set or clear a custom name. Empty rules are also allowed.

Loading order and runtime behavior

  • Remote CSS links are added as ordered <link rel="stylesheet"> elements, followed by inline CSS injected with chrome.scripting.insertCSS().
  • Remote JavaScript links are fetched and executed in list order, followed by inline JavaScript.
  • JavaScript is fetched by the extension service worker and executed in the rule's selected world; the source URL therefore does not appear as a page network request.
  • Each rule can switch between the isolated USER_SCRIPT world and the page's MAIN world from the Page scripts heading. Save the rule to apply the change.
  • A failed remote JavaScript request is skipped without blocking later scripts.
  • Remote resources are requested when a matching page loads and follow normal HTTP cache behavior.
  • JavaScript executes once per rule version in the same document. Reordering sources, editing code, or changing the execution world creates a new version.
  • SPA URL changes are reconciled without requiring a full page reload.

Language

On first use, the Options page reads the first language returned by chrome.i18n.getAcceptLanguages():

  • Chinese language variants use Chinese.
  • All other languages use English.

Choosing 中文 or EN stores the selection in chrome.storage.local and overrides automatic detection on later visits.

The selected light or dark theme is also stored locally and restored when the Options page is reopened.

The extension name and description shown by Chrome use Manifest localization and follow Chrome's own interface locale.

Permissions and security

PagePatch declares:

  • scripting to add and remove CSS.
  • storage to persist rules, language and theme preferences, and per-tab state.
  • userScripts to execute user-provided JavaScript through Chrome's supported User Scripts API.
  • Optional HTTP/HTTPS host access, requested only for configured pages and remote JavaScript sources. CSS link domains are not requested.

Each rule can use Chrome's isolated USER_SCRIPT world or the page's MAIN world. In either mode, linked scripts run before inline Custom JS and can share variables and functions with it. The host page cannot access isolated-world globals; MAIN-world globals are shared with the page and should only be used with trusted scripts.

Only add CSS and JavaScript from sources you trust. Remote JavaScript has the same ability to modify a matched page as inline JavaScript.

Limitations

  • Content is injected only into the top-level page, not into iframes.
  • Chrome-protected pages such as chrome:// URLs and the Chrome Web Store cannot be modified.
  • Disabling a rule removes its injected CSS immediately, but JavaScript side effects usually remain until the page is refreshed.
  • Changing a JavaScript execution world runs a new rule version, but effects from the previous world can remain until the page is refreshed.
  • Remote JavaScript is executed as classic user-script code. Relative module imports are not supported.

Development

PagePatch uses plain HTML, CSS, and JavaScript with no build step or runtime dependencies.

Run all tests:

node --test tests/*.test.mjs

The test suite covers URL matching, rule validation, legacy data migration, permission aggregation, localization, CSS ordering, JavaScript ordering, and injection lifecycle behavior.

Package and release

Create a local Chrome Web Store ZIP using the version from manifest.json:

bash scripts/package-extension.sh

The archive is written to dist/PagePatch-X.Y.Z.zip. Release archives are ignored by Git and contain only the files required at extension runtime.

For a release, update manifest.json to a new semantic version, commit all intended changes, and run:

bash scripts/release.sh

The release script requires a clean main branch, runs all checks, creates the matching annotated vX.Y.Z tag, and atomically pushes main and the tag. Do not use a plain git push for release commits. The tag starts GitHub Actions, which creates or updates the corresponding GitHub Release and uploads the packaged extension.

Project structure

manifest.json       Extension manifest
background.js       CSS and JavaScript injection lifecycle
options.html        Options page markup
options.css         Options page styles
options.js          Rule editor and UI behavior
rules.mjs           Rule parsing, validation, and normalization
i18n.mjs            English and Chinese Options-page messages
_locales/           Chrome Manifest localization
icons/              Extension icon source and PNG sizes
tests/              Unit and background integration tests
scripts/            Packaging and release helpers
.github/workflows/  Tagged GitHub Release automation

About

Apply custom CSS and JavaScript to pages using URL rules.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages