Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

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

License

NotificationsYou must be signed in to change notification settings

DonKult/dotPageMod

Repository files navigation

Logo of dotPageMod dotPageMod

FirefoxWebExtensionto 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 easiersharing and syncing (e.g. private, public, work, home, …)
  • port specific hosts withhostname_port
  • hostnames likemozilla.org matchdeveloper.mozilla.org
  • in fact:org matches all hosts in that top-level domain, too
  • ALL for all hosts (on http/https) orALL_scheme for all hosts on aspecific scheme
  • useFRAMEWORK directory to include any/all JavaScript/CSS frameworks (likeJQuery) you might want to use in your scripts – they are automaticallyincluded before your scripts are sourced.
  • scripts can show desktop notifications without WebAPI (see Cheatsheet)
  • scripts are run inreadyStateinteractive by default, but filenames ending in.start.js runscripts inloading and.idle.js atcomplete instead(see alsoRunAt).
  • your JavaScript/CSS works even if the page has them blocked by aContentSecurity Policy oruMatrix
  • your PageMods apply to the top window (not to frames) and apply to existingpages on (re)load
  • on deactivation CSS sheets are automatically unapplied, JavaScript modificationscan be reverted by registering an undo method
  • on Linux with inotifywait (packaged in Debian ininotify-tools) the addonwill 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 & filenameindicates 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 usingGreasemonkey, butjust hiding a few elements with it felt very daunting with all this metadataand editing in a browser window. Iregressed to usingAdblockPlus and lateruBlockOrigin for cosmetic filtering and more andmore to block the execution of JavaScript by default. Eventually I introduceduMatrix with a rigid block-policy to themix which ended up leaving uBlock mostly jobless beside a bunch of cosmeticfilters. Management of these isn't perfect through and sometimes you want morethan justdisplay: none – especially now that I had all of JavaScript blockedby default and some websites downright refuse to be usable without it (e.g.default collapsed infoboxes). So I moved my filters to~/.css and startedfixing up websites in~/.js withdotjs.Quickly I ended up hitting issue#27: console.log doesn't work fromdotjs which I researched andafter commenting researched even more. Set out to write a patch to have thisoption set automatically I ended up changing other things as well until Irealized that the architecture as-is wasn't to my liking (using a single globalPageMod reading files dynamically and sending the content to be processed byeval (JS) and by DOM insertion (CSS) – the later failing in the event of acontent policy forbidding inline CSS) – and I always wanted to look intodeveloping Firefox extensions…

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

Cheatsheet

@-moz-document url-prefix(http://www.w3.org/Style/) { }@-moz-document regex("https:.*") { }
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 commonchanges like event handlers, style toggles and removal of added elements.

Note: If a CSS file is changed and config reloaded the old CSS will becleanly removed from open tabs and the new one applied. The situation is morecomplicated for JS: Individual files can't be unapplied (obviously), so inthis case the tab gets the detach message described above and all JS files effectingthis tab are reapplied. If the scripts effecting this tab have no clean detachbehaviour 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 beonSuspendbut it is neither implemented in Firefox nor a good drop-in as it can still be cancelledand comes with no runtime guarantees whatsoever. I really hope browser vendors will makeup 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 coursenever need to remove it. ;)

showing desktop notifications

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

Note: Anotification viaWebAPI requiresthe website to have permission for it, but our scripts are written by the user,so permission is implicitly given – and independent from the permission statusof 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 thewindow 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 asurl(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 forencodeanddecode commands)

binary image formats and other things

The URI needs to beurl(data:image/TYPE;base64,ENCODED).Encoding can be done withbase64 -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 likeOpenUserJS,GreasyFork andUserStyles can bean inspiration of what you could possibly do with your new JS/CSS powers givenenough dedication. More (humble) examples can be easily found e.g. on github bysearching fordotjs.

If you are more interested in seeing an example of how this extension could beused in practice by a user you can have a look at theexamplesfolder.

Note: The examples are provided as-is, I am neither endorsing norrecommending using any of the examples or even the websites they might apply toeven if they might have been used by me at some point in the past. Noguarantees 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 thatobviously a user has cared deeply enough about the site to modify it to catereven better to its own needs instead of moving away to a competitor beforestarting a "you are experiencing it all wrong – professionals have designedthat for you!" frenzy. You might even recognize the chance to incorporate thechanges into your design for the benefit of all users (if applicable).

If you want to have a look you should start exploring withFRAMEWORK/david.jsas this nano framework is heavily used in the example configuration – nothingprevents you from using heavier guns like JQuery in your own set of course.

Feel free to propose more examples in patches and pull-requests, but note thatI reserve the right to deny any proposal if I deem the example unworthy by mysole reasoning. This explicitly includes examples whose sole purpose it is tohide elements on a page as nobody needs to see an example ofdisplay: none¹even if that is a valid usecase in practice and my own config contains plentyof those.

¹ if you really want to see one:ALL/antisocial.css was made for you.

Installation

At the moment you have to build the extension yourself to install it. Giventhat I approximate the userbase to be only me, I have no plans to shuffle theaddon into the review queue as it would just waste valuable reviewer time.That also means you have to run a Developer/Nightly edition of Firefox as itisn't signed and only those allow disabling the signature requirement withtheabout:config optionxpinstall.signatures.required you have to set tofalse (see alsoMozillas FAQ on extension signing).

If the intro wasn't discouraging enough for you want to first choose a permanentlocation on your disk to store this repository in for simplicity as you are about tocreate a softlink to the native application configuration file (at least thatis what you need to do on Linux, seeNative messaging documentationfor details).make install tries to do the right thing for your current user.

With the native app done, you need to install the webextension itself. You can eitherchoose to use one of the releases published on Github or built it yourself from source;that isn't hard, don't worry! You even have two options:

Building with Docker

You can useDocker (packaged asdocker.io in Debian)to build the add-on if you so choose. The includedDockerfilehas the details if you are unsure how to do it. If you follow it by the letter youwill end up with a checkout of the git repository in/mnt/dotPageMod as yourpermanent location which will including a builtdotpagemod.xpi.

Building manually

Apart from a typical Linux system you already have, you will likely need to installPandoc andzip.Checkout the repository to the permanent location you have chosen, then it isas simple as runningmake which will produce adotpagemod.xpi file for you.

Configuring the extension

After acquiring an xpi file including the webextension you can installit e.g. viaabout:addonsInstall Add-on from File….

Now that you have the extension installed you will need to configure it.Clicking on the new button and in the opening panel on the addon name in theincluded title bar brings you the fastest to the option panel, but you can alsogo the usual way as for any other extensions of course.

The options want you to specify a directory containing your scripts andstylesheets. Where you want to store them is up to you and depends a bit on howmuch you want to share the collections (across profiles, users, computers, …),but you can change the path anytime you like so don't worry too much now andjust pick a place. In this directory copy/link the examples/ directory in (notthe content, the entire directory). After you have set and saved the option youshould be able to visit a website modified by the examples and see the extensionworking. If not something is probably wrong with the app: Seeburger menuDeveloperBrowser console. From there you can either keep the examples(or not), modify them and start your own collections. Have fun fixing the web!

Contributing aka Where are all the testcases?

Looking at the source it doesn't take long to figure out that the addon codecomes with no tests attached. Why is that you might ask – and you are right!I pondered hard about this myself, but ultimately decided that the way thisaddon works is too hard to test for me at this point in time given no previousexperience with addon development as a whole and that nearly all interestingfunctions deal heavily with files which isn't exactly a strong suite of the SDK.Until this will inescapably bite me (and it surely will), I will kid you and mealike that this addon is sufficiently small to not need automatic tests…

You can treat the examples folder as well as your personal collection as atestcase – it is what I do. So, if you happen to want to provide a patch, feelfree to implement an example for its use as well and fling it my way.

What is in the name?

Back in early 2016 the best way to create a Firefox extension was to use theAdd-on SDK. In the SDK an API calledpage-modwas used to modify webpages by inserting JS and CSS files. The SDK is no moreand the API used by WebExtensions is entirely different, but the name stayed asthe underlying idea remains true: Having a firefox extension which readsdotfiles and modifies pages with it.

Why isn't it working on about: pages or addons.mozilla.org?

The reason is security. WebExtensions aren't allowed to insert code intoprivileged tabs like about: pages and a few other domains to avoid peoplebeing tricked by evil extensions and co. The older extension types didn'thave such restrictions. Perhaps one day there is a way to get themworking again for all tabs if a user can manage the risk.

At least for "restricted domains" in Firefox you can use the hiddenabout:config optionextensions.webextensions.restrictedDomains tomodify the set – including making it empty, so that e.g. the includedexample foraddons.mozilla.org works again. This option doesNOTaffectabout: pages or the PDF viewer through.

Logo

The logo is derived from Technology Class CSS3-Styling Icon which accompaniesthe official HTML5 LogoHTML5 Logo byW3C under theCC-BY-3.

The original is black – I am coloring the 'J' in this stylised 3 in yellowand the remaining 2 strokes in blue as JavaScript and CSS tend to be shown withthose shield colors accompanying the HTML5 icon. They are also the colors oftheSelfHTML logo which was a happy accidentthrough.

Not very creative, I know, but it seemed better than using a gear or wrench…

License

Apart from the logo, which is (also) licensed under theCreative CommonsAttribution 3.0 as mentioned inthe previous paragraph, the extension isMIT (Expat) licensed.


[8]ページ先頭

©2009-2025 Movatter.jp