Userscript @match & @exclude to match paths at certain level, but not sublevels

288 Views Asked by At

How can one use @match and @exclude rules in a userscript to match URLs that have an arbitrary path at a certain level (a "level" being each new / in the path, not sure if there's a more technical name for it), but not at sublevels (i.e. having subsequent forward-slashes /)?

Example

A userscript is intended to match the homepage of any subreddit on Reddit.com, but not any sub-pages of that subreddit. This is what I've tried:

@match    https://*.reddit.com/r/*/
@exclude  https://*.reddit.com/r/*/*/

My understanding is that this SHOULD match, for example, https://reddit.com/r/funny but NOT match https://reddit.com/r/funny/submit, https://reddit.com/r/funny/new, https://reddit.com/r/funny/comments/blahblahblah, etc. However, my userscript seems to be firing on those sub-pages anyway.

I'm basing this construction off the Mozilla documentation for Match Patterns, which states:

Pattern

https://mozilla.org/\*/b/\*/

Match HTTPS URLs hosted on "mozilla.org", whose path contains a component "b" somewhere in the middle. Will match URLs with query strings, if the string ends in a /.

Example matches

https://mozilla.org/a/b/c/

https://mozilla.org/d/b/f/

https://mozilla.org/a/b/c/d/

https://mozilla.org/a/b/c/d/#section1

https://mozilla.org/a/b/c/d/?foo=/

https://mozilla.org/a?foo=21314&bar=/b/&extra=c/

Example non-matches

https://mozilla.org/b/*/

(unmatched path)

https://mozilla.org/a/b/

(unmatched path)

https://mozilla.org/a/b/c/d/?foo=bar

(unmatched path due to URL query string)

I know I could solve this using the deprecated @include with RegEx (or RegEx in @exclude, for that matter, as Regex in userscript rules generally reduces performance). I know I could add logic to my userscript that validates the pathname before executing the rest of the script, but I'd like an elegant solution using only the basic @match and @exclude if possible.

Is there a better way to form these rules to make that happen?

1

There are 1 best solutions below

3
erosman On

Match Patterns are working correctly, but there are other considerations.

Test Script

Note: Some sites, like Reddit, use JavaScript to navigate between pages, which requires additional consideration to run the script.
Open each URL in a new tab, for testing.

// ==UserScript==
// @name          Match Test Script
// @match         https://*.reddit.com/r/*/
// @exclude       https://*.reddit.com/r/*/*/
// ==/UserScript==

console.log('Match Test Script', location.href);

Result

Tested above with FM|GM|TM|VM and all were working as expected.

Match

https://www.reddit.com/r/funny/

No Match

https://www.reddit.com/r/funny/submit
https://www.reddit.com/r/funny/submit/
https://www.reddit.com/r/funny/comments/14jmh7e/forging_a_return_to_productive_conversation_an/

UserScript matching in manifest v3

Once MV3 scripting is fully implemented for userscripts, all userscript managers are expected to use Match Patterns.

UserScript matching in manifest v2

Currently, userscript managers use different methods to match & inject userscripts.

  • GM|TM|VM convert match/include/exclude to regular expression and manually check matching for injection
    (TM has started to use the dedicated API in some cases on Firefox)
  • FireMonkey uses the dedicated API and Firefox checks matching for injection based on Match Patterns