aboutsummaryrefslogtreecommitdiff
path: root/README
diff options
context:
space:
mode:
authorMiguel Ángel Moreno <mail@migalmoreno.com>2022-05-12 23:51:40 +0200
committerMiguel Ángel Moreno <mail@migalmoreno.com>2022-05-12 23:53:32 +0200
commit70b2b81f061669abcc6481651f14b0a731749c41 (patch)
treeb4caf35195dee131e84e28909db66dded6bd972e /README
parentf43d4161a715df35b2876db3c994e9821ab30c13 (diff)
chore: Splits extension into sub-extensions
Diffstat (limited to 'README')
-rw-r--r--README381
1 files changed, 59 insertions, 322 deletions
diff --git a/README b/README
index 4b1dbdc..4210253 100644
--- a/README
+++ b/README
@@ -1,370 +1,107 @@
# -*- mode: org; -*-
-#+title: nx-mapper
-=nx-mapper= is an extension for the [[https://nyxt.atlas.engineer/][Nyxt]] browser which aims at reducing the complexity associated with defining common browsing behaviors desired by power users in the form of two modes: [[#stylor-mode][stylor-mode]], which offers fine-grained control over Nyxt's themes and [[#rural-mode][rural-mode]], which allows you to build composable URL associations.
+#+title: nx-router
+=nx-router= is a URL routing extension for [[https://nyxt.atlas.engineer/][Nyxt]]. It lets you define fine-grained routes so you can enhance the browsing experience without get your attention sucked away. You can set up URL redirects, block lists, open resources with external applications, all in a cohesive configuration language.
* Installation
-To install the extension, you should download the source and place it in Nyxt's extensions path, by default given by the value of =nyxt-source-registry= (=~/.local/share/nyxt/extensions=).
+To install the extension, you need to download the source and place it in Nyxt's extensions path, given by the value of =(nyxt-source-registry)= (by default =~/.local/share/nyxt/extensions=).
#+begin_src sh
-git clone https://github.com/efimerspan/nx-mapper ~/.local/share/nyxt/nx-mapper
+git clone https://github.com/efimerspan/nx-router ~/.local/share/nyxt/nx-router
#+end_src
-It's worth noting that the extension works with Nyxt 3 onward, so you should probably use it with the latest version of Nyxt master for the time being.
+The extension works with *Nyxt 3 onward*, so ensure to use it with the latest version of Nyxt master for the time being.
-However, if you want to place the extension elsewhere in the system, such as for development purposes, you can configure so via the ASDF source registry mechanism. For this, you'll need to create a file in the source registry directory, =~/.config/common-lisp/source-registry.conf.d/=, and then put the following contents into it, replacing the path with the desired system path.
+If you want to place the extension elsewhere in the system, such as for development purposes, you can configure so via the ASDF source registry mechanism. For this, you'll need to create a file in the source registry directory, =~/.config/common-lisp/source-registry.conf.d/=, and then put the following contents into it, replacing the path with the desired system path.
#+name: 10-personal-lisp.conf
#+begin_src lisp
(:tree "/path/to/user/location")
#+end_src
-Then, make sure to refresh the ASDF cache via =asdf:clear-source-registry=. Now, ASDF will be able to find the extension on the custom path. For more information on this utility, please refer to the [[https://asdf.common-lisp.dev/asdf.html][ASDF manual]].
+Then, make sure to refresh the ASDF cache via =asdf:clear-source-registry=. ASDF will now be able to find the extension on the custom path. For more information on this utility, please refer to the [[https://asdf.common-lisp.dev/asdf.html][ASDF manual]].
However, by default Nyxt won't read the custom source registry path we provided, so ensure to include a =reset-asdf-registries= invocation in the Nyxt's initialization file too.
-Then, in the init file, ensure to include the following.
+In your Nyxt initialization file, place the following.
#+begin_src lisp
-(load-after-system :nx-mapper (nyxt-init-file "/path/to/mapper.lisp"))
+(load-after-system :nx-router (nyxt-init-file "/path/to/router.lisp"))
(define-configuration buffer
- ((default-modes
- (append
- ;; Either of them or both, depending on what functionality you want
- '(stylor:stylor-mode
- rural:rural-mode)
- %slot-default%)))
+ ((default-modes `(router:router-mode ,@%slot-default%))))
#+end_src
-Where =/path/to/mapper.lisp= is a custom file that should be created to provide the extension settings after the =nx-mapper= system has been successfully loaded. Inside this file, you can take two approaches when it comes to supplying the extension options, as described by the following.
-
-#+name: mapper.lisp
-#+begin_src lisp
-(define-configuration mapper:settings
- ;; provide all the mapping types
-)
-#+end_src
-
-As you might notice from the above, you can bundle everything into the global =nx-mapper:settings= class, but optionally you can configure everything per sub-extension too, which is useful if you want to split the configuration of each mode per file, such as by having a =style.lisp= for =stylor-mode= and a =url.lisp= for =rural-mode=. The next section gives examples of how to structure and configure each.
-
-#+name: stylor.lisp
-#+begin_src lisp
-(define-configuration stylor:stylor-mode
- ((stylor:auto-p t))) ;; Whether to set the browser theme according to system settings
-
-(define-configuration nx-mapper/stylor-mode:settings
- ((stylor:scripts
- ;; user script mappings
- )
- (stylor:external-themes
- ;; user styles mappings
- )
- (stylor:internal-themes
- ;; browser theme mappings
- )))
-#+end_src
-
-#+name: rural.lisp
-#+begin_src lisp
-(define-configuration rural:rural-mode
- ((rural:banner-p nil) ;; Whether to show a banner when encountering a block rule
- (rural:media-enabled-p nil))) ;; Whether to allow media in all sites
-
-(define-configuration rural:settings
- ((rural:url-mappings
- ;; URL associations mappings
- )))
-#+end_src
+Where =/path/to/router.lisp= is a custom file that should be created to provide the extension settings after the =nx-router= system has been successfully loaded. Inside this file, you should provide the extension options, explained in the following section.
* Configuration
-
-** stylor-mode
-:PROPERTIES:
-:CUSTOM_ID: stylor-mode
-:END:
-/stylor-mode/ acts like a userscript and userstyle manager, as well as an easy way to manage Nyxt's themes. Its functionality is split into three core parts:
-
-- Internal themes :: these tweak the overall browser's interface elements and allow you to change the browser's appearance on the fly.
-- External themes :: these map sources that act like triggers for which to apply CSS styles. These triggers are in the form of URL predicates and styles can be supplied as CSS strings, local path names, URLs where remote style sheets are hosted, or a function which takes the current internal theme and uses it to style the CSS. The latter is a nifty feature which allows you to share internal and external themes, achieving a more consistent look if that's something the user is interested in for a given site.
-- Scripts :: these also map sources which act like triggers for which an arbitrary JavaScript snippet will be executed. This is slightly more powerful than just altering the look via themes, as it also enables you to tweak the behavior of sites.
-
-Therefore, using these three concepts, you can include something along the following lines in your Nyxt init file.
+To get familiar with the format of URL rules in =nx-router=, see the following sample configuration along with the description of what each slot does.
#+begin_src lisp
-(import 'mapper:make-mapping)
+(import 'router:make-route)
-(define-configuration stylor:settings
- ((stylor:scripts
+(define-configuration router:router-mode
+ ((router:enforce-p t) ; Set this to non-nil to prevent you from disabling the mode
+ (router:media-enabled-p t) ; Show media in sites
+ (router:banner-p t) ; Show a banner upon visiting blocked sites
+ (router:routes
(list
- (make-mapping "FSF" '(match-domain "fsf.org")
- :script (ps:ps (setf (ps:@ document body |innerHTML|)
- "This was invoked by some sample JavaScript.")))))
- (stylor:external-themes
- (list
- (make-mapping "GitHub" '(match-domain "github.com")
- :style (cl-css:css '(("a[href*=watchers]"
- :display "none !important"))))
- (make-mapping "Lisp Documentation" '(match-domain "lisp.se" "lispworks.com")
- :style (lambda (theme)
- (theme:themed-css theme
- (*
- :background-color theme:background
- :color theme:text))))
- (make-mapping "Medium" '(match-domain "medium.com")
- :style (asdf:system-relative-pathname :nx-mapper "styles/medium.css"))
- (make-mapping "Nord Startpage" '(match-domain "startpage.com")
- :style (quri:uri "https://bpa.st/raw/4WYA"))))
- (stylor:internal-themes
- (list
- (make-mapping "Modus Operandi" nil
- :background-color "white"
- :text-color "black"
- :primary-color "#093060"
- :secondary-color "#f0f0f0"
- :tertiary-color "#dfdfdf"
- :quaternary-color "#005a5f"
- :accent-color "#8f0075"
- :font-family "Iosevka"
- :stylist (make-instance 'nx-mapper/stylor-mode:user-stylist))
- (make-mapping "Modus Vivendi" nil
- :dark-p t
- :background-color "black"
- :text-color "white"
- :primary-color "#c6eaff"
- :secondary-color "#323232"
- :tertiary-color "#323232"
- :quaternary-color "#a8a8a8"
- :accent-color "#afafef"
- :font-family "Iosevka"
- :stylist (make-instance 'nx-mapper/stylor-mode:user-stylist))))))
-#+end_src
-
-The above configuration initially defines a script mapping called =FSF= which matches on the =fsf.org= domain, thereby triggering the script provided by the =script= slot, which in this case will simply change the page's internal contents to effectively just show the string "/This was invoked by some sample JavaScript/".
-
-The next set of rules involve external themes, which carry the same principle as scripts in that they map a set of predicates to external styles specified by the =style= slot. As previously outlined, this style can be in the form of a CSS string, such as the one specified by the =GitHub= mapping (which uses the library =cl-css= that compiles Common Lisp into a CSS string). This first mapping, for instance, gets rid of the number specifying how many people are watching a repository. The =style= slot can also take a function that has the current active internal theme as its argument, such the one given by the =Lisp Documentation= mapping, which will essentially provide the same background and text color as the current internal theme for the whole site. If the style sheet becomes too big or you would like to use your favorite editor to tweak it, you can optionally also provide a pathname pointing to the CSS file. Finally, if you have your styles remotely backed up or stumble across one you like in a user-style or user-script platform like [[https://userstyles.world/][UserStyles.world]], you can simply point to their URL and they will be automatically applied.
-
-Finally, there's the internal themes rules, where as we can see from the above we have to issue a name for the mapping, and then a set of theme attributes which are built into the =nyxt/theme= library that ships with the browser as of version =2.2.4=. In addition to these, each internal theme can take a "/stylist/", a custom style crafter that allows you to style specific elements of the browser's interface if you aren't satisfied with the default layout of a certain element, such as the mode line, as well as allowing for dynamic theme change without having to restart the browser. A stylist effectively aims at reducing the complexity associated with having to manually define the =style= slot of many user classes, and can be defined as follows.
-
-#+begin_src lisp
-(define-configuration stylor:stylist
- ((stylor:name "Minimal UI")
- (stylor:prompt-style
- (lambda (theme)
- (theme:themed-css theme
- (* :font-family theme:font-family)
- ("#prompt-modes"
- :display "none")
- ("#prompt-area"
- :background-color theme:tertiary
- :color theme:quaternary
- :border "1px solid"
- :border-color (if (theme:dark-p theme:theme) theme:quaternary theme:text))
- ("#input"
- :background-color theme:tertiary
- :color theme:text)
- (".source-content"
- :border "none"
- :border-collapse collapse)
- (".source-name"
- :background-color theme:background
- :color theme:text
- :font-style "italic")
- (".source-content th"
- :padding-left "0"
- :background-color theme:background
- :font-weight "bold")
- (".source-content td"
- :padding "0 2px")
- ("#selection"
- :font-weight "bold"
- :background-color theme:secondary
- :color theme:text))))
- (stylor:buffer-style
- (lambda (theme)
- (theme:themed-css theme
- (body
- :font-family theme:font-family
- :background-color theme:background
- :color theme:text)
- ("h1,h2,h3,h4,h5,h6"
- :font-family "IBM Plex Sans"
- :color theme:primary)
- ("p,pre,td"
- :font-family "IBM Plex Sans"
- :color theme:text)
- (pre
- :background-color theme:tertiary)
- ("button,a:link"
- :color theme:text
- :font-family "IBM Plex Sans")
- (".button, .button:hover , .button:visited, .button:active"
- :background-color theme:secondary
- :border "1px solid"
- :border-color (if (theme:dark-p theme:theme) theme:quaternary theme:text)
- :color theme:text)
- (code
- :font-family "Iosevka"
- :background-color theme:tertiary))))
- (stylor:status-style
- (lambda (theme)
- (theme:themed-css theme
- (body
- :font-family theme:font-family
- :height "100%"
- :width "100%"
- :border "1px solid"
- :border-color (if (theme:dark-p theme:theme) theme:quaternary theme:text)
- :box-sizing "border-box"
- :line-height "20px"
- :display "flex"
- :flex-direction "column"
- :background theme:tertiary
- :flex-wrap "wrap")
- ("#container"
- :display "flex"
- :height "100%"
- :width "100%"
- :line-height "20px"
- :justify-content "space-between"
- :align-items "center")
- ("#buttons"
- :display "flex"
- :align-items "center"
- :justify-content "center"
- :line-height "20px"
- :height "100%")
- ("#url"
- :font-weight "bold"
- :max-width "60%"
- :padding-right "0"
- :padding-left "5px"
- :background-color theme:tertiary
- :color theme:text
- :box-sizing "border-box"
- :z-index "auto")
- ("#tabs, #controls" :display "none")
- ("#modes"
- :padding-right "2px"
- :background-color theme:tertiary
- :box-sizing "border-box"
- :color theme:text
- :display "flex"
- :justify-contents "flex-end"
- :z-index "auto")
- (.button
- :color theme:text))))
- (stylor:message-style
- (lambda (theme)
- (theme:themed-css theme
- (body
- :color theme:text
- :background-color theme:background
- :font-family theme:font-family))))
- (stylor:hint-style
- (lambda (theme)
- (theme:themed-css theme
- (".nyxt-hint"
- :background-color theme:primary
- :color theme:background
- :font-weight "bold"
- :padding "0px 3px"
- :border-radius "2px"
- :z-index #.(1- (expt 2 31))))))))
-#+end_src
-
-This is an example stylist which I use in my configuration for a more compact and minimal interface to the browser, which looks like the following, but the user is welcome to change each style slot as they see fit. Also, it's worth noting this is the default stylist, but you can pass any stylist object to an internal theme, to tweak the layout appearance per theme too.
-
-[[file:assets/stylist-dark.jpg]]
-
-[[file:assets/stylist-light.jpg]]
-
-** rural-mode
-:PROPERTIES:
-:CUSTOM_ID: rural-mode
-:END:
-=rural-mode= is an extension which enables fine-grained control over URL associations. Even though the Nyxt team is already working on a solution via =no-procrastinate-mode= which prevents the access to certain hosts as per [[https://github.com/atlas-engineer/nyxt/pull/1771][#1771]], as well as =blocker-mode=, which can also be leveraged to block the access to arbitrary hosts, I find that declaratively specifying these mappings in a consistent syntax and without having to rely on multiple external files is more cohesive. Also, even though there's already a Nyxt extension which provides redirections in the form of [[https://github.com/kssytsrk/nx-freestance-handler][nx-freestance-handler]], I quickly felt its limitation in the number of sites it provides support for, as I found myself adding more request resource handlers to my own configuration. As such, I decided to roll out a more general-purpose solution, so the user is not limited to a predefined number of URL associations and can mold flexible mappings as they please.
-
-Therefore, you can set up a configuration for some URL mappings such as what follows in your Nyxt initialization file.
-
-#+begin_src lisp
-(import 'mapper:make-mapping)
-
-(define-configuration rural:settings
- ((rural:url-mappings
- (list
- ;; 1
- (make-mapping "Instagram" '((match-domain "instagram.com")
- (match-regex "https://bibliogram.*")
- :redirect '("insta.trom.tf" (:path ("/u" (not "/" "/p/" "/tv"))))
- :instances (lambda ()
- (delete
- nil
- (mapcar
- (lambda (instance)
- (unless (str:emptyp
- (alex:assoc-value instance :url))
- (alex:assoc-value instance :url)))
- (json:with-decoder-simple-list-semantics
- (json:decode-json-from-string
- (dex:get
- "https://bibliogram.art/api/instances"))))))))
- ;; 2
- (make-mapping "Reddit" '(match-domain "reddit.com")
- :redirect "teddit.namazso.eu"
- :blocklist '(:path (:contains (not "/comments"))))
- ;; 3
- (make-mapping "Audio" '((match-regex ".*/watch\\?v=.*")
- (match-file-extension "mp3")
+ (make-route '((match-domain "instagram.com")
+ (match-regex "https://bibliogram.*"))
+ :redirect '("insta.trom.tf" (:path ("/u" (not "/" "/p/" "/tv"))))
+ :instances (lambda ()
+ (delete
+ nil
+ (mapcar
+ (lambda (instance)
+ (unless (str:emptyp
+ (alex:assoc-value instance :url))
+ (alex:assoc-value instance :url)))
+ (json:with-decoder-simple-list-semantics
+ (json:decode-json-from-string
+ (dex:get
+ "https://bibliogram.art/api/instances")))))))
+ (make-route (match-domain "reddit.com")
+ :redirect "teddit.namazso.eu"
+ :blocklist '(:path (:contains (not "/comments"))))
+ (make-route '((match-regex ".*/watch\\?v=.*")
+ (match-file-extension "mp3")
:redirect "youtube.com"
:external (lambda (data)
(eval-in-emacs
`(init-multimedia-mpv-start
,(quri:render-uri (url data))
:audio-only t :repeat t)))))
- ;; 4
- (make-mapping "Amazon" '(match-domain "amazon.com")
- :blocklist '(:host (:starts (not "smile"))))
- ;; 5
- (make-mapping "Lemmy" '(match-domain "lemmy.ml")
- :blocklist '(:path (:contains ("post") :starts ("/u"))))
- ;; 6
- (make-mapping "GitHub" '(match-domain "github.com")
- :blocklist '(:path (or 1 (:contains (not "pulls" "search")))))
- ;; 7
- (make-mapping "Blocked" '((match-domain "timewastingsite1.com"
- "timewastingsite2.com"))
- :blocklist t)))))
+ (make-route (match-domain "amazon.com")
+ :blocklist '(:host (:starts (not "smile"))))
+ (make-route (match-domain "lemmy.ml")
+ :blocklist '(:path (:contains ("post") :starts ("/u"))))
+ (make-route (match-domain "github.com")
+ :blocklist '(:path (or 1 (:contains (not "pulls" "search")))))
+ (make-route (match-domain "timewastingsite1.com"
+ "timewastingsite2.com")
+ :blocklist t)))))
#+end_src
-=rural-mode= mapping slots can hold the following values:
+=route= slots include a mini-DSL that specifies what URL part to block as well as the comparison type. Personally, I believe this is a bit more straightforward than having to fiddle around with complex regular expressions. The following is a detailed description of all the available slots:
-- =:redirect= :: this can take a redirect URL as a string, or a single pair of the form =(REPLACEMENT-PATH ORIGINAL-PATHS)=, where =ORIGINAL-PATHS= is a list of paths of the original URL which will be redirected to =REPLACEMENT-PATH=. If you want to redirect all paths except =ORIGINAL-PATHS= to =REPLACEMENT-PATH=, prefix this list with =not=.
-- =:blocklist= :: this is a property list of blocking conditions in the form of =(TYPE VALUE)=, where =TYPE= can be one of =:path= or =:host=, and =VALUE= is either another property list of the form =(TYPE PATHNAMES)=, where =TYPE= is either =:starts=, =:ends=, or =:contains= to denote the URL comparison and =PATHNAMES= is a list of URL pathnames to draw the comparison against, or an integer to indicate the number of URL /sections/ (e.g. =https://example.com/section_1/section_2=) to block in case the blocking condition value is not known. If =PATHNAMES= is prefixed with =not=, all sites will be blocked except for the specified list. Also, a blocklist can be given the value =t= to block the whole URL for the defined sources.
+- =:redirect= :: can take a redirect URL as a string, or a single pair of the form =(REPLACEMENT-PATH ORIGINAL-PATHS)=, where =ORIGINAL-PATHS= is a list of paths of the original URL which will be redirected to =REPLACEMENT-PATH=. If you want to redirect all paths except =ORIGINAL-PATHS= to =REPLACEMENT-PATH=, prefix this list with =not=.
+- =:blocklist= :: a property list of blocking conditions in the form of =(TYPE VALUE)=, where =TYPE= can be one of =:path= or =:host=, and =VALUE= is either another property list of the form =(TYPE PATHNAMES)=, where =TYPE= is either =:starts=, =:ends=, or =:contains= to denote the URL comparison and =PATHNAMES= is a list of URL pathnames to draw the comparison against, or an integer to indicate the number of URL /sections/ (e.g. =https://example.com/section_1/section_2=) to block in case the blocking condition value is not known. If =PATHNAMES= is prefixed with =not=, all sites will be blocked except for the specified list. Also, a blocklist can be given the value =t= to block the whole URL for the defined sources.
- =:external= :: used to open resources externally. If it's a function, it takes a single parameter =REQUEST-DATA= and can invoke arbitrary Lisp forms within it. If provided as a string, it will run the specified command via =uiop:run-program= with the current URL as its argument in a =format=-like syntax.
-- =:media-p= :: whether to show media in the resource or not. This is useful if you want to block all media via the =nx-mapper/rural-mode:media-enabled-p= slot in =nx-mapper/rural-mode:settings=, but only override it for certain resources.
+- =:media-p= :: whether to show media in the resource or not. This is useful if you want to block all media via the =router:media-enabled-p= slot, but only override it for certain resources.
- =:instances= :: provides a list of instances to add to the default sources automatically computed via a custom function, which is useful if a service provides an official endpoint where these are stored.
-The following describes the above examples:
-
-1. Set up all Instagram requests to redirect to the host =insta.trom.tf= and additionally redirect all its paths which don't start with =/=, =/p/=, or =/tv= to =/u= paths, as this is what the [[https://bibliogram.art/][Bibliogram]] alternative Instagram front-end uses for its URL structure. Do note this mapping also takes an =instances= slot, which can be either a list or a function that will compute a list of instances. This is useful if the service used to redirect the predicates offers a list of predefined instances, and these will also be added to the mapping's predicates on mapping instantiation. Indeed, mapping sources can also consist of lists of predicates for which to match URLs, which means on the =Instagram= mapping above, it will match either domains that contain =instagram.com= or URLs that contain the regexp starting with =https://bibliogram.*=. This was added to allow for more granularity, so that mappings can get applied on more triggers.
-
-2. Redirect all Reddit requests to the =teddit.namazso.eu= host and additionally block all of the paths pertaining to such trigger except the ones that contain the =/comments= path. This would essentially limit the user to only being able to access Reddit publications instead of sections like its main feed.
-
-3. Matches on YouTube video URLs, videos hosted on its alternative front-ends such as [[https://invidious.io/][Invidious]], as well as MP3 files, redirecting all of these requests to =youtube.com=, and dispatching a rule which invokes an external program with the current request data, in this case launching an [[https://mpv.io/][mpv]] player IPC client process to control the player from Emacs. Do note this is a custom function from my configuration, but we could also pass a one-placeholder format string such as =mpv --video=no ~a= to the =:external= slot if we'd rather not use a Lisp form, where =~a= represents the current mapping URL.
-
-4. Showcases the use of a hostname blocklist, in this case preventing the user from accessing Amazon URLs unless they contain the =smile= hostname.
+The following describes the above routers as per their order.
-5. Consists of a blocklist for certain paths of the =lemmy.ml= domain; namely, the blocked paths would be those that contain =post= on them or the ones that start with =/u=, which would block all publications and user profiles on the site.
+- Set up all Instagram requests to redirect to the host =insta.trom.tf= and additionally redirect all its paths which don't start with =/=, =/p/=, or =/tv= to =/u= paths, as this is what the [[https://bibliogram.art/][Bibliogram]] alternative Instagram front-end uses for its URL structure. Do note this route also takes an =instances= slot, which can be either a list or a function that will compute a list of instances. This is useful if the service used to redirect the predicates offers a list of predefined instances, and these will also be added to the route's predicates on route instantiation. Indeed, triggers can also consist of lists of predicates for which to match URLs, which means on the =Instagram= route above, it will match either domains that contain =instagram.com= or URLs that contain the regexp starting with =https://bibliogram.*=.
-6. Provides a combined path rule for =github.com= requests. Combined rules (specified via =or=) in paths allow you to specify two or more predicates that you wish to draw the path comparison against. In this combination, the integer will first indicate that we want to block those paths that consist of a single sub-section (e.g. =https://github.com/profile_name=), /or/ block all paths except the ones which contain =pulls= or =search=. This essentially allows you to specify a more general block rule and bypass it for certain scenarios. In this case, it would block all single-sub-section paths on =github.com= (such as profiles, the marketplace and so on) but at the same time allow you to use GitHub's search engine and see your listed pull requests.
+- Redirect all Reddit requests to the =teddit.namazso.eu= host and additionally block all of the paths belonging to this trigger except those that contain the =/comments= path. This would essentially limit the user to only being able to access Reddit publications instead of sections like its main feed.
-7. Serves as a general blocklist trigger. To block an entire URL predicate or list of predicates, you can simply pass =t= to the =blocklist= slot.
+- Matches on YouTube video URLs, videos hosted on its alternative front-ends such as [[https://invidious.io/][Invidious]], as well as MP3 files, redirecting all of these requests to =youtube.com=, and dispatching a rule which invokes an external program with the current request data, in this case launching an [[https://mpv.io/][mpv]] player IPC client process to control the player from Emacs. Do note this is a custom function from my configuration, but we could also pass a one-placeholder format string such as =mpv --video=no ~a= to the =:external= slot if we'd rather not use a Lisp form, where =~a= represents the current route URL.
-** Customization Interface
-For those who aren't well versed with Lisp yet or don't like to tweak around with configuration files, a customization interface is provided through the =customize-mappings= command, which will show a two-paned settings page consisting of an automatically generated code snippet to be pasted in the user's Nyxt initialization file on the left pane and the actual extension settings on the right pane.
+- Showcases the use of a hostname blocklist, in this case preventing the user from accessing Amazon URLs unless they contain the =smile= hostname.
-Thus, the user can tweak the configuration on the right pane, being able to add, delete, and edit mappings as well as seeing their information in a more user-friendly interface, which is especially useful if they aren't used to a language with lots parentheses. Changes will see themselves reflected on the left pane as the user changes them, but it's important to note these will only persist for the current Nyxt session and it's thereby crucial one copies them over to their configuration so they get persisted.
+- Consists of a blocklist for certain paths of the =lemmy.ml= domain; namely, the blocked paths would be those that contain =post= on them or the ones that start with =/u=, which would block all publications and user profiles on the site.
-Moreover, there are some interactive commands like =select-internal-theme= which also allow the user to change the current theme on the fly without having to tweak their configuration.
+- Provides a combined path rule for =github.com= requests. Combined rules (specified via =or=) in paths allow you to specify two or more predicates that you wish to draw the path comparison against. In this combination, the integer will first indicate that we want to block those paths that consist of a single sub-section (e.g. =https://github.com/profile_name=), /or/ block all paths except the ones which contain =pulls= or =search=. This essentially allows you to specify a more general block rule and bypass it for certain scenarios. In this case, it would block all single-sub-section paths on =github.com= (such as profiles, the marketplace and so on) but at the same time allow you to use GitHub's search engine and see your listed pull requests.
-[[file:assets/custom.jpg]]
+- Serves as a general blocklist trigger. To block an entire URL predicate or list of predicates, you can simply pass =t= to the =blocklist= slot.