]> git.armaanb.net Git - chorizo.git/commitdiff
draft
authorArmaan Bhojwani <me@armaanb.net>
Tue, 12 Oct 2021 01:45:48 +0000 (21:45 -0400)
committerArmaan Bhojwani <me@armaanb.net>
Tue, 12 Oct 2021 03:08:15 +0000 (23:08 -0400)
20 files changed:
.clang-format
.gitignore
Makefile
README
browser.c [new file with mode: 0644]
chorizo-usage.7 [new file with mode: 0644]
chorizo.1 [new file with mode: 0644]
chorizo.desktop [deleted file]
chorizo.ini [deleted file]
config.h [new file with mode: 0644]
downloads.c [new file with mode: 0644]
downloads.h [new file with mode: 0644]
extensions/we_adblock.c
man/chorizo-config.5.scd [deleted file]
man/chorizo-usage.1.scd [deleted file]
man/chorizo.1.scd [deleted file]
src/browser.c [deleted file]
src/downloads.c [deleted file]
src/downloads.h [deleted file]
user-scripts/darkreader.js [new file with mode: 0644]

index 3577d9dd6de9a5a7afd5da743263515861f67574..29b06b02ce7fb7d55734e4ed14a6afd077cc30fa 100644 (file)
@@ -1,3 +1,98 @@
-BasedOnStyle: llvm
-AlwaysBreakAfterReturnType: AllDefinitions
-IndentWidth: 4
\ No newline at end of file
+# SPDX-License-Identifier: GPL-2.0, Linux Kernel, Armaan Bhojwani
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Left # Unknown to clang-format-4.0
+AlignOperands: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: true
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+  AfterClass: false
+  AfterControlStatement: false
+  AfterEnum: false
+  AfterFunction: true
+  AfterNamespace: true
+  AfterStruct: false
+  AfterUnion: false
+  AfterExternBlock: false # Unknown to clang-format-5.0
+  BeforeCatch: false
+  BeforeElse: false
+  IndentBraces: false
+  SplitEmptyFunction: true # Unknown to clang-format-4.0
+  SplitEmptyRecord: true # Unknown to clang-format-4.0
+  SplitEmptyNamespace: true # Unknown to clang-format-4.0
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false # Unknown to clang-format-4.0
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: false # Unknown to clang-format-4.0
+IncludeBlocks: Preserve # Unknown to clang-format-5.0
+IncludeCategories:
+  - Regex: '.*'
+    Priority: 1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+IndentPPDirectives: None # Unknown to clang-format-5.0
+IndentWidth: 8
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+
+PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakString: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 60
+
+PointerAlignment: Right
+ReflowComments: false
+SortIncludes: false
+SortUsingDeclarations: false # Unknown to clang-format-4.0
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
+SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp03
+TabWidth: 8
+UseTab: Always
index 55b25925675edf78ccad5e6117651e91b04543e3..0ad50fca324a99e7fcbea8b99d1a0d08cbc5ae6a 100644 (file)
@@ -1,5 +1,2 @@
 chorizo
 *.so
-darkreader.js
-*.1
-*.5
\ No newline at end of file
index fe0f4aba950f9f6fdbe345a7a2f863aeba0b00fd..40a4089b68f4726bc17888261b033dc31a375230 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,54 +1,40 @@
-CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3
-
+CFLAGS += -std=c11 -Wall -Wextra -Wno-unused-parameter -D_XOPEN_SOURCE="700"
+LIBS = `pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0`
 PREFIX = /usr/local
 bindir = $(DESTDIR)$(PREFIX)/bin
 libdir = $(DESTDIR)$(PREFIX)/lib
 datadir = $(DESTDIR)$(PREFIX)/share
-mandir = $(datadir)/man
-docdir = $(datadir)/doc
-
-.PHONY: man clean uninstall install extensions
+mandir = $(DESTDIR)/$(PREFIX)/man
 
-all: man chorizo extensions darkreader
+.PHONY: chorizo clean uninstall install extensions update-darkreader
 
-man:
-       for i in man/*.scd; do \
-               printf "SCDOC\t%s\n" $$i; \
-               scdoc < $$i > $$(echo "$$i" | rev | cut -f 2- -d '.' | rev); \
-       done
+all: extensions chorizo
 
 chorizo:
-       $(CC) $(CFLAGS) $(LDFLAGS) \
-               -D__NAME__=\"chorizo\" \
-               -D__NAME_UPPERCASE__=\"CHORIZO\" \
-               -DVERSION=\"v1.0.0\" \
-               -o chorizo src/*.c \
-               `pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0`
+       $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o chorizo *.c
+
+format:
+       for i in *.c *.h; do clang-format $$i > tmp; mv tmp $$i; done
 
 extensions:
        for i in extensions/*.c; do \
                outp=$$(echo "$$i" | sed 's/\$\.c/.so/g'); \
-               $(CC) $(CFLAGS) $(LDFLAGS) \
-                       -D__NAME__=\"chorizo\" \
-                       -D__NAME_UPPERCASE__=\"CHORIZO\" \
-                       -shared -o $$outp -fPIC $$i \
-                       `pkg-config --cflags --libs glib-2.0 webkit2gtk-4.0`; \
+               $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $$outp -fPIC $$i $(LIBS); \
        done
 
 install: all
        mkdir -p $(bindir) \
                $(mandir)/man1 \
-               $(mandir)/man5 \
+               $(mandir)/man7 \
                $(libdir)/chorizo/web-extensions \
-               $(datadir)/chorizo/user-scripts \
-               $(datadir)/applications \
-               $(docdir)/chorizo
+               $(datadir)/chorizo/user-scripts
 
        cp chorizo $(bindir)/
-       cp man/*.1 $(mandir)/man1/
-       cp man/*.5 $(mandir)/man5/
-       cp chorizo.ini $(docdir)/chorizo/
-       cp chorizo.desktop $(datadir)/applications/
+
+       cp chorizo.1 $(mandir)/man1/
+       cp chorizo-usage.7 $(mandir)/man7/
+       makewhatis /usr/local/man
+
        cp -r extensions/*.so $(libdir)/chorizo/web-extensions/
        cp -r user-scripts/* $(datadir)/chorizo/user-scripts/
 
@@ -56,14 +42,12 @@ uninstall:
        rm -rf $(bindir)/chorizo \
                $(libdir)/chorizo \
                $(mandir)/man1/chorizo* \
-               $(mandir)/man5/chorizo* \
-               $(datadir)/chorizo \
-               $(datadir)/applications/chorizo.desktop \
-               $(docdir)/chorizo
+               $(mandir)/man7/chorizo* \
+               $(datadir)/chorizo
 
 reinstall: uninstall install
 
-darkreader:
+update-darkreader:
        curl -L "https://cdn.jsdelivr.net/npm/darkreader/darkreader.min.js" \
                -o user-scripts/darkreader.js
        echo >> user-scripts/darkreader.js
@@ -71,8 +55,4 @@ darkreader:
                >> user-scripts/darkreader.js
 
 clean:
-       rm -fv chorizo \
-               extensions/*.so \
-               man/*.1 \
-               man/*.5 \
-               user-scripts/darkreader.js
+       rm -fv chorizo extensions/*.so
diff --git a/README b/README
index 373d692a0d7d09a965c3f75a23f2b5303f044a87..a42cedd3563e14239cb34ea0e32b946557440bb7 100644 (file)
--- a/README
+++ b/README
@@ -1,31 +1,11 @@
-        _                _
-    ___| |__   ___  _ __(_)_______
-   / __| '_ \ / _ \| '__| |_  / _ \
-  | (__| | | | (_) | |  | |/ / (_) |
-   \___|_| |_|\___/|_|  |_/___\___/
-  https://sr.ht/~armaan/chorizo
+chorizo
+======
 
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+http://armaanb.net/chorizo.html
 
 A simple web browser using GTK+ 3, GLib and WebKit2GTK+.
 
-Features:
-    - A WebKit2 viewport
-    - An input box to change the URI, search the current page, or
-      search the web
-    - Tab management
-    - Full keyboard control
-    - An ini configuration file
-    - Built-in download manager
-    - Web feeds indicator
-    - Global content zoom
-    - Cooperative instances using FIFOs
-    - Certificate trust store
-    - User script support
-    - Extensions
-
-Refer to the manpages chorizo(1), chorizo-usage(1), and
-chorizo-config(5), for more information.
+Refer to the manpages chorizo(1), and chorizo-usage(1) for more information.
 
 Installation
 ------------
@@ -34,10 +14,12 @@ The following C libraries are required:
 
     - GTK+ 3
     - WebKit2 API for GTK+ 3
-    - gst-libav, gst-plugins-good - for media playback
+    - gst-libav, gst-plugins-good (for media playback)
 
-To generate the manpages, scdoc is required. This isn't necesary on
-release tarballs.
+The following programs are required:
+    - A C compiler supporting C11
+    - make
+    - pkg-config
 
 chorizo expects to be run on a POSIX-ish operating system.
 
@@ -47,62 +29,22 @@ To build and install the program:
     # make install
 
 
-Background information
-----------------------
-
-What chorizo is and what it's not
-
-  chorizo does what I need. It won't do other things. I'm open for
-  contributions but please don't be upset if I turn them down -- which
-  might happen if it's a feature that I simply don't need.
-
-  chorizo does not compete with powerful browsers like dwb or luakit, nor
-  with monstrous applications like Firefox or Chromium. Because under
-  the hood chorizo is powered by WebKit, however, it is on par with
-  browsers like Safari for page rendering features.
-
 How is chorizo related to lariza?
+---------------------------------
 
   chorizo is a fork of the lariza browser by Peter Hofmann. I wanted
   to take it in a slightly different direction (mostly just adding
   features not considered to be in the spirit of lariza), so I forked
   it. The name was changed in order to reduce confusion between the
-  two browsers as they grew apart. The versioning scheme was also
-  moved away from being calendar-based.
+  two browsers as they grew apart.
 
-  Features that this fork has that lariza is missing:
-    - Configuration file
+  Differences:
+    - New versioning scheme
     - Revamped download manager
-    - New, ergonomic keybindings inspire by both Emacs and Vim
+    - New keybindings
     - Better default directories
-    - Easily togglable images and JavaScript
+    - Easily togglable JavaScript
     - Cleaned up source code
     - Easy web searching
     - User stylesheet support
     - A variety of tweaks and adjustments that make the experience nicer
-
-Migrating from another browser
-------------------------------
-
-From lariza:
-  1. Copy the relevant paths from ~/.config/lariza to
-  ~/.local/share/chorizo. Read chorizo(1) for full details on the
-  correct paths.
-
-  2. Your symlinks from /usr will broken, so you should relink everything.
-
-  3. Read lariza-config(5), as the keybindings are radically different
-  out of the box. Everything is configurable, however, and you can
-  reconfigure the bindings to act just like your previous browser.
-
-From Firefox/Chromium/Brave/etc:
-  1. Set your expectations right. Read the background information
-  section of the README.
-
-  2. Copy the cookie database into ~/.local/share/lariza/cookies.db.
-
-  3. Read all the manpages.
-
-Copyright
----------
-MIT License, see the LICENSE file for more information.
diff --git a/browser.c b/browser.c
new file mode 100644 (file)
index 0000000..020ce9f
--- /dev/null
+++ b/browser.c
@@ -0,0 +1,1298 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <webkit2/webkit2.h>
+
+#include "config.h"
+#include "downloads.h"
+
+WebKitWebView *client_new_request(WebKitWebView *, WebKitNavigationAction *,
+                                 gpointer);
+gboolean crashed_web_view(WebKitWebView *, gpointer);
+gboolean decide_policy(WebKitWebView *, WebKitPolicyDecision *,
+                      WebKitPolicyDecisionType, gpointer);
+gboolean key_location(GtkWidget *, GdkEvent *, gpointer);
+gboolean key_tablabel(GtkWidget *, GdkEvent *, gpointer);
+gboolean key_web_view(GtkWidget *, GdkEvent *, gpointer);
+gboolean remote_msg(GIOChannel *, GIOCondition, gpointer);
+gchar *ensure_uri_scheme(const gchar *);
+void changed_favicon(GObject *, GParamSpec *, gpointer);
+void changed_load_progress(GObject *, GParamSpec *, gpointer);
+void changed_title(GObject *, GParamSpec *, gpointer);
+void changed_uri(GObject *, GParamSpec *, gpointer);
+void grab_feeds_finished(GObject *, GAsyncResult *, gpointer);
+void hover_web_view(WebKitWebView *, WebKitHitTestResult *, guint, gpointer);
+void icon_location(GtkEntry *, GtkEntryIconPosition, GdkEvent *, gpointer);
+void mainwindow_title(gint);
+void notebook_switch_page(GtkNotebook *, GtkWidget *, guint, gpointer);
+void show_web_view(WebKitWebView *, gpointer);
+void trust_user_certs(WebKitWebContext *);
+
+struct Client {
+       GtkWidget *jsbutton;
+       GtkWidget *location;
+       GtkWidget *tabicon;
+       GtkWidget *tablabel;
+       GtkWidget *vbox;
+       GtkWidget *web_view;
+       WebKitSettings *settings;
+       gboolean focus_new_tab;
+       gchar *external_handler_uri;
+       gchar *feed_html;
+       gchar *hover_uri;
+};
+
+struct MainWindow {
+       GtkWidget *notebook;
+       GtkWidget *win;
+} mw;
+
+struct Configuration {
+       gboolean cooperative_alone;
+       gboolean noncooperative_instances;
+       gboolean private;
+       gboolean verbose;
+} cfg;
+
+gint clients = 0;
+struct Client **client_arr;
+
+int cooperative_pipe_fp = 0;
+gchar *search_text;
+gchar *fifopath;
+char **closed_tabs;
+
+void
+togglejs(GtkButton *jsbutton, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       webkit_settings_set_enable_javascript(
+               c->settings,
+               !webkit_settings_get_enable_javascript(c->settings));
+       webkit_web_view_set_settings(WEBKIT_WEB_VIEW(c->web_view), c->settings);
+}
+
+void
+client_destroy(GtkWidget *widget, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       gint idx;
+       g_signal_handlers_disconnect_by_func(G_OBJECT(c->web_view),
+                                            changed_load_progress, c);
+
+       idx = gtk_notebook_page_num(GTK_NOTEBOOK(mw.notebook), c->vbox);
+       if (idx == -1)
+               fprintf(stderr, "chorizo: Tab index was -1, bamboozled\n");
+       else
+               gtk_notebook_remove_page(GTK_NOTEBOOK(mw.notebook), idx);
+
+       if (!cfg.private && WEBKIT_IS_WEB_VIEW(c->web_view)) {
+               int len = sizeof(closed_tabs) / sizeof(char *);
+               const char *uri =
+                       webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
+               closed_tabs = (char **)realloc(closed_tabs,
+                                              len * sizeof(closed_tabs[0]));
+               closed_tabs[len] = strdup(uri);
+       }
+
+       free(c);
+       clients--;
+
+       quit_if_nothing_active();
+}
+
+void
+set_uri(const char *uri, struct Client *c)
+{
+       if (!gtk_widget_is_focus(c->location))
+               gtk_entry_set_text(GTK_ENTRY(c->location),
+                                  (uri != NULL) ? uri : "");
+}
+
+WebKitWebView *
+client_new(const gchar *uri, WebKitWebView *related_wv, gboolean show,
+          gboolean focus_tab)
+{
+       struct Client *c;
+       gchar *f;
+       GtkWidget *evbox, *tabbox;
+       if (uri != NULL && !cfg.noncooperative_instances &&
+           !cfg.cooperative_alone) {
+               f = ensure_uri_scheme(uri);
+               write(cooperative_pipe_fp, f, strlen(f));
+               write(cooperative_pipe_fp, "\n", 1);
+               g_free(f);
+               return NULL;
+       }
+       c = calloc(1, sizeof(struct Client));
+       if (!c) {
+               fprintf(stderr, "chorizo: fatal: calloc failed\n");
+               exit(EXIT_FAILURE);
+       }
+       c->focus_new_tab = focus_tab;
+
+       if (related_wv == NULL) {
+               WebKitUserContentManager *ucm =
+                       webkit_user_content_manager_new();
+               WebKitUserScript *wkscript;
+               WebKitUserStyleSheet *wkstyle;
+               gchar *path = NULL, *source, *base;
+               const gchar *entry = NULL;
+               GDir *dir = NULL;
+               base = g_build_filename(g_get_user_data_dir(), "chorizo",
+                                       "user-scripts", NULL);
+               dir = g_dir_open(base, 0, NULL);
+               if (dir != NULL) {
+                       while ((entry = g_dir_read_name(dir)) != NULL) {
+                               path = g_build_filename(base, entry, NULL);
+                               if (g_str_has_suffix(path, ".js")) {
+                                       g_file_get_contents(path, &source, NULL,
+                                                           NULL);
+                                       wkscript = webkit_user_script_new(
+                                               source,
+                                               WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
+                                               WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
+                                               NULL, NULL);
+                                       webkit_user_content_manager_add_script(
+                                               ucm, wkscript);
+                                       webkit_user_script_unref(wkscript);
+                               }
+                               g_free(path);
+                               if (source)
+                                       g_free(source);
+                       }
+                       g_dir_close(dir);
+               }
+               base = g_build_filename(g_get_user_data_dir(), "chorizo",
+                                       "user-styles", NULL);
+               dir = g_dir_open(base, 0, NULL);
+               if (dir != NULL) {
+                       while ((entry = g_dir_read_name(dir)) != NULL) {
+                               path = g_build_filename(base, entry, NULL);
+                               if (g_str_has_suffix(path, ".css")) {
+                                       g_file_get_contents(path, &source, NULL,
+                                                           NULL);
+                                       wkstyle = webkit_user_style_sheet_new(
+                                               source,
+                                               WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
+                                               WEBKIT_USER_STYLE_LEVEL_USER,
+                                               NULL, NULL);
+                                       webkit_user_content_manager_add_style_sheet(
+                                               ucm, wkstyle);
+                                       webkit_user_style_sheet_unref(wkstyle);
+                               }
+                               g_free(path);
+                               g_free(source);
+                       }
+                       g_dir_close(dir);
+               }
+               g_free(base);
+
+               c->web_view =
+                       webkit_web_view_new_with_user_content_manager(ucm);
+       } else {
+               c->web_view = webkit_web_view_new_with_related_view(related_wv);
+       }
+
+       c->settings =
+               webkit_web_view_get_settings(WEBKIT_WEB_VIEW(c->web_view));
+       webkit_settings_set_enable_javascript(c->settings, cfg_js_default);
+       if (cfg.verbose) {
+               webkit_settings_set_enable_write_console_messages_to_stdout(
+                       c->settings, true);
+       }
+       webkit_settings_set_enable_developer_extras(c->settings, TRUE);
+
+       g_signal_connect(G_OBJECT(c->web_view), "notify::favicon",
+                        G_CALLBACK(changed_favicon), c);
+       g_signal_connect(G_OBJECT(c->web_view), "notify::title",
+                        G_CALLBACK(changed_title), c);
+       g_signal_connect(G_OBJECT(c->web_view), "notify::uri",
+                        G_CALLBACK(changed_uri), c);
+       g_signal_connect(G_OBJECT(c->web_view),
+                        "notify::estimated-load-progress",
+                        G_CALLBACK(changed_load_progress), c);
+       g_signal_connect(G_OBJECT(c->web_view), "create",
+                        G_CALLBACK(client_new_request), NULL);
+       g_signal_connect(G_OBJECT(c->web_view), "close",
+                        G_CALLBACK(client_destroy), c);
+       g_signal_connect(G_OBJECT(c->web_view), "decide-policy",
+                        G_CALLBACK(decide_policy), NULL);
+       g_signal_connect(G_OBJECT(c->web_view), "key-press-event",
+                        G_CALLBACK(key_web_view), c);
+       g_signal_connect(G_OBJECT(c->web_view), "button-release-event",
+                        G_CALLBACK(key_web_view), c);
+       g_signal_connect(G_OBJECT(c->web_view), "scroll-event",
+                        G_CALLBACK(key_web_view), c);
+       g_signal_connect(G_OBJECT(c->web_view), "mouse-target-changed",
+                        G_CALLBACK(hover_web_view), c);
+       g_signal_connect(G_OBJECT(c->web_view), "web-process-crashed",
+                        G_CALLBACK(crashed_web_view), c);
+
+       GtkWidget *locbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+       c->jsbutton = gtk_toggle_button_new_with_label("JS");
+       gtk_widget_set_tooltip_text(c->jsbutton, "Toggle JavaScript execution");
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->jsbutton),
+                                    cfg_js_default);
+       g_signal_connect(G_OBJECT(c->jsbutton), "toggled", G_CALLBACK(togglejs),
+                        c);
+
+       c->location = gtk_entry_new();
+       gtk_box_pack_start(GTK_BOX(locbox), c->location, TRUE, TRUE, 0);
+
+       if (cfg.private) {
+               GtkWidget *privindicator = gtk_label_new("Private mode");
+               gtk_widget_set_tooltip_text(
+                       privindicator,
+                       "You are in private mode. No history, caches, or "
+                       "cookies will be saved beyond this session.");
+               gtk_box_pack_end(GTK_BOX(locbox), privindicator, FALSE, FALSE,
+                                5);
+       }
+       gtk_box_pack_start(GTK_BOX(locbox), c->jsbutton, FALSE, FALSE, 5);
+
+       g_signal_connect(G_OBJECT(c->location), "key-press-event",
+                        G_CALLBACK(key_location), c);
+       g_signal_connect(G_OBJECT(c->location), "icon-release",
+                        G_CALLBACK(icon_location), c);
+       /*
+       * XXX This is a workaround. Setting this to NULL (which is done in
+       * grab_feeds_finished() if no feed has been detected) adds a little
+       * padding left of the text. Not sure why. The point of this call
+       * right here is to have that padding right from the start. This
+       * avoids a graphical artifact.
+       */
+
+       gtk_entry_set_icon_from_icon_name(GTK_ENTRY(c->location),
+                                         GTK_ENTRY_ICON_SECONDARY, NULL);
+
+       c->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+       gtk_box_pack_start(GTK_BOX(c->vbox), locbox, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(c->vbox), c->web_view, TRUE, TRUE, 0);
+       gtk_container_set_focus_child(GTK_CONTAINER(c->vbox), c->web_view);
+
+       c->tabicon = gtk_image_new_from_icon_name("text-html",
+                                                 GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+       c->tablabel = gtk_label_new("chorizo");
+       gtk_label_set_ellipsize(GTK_LABEL(c->tablabel), PANGO_ELLIPSIZE_END);
+       gtk_label_set_width_chars(GTK_LABEL(c->tablabel), 20);
+       gtk_widget_set_has_tooltip(c->tablabel, TRUE);
+
+       /*
+       * XXX I don't own a HiDPI screen, so I don't know if scale_factor
+       * does the right thing.
+       */
+       tabbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
+                            5 * gtk_widget_get_scale_factor(mw.win));
+       gtk_box_pack_start(GTK_BOX(tabbox), c->tabicon, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(tabbox), c->tablabel, TRUE, TRUE, 0);
+
+       evbox = gtk_event_box_new();
+       gtk_container_add(GTK_CONTAINER(evbox), tabbox);
+       g_signal_connect(G_OBJECT(evbox), "button-release-event",
+                        G_CALLBACK(key_tablabel), c);
+
+       gtk_widget_add_events(evbox, GDK_SCROLL_MASK);
+       g_signal_connect(G_OBJECT(evbox), "scroll-event",
+                        G_CALLBACK(key_tablabel), c);
+
+       //For easy access, store a reference to our label.
+       g_object_set_data(G_OBJECT(evbox), "chorizo-tab-label", c->tablabel);
+
+       /*
+       * This only shows the event box and the label inside, nothing else.
+       * Needed because the evbox/label is "internal" to the notebook and
+       * not part of the normal "widget tree" (IIUC).
+       */
+       gtk_widget_show_all(evbox);
+
+       int page = gtk_notebook_get_current_page(GTK_NOTEBOOK(mw.notebook)) + 1;
+       gtk_notebook_insert_page(GTK_NOTEBOOK(mw.notebook), c->vbox, evbox,
+                                page);
+       gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(mw.notebook), c->vbox,
+                                        TRUE);
+
+       if (show)
+               show_web_view(NULL, c);
+       else
+               g_signal_connect(G_OBJECT(c->web_view), "ready-to-show",
+                                G_CALLBACK(show_web_view), c);
+
+       if (uri != NULL) {
+               f = ensure_uri_scheme(uri);
+               webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->web_view), f);
+               g_free(f);
+       }
+       set_uri(uri, c);
+
+       clients++;
+       client_arr = realloc(client_arr, (clients + 1) * sizeof(client_arr[0]));
+       client_arr[clients] = c;
+
+       if (clients == 1 || uri == NULL)
+               gtk_widget_grab_focus(c->location);
+
+       return WEBKIT_WEB_VIEW(c->web_view);
+}
+
+WebKitWebView *
+client_new_request(WebKitWebView *web_view,
+                  WebKitNavigationAction *navigation_action, gpointer data)
+{
+       return client_new(NULL, web_view, FALSE, FALSE);
+}
+
+void
+mkdirp(const char *dir, mode_t mode)
+{
+       char tmp[256];
+       char *p = NULL;
+       size_t len;
+       snprintf(tmp, sizeof(tmp), "%s", dir);
+       len = strlen(tmp);
+       if (tmp[len - 1] == '/')
+               tmp[len - 1] = 0;
+       for (p = tmp + 1; *p; p++)
+               if (*p == '/') {
+                       *p = 0;
+                       mkdir(tmp, mode);
+                       *p = '/';
+               }
+       mkdir(tmp, S_IRWXU);
+}
+
+void
+cooperation_setup(void)
+{
+       GIOChannel *towatch;
+       gchar *fifofilename;
+
+       gchar *priv = (cfg.private) ? "-private" : "";
+       const gchar *fifo_suffix_env = g_getenv("CHORIZO_FIFO_SUFFIX");
+       const gchar *fifo_suffix = (fifo_suffix_env) ? fifo_suffix_env : "";
+       fifofilename = g_strdup_printf("%s%s%s%s", "chorizo", priv, ".fifo",
+                                      fifo_suffix);
+       fifopath = g_build_filename(g_get_user_runtime_dir(), "chorizo",
+                                   fifofilename, NULL);
+       mkdirp(dirname(fifopath), 0600);
+       g_free(fifofilename);
+
+       if (!g_file_test(fifopath, G_FILE_TEST_EXISTS))
+               mkfifo(fifopath, 0600);
+
+       cooperative_pipe_fp = open(fifopath, O_WRONLY | O_NONBLOCK);
+       if (!cooperative_pipe_fp) {
+               fprintf(stderr, "chorizo: Can't open FIFO at all.\n");
+       } else {
+               if (write(cooperative_pipe_fp, "", 0) == -1) {
+                       /*
+                       * Could not do an empty write to the FIFO which
+                       * means there's no one listening.
+                       */
+                       close(cooperative_pipe_fp);
+                       towatch = g_io_channel_new_file(fifopath, "r+", NULL);
+                       g_io_add_watch(towatch, G_IO_IN, (GIOFunc)remote_msg,
+                                      NULL);
+               } else {
+                       cfg.cooperative_alone = FALSE;
+               }
+       }
+}
+
+void
+changed_load_progress(GObject *obj, GParamSpec *pspec, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       gdouble p;
+       gchar *grab_feeds =
+               "a = document.querySelectorAll('"
+               "    html > head > "
+               "link[rel=\"alternate\"][href][type=\"application/atom+xml\"],"
+               "    html > head > "
+               "link[rel=\"alternate\"][href][type=\"application/rss+xml\"]"
+               "');"
+               "if (a.length == 0)"
+               "    null;"
+               "else {"
+               "    out = '';"
+               "    for (i = 0; i < a.length; i++) {"
+               "        url = encodeURIComponent(a[i].href);"
+               "        if ('title' in a[i] && a[i].title != '')"
+               "            title = encodeURIComponent(a[i].title);"
+               "        else"
+               "            title = url;"
+               "        out += '<li><a href=\"' + url + '\">' + title + "
+               "'</a></li>';"
+               "    }"
+               "    out;"
+               "}";
+       p = webkit_web_view_get_estimated_load_progress(
+               WEBKIT_WEB_VIEW(c->web_view));
+       if (p == 1) {
+               p = 0;
+
+               /*
+               * The page has loaded fully. We now run the short JavaScript
+               * snippet above that operates on the DOM. It tries to grab
+               * all occurences of <link rel="alternate" ...>, i.e.
+               * RSS/Atom feed references.
+               */
+               webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(c->web_view),
+                                              grab_feeds, NULL,
+                                              grab_feeds_finished, c);
+       }
+       gtk_entry_set_progress_fraction(GTK_ENTRY(c->location), p);
+}
+
+void
+changed_favicon(GObject *obj, GParamSpec *pspec, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       cairo_surface_t *f;
+       int w, h, w_should, h_should;
+       GdkPixbuf *pb, *pb_scaled;
+       f = webkit_web_view_get_favicon(WEBKIT_WEB_VIEW(c->web_view));
+       if (f == NULL) {
+               gtk_image_set_from_icon_name(GTK_IMAGE(c->tabicon), "text-html",
+                                            GTK_ICON_SIZE_SMALL_TOOLBAR);
+       } else {
+               w = cairo_image_surface_get_width(f);
+               h = cairo_image_surface_get_height(f);
+               pb = gdk_pixbuf_get_from_surface(f, 0, 0, w, h);
+               if (pb != NULL) {
+                       w_should = 16 * gtk_widget_get_scale_factor(c->tabicon);
+                       h_should = 16 * gtk_widget_get_scale_factor(c->tabicon);
+                       pb_scaled = gdk_pixbuf_scale_simple(
+                               pb, w_should, h_should, GDK_INTERP_BILINEAR);
+                       gtk_image_set_from_pixbuf(GTK_IMAGE(c->tabicon),
+                                                 pb_scaled);
+
+                       g_object_unref(pb_scaled);
+                       g_object_unref(pb);
+               }
+       }
+}
+
+void
+changed_title(GObject *obj, GParamSpec *pspec, gpointer data)
+{
+       const gchar *t, *u;
+       struct Client *c = (struct Client *)data;
+       u = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
+       t = webkit_web_view_get_title(WEBKIT_WEB_VIEW(c->web_view));
+
+       u = u == NULL ? "chorizo" : u;
+       u = u[0] == 0 ? "chorizo" : u;
+
+       t = t == NULL ? u : t;
+       t = t[0] == 0 ? u : t;
+
+       gchar *name = malloc(strlen(t) + 4);
+       gboolean mute =
+               webkit_web_view_get_is_muted(WEBKIT_WEB_VIEW(c->web_view));
+       gchar *muted = (mute) ? "[m] " : "";
+       sprintf(name, "%s%s", muted, t);
+       gtk_label_set_text(GTK_LABEL(c->tablabel), name);
+       g_free(name);
+
+       gtk_widget_set_tooltip_text(c->tablabel, t);
+       mainwindow_title(
+               gtk_notebook_get_current_page(GTK_NOTEBOOK(mw.notebook)));
+}
+
+void
+changed_uri(GObject *obj, GParamSpec *pspec, gpointer data)
+{
+       const gchar *t;
+       struct Client *c = (struct Client *)data;
+       FILE *fp;
+       t = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
+
+       /*
+       * When a web process crashes, we get a "notify::uri" signal, but we
+       * can no longer read a meaningful URI. It's just an empty string
+       * now. Not updating the location bar in this scenario is important,
+       * because we would override the "WEB PROCESS CRASHED" message.
+       */
+       if (t != NULL && strlen(t) > 0) {
+               set_uri(t, c);
+
+               //No g_get_user_state_dir unfortunately
+               gchar *state_env = getenv("XDG_STATE_DIR");
+               gchar *state_dir = (state_env) ?
+                                          state_env :
+                                          g_build_filename(g_get_home_dir(),
+                                                           ".local", "state",
+                                                           "chorizo", NULL);
+
+               gchar *history_file =
+                       g_build_filename(state_dir, "history", NULL);
+               if (!cfg.private) {
+                       mkdirp(state_dir, 0700);
+                       fp = fopen(history_file, "a");
+                       if (fp != NULL) {
+                               fprintf(fp, "%s\n", t);
+                               fclose(fp);
+                       } else {
+                               perror("chorizo: Error opening history file");
+                       }
+               }
+               g_free(history_file);
+               g_free(state_dir);
+       }
+}
+gboolean
+crashed_web_view(WebKitWebView *web_view, gpointer data)
+{
+       gchar *t;
+       struct Client *c = (struct Client *)data;
+       t = g_strdup_printf("WEB PROCESS CRASHED: %s",
+                           webkit_web_view_get_uri(WEBKIT_WEB_VIEW(web_view)));
+       gtk_entry_set_text(GTK_ENTRY(c->location), t);
+       g_free(t);
+
+       return TRUE;
+}
+gboolean
+decide_policy(WebKitWebView *web_view, WebKitPolicyDecision *decision,
+             WebKitPolicyDecisionType type, gpointer data)
+{
+       WebKitResponsePolicyDecision *r;
+       switch (type) {
+       case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
+               r = WEBKIT_RESPONSE_POLICY_DECISION(decision);
+               if (!webkit_response_policy_decision_is_mime_type_supported(r))
+                       webkit_policy_decision_download(decision);
+               else
+                       webkit_policy_decision_use(decision);
+               break;
+       default:
+               //Use whatever default there is.
+               return FALSE;
+       }
+       return TRUE;
+}
+
+gchar *
+ensure_uri_scheme(const gchar *t)
+{
+       gchar *f, *fabs;
+       f = g_ascii_strdown(t, -1);
+       if (!g_str_has_prefix(f, "http:") && !g_str_has_prefix(f, "https:") &&
+           !g_str_has_prefix(f, "file:") && !g_str_has_prefix(f, "about:") &&
+           !g_str_has_prefix(f, "data:") && !g_str_has_prefix(f, "webkit:")) {
+               g_free(f);
+               fabs = realpath(t, NULL);
+               if (fabs != NULL) {
+                       f = g_strdup_printf("file://%s", fabs);
+                       free(fabs);
+               } else {
+                       f = g_strdup_printf("http://%s", t);
+               }
+               return f;
+       } else
+               return g_strdup(t);
+}
+
+void
+grab_feeds_finished(GObject *object, GAsyncResult *result, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       WebKitJavascriptResult *js_result;
+       JSCValue *value;
+       JSCException *exception;
+       GError *err = NULL;
+       gchar *str_value;
+       g_free(c->feed_html);
+       c->feed_html = NULL;
+
+       /*
+       * This was taken almost verbatim from the example in WebKit's
+       * documentation:
+       *
+       * https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html
+       */
+
+       js_result = webkit_web_view_run_javascript_finish(
+               WEBKIT_WEB_VIEW(object), result, &err);
+       if (!js_result) {
+               fprintf(stderr, "chorizo: Error running javascript: %s\n",
+                       err->message);
+               g_error_free(err);
+               return;
+       }
+       value = webkit_javascript_result_get_js_value(js_result);
+       if (jsc_value_is_string(value)) {
+               str_value = jsc_value_to_string(value);
+               exception =
+                       jsc_context_get_exception(jsc_value_get_context(value));
+               if (exception != NULL) {
+                       fprintf(stderr,
+                               "chorizo: Error running javascript: %s\n",
+                               jsc_exception_get_message(exception));
+               } else {
+                       c->feed_html = str_value;
+               }
+
+               gtk_entry_set_icon_from_icon_name(
+                       GTK_ENTRY(c->location), GTK_ENTRY_ICON_SECONDARY,
+                       "application-rss+xml-symbolic");
+               gtk_entry_set_icon_activatable(GTK_ENTRY(c->location),
+                                              GTK_ENTRY_ICON_SECONDARY, TRUE);
+       } else {
+               gtk_entry_set_icon_from_icon_name(
+                       GTK_ENTRY(c->location), GTK_ENTRY_ICON_SECONDARY, NULL);
+       }
+
+       webkit_javascript_result_unref(js_result);
+}
+
+void
+hover_web_view(WebKitWebView *web_view, WebKitHitTestResult *ht,
+              guint modifiers, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       const char *to_show;
+       g_free(c->hover_uri);
+
+       if (webkit_hit_test_result_context_is_link(ht)) {
+               to_show = webkit_hit_test_result_get_link_uri(ht);
+               c->hover_uri = g_strdup(to_show);
+       } else {
+               to_show = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
+               c->hover_uri = NULL;
+       }
+
+       if (!gtk_widget_is_focus(c->location))
+               set_uri(to_show, c);
+}
+
+void
+icon_location(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event,
+             gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       gchar *d;
+       gchar *data_template = "data:text/html,"
+                              "<!DOCTYPE html>"
+                              "<html>"
+                              "    <head>"
+                              "        <meta charset=\"UTF-8\">"
+                              "        <title>Feeds</title>"
+                              "    </head>"
+                              "    <body>"
+                              "        <p>Feeds found on this page:</p>"
+                              "        <ul>"
+                              "        %s"
+                              "        </ul>"
+                              "    </body>"
+                              "</html>";
+       if (c->feed_html != NULL) {
+               /*
+               * What we're actually trying to do is show a simple HTML
+               * page that lists all the feeds on the current page. The
+               * function webkit_web_view_load_html() looks like the proper
+               * way to do that. Sad thing is, it doesn't create a history
+               * entry, but instead simply replaces the content of the
+               * current page. This is not what we want.
+               *
+               * RFC 2397 [0] defines the data URI scheme [1]. We abuse this
+               * mechanism to show my custom HTML snippet* and*create a
+               * history entry.
+               *
+               * [0]: https://tools.ietf.org/html/rfc2397 [1]:
+               * https://en.wikipedia.org/wiki/Data_URI_scheme
+               */
+
+               d = g_strdup_printf(data_template, c->feed_html);
+               webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->web_view), d);
+               g_free(d);
+       }
+}
+
+void
+init_default_web_context(void)
+{
+       gchar *p;
+       WebKitWebContext *wc;
+       WebKitCookieManager *cm;
+       wc = (cfg.private) ? webkit_web_context_new_ephemeral() :
+                            webkit_web_context_get_default();
+
+       p = g_build_filename(g_get_user_config_dir(), "chorizo", "adblock",
+                            NULL);
+       webkit_web_context_set_sandbox_enabled(wc, TRUE);
+       webkit_web_context_add_path_to_sandbox(wc, p, TRUE);
+       g_free(p);
+
+       WebKitProcessModel model =
+               WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES;
+       webkit_web_context_set_process_model(wc, model);
+
+       p = g_build_filename(g_get_user_data_dir(), "chorizo", "web-extensions",
+                            NULL);
+       webkit_web_context_set_web_extensions_directory(wc, p);
+       g_free(p);
+
+       char *xdg_down = getenv("XDG_DOWNLOAD_DIR");
+       g_signal_connect(G_OBJECT(wc), "download-started",
+                        G_CALLBACK(download_start),
+                        (xdg_down) ? xdg_down : "/var/tmp");
+
+       trust_user_certs(wc);
+
+       cm = webkit_web_context_get_cookie_manager(wc);
+       webkit_cookie_manager_set_accept_policy(cm, cfg_cookie_policy);
+
+       if (!cfg.private) {
+               webkit_web_context_set_favicon_database_directory(wc, NULL);
+
+               gchar *fname = g_build_filename("/", g_get_user_data_dir(),
+                                               "chorizo", "cookies.db", NULL);
+               mkdirp(dirname(fname), 0700);
+               WebKitCookiePersistentStorage type =
+                       WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE;
+               webkit_cookie_manager_set_persistent_storage(cm, fname, type);
+               g_free(fname);
+       }
+       webkit_web_context_set_spell_checking_enabled(wc, TRUE);
+}
+
+void
+search(gpointer data, gint direction)
+{
+       struct Client *c = (struct Client *)data;
+       WebKitWebView *web_view = WEBKIT_WEB_VIEW(c->web_view);
+       WebKitFindController *fc =
+               webkit_web_view_get_find_controller(web_view);
+       if (search_text == NULL)
+               return;
+
+       switch (direction) {
+       case 0:
+               webkit_find_controller_search(
+                       fc, search_text,
+                       WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE |
+                               WEBKIT_FIND_OPTIONS_WRAP_AROUND,
+                       G_MAXUINT);
+               break;
+       case 1:
+               webkit_find_controller_search_next(fc);
+               break;
+       case -1:
+               webkit_find_controller_search_previous(fc);
+               break;
+       case 2:
+               webkit_find_controller_search_finish(fc);
+               break;
+       }
+}
+
+void
+search_init(struct Client *c, int direction)
+{
+       gtk_widget_grab_focus(c->location);
+       const gchar *contents = gtk_entry_get_text(GTK_ENTRY(c->location));
+       if (strcspn(contents, "s/")) {
+               gtk_entry_set_text(GTK_ENTRY(c->location), "s/");
+               gtk_editable_set_position(GTK_EDITABLE(c->location), -1);
+       } else {
+               search(c, 0);
+               search(c, -1);
+               search(c, direction);
+       }
+}
+gboolean
+key_common(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       gdouble now;
+       if (event->type == GDK_KEY_PRESS) {
+               if (((GdkEventKey *)event)->state & GDK_CONTROL_MASK) {
+                       const char *uri = webkit_web_view_get_uri(
+                               WEBKIT_WEB_VIEW(c->web_view));
+                       int key = ((GdkEventKey *)event)->keyval;
+                       if (GDK_KEY_y == key) {
+                               downloadmanager_show();
+                               return TRUE;
+                       } else if (GDK_KEY_h == key) {
+                               webkit_web_view_go_back(
+                                       WEBKIT_WEB_VIEW(c->web_view));
+                               return TRUE;
+                       } else if (GDK_KEY_l == key) {
+                               webkit_web_view_go_forward(
+                                       WEBKIT_WEB_VIEW(c->web_view));
+                               return TRUE;
+                       } else if (GDK_KEY_o == key) {
+                               gtk_widget_grab_focus(c->location);
+                               return TRUE;
+                       } else if (GDK_KEY_Print == key) {
+                               WebKitPrintOperation *operation =
+                                       webkit_print_operation_new(
+                                               WEBKIT_WEB_VIEW(c->web_view));
+                               GtkWidget *toplevel =
+                                       gtk_widget_get_toplevel(mw.win);
+                               webkit_print_operation_run_dialog(
+                                       operation, GTK_WINDOW(toplevel));
+                               return TRUE;
+                       } else if (GDK_KEY_g == key) {
+                               search(c, 2);
+                               gtk_widget_grab_focus(c->web_view);
+                               gtk_editable_set_position(
+                                       GTK_EDITABLE(c->location), -1);
+                               if (uri)
+                                       gtk_entry_set_text(
+                                               GTK_ENTRY(c->location), uri);
+                               webkit_web_view_run_javascript(
+                                       WEBKIT_WEB_VIEW(c->web_view),
+                                       "window.getSelection().removeAllRanges();"
+                                       "document.activeElement.blur();",
+                                       NULL, NULL, c);
+                               return TRUE;
+                       } else if (GDK_KEY_r == key) {
+                               webkit_web_view_reload_bypass_cache(
+                                       WEBKIT_WEB_VIEW(c->web_view));
+                               return TRUE;
+                       } else if (GDK_KEY_j == key) {
+                               for (int i = 0; i <= cfg_scroll_lines - 1;
+                                    i++) {
+                                       event->key.keyval = GDK_KEY_Down;
+                                       gdk_event_put(event);
+                               }
+                               return TRUE;
+                       } else if (GDK_KEY_k == key) {
+                               for (int i = 0; i <= cfg_scroll_lines - 1;
+                                    i++) {
+                                       event->key.keyval = GDK_KEY_Up;
+                                       gdk_event_put(event);
+                               }
+                               return TRUE;
+                       } else if (GDK_KEY_f == key) {
+                               event->key.keyval = GDK_KEY_Page_Down;
+                               gdk_event_put(event);
+                               return TRUE;
+                       } else if (GDK_KEY_b == key) {
+                               event->key.keyval = GDK_KEY_Page_Up;
+                               gdk_event_put(event);
+                               return TRUE;
+                       } else if (GDK_KEY_s == key) {
+                               search_init(c, 1);
+                               return TRUE;
+                       } else if (GDK_KEY_r == key) {
+                               search_init(c, -1);
+                               return TRUE;
+                       } else if (GDK_KEY_q == key) {
+                               client_destroy(NULL, c);
+                               return TRUE;
+                       } else if (GDK_KEY_1 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 0);
+                               return TRUE;
+                       } else if (GDK_KEY_2 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 1);
+                               return TRUE;
+                       } else if (GDK_KEY_3 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 2);
+                               return TRUE;
+                       } else if (GDK_KEY_4 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 3);
+                               return TRUE;
+                       } else if (GDK_KEY_5 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 4);
+                               return TRUE;
+                       } else if (GDK_KEY_6 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 5);
+                               return TRUE;
+                       } else if (GDK_KEY_7 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 6);
+                               return TRUE;
+                       } else if (GDK_KEY_8 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 7);
+                               return TRUE;
+                       } else if (GDK_KEY_9 == key) {
+                               gtk_notebook_set_current_page(
+                                       GTK_NOTEBOOK(mw.notebook), 8);
+                               return TRUE;
+                       } else if (GDK_KEY_u == key) {
+                               gtk_notebook_prev_page(
+                                       GTK_NOTEBOOK(mw.notebook));
+                               return TRUE;
+                       } else if (GDK_KEY_m == key) {
+                               gboolean muted = webkit_web_view_get_is_muted(
+                                       WEBKIT_WEB_VIEW(c->web_view));
+                               webkit_web_view_set_is_muted(
+                                       WEBKIT_WEB_VIEW(c->web_view), !muted);
+                               changed_title(G_OBJECT(c->web_view), NULL, c);
+                               return TRUE;
+                       } else if (GDK_KEY_t == key) {
+                               client_new(cfg_home_uri, NULL, TRUE, TRUE);
+                               return TRUE;
+                       } else if (GDK_KEY_bracketleft == key) {
+                               if (!closed_tabs)
+                                       return TRUE;
+                               int len = sizeof(closed_tabs) / sizeof(char *);
+                               if (len < 1)
+                                       return TRUE;
+                               client_new(closed_tabs[len], NULL, TRUE, TRUE);
+                               free(closed_tabs[len]);
+                               closed_tabs = (char **)realloc(
+                                       closed_tabs,
+                                       (len - 1) * sizeof(closed_tabs[0]));
+                               return TRUE;
+                       } else if (GDK_KEY_i == key) {
+                               gtk_notebook_next_page(
+                                       GTK_NOTEBOOK(mw.notebook));
+                               return TRUE;
+                       } else if (GDK_KEY_p == key) {
+                               gboolean on =
+                                       webkit_settings_get_enable_javascript(
+                                               c->settings);
+                               webkit_settings_set_enable_javascript(
+                                       c->settings, !on);
+                               webkit_web_view_set_settings(
+                                       WEBKIT_WEB_VIEW(c->web_view),
+                                       c->settings);
+                               gtk_toggle_button_set_active(
+                                       GTK_TOGGLE_BUTTON(c->jsbutton), !on);
+                       } else if (GDK_KEY_d == key) {
+                               gtk_widget_grab_focus(c->location);
+                               gtk_entry_set_text(GTK_ENTRY(c->location),
+                                                  "w/");
+                               gtk_editable_set_position(
+                                       GTK_EDITABLE(c->location), -1);
+                               return TRUE;
+                       } else if (GDK_KEY_equal == key) {
+                               now = webkit_web_view_get_zoom_level(
+                                       WEBKIT_WEB_VIEW(c->web_view));
+                               webkit_web_view_set_zoom_level(
+                                       WEBKIT_WEB_VIEW(c->web_view),
+                                       now + 0.1);
+                               return TRUE;
+                       } else if (GDK_KEY_minus == key) {
+                               now = webkit_web_view_get_zoom_level(
+                                       WEBKIT_WEB_VIEW(c->web_view));
+                               webkit_web_view_set_zoom_level(
+                                       WEBKIT_WEB_VIEW(c->web_view),
+                                       now - 0.1);
+                               return TRUE;
+                       } else if (GDK_KEY_0 == key) {
+                               webkit_web_view_set_zoom_level(
+                                       WEBKIT_WEB_VIEW(c->web_view), 1);
+                               return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+gboolean
+key_location(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       const gchar *t;
+       if (key_common(widget, event, data))
+               return TRUE;
+
+       if (event->type == GDK_KEY_PRESS) {
+               int key = ((GdkEventKey *)event)->keyval;
+               if ((GDK_KEY_KP_Enter == key) || (GDK_KEY_Return == key)) {
+                       gtk_widget_grab_focus(c->web_view);
+                       t = gtk_entry_get_text(GTK_ENTRY(c->location));
+                       if (t != NULL && t[0] == 's' && t[1] == '/') {
+                               if (search_text != NULL)
+                                       g_free(search_text);
+                               search_text = g_strdup(t + 2);
+                               search(c, 0);
+                       } else if (t != NULL && t[0] == 'w' && t[1] == '/') {
+                               int len = strlen(cfg_search_engine) +
+                                         strlen(t) - 2;
+                               gchar *f = malloc(len + 1);
+                               snprintf(f, len + 1, "%s%s", cfg_search_engine,
+                                        t + 2);
+                               webkit_web_view_load_uri(
+                                       WEBKIT_WEB_VIEW(c->web_view), f);
+                               g_free(f);
+                       } else {
+                               webkit_web_view_load_uri(
+                                       WEBKIT_WEB_VIEW(c->web_view),
+                                       ensure_uri_scheme(t));
+                       }
+                       return TRUE;
+               } else if (GDK_KEY_Escape == key) {
+                       t = webkit_web_view_get_uri(
+                               WEBKIT_WEB_VIEW(c->web_view));
+                       gtk_entry_set_text(GTK_ENTRY(c->location),
+                                          (t == NULL) ? "" : t);
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+gboolean
+key_tablabel(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       GdkScrollDirection direction;
+       if (event->type == GDK_BUTTON_RELEASE) {
+               switch (((GdkEventButton *)event)->button) {
+               case 2:
+                       client_destroy(NULL, data);
+                       return TRUE;
+               }
+       } else if (event->type == GDK_SCROLL) {
+               gdk_event_get_scroll_direction(event, &direction);
+               switch (direction) {
+               case GDK_SCROLL_UP:
+                       gtk_notebook_prev_page(GTK_NOTEBOOK(mw.notebook));
+                       break;
+               case GDK_SCROLL_DOWN:
+                       gtk_notebook_next_page(GTK_NOTEBOOK(mw.notebook));
+                       break;
+               default:
+                       break;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+gboolean
+key_web_view(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       gdouble dx, dy;
+       gfloat z;
+       if (key_common(widget, event, data))
+               return TRUE;
+
+       if (event->type == GDK_KEY_PRESS) {
+               if (((GdkEventKey *)event)->keyval == GDK_KEY_Escape) {
+                       webkit_web_view_stop_loading(
+                               WEBKIT_WEB_VIEW(c->web_view));
+                       gtk_entry_set_progress_fraction(GTK_ENTRY(c->location),
+                                                       0);
+               }
+       } else if (event->type == GDK_BUTTON_RELEASE) {
+               GdkModifierType modifiers =
+                       gtk_accelerator_get_default_mod_mask();
+               switch (((GdkEventButton *)event)->button) {
+               case 1:
+                       if ((((GdkEventButton *)event)->state & modifiers) ==
+                                   GDK_CONTROL_MASK &&
+                           c->hover_uri != NULL) {
+                               client_new(c->hover_uri, NULL, TRUE, FALSE);
+                               return TRUE;
+                       }
+                       break;
+               case 8:
+                       webkit_web_view_go_back(WEBKIT_WEB_VIEW(c->web_view));
+                       return TRUE;
+               case 9:
+                       webkit_web_view_go_forward(
+                               WEBKIT_WEB_VIEW(c->web_view));
+                       return TRUE;
+               }
+       } else if (event->type == GDK_SCROLL) {
+               event->scroll.delta_y *= cfg_scroll_lines;
+               if (((GdkEventScroll *)event)->state & GDK_CONTROL_MASK) {
+                       gdk_event_get_scroll_deltas(event, &dx, &dy);
+                       z = webkit_web_view_get_zoom_level(
+                               WEBKIT_WEB_VIEW(c->web_view));
+                       z += -dy * 0.1;
+                       z = dx != 0 ? 1 : z;
+                       webkit_web_view_set_zoom_level(
+                               WEBKIT_WEB_VIEW(c->web_view), z);
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+void
+mainwindow_setup(void)
+{
+       mw.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       gtk_window_set_default_size(GTK_WINDOW(mw.win), 800, 600);
+       g_signal_connect(G_OBJECT(mw.win), "destroy", gtk_main_quit, NULL);
+
+       gchar *priv = (cfg.private) ? "-private" : "";
+       gchar *title = malloc(strlen(priv) + 7);
+       sprintf(title, "%s%s", "chorizo", priv);
+       gtk_window_set_title(GTK_WINDOW(mw.win), title);
+       g_free(title);
+
+       mw.notebook = gtk_notebook_new();
+       gtk_notebook_set_scrollable(GTK_NOTEBOOK(mw.notebook), TRUE);
+       gtk_container_add(GTK_CONTAINER(mw.win), mw.notebook);
+       g_signal_connect(G_OBJECT(mw.notebook), "switch-page",
+                        G_CALLBACK(notebook_switch_page), NULL);
+}
+
+void
+mainwindow_title(gint idx)
+{
+       GtkWidget *child, *widg, *tablabel;
+       const gchar *text;
+       child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(mw.notebook), idx);
+       if (child == NULL)
+               return;
+
+       widg = gtk_notebook_get_tab_label(GTK_NOTEBOOK(mw.notebook), child);
+       tablabel = (GtkWidget *)g_object_get_data(G_OBJECT(widg),
+                                                 "chorizo-tab-label");
+       text = gtk_label_get_text(GTK_LABEL(tablabel));
+       gtk_window_set_title(GTK_WINDOW(mw.win), text);
+}
+
+void
+notebook_switch_page(GtkNotebook *nb, GtkWidget *p, guint idx, gpointer data)
+{
+       mainwindow_title(idx);
+}
+gboolean
+quit_if_nothing_active(void)
+{
+       if (clients == 0) {
+               if (downloads == 0) {
+                       gtk_main_quit();
+                       return TRUE;
+               } else {
+                       downloadmanager_show();
+               }
+       }
+       return FALSE;
+}
+gboolean
+remote_msg(GIOChannel *channel, GIOCondition condition, gpointer data)
+{
+       gchar *uri = NULL;
+       g_io_channel_read_line(channel, &uri, NULL, NULL, NULL);
+       if (uri) {
+               g_strstrip(uri);
+               client_new(uri, NULL, TRUE, TRUE);
+               g_free(uri);
+       }
+       return TRUE;
+}
+
+void
+show_web_view(WebKitWebView *web_view, gpointer data)
+{
+       struct Client *c = (struct Client *)data;
+       gint idx;
+       (void)web_view;
+
+       gtk_widget_show_all(mw.win);
+
+       if (c->focus_new_tab) {
+               idx = gtk_notebook_page_num(GTK_NOTEBOOK(mw.notebook), c->vbox);
+               if (idx != -1)
+                       gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook),
+                                                     idx);
+
+               gtk_widget_grab_focus(c->web_view);
+       }
+}
+
+void
+trust_user_certs(WebKitWebContext *wc)
+{
+       GTlsCertificate *cert;
+       gchar *basedir, *absfile;
+       const gchar *file;
+       GDir *dir = NULL;
+       basedir = g_build_filename(g_get_user_data_dir(), "chorizo", "certs",
+                                  NULL);
+       dir = g_dir_open(basedir, 0, NULL);
+       g_free(basedir);
+       if (dir != NULL) {
+               file = g_dir_read_name(dir);
+               while (file != NULL) {
+                       absfile = g_build_filename(g_get_user_data_dir(),
+                                                  "chorizo", "certs", file,
+                                                  NULL);
+                       cert = g_tls_certificate_new_from_file(absfile, NULL);
+                       g_free(absfile);
+                       if (cert == NULL)
+                               fprintf(stderr,
+                                       "chorizo: Could not load trusted cert '%s'\n",
+                                       file);
+                       else
+                               webkit_web_context_allow_tls_certificate_for_host(
+                                       wc, cert, file);
+                       file = g_dir_read_name(dir);
+               }
+               g_dir_close(dir);
+       }
+}
+
+int
+main(int argc, char **argv)
+{
+       int opt, i;
+
+       //TODO:pretty this
+       cfg.noncooperative_instances = FALSE;
+       cfg.cooperative_alone = TRUE;
+
+       while ((opt = getopt(argc, argv, "cpvV")) != -1) {
+               switch (opt) {
+               case 'c':
+                       cfg.noncooperative_instances = TRUE;
+                       break;
+               case 'p':
+                       cfg.private = TRUE;
+                       break;
+               case 'v':
+                       cfg.verbose = TRUE;
+                       break;
+               case 'V':
+                       printf("%s %s\n", "chorizo", VERSION);
+                       exit(0);
+               default:
+                       fprintf(stderr,
+                               "Usage: chorizo [OPTION]... [URI]...\n");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       gtk_init(&argc, &argv);
+
+       //Keep clipboard contents after program closes
+       gtk_clipboard_store(gtk_clipboard_get_for_display(
+               gdk_display_get_default(), GDK_SELECTION_CLIPBOARD));
+
+       if (!cfg.noncooperative_instances)
+               cooperation_setup();
+
+       if (cfg.noncooperative_instances || cfg.cooperative_alone)
+               init_default_web_context();
+
+       downloadmanager_setup();
+       mainwindow_setup();
+
+       client_arr = malloc(sizeof(struct Client *));
+       if (optind >= argc) {
+               client_new(cfg_home_uri, NULL, TRUE, TRUE);
+       } else {
+               for (i = optind; i < argc; i++)
+                       client_new(argv[i], NULL, TRUE, TRUE);
+       }
+
+       if (cfg.noncooperative_instances || cfg.cooperative_alone) {
+               gtk_main();
+               remove(fifopath);
+       }
+       for (int i = 0; i < clients; i++) {
+               free(&(client_arr[i]));
+       }
+
+       exit(EXIT_SUCCESS);
+}
diff --git a/chorizo-usage.7 b/chorizo-usage.7
new file mode 100644 (file)
index 0000000..5857863
--- /dev/null
@@ -0,0 +1,93 @@
+.TH "chorizo-usage" "7" "2021-10-11"
+.P
+.SH NAME
+chorizo-usage - extended usage hints
+.P
+.SH DESCRIPTION
+\fBchorizo\fR is a simple web browser using GTK+ 3, GLib and WebKit2GTK+.\& This
+manpage contains additional hints and pointers regarding its usage.\&
+.P
+.SH DOWNLOAD MANAGER
+Open the download manager using the appropriate hotkey.\& A new window listing
+your downloads will appear.\& Clicking on an item will remove it from the list and
+\fB\fRif needed\fB\fR cancel the download.\&
+.P
+There's no file manager integration, nor does \fBchorizo\fR delete, overwrite or
+resume downloads.\& If a file already exists, it won't be touched.\& Instead, the
+new file name will have a suffix such as \fB.\&1\fR, \fB.\&2\fR, \fB.\&3\fR, and so on.\&
+.P
+.SH USER-SUPPLIED JAVASCRIPT FILES
+When a page is being loaded, the directory \fI~/.\&local/share/chorizo/user-scripts\fR
+will be scanned and each file in it ending with \fB.\&js\fR will be run as a
+JavaScript file in the context of said page.\&
+.P
+\fBchorizo\fR comes with the following scripts:
+.P
+\fBhints.\&js\fR
+.RS 4
+Press \fBf\fR (open link in current window) or \fBF\fR (open in new window) to
+activate link hints.\& After typing the characters for one of them, press
+\fBEnter\fR to confirm.\& Press \fBEscape\fR to abort.\&
+.P
+.RE
+\fBprivacy-redirect.\&js\fR
+.RS 4
+Redirects YouTube, Reddit, etc to privacy respecting alternatives.\&
+.P
+.RE
+\fBdarkreader.\&js\fR
+.RS 4
+See https://darkreader.\&org.\&
+.P
+.RE
+Those bundled scripts are automatically installed on \fBmake install\fR.\& To use
+them, though, make sure to link them to the directory mentioned above.\&
+.P
+.SH USER-SUPPLIED CSS FILES
+User supplied CSS files will be scanned for from
+\fI~/.\&local/share/chorizo/user-styles\fR, and be applied every time a page
+loads.\& The rules in these files override any rules provided by the website.\&
+.P
+.SH WEB EXTENSIONS
+On startup, WebKit checks \fI~/.\&local/share/chorizo/web-extensions\fR for any \fB.\&so\fR
+files.\& See
+<http://blogs.\&igalia.\&com/carlosgc/2013/09/10/webkit2gtk-web-process-extensions/>
+this blog post for further information on these extensions.\&
+.P
+\fBchorizo\fR comes with the following extensions:
+.P
+\fBwe_adblock.\&so\fR
+.RS 4
+Generic adblock.\& Reads patterns from the file \fI~/.\&config/chorizo/adblock\fR.\& Each
+line can contain a regular expression.\& These expressions match
+case-insensitive and partially, i.\&e.\&\fB*foo.\&*\fR is the same as \fB.\&*FOO.\&*\fR and
+you can use anchors like \fB^https?\&://.\&.\&.\&\fR.\& Please refer to
+https://developer.\&gnome.\&org/glib/stable/glib-regex-syntax.\&html the GLib
+reference for more details.\& Lines starting with "#" are ignored.\&
+.P
+Those bundled web extensions are automatically compiled when you run \fBmake\fR
+and installed on \fBmake install\fR.\& To use them, though, make sure to link them
+to the directory mentioned above.\&
+.P
+.RE
+.SH TRUSTED CERTIFICATES
+By default, \fBchorizo\fR trusts whatever CAs are trusted by WebKit.\& If you wish to
+trust additional certificates, such as self-signed certificates, the first thing
+you should do is try to add the appropriate CAs to your system-wide store.\&
+.P
+If you wish to add simple exceptions, you can grab the certificate and store it
+in the directory \fI~/.\&local/share/chorizo/certs\fR.\& The filename must be equal to
+the hostname:
+.P
+.RS 4
+$ echo | openssl s_client -connect foo.\&de:443 | openssl x509 >foo.\&de
+.P
+.RE
+This tells \fBchorizo\fR to trust the given certificate when connecting to host
+\fBfoo.\&de\fR.\&
+.P
+Note: This is NOT equal to certificate pinning.\& WebKit ignores user-specified
+certificates if the server's certificate can be validated by any system-wide CA.\&
+.P
+.SH SEE ALSO
+\fBchorizo\fR(1), \fBchorizo-config\fR(5)
diff --git a/chorizo.1 b/chorizo.1
new file mode 100644 (file)
index 0000000..e7ecd4c
--- /dev/null
+++ b/chorizo.1
@@ -0,0 +1,107 @@
+.TH "chorizo" "1" "2021-10-11"
+.P
+.SH NAME
+chorizo - simple web browser
+.P
+.SH SYNOPSIS
+\fBchorizo\fR - [-C] [\fIURI .\&.\&.\&\fR]
+.P
+.SH DESCRIPTION
+\fBchorizo\fR is a simple web browser using GTK+ 3, GLib and WebKit2GTK+.\&
+.P
+.SH OPTIONS
+In addition to the standard arguments of GTK+ 3, \fBchorizo\fR knows about the
+following options:
+.P
+\fB-C\fR
+.RS 4
+Disables cooperative instances.\&
+.P
+.RE
+\fB-p\fR
+.RS 4
+Launch a private window.\&
+.P
+.RE
+\fB-v\fR
+.RS 4
+Print version and exit.\&
+.P
+.RE
+After these options there can be any number of URIs specified to open.\&
+.P
+.SH ENVIRONMENT
+In addition to the standard variables of GTK+ 3, \fBchorizo\fR knows about the
+following environment variable:
+.P
+\fBCHORIZO_FIFO_SUFFIX\fR
+.RS 4
+Cooperative instances are implemented using a named pipe in the file
+system.\& The name of this pipe usually is (at least on modern systems following
+XDG standards: /var/run/user/$UID/chorizo.\&fifo-$CHORIZO_FIFO_SUFFIX
+.P
+\fB$UID\fR is the id of your user.\& \fB$CHORIZO_FIFO_SUFFIX\fR defaults to \fBmain\fR.\& If you
+change this variable, you can launch several independent cooperative instances
+of \fBchorizo\fR.\&
+.P
+.RE
+.SH FILES
+XDG variables will be used to construct these paths.\&
+\fB~/.\&config/chorizo/chorizo.\&ini\fR
+.RS 4
+Configuration file.\& See \fBchorizo-config\fR(5).\&
+.P
+.RE
+\fB~/.\&config/chorizo/adblock\fR
+.RS 4
+Adblock patterns.\& See \fBchorizo-usage\fR(1).\&
+.P
+.RE
+\fB~/.\&local/share/chorizo/certs\fR
+.RS 4
+Directory where trusted certificates are stored.\& See \fBchorizo-usage\fR(1).\&
+.P
+.RE
+\fB~/.\&local/share/chorizo/cookies.\&db\fR
+.RS 4
+Database where cookies are stored.\& It is kept in the same format as Firefox,
+so the file can easily be copied over.\&
+.P
+.RE
+\fB~/.\&local/share/chorizo/user-scripts\fR
+.RS 4
+Directory to store user-supplied JavaScript snippets.\& See \fBchorizo-usage\fR(1).\&
+.P
+.RE
+\fB~/.\&local/share/chorizo/user-styles\fR
+.RS 4
+Directory to store user-supplied CSS snippets.\& See \fBchorizo-usage\fR(1).\&
+.P
+.RE
+\fB~/.\&local/share/chorizo/web-extensions\fR
+.RS 4
+Sets the directory where WebKit will look for web extensions.\& See
+\fBchorizo-usage\fR(1).\&
+.P
+.RE
+\fB~/.\&cache/chorizo\fR
+\fB~/.\&cache/webkitgtk\fR
+.RS 4
+General caches.\&
+.P
+.RE
+\fB~/.\&local/share/webkitgtk\fR
+.RS 4
+WebKitGTK will dump its caches and local storage here.\& It is probably wise to
+clean those directories regularly or to mount them as \fBtmpfs\fR(5).\&
+.P
+.RE
+.SH LICENSE
+\fBchorizo\fR is released under the MIT license.\& See the accompanying LICENSE file.\&
+.P
+.SH HISTORY
+chorizo is a fork of the lariza browser by Peter Hofmann.\& The project was
+started in June 2014.\& This fork is maintained by Armaan Bhojwani.\&
+.P
+.SH SEE ALSO
+\fBchorizo-usage\fR(1), \fBchorizo-config\fR(5)
diff --git a/chorizo.desktop b/chorizo.desktop
deleted file mode 100644 (file)
index 1b35ac9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Based on vimb / chromium's desktop entry
-[Desktop Entry]
-Name=chorizo
-GenericName=Web Browser
-Comment=Access the Internet
-Exec=chorizo %U
-Terminal=false
-Icon=
-Type=Application
-Categories=GTK;Network;WebBrowser;
-MimeType=text/html;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;
\ No newline at end of file
diff --git a/chorizo.ini b/chorizo.ini
deleted file mode 100644 (file)
index 5f56a50..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# chorizo browser example configuration file. A full list of options
-# can be found in chorizo-config(5).
-
-# [browser]
-# homepage=https://duckduckgo.com
-# console_to_stdout=true
-
-# [ui]
-# tab_width=25
-# zoom_level=1.25
-
-# [keybindings]
-# download_manager=m
\ No newline at end of file
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..af1da40
--- /dev/null
+++ b/config.h
@@ -0,0 +1,16 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define VERSION "1.1.0"
+gboolean cfg_js_default = TRUE;
+//Should JavaScript be enabled by default
+WebKitCookieAcceptPolicy cfg_cookie_policy = WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS;
+//Cookie policy
+gchar *cfg_home_uri = NULL;
+//Default URI
+int cfg_scroll_lines = 3;
+//Number of lines to scroll at a time
+gchar *cfg_search_engine = "https://searx.be/search?q=";
+//Search engine
+
+#endif
diff --git a/downloads.c b/downloads.c
new file mode 100644 (file)
index 0000000..c738863
--- /dev/null
@@ -0,0 +1,271 @@
+#include <webkit2/webkit2.h>
+
+#include "downloads.h"
+
+gboolean download_handle(WebKitDownload *, gchar *, gpointer);
+void download_click(GtkToolButton *, gpointer);
+void download_cancel(GtkMenuItem *, gpointer);
+gboolean downloadmanager_delete(GtkWidget *, gpointer);
+
+struct DownloadManager {
+       GtkWidget *scroll;
+       GtkWidget *toolbar;
+       GtkWidget *win;
+} dm;
+
+gint downloads = 0;
+
+struct DownloadItem {
+       GtkToolButton *tb;
+       WebKitDownload *download;
+};
+gboolean
+key_downloadmanager(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       if (event->type == GDK_KEY_PRESS) {
+               if (((GdkEventKey *)event)->state & GDK_CONTROL_MASK) {
+                       int key = ((GdkEventKey *)event)->keyval;
+                       if ((GDK_KEY_q == key) || (GDK_KEY_y == key)) {
+                               downloadmanager_delete(dm.win, NULL);
+                               return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
+void
+changed_download_progress(GObject *obj, GParamSpec *pspec, gpointer data)
+{
+       WebKitDownload *download = WEBKIT_DOWNLOAD(obj);
+       WebKitURIResponse *resp;
+       GtkToolItem *tb = GTK_TOOL_ITEM(data);
+       gdouble p, size_mb;
+       const gchar *uri;
+       gchar *t, *filename, *base;
+       p = webkit_download_get_estimated_progress(download);
+       p = p > 1 ? 1 : p;
+       p = p < 0 ? 0 : p;
+       p *= 100;
+       resp = webkit_download_get_response(download);
+       size_mb = webkit_uri_response_get_content_length(resp) / 1e6;
+
+       uri = webkit_download_get_destination(download);
+       filename = g_filename_from_uri(uri, NULL, NULL);
+       base = g_path_get_basename(filename);
+       t = g_strdup_printf("%s (%.0f%% of %.1f MB)", base, p, size_mb);
+       g_free(filename);
+       g_free(base);
+       gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), t);
+       g_free(t);
+}
+
+void
+download_finished(WebKitDownload *download, gpointer data)
+{
+       if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(data)),
+                  "dialog-error") != 0)
+               gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(data),
+                                             "emblem-downloads");
+       downloads--;
+}
+
+void
+download_start(WebKitWebView *web_view, WebKitDownload *download, gpointer data)
+{
+       g_signal_connect(G_OBJECT(download), "decide-destination",
+                        G_CALLBACK(download_handle), data);
+}
+gboolean
+download_handle(WebKitDownload *download, gchar *suggested_filename,
+               gpointer data)
+{
+       gchar *uri;
+       GtkToolItem *tb;
+
+       GtkWidget *chooser = gtk_file_chooser_dialog_new(
+               "Choose download location", GTK_WINDOW(dm.win),
+               GTK_FILE_CHOOSER_ACTION_SAVE, "Save file", GTK_RESPONSE_ACCEPT,
+               "Cancel", GTK_RESPONSE_CANCEL, NULL);
+       gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser),
+                                           (char *)data);
+       gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser),
+                                         suggested_filename);
+       gtk_file_chooser_set_do_overwrite_confirmation(
+               GTK_FILE_CHOOSER(chooser), TRUE);
+       gint res = gtk_dialog_run(GTK_DIALOG(chooser));
+       switch (res) {
+       case GTK_RESPONSE_ACCEPT:
+               uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(chooser));
+               webkit_download_set_destination(
+                       download,
+                       gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(chooser)));
+               break;
+       case GTK_RESPONSE_CANCEL:
+               return FALSE;
+       default:
+               return FALSE;
+       }
+
+       gtk_widget_destroy(chooser);
+
+       remove(uri + 7);
+       tb = gtk_tool_button_new(NULL, NULL);
+       gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(tb), "network-receive");
+       gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), uri);
+       gtk_toolbar_insert(GTK_TOOLBAR(dm.toolbar), tb, 0);
+       gtk_widget_show_all(dm.win);
+
+       g_signal_connect(G_OBJECT(download), "notify::estimated-progress",
+                        G_CALLBACK(changed_download_progress), tb);
+
+       downloads++;
+       g_signal_connect(G_OBJECT(download), "finished",
+                        G_CALLBACK(download_finished), tb);
+
+       g_object_ref(download);
+
+       struct DownloadItem *payload = malloc(sizeof(*payload));
+       payload->tb = (GtkToolButton *)tb;
+       payload->download = download;
+       g_signal_connect(G_OBJECT(tb), "clicked", G_CALLBACK(download_click),
+                        payload);
+       g_signal_connect(G_OBJECT(tb), "failed", G_CALLBACK(download_cancel),
+                        payload);
+       g_signal_connect(G_OBJECT(tb), "destroy_event", G_CALLBACK(g_free),
+                        payload);
+
+       //Propagate-- to whom it may concern.
+       return FALSE;
+}
+
+void
+download_cancel(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(payload->tb),
+                                     "dialog-error");
+       webkit_download_cancel(payload->download);
+}
+
+void
+download_remove(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       g_object_unref(payload->download);
+       gtk_widget_destroy(GTK_WIDGET(payload->tb));
+}
+
+void
+download_copy_url(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       WebKitURIRequest *req = webkit_download_get_request(payload->download);
+       const gchar *uri = webkit_uri_request_get_uri(req);
+       gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), uri,
+                              strlen(uri));
+}
+
+void
+download_copy_path(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       const gchar *path = webkit_download_get_destination(payload->download);
+       gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+                              path + 7, strlen(path) - 7);
+       //Offset by 7 to remove "file://"
+}
+
+void
+download_xdg_open(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       const gchar *path = webkit_download_get_destination(payload->download);
+       char *cmd = malloc(strlen(path) + 9);
+       sprintf(cmd, "xdg-open %s", path);
+       system(cmd);
+}
+
+void
+download_click(GtkToolButton *tb, gpointer data)
+{
+       GtkWidget *pmenu = gtk_menu_new();
+       GtkWidget *option;
+       if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(tb)),
+                  "network-receive") == 0) {
+               option = gtk_menu_item_new_with_label("Cancel download");
+               g_signal_connect(G_OBJECT(option), "activate",
+                                G_CALLBACK(download_cancel), data);
+               gtk_widget_show(option);
+               gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+       } else {
+               option = gtk_menu_item_new_with_label("Remove download");
+               g_signal_connect(G_OBJECT(option), "activate",
+                                G_CALLBACK(download_remove), data);
+               gtk_widget_show(option);
+               gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+
+               option =
+                       gtk_menu_item_new_with_label("Open file with xdg-open");
+               gtk_widget_show(option);
+               gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+               g_signal_connect(G_OBJECT(option), "activate",
+                                G_CALLBACK(download_xdg_open), data);
+       }
+
+       option = gtk_menu_item_new_with_label("Copy download URL");
+       gtk_widget_show(option);
+       gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+       g_signal_connect(G_OBJECT(option), "activate",
+                        G_CALLBACK(download_copy_url), data);
+
+       option = gtk_menu_item_new_with_label("Copy local path");
+       gtk_widget_show(option);
+       gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+       g_signal_connect(G_OBJECT(option), "activate",
+                        G_CALLBACK(download_copy_path), data);
+
+       gtk_menu_popup_at_pointer(GTK_MENU(pmenu), NULL);
+}
+gboolean
+downloadmanager_delete(GtkWidget *obj, gpointer data)
+{
+       if (!quit_if_nothing_active())
+               gtk_widget_hide(dm.win);
+
+       return TRUE;
+}
+
+void
+downloadmanager_setup(void)
+{
+       dm.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       gtk_window_set_type_hint(GTK_WINDOW(dm.win),
+                                GDK_WINDOW_TYPE_HINT_DIALOG);
+       gtk_window_set_default_size(GTK_WINDOW(dm.win), 500, 250);
+       gtk_window_set_title(GTK_WINDOW(dm.win), "chorizo - Download Manager");
+       g_signal_connect(G_OBJECT(dm.win), "delete-event",
+                        G_CALLBACK(downloadmanager_delete), NULL);
+       g_signal_connect(G_OBJECT(dm.win), "key-press-event",
+                        G_CALLBACK(key_downloadmanager), NULL);
+
+       dm.toolbar = gtk_toolbar_new();
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(dm.toolbar),
+                                      GTK_ORIENTATION_VERTICAL);
+       gtk_toolbar_set_style(GTK_TOOLBAR(dm.toolbar), GTK_TOOLBAR_BOTH_HORIZ);
+       gtk_toolbar_set_show_arrow(GTK_TOOLBAR(dm.toolbar), FALSE);
+
+       dm.scroll = gtk_scrolled_window_new(NULL, NULL);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dm.scroll),
+                                      GTK_POLICY_AUTOMATIC,
+                                      GTK_POLICY_AUTOMATIC);
+       gtk_container_add(GTK_CONTAINER(dm.scroll), dm.toolbar);
+
+       gtk_container_add(GTK_CONTAINER(dm.win), dm.scroll);
+}
+
+void
+downloadmanager_show(void)
+{
+       gtk_widget_show_all(dm.win);
+}
diff --git a/downloads.h b/downloads.h
new file mode 100644 (file)
index 0000000..a12afd5
--- /dev/null
@@ -0,0 +1,5 @@
+extern int downloads;
+gboolean quit_if_nothing_active(void);
+void download_start(WebKitWebView *, WebKitDownload *, gpointer);
+void downloadmanager_setup(void);
+void downloadmanager_show(void);
index 50a756040fafc36ccfc80b800ad2be568bada4a6..37fa3b732f38f7cb0541b9bde09612ab983c839c 100644 (file)
@@ -12,7 +12,7 @@ adblock_load(void) {
     GIOChannel *channel = NULL;
     gchar *path = NULL, *buf = NULL;
 
-    path = g_build_filename(g_get_user_config_dir(), __NAME__, "adblock", NULL);
+    path = g_build_filename(g_get_user_config_dir(), "chorizo", "adblock", NULL);
     channel = g_io_channel_new_file(path, "r", &err);
     if (channel != NULL) {
         while (g_io_channel_read_line(channel, &buf, NULL, NULL, NULL) ==
@@ -22,7 +22,7 @@ adblock_load(void) {
                 re = g_regex_new(buf, G_REGEX_CASELESS | G_REGEX_OPTIMIZE,
                                  G_REGEX_MATCH_PARTIAL, &err);
                 if (err != NULL) {
-                    fprintf(stderr, __NAME__ ": Could not compile regex: %s\n",
+                    fprintf(stderr, "chorizo: Could not compile regex: %s\n",
                             buf);
                     g_error_free(err);
                     err = NULL;
diff --git a/man/chorizo-config.5.scd b/man/chorizo-config.5.scd
deleted file mode 100644 (file)
index e472a78..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-chorizo-config(5)
-
-# NAME
-_chorizo.ini_ - configuration file for *chorizo*(1)
-
-# DESCRIPTION
-_chorizo.ini_ is the system configuration file for the chorizo browser. The syntax
-is the standard GTK ini format. An example is provided at
-_/usr/share/doc/chorizo/chorizo.ini_, and user configuration should go in
-_~/.config/chorizo/chorizo.ini_, or your equivalent as set by
-$XDG_CONFIG_DIR. Settings must go under the relevant subsection.
-
-# OPTIONS
-## BROWSER
-*console_to_stdout*++
-       Type: boolean++
-       Default: false++
-       Print the contents of the browser console to stdout.
-
-*cookie_policy*++
-       Type: string++
-       Default: "no_third_party"++
-       Options: "all", "none", "no_third_party"++
-       Determines what cookies are accepted.
-
-*history_file*++
-       Type: string++
-       Default: none++
-       File that chorizo should save history to.
-
-*homepage*++
-       Type: string++
-       Default: "about:blank"++
-       Set the default URI for new tabs.
-
-*images_enabled*++
-       Type: boolean++
-       Default: true++
-       Determines whether or not images are enabled by default.
-
-*javascript_can_access_clipboard*++
-       Type: boolean++
-       Default: false++
-       Determines whether or not JavaScript can access the clipboard. Necessary for
-       websites like gDrive, and "click to copy" buttons
-
-*javascript_enabled*++
-       Type: boolean++
-       Default: true++
-       Determines whether or not JavaScript is enabled by default.
-
-*search_engine*++
-       Type: string++
-       Default: "https://duckduckgo.com?q="++
-       What search engine to use when searching with "w/".
-
-*spellcheck_enabled*++
-       Type: boolean++
-       Default: true++
-       Disable spell checking.
-
-*spellcheck_language*++
-       Type: string++
-       Default: "en_US;"++
-       Language to use for spell checking.
-
-*user_agent*++
-       Type: string++
-       Default: the WebKit default++
-       Choose a custom user agent.
-
-*webgl_enabled*++
-       Type: boolean++
-       Default: true++
-       Determines whether or not WebGL is enabled.
-
-## UI
-*default_uri*++
-       Type: string++
-       Default: "https://"++
-       The URI to fill the location bar with when entering the it from the homepage.
-
-*font_family_default*++
-       Type: string++
-       Default: "sans-serif"++
-       Default font family.
-
-*font_family_default_monospace*++
-       Type: string++
-       Default: "monospace"++
-       Default monospace font family
-
-*font_family_default_sans_serif*++
-       Type: string++
-       Default: "sans-serif"++
-       Default sans-serif font family
-
-*font_family_default_serif*++
-       Type: string++
-       Default: "serif"++
-       Default serif font family
-
-*font_size_default*++
-       Type: integer++
-       Default: 16++
-       Default font size.
-
-*font_size_default_monospace*++
-       Type: integer++
-       Default: 13++
-       Default monospace font size.
-
-*scroll_lines*++
-       Type: integer++
-       Default: 3++
-       Number of lines to scroll in the "scroll_lines_\*" keybindings.
-
-*tab_width*++
-       Type: integer++
-       Default: 20++
-       Width of each tab in characters.
-
-*zoom_level*++
-       Type: double++
-       Default: 1.0++
-       Default zoom level of each page.
-
-## KEYBINDINGS
-All of these keybindings are bound to Control + key.
-
-*download_manager*++
-       Type: string++
-       Default: y++
-       Toggle the download manager.
-
-*history_back*++
-       Type: string++
-       Default: h++
-       Go back in history.
-
-*history_forwards*++
-       Type: string++
-       Default: h++
-       Go forwards in history.
-
-*location*++
-       Type: string++
-       Default: t++
-       Select the URL.
-
-*print*++
-       Type: string++
-       Default: Print++
-       Print the current page
-
-*quit*++
-       Type: string++
-       Default: g++
-       Deselect everything and focus on the webpage.
-
-*reload*++
-       Type: string++
-       Default: e++
-       Reload the current tab.
-
-*scroll_line_down*++
-       Type: string++
-       Default: j++
-       Scroll down one line.
-
-*scroll_line_up*++
-       Type: string++
-       Default: k++
-       Scroll up one line.
-
-*scroll_page_down*++
-       Type: string++
-       Default: f++
-       Scroll down one page.
-
-*scroll_page_up*++
-       Type: string++
-       Default: b++
-       Scroll up one page.
-
-*search_backwards*++
-       Type: string++
-       Default: r++
-       Search in-page backwareds.
-
-*search_forwards*++
-       Type: string++
-       Default: s++
-       Search in-page forwards.
-
-*tab_close*++
-       Type: string++
-       Default: q++
-       Close the current tab.
-
-*tab_switch_[1-9]*++
-       Type: string++
-       Default: [1-9]++
-       Group of options to jump to a particular tab, numbered from the left. Set
-       these separately from each other.
-
-*tab_previous*++
-       Type: string++
-       Default: u++
-       Focus the previous tab.
-
-*tab_mute*++
-       Type: string++
-       Default: AudioMute++
-       Mute the current tab.
-
-*tab_new*++
-       Type: string++
-       Default: w++
-       Open a new tab.
-
-*tab_next*++
-       Type: string++
-       Default: i++
-       Focus the next tab.
-
-*toggle_js*++
-       Type: string++
-       Default: o++
-       Toggle JavaScript.
-
-*toggle_img*++
-       Type: string++
-       Default: NULL++
-       Toggle image loading.
-
-*web_search*++
-       Type: string++
-       Default: d++
-       Start a web search.
-
-*zoom_in*++
-       Type: string++
-       Default: =++
-       Zoom in 10%.
-
-*zoom_out*++
-       Type: string++
-       Default: -++
-       Zoom out 10%.
-
-*zoom_reset*++
-       Type: string++
-       Default: -++
-       Reset zoom to default.
diff --git a/man/chorizo-usage.1.scd b/man/chorizo-usage.1.scd
deleted file mode 100644 (file)
index 66b0639..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-chorizo-usage(1)
-
-# NAME
-chorizo-usage - extended usage hints
-
-# DESCRIPTION
-*chorizo* is a simple web browser using GTK+ 3, GLib and WebKit2GTK+. This
-manpage contains additional hints and pointers regarding its usage.
-
-# KEYBINDINGS AND CONFIGURATION
-For this information, please refer to *chorizo-config*(5).
-
-# DOWNLOAD MANAGER
-Open the download manager using the appropriate hotkey. A new window listing
-your downloads will appear. Clicking on an item will remove it from the list and
-**if needed** cancel the download.
-
-There's no file manager integration, nor does *chorizo* delete, overwrite or
-resume downloads. If a file already exists, it won't be touched. Instead, the
-new file name will have a suffix such as *.1*, *.2*, *.3*, and so on.
-
-# USER-SUPPLIED JAVASCRIPT FILES
-When a page is being loaded, the directory _~/.local/share/chorizo/user-scripts_
-will be scanned and each file in it ending with *.js* will be run as a
-JavaScript file in the context of said page.
-
-*chorizo* comes with the following scripts:
-
-*hints.js*
-       Press *f* (open link in current window) or *F* (open in new window) to
-       activate link hints. After typing the characters for one of them, press
-       *Enter* to confirm. Press *Escape* to abort.
-
-*privacy-redirect.js*
-       Redirects YouTube, Reddit, etc to privacy respecting alternatives.
-
-*darkreader.js*
-       See https://darkreader.org.
-
-Those bundled scripts are automatically installed on *make install*. To use
-them, though, make sure to link them to the directory mentioned above.
-
-# USER-SUPPLIED CSS FILES
-User supplied CSS files will be scanned for from
-_~/.local/share/chorizo/user-styles_, and be applied every time a page
-loads. The rules in these files override any rules provided by the website.
-
-# WEB EXTENSIONS
-On startup, WebKit checks _~/.local/share/chorizo/web-extensions_ for any *.so*
-files. See
-<http://blogs.igalia.com/carlosgc/2013/09/10/webkit2gtk-web-process-extensions/>
-this blog post for further information on these extensions.
-
-*chorizo* comes with the following extensions:
-
-*we_adblock.so*
-       Generic adblock. Reads patterns from the file _~/.config/chorizo/adblock_. Each
-       line can contain a regular expression. These expressions match
-       case-insensitive and partially, i.e.*\*foo.\** is the same as *.\*FOO.\** and
-       you can use anchors like *^https?://...*. Please refer to
-       https://developer.gnome.org/glib/stable/glib-regex-syntax.html the GLib
-       reference for more details. Lines starting with "#" are ignored.
-
-       Those bundled web extensions are automatically compiled when you run *make*
-       and installed on *make install*. To use them, though, make sure to link them
-       to the directory mentioned above.
-
-# TRUSTED CERTIFICATES
-By default, *chorizo* trusts whatever CAs are trusted by WebKit. If you wish to
-trust additional certificates, such as self-signed certificates, the first thing
-you should do is try to add the appropriate CAs to your system-wide store.
-
-If you wish to add simple exceptions, you can grab the certificate and store it
-in the directory _~/.local/share/chorizo/certs_. The filename must be equal to
-the hostname:
-
-       $ echo | openssl s_client -connect foo.de:443 | openssl x509 >foo.de
-
-This tells *chorizo* to trust the given certificate when connecting to host
-*foo.de*.
-
-Note: This is NOT equal to certificate pinning. WebKit ignores user-specified
-certificates if the server's certificate can be validated by any system-wide CA.
-
-# SEE ALSO
-*chorizo*(1), *chorizo-config*(5)
diff --git a/man/chorizo.1.scd b/man/chorizo.1.scd
deleted file mode 100644 (file)
index 22dcf42..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-chorizo(1)
-
-# NAME
-chorizo - simple web browser
-
-# SYNOPSIS
-*chorizo* - [-C] [_URI ..._]
-
-# DESCRIPTION
-*chorizo* is a simple web browser using GTK+ 3, GLib and WebKit2GTK+.
-
-# OPTIONS
-In addition to the standard arguments of GTK+ 3, *chorizo* knows about the
-following options:
-
-*-C*
-       Disables cooperative instances.
-
-*-p*
-       Launch a private window.
-
-*-v*
-       Print version and exit.
-
-After these options there can be any number of URIs specified to open.
-
-# ENVIRONMENT
-In addition to the standard variables of GTK+ 3, *chorizo* knows about the
-following environment variable:
-
-*CHORIZO_FIFO_SUFFIX*
-       Cooperative instances are implemented using a named pipe in the file
-       system. The name of this pipe usually is (at least on modern systems following
-       XDG standards: /var/run/user/$UID/chorizo.fifo-$CHORIZO_FIFO_SUFFIX
-
-       *$UID* is the id of your user. *$CHORIZO_FIFO_SUFFIX* defaults to *main*. If you
-       change this variable, you can launch several independent cooperative instances
-       of *chorizo*.
-
-# FILES
-XDG variables will be used to construct these paths.
-*~/.config/chorizo/chorizo.ini*
-       Configuration file. See *chorizo-config*(5).
-
-*~/.config/chorizo/adblock*
-       Adblock patterns. See *chorizo-usage*(1).
-
-*~/.local/share/chorizo/certs*
-       Directory where trusted certificates are stored. See *chorizo-usage*(1).
-
-*~/.local/share/chorizo/cookies.db*
-       Database where cookies are stored. It is kept in the same format as Firefox,
-       so the file can easily be copied over.
-
-*~/.local/share/chorizo/user-scripts*
-       Directory to store user-supplied JavaScript snippets. See *chorizo-usage*(1).
-
-*~/.local/share/chorizo/user-styles*
-       Directory to store user-supplied CSS snippets. See *chorizo-usage*(1).
-
-*~/.local/share/chorizo/web-extensions*
-       Sets the directory where WebKit will look for web extensions. See
-       *chorizo-usage*(1).
-
-*~/.cache/chorizo*
-*~/.cache/webkitgtk*
-       General caches.
-
-*~/.local/share/webkitgtk*
-       WebKitGTK will dump its caches and local storage here. It is probably wise to
-       clean those directories regularly or to mount them as *tmpfs*(5).
-
-# LICENSE
-*chorizo* is released under the MIT license. See the accompanying LICENSE file.
-
-# HISTORY
-chorizo is a fork of the lariza browser by Peter Hofmann. The project was
-started in June 2014. This fork is maintained by Armaan Bhojwani.
-
-# SEE ALSO
-*chorizo-usage*(1), *chorizo-config*(5)
diff --git a/src/browser.c b/src/browser.c
deleted file mode 100644 (file)
index 3edab07..0000000
+++ /dev/null
@@ -1,1344 +0,0 @@
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <webkit2/webkit2.h>
-
-#include "downloads.h"
-
-void client_destroy(GtkWidget *, gpointer);
-WebKitWebView *client_new(const gchar *, WebKitWebView *, gboolean, gboolean);
-WebKitWebView *client_new_request(WebKitWebView *, WebKitNavigationAction *,
-                                  gpointer);
-void cooperation_setup(void);
-void changed_load_progress(GObject *, GParamSpec *, gpointer);
-void changed_favicon(GObject *, GParamSpec *, gpointer);
-void changed_title(GObject *, GParamSpec *, gpointer);
-void changed_uri(GObject *, GParamSpec *, gpointer);
-gboolean crashed_web_view(WebKitWebView *, gpointer);
-gboolean decide_policy(WebKitWebView *, WebKitPolicyDecision *,
-                       WebKitPolicyDecisionType, gpointer);
-gchar *ensure_uri_scheme(const gchar *);
-void grab_environment_configuration(void);
-void grab_feeds_finished(GObject *, GAsyncResult *, gpointer);
-void hover_web_view(WebKitWebView *, WebKitHitTestResult *, guint, gpointer);
-void icon_location(GtkEntry *, GtkEntryIconPosition, GdkEvent *, gpointer);
-void init_default_web_context(void);
-gboolean key_common(GtkWidget *, GdkEvent *, gpointer);
-gboolean key_location(GtkWidget *, GdkEvent *, gpointer);
-gboolean key_tablabel(GtkWidget *, GdkEvent *, gpointer);
-gboolean key_web_view(GtkWidget *, GdkEvent *, gpointer);
-void mainwindow_setup(void);
-void mainwindow_title(gint);
-void notebook_switch_page(GtkNotebook *, GtkWidget *, guint, gpointer);
-gboolean remote_msg(GIOChannel *, GIOCondition, gpointer);
-void run_user_scripts(WebKitWebView *);
-void search(gpointer, gint);
-void show_web_view(WebKitWebView *, gpointer);
-void trust_user_certs(WebKitWebContext *);
-GKeyFile *get_ini(void);
-GKeyFile *config;
-
-struct Client {
-    GtkWidget *imgbutton;
-    GtkWidget *jsbutton;
-    GtkWidget *location;
-    GtkWidget *tabicon;
-    GtkWidget *tablabel;
-    GtkWidget *vbox;
-    GtkWidget *web_view;
-    WebKitSettings *settings;
-    gboolean focus_new_tab;
-    gchar *external_handler_uri;
-    gchar *feed_html;
-    gchar *hover_uri;
-};
-
-struct Configuration {
-    gdouble zoom_level;
-    WebKitCookieAcceptPolicy cookie_policy;
-    gboolean cooperative_alone;
-    gboolean cooperative_instances;
-    gboolean images_enabled;
-    gboolean javascript_enabled;
-    gboolean private;
-    gboolean spellcheck_enabled;
-    gchar *default_uri;
-    gchar *home_uri;
-    gchar *search_engine;
-    gchar *spellcheck_language;
-    gint scroll_lines;
-    gint tab_width_chars;
-} cfg;
-
-struct MainWindow {
-    GtkWidget *win;
-    GtkWidget *notebook;
-} mw;
-
-gint clients = 0;
-struct Client **client_arr;
-
-int cooperative_pipe_fp = 0;
-gchar *search_text;
-
-void
-togglejs(GtkButton *jsbutton, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    webkit_settings_set_enable_javascript(
-        c->settings, !webkit_settings_get_enable_javascript(c->settings));
-    webkit_web_view_set_settings(WEBKIT_WEB_VIEW(c->web_view), c->settings);
-}
-
-void
-toggleimg(GtkButton *imgbutton, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    webkit_settings_set_auto_load_images(
-        c->settings, !webkit_settings_get_auto_load_images(c->settings));
-    webkit_web_view_set_settings(WEBKIT_WEB_VIEW(c->web_view), c->settings);
-}
-
-void
-client_destroy(GtkWidget *widget, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    gint idx;
-
-    g_signal_handlers_disconnect_by_func(G_OBJECT(c->web_view),
-                                         changed_load_progress, c);
-
-    idx = gtk_notebook_page_num(GTK_NOTEBOOK(mw.notebook), c->vbox);
-    if (idx == -1)
-        fprintf(stderr, __NAME__ ": Tab index was -1, bamboozled\n");
-    else
-        gtk_notebook_remove_page(GTK_NOTEBOOK(mw.notebook), idx);
-
-    free(c);
-    clients--;
-
-    quit_if_nothing_active();
-}
-
-void
-set_uri(const char *uri, struct Client *c) {
-    if (!gtk_widget_is_focus(c->location) && uri != NULL)
-        gtk_entry_set_text(GTK_ENTRY(c->location), uri);
-}
-
-WebKitWebView *
-client_new(const gchar *uri, WebKitWebView *related_wv, gboolean show,
-           gboolean focus_tab) {
-    struct Client *c;
-    gchar *f;
-    GtkWidget *evbox, *tabbox;
-
-    if (uri != NULL && cfg.cooperative_instances && !cfg.cooperative_alone) {
-        f = ensure_uri_scheme(uri);
-        write(cooperative_pipe_fp, f, strlen(f));
-        write(cooperative_pipe_fp, "\n", 1);
-        g_free(f);
-        return NULL;
-    }
-
-    c = calloc(1, sizeof(struct Client));
-    if (!c) {
-        fprintf(stderr, __NAME__ ": fatal: calloc failed\n");
-        exit(EXIT_FAILURE);
-    }
-
-    c->focus_new_tab = focus_tab;
-
-    if (related_wv == NULL) {
-        WebKitUserContentManager *ucm = webkit_user_content_manager_new();
-        WebKitUserScript *wkscript;
-        WebKitUserStyleSheet *wkstyle;
-        gchar *path = NULL, *source, *base;
-        const gchar *entry = NULL;
-        GDir *dir = NULL;
-
-        base = g_build_filename(g_get_user_data_dir(), __NAME__, "user-scripts",
-                                NULL);
-        dir = g_dir_open(base, 0, NULL);
-        if (dir != NULL) {
-            while ((entry = g_dir_read_name(dir)) != NULL) {
-                path = g_build_filename(base, entry, NULL);
-                if (g_str_has_suffix(path, ".js")) {
-                    g_file_get_contents(path, &source, NULL, NULL);
-                    wkscript = webkit_user_script_new(
-                        source, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
-                        WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START, NULL,
-                        NULL);
-                    webkit_user_content_manager_add_script(ucm, wkscript);
-                    webkit_user_script_unref(wkscript);
-                }
-                g_free(path);
-                g_free(source);
-            }
-            g_dir_close(dir);
-        }
-
-        base = g_build_filename(g_get_user_data_dir(), __NAME__, "user-styles",
-                                NULL);
-        dir = g_dir_open(base, 0, NULL);
-        if (dir != NULL) {
-            while ((entry = g_dir_read_name(dir)) != NULL) {
-                path = g_build_filename(base, entry, NULL);
-                if (g_str_has_suffix(path, ".css")) {
-                    g_file_get_contents(path, &source, NULL, NULL);
-                    wkstyle = webkit_user_style_sheet_new(
-                        source, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
-                        WEBKIT_USER_STYLE_LEVEL_USER, NULL, NULL);
-                    webkit_user_content_manager_add_style_sheet(ucm, wkstyle);
-                    webkit_user_style_sheet_unref(wkstyle);
-                }
-                g_free(path);
-                g_free(source);
-            }
-            g_dir_close(dir);
-        }
-
-        g_free(base);
-
-        c->web_view = webkit_web_view_new_with_user_content_manager(ucm);
-    } else {
-        c->web_view = webkit_web_view_new_with_related_view(related_wv);
-    }
-
-    // Get settings
-    c->settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(c->web_view));
-    webkit_settings_set_enable_javascript(c->settings, cfg.javascript_enabled);
-    webkit_settings_set_auto_load_images(c->settings, cfg.images_enabled);
-
-    GKeyFile *config = get_ini();
-    char *val;
-    val = g_key_file_get_string(config, "ui", "font_family_default", NULL);
-    if (val != NULL)
-        webkit_settings_set_default_font_family(c->settings, val);
-
-    val = g_key_file_get_string(config, "ui", "font_family_default_monospace",
-                                NULL);
-    if (val != NULL)
-        webkit_settings_set_monospace_font_family(c->settings, val);
-
-    val = g_key_file_get_string(config, "ui", "font_family_default_sans_serif",
-                                NULL);
-    if (val != NULL)
-        webkit_settings_set_sans_serif_font_family(c->settings, val);
-
-    val =
-        g_key_file_get_string(config, "ui", "font_family_default_serif", NULL);
-    if (val != NULL)
-        webkit_settings_set_serif_font_family(c->settings, val);
-
-    val = g_key_file_get_string(config, "browser", "user_agent", NULL);
-    if (val != NULL)
-        g_object_set(c->settings, "user-agent", val, NULL);
-
-    int val2;
-    val2 = g_key_file_get_integer(config, "ui", "font_size_default", NULL);
-    if (val2)
-        webkit_settings_set_default_font_size(c->settings, val2);
-
-    val2 = g_key_file_get_integer(config, "ui", "font_size_default_monospace",
-                                  NULL);
-    if (val2)
-        webkit_settings_set_default_monospace_font_size(c->settings, val2);
-
-    gboolean val3;
-    val3 = g_key_file_get_boolean(config, "browser", "console_to_stdout", NULL);
-    if (val3)
-        webkit_settings_set_enable_write_console_messages_to_stdout(c->settings,
-                                                                    val3);
-
-    val3 = g_key_file_get_boolean(config, "browser", "webgl_enable", NULL);
-    if (!val3)
-        webkit_settings_set_enable_webgl(c->settings, val3);
-
-    val3 = g_key_file_get_boolean(config, "browser",
-                                  "javascript_can_access_clipboard", NULL);
-    if (val3)
-        webkit_settings_set_javascript_can_access_clipboard(c->settings, val3);
-
-    double val4;
-    val4 = g_key_file_get_double(config, "ui", "zoom_level", NULL);
-    if (val4)
-        webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(c->web_view), val4);
-
-    webkit_settings_set_enable_developer_extras(c->settings, TRUE);
-
-    g_signal_connect(G_OBJECT(c->web_view), "notify::favicon",
-                     G_CALLBACK(changed_favicon), c);
-    g_signal_connect(G_OBJECT(c->web_view), "notify::title",
-                     G_CALLBACK(changed_title), c);
-    g_signal_connect(G_OBJECT(c->web_view), "notify::uri",
-                     G_CALLBACK(changed_uri), c);
-    g_signal_connect(G_OBJECT(c->web_view), "notify::estimated-load-progress",
-                     G_CALLBACK(changed_load_progress), c);
-    g_signal_connect(G_OBJECT(c->web_view), "create",
-                     G_CALLBACK(client_new_request), NULL);
-    g_signal_connect(G_OBJECT(c->web_view), "close", G_CALLBACK(client_destroy),
-                     c);
-    g_signal_connect(G_OBJECT(c->web_view), "decide-policy",
-                     G_CALLBACK(decide_policy), NULL);
-    g_signal_connect(G_OBJECT(c->web_view), "key-press-event",
-                     G_CALLBACK(key_web_view), c);
-    g_signal_connect(G_OBJECT(c->web_view), "button-release-event",
-                     G_CALLBACK(key_web_view), c);
-    g_signal_connect(G_OBJECT(c->web_view), "scroll-event",
-                     G_CALLBACK(key_web_view), c);
-    g_signal_connect(G_OBJECT(c->web_view), "mouse-target-changed",
-                     G_CALLBACK(hover_web_view), c);
-    g_signal_connect(G_OBJECT(c->web_view), "web-process-crashed",
-                     G_CALLBACK(crashed_web_view), c);
-
-    GtkWidget *locbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-
-    c->jsbutton = gtk_toggle_button_new_with_label("JS");
-    gtk_widget_set_tooltip_text(c->jsbutton, "Toggle JavaScript execution");
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->jsbutton),
-                                 cfg.javascript_enabled);
-    g_signal_connect(G_OBJECT(c->jsbutton), "toggled", G_CALLBACK(togglejs), c);
-
-    c->imgbutton = gtk_toggle_button_new_with_label("IMG");
-    gtk_widget_set_tooltip_text(c->imgbutton, "Toggle image loading");
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->imgbutton),
-                                 cfg.images_enabled);
-    g_signal_connect(G_OBJECT(c->imgbutton), "toggled", G_CALLBACK(toggleimg),
-                     c);
-
-    c->location = gtk_entry_new();
-    gtk_box_pack_start(GTK_BOX(locbox), c->location, TRUE, TRUE, 0);
-
-    if (cfg.private) {
-        GtkWidget *privindicator = gtk_label_new("Private mode");
-        gtk_widget_set_tooltip_text(
-            privindicator, "You are in private mode. No history, caches, or "
-                           "cookies will be saved beyond this session.");
-        gtk_box_pack_end(GTK_BOX(locbox), privindicator, FALSE, FALSE, 5);
-    }
-
-    gtk_box_pack_start(GTK_BOX(locbox), c->jsbutton, FALSE, FALSE, 5);
-    gtk_box_pack_start(GTK_BOX(locbox), c->imgbutton, FALSE, FALSE, 0);
-
-    g_signal_connect(G_OBJECT(c->location), "key-press-event",
-                     G_CALLBACK(key_location), c);
-    g_signal_connect(G_OBJECT(c->location), "icon-release",
-                     G_CALLBACK(icon_location), c);
-    /* XXX This is a workaround. Setting this to NULL (which is done in
-     * grab_feeds_finished() if no feed has been detected) adds a little
-     * padding left of the text. Not sure why. The point of this call
-     * right here is to have that padding right from the start. This
-     * avoids a graphical artifact. */
-    gtk_entry_set_icon_from_icon_name(GTK_ENTRY(c->location),
-                                      GTK_ENTRY_ICON_SECONDARY, NULL);
-
-    c->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
-    gtk_box_pack_start(GTK_BOX(c->vbox), locbox, FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(c->vbox), c->web_view, TRUE, TRUE, 0);
-    gtk_container_set_focus_child(GTK_CONTAINER(c->vbox), c->web_view);
-
-    c->tabicon =
-        gtk_image_new_from_icon_name("text-html", GTK_ICON_SIZE_SMALL_TOOLBAR);
-
-    c->tablabel = gtk_label_new(__NAME__);
-    gtk_label_set_ellipsize(GTK_LABEL(c->tablabel), PANGO_ELLIPSIZE_END);
-    gtk_label_set_width_chars(GTK_LABEL(c->tablabel), cfg.tab_width_chars);
-    gtk_widget_set_has_tooltip(c->tablabel, TRUE);
-
-    /* XXX I don't own a HiDPI screen, so I don't know if scale_factor
-     * does the right thing. */
-    tabbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
-                         5 * gtk_widget_get_scale_factor(mw.win));
-    gtk_box_pack_start(GTK_BOX(tabbox), c->tabicon, FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(tabbox), c->tablabel, TRUE, TRUE, 0);
-
-    evbox = gtk_event_box_new();
-    gtk_container_add(GTK_CONTAINER(evbox), tabbox);
-    g_signal_connect(G_OBJECT(evbox), "button-release-event",
-                     G_CALLBACK(key_tablabel), c);
-
-    gtk_widget_add_events(evbox, GDK_SCROLL_MASK);
-    g_signal_connect(G_OBJECT(evbox), "scroll-event", G_CALLBACK(key_tablabel),
-                     c);
-
-    // For easy access, store a reference to our label.
-    g_object_set_data(G_OBJECT(evbox), "chorizo-tab-label", c->tablabel);
-
-    /* This only shows the event box and the label inside, nothing else.
-     * Needed because the evbox/label is "internal" to the notebook and
-     * not part of the normal "widget tree" (IIUC). */
-    gtk_widget_show_all(evbox);
-
-    int page = gtk_notebook_get_current_page(GTK_NOTEBOOK(mw.notebook)) + 1;
-    gtk_notebook_insert_page(GTK_NOTEBOOK(mw.notebook), c->vbox, evbox, page);
-    gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(mw.notebook), c->vbox, TRUE);
-
-    if (show)
-        show_web_view(NULL, c);
-    else
-        g_signal_connect(G_OBJECT(c->web_view), "ready-to-show",
-                         G_CALLBACK(show_web_view), c);
-
-    if (uri != NULL) {
-        f = ensure_uri_scheme(uri);
-        webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->web_view), f);
-        g_free(f);
-    }
-
-    set_uri(uri, c);
-
-    clients++;
-    client_arr = realloc(client_arr, (clients + 1) * sizeof(client_arr[0]));
-    client_arr[clients] = c;
-
-    return WEBKIT_WEB_VIEW(c->web_view);
-}
-
-WebKitWebView *
-client_new_request(WebKitWebView *web_view,
-                   WebKitNavigationAction *navigation_action, gpointer data) {
-    return client_new(NULL, web_view, FALSE, FALSE);
-}
-
-void
-cooperation_setup(void) {
-    GIOChannel *towatch;
-    gchar *fifofilename, *fifopath;
-
-    gchar *priv = (cfg.private) ? "-private" : "";
-    fifofilename = g_strdup_printf("%s%s%s-%s", __NAME__, priv, ".fifo",
-                                   g_getenv(__NAME_UPPERCASE__ "_FIFO_SUFFIX"));
-    fifopath = g_build_filename(g_get_user_runtime_dir(), fifofilename, NULL);
-    g_free(fifofilename);
-
-    if (!g_file_test(fifopath, G_FILE_TEST_EXISTS))
-        mkfifo(fifopath, 0600);
-
-    cooperative_pipe_fp = open(fifopath, O_WRONLY | O_NONBLOCK);
-    if (!cooperative_pipe_fp) {
-        fprintf(stderr, __NAME__ ": Can't open FIFO at all.\n");
-    } else {
-        if (write(cooperative_pipe_fp, "", 0) == -1) {
-            /* Could not do an empty write to the FIFO which means there's
-             * no one listening. */
-            close(cooperative_pipe_fp);
-            towatch = g_io_channel_new_file(fifopath, "r+", NULL);
-            g_io_add_watch(towatch, G_IO_IN, (GIOFunc)remote_msg, NULL);
-        } else {
-            cfg.cooperative_alone = FALSE;
-        }
-    }
-
-    g_free(fifopath);
-}
-
-void
-changed_load_progress(GObject *obj, GParamSpec *pspec, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    gdouble p;
-    gchar *grab_feeds =
-        "a = document.querySelectorAll('"
-        "    html > head > "
-        "link[rel=\"alternate\"][href][type=\"application/atom+xml\"],"
-        "    html > head > "
-        "link[rel=\"alternate\"][href][type=\"application/rss+xml\"]"
-        "');"
-        "if (a.length == 0)"
-        "    null;"
-        "else {"
-        "    out = '';"
-        "    for (i = 0; i < a.length; i++) {"
-        "        url = encodeURIComponent(a[i].href);"
-        "        if ('title' in a[i] && a[i].title != '')"
-        "            title = encodeURIComponent(a[i].title);"
-        "        else"
-        "            title = url;"
-        "        out += '<li><a href=\"' + url + '\">' + title + "
-        "'</a></li>';"
-        "    }"
-        "    out;"
-        "}";
-
-    p = webkit_web_view_get_estimated_load_progress(
-        WEBKIT_WEB_VIEW(c->web_view));
-    if (p == 1) {
-        p = 0;
-
-        /* The page has loaded fully. We now run the short JavaScript
-         * snippet above that operates on the DOM. It tries to grab all
-         * occurences of <link rel="alternate" ...>, i.e. RSS/Atom feed
-         * references. */
-        webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(c->web_view), grab_feeds,
-                                       NULL, grab_feeds_finished, c);
-    }
-    gtk_entry_set_progress_fraction(GTK_ENTRY(c->location), p);
-}
-
-void
-changed_favicon(GObject *obj, GParamSpec *pspec, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    cairo_surface_t *f;
-    int w, h, w_should, h_should;
-    GdkPixbuf *pb, *pb_scaled;
-
-    f = webkit_web_view_get_favicon(WEBKIT_WEB_VIEW(c->web_view));
-    if (f == NULL) {
-        gtk_image_set_from_icon_name(GTK_IMAGE(c->tabicon), "text-html",
-                                     GTK_ICON_SIZE_SMALL_TOOLBAR);
-    } else {
-        w = cairo_image_surface_get_width(f);
-        h = cairo_image_surface_get_height(f);
-        pb = gdk_pixbuf_get_from_surface(f, 0, 0, w, h);
-        if (pb != NULL) {
-            w_should = 16 * gtk_widget_get_scale_factor(c->tabicon);
-            h_should = 16 * gtk_widget_get_scale_factor(c->tabicon);
-            pb_scaled = gdk_pixbuf_scale_simple(pb, w_should, h_should,
-                                                GDK_INTERP_BILINEAR);
-            gtk_image_set_from_pixbuf(GTK_IMAGE(c->tabicon), pb_scaled);
-
-            g_object_unref(pb_scaled);
-            g_object_unref(pb);
-        }
-    }
-}
-
-void
-changed_title(GObject *obj, GParamSpec *pspec, gpointer data) {
-    const gchar *t, *u;
-    struct Client *c = (struct Client *)data;
-
-    u = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
-    t = webkit_web_view_get_title(WEBKIT_WEB_VIEW(c->web_view));
-
-    u = u == NULL ? __NAME__ : u;
-    u = u[0] == 0 ? __NAME__ : u;
-
-    t = t == NULL ? u : t;
-    t = t[0] == 0 ? u : t;
-
-    gchar *name = malloc(strlen(t) + 4);
-    gboolean mute = webkit_web_view_get_is_muted(WEBKIT_WEB_VIEW(c->web_view));
-    gchar *muted = (mute) ? "[m] " : "";
-    sprintf(name, "%s%s", muted, t);
-    gtk_label_set_text(GTK_LABEL(c->tablabel), name);
-    g_free(name);
-
-    gtk_widget_set_tooltip_text(c->tablabel, t);
-    mainwindow_title(gtk_notebook_get_current_page(GTK_NOTEBOOK(mw.notebook)));
-}
-
-void
-changed_uri(GObject *obj, GParamSpec *pspec, gpointer data) {
-    const gchar *t;
-    struct Client *c = (struct Client *)data;
-    FILE *fp;
-
-    t = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
-
-    /* When a web process crashes, we get a "notify::uri" signal, but we
-     * can no longer read a meaningful URI. It's just an empty string
-     * now. Not updating the location bar in this scenario is important,
-     * because we would override the "WEB PROCESS CRASHED" message. */
-    if (t != NULL && strlen(t) > 0) {
-        set_uri(t, c);
-
-        gchar *history_file =
-            g_key_file_get_string(config, "browser", "history_file", NULL);
-
-        if (history_file != NULL && !cfg.private) {
-            fp = fopen(history_file, "a");
-            if (fp != NULL) {
-                fprintf(fp, "%s\n", t);
-                fclose(fp);
-            } else {
-                perror(__NAME__ ": Error opening history file");
-            }
-        }
-    }
-}
-
-gboolean
-crashed_web_view(WebKitWebView *web_view, gpointer data) {
-    gchar *t;
-    struct Client *c = (struct Client *)data;
-
-    t = g_strdup_printf("WEB PROCESS CRASHED: %s",
-                        webkit_web_view_get_uri(WEBKIT_WEB_VIEW(web_view)));
-    gtk_entry_set_text(GTK_ENTRY(c->location), t);
-    g_free(t);
-
-    return TRUE;
-}
-
-gboolean
-decide_policy(WebKitWebView *web_view, WebKitPolicyDecision *decision,
-              WebKitPolicyDecisionType type, gpointer data) {
-    WebKitResponsePolicyDecision *r;
-
-    switch (type) {
-    case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
-        r = WEBKIT_RESPONSE_POLICY_DECISION(decision);
-        if (!webkit_response_policy_decision_is_mime_type_supported(r))
-            webkit_policy_decision_download(decision);
-        else
-            webkit_policy_decision_use(decision);
-        break;
-    default:
-        // Use whatever default there is.
-        return FALSE;
-    }
-    return TRUE;
-}
-
-gchar *
-ensure_uri_scheme(const gchar *t) {
-    gchar *f, *fabs;
-
-    f = g_ascii_strdown(t, -1);
-    if (!g_str_has_prefix(f, "http:") && !g_str_has_prefix(f, "https:") &&
-        !g_str_has_prefix(f, "file:") && !g_str_has_prefix(f, "about:") &&
-        !g_str_has_prefix(f, "data:") && !g_str_has_prefix(f, "webkit:")) {
-        g_free(f);
-        fabs = realpath(t, NULL);
-        if (fabs != NULL) {
-            f = g_strdup_printf("file://%s", fabs);
-            free(fabs);
-        } else {
-            f = g_strdup_printf("http://%s", t);
-        }
-        return f;
-    } else
-        return g_strdup(t);
-}
-
-void
-get_config(void) {
-    cfg.cooperative_alone = TRUE;
-    cfg.cooperative_instances = TRUE;
-
-    config = get_ini();
-
-    cfg.home_uri = g_key_file_get_string(config, "browser", "homepage", NULL);
-    cfg.home_uri = (cfg.home_uri) ? cfg.home_uri : "about:blank";
-
-    cfg.javascript_enabled =
-        g_key_file_get_boolean(config, "browser", "javascript_enabled", NULL);
-    cfg.javascript_enabled =
-        (cfg.javascript_enabled) ? cfg.javascript_enabled : TRUE;
-
-    cfg.images_enabled =
-        g_key_file_get_boolean(config, "browser", "images_enabled", NULL);
-    cfg.images_enabled = (cfg.images_enabled) ? cfg.images_enabled : TRUE;
-
-    char *input_cookie_policy =
-        g_key_file_get_string(config, "browser", "cookie_policy", NULL);
-    cfg.cookie_policy = WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY;
-    if (input_cookie_policy) {
-        if (strcmp(input_cookie_policy, "all") == 0) {
-            cfg.cookie_policy = WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS;
-        } else if (strcmp(input_cookie_policy, "none") == 0) {
-            cfg.cookie_policy = WEBKIT_COOKIE_POLICY_ACCEPT_NEVER;
-        }
-    }
-
-    cfg.default_uri = g_key_file_get_string(config, "ui", "default_uri", NULL);
-    cfg.default_uri = (cfg.default_uri) ? cfg.default_uri : "https://";
-
-    cfg.tab_width_chars =
-        g_key_file_get_integer(config, "ui", "tab_width", NULL);
-    cfg.tab_width_chars = (cfg.tab_width_chars) ? cfg.tab_width_chars : 20;
-
-    cfg.search_engine =
-        g_key_file_get_string(config, "ui", "search_engine", NULL);
-    cfg.search_engine =
-        (cfg.search_engine) ? cfg.search_engine : "https://duckduckgo.com?q=";
-
-    cfg.spellcheck_enabled =
-        g_key_file_get_boolean(config, "ui", "spellcheck_enabled", NULL);
-    cfg.spellcheck_enabled =
-        (cfg.spellcheck_enabled) ? cfg.spellcheck_enabled : FALSE;
-
-    cfg.spellcheck_language =
-        g_key_file_get_string(config, "ui", "spellcheck_language", NULL);
-    cfg.spellcheck_language =
-        (cfg.spellcheck_language) ? cfg.spellcheck_language : "en_US";
-
-    cfg.scroll_lines =
-        g_key_file_get_integer(config, "ui", "scroll_lines", NULL);
-    cfg.scroll_lines = (cfg.scroll_lines) ? cfg.scroll_lines : 3;
-}
-
-void
-grab_feeds_finished(GObject *object, GAsyncResult *result, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    WebKitJavascriptResult *js_result;
-    JSCValue *value;
-    JSCException *exception;
-    GError *err = NULL;
-    gchar *str_value;
-
-    g_free(c->feed_html);
-    c->feed_html = NULL;
-
-    /* This was taken almost verbatim from the example in WebKit's
-     * documentation:
-     *
-     * https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html
-     */
-
-    js_result = webkit_web_view_run_javascript_finish(WEBKIT_WEB_VIEW(object),
-                                                      result, &err);
-    if (!js_result) {
-        fprintf(stderr, __NAME__ ": Error running javascript: %s\n",
-                err->message);
-        g_error_free(err);
-        return;
-    }
-
-    value = webkit_javascript_result_get_js_value(js_result);
-    if (jsc_value_is_string(value)) {
-        str_value = jsc_value_to_string(value);
-        exception = jsc_context_get_exception(jsc_value_get_context(value));
-        if (exception != NULL) {
-            fprintf(stderr, __NAME__ ": Error running javascript: %s\n",
-                    jsc_exception_get_message(exception));
-        } else {
-            c->feed_html = str_value;
-        }
-
-        gtk_entry_set_icon_from_icon_name(GTK_ENTRY(c->location),
-                                          GTK_ENTRY_ICON_SECONDARY,
-                                          "application-rss+xml-symbolic");
-        gtk_entry_set_icon_activatable(GTK_ENTRY(c->location),
-                                       GTK_ENTRY_ICON_SECONDARY, TRUE);
-    } else {
-        gtk_entry_set_icon_from_icon_name(GTK_ENTRY(c->location),
-                                          GTK_ENTRY_ICON_SECONDARY, NULL);
-    }
-
-    webkit_javascript_result_unref(js_result);
-}
-
-void
-hover_web_view(WebKitWebView *web_view, WebKitHitTestResult *ht,
-               guint modifiers, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    const char *to_show;
-
-    g_free(c->hover_uri);
-
-    if (webkit_hit_test_result_context_is_link(ht)) {
-        to_show = webkit_hit_test_result_get_link_uri(ht);
-        c->hover_uri = g_strdup(to_show);
-    } else {
-        to_show = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
-        c->hover_uri = NULL;
-    }
-
-    if (!gtk_widget_is_focus(c->location))
-        set_uri(to_show, c);
-}
-
-void
-icon_location(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event,
-              gpointer data) {
-    struct Client *c = (struct Client *)data;
-    gchar *d;
-    gchar *data_template = "data:text/html,"
-                           "<!DOCTYPE html>"
-                           "<html>"
-                           "    <head>"
-                           "        <meta charset=\"UTF-8\">"
-                           "        <title>Feeds</title>"
-                           "    </head>"
-                           "    <body>"
-                           "        <p>Feeds found on this page:</p>"
-                           "        <ul>"
-                           "        %s"
-                           "        </ul>"
-                           "    </body>"
-                           "</html>";
-
-    if (c->feed_html != NULL) {
-        /* What we're actually trying to do is show a simple HTML page
-         * that lists all the feeds on the current page. The function
-         * webkit_web_view_load_html() looks like the proper way to do
-         * that. Sad thing is, it doesn't create a history entry, but
-         * instead simply replaces the content of the current page. This
-         * is not what we want.
-         *
-         * RFC 2397 [0] defines the data URI scheme [1]. We abuse this
-         * mechanism to show my custom HTML snippet *and* create a
-         * history entry.
-         *
-         * [0]: https://tools.ietf.org/html/rfc2397
-         * [1]: https://en.wikipedia.org/wiki/Data_URI_scheme */
-        d = g_strdup_printf(data_template, c->feed_html);
-        webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->web_view), d);
-        g_free(d);
-    }
-}
-
-void
-init_default_web_context(void) {
-    gchar *p;
-    WebKitWebContext *wc;
-    WebKitCookieManager *cm;
-
-    wc = (cfg.private) ? webkit_web_context_new_ephemeral()
-                       : webkit_web_context_get_default();
-
-    p = g_build_filename(g_get_user_config_dir(), __NAME__, "adblock", NULL);
-    webkit_web_context_set_sandbox_enabled(wc, TRUE);
-    webkit_web_context_add_path_to_sandbox(wc, p, TRUE);
-    g_free(p);
-
-    WebKitProcessModel model =
-        WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES;
-    webkit_web_context_set_process_model(wc, model);
-
-    p = g_build_filename(g_get_user_data_dir(), __NAME__, "web-extensions",
-                         NULL);
-    webkit_web_context_set_web_extensions_directory(wc, p);
-    g_free(p);
-
-    char *xdg_down = getenv("XDG_DOWNLOAD_DIR");
-    g_signal_connect(G_OBJECT(wc), "download-started",
-                     G_CALLBACK(download_start),
-                     (xdg_down) ? xdg_down : "/var/tmp");
-
-    trust_user_certs(wc);
-
-    cm = webkit_web_context_get_cookie_manager(wc);
-    webkit_cookie_manager_set_accept_policy(cm, cfg.cookie_policy);
-
-    if (!cfg.private) {
-        webkit_web_context_set_favicon_database_directory(wc, NULL);
-
-        gchar *fname = g_build_filename("/", g_get_user_data_dir(), __NAME__,
-                                        "cookies.db", NULL);
-        WebKitCookiePersistentStorage type =
-            WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE;
-        webkit_cookie_manager_set_persistent_storage(cm, fname, type);
-        g_free(fname);
-    }
-
-    const gchar *const languages[2] = {(const gchar *)cfg.spellcheck_language,
-                                       NULL};
-    webkit_web_context_set_spell_checking_languages(wc, languages);
-    webkit_web_context_set_spell_checking_enabled(wc, cfg.spellcheck_enabled);
-}
-
-void
-search(gpointer data, gint direction) {
-    struct Client *c = (struct Client *)data;
-    WebKitWebView *web_view = WEBKIT_WEB_VIEW(c->web_view);
-    WebKitFindController *fc = webkit_web_view_get_find_controller(web_view);
-
-    if (search_text == NULL)
-        return;
-
-    switch (direction) {
-    case 0:
-        webkit_find_controller_search(fc, search_text,
-                                      WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE |
-                                          WEBKIT_FIND_OPTIONS_WRAP_AROUND,
-                                      G_MAXUINT);
-        break;
-    case 1:
-        webkit_find_controller_search_next(fc);
-        break;
-    case -1:
-        webkit_find_controller_search_previous(fc);
-        break;
-    case 2:
-        webkit_find_controller_search_finish(fc);
-        break;
-    }
-}
-
-void
-search_init(struct Client *c, int direction) {
-    gtk_widget_grab_focus(c->location);
-    const gchar *contents = gtk_entry_get_text(GTK_ENTRY(c->location));
-    if (strcspn(contents, "s/")) {
-        gtk_entry_set_text(GTK_ENTRY(c->location), "s/");
-        gtk_editable_set_position(GTK_EDITABLE(c->location), -1);
-    } else {
-        search(c, 0);
-        search(c, -1);
-        search(c, direction);
-    }
-}
-
-int
-def_key(char *key, unsigned int def) {
-    char *conf = g_key_file_get_string(config, "keybindings", key, NULL);
-    return (conf) ? gdk_keyval_from_name((conf) ? conf : NULL) : def;
-}
-
-gboolean
-key_common(GtkWidget *widget, GdkEvent *event, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    gdouble now;
-    gchar *f;
-
-    if (event->type == GDK_KEY_PRESS) {
-        if (((GdkEventKey *)event)->state & GDK_CONTROL_MASK) {
-            const char *uri =
-                webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
-            int key = ((GdkEventKey *)event)->keyval;
-            if (def_key("download_manager", GDK_KEY_y) == key) {
-                downloadmanager_show();
-                return TRUE;
-            } else if (def_key("history_back", GDK_KEY_h) == key) {
-                webkit_web_view_go_back(WEBKIT_WEB_VIEW(c->web_view));
-                return TRUE;
-            } else if (def_key("history_forwards", GDK_KEY_l) == key) {
-                webkit_web_view_go_forward(WEBKIT_WEB_VIEW(c->web_view));
-                return TRUE;
-            } else if (def_key("location", GDK_KEY_t) == key) {
-                gtk_widget_grab_focus(c->location);
-                const char *goal = (strcmp(cfg.home_uri, uri) == 0 || !uri)
-                                       ? cfg.default_uri
-                                       : uri;
-                gtk_entry_set_text(GTK_ENTRY(c->location), goal);
-                gtk_editable_set_position(GTK_EDITABLE(c->location), -1);
-                return TRUE;
-            } else if (def_key("print", GDK_KEY_Print) == key) {
-                WebKitPrintOperation *operation =
-                    webkit_print_operation_new(WEBKIT_WEB_VIEW(c->web_view));
-                GtkWidget *toplevel = gtk_widget_get_toplevel(mw.win);
-                webkit_print_operation_run_dialog(operation,
-                                                  GTK_WINDOW(toplevel));
-                return TRUE;
-            } else if (def_key("quit", GDK_KEY_g) == key) {
-                search(c, 2);
-                gtk_widget_grab_focus(c->web_view);
-                gtk_entry_set_text(GTK_ENTRY(c->location), uri);
-                gtk_editable_set_position(GTK_EDITABLE(c->location), -1);
-                webkit_web_view_run_javascript(
-                    WEBKIT_WEB_VIEW(c->web_view),
-                    "window.getSelection().removeAllRanges();"
-                    "document.activeElement.blur();",
-                    NULL, NULL, c);
-                return TRUE;
-            } else if (def_key("reload", GDK_KEY_e) == key) {
-                webkit_web_view_reload_bypass_cache(
-                    WEBKIT_WEB_VIEW(c->web_view));
-                return TRUE;
-            } else if (def_key("scroll_line_down", GDK_KEY_j) == key) {
-                for (int i = 0; i <= cfg.scroll_lines - 1; i++) {
-                    event->key.keyval = GDK_KEY_Down;
-                    gdk_event_put(event);
-                }
-                return TRUE;
-            } else if (def_key("scroll_line_up", GDK_KEY_k) == key) {
-                for (int i = 0; i <= cfg.scroll_lines - 1; i++) {
-                    event->key.keyval = GDK_KEY_Up;
-                    gdk_event_put(event);
-                }
-                return TRUE;
-            } else if (def_key("scroll_page_down", GDK_KEY_f) == key) {
-                event->key.keyval = GDK_KEY_Page_Down;
-                gdk_event_put(event);
-                return TRUE;
-            } else if (def_key("scroll_page_up", GDK_KEY_b) == key) {
-                event->key.keyval = GDK_KEY_Page_Up;
-                gdk_event_put(event);
-                return TRUE;
-            } else if (def_key("search_forwards", GDK_KEY_s) == key) {
-                search_init(c, 1);
-                return TRUE;
-            } else if (def_key("search_backwards", GDK_KEY_r) == key) {
-                search_init(c, -1);
-                return TRUE;
-            } else if (def_key("tab_close", GDK_KEY_q) == key) {
-                client_destroy(NULL, c);
-                return TRUE;
-            } else if (def_key("tab_switch_1", GDK_KEY_1) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 0);
-                return TRUE;
-            } else if (def_key("tab_switch_2", GDK_KEY_2) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 1);
-                return TRUE;
-            } else if (def_key("tab_switch_3", GDK_KEY_3) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 2);
-                return TRUE;
-            } else if (def_key("tab_switch_4", GDK_KEY_4) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 3);
-                return TRUE;
-            } else if (def_key("tab_switch_5", GDK_KEY_5) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 4);
-                return TRUE;
-            } else if (def_key("tab_switch_6", GDK_KEY_6) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 5);
-                return TRUE;
-            } else if (def_key("tab_switch_7", GDK_KEY_7) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 6);
-                return TRUE;
-            } else if (def_key("tab_switch_8", GDK_KEY_8) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 7);
-                return TRUE;
-            } else if (def_key("tab_switch_9", GDK_KEY_9) == key) {
-                gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), 8);
-                return TRUE;
-            } else if (def_key("tab_previous", GDK_KEY_u) == key) {
-                gtk_notebook_prev_page(GTK_NOTEBOOK(mw.notebook));
-                return TRUE;
-            } else if (def_key("tab_mute", GDK_KEY_m) == key) {
-                gboolean muted =
-                    webkit_web_view_get_is_muted(WEBKIT_WEB_VIEW(c->web_view));
-                webkit_web_view_set_is_muted(WEBKIT_WEB_VIEW(c->web_view),
-                                             !muted);
-                changed_title(G_OBJECT(c->web_view), NULL, c);
-                return TRUE;
-            } else if (def_key("tab_new", GDK_KEY_w) == key) {
-                f = ensure_uri_scheme(cfg.home_uri);
-                client_new(f, NULL, TRUE, TRUE);
-                g_free(f);
-                return TRUE;
-            } else if (def_key("tab_next", GDK_KEY_i) == key) {
-                gtk_notebook_next_page(GTK_NOTEBOOK(mw.notebook));
-                return TRUE;
-            } else if (def_key("toggle_js", GDK_KEY_o) == key) {
-                gboolean on =
-                    webkit_settings_get_enable_javascript(c->settings);
-                webkit_settings_set_enable_javascript(c->settings, !on);
-                webkit_web_view_set_settings(WEBKIT_WEB_VIEW(c->web_view),
-                                             c->settings);
-                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->jsbutton),
-                                             !on);
-            } else if (def_key("toggle_img", -1) == key) {
-                gboolean on = webkit_settings_get_auto_load_images(c->settings);
-                webkit_settings_set_auto_load_images(c->settings, !on);
-                webkit_web_view_set_settings(WEBKIT_WEB_VIEW(c->web_view),
-                                             c->settings);
-                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->imgbutton),
-                                             !on);
-            } else if (def_key("web_search", GDK_KEY_d) == key) {
-                gtk_widget_grab_focus(c->location);
-                gtk_entry_set_text(GTK_ENTRY(c->location), "w/");
-                gtk_editable_set_position(GTK_EDITABLE(c->location), -1);
-                return TRUE;
-            } else if (def_key("zoom_in", GDK_KEY_equal) == key) {
-                now = webkit_web_view_get_zoom_level(
-                    WEBKIT_WEB_VIEW(c->web_view));
-                webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(c->web_view),
-                                               now + 0.1);
-                return TRUE;
-            } else if (def_key("zoom_out", GDK_KEY_minus) == key) {
-                now = webkit_web_view_get_zoom_level(
-                    WEBKIT_WEB_VIEW(c->web_view));
-                webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(c->web_view),
-                                               now - 0.1);
-                return TRUE;
-            } else if (def_key("zoom_reset", GDK_KEY_0) == key) {
-                webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(c->web_view),
-                                               cfg.zoom_level);
-                return TRUE;
-            }
-        }
-    }
-    return FALSE;
-}
-
-gboolean
-key_location(GtkWidget *widget, GdkEvent *event, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    const gchar *t;
-    gchar *f;
-
-    if (key_common(widget, event, data))
-        return TRUE;
-
-    if (event->type == GDK_KEY_PRESS) {
-        int key = ((GdkEventKey *)event)->keyval;
-        if ((GDK_KEY_KP_Enter == key) || (GDK_KEY_Return == key)) {
-            gtk_widget_grab_focus(c->web_view);
-            t = gtk_entry_get_text(GTK_ENTRY(c->location));
-            if (t != NULL && t[0] == 's' && t[1] == '/') {
-                if (search_text != NULL)
-                    g_free(search_text);
-                search_text = g_strdup(t + 2);
-                search(c, 0);
-            } else if (t != NULL && t[0] == 'w' && t[1] == '/') {
-                int len = strlen(cfg.search_engine) + strlen(t) - 2;
-                gchar *f = malloc(len + 1);
-                snprintf(f, len + 1, "%s%s", cfg.search_engine, t + 2);
-                webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->web_view), f);
-                g_free(f);
-            } else {
-                f = ensure_uri_scheme(t);
-                webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->web_view), f);
-                g_free(f);
-            }
-            return TRUE;
-        } else if (GDK_KEY_Escape == key) {
-            t = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(c->web_view));
-            gtk_entry_set_text(GTK_ENTRY(c->location), (t == NULL) ? "" : t);
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-gboolean
-key_tablabel(GtkWidget *widget, GdkEvent *event, gpointer data) {
-    GdkScrollDirection direction;
-
-    if (event->type == GDK_BUTTON_RELEASE) {
-        switch (((GdkEventButton *)event)->button) {
-        case 2:
-            client_destroy(NULL, data);
-            return TRUE;
-        }
-    } else if (event->type == GDK_SCROLL) {
-        gdk_event_get_scroll_direction(event, &direction);
-        switch (direction) {
-        case GDK_SCROLL_UP:
-            gtk_notebook_prev_page(GTK_NOTEBOOK(mw.notebook));
-            break;
-        case GDK_SCROLL_DOWN:
-            gtk_notebook_next_page(GTK_NOTEBOOK(mw.notebook));
-            break;
-        default:
-            break;
-        }
-        return TRUE;
-    }
-    return FALSE;
-}
-
-gboolean
-key_web_view(GtkWidget *widget, GdkEvent *event, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    gdouble dx, dy;
-    gfloat z;
-
-    if (key_common(widget, event, data))
-        return TRUE;
-
-    if (event->type == GDK_KEY_PRESS) {
-        if (((GdkEventKey *)event)->keyval == GDK_KEY_Escape) {
-            webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(c->web_view));
-            gtk_entry_set_progress_fraction(GTK_ENTRY(c->location), 0);
-        }
-    } else if (event->type == GDK_BUTTON_RELEASE) {
-        GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask();
-        switch (((GdkEventButton *)event)->button) {
-        case 1:
-            if ((((GdkEventButton *)event)->state & modifiers) ==
-                    GDK_CONTROL_MASK &&
-                c->hover_uri != NULL) {
-                client_new(c->hover_uri, NULL, TRUE, FALSE);
-                return TRUE;
-            }
-            break;
-        case 8:
-            webkit_web_view_go_back(WEBKIT_WEB_VIEW(c->web_view));
-            return TRUE;
-        case 9:
-            webkit_web_view_go_forward(WEBKIT_WEB_VIEW(c->web_view));
-            return TRUE;
-        }
-    } else if (event->type == GDK_SCROLL) {
-        event->scroll.delta_y *= cfg.scroll_lines;
-        if (((GdkEventScroll *)event)->state & GDK_CONTROL_MASK) {
-            gdk_event_get_scroll_deltas(event, &dx, &dy);
-            z = webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(c->web_view));
-            z += -dy * 0.1;
-            z = dx != 0 ? cfg.zoom_level : z;
-            webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(c->web_view), z);
-            return TRUE;
-        }
-    }
-
-    return FALSE;
-}
-
-void
-mainwindow_setup(void) {
-    mw.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-    gtk_window_set_default_size(GTK_WINDOW(mw.win), 800, 600);
-    g_signal_connect(G_OBJECT(mw.win), "destroy", gtk_main_quit, NULL);
-
-    gchar *priv = (cfg.private) ? "-private" : "";
-    gchar *title = malloc(strlen(priv) + strlen(__NAME__) + 1);
-    sprintf(title, "%s%s", __NAME__, priv);
-    gtk_window_set_title(GTK_WINDOW(mw.win), title);
-    g_free(title);
-
-    mw.notebook = gtk_notebook_new();
-    gtk_notebook_set_scrollable(GTK_NOTEBOOK(mw.notebook), TRUE);
-    gtk_container_add(GTK_CONTAINER(mw.win), mw.notebook);
-    g_signal_connect(G_OBJECT(mw.notebook), "switch-page",
-                     G_CALLBACK(notebook_switch_page), NULL);
-}
-
-void
-mainwindow_title(gint idx) {
-    GtkWidget *child, *widg, *tablabel;
-    const gchar *text;
-
-    child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(mw.notebook), idx);
-    if (child == NULL)
-        return;
-
-    widg = gtk_notebook_get_tab_label(GTK_NOTEBOOK(mw.notebook), child);
-    tablabel =
-        (GtkWidget *)g_object_get_data(G_OBJECT(widg), "chorizo-tab-label");
-    text = gtk_label_get_text(GTK_LABEL(tablabel));
-    gtk_window_set_title(GTK_WINDOW(mw.win), text);
-}
-
-void
-notebook_switch_page(GtkNotebook *nb, GtkWidget *p, guint idx, gpointer data) {
-    mainwindow_title(idx);
-}
-
-gboolean
-quit_if_nothing_active(void) {
-    if (clients == 0) {
-        if (downloads == 0) {
-            gtk_main_quit();
-            return TRUE;
-        } else {
-            downloadmanager_show();
-        }
-    }
-
-    return FALSE;
-}
-
-gboolean
-remote_msg(GIOChannel *channel, GIOCondition condition, gpointer data) {
-    gchar *uri = NULL;
-
-    g_io_channel_read_line(channel, &uri, NULL, NULL, NULL);
-    if (uri) {
-        g_strstrip(uri);
-        client_new(uri, NULL, TRUE, TRUE);
-        g_free(uri);
-    }
-    return TRUE;
-}
-
-void
-show_web_view(WebKitWebView *web_view, gpointer data) {
-    struct Client *c = (struct Client *)data;
-    gint idx;
-
-    (void)web_view;
-
-    gtk_widget_show_all(mw.win);
-
-    if (c->focus_new_tab) {
-        idx = gtk_notebook_page_num(GTK_NOTEBOOK(mw.notebook), c->vbox);
-        if (idx != -1)
-            gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.notebook), idx);
-
-        gtk_widget_grab_focus(c->web_view);
-    }
-}
-
-void
-trust_user_certs(WebKitWebContext *wc) {
-    GTlsCertificate *cert;
-    gchar *basedir, *absfile;
-    const gchar *file;
-    GDir *dir = NULL;
-
-    basedir = g_build_filename(g_get_user_data_dir(), __NAME__, "certs", NULL);
-    dir = g_dir_open(basedir, 0, NULL);
-    g_free(basedir);
-    if (dir != NULL) {
-        file = g_dir_read_name(dir);
-        while (file != NULL) {
-            absfile = g_build_filename(g_get_user_data_dir(), __NAME__, "certs",
-                                       file, NULL);
-            cert = g_tls_certificate_new_from_file(absfile, NULL);
-            g_free(absfile);
-            if (cert == NULL)
-                fprintf(stderr, __NAME__ ": Could not load trusted cert '%s'\n",
-                        file);
-            else
-                webkit_web_context_allow_tls_certificate_for_host(wc, cert,
-                                                                  file);
-            file = g_dir_read_name(dir);
-        }
-        g_dir_close(dir);
-    }
-}
-
-GKeyFile *
-get_ini(void) {
-    GKeyFileFlags flags = G_KEY_FILE_NONE;
-    config = g_key_file_new();
-
-    // Load user config
-    gchar *fname = g_build_filename(g_get_user_config_dir(), __NAME__,
-                                    "chorizo.ini", NULL);
-    if (!g_key_file_load_from_file(config, fname, flags, NULL)) {
-        // Load global config
-        if (!g_key_file_load_from_file(config, "/etc/chorizo.ini", flags,
-                                       NULL)) {
-            fprintf(stderr, "Could not load chorizo.ini");
-        }
-    }
-    g_free(fname);
-    return config;
-}
-
-int
-main(int argc, char **argv) {
-    int opt, i;
-
-    while ((opt = getopt(argc, argv, "Cpv")) != -1) {
-        switch (opt) {
-        case 'C':
-            cfg.cooperative_instances = FALSE;
-            break;
-        case 'p':
-            cfg.private = true;
-            break;
-        case 'v':
-            printf("%s %s\n", __NAME__, VERSION);
-            exit(0);
-        default:
-            fprintf(stderr, "Usage: " __NAME__ " [OPTION]... [URI]...\n");
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    gtk_init(&argc, &argv);
-
-    // Keep clipboard contents after program closes
-    gtk_clipboard_store(gtk_clipboard_get_for_display(gdk_display_get_default(),
-                                                      GDK_SELECTION_CLIPBOARD));
-
-    get_config();
-
-    if (cfg.cooperative_instances)
-        cooperation_setup();
-
-    if (!cfg.cooperative_instances || cfg.cooperative_alone)
-        init_default_web_context();
-
-    downloadmanager_setup();
-    mainwindow_setup();
-
-    client_arr = malloc(sizeof(struct Client *));
-    if (optind >= argc) {
-        client_new(cfg.home_uri, NULL, TRUE, TRUE);
-    } else {
-        for (i = optind; i < argc; i++)
-            client_new(argv[i], NULL, TRUE, TRUE);
-    }
-
-    if (!cfg.cooperative_instances || cfg.cooperative_alone)
-        gtk_main();
-
-    for (int i = 0; i < clients; i++) {
-        free(&(client_arr[i]));
-    }
-
-    exit(EXIT_SUCCESS);
-}
diff --git a/src/downloads.c b/src/downloads.c
deleted file mode 100644 (file)
index db7aaf8..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-#include <webkit2/webkit2.h>
-
-#include "downloads.h"
-
-gboolean download_handle(WebKitDownload *, gchar *, gpointer);
-void download_click(GtkToolButton *, gpointer);
-void download_cancel(GtkMenuItem *, gpointer);
-gboolean downloadmanager_delete(GtkWidget *, gpointer);
-
-struct DownloadManager {
-    GtkWidget *scroll;
-    GtkWidget *toolbar;
-    GtkWidget *win;
-} dm;
-
-gint downloads = 0;
-
-struct DownloadItem {
-    GtkToolButton *tb;
-    WebKitDownload *download;
-};
-
-gboolean
-key_downloadmanager(GtkWidget *widget, GdkEvent *event, gpointer data) {
-    if (event->type == GDK_KEY_PRESS) {
-        if (((GdkEventKey *)event)->state & GDK_CONTROL_MASK) {
-            int key = ((GdkEventKey *)event)->keyval;
-            if ((def_key("close_tab", GDK_KEY_q) == key) ||
-                (def_key("download_manager", GDK_KEY_y) == key)) {
-                downloadmanager_delete(dm.win, NULL);
-                return TRUE;
-            }
-        }
-    }
-
-    return FALSE;
-}
-
-void
-changed_download_progress(GObject *obj, GParamSpec *pspec, gpointer data) {
-    WebKitDownload *download = WEBKIT_DOWNLOAD(obj);
-    WebKitURIResponse *resp;
-    GtkToolItem *tb = GTK_TOOL_ITEM(data);
-    gdouble p, size_mb;
-    const gchar *uri;
-    gchar *t, *filename, *base;
-
-    p = webkit_download_get_estimated_progress(download);
-    p = p > 1 ? 1 : p;
-    p = p < 0 ? 0 : p;
-    p *= 100;
-    resp = webkit_download_get_response(download);
-    size_mb = webkit_uri_response_get_content_length(resp) / 1e6;
-
-    uri = webkit_download_get_destination(download);
-    filename = g_filename_from_uri(uri, NULL, NULL);
-    base = g_path_get_basename(filename);
-    t = g_strdup_printf("%s (%.0f%% of %.1f MB)", base, p, size_mb);
-    g_free(filename);
-    g_free(base);
-    gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), t);
-    g_free(t);
-}
-
-void
-download_finished(WebKitDownload *download, gpointer data) {
-    if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(data)),
-               "dialog-error") != 0)
-        gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(data),
-                                      "emblem-downloads");
-    downloads--;
-}
-
-void
-download_start(WebKitWebView *web_view, WebKitDownload *download,
-               gpointer data) {
-    g_signal_connect(G_OBJECT(download), "decide-destination",
-                     G_CALLBACK(download_handle), data);
-}
-
-gboolean
-download_handle(WebKitDownload *download, gchar *suggested_filename,
-                gpointer data) {
-    gchar *uri;
-    GtkToolItem *tb;
-
-    GtkWidget *chooser = gtk_file_chooser_dialog_new(
-        "Choose download location", GTK_WINDOW(dm.win),
-        GTK_FILE_CHOOSER_ACTION_SAVE, "Save file", GTK_RESPONSE_ACCEPT,
-        "Cancel", GTK_RESPONSE_CANCEL, NULL);
-    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser),
-                                        (char *)data);
-    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser),
-                                      suggested_filename);
-    gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(chooser),
-                                                   TRUE);
-    gint res = gtk_dialog_run(GTK_DIALOG(chooser));
-
-    switch (res) {
-    case GTK_RESPONSE_ACCEPT:
-        uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(chooser));
-        webkit_download_set_destination(
-            download, gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(chooser)));
-        break;
-    case GTK_RESPONSE_CANCEL:
-        return FALSE;
-    default:
-        return FALSE;
-    }
-
-    gtk_widget_destroy(chooser);
-
-    remove(uri + 7);
-    tb = gtk_tool_button_new(NULL, NULL);
-    gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(tb), "network-receive");
-    gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), uri);
-    gtk_toolbar_insert(GTK_TOOLBAR(dm.toolbar), tb, 0);
-    gtk_widget_show_all(dm.win);
-
-    g_signal_connect(G_OBJECT(download), "notify::estimated-progress",
-                     G_CALLBACK(changed_download_progress), tb);
-
-    downloads++;
-    g_signal_connect(G_OBJECT(download), "finished",
-                     G_CALLBACK(download_finished), tb);
-
-    g_object_ref(download);
-
-    struct DownloadItem *payload = malloc(sizeof(*payload));
-    payload->tb = (GtkToolButton *)tb;
-    payload->download = download;
-    g_signal_connect(G_OBJECT(tb), "clicked", G_CALLBACK(download_click),
-                     payload);
-    g_signal_connect(G_OBJECT(tb), "failed", G_CALLBACK(download_cancel),
-                     payload);
-    g_signal_connect(G_OBJECT(tb), "destroy_event", G_CALLBACK(g_free),
-                     payload);
-
-    // Propagate -- to whom it may concern.
-    return FALSE;
-}
-
-void
-download_cancel(GtkMenuItem *tb, gpointer data) {
-    struct DownloadItem *payload = data;
-    gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(payload->tb), "dialog-error");
-    webkit_download_cancel(payload->download);
-}
-
-void
-download_remove(GtkMenuItem *tb, gpointer data) {
-    struct DownloadItem *payload = data;
-    g_object_unref(payload->download);
-    gtk_widget_destroy(GTK_WIDGET(payload->tb));
-}
-
-void
-download_copy_url(GtkMenuItem *tb, gpointer data) {
-    struct DownloadItem *payload = data;
-    WebKitURIRequest *req = webkit_download_get_request(payload->download);
-    const gchar *uri = webkit_uri_request_get_uri(req);
-    gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), uri,
-                           strlen(uri));
-}
-
-void
-download_copy_path(GtkMenuItem *tb, gpointer data) {
-    struct DownloadItem *payload = data;
-    const gchar *path = webkit_download_get_destination(payload->download);
-    gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), path + 7,
-                           strlen(path) - 7); // Offset by 7 to remove "file://"
-}
-
-void
-download_xdg_open(GtkMenuItem *tb, gpointer data) {
-    struct DownloadItem *payload = data;
-    const gchar *path = webkit_download_get_destination(payload->download);
-    char *cmd = malloc(strlen(path) + 9);
-    sprintf(cmd, "xdg-open %s", path);
-    system(cmd);
-}
-
-void
-download_click(GtkToolButton *tb, gpointer data) {
-    GtkWidget *pmenu = gtk_menu_new();
-    GtkWidget *option;
-
-    if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(tb)),
-               "network-receive") == 0) {
-        option = gtk_menu_item_new_with_label("Cancel download");
-        g_signal_connect(G_OBJECT(option), "activate",
-                         G_CALLBACK(download_cancel), data);
-        gtk_widget_show(option);
-        gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
-    } else {
-        option = gtk_menu_item_new_with_label("Remove download");
-        g_signal_connect(G_OBJECT(option), "activate",
-                         G_CALLBACK(download_remove), data);
-        gtk_widget_show(option);
-        gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
-
-        option = gtk_menu_item_new_with_label("Open file with xdg-open");
-        gtk_widget_show(option);
-        gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
-        g_signal_connect(G_OBJECT(option), "activate",
-                         G_CALLBACK(download_xdg_open), data);
-    }
-
-    option = gtk_menu_item_new_with_label("Copy download URL");
-    gtk_widget_show(option);
-    gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
-    g_signal_connect(G_OBJECT(option), "activate",
-                     G_CALLBACK(download_copy_url), data);
-
-    option = gtk_menu_item_new_with_label("Copy local path");
-    gtk_widget_show(option);
-    gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
-    g_signal_connect(G_OBJECT(option), "activate",
-                     G_CALLBACK(download_copy_path), data);
-
-    gtk_menu_popup_at_pointer(GTK_MENU(pmenu), NULL);
-}
-
-gboolean
-downloadmanager_delete(GtkWidget *obj, gpointer data) {
-    if (!quit_if_nothing_active())
-        gtk_widget_hide(dm.win);
-
-    return TRUE;
-}
-
-void
-downloadmanager_setup(void) {
-    dm.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-    gtk_window_set_type_hint(GTK_WINDOW(dm.win), GDK_WINDOW_TYPE_HINT_DIALOG);
-    gtk_window_set_default_size(GTK_WINDOW(dm.win), 500, 250);
-    gtk_window_set_title(GTK_WINDOW(dm.win), __NAME__ " - Download Manager");
-    g_signal_connect(G_OBJECT(dm.win), "delete-event",
-                     G_CALLBACK(downloadmanager_delete), NULL);
-    g_signal_connect(G_OBJECT(dm.win), "key-press-event",
-                     G_CALLBACK(key_downloadmanager), NULL);
-
-    dm.toolbar = gtk_toolbar_new();
-    gtk_orientable_set_orientation(GTK_ORIENTABLE(dm.toolbar),
-                                   GTK_ORIENTATION_VERTICAL);
-    gtk_toolbar_set_style(GTK_TOOLBAR(dm.toolbar), GTK_TOOLBAR_BOTH_HORIZ);
-    gtk_toolbar_set_show_arrow(GTK_TOOLBAR(dm.toolbar), FALSE);
-
-    dm.scroll = gtk_scrolled_window_new(NULL, NULL);
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dm.scroll),
-                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-    gtk_container_add(GTK_CONTAINER(dm.scroll), dm.toolbar);
-
-    gtk_container_add(GTK_CONTAINER(dm.win), dm.scroll);
-}
-
-void
-downloadmanager_show(void) {
-    gtk_widget_show_all(dm.win);
-}
diff --git a/src/downloads.h b/src/downloads.h
deleted file mode 100644 (file)
index cd80b9b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-extern int downloads;
-gboolean quit_if_nothing_active(void);
-int def_key(char *, unsigned int);
-void download_start(WebKitWebView *, WebKitDownload *, gpointer);
-void downloadmanager_setup(void);
-void downloadmanager_show(void);
diff --git a/user-scripts/darkreader.js b/user-scripts/darkreader.js
new file mode 100644 (file)
index 0000000..e253e86
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * Minified by jsDelivr using Terser v5.7.1.
+ * Original file: /npm/darkreader@4.9.39/darkreader.js
+ *
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
+ */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DarkReader={})}(this,(function(e){"use strict";
+/*! *****************************************************************************
+    Copyright (c) Microsoft Corporation.
+
+    Permission to use, copy, modify, and/or distribute this software for any
+    purpose with or without fee is hereby granted.
+
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+    PERFORMANCE OF THIS SOFTWARE.
+    ***************************************************************************** */var t=function(){return(t=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var o in t=arguments[r])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};function r(e,t,r,n){return new(r||(r=Promise))((function(o,a){function i(e){try{s(n.next(e))}catch(e){a(e)}}function u(e){try{s(n.throw(e))}catch(e){a(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,u)}s((n=n.apply(e,t||[])).next())}))}function n(e,t){var r,n,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(r)throw new TypeError("Generator is already executing.");for(;i;)try{if(r=1,n&&(o=2&a[0]?n.return:a[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,a[1])).done)return o;switch(n=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,n=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=i.trys,(o=o.length>0&&o[o.length-1])||6!==a[0]&&2!==a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],n=0}finally{r=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}}function o(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function a(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i}function i(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o<a;o++)!n&&o in t||(n||(n=Array.prototype.slice.call(t,0,o)),n[o]=t[o]);return e.concat(n||t)}var u="bg-fetch-response",s="cs-fetch",c="undefined"==typeof navigator?"some useragent":navigator.userAgent.toLowerCase(),l="undefined"==typeof navigator?"some platform":navigator.platform.toLowerCase(),d=c.includes("chrome")||c.includes("chromium"),f=c.includes("thunderbird"),h=c.includes("firefox")||f;c.includes("vivaldi"),c.includes("yabrowser"),c.includes("opr")||c.includes("opera"),c.includes("edg");var p=c.includes("safari")&&!d,v=l.startsWith("win"),m=l.startsWith("mac");c.includes("mobile");var g,b="function"==typeof ShadowRoot,y="function"==typeof MediaQueryList&&"function"==typeof MediaQueryList.prototype.addEventListener;(g=c.match(/chrom[e|ium]\/([^ ]+)/))&&g[1]&&g[1];var w=function(){try{return document.querySelector(":defined"),!0}catch(e){return!1}}();function k(e,t,o){return r(this,void 0,void 0,(function(){var r;return n(this,(function(n){switch(n.label){case 0:return[4,fetch(e,{cache:"force-cache",credentials:"omit",referrer:o})];case 1:if(r=n.sent(),h&&"text/css"===t&&e.startsWith("moz-extension://")&&e.endsWith(".css"))return[2,r];if(t&&!r.headers.get("Content-Type").startsWith(t))throw new Error("Mime type mismatch when loading "+e);if(!r.ok)throw new Error("Unable to load "+e+" "+r.status+" "+r.statusText);return[2,r]}}))}))}function S(e,t){return r(this,void 0,void 0,(function(){return n(this,(function(r){switch(r.label){case 0:return[4,k(e,t)];case 1:return[4,_(r.sent())];case 2:return[2,r.sent()]}}))}))}function _(e){return r(this,void 0,void 0,(function(){var t;return n(this,(function(r){switch(r.label){case 0:return[4,e.blob()];case 1:return t=r.sent(),[4,new Promise((function(e){var r=new FileReader;r.onloadend=function(){return e(r.result)},r.readAsDataURL(t)}))];case 2:return[2,r.sent()]}}))}))}globalThis.chrome&&globalThis.chrome.runtime&&globalThis.chrome.runtime.getManifest&&globalThis.chrome.runtime.getManifest().manifest_version;var E=function(e){return r(void 0,void 0,void 0,(function(){return n(this,(function(t){return[2,Promise.reject(new Error(["Embedded Dark Reader cannot access a cross-origin resource",e,"Overview your URLs and CORS policies or use","`DarkReader.setFetchMethod(fetch: (url) => Promise<Response>))`.","See if using `DarkReader.setFetchMethod(window.fetch)`","before `DarkReader.enable()` works."].join(" ")))]}))}))},x=E;function C(e){return r(this,void 0,void 0,(function(){return n(this,(function(t){switch(t.label){case 0:return[4,x(e)];case 1:return[2,t.sent()]}}))}))}window.chrome||(window.chrome={}),chrome.runtime||(chrome.runtime={});var V=new Set;function T(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return r(this,void 0,void 0,(function(){var t,r,o,a,i,c,l;return n(this,(function(n){switch(n.label){case 0:if(!e[0]||e[0].type!==s)return[3,8];t=e[0].id,n.label=1;case 1:return n.trys.push([1,7,,8]),r=e[0].data,o=r.url,a=r.responseType,[4,C(o)];case 2:return i=n.sent(),"data-url"!==a?[3,4]:[4,_(i)];case 3:return c=n.sent(),[3,6];case 4:return[4,i.text()];case 5:c=n.sent(),n.label=6;case 6:return V.forEach((function(e){return e({type:u,data:c,error:null,id:t})})),[3,8];case 7:return l=n.sent(),console.error(l),V.forEach((function(e){return e({type:u,data:null,error:l,id:t})})),[3,8];case 8:return[2]}}))}))}function R(e){V.add(e)}if("function"==typeof chrome.runtime.sendMessage){var M=chrome.runtime.sendMessage;chrome.runtime.sendMessage=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];T.apply(void 0,i([],a(e))),M.apply(chrome.runtime,e)}}else chrome.runtime.sendMessage=T;if(chrome.runtime.onMessage||(chrome.runtime.onMessage={}),"function"==typeof chrome.runtime.onMessage.addListener){var A=chrome.runtime.onMessage.addListener;chrome.runtime.onMessage.addListener=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];R.apply(void 0,i([],a(e))),A.apply(chrome.runtime.onMessage,e)}}else chrome.runtime.onMessage.addListener=R;var L="dynamicTheme",P={background:"#181a1b",text:"#e8e6e3"},O={background:"#dcdad7",text:"#181a1b"},j={mode:1,brightness:100,contrast:100,grayscale:0,sepia:0,useFont:!1,fontFamily:m?"Helvetica Neue":v?"Segoe UI":"Open Sans",textStroke:0,engine:L,stylesheet:"",darkSchemeBackgroundColor:P.background,darkSchemeTextColor:P.text,lightSchemeBackgroundColor:O.background,lightSchemeTextColor:O.text,scrollbarColor:m?"":"auto",selectionColor:"auto",styleSystemControls:!0};function D(e,t){var r,n;if(function(e){return null!=e.length}(e))for(var a=0,i=e.length;a<i;a++)t(e[a]);else try{for(var u=o(e),s=u.next();!s.done;s=u.next()){t(s.value)}}catch(e){r={error:e}}finally{try{s&&!s.done&&(n=u.return)&&n.call(u)}finally{if(r)throw r.error}}}function F(e,t){D(t,(function(t){return e.push(t)}))}function q(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t]}function N(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t]}function B(e){var t,r=!1,n=null;return Object.assign((function(){for(var o=[],u=0;u<arguments.length;u++)o[u]=arguments[u];t=o,n?r=!0:(e.apply(void 0,i([],a(t))),n=requestAnimationFrame((function(){n=null,r&&(e.apply(void 0,i([],a(t))),r=!1)})))}),{cancel:function(){cancelAnimationFrame(n),r=!1,n=null}})}function W(e){var t=0;return e.seconds&&(t+=1e3*e.seconds),e.minutes&&(t+=60*e.minutes*1e3),e.hours&&(t+=60*e.hours*60*1e3),e.days&&(t+=24*e.days*60*60*1e3),t}function I(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function U(e,t,r){void 0===r&&(r=Function.prototype);var n=W({seconds:2}),o=W({seconds:10}),a=e.previousSibling,i=e.parentNode;if(!i)throw new Error("Unable to watch for node position: parent element not found");if("prev-sibling"===t&&!a)throw new Error("Unable to watch for node position: there is no previous sibling");var u=0,s=null,c=null,l=B((function(){if(!c){u++;var f=Date.now();if(null==s)s=f;else if(u>=10){if(f-s<o)return N("Node position watcher paused: retry in "+n+"ms",e,a),void(c=setTimeout((function(){s=null,u=0,c=null,l()}),n));s=f,u=1}if("parent"===t&&a&&a.parentNode!==i)return N("Unable to restore node position: sibling parent changed",e,a,i),void h();if("prev-sibling"===t){if(null==a.parentNode)return N("Unable to restore node position: sibling was removed",e,a,i),void h();a.parentNode!==i&&(N("Style was moved to another parent",e,a,i),p(a.parentNode))}N("Restoring node position",e,a,i),i.insertBefore(e,a?a.nextSibling:i.firstChild),d.takeRecords(),r&&r()}})),d=new MutationObserver((function(){("parent"===t&&e.parentNode!==i||"prev-sibling"===t&&e.previousSibling!==a)&&l()})),f=function(){d.observe(i,{childList:!0})},h=function(){clearTimeout(c),d.disconnect(),l.cancel()},p=function(e){i=e,h(),f()};return f(),{run:f,stop:h,skip:function(){d.takeRecords()}}}function z(e,t){if(null!=e)for(var r=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:function(e){return null==e.shadowRoot?NodeFilter.FILTER_SKIP:NodeFilter.FILTER_ACCEPT}}),n=e.shadowRoot?r.currentNode:r.nextNode();null!=n;n=r.nextNode())t(n),z(n.shadowRoot,t)}function $(){return"complete"===document.readyState||"interactive"===document.readyState}var H=new Set;function G(e){H.add(e)}function Q(e){H.delete(e)}function K(){return"complete"===document.readyState}var J=new Set;function X(e){J.add(e)}if(!$()){var Y=function(){$()&&(H.forEach((function(e){return e()})),H.clear(),K()&&(document.removeEventListener("readystatechange",Y),J.forEach((function(e){return e()})),J.clear()))};document.addEventListener("readystatechange",Y)}var Z,ee=new Map,te=new WeakMap;function re(e,t){var r,n,o;if(ee.has(e))r=ee.get(e),n=te.get(r);else{var a=!1,i=!1;(r=new MutationObserver((function(t){if(function(e){if(e.length>1e3)return!0;for(var t=0,r=0;r<e.length;r++)if((t+=e[r].addedNodes.length)>1e3)return!0;return!1}(t))!a||$()?n.forEach((function(t){return(0,t.onHugeMutations)(e)})):i||(G(o=function(){return n.forEach((function(t){return(0,t.onHugeMutations)(e)}))}),i=!0),a=!0;else{var r=function(e){var t=new Set,r=new Set,n=new Set;e.forEach((function(e){D(e.addedNodes,(function(e){e instanceof Element&&e.isConnected&&t.add(e)})),D(e.removedNodes,(function(e){e instanceof Element&&(e.isConnected?n.add(e):r.add(e))}))})),n.forEach((function(e){return t.delete(e)}));var o=[],a=[];return t.forEach((function(e){t.has(e.parentElement)&&o.push(e)})),r.forEach((function(e){r.has(e.parentElement)&&a.push(e)})),o.forEach((function(e){return t.delete(e)})),a.forEach((function(e){return r.delete(e)})),{additions:t,moves:n,deletions:r}}(t);n.forEach((function(e){return(0,e.onMinorMutations)(r)}))}}))).observe(e,{childList:!0,subtree:!0}),ee.set(e,r),n=new Set,te.set(r,n)}return n.add(t),{disconnect:function(){n.delete(t),o&&Q(o),0===n.size&&(r.disconnect(),te.delete(r),ee.delete(e))}}}var ne=new Map;function oe(e){return Z||(Z=document.createElement("a")),Z.href=e,Z.href}function ae(e,t){void 0===t&&(t=null);var r=e+(t?";"+t:"");if(ne.has(r))return ne.get(r);if(t){var n=new URL(e,oe(t));return ne.set(r,n),n}var o=new URL(oe(e));return ne.set(e,o),o}function ie(e,t){if(t.match(/^data\\?\:/))return t;if(/^\/\//.test(t))return""+location.protocol+t;var r=ae(e);return ae(t,r.href).href}function ue(e,t,r){D(e,(function(e){if(e.selectorText)t(e);else if(e.href)try{ue(e.styleSheet.cssRules,t,r)}catch(e){q("Found a non-loaded link."),r&&r()}else if(e.media){var n=Array.from(e.media),o=n.some((function(e){return e.startsWith("screen")||e.startsWith("all")})),a=n.some((function(e){return e.startsWith("print")||e.startsWith("speech")}));!o&&a||ue(e.cssRules,t,r)}else e.conditionText?CSS.supports(e.conditionText)&&ue(e.cssRules,t,r):N("CSSRule type not supported",e)}))}var se=["background","border","border-color","border-bottom","border-left","border-right","border-top","outline","outline-color"],ce=p?se.map((function(e){return[e,new RegExp(e+":\\s*(.*?)\\s*;")]})):null;function le(e,t){D(e,(function(r){var n=e.getPropertyValue(r).trim();n&&t(r,n)}));var r=e.cssText;r.includes("var(")&&(p?ce.forEach((function(e){var n=a(e,2),o=n[0],i=n[1],u=r.match(i);if(u&&u[1]){var s=u[1].trim();t(o,s)}})):se.forEach((function(r){var n=e.getPropertyValue(r);n&&n.includes("var(")&&t(r,n)})))}var de=/url\((('.+?')|(".+?")|([^\)]*?))\)/g,fe=/@import\s*(url\()?(('.+?')|(".+?")|([^\)]*?))\)?;?/g;function he(e){return e.replace(/^url\((.*)\)$/,"$1").trim().replace(/^"(.*)"$/,"$1").replace(/^'(.*)'$/,"$1")}function pe(e){var t=ae(e);return""+t.origin+t.pathname.replace(/\?.*$/,"").replace(/(\/)([^\/]+)$/i,"$1")}var ve=/\/\*[\s\S]*?\*\//g;var me=/@font-face\s*{[^}]*}/g;function ge(e){var t=e.h,r=e.s,n=e.l,o=e.a,i=void 0===o?1:o;if(0===r){var u=a([n,n,n].map((function(e){return Math.round(255*e)})),3),s=u[0],c=u[1];return{r:s,g:u[2],b:c,a:i}}var l=(1-Math.abs(2*n-1))*r,d=l*(1-Math.abs(t/60%2-1)),f=n-l/2,h=a((t<60?[l,d,0]:t<120?[d,l,0]:t<180?[0,l,d]:t<240?[0,d,l]:t<300?[d,0,l]:[l,0,d]).map((function(e){return Math.round(255*(e+f))})),3);return{r:h[0],g:h[1],b:h[2],a:i}}function be(e){var t=e.r,r=e.g,n=e.b,o=e.a,a=void 0===o?1:o,i=t/255,u=r/255,s=n/255,c=Math.max(i,u,s),l=Math.min(i,u,s),d=c-l,f=(c+l)/2;if(0===d)return{h:0,s:0,l:f,a:a};var h=60*(c===i?(u-s)/d%6:c===u?(s-i)/d+2:(i-u)/d+4);return h<0&&(h+=360),{h:h,s:d/(1-Math.abs(2*f-1)),l:f,a:a}}function ye(e,t){void 0===t&&(t=0);var r=e.toFixed(t);if(0===t)return r;var n=r.indexOf(".");if(n>=0){var o=r.match(/0+$/);if(o)return o.index===n+1?r.substring(0,n):r.substring(0,o.index)}return r}function we(e){var t=e.h,r=e.s,n=e.l,o=e.a;return null!=o&&o<1?"hsla("+ye(t)+", "+ye(100*r)+"%, "+ye(100*n)+"%, "+ye(o,2)+")":"hsl("+ye(t)+", "+ye(100*r)+"%, "+ye(100*n)+"%)"}var ke=/^rgba?\([^\(\)]+\)$/,Se=/^hsla?\([^\(\)]+\)$/,_e=/^#[0-9a-f]+$/i;function Ee(e){var t,r,n,o,i,u=e.trim().toLowerCase();if(u.match(ke))return t=a(xe(u,Ce,Ve),4),r=t[0],n=t[1],o=t[2],i=t[3],{r:r,g:n,b:o,a:void 0===i?1:i};if(u.match(Se))return function(e){var t=a(xe(e,Te,Re),4),r=t[0],n=t[1],o=t[2],i=t[3];return ge({h:r,s:n,l:o,a:void 0===i?1:i})}(u);if(u.match(_e))return function(e){var t=e.substring(1);switch(t.length){case 3:case 4:var r=a([0,1,2].map((function(e){return parseInt(""+t[e]+t[e],16)})),3);return{r:r[0],g:r[1],b:r[2],a:3===t.length?1:parseInt(""+t[3]+t[3],16)/255};case 6:case 8:var n=a([0,2,4].map((function(e){return parseInt(t.substring(e,e+2),16)})),3);return{r:n[0],g:n[1],b:n[2],a:6===t.length?1:parseInt(t.substring(6,8),16)/255}}throw new Error("Unable to parse "+e)}(u);if(Me.has(u))return function(e){var t=Me.get(e);return{r:t>>16&255,g:t>>8&255,b:t>>0&255,a:1}}(u);if(Ae.has(u))return function(e){var t=Ae.get(e);return{r:t>>16&255,g:t>>8&255,b:t>>0&255,a:1}}(u);if("transparent"===e)return{r:0,g:0,b:0,a:0};throw new Error("Unable to parse "+e)}function xe(e,t,r){var n=function(e){var t=[],r=0,n=!1,o=e.indexOf("(");e=e.substring(o+1,e.length-1);for(var a=0;a<e.length;a++){var i=e[a];i>="0"&&i<="9"||"."===i||"+"===i||"-"===i?n=!0:!n||" "!==i&&","!==i?n||(r=a+1):(t.push(e.substring(r,a)),n=!1,r=a+1)}return n&&t.push(e.substring(r,e.length)),t}(e),o=Object.entries(r);return n.map((function(e){return e.trim()})).map((function(e,r){var n,i=o.find((function(t){var r=a(t,1)[0];return e.endsWith(r)}));return n=i?parseFloat(e.substring(0,e.length-i[0].length))/i[1]*t[r]:parseFloat(e),t[r]>1?Math.round(n):n}))}var Ce=[255,255,255,1],Ve={"%":100};var Te=[360,1,1,1],Re={"%":100,deg:360,rad:2*Math.PI,turn:1};var Me=new Map(Object.entries({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgrey:11119017,darkgreen:25600,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,grey:8421504,green:32768,greenyellow:11403055,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgrey:13882323,lightgreen:9498256,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074})),Ae=new Map(Object.entries({ActiveBorder:3906044,ActiveCaption:0,AppWorkspace:11184810,Background:6513614,ButtonFace:16777215,ButtonHighlight:15329769,ButtonShadow:10461343,ButtonText:0,CaptionText:0,GrayText:8355711,Highlight:11720703,HighlightText:0,InactiveBorder:16777215,InactiveCaption:16777215,InactiveCaptionText:0,InfoBackground:16514245,InfoText:0,Menu:16185078,MenuText:16777215,Scrollbar:11184810,ThreeDDarkShadow:0,ThreeDFace:12632256,ThreeDHighlight:16777215,ThreeDLightShadow:16777215,ThreeDShadow:0,Window:15527148,WindowFrame:11184810,WindowText:0,"-webkit-focus-ring-color":15046400}).map((function(e){var t=a(e,2),r=t[0],n=t[1];return[r.toLowerCase(),n]})));function Le(e,t,r,n,o){return(e-t)*(o-n)/(r-t)+n}function Pe(e,t,r){return Math.min(r,Math.max(t,e))}function Oe(e,t){for(var r=[],n=0,o=e.length;n<o;n++){r[n]=[];for(var a=0,i=t[0].length;a<i;a++){for(var u=0,s=0,c=e[0].length;s<c;s++)u+=e[n][s]*t[s][a];r[n][a]=u}}return r}function je(e,t,r){void 0===r&&(r=0);for(var n,o=[];n=e.exec(t);)o.push(n[r]);return o}function De(e){var t=Fe.identity();return 0!==e.sepia&&(t=Oe(t,Fe.sepia(e.sepia/100))),0!==e.grayscale&&(t=Oe(t,Fe.grayscale(e.grayscale/100))),100!==e.contrast&&(t=Oe(t,Fe.contrast(e.contrast/100))),100!==e.brightness&&(t=Oe(t,Fe.brightness(e.brightness/100))),1===e.mode&&(t=Oe(t,Fe.invertNHue())),t}var Fe={identity:function(){return[[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]]},invertNHue:function(){return[[.333,-.667,-.667,0,1],[-.667,.333,-.667,0,1],[-.667,-.667,.333,0,1],[0,0,0,1,0],[0,0,0,0,1]]},brightness:function(e){return[[e,0,0,0,0],[0,e,0,0,0],[0,0,e,0,0],[0,0,0,1,0],[0,0,0,0,1]]},contrast:function(e){var t=(1-e)/2;return[[e,0,0,0,t],[0,e,0,0,t],[0,0,e,0,t],[0,0,0,1,0],[0,0,0,0,1]]},sepia:function(e){return[[.393+.607*(1-e),.769-.769*(1-e),.189-.189*(1-e),0,0],[.349-.349*(1-e),.686+.314*(1-e),.168-.168*(1-e),0,0],[.272-.272*(1-e),.534-.534*(1-e),.131+.869*(1-e),0,0],[0,0,0,1,0],[0,0,0,0,1]]},grayscale:function(e){return[[.2126+.7874*(1-e),.7152-.7152*(1-e),.0722-.0722*(1-e),0,0],[.2126-.2126*(1-e),.7152+.2848*(1-e),.0722-.0722*(1-e),0,0],[.2126-.2126*(1-e),.7152-.7152*(1-e),.0722+.9278*(1-e),0,0],[0,0,0,1,0],[0,0,0,0,1]]}};function qe(e){return e[1===e.mode?"darkSchemeBackgroundColor":"lightSchemeBackgroundColor"]}function Ne(e){return e[1===e.mode?"darkSchemeTextColor":"lightSchemeTextColor"]}var Be=new Map,We=new Map;function Ie(e){if(We.has(e))return We.get(e);var t=be(Ee(e));return We.set(e,t),t}var Ue=["r","g","b","a"],ze=["mode","brightness","contrast","grayscale","sepia","darkSchemeBackgroundColor","darkSchemeTextColor","lightSchemeBackgroundColor","lightSchemeTextColor"];function $e(e,t,r,n,o){var i;Be.has(r)?i=Be.get(r):(i=new Map,Be.set(r,i));var u=function(e,t){var r="";return Ue.forEach((function(t){r+=e[t]+";"})),ze.forEach((function(e){r+=t[e]+";"})),r}(e,t);if(i.has(u))return i.get(u);var s=ge(r(be(e),null==n?null:Ie(n),null==o?null:Ie(o))),c=s.r,l=s.g,d=s.b,f=s.a,h=a(function(e,t){var r=a(e,3),n=Oe(t,[[r[0]/255],[r[1]/255],[r[2]/255],[1],[1]]);return[0,1,2].map((function(e){return Pe(Math.round(255*n[e][0]),0,255)}))}([c,l,d],De(t)),3),p=h[0],v=h[1],m=h[2],g=1===f?function(e){var t=e.r,r=e.g,n=e.b,o=e.a;return"#"+(null!=o&&o<1?[t,r,n,Math.round(255*o)]:[t,r,n]).map((function(e){return(e<16?"0":"")+e.toString(16)})).join("")}({r:p,g:v,b:m}):function(e){var t=e.r,r=e.g,n=e.b,o=e.a;return null!=o&&o<1?"rgba("+ye(t)+", "+ye(r)+", "+ye(n)+", "+ye(o,2)+")":"rgb("+ye(t)+", "+ye(r)+", "+ye(n)+")"}({r:p,g:v,b:m,a:f});return i.set(u,g),g}function He(e){return e}function Ge(e,t){var r=qe(t);return $e(e,t,Qe,Ne(t),r)}function Qe(e,t,r){var n,o=e.h,a=e.s,i=e.l,u=e.a,s=i<.5;s?n=i<.2||a<.12:n=a<.24||i>.8&&(o>200&&o<280);var c=o,l=i;return n&&(s?(c=t.h,l=t.s):(c=r.h,l=r.s)),{h:c,s:l,l:Le(i,0,1,t.l,r.l),a:u}}function Ke(e,t){var r=e.h,n=e.s,o=e.l,a=e.a,i=n<.12||o>.8&&(r>200&&r<280);if(o<.5){var u=Le(o,0,.5,0,.4);return i?{h:t.h,s:t.s,l:u,a:a}:{h:r,s:n,l:u,a:a}}var s=Le(o,.5,1,.4,t.l);if(i)return{h:t.h,s:t.s,l:s,a:a};var c=r;r>60&&r<180&&(c=r>120?Le(r,120,180,135,180):Le(r,60,120,60,105));return{h:c,s:n,l:s,a:a}}function Je(e,r){if(0===r.mode)return Ge(e,r);var n=qe(r);return $e(e,t(t({},r),{mode:0}),Ke,n)}var Xe,Ye=.55;function Ze(e){return Le(e,205,245,205,220)}function et(e,t){var r=e.h,n=e.s,o=e.l,a=e.a,i=o<.2||n<.24,u=!i&&r>205&&r<245;if(o>.5){var s=Le(o,.5,1,Ye,t.l);if(i)return{h:t.h,s:t.s,l:s,a:a};var c=r;return u&&(c=Ze(r)),{h:c,s:n,l:s,a:a}}if(i)return{h:t.h,s:t.s,l:Le(o,0,.5,t.l,Ye),a:a};var l,d=r;return u?(d=Ze(r),l=Le(o,0,.5,t.l,Math.min(1,.6000000000000001))):l=Le(o,0,.5,t.l,Ye),{h:d,s:n,l:l,a:a}}function tt(e,r){if(0===r.mode)return Ge(e,r);var n=Ne(r);return $e(e,t(t({},r),{mode:0}),et,n)}function rt(e,t,r){var n=e.h,o=e.s,a=e.l,i=e.a,u=n,s=o;return(a<.2||o<.24)&&(a<.5?(u=t.h,s=t.s):(u=r.h,s=r.s)),{h:u,s:s,l:Le(a,0,1,.5,.2),a:i}}function nt(e,r){if(0===r.mode)return Ge(e,r);var n=Ne(r),o=qe(r);return $e(e,t(t({},r),{mode:0}),rt,n,o)}function ot(e,t){return Je(e,t)}function at(e){var t=[];return e.mode===Xe.dark&&t.push("invert(100%) hue-rotate(180deg)"),100!==e.brightness&&t.push("brightness("+e.brightness+"%)"),100!==e.contrast&&t.push("contrast("+e.contrast+"%)"),0!==e.grayscale&&t.push("grayscale("+e.grayscale+"%)"),0!==e.sepia&&t.push("sepia("+e.sepia+"%)"),0===t.length?null:t.join(" ")}!function(e){e[e.light=0]="light",e[e.dark=1]="dark"}(Xe||(Xe={}));var it=0,ut=new Map,st=new Map;function ct(e){return r(this,void 0,void 0,(function(){return n(this,(function(t){return[2,new Promise((function(t,r){var n=++it;ut.set(n,t),st.set(n,r),chrome.runtime.sendMessage({type:s,data:e,id:n})}))]}))}))}chrome.runtime.onMessage.addListener((function(e){var t=e.type,r=e.data,n=e.error,o=e.id;if(t===u){var a=ut.get(o),i=st.get(o);ut.delete(o),st.delete(o),n?i&&i(n):a&&a(r)}}));var lt=new(function(){function e(){this.queue=[],this.timerId=null,this.frameDuration=1e3/60}return e.prototype.addToQueue=function(e){this.queue.push(e),this.startQueue()},e.prototype.stopQueue=function(){null!==this.timerId&&(cancelAnimationFrame(this.timerId),this.timerId=null),this.queue=[]},e.prototype.startQueue=function(){var e=this;this.timerId||(this.timerId=requestAnimationFrame((function(){e.timerId=null;for(var t,r=Date.now();t=e.queue.shift();)if(t(),Date.now()-r>=e.frameDuration){e.startQueue();break}})))},e}());function dt(e){return r(this,void 0,void 0,(function(){var o=this;return n(this,(function(a){return[2,new Promise((function(a,i){return r(o,void 0,void 0,(function(){var r,o,u,s;return n(this,(function(n){switch(n.label){case 0:return e.startsWith("data:")?(r=e,[3,4]):[3,1];case 1:return n.trys.push([1,3,,4]),[4,ft(e)];case 2:return r=n.sent(),[3,4];case 3:return o=n.sent(),i(o),[3,4];case 4:return n.trys.push([4,6,,7]),[4,ht(r)];case 5:return u=n.sent(),lt.addToQueue((function(){a(t({src:e,dataURL:r,width:u.naturalWidth,height:u.naturalHeight},function(e){pt||(t=mt,r=mt,(pt=document.createElement("canvas")).width=t,pt.height=r,(vt=pt.getContext("2d")).imageSmoothingEnabled=!1);var t,r;var n=e.naturalWidth,o=e.naturalHeight;if(0===o||0===n)return N("logWarn(Image is empty "+e.currentSrc+")"),null;if(n*o*4>gt)return q("Skipped large image analyzing(Larger than 5mb in memory)"),{isDark:!1,isLight:!1,isTransparent:!1,isLarge:!1,isTooLarge:!0};var a=n*o,i=Math.min(1,Math.sqrt(mt/a)),u=Math.ceil(n*i),s=Math.ceil(o*i);vt.clearRect(0,0,u,s),vt.drawImage(e,0,0,n,o,0,0,u,s);var c,l,d,f,h,p,v,m=vt.getImageData(0,0,u,s).data,g=.05,b=.4,y=.7,w=0,k=0,S=0;for(d=0;d<s;d++)for(l=0;l<u;l++)f=m[(c=4*(d*u+l))+0]/255,h=m[c+1]/255,p=m[c+2]/255,m[c+3]/255<g?w++:((v=.2126*f+.7152*h+.0722*p)<b&&k++,v>y&&S++);var _=u*s,E=_-w;return{isDark:k/E>=.7,isLight:S/E>=.7,isTransparent:w/_>=.1,isLarge:a>=48e4,isTooLarge:!1}}(u)))})),[3,7];case 6:return s=n.sent(),i(s),[3,7];case 7:return[2]}}))}))}))]}))}))}function ft(e){return r(this,void 0,void 0,(function(){return n(this,(function(t){switch(t.label){case 0:return new URL(e).origin!==location.origin?[3,2]:[4,S(e)];case 1:return[2,t.sent()];case 2:return[4,ct({url:e,responseType:"data-url"})];case 3:return[2,t.sent()]}}))}))}function ht(e){return r(this,void 0,void 0,(function(){return n(this,(function(t){return[2,new Promise((function(t,r){var n=new Image;n.onload=function(){return t(n)},n.onerror=function(){return r("Unable to load image "+e)},n.src=e}))]}))}))}var pt,vt,mt=1024;var gt=5242880;function bt(e,t){var r=e.dataURL,n=e.width,o=e.height,a=['<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="'+n+'" height="'+o+'">',"<defs>",'<filter id="darkreader-image-filter">','<feColorMatrix type="matrix" values="'+De(t).slice(0,4).map((function(e){return e.map((function(e){return e.toFixed(3)})).join(" ")})).join(" ")+'" />',"</filter>","</defs>",'<image width="'+n+'" height="'+o+'" filter="url(#darkreader-image-filter)" xlink:href="'+r+'" />',"</svg>"].join("");return"data:image/svg+xml;base64,"+btoa(a)}function yt(){lt&&lt.stopQueue(),pt=null,vt=null}function wt(e,t){return Boolean(e&&e.getPropertyPriority(t))}function kt(e,t,r,n,o,a){if(e.startsWith("--")){if(i=function(e,t,r,n,o,a){return e.getModifierForVariable({varName:t,sourceValue:r,rule:n,ignoredImgSelectors:o,isCancelled:a})}(n,e,t,r,o,a))return{property:e,value:i,important:wt(r.style,e),sourceValue:t}}else if(t.includes("var(")){if(i=function(e,t,r){return e.getModifierForVarDependant(t,r)}(n,e,t))return{property:e,value:i,important:wt(r.style,e),sourceValue:t}}else if(e.includes("color")&&"-webkit-print-color-adjust"!==e||"fill"===e||"stroke"===e||"stop-color"===e){if(i=function(e,t){if(xt.has(t.toLowerCase()))return t;try{var r=Vt(t);return e.includes("background")?function(e){return Je(r,e)}:e.includes("border")||e.includes("outline")?function(e){return nt(r,e)}:function(e){return tt(r,e)}}catch(e){return N("Color parse error",e),null}}(e,t))return{property:e,value:i,important:wt(r.style,e),sourceValue:t}}else if("background-image"===e||"list-style-image"===e){if(i=Lt(t,r,o,a))return{property:e,value:i,important:wt(r.style,e),sourceValue:t}}else if(e.includes("shadow")){var i;if(i=Pt(t))return{property:e,value:i,important:wt(r.style,e),sourceValue:t}}return null}function St(e,r,n){var o=[];return r||(o.push("html {"),o.push("    background-color: "+Je({r:255,g:255,b:255},e)+" !important;"),o.push("}")),o.push((r?"":"html, body, ")+(n?"input, textarea, select, button":"")+" {"),o.push("    background-color: "+Je({r:255,g:255,b:255},e)+";"),o.push("}"),o.push("html, body, "+(n?"input, textarea, select, button":"")+" {"),o.push("    border-color: "+nt({r:76,g:76,b:76},e)+";"),o.push("    color: "+tt({r:0,g:0,b:0},e)+";"),o.push("}"),o.push("a {"),o.push("    color: "+tt({r:0,g:64,b:255},e)+";"),o.push("}"),o.push("table {"),o.push("    border-color: "+nt({r:128,g:128,b:128},e)+";"),o.push("}"),o.push("::placeholder {"),o.push("    color: "+tt({r:169,g:169,b:169},e)+";"),o.push("}"),o.push("input:-webkit-autofill,"),o.push("textarea:-webkit-autofill,"),o.push("select:-webkit-autofill {"),o.push("    background-color: "+Je({r:250,g:255,b:189},e)+" !important;"),o.push("    color: "+tt({r:0,g:0,b:0},e)+" !important;"),o.push("}"),e.scrollbarColor&&o.push(function(e){var r,n,o,a,i,u,s=[];if("auto"===e.scrollbarColor)r=Je({r:241,g:241,b:241},e),n=tt({r:96,g:96,b:96},e),o=Je({r:176,g:176,b:176},e),a=Je({r:144,g:144,b:144},e),i=Je({r:96,g:96,b:96},e),u=Je({r:255,g:255,b:255},e);else{var c=be(Ee(e.scrollbarColor)),l=c.l>.5,d=function(e){return t(t({},c),{l:Pe(c.l+e,0,1)})},f=function(e){return t(t({},c),{l:Pe(c.l-e,0,1)})};r=we(f(.4)),n=we(l?f(.4):d(.4)),o=we(c),a=we(d(.1)),i=we(d(.2))}s.push("::-webkit-scrollbar {"),s.push("    background-color: "+r+";"),s.push("    color: "+n+";"),s.push("}"),s.push("::-webkit-scrollbar-thumb {"),s.push("    background-color: "+o+";"),s.push("}"),s.push("::-webkit-scrollbar-thumb:hover {"),s.push("    background-color: "+a+";"),s.push("}"),s.push("::-webkit-scrollbar-thumb:active {"),s.push("    background-color: "+i+";"),s.push("}"),s.push("::-webkit-scrollbar-corner {"),s.push("    background-color: "+u+";"),s.push("}"),h&&(s.push("* {"),s.push("    scrollbar-color: "+o+" "+r+";"),s.push("}"));return s.join("\n")}(e)),e.selectionColor&&o.push(function(e){var t=[],r=_t(e),n=r.backgroundColorSelection,o=r.foregroundColorSelection;return["::selection","::-moz-selection"].forEach((function(e){t.push(e+" {"),t.push("    background-color: "+n+" !important;"),t.push("    color: "+o+" !important;"),t.push("}")})),t.join("\n")}(e)),o.join("\n")}function _t(e){var r,n;if("auto"===e.selectionColor)r=Je({r:0,g:96,b:212},t(t({},e),{grayscale:0})),n=tt({r:255,g:255,b:255},t(t({},e),{grayscale:0}));else{var o=be(Ee(e.selectionColor));r=e.selectionColor,n=o.l<.5?"#FFF":"#000"}return{backgroundColorSelection:r,foregroundColorSelection:n}}function Et(e,t){var r=t.strict,n=[];return n.push("html, body, "+(r?"body :not(iframe)":"body > :not(iframe)")+" {"),n.push("    background-color: "+Je({r:255,g:255,b:255},e)+" !important;"),n.push("    border-color: "+nt({r:64,g:64,b:64},e)+" !important;"),n.push("    color: "+tt({r:0,g:0,b:0},e)+" !important;"),n.push("}"),n.join("\n")}var xt=new Set(["inherit","transparent","initial","currentcolor","none","unset"]),Ct=new Map;function Vt(e){if(e=e.trim(),Ct.has(e))return Ct.get(e);var t=Ee(e);return Ct.set(e,t),t}function Tt(e){try{return Vt(e)}catch(e){return null}}var Rt=/[\-a-z]+gradient\(([^\(\)]*(\(([^\(\)]*(\(.*?\)))*[^\(\)]*\))){0,15}[^\(\)]*\)/g,Mt=new Map,At=new Map;function Lt(e,o,a,i){var u=this;try{var s=je(Rt,e),c=je(de,e);if(0===c.length&&0===s.length)return e;var l=function(t){var r=0;return t.map((function(t){var n=e.indexOf(t,r);return r=n+t.length,{match:t,index:n}}))},d=l(c).map((function(e){return t({type:"url"},e)})).concat(l(s).map((function(e){return t({type:"gradient"},e)}))).sort((function(e,t){return e.index-t.index})),f=function(e,r){var n,o=e.isDark,a=e.isLight,i=e.isTransparent,u=e.isLarge,s=e.isTooLarge,c=e.width;if(s)n='url("'+e.src+'")';else if(o&&i&&1===r.mode&&!u&&c>2){q("Inverting dark image "+e.src),n='url("'+bt(e,t(t({},r),{sepia:Pe(r.sepia+10,0,100)}))+'")'}else if(a&&!i&&1===r.mode){if(u)n="none";else q("Dimming light image "+e.src),n='url("'+bt(e,r)+'")'}else if(0===r.mode&&a&&!u){q("Applying filter to image "+e.src),n='url("'+bt(e,t(t({},r),{brightness:Pe(r.brightness-10,5,200),sepia:Pe(r.sepia+10,0,100)}))+'")'}else n=null;return n},h=[],p=0;return d.forEach((function(t,s){var c=t.match,l=t.type,v=t.index,m=p,g=v+c.length;p=g,h.push((function(){return e.substring(m,v)})),h.push("url"===l?function(e){var t;if(function(e,t){if(!e||0===t.length)return!1;if(t.some((function(e){return"*"===e})))return!0;for(var r=e.split(/,\s*/g),n=function(e){var n=t[e];if(r.some((function(e){return e===n})))return{value:!0}},o=0;o<t.length;o++){var a=n(o);if("object"==typeof a)return a.value}return!1}(o.selectorText,a))return null;var s=he(e),c=o.parentStyleSheet,l=c&&c.href?pe(c.href):(null===(t=c.ownerNode)||void 0===t?void 0:t.baseURI)||location.origin,d='url("'+(s=ie(l,s))+'")';return function(e){return r(u,void 0,void 0,(function(){var t,r;return n(this,(function(n){switch(n.label){case 0:return Mt.has(s)?(t=Mt.get(s),[3,7]):[3,1];case 1:return n.trys.push([1,6,,7]),At.has(s)?(r=At.get(s),[4,new Promise((function(e){return r.push(e)}))]):[3,3];case 2:return(t=n.sent())?[3,5]:[2,null];case 3:return At.set(s,[]),[4,dt(s)];case 4:t=n.sent(),Mt.set(s,t),At.get(s).forEach((function(e){return e(t)})),At.delete(s),n.label=5;case 5:return i()?[2,null]:[3,7];case 6:return N(n.sent()),At.has(s)&&(At.get(s).forEach((function(e){return e(null)})),At.delete(s)),[2,d];case 7:return[2,f(t,e)||d]}}))}))}}(c):function(e){var t=e.match(/^(.*-gradient)\((.*)\)$/),r=t[1],n=t[2],o=/^(from|color-stop|to)\(([^\(\)]*?,\s*)?(.*?)\)$/,a=je(/([^\(\),]+(\([^\(\)]*(\([^\(\)]*\)*[^\(\)]*)?\))?[^\(\),]*),?/g,n,1).map((function(e){var t=Tt(e=e.trim());if(t)return function(e){return ot(t,e)};var r=e.lastIndexOf(" ");if(t=Tt(e.substring(0,r)))return function(n){return ot(t,n)+" "+e.substring(r+1)};var n=e.match(o);return n&&(t=Tt(n[3]))?function(e){return n[1]+"("+(n[2]?n[2]+", ":"")+ot(t,e)+")"}:function(){return e}}));return function(e){return r+"("+a.map((function(t){return t(e)})).join(", ")+")"}}(c)),s===d.length-1&&h.push((function(){return e.substring(g)}))})),function(e){var t=h.filter(Boolean).map((function(t){return t(e)}));return t.some((function(e){return e instanceof Promise}))?Promise.all(t).then((function(e){return e.join("")})):t.join("")}}catch(t){return N("Unable to parse gradient "+e,t),null}}function Pt(e){try{var t=0,r=je(/(^|\s)(?!calc)([a-z]+\(.+?\)|#[0-9a-f]+|[a-z]+)(.*?(inset|outset)?($|,))/gi,e,2),n=r.map((function(n,o){var a=t,i=e.indexOf(n,t),u=i+n.length;t=u;var s=Tt(n);return s?function(t){return""+e.substring(a,i)+function(e,t){return Je(e,t)}(s,t)+(o===r.length-1?e.substring(u):"")}:function(){return e.substring(a,u)}}));return function(e){return n.map((function(t){return t(e)})).join("")}}catch(t){return N("Unable to parse shadow "+e,t),null}}function Ot(){Ct.clear(),Be.clear(),We.clear(),Mt.clear(),yt(),At.clear()}var jt=new(function(){function e(){this.varTypes=new Map,this.rulesQueue=[],this.definedVars=new Set,this.varRefs=new Map,this.unknownColorVars=new Set,this.unknownBgVars=new Set,this.undefinedVars=new Set,this.initialVarTypes=new Map,this.changedTypeVars=new Set,this.typeChangeSubscriptions=new Map,this.unstableVarValues=new Map}return e.prototype.clear=function(){this.varTypes.clear(),this.rulesQueue.splice(0),this.definedVars.clear(),this.varRefs.clear(),this.unknownColorVars.clear(),this.unknownBgVars.clear(),this.undefinedVars.clear(),this.initialVarTypes.clear(),this.changedTypeVars.clear(),this.typeChangeSubscriptions.clear(),this.unstableVarValues.clear()},e.prototype.isVarType=function(e,t){return this.varTypes.has(e)&&(this.varTypes.get(e)&t)>0},e.prototype.addRulesForMatching=function(e){this.rulesQueue.push(e)},e.prototype.matchVariablesAndDependants=function(){var e=this;this.changedTypeVars.clear(),this.initialVarTypes=new Map(this.varTypes),this.collectRootVariables(),this.collectVariablesAndVarDep(this.rulesQueue),this.rulesQueue.splice(0),this.collectRootVarDependants(),this.varRefs.forEach((function(t,r){t.forEach((function(t){e.varTypes.has(r)&&e.resolveVariableType(t,e.varTypes.get(r))}))})),this.unknownColorVars.forEach((function(t){e.unknownBgVars.has(t)?(e.unknownColorVars.delete(t),e.unknownBgVars.delete(t),e.resolveVariableType(t,1)):e.isVarType(t,7)?e.unknownColorVars.delete(t):e.undefinedVars.add(t)})),this.unknownBgVars.forEach((function(t){null!=e.findVarRef(t,(function(t){return e.unknownColorVars.has(t)||e.isVarType(t,6)}))?e.itarateVarRefs(t,(function(t){e.resolveVariableType(t,1)})):e.isVarType(t,9)?e.unknownBgVars.delete(t):e.undefinedVars.add(t)})),this.changedTypeVars.forEach((function(t){e.typeChangeSubscriptions.has(t)&&e.typeChangeSubscriptions.get(t).forEach((function(e){e()}))})),this.changedTypeVars.clear()},e.prototype.getModifierForVariable=function(e){var t=this;return function(r){var n=e.varName,o=e.sourceValue,a=e.rule,i=e.ignoredImgSelectors,u=e.isCancelled,s=function(){var e=[],s=function(a,i,u){if(t.isVarType(n,a)){var s,c=i(n);if($t(o))if(Ht(o)){var l=Jt(o,t.unstableVarValues);l||(l=1===a?"#ffffff":"#000000"),s=u(l,r)}else s=Nt(o,(function(e){return i(e)}),(function(e){return u(e,r)}));else s=u(o,r);e.push({property:c,value:s})}};if(s(1,Bt,Gt),s(2,Wt,Qt),s(4,It,Kt),t.isVarType(n,8)){var c=Ut(n),l=o;$t(o)&&(l=Nt(o,(function(e){return Bt(e)}),(function(e){return Gt(e,r)})));var d=Lt(l,a,i,u);l="function"==typeof d?d(r):d,e.push({property:c,value:l})}return e},c=new Set;return{declarations:s(),onTypeChange:{addListener:function(e){var r=function(){var t=s();e(t)};c.add(r),t.subscribeForVarTypeChange(n,r)},removeListeners:function(){c.forEach((function(e){t.unsubscribeFromVariableTypeChanges(n,e)}))}}}}},e.prototype.getModifierForVarDependant=function(e,t){var r=this;if(t.match(/^\s*(rgb|hsl)a?\(/)){var n=e.startsWith("background"),o="color"===e||"caret-color"===e;return function(e){var a=Jt(t,r.unstableVarValues);return a||(a=n?"#ffffff":"#000000"),(n?Gt:o?Qt:Kt)(a,e)}}if("background-color"===e)return function(e){return Nt(t,(function(e){return Bt(e)}),(function(t){return Gt(t,e)}))};if("color"===e||"caret-color"===e)return function(e){return Nt(t,(function(e){return Wt(e)}),(function(t){return Qt(t,e)}))};if("background"===e||"background-image"===e||"box-shadow"===e)return function(n){var o=new Set,a=function(){var a=Nt(t,(function(e){return r.isVarType(e,1)?Bt(e):r.isVarType(e,8)?Ut(e):(o.add(e),e)}),(function(e){return Gt(e,n)}));return"box-shadow"===e&&Pt(a)(n)||a},i=a();return o.size>0?new Promise((function(e){var t=o.values().next().value,n=function(){r.unsubscribeFromVariableTypeChanges(t,n);var o=a();e(o)};r.subscribeForVarTypeChange(t,n)})):i};if(e.startsWith("border")||e.startsWith("outline")){if(t.endsWith(")")){var a=t.match(/((rgb|hsl)a?)\(/);if(a){var i=a.index;return function(e){return Jt(t,r.unstableVarValues)?""+t.substring(0,i)+Kt(Jt(t.substring(i,t.length),r.unstableVarValues),e):t}}}return function(e){return Nt(t,(function(e){return It(e)}),(function(t){return Qt(t,e)}))}}return null},e.prototype.subscribeForVarTypeChange=function(e,t){this.typeChangeSubscriptions.has(e)||this.typeChangeSubscriptions.set(e,new Set);var r=this.typeChangeSubscriptions.get(e);r.has(t)||r.add(t)},e.prototype.unsubscribeFromVariableTypeChanges=function(e,t){this.typeChangeSubscriptions.has(e)&&this.typeChangeSubscriptions.get(e).delete(t)},e.prototype.collectVariablesAndVarDep=function(e){var t=this;e.forEach((function(e){ue(e,(function(e){e.style&&le(e.style,(function(e,r){zt(e)&&t.inspectVariable(e,r),$t(r)&&t.inspectVarDependant(e,r)}))}))}))},e.prototype.collectRootVariables=function(){var e=this;le(document.documentElement.style,(function(t,r){zt(t)&&e.inspectVariable(t,r)}))},e.prototype.inspectVariable=function(e,t){(this.unstableVarValues.set(e,t),$t(t)&&Ht(t)&&(this.unknownColorVars.add(e),this.definedVars.add(e)),this.definedVars.has(e))||(this.definedVars.add(e),Tt(t)?this.unknownColorVars.add(e):(t.includes("url(")||t.includes("linear-gradient(")||t.includes("radial-gradient("))&&this.resolveVariableType(e,8))},e.prototype.resolveVariableType=function(e,t){var r=this.initialVarTypes.get(e)||0,n=(this.varTypes.get(e)||0)|t;this.varTypes.set(e,n),(n!==r||this.undefinedVars.has(e))&&(this.changedTypeVars.add(e),this.undefinedVars.delete(e)),this.unknownColorVars.delete(e),this.unknownBgVars.delete(e)},e.prototype.collectRootVarDependants=function(){var e=this;le(document.documentElement.style,(function(t,r){$t(r)&&e.inspectVarDependant(t,r)}))},e.prototype.inspectVarDependant=function(e,t){var r=this;zt(e)?this.iterateVarDeps(t,(function(t){r.varRefs.has(e)||r.varRefs.set(e,new Set),r.varRefs.get(e).add(t)})):"background-color"===e||"box-shadow"===e?this.iterateVarDeps(t,(function(e){return r.resolveVariableType(e,1)})):"color"===e||"caret-color"===e?this.iterateVarDeps(t,(function(e){return r.resolveVariableType(e,2)})):e.startsWith("border")||e.startsWith("outline")?this.iterateVarDeps(t,(function(e){return r.resolveVariableType(e,4)})):"background"!==e&&"background-image"!==e||this.iterateVarDeps(t,(function(e){if(!r.isVarType(e,9)){var t=null!=r.findVarRef(e,(function(e){return r.unknownColorVars.has(e)||r.isVarType(e,6)}));r.itarateVarRefs(e,(function(e){t?r.resolveVariableType(e,1):r.unknownBgVars.add(e)}))}}))},e.prototype.iterateVarDeps=function(e,t){var r=new Set;!function(e,t){Nt(e,(function(e){return t(e),e}))}(e,(function(e){return r.add(e)})),r.forEach((function(e){return t(e)}))},e.prototype.findVarRef=function(e,t,r){var n,a;if(void 0===r&&(r=new Set),r.has(e))return null;if(r.add(e),t(e))return e;var i=this.varRefs.get(e);if(!i||0===i.size)return null;try{for(var u=o(i),s=u.next();!s.done;s=u.next()){var c=s.value,l=this.findVarRef(c,t,r);if(l)return l}}catch(e){n={error:e}}finally{try{s&&!s.done&&(a=u.return)&&a.call(u)}finally{if(n)throw n.error}}return null},e.prototype.itarateVarRefs=function(e,t){this.findVarRef(e,(function(e){return t(e),!1}))},e.prototype.setOnRootVariableChange=function(e){this.onRootVariableDefined=e},e.prototype.putRootVars=function(e,t){var r,n,i=this,u=e.sheet;u.cssRules.length>0&&u.deleteRule(0);var s=new Map;le(document.documentElement.style,(function(e,r){zt(e)&&(i.isVarType(e,1)&&s.set(Bt(e),Gt(r,t)),i.isVarType(e,2)&&s.set(Wt(e),Qt(r,t)),i.isVarType(e,4)&&s.set(It(e),Kt(r,t)),i.subscribeForVarTypeChange(e,i.onRootVariableDefined))}));var c=[];c.push(":root {");try{for(var l=o(s),d=l.next();!d.done;d=l.next()){var f=a(d.value,2),h=f[0],p=f[1];c.push("    "+h+": "+p+";")}}catch(e){r={error:e}}finally{try{d&&!d.done&&(n=l.return)&&n.call(l)}finally{if(r)throw r.error}}c.push("}");var v=c.join("\n");u.insertRule(v)},e}());function Dt(e,t){void 0===t&&(t=0);var r=e.indexOf("var(",t);if(r>=0){var n=function(e,t){void 0===t&&(t=0);for(var r=e.length,n=0,o=-1,a=t;a<r;a++)if(0===n){if((i=e.indexOf("(",a))<0)break;o=i,n++,a=i}else{var i,u=e.indexOf(")",a);if(u<0)break;if((i=e.indexOf("(",a))<0||u<i){if(0==--n)return{start:o,end:u+1};a=u}else n++,a=i}return null}(e,r+3);return n?{start:r,end:n.end}:null}}function Ft(e,t){var r=function(e){for(var t,r=[],n=0;t=Dt(e,n);){var o=t.start,a=t.end;r.push({start:o,end:a,value:e.substring(o,a)}),n=t.end+1}return r}(e),n=r.length;if(0===n)return e;var o=e.length,a=r.map((function(e){return t(e.value)})),i=[];i.push(e.substring(0,r[0].start));for(var u=0;u<n;u++){i.push(a[u]);var s=r[u].end,c=u<n-1?r[u+1].start:o;i.push(e.substring(s,c))}return i.join("")}function qt(e){var t,r,n=e.indexOf(",");return n>=0?(t=e.substring(4,n).trim(),r=e.substring(n+1,e.length-1).trim()):(t=e.substring(4,e.length-1).trim(),r=""),{name:t,fallback:r}}function Nt(e,t,r){return Ft(e,(function(e){var n=qt(e),o=n.name,a=n.fallback,i=t(o);return a?"var("+i+", "+($t(a)?Nt(a,t,r):r?r(a):a)+")":"var("+i+")"}))}function Bt(e){return"--darkreader-bg"+e}function Wt(e){return"--darkreader-text"+e}function It(e){return"--darkreader-border"+e}function Ut(e){return"--darkreader-bgimg"+e}function zt(e){return e.startsWith("--")}function $t(e){return e.includes("var(")}function Ht(e){return e.match(/^\s*(rgb|hsl)a?\(/)}function Gt(e,t){var r=Tt(e);return r?Je(r,t):e}function Qt(e,t){var r=Tt(e);return r?tt(r,t):e}function Kt(e,t){var r=Tt(e);return r?nt(r,t):e}function Jt(e,t,r){void 0===r&&(r=new Set);var n=!1,o=Ft(e,(function(e){var o=qt(e),a=o.name,i=o.fallback;if(r.has(a))return n=!0,null;r.add(a);var u=t.get(a)||i,s=null;return u&&(s=$t(u)?Jt(u,t,r):u),s||(n=!0,null)}));return n?null:o}var Xt={"background-color":{customProp:"--darkreader-inline-bgcolor",cssProp:"background-color",dataAttr:"data-darkreader-inline-bgcolor"},"background-image":{customProp:"--darkreader-inline-bgimage",cssProp:"background-image",dataAttr:"data-darkreader-inline-bgimage"},"border-color":{customProp:"--darkreader-inline-border",cssProp:"border-color",dataAttr:"data-darkreader-inline-border"},"border-bottom-color":{customProp:"--darkreader-inline-border-bottom",cssProp:"border-bottom-color",dataAttr:"data-darkreader-inline-border-bottom"},"border-left-color":{customProp:"--darkreader-inline-border-left",cssProp:"border-left-color",dataAttr:"data-darkreader-inline-border-left"},"border-right-color":{customProp:"--darkreader-inline-border-right",cssProp:"border-right-color",dataAttr:"data-darkreader-inline-border-right"},"border-top-color":{customProp:"--darkreader-inline-border-top",cssProp:"border-top-color",dataAttr:"data-darkreader-inline-border-top"},"box-shadow":{customProp:"--darkreader-inline-boxshadow",cssProp:"box-shadow",dataAttr:"data-darkreader-inline-boxshadow"},color:{customProp:"--darkreader-inline-color",cssProp:"color",dataAttr:"data-darkreader-inline-color"},fill:{customProp:"--darkreader-inline-fill",cssProp:"fill",dataAttr:"data-darkreader-inline-fill"},stroke:{customProp:"--darkreader-inline-stroke",cssProp:"stroke",dataAttr:"data-darkreader-inline-stroke"},"outline-color":{customProp:"--darkreader-inline-outline",cssProp:"outline-color",dataAttr:"data-darkreader-inline-outline"},"stop-color":{customProp:"--darkreader-inline-stopcolor",cssProp:"stop-color",dataAttr:"data-darkreader-inline-stopcolor"}},Yt=Object.values(Xt),Zt={};Yt.forEach((function(e){var t=e.cssProp,r=e.customProp;return Zt[r]=t}));var er=["style","fill","stop-color","stroke","bgcolor","color"],tr=er.map((function(e){return"["+e+"]"})).join(", ");function rr(){return Yt.map((function(e){var t=e.dataAttr,r=e.customProp;return["["+t+"] {","  "+e.cssProp+": var("+r+") !important;","}"].join("\n")})).join("\n")}var nr=new Map,or=new Map;function ar(e,t,r){nr.has(e)&&(nr.get(e).disconnect(),or.get(e).disconnect());var n=new WeakSet;function o(e){(function(e){var t=[];return e instanceof Element&&e.matches(tr)&&t.push(e),(e instanceof Element||b&&e instanceof ShadowRoot||e instanceof Document)&&F(t,e.querySelectorAll(tr)),t})(e).forEach((function(e){n.has(e)||(n.add(e),t(e))})),z(e,(function(o){n.has(e)||(n.add(e),r(o.shadowRoot),ar(o.shadowRoot,t,r))}))}var u=re(e,{onMinorMutations:function(e){e.additions.forEach((function(e){return o(e)}))},onHugeMutations:function(){o(e)}});nr.set(e,u);var s=0,c=null,l=W({seconds:10}),d=W({seconds:2}),f=[],h=null,p=B((function(e){e.forEach((function(e){er.includes(e.attributeName)&&t(e.target)}))})),v=new MutationObserver((function(e){if(h)f.push.apply(f,i([],a(e)));else{s++;var t=Date.now();if(null==c)c=t;else if(s>=50){if(t-c<l)return h=setTimeout((function(){c=null,s=0,h=null;var e=f;f=[],p(e)}),d),void f.push.apply(f,i([],a(e)));c=t,s=1}p(e)}}));v.observe(e,{attributes:!0,attributeFilter:er.concat(Yt.map((function(e){return e.dataAttr}))),subtree:!0}),or.set(e,v)}var ir=new WeakMap,ur=["brightness","contrast","grayscale","sepia","mode"];function sr(e,t){return er.map((function(t){return t+'="'+e.getAttribute(t)+'"'})).concat(ur.map((function(e){return e+'="'+t[e]+'"'}))).join(" ")}function cr(e,t,r,n){if(sr(e,t)!==ir.get(e)){var o=new Set(Object.keys(Xt));if(r.length>0&&function(e,t){for(var r=0,n=t.length;r<n;r++){var o=t[r];if(e.matches(o))return!0}return!1}(e,r))o.forEach((function(t){e.removeAttribute(Xt[t].dataAttr)}));else{if(e.hasAttribute("bgcolor"))((u=e.getAttribute("bgcolor")).match(/^[0-9a-f]{3}$/i)||u.match(/^[0-9a-f]{6}$/i))&&(u="#"+u),s("background-color","background-color",u);if(e.hasAttribute("color")&&"mask-icon"!==e.rel)((u=e.getAttribute("color")).match(/^[0-9a-f]{3}$/i)||u.match(/^[0-9a-f]{6}$/i))&&(u="#"+u),s("color","color",u);if(e instanceof SVGElement){if(e.hasAttribute("fill")){var a=e.getAttribute("fill");if("none"!==a)if(e instanceof SVGTextElement)s("fill","color",a);else{var i=function(){var t=e.getBoundingClientRect(),r=t.width,n=t.height;s("fill",r>32||n>32?"background-color":"color",a)};K()?i():X(i)}}e.hasAttribute("stop-color")&&s("stop-color","background-color",e.getAttribute("stop-color"))}if(e.hasAttribute("stroke")){var u=e.getAttribute("stroke");s("stroke",e instanceof SVGLineElement||e instanceof SVGTextElement?"border-color":"color",u)}e.style&&le(e.style,(function(t,r){if("background-image"!==t||!r.includes("url"))if(Xt.hasOwnProperty(t))s(t,t,r);else{var n=Zt[t];!n||e.style.getPropertyValue(n)||e.hasAttribute(n)||e.style.setProperty(t,"")}})),e.style&&e instanceof SVGTextElement&&e.style.fill&&s("fill","color",e.style.getPropertyValue("fill")),D(o,(function(t){e.removeAttribute(Xt[t].dataAttr)})),ir.set(e,sr(e,t))}}function s(r,a,i){var u=Xt[r],s=u.customProp,c=u.dataAttr,l=kt(a,i,{},jt,n,null);if(l){var d=l.value;"function"==typeof d&&(d=d(t)),e.style.setProperty(s,d),e.hasAttribute(c)||e.setAttribute(c,""),o.delete(r)}}}var lr="theme-color",dr='meta[name="theme-color"]',fr=null,hr=null;function pr(e,t){fr=fr||e.content;try{var r=Ee(fr);e.content=Je(r,t)}catch(e){N(e)}}var vr=["mode","brightness","contrast","grayscale","sepia","darkSchemeBackgroundColor","darkSchemeTextColor","lightSchemeBackgroundColor","lightSchemeTextColor"];var mr=function(){var e=[],t=null;function r(){for(var r;r=e.shift();)r();t=null}return{add:function(n){e.push(n),t||(t=requestAnimationFrame(r))},cancel:function(){e.splice(0),cancelAnimationFrame(t),t=null}}}();function gr(){var e=0,t=new Set,r=new Map,n=new Set,o=null,u=!1,s=!1;return{modifySheet:function(c){var l=c.sourceCSSRules,d=c.theme,f=c.ignoreImageAnalysis,h=c.force,p=c.prepareSheet,v=c.isAsyncCancelled,m=0===r.size,g=new Set(r.keys()),b=function(e){return vr.map((function(t){return t+":"+e[t]})).join(";")}(d),y=b!==o;u&&(s=!0);var w=[];if(ue(l,(function(e){var n=e.cssText,o=!1;if(g.delete(n),e.parentRule instanceof CSSMediaRule&&(n+=";"+e.parentRule.media.mediaText),t.has(n)||(t.add(n),o=!0),o){m=!0;var a=[];e.style&&le(e.style,(function(t,r){var n=kt(t,r,e,jt,f,v);n&&a.push(n)}));var i=null;if(a.length>0){var u=e.parentRule;i={selector:e.selectorText,declarations:a,parentRule:u},w.push(i)}r.set(n,i)}else w.push(r.get(n))}),(function(){u=!0})),g.forEach((function(e){t.delete(e),r.delete(e)})),o=b,h||m||y){e++;var k=new Map,S=new Map,_=0,E=0,x={rule:null,rules:[],isGroup:!0},C=new WeakMap;n.forEach((function(e){return e()})),n.clear(),w.filter((function(e){return e})).forEach((function(t){var r=t.selector,o=t.declarations,u=R(t.parentRule),s={selector:r,declarations:[],isGroup:!1},c=s.declarations;function l(t,r,n,o){var a=++_,i={property:t,value:null,important:n,asyncKey:a,sourceValue:o};c.push(i);var u=e;r.then((function(t){t&&!v()&&u===e&&(i.value=t,mr.add((function(){v()||u!==e||function(e){var t=k.get(e),r=t.rule,n=t.target,o=t.index;n.deleteRule(o),T(n,o,r),k.delete(e)}(a)})))}))}function f(t,r,o,u){var s=r,d=s.declarations,f=s.onTypeChange,h=++E,p=e,m=c.length,g=[];if(0===d.length){var b={property:t,value:u,important:o,sourceValue:u,varKey:h};c.push(b),g=[b]}d.forEach((function(e){if(e.value instanceof Promise)l(e.property,e.value,o,u);else{var t={property:e.property,value:e.value,important:o,sourceValue:u,varKey:h};c.push(t),g.push(t)}})),f.addListener((function(t){if(!v()&&p===e){var r=t.map((function(e){return{property:e.property,value:e.value,important:o,sourceValue:u,varKey:h}})),n=c.indexOf(g[0],m);c.splice.apply(c,i([n,g.length],a(r))),g=r,function(e){var t=S.get(e),r=t.rule,n=t.target,o=t.index;n.deleteRule(o),T(n,o,r)}(h)}})),n.add((function(){return f.removeListeners()}))}u.rules.push(s),o.forEach((function(e){var t=e.property,r=e.value,n=e.important,o=e.sourceValue;if("function"==typeof r){var a=r(d);a instanceof Promise?l(t,a,n,o):t.startsWith("--")?f(t,a,n,o):c.push({property:t,value:a,important:n,sourceValue:o})}else c.push({property:t,value:r,important:n,sourceValue:o})}))}));var V=p();!function e(t,r,n){t.rules.forEach((function(t){t.isGroup?e(t,function(e,t){var r=e.rule;if(r instanceof CSSMediaRule){var n=r.media,o=t.cssRules.length;return t.insertRule("@media "+n.mediaText+" {}",o),t.cssRules[o]}return t}(t,r),n):n(t,r)}))}(x,V,(function(e,t){var r=t.cssRules.length;e.declarations.forEach((function(n){var o=n.asyncKey,a=n.varKey;null!=o&&k.set(o,{rule:e,target:t,index:r}),null!=a&&S.set(a,{rule:e,target:t,index:r})})),T(t,r,e)}))}function T(e,t,r){var n=r.selector+" { "+r.declarations.map((function(e){var t=e.property,r=e.value,n=e.important,o=e.sourceValue;return t+": "+(null==r?o:r)+(n?" !important":"")+";"})).join(" ")+" }";e.insertRule(n,t)}function R(e){if(null==e)return x;if(C.has(e))return C.get(e);var t={rule:e,rules:[],isGroup:!0};return C.set(e,t),R(e.parentRule).rules.push(t),t}},shouldRebuildStyle:function(){return u&&!s}}}function br(e){return(e instanceof HTMLStyleElement||e instanceof SVGStyleElement||e instanceof HTMLLinkElement&&e.rel&&e.rel.toLowerCase().includes("stylesheet")&&!e.disabled)&&!e.classList.contains("darkreader")&&"print"!==e.media.toLowerCase()&&!e.classList.contains("stylus")}function yr(e,t,r){return void 0===t&&(t=[]),void 0===r&&(r=!0),br(e)?t.push(e):(e instanceof Element||b&&e instanceof ShadowRoot||e===document)&&(D(e.querySelectorAll('style, link[rel*="stylesheet" i]:not([disabled])'),(function(e){return yr(e,t,!1)})),r&&z(e,(function(e){return yr(e.shadowRoot,t,!1)}))),t}var wr=new WeakSet,kr=new WeakSet,Sr=!1;document.addEventListener("__darkreader__inlineScriptsAllowed",(function(){Sr=!0}));var _r=0,Er=new Map;function xr(e,t){for(var o=t.update,i=t.loadingStart,u=t.loadingEnd,s=[],c=e;(c=c.nextElementSibling)&&c.matches(".darkreader");)s.push(c);var l=s.find((function(e){return e.matches(".darkreader--cors")&&!kr.has(e)}))||null,h=s.find((function(e){return e.matches(".darkreader--sync")&&!wr.has(e)}))||null,v=null,m=null,g=!1,b=!0,y=gr(),w=new MutationObserver((function(){o()})),k={attributes:!0,childList:!0,subtree:!0,characterData:!0};function S(){return e instanceof HTMLStyleElement&&e.textContent.trim().match(fe)}function _(e){var t=!1;if(e){var r=void 0;e:for(var n=0,o=e.length;n<o;n++)if((r=e[n]).href&&r.href.startsWith("http")&&!r.href.startsWith(location.origin)){t=!0;break e}}return t}function E(){if(l)return l.sheet.cssRules;if(S())return null;var e=L();return _(e)?null:e}function x(){l?(e.nextSibling!==l&&e.parentNode.insertBefore(l,e.nextSibling),l.nextSibling!==h&&e.parentNode.insertBefore(h,l.nextSibling)):e.nextSibling!==h&&e.parentNode.insertBefore(h,e.nextSibling)}var C=!1,V=!1,T=++_r;function R(){return r(this,void 0,void 0,(function(){var t,r,o,i,u,s,c,d;return n(this,(function(n){switch(n.label){case 0:if(!(e instanceof HTMLLinkElement))return[3,7];if(o=a(A(),2),i=o[0],(u=o[1])&&N(u),!(!i&&!u&&!p||p&&!e.sheet||(f=u,f&&f.message&&f.message.includes("loading"))))return[3,5];n.label=1;case 1:return n.trys.push([1,3,,4]),q("Linkelement "+T+" is not loaded yet and thus will be await for",e),[4,Cr(e,T)];case 2:return n.sent(),[3,4];case 3:return N(n.sent()),V=!0,[3,4];case 4:if(g)return[2,null];d=a(A(),2),i=d[0],(u=d[1])&&N(u),n.label=5;case 5:return s=_(i),null==i||s?[4,Vr(e.href)]:[2,i];case 6:return t=n.sent(),r=pe(e.href),g?[2,null]:[3,8];case 7:if(!S())return[2,null];t=e.textContent.trim(),r=pe(location.href),n.label=8;case 8:if(!t)return[3,13];n.label=9;case 9:return n.trys.push([9,11,,12]),[4,Tr(t,r)];case 10:return c=n.sent(),l=function(e,t){if(!t)return null;var r=document.createElement("style");return r.classList.add("darkreader"),r.classList.add("darkreader--cors"),r.media="screen",r.textContent=t,e.parentNode.insertBefore(r,e.nextSibling),r.sheet.disabled=!0,kr.add(r),r}(e,c),[3,12];case 11:return N(n.sent()),[3,12];case 12:if(l)return v=U(l,"prev-sibling"),[2,l.sheet.cssRules];n.label=13;case 13:return[2,null]}var f}))}))}var M=!1;function A(){try{return null==e.sheet?[null,null]:[e.sheet.cssRules,null]}catch(e){return[null,e]}}function L(){var e=a(A(),2),t=e[0],r=e[1];return r?(N(r),null):t}function P(){e.addEventListener("__darkreader__updateSheet",W),f||Sr&&e.sheet||function(){O=D(),F();var t=function(){D()!==O&&(O=D(),o()),Sr&&e.sheet?F():j=requestAnimationFrame(t)};t()}()}var O=null,j=null;function D(){var e=L();return e?e.length:null}function F(){cancelAnimationFrame(j)}var B=!1;function W(){function e(){B=!1,g||o()}Sr=!0,F(),B||(B=!0,"function"==typeof queueMicrotask?queueMicrotask(e):requestAnimationFrame(e))}function z(){e.removeEventListener("__darkreader__updateSheet",W),F()}function $(){w.disconnect(),g=!0,v&&v.stop(),m&&m.stop(),z()}var H=0;return{details:function(){var e=E();return e?{rules:e}:(C||V||(C=!0,i(),R().then((function(e){C=!1,u(),e&&o()})).catch((function(e){N(e),C=!1,u()}))),null)},render:function(t,r){var n=E();function a(){h||((h=e instanceof SVGStyleElement?document.createElementNS("http://www.w3.org/2000/svg","style"):document.createElement("style")).classList.add("darkreader"),h.classList.add("darkreader--sync"),h.media="screen",!d&&e.title&&(h.title=e.title),wr.add(h)),m&&m.stop(),x(),null==h.sheet&&(h.textContent="");for(var t=h.sheet,r=t.cssRules.length-1;r>=0;r--)t.deleteRule(r);return m?m.run():m=U(h,"prev-sibling",(function(){M=!0,i()})),h.sheet}function i(){var e=M;M=!1,y.modifySheet({prepareSheet:a,sourceCSSRules:n,theme:t,ignoreImageAnalysis:r,force:e,isAsyncCancelled:function(){return g}}),b=0===h.sheet.cssRules.length,y.shouldRebuildStyle()&&X((function(){return o()}))}n&&(g=!1,i())},pause:$,destroy:function(){if($(),I(l),I(h),u(),Er.has(T)){var e=Er.get(T);Er.delete(T),e&&e()}},watch:function(){w.observe(e,k),e instanceof HTMLStyleElement&&P()},restore:function(){h&&(++H>10?N("Style sheet was moved multiple times",e):(N("Restore style",h,e),x(),v&&v.skip(),m&&m.skip(),b||(M=!0,o())))}}}function Cr(e,t){return r(this,void 0,void 0,(function(){return n(this,(function(r){return[2,new Promise((function(r,n){var o=function(){e.removeEventListener("load",a),e.removeEventListener("error",i),Er.delete(t)},a=function(){o(),q("Linkelement "+t+" has been loaded"),r()},i=function(){o(),n("Linkelement "+t+" couldn't be loaded. "+e.href)};Er.set(t,(function(){o(),n()})),e.addEventListener("load",a),e.addEventListener("error",i),e.href||i()}))]}))}))}function Vr(e){return r(this,void 0,void 0,(function(){return n(this,(function(t){switch(t.label){case 0:return e.startsWith("data:")?[4,fetch(e)]:[3,3];case 1:return[4,t.sent().text()];case 2:return[2,t.sent()];case 3:return[4,ct({url:e,responseType:"text",mimeType:"text/css",origin:window.location.origin})];case 4:return[2,t.sent()]}}))}))}function Tr(e,t,a){return void 0===a&&(a=new Map),r(this,void 0,void 0,(function(){var r,i,u,s,c,l,d,f,h,p;return n(this,(function(n){switch(n.label){case 0:e=function(e,t){return e.replace(de,(function(e){var r=he(e);return'url("'+ie(t,r)+'")'}))}(e=function(e){return e.replace(me,"")}(e=e.replace(ve,"")),t),r=je(fe,e),n.label=1;case 1:n.trys.push([1,10,11,12]),i=o(r),u=i.next(),n.label=2;case 2:return u.done?[3,9]:(s=u.value,c=he(s.substring(7).trim().replace(/;$/,"")),l=ie(t,c),d=void 0,a.has(l)?(d=a.get(l),[3,7]):[3,3]);case 3:return n.trys.push([3,6,,7]),[4,Vr(l)];case 4:return d=n.sent(),a.set(l,d),[4,Tr(d,pe(l),a)];case 5:return d=n.sent(),[3,7];case 6:return N(n.sent()),d="",[3,7];case 7:e=e.split(s).join(d),n.label=8;case 8:return u=i.next(),[3,2];case 9:return[3,12];case 10:return f=n.sent(),h={error:f},[3,12];case 11:try{u&&!u.done&&(p=i.return)&&p.call(i)}finally{if(h)throw h.error}return[7];case 12:return[2,e=e.trim()]}}))}))}var Rr,Mr,Ar=[],Lr=new Map;function Pr(e){w&&D(e.querySelectorAll(":not(:defined)"),(function(e){var t=e.tagName.toLowerCase();if(!t.includes("-")){var o=e.getAttribute("is");if(!o)return;t=o}Lr.has(t)||(Lr.set(t,new Set),function(e){return r(this,void 0,void 0,(function(){return n(this,(function(t){return[2,new Promise((function(t){if(window.customElements&&"function"==typeof customElements.whenDefined)customElements.whenDefined(e).then(t);else if(Or)jr.set(e,t),document.dispatchEvent(new CustomEvent("__darkreader__addUndefinedResolver",{detail:{tag:e}}));else{var r=function(){var n=Lr.get(e);n&&n.size>0&&(n.values().next().value.matches(":defined")?t():requestAnimationFrame(r))};requestAnimationFrame(r)}}))]}))}))}(t).then((function(){if(Mr){var e=Lr.get(t);Lr.delete(t),Mr(Array.from(e))}}))),Lr.get(t).add(e)}))}var Or=!1;document.addEventListener("__darkreader__inlineScriptsAllowed",(function(){Or=!0}));var jr=new Map;function Dr(e){(Or=!0,jr.has(e.detail.tag))&&jr.get(e.detail.tag)()}function Fr(e,t,r){qr();var n=new Set(e),o=new WeakMap,a=new WeakMap;function i(e){o.set(e,e.previousElementSibling),a.set(e,e.nextElementSibling)}function u(e){var r=e.createdStyles,u=e.removedStyles,s=e.movedStyles;r.forEach((function(e){return i(e)})),s.forEach((function(e){return i(e)})),u.forEach((function(e){return t=e,o.delete(t),void a.delete(t);var t})),r.forEach((function(e){return n.add(e)})),u.forEach((function(e){return n.delete(e)})),r.size+u.size+s.size>0&&t({created:Array.from(r),removed:Array.from(u),moved:Array.from(s),updated:[]})}function s(e){var t=e.additions,r=e.moves,n=e.deletions,o=new Set,a=new Set,i=new Set;t.forEach((function(e){return yr(e).forEach((function(e){return o.add(e)}))})),n.forEach((function(e){return yr(e).forEach((function(e){return a.add(e)}))})),r.forEach((function(e){return yr(e).forEach((function(e){return i.add(e)}))})),u({createdStyles:o,removedStyles:a,movedStyles:i}),t.forEach((function(e){z(e,f),Pr(e)}))}function c(e){var t=new Set(yr(e)),r=new Set,i=new Set,s=new Set;t.forEach((function(e){n.has(e)||r.add(e)})),n.forEach((function(e){t.has(e)||i.add(e)})),t.forEach((function(e){var t;r.has(e)||i.has(e)||(t=e).previousElementSibling===o.get(t)&&t.nextElementSibling===a.get(t)||s.add(e)})),u({createdStyles:r,removedStyles:i,movedStyles:s}),z(e,f),Pr(e)}function l(e){var r=new Set,n=new Set;e.forEach((function(e){var t=e.target;t.isConnected&&(br(t)?r.add(t):t instanceof HTMLLinkElement&&t.disabled&&n.add(t))})),r.size+n.size>0&&t({updated:Array.from(r),created:[],removed:Array.from(n),moved:[]})}function d(e){var t=re(e,{onMinorMutations:s,onHugeMutations:c}),r=new MutationObserver(l);r.observe(e,{attributes:!0,attributeFilter:["rel","disabled","media"],subtree:!0}),Ar.push(t,r),Rr.add(e)}function f(e){var t=e.shadowRoot;null==t||Rr.has(t)||(d(t),r(t))}e.forEach(i),d(document),z(document.documentElement,f),Mr=function(e){var r=[];e.forEach((function(e){return F(r,yr(e.shadowRoot))})),t({created:r,updated:[],removed:[],moved:[]}),e.forEach((function(e){var t=e.shadowRoot;null!=t&&(f(e),z(t,f),Pr(t))}))},document.addEventListener("__darkreader__isDefined",Dr),Pr(document)}function qr(){Ar.forEach((function(e){return e.disconnect()})),Ar.splice(0,Ar.length),Rr=new WeakSet,Mr=null,Lr.clear(),document.removeEventListener("__darkreader__isDefined",Dr)}var Nr=new WeakMap,Br=new WeakSet;function Wr(e){var t=!1;return{render:function(r,n){e.adoptedStyleSheets.forEach((function(o){if(!Br.has(o)){var u=o.rules,s=new CSSStyleSheet;gr().modifySheet({prepareSheet:function(){for(var t=s.cssRules.length-1;t>=0;t--)s.deleteRule(t);return function(t,r){var n=i([],a(e.adoptedStyleSheets)),o=n.indexOf(t),u=n.indexOf(r);o!==u-1&&(u>=0&&n.splice(u,1),n.splice(o+1,0,r),e.adoptedStyleSheets=n)}(o,s),Nr.set(o,s),Br.add(s),s},sourceCSSRules:u,theme:r,ignoreImageAnalysis:n,force:!1,isAsyncCancelled:function(){return t}})}}))},destroy:function(){t=!0;var r=i([],a(e.adoptedStyleSheets));e.adoptedStyleSheets.forEach((function(e){if(Br.has(e)){var t=r.indexOf(e);t>=0&&r.splice(t,1),Nr.delete(e),Br.delete(e)}})),e.adoptedStyleSheets=r}}}function Ir(){document.dispatchEvent(new CustomEvent("__darkreader__inlineScriptsAllowed"));var e=Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype,"addRule"),t=Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype,"insertRule"),r=Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype,"deleteRule"),n=Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype,"removeRule"),o=Object.getOwnPropertyDescriptor(Document.prototype,"styleSheets"),u=location.hostname.endsWith("baidu.com"),s=u?Object.getOwnPropertyDescriptor(Element.prototype,"getElementsByTagName"):null,c=function(){Object.defineProperty(CSSStyleSheet.prototype,"addRule",e),Object.defineProperty(CSSStyleSheet.prototype,"insertRule",t),Object.defineProperty(CSSStyleSheet.prototype,"deleteRule",r),Object.defineProperty(CSSStyleSheet.prototype,"removeRule",n),document.removeEventListener("__darkreader__cleanUp",c),document.removeEventListener("__darkreader__addUndefinedResolver",l),Object.defineProperty(Document.prototype,"styleSheets",o),u&&Object.defineProperty(Element.prototype,"getElementsByTagName",s)},l=function(e){customElements.whenDefined(e.detail.tag).then((function(){document.dispatchEvent(new CustomEvent("__darkreader__isDefined",{detail:{tag:e.detail.tag}}))}))};document.addEventListener("__darkreader__cleanUp",c),document.addEventListener("__darkreader__addUndefinedResolver",l);var d=new Event("__darkreader__updateSheet");Object.defineProperty(CSSStyleSheet.prototype,"addRule",Object.assign({},e,{value:function(t,r,n){return e.value.call(this,t,r,n),this.ownerNode&&!this.ownerNode.classList.contains("darkreader")&&this.ownerNode.dispatchEvent(d),-1}})),Object.defineProperty(CSSStyleSheet.prototype,"insertRule",Object.assign({},t,{value:function(e,r){var n=t.value.call(this,e,r);return this.ownerNode&&!this.ownerNode.classList.contains("darkreader")&&this.ownerNode.dispatchEvent(d),n}})),Object.defineProperty(CSSStyleSheet.prototype,"deleteRule",Object.assign({},r,{value:function(e){r.value.call(this,e),this.ownerNode&&!this.ownerNode.classList.contains("darkreader")&&this.ownerNode.dispatchEvent(d)}})),Object.defineProperty(CSSStyleSheet.prototype,"removeRule",Object.assign({},n,{value:function(e){n.value.call(this,e),this.ownerNode&&!this.ownerNode.classList.contains("darkreader")&&this.ownerNode.dispatchEvent(d)}})),Object.defineProperty(Document.prototype,"styleSheets",Object.assign({},o,{get:function(){var e=i([],a(o.get.call(this))).filter((function(e){return!e.ownerNode.classList.contains("darkreader")}));return Object.setPrototypeOf(e,StyleSheetList.prototype)}})),u&&Object.defineProperty(Element.prototype,"getElementsByTagName",Object.assign({},s,{value:function(e){var t=this,r=function(){var r=s.value.call(t,e);return"style"===e&&(r=Object.setPrototypeOf(i([],a(r)).filter((function(e){return!e.classList.contains("darkreader")})),NodeList.prototype)),r},n=r();return new Proxy(n,{get:function(e,t){return r()[t]}})}}))}var Ur=function(){if("randomUUID"in crypto){var e=crypto.randomUUID();return e.substring(0,8)+e.substring(9,13)+e.substring(14,18)+e.substring(19,23)+e.substring(24)}return Array.from(crypto.getRandomValues(new Uint8Array(16))).map((function(e){return((t=e)<16?"0":"")+t.toString(16);var t})).join("")}(),zr=new Map,$r=[],Hr=null,Gr=null,Qr=null,Kr=null,Jr=null;function Xr(e,t){void 0===t&&(t=document.head||document);var r=t.querySelector("."+e);return r||((r=document.createElement("style")).classList.add("darkreader"),r.classList.add(e),r.media="screen",r.textContent=""),r}var Yr=new Map;function Zr(e,t){Yr.has(t)&&Yr.get(t).stop(),Yr.set(t,U(e,"parent"))}function en(){var e=Xr("darkreader--fallback",document);e.textContent=Et(Hr,{strict:!0}),document.head.insertBefore(e,document.head.firstChild),Zr(e,"fallback");var r=Xr("darkreader--user-agent");r.textContent=St(Hr,Qr,Hr.styleSystemControls),document.head.insertBefore(r,e.nextSibling),Zr(r,"user-agent");var n,o,a=Xr("darkreader--text");Hr.useFont||Hr.textStroke>0?a.textContent=(n=Hr,(o=[]).push('*:not(pre, pre *, code, .far, .fa, .glyphicon, [class*="vjs-"], .fab, .fa-github, .fas, .material-icons, .icofont, .typcn, mu, [class*="mu-"], .glyphicon, .icon) {'),n.useFont&&n.fontFamily&&o.push("  font-family: "+n.fontFamily+" !important;"),n.textStroke>0&&(o.push("  -webkit-text-stroke: "+n.textStroke+"px !important;"),o.push("  text-stroke: "+n.textStroke+"px !important;")),o.push("}"),o.join("\n")):a.textContent="",document.head.insertBefore(a,e.nextSibling),Zr(a,"text");var i=Xr("darkreader--invert");Gr&&Array.isArray(Gr.invert)&&Gr.invert.length>0?i.textContent=[Gr.invert.join(", ")+" {","    filter: "+at(t(t({},Hr),{contrast:0===Hr.mode?Hr.contrast:Pe(Hr.contrast-10,0,100)}))+" !important;","}"].join("\n"):i.textContent="",document.head.insertBefore(i,a.nextSibling),Zr(i,"invert");var u=Xr("darkreader--inline");u.textContent=rr(),document.head.insertBefore(u,i.nextSibling),Zr(u,"inline");var s=Xr("darkreader--override");s.textContent=Gr&&Gr.css?nn(Gr.css):"",document.head.appendChild(s),Zr(s,"override");var c=Xr("darkreader--variables"),l=_t(Hr),d=Hr.darkSchemeBackgroundColor,f=Hr.darkSchemeTextColor,h=Hr.lightSchemeBackgroundColor,p=Hr.lightSchemeTextColor,v=Hr.mode,m=0===v?h:d,g=0===v?p:f;m=Je(Ee(m),Hr),g=tt(Ee(g),Hr),c.textContent=[":root {","   --darkreader-neutral-background: "+m+";","   --darkreader-neutral-text: "+g+";","   --darkreader-selection-background: "+l.backgroundColorSelection+";","   --darkreader-selection-text: "+l.foregroundColorSelection+";","}"].join("\n"),document.head.insertBefore(c,u.nextSibling),Zr(c,"variables");var b=Xr("darkreader--root-vars");document.head.insertBefore(b,c.nextSibling);var y=function(e,t){void 0===t&&(t=document.head||document);var r=t.querySelector("."+e);return r||((r=document.createElement("script")).classList.add("darkreader"),r.classList.add(e)),r}("darkreader--proxy");y.append("("+Ir+")()"),document.head.insertBefore(y,b.nextSibling),y.remove()}var tn=new Set;function rn(e){var r=Xr("darkreader--inline",e);r.textContent=rr(),e.insertBefore(r,e.firstChild);var n=Xr("darkreader--override",e);n.textContent=Gr&&Gr.css?nn(Gr.css):"",e.insertBefore(n,r.nextSibling);var o=Xr("darkreader--invert",e);Gr&&Array.isArray(Gr.invert)&&Gr.invert.length>0?o.textContent=[Gr.invert.join(", ")+" {","    filter: "+at(t(t({},Hr),{contrast:0===Hr.mode?Hr.contrast:Pe(Hr.contrast-10,0,100)}))+" !important;","}"].join("\n"):o.textContent="",e.insertBefore(o,n.nextSibling),tn.add(e)}function nn(e){return e.replace(/\${(.+?)}/g,(function(e,t){var r=Tt(t);return r?$e(r,Hr,He):(N("Couldn't parse CSSTemplate's color."),t)}))}function on(){var e=document.querySelector(".darkreader--fallback");e&&(e.textContent="")}var an=0,un=new Set;function sn(e){var t=++an;q("New manager for element, with loadingStyleID "+t,e);var r=xr(e,{update:function(){var e=r.details();e&&(jt.addRulesForMatching(e.rules),jt.matchVariablesAndDependants(),r.render(Hr,Kr))},loadingStart:function(){if(!$()||!pn){un.add(t),q("Current amount of styles loading: "+un.size);var e=document.querySelector(".darkreader--fallback");e.textContent||(e.textContent=Et(Hr,{strict:!1}))}},loadingEnd:function(){un.delete(t),q("Removed loadingStyle "+t+", now awaiting: "+un.size),q("To-do to be loaded",un),0===un.size&&$()&&on()}});return zr.set(e,r),r}function cn(e){var t=zr.get(e);t&&(t.destroy(),zr.delete(e))}var ln=B((function(e){zr.forEach((function(e){return e.render(Hr,Kr)})),$r.forEach((function(e){return e.render(Hr,Kr)})),e&&e()})),dn=function(){ln.cancel()};function fn(){0!==un.size?N("DOM is ready, but still have styles being loaded.",un):on()}var hn=null,pn=!document.hidden;function vn(){document.removeEventListener("visibilitychange",hn),hn=null}function mn(){function e(){var e,t;!function(){dn();var e=yr(document).filter((function(e){return!zr.has(e)})).map((function(e){return sn(e)}));e.map((function(e){return e.details()})).filter((function(e){return e&&e.rules.length>0})).forEach((function(e){jt.addRulesForMatching(e.rules)})),jt.matchVariablesAndDependants(),jt.setOnRootVariableChange((function(){jt.putRootVars(document.head.querySelector(".darkreader--root-vars"),Hr)})),jt.putRootVars(document.head.querySelector(".darkreader--root-vars"),Hr),zr.forEach((function(e){return e.render(Hr,Kr)})),0===un.size&&on(),e.forEach((function(e){return e.watch()}));var t=function(e){for(var t=[],r=0,n=e.length;r<n;r++)t.push(e[r]);return t}(document.querySelectorAll(tr));z(document.documentElement,(function(e){rn(e.shadowRoot);var r=e.shadowRoot.querySelectorAll(tr);r.length>0&&F(t,r)})),t.forEach((function(e){return cr(e,Hr,Jr,Kr)})),gn(document)}(),Fr(Array.from(zr.keys()),(function(e){var t=e.created,r=e.updated,n=e.removed,o=e.moved,a=n,i=t.concat(r).concat(o).filter((function(e){return!zr.has(e)})),u=o.filter((function(e){return zr.has(e)}));q("Styles to be removed:",a),a.forEach((function(e){return cn(e)}));var s=i.map((function(e){return sn(e)}));s.map((function(e){return e.details()})).filter((function(e){return e&&e.rules.length>0})).forEach((function(e){jt.addRulesForMatching(e.rules)})),jt.matchVariablesAndDependants(),s.forEach((function(e){return e.render(Hr,Kr)})),s.forEach((function(e){return e.watch()})),u.forEach((function(e){return zr.get(e).restore()}))}),(function(e){rn(e),gn(e)})),e=function(e){cr(e,Hr,Jr,Kr),e===document.documentElement&&e.getAttribute("style").includes("--")&&(jt.matchVariablesAndDependants(),jt.putRootVars(document.head.querySelector(".darkreader--root-vars"),Hr))},t=function(e){rn(e);var t=e.querySelectorAll(tr);t.length>0&&D(t,(function(e){return cr(e,Hr,Jr,Kr)}))},ar(document,e,t),z(document.documentElement,(function(r){ar(r.shadowRoot,e,t)})),G(fn)}var t,r,n,o;en(),document.hidden?(t=e,r=Boolean(hn),hn=function(){document.hidden||(vn(),t(),pn=!0)},r||document.addEventListener("visibilitychange",hn)):e(),n=Hr,(o=document.querySelector(dr))?pr(o,n):(hr&&hr.disconnect(),(hr=new MutationObserver((function(e){e:for(var t=0;t<e.length;t++)for(var r=e[t].addedNodes,o=0;o<r.length;o++){var a=r[o];if(a instanceof HTMLMetaElement&&a.name===lr){hr.disconnect(),hr=null,pr(a,n);break e}}}))).observe(document.head,{childList:!0}))}function gn(e){if(Array.isArray(e.adoptedStyleSheets)&&e.adoptedStyleSheets.length>0){var t=Wr(e);$r.push(t),t.render(Hr,Kr)}}function bn(){zr.forEach((function(e){return e.pause()})),D(Yr.values(),(function(e){return e.stop()})),Yr.clear(),qr(),nr.forEach((function(e){return e.disconnect()})),or.forEach((function(e){return e.disconnect()})),nr.clear(),or.clear(),Q(fn),J.clear()}function yn(){var e,t=document.querySelector('meta[name="darkreader"]');return t?t.content!==Ur:((e=document.createElement("meta")).name="darkreader",e.content=Ur,document.head.appendChild(e),!1)}function wn(e,t,r){if(Hr=e,(Gr=t)?(Kr=Array.isArray(Gr.ignoreImageAnalysis)?Gr.ignoreImageAnalysis:[],Jr=Array.isArray(Gr.ignoreInlineStyle)?Gr.ignoreInlineStyle:[]):(Kr=[],Jr=[]),Qr=r,document.head){if(yn())return;document.documentElement.setAttribute("data-darkreader-mode","dynamic"),document.documentElement.setAttribute("data-darkreader-scheme",Hr.mode?"dark":"dimmed"),mn()}else{if(!h){var n=Xr("darkreader--fallback");document.documentElement.appendChild(n),n.textContent=Et(Hr,{strict:!0})}var o=new MutationObserver((function(){if(document.head){if(o.disconnect(),yn())return void kn();mn()}}));o.observe(document,{childList:!0,subtree:!0})}}function kn(){document.documentElement.removeAttribute("data-darkreader-mode"),document.documentElement.removeAttribute("data-darkreader-scheme"),jt.clear(),ne.clear(),vn(),dn(),bn(),Ot(),I(document.querySelector(".darkreader--fallback")),document.head&&(!function(){hr&&(hr.disconnect(),hr=null);var e=document.querySelector(dr);e&&fr&&(e.content=fr)}(),I(document.head.querySelector(".darkreader--user-agent")),I(document.head.querySelector(".darkreader--text")),I(document.head.querySelector(".darkreader--invert")),I(document.head.querySelector(".darkreader--inline")),I(document.head.querySelector(".darkreader--override")),I(document.head.querySelector(".darkreader--variables")),I(document.head.querySelector(".darkreader--root-vars")),I(document.head.querySelector('meta[name="darkreader"]')),document.dispatchEvent(new CustomEvent("__darkreader__cleanUp")),I(document.head.querySelector(".darkreader--proxy"))),tn.forEach((function(e){I(e.querySelector(".darkreader--inline")),I(e.querySelector(".darkreader--override"))})),tn.clear(),D(zr.keys(),(function(e){return cn(e)})),un.clear(),Er.clear(),D(document.querySelectorAll(".darkreader"),I),$r.forEach((function(e){e.destroy()})),$r.splice(0)}var Sn=/url\(\"(blob\:.*?)\"\)/g;function _n(e){return r(this,void 0,void 0,(function(){var t,r;return n(this,(function(n){switch(n.label){case 0:return t=[],je(Sn,e,1).forEach((function(e){var r=S(e);t.push(r)})),[4,Promise.all(t)];case 1:return r=n.sent(),[2,e.replace(Sn,(function(){return'url("'+r.shift()+'")'}))]}}))}))}function En(){return r(this,void 0,void 0,(function(){function e(e,r){var n=document.querySelector(e);n&&n.textContent&&(t.push("/* "+r+" */"),t.push(n.textContent),t.push(""))}var t,r,o,a,i;return n(this,(function(n){switch(n.label){case 0:return t=['/*\n                        _______\n                       /       \\\n                      .==.    .==.\n                     ((  ))==((  ))\n                    / "=="    "=="\\\n                   /____|| || ||___\\\n       ________     ____    ________  ___    ___\n       |  ___  \\   /    \\   |  ___  \\ |  |  /  /\n       |  |  \\  \\ /  /\\  \\  |  |  \\  \\|  |_/  /\n       |  |   )  /  /__\\  \\ |  |__/  /|  ___  \\\n       |  |__/  /  ______  \\|  ____  \\|  |  \\  \\\n_______|_______/__/ ____ \\__\\__|___\\__\\__|___\\__\\____\n|  ___  \\ |  ____/ /    \\   |  ___  \\ |  ____|  ___  \\\n|  |  \\  \\|  |___ /  /\\  \\  |  |  \\  \\|  |___|  |  \\  \\\n|  |__/  /|  ____/  /__\\  \\ |  |   )  |  ____|  |__/  /\n|  ____  \\|  |__/  ______  \\|  |__/  /|  |___|  ____  \\\n|__|   \\__\\____/__/      \\__\\_______/ |______|__|   \\__\\\n                https://darkreader.org\n*/\n\n/*! Dark reader generated CSS | Licensed under MIT https://github.com/darkreader/darkreader/blob/master/LICENSE */\n'],e(".darkreader--fallback","Fallback Style"),e(".darkreader--user-agent","User-Agent Style"),e(".darkreader--text","Text Style"),e(".darkreader--invert","Invert Style"),e(".darkreader--variables","Variables Style"),r=[],document.querySelectorAll(".darkreader--sync").forEach((function(e){D(e.sheet.cssRules,(function(e){e&&e.cssText&&r.push(e.cssText)}))})),r.length?(o=function(e){function t(e){return e.replace(/^\s+/,"")}function r(e){return 0===e?"":" ".repeat(4*e)}if(e.length<5e4)for(var n=/[^{}]+{\s*}/;n.test(e);)e=e.replace(n,"");for(var o=e.replace(/\s{2,}/g," ").replace(/\{/g,"{\n").replace(/\}/g,"\n}\n").replace(/\;(?![^\(|\"]*(\)|\"))/g,";\n").replace(/\,(?![^\(|\"]*(\)|\"))/g,",\n").replace(/\n\s*\n/g,"\n").split("\n"),a=0,i=[],u=0,s=o.length;u<s;u++){var c=o[u]+"\n";c.includes("{")?i.push(r(a++)+t(c)):c.includes("}")?i.push(r(--a)+t(c)):i.push(r(a)+t(c))}return i.join("").trim()}(r.join("\n")),t.push("/* Modified CSS */"),i=(a=t).push,[4,_n(o)]):[3,2];case 1:i.apply(a,[n.sent()]),t.push(""),n.label=2;case 2:return e(".darkreader--override","Override Style"),[2,t.join("\n")]}}))}))}var xn=!1,Cn=function(){try{return window.self!==window.top}catch(e){return console.warn(e),!0}}();function Vn(e,r){void 0===e&&(e={}),void 0===r&&(r=null);var n=t(t({},j),e);if(n.engine!==L)throw new Error("Theme engine is not supported.");wn(n,r,Cn),xn=!0}function Tn(){kn(),xn=!1}var Rn=matchMedia("(prefers-color-scheme: dark)"),Mn={themeOptions:null,fixes:null};function An(){Rn.matches?Vn(Mn.themeOptions,Mn.fixes):Tn()}var Ln=function(e){x=e||E};e.auto=function(e,t){void 0===e&&(e={}),void 0===t&&(t=null),e?(Mn={themeOptions:e,fixes:t},An(),y?Rn.addEventListener("change",An):Rn.addListener(An)):(y?Rn.removeEventListener("change",An):Rn.removeListener(An),Tn())},e.disable=Tn,e.enable=Vn,e.exportGeneratedCSS=function(){return r(this,void 0,void 0,(function(){return n(this,(function(e){switch(e.label){case 0:return[4,En()];case 1:return[2,e.sent()]}}))}))},e.isEnabled=function(){return xn},e.setFetchMethod=Ln,Object.defineProperty(e,"__esModule",{value:!0})}));
+//# sourceMappingURL=/sm/5be885d11df3ea74a4395d7b62c89b39f3ea920787b81a23ef27e58e905733ef.map
+DarkReader.enable({brightness:100,contrast:100,sepia:0});