SkillAgentSearch skills...

DotPageMod

Firefox WebExtension to load local CSS and JavaScript from your dotfiles into webpages

Install / Use

/learn @DonKult/DotPageMod
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Logo of dotPageMod dotPageMod

Firefox WebExtension to load local CSS and JavaScript from your dotfiles into webpages.

Features

  • each hostname has its own directory in your config directory of your own choosing
  • the hostname directories itself can be stored in independent packs for easier sharing and syncing (e.g. private, public, work, home, …)
  • port specific hosts with hostname_port
  • hostnames like mozilla.org match developer.mozilla.org
  • in fact: org matches all hosts in that top-level domain, too
  • ALL for all hosts (on http/https) or ALL_scheme for all hosts on a specific scheme
  • use FRAMEWORK directory to include any/all JavaScript/CSS frameworks (like JQuery) you might want to use in your scripts – they are automatically included before your scripts are sourced.
  • scripts can show desktop notifications without WebAPI (see Cheatsheet)
  • scripts are run in readyState interactive by default, but filenames ending in .start.js run scripts in loading and .idle.js at complete instead (see also RunAt).
  • your JavaScript/CSS works even if the page has them blocked by a Content Security Policy or uMatrix
  • your PageMods apply to the top window (not to frames) and apply to existing pages on (re)load
  • on deactivation CSS sheets are automatically unapplied, JavaScript modifications can be reverted by registering an undo method
  • on Linux with inotifywait (packaged in Debian in inotify-tools) the addon will reload automatically on relevant changes in the config directory
  • a badge on the toolbar button indicates how many files modify the current tab. A list of these files can be accessed in the panel. A red badge & filename indicates a file couldn't be applied, e.g. due to a programming error in it.

(Better?) Alternatives

So, why another one?

A long while ago I was using Greasemonkey, but just hiding a few elements with it felt very daunting with all this metadata and editing in a browser window. I regressed to using Adblock Plus and later uBlock Origin for cosmetic filtering and more and more to block the execution of JavaScript by default. Eventually I introduced uMatrix with a rigid block-policy to the mix which ended up leaving uBlock mostly jobless beside a bunch of cosmetic filters. Management of these isn't perfect through and sometimes you want more than just display: none – especially now that I had all of JavaScript blocked by default and some websites downright refuse to be usable without it (e.g. default collapsed infoboxes). So I moved my filters to ~/.css and started fixing up websites in ~/.js with dotjs. Quickly I ended up hitting issue #27: console.log doesn't work from dotjs which I researched and after commenting researched even more. Set out to write a patch to have this option set automatically I ended up changing other things as well until I realized that the architecture as-is wasn't to my liking (using a single global PageMod reading files dynamically and sending the content to be processed by eval (JS) and by DOM insertion (CSS) – the later failing in the event of a content policy forbidding inline CSS) – and I always wanted to look into developing Firefox extensions…

So, with a "how hard can it be?" I moved on to write my own extension to resolve my real as well as my imaginary problems by introducing new problems – not for me (hopefully), but potentially for anyone (else) wanting to use it…

Cheatsheet

path-specific CSS

@-moz-document url-prefix(http://www.w3.org/Style/) { }
@-moz-document regex("https:.*") { }

path-specific JavaScript

if (window.location.pathname === '/Style/')
if (window.location.pathname.startsWith('/Style/'))

undo changes

browser.runtime.onMessage.addListener(l => {
	if (l.cmd !== 'detach') return;
	// TODO: react here
});

Note: The example nano-framework has some wrappers and examples to undo common changes like event handlers, style toggles and removal of added elements.

Note: If a CSS file is changed and config reloaded the old CSS will be cleanly removed from open tabs and the new one applied. The situation is more complicated for JS: Individual files can't be unapplied (obviously), so in this case the tab gets the detach message described above and all JS files effecting this tab are reapplied. If the scripts effecting this tab have no clean detach behaviour you might be better off reloading the page to get a fresh start.

Beware: This doesn't work on addon update/removal as there is no API for it. The closest might be onSuspend but it is neither implemented in Firefox nor a good drop-in as it can still be cancelled and comes with no runtime guarantees whatsoever. I really hope browser vendors will make up their mind on this as this doesn't feel like a good user experience. On the upside, you hopefully don't need to update the extension itself all too often – and of course never need to remove it. ;)

showing desktop notifications

browser.runtime.sendMessage({'cmd': 'notify', 'title': title, 'message': msg});

Note: A notification via WebAPI requires the website to have permission for it, but our scripts are written by the user, so permission is implicitly given – and independent from the permission status of the website.

modifying current tab (pin, active, mute, reload, close, …)

browser.runtime.sendMessage('tab/activate');
browser.runtime.sendMessage('tab/pin');
browser.runtime.sendMessage('tab/unpin');
browser.runtime.sendMessage('tab/mute');
browser.runtime.sendMessage('tab/unmute');
browser.runtime.sendMessage('tab/close');
browser.runtime.sendMessage('tab/reload');
browser.runtime.sendMessage('tab/force-reload');
window.location = 'https://example.org';
browser.runtime.sendMessage({ cmd: 'tab/url', url: 'https://example.org'});

open a new tab

window.open(url, '_blank');
browser.runtime.sendMessage({ cmd: 'tab/open', active: true, pinned: false, window: 'tab', url: 'https://example.org' });

Note: The first option requires the website to have popup permissions. The second is less simple, but can open tabs in the 'current' window or in the window the tab belongs to the script runs in (default).

embedding images and co in CSS

SVG

URL encoding is enough here and has the benefit of allowing modifications still, the encoded string can be used as url(data:image/svg+xml,ENCODED).

perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "to encode"
echo 'to decode' | awk -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..

(Source for encode and decode commands)

binary image formats and other things

The URI needs to be url(data:image/TYPE;base64,ENCODED). Encoding can be done with base64 -w 0 < image.file.

URL to directory resolution

  • http://dotpagemod.example.com:8080/ => ALL, ALL_http, com, com_8080, example.com, example.com_8080, dotpagemod.example.com, dotpagemod.example.com_8080
  • http://dotpagemod.example.com/ => ALL, ALL_http, com, com_80, example.com, example.com_80, dotpagemod.example.com, dotpagemod.example.com_80
  • https://dotpagemod.example.com/ => ALL, ALL_https, com, com_443, example.com, example.com_443, dotpagemod.example.com, dotpagemod.example.com_443
  • ftp://dotpagemod.example.com/ => ALL_ftp, com, com_21, example.com, example.com_21, dotpagemod.example.com, dotpagemod.example.com_21

Examples

Websites like OpenUserJS, Greasy Fork and UserStyles can be an inspiration of what you could possibly do with your new JS/CSS powers given enough dedication. More (humble) examples can be easily found e.g. on github by searching for dotjs.

If you are more interested in seeing an example of how this extension could be used in practice by a user you can have a look at the examples folder.

Note: The examples are provided as-is, I am neither endorsing nor recommending using any of the examples or even the websites they might apply to even if they might have been used by me at some point in the past. No guarantees are made that they work as intended and/or (not) eat your babies (instead). You have been warned.

Website owners who find examples applying to their sites should remember that obviously a user has cared deeply enough about the site to modify it to cater even better to its own needs instead of moving away to a competitor before starting a "you are experiencing it all wrong – professionals have designed that for you!" frenzy. You might even recognize the chance to

View on GitHub
GitHub Stars9
CategoryDevelopment
Updated1mo ago
Forks2

Languages

JavaScript

Security Score

90/100

Audited on Feb 24, 2026

No findings