├── .gitignore ├── GNUmakefile ├── LICENSE ├── README.md ├── config.mak ├── docs ├── description.md ├── options │ ├── help │ ├── list │ ├── remove │ └── version ├── readme_installation.md └── releasenotes │ ├── 0_next.md │ └── 2020.11.22.md ├── func ├── ERR.sh ├── addfiles.sh └── removefile.sh ├── options ├── vivaldi-autoinject-custom-js-ui └── vivaldi-autoinject-custom-js-ui.1 /.gitignore: -------------------------------------------------------------------------------- 1 | .cache/ 2 | **/_* 3 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | .PHONY: all install-dev uninstall-dev 2 | 3 | .ONESHELL: 4 | .DEFAULT_GOAL := all 5 | 6 | SHELL := /bin/bash 7 | CUSTOM_TARGETS = 8 | 9 | NAME := $(notdir $(realpath .)) 10 | VERSION := 0 11 | UPDATED := $(shell date +'%Y-%m-%d') 12 | AUTHOR := anon 13 | CACHE_DIR := .cache 14 | DOCS_DIR := docs 15 | CONF_DIR := conf 16 | AWK_DIR := awklib 17 | FUNCS_DIR := func 18 | FILE_EXT := .sh 19 | INDENT := $(shell echo -e " ") 20 | USAGE = $(NAME) [OPTIONS] 21 | OPTIONS_FILE := options 22 | MONOLITH = _$(NAME) 23 | BASE := _init$(FILE_EXT) 24 | SHBANG := \#!/bin/bash 25 | OPTIONS_ARRAY_NAME := _o 26 | FUNC_STYLE := "() {" 27 | 28 | config_mak := config.mak 29 | help_table := $(CACHE_DIR)/help_table.txt 30 | long_help := $(CACHE_DIR)/long_help.md 31 | getopt := $(CACHE_DIR)/getopt 32 | print_help := $(CACHE_DIR)/print_help$(FILE_EXT) 33 | print_version := $(CACHE_DIR)/print_version$(FILE_EXT) 34 | 35 | ifneq ($(wildcard $(config_mak)),) 36 | include config.mak 37 | else 38 | config_mak := 39 | endif 40 | 41 | ifeq ($(wildcard $(OPTIONS_FILE)),) 42 | OPTIONS_FILE := 43 | help_table := 44 | long_help := 45 | getopt := 46 | print_help := 47 | print_version := 48 | endif 49 | 50 | function_createconf := $(FUNCS_DIR)/_createconf$(FILE_EXT) 51 | function_awklib := $(FUNCS_DIR)/_awklib$(FILE_EXT) 52 | 53 | ifneq ($(wildcard $(CONF_DIR)/*),) 54 | include_createconf = $(function_createconf) 55 | conf_dirs = $(patsubst ./%,%,$(shell find "./$(CONF_DIR)" -type d)) 56 | conf_files = $(patsubst ./%,%,$(shell find "./$(CONF_DIR)" -type f)) 57 | else 58 | $(shell rm -f $(function_createconf)) 59 | endif 60 | 61 | ifneq ($(wildcard $(AWK_DIR)/*),) 62 | include_awklib = $(function_awklib) 63 | awk_files = $(wildcard $(AWK_DIR)/*) 64 | else 65 | $(shell rm -f $(function_awklib)) 66 | endif 67 | 68 | option_docs = $(wildcard $(DOCS_DIR)/options/*) 69 | 70 | generated_functions := $(function_err) $(include_createconf) $(include_awklib) 71 | function_files := \ 72 | $(generated_functions) \ 73 | $(filter-out $(generated_functions),$(wildcard $(FUNCS_DIR)/*)) 74 | 75 | 76 | # this hack writes 1 or 0 to the file .cache/got_func 77 | # depending on existence of files in FUNC_DIR 78 | # but it also makes sure to only update the file 79 | # if the value has changed. 80 | # this is needed for _init.sh (BASE) to know it needs 81 | # to be rebuilt on this event. 82 | 83 | ifneq ($(wildcard $(CACHE_DIR)/got_func),) 84 | ifneq ($(wildcard $(FUNCS_DIR)/*),) 85 | ifneq ($(file < $(CACHE_DIR)/got_func), 1) 86 | $(shell echo 1 > $(CACHE_DIR)/got_func) 87 | endif 88 | else 89 | ifneq ($(file < $(CACHE_DIR)/got_func), 0) 90 | $(shell echo 0 > $(CACHE_DIR)/got_func) 91 | endif 92 | endif 93 | endif 94 | 95 | $(CACHE_DIR)/got_func: | $(CACHE_DIR)/ 96 | @$(info making $@) 97 | [[ -d $${tmp:=$(FUNCS_DIR)} ]] && tmp=1 || tmp=0 98 | echo $$tmp > $@ 99 | 100 | clean: 101 | rm -rf $(wildcard _*) $(CACHE_DIR) $(generated_functions) 102 | 103 | install-dev: $(BASE) $(NAME) 104 | ln -s $(realpath $(NAME)) $(PREFIX)/bin/$(NAME) 105 | 106 | uninstall-dev: $(PREFIX)/bin/$(NAME) 107 | rm $^ 108 | 109 | $(BASE): $(getopt) $(print_help) $(print_version) $(CACHE_DIR)/got_func 110 | @$(info making $@) 111 | { 112 | printf '%s\n' '$(SHBANG)' '' 113 | 114 | [[ -f $${pv:=$(print_version)} ]] \ 115 | && grep -vhE -e '^#!/' $(print_version) | sed '0,/2/s//$$\{__stderr:-2\}/' 116 | [[ -f $${ph:=$(print_help)} ]] \ 117 | && grep -vhE -e '^#!/' $(print_help) | sed '0,/2/s//$$\{__stderr:-2\}/' 118 | 119 | echo 120 | 121 | [[ -d $${fd:=$(FUNCS_DIR)} ]] && { 122 | printf '%s\n' \ 123 | 'for ___f in "$$__dir/$(FUNCS_DIR)"/*; do' \ 124 | '$(INDENT). "$$___f" ; done ; unset -v ___f' 125 | } 126 | 127 | echo 128 | 129 | [[ -f $${go:=$(getopt)} ]] && cat $(getopt) 130 | 131 | echo "((BASHBUD_VERBOSE)) && _o[verbose]=1" 132 | echo 133 | 134 | echo 'main "$$@"' 135 | } > $@ 136 | 137 | $(MONOLITH): $(print_version) $(NAME) $(print_help) $(function_files) $(getopt) 138 | @$(info making $@) 139 | { 140 | printf '%s\n' '$(SHBANG)' '' 141 | re='#bashbud$$' 142 | for f in $^; do 143 | # ignore files where the first line ends with '#bashbud' 144 | [[ $$(head -n1 $$f) =~ $$re ]] && continue 145 | # ignore lines that ends with '#bashbud' (and shbangs) 146 | grep -vhE -e '^#!' -e '#bashbud$$' $$f 147 | done 148 | 149 | echo 'main "$$@"' 150 | } > $@ 151 | 152 | chmod +x $@ 153 | 154 | # if a file in docs/options contains more than 155 | # 2 lines, it will get added to the file .cache/long_help.md 156 | # like this: 157 | # ### -s, --long-option ARG 158 | # text in docs/options/long-option after the first 2 lines 159 | $(long_help): $(CACHE_DIR)/options_in_use $(option_docs) 160 | @$(info making $@) 161 | for option in $(file < $(CACHE_DIR)/options_in_use); do 162 | [[ $$(wc -l < "$(DOCS_DIR)/options/$$option") -lt 2 ]] \ 163 | && continue 164 | printf '### ' 165 | sed -r 's/\|\s*$$//g;s/^\s*//g' "$(CACHE_DIR)/options/$$option" 166 | echo 167 | tail -qn +3 "$(DOCS_DIR)/options/$$option" 168 | echo 169 | done > $@ 170 | 171 | $(CACHE_DIR)/synopsis.txt: $(OPTIONS_FILE) | $(CACHE_DIR)/ 172 | @$(info making $@) 173 | sed 's/^/$(NAME) /g;s/*//g' $< > $@ 174 | 175 | $(help_table): $(long_help) 176 | @$(info making $@) 177 | for option in $$(cat $(CACHE_DIR)/options_in_use); do 178 | [[ -f $(CACHE_DIR)/options/$$option ]] \ 179 | && frag=$$(cat $(CACHE_DIR)/options/$$option) \ 180 | || frag="$$option | " 181 | 182 | [[ -f $(DOCS_DIR)/options/$$option ]] \ 183 | && desc=$$(head -qn1 $(DOCS_DIR)/options/$$option) \ 184 | || desc='short description ' 185 | 186 | paste <(echo "$$frag") <(echo "$$desc") 187 | done | tr -d '\t\\' > $@ 188 | 189 | $(print_version): $(config_mak) | $(CACHE_DIR)/ 190 | @$(info making $@) 191 | echo $(SHBANG) 192 | fstyle=$(FUNC_STYLE) 193 | printf "__print_version$${fstyle}\n" > $@ 194 | printf '%s\n' \ 195 | "$(INDENT)>&2 printf '%s\n' \\" \ 196 | "$(INDENT)$(INDENT)'$(NAME) - version: $(VERSION)' \\" \ 197 | "$(INDENT)$(INDENT)'updated: $(UPDATED) by $(AUTHOR)'" \ 198 | "}" \ 199 | "" >> $@ 200 | 201 | $(print_help): $(help_table) $(CACHE_DIR)/synopsis.txt 202 | @$(info making $@) 203 | { 204 | echo $(SHBANG) 205 | fstyle=$(FUNC_STYLE) 206 | printf "__print_help$${fstyle}\n" 207 | echo "$(INDENT)cat << 'EOB' >&2 " 208 | if [[ options = "$(USAGE)" ]]; then 209 | cat $(CACHE_DIR)/synopsis.txt 210 | echo 211 | else 212 | printf '%s\n' 'usage: $(USAGE)' '' 213 | echo 214 | fi 215 | cat $(help_table) 216 | printf '%s\n' 'EOB' '}' 217 | } > $@ 218 | 219 | $(function_createconf): $(conf_files) | $(FUNCS_DIR)/ 220 | @$(info making $@) 221 | { 222 | printf '%s\n' \ 223 | '$(SHBANG)' \ 224 | '' \ 225 | '### _createconf() function is automatically generated' \ 226 | '### from makefile based on the content of the $(CONF_DIR)/ directory' \ 227 | '' 228 | 229 | 230 | fstyle=$(FUNC_STYLE) 231 | printf "_createconf$${fstyle}\n" 232 | 233 | echo 'local trgdir="$$1"' 234 | 235 | echo 'mkdir -p $(subst $(CONF_DIR),"$$trgdir",$(conf_dirs))' 236 | for f in $(conf_files); do 237 | 238 | echo "" 239 | echo 'if [[ -d $$__dir ]]; then #bashbud' 240 | echo "cat \"\$$__dir/$$f\" > \"$${f/$(subst /,\/,$(CONF_DIR))/\$$trgdir}\" #bashbud" 241 | echo 'else #bashbud' 242 | echo "cat << 'EOCONF' > \"$${f/$(subst /,\/,$(CONF_DIR))/\$$trgdir}\"" 243 | cat "$$f" 244 | echo "EOCONF" 245 | echo 'fi #bashbud' 246 | [[ -x $$f ]] && echo "chmod +x \"$${f/$(subst /,\/,$(CONF_DIR))/\$$trgdir}\"" 247 | done 248 | 249 | echo '}' 250 | } > $@ 251 | 252 | $(function_awklib): $(awk_files) | $(FUNCS_DIR)/ 253 | @$(info making $@) 254 | { 255 | printf '%s\n' \ 256 | '$(SHBANG)' \ 257 | '' \ 258 | '### _awklib() function is automatically generated' \ 259 | '### from makefile based on the content of the $(AWK_DIR)/ directory' \ 260 | '' 261 | 262 | fstyle=$(FUNC_STYLE) 263 | printf "_awklib$${fstyle}\n" 264 | printf '%s\n' \ 265 | '[[ -d $$__dir ]] && { cat "$$__dir/$(AWK_DIR)/"* ; return ;} #bashbud' \ 266 | "cat << 'EOAWK'" 267 | cat $(awk_files) 268 | printf '%s\n' "EOAWK" '}' 269 | } > $@ 270 | 271 | $(CACHE_DIR)/: 272 | @$(info creating $(CACHE_DIR)/ dir) 273 | mkdir -p $(CACHE_DIR) $(CACHE_DIR)/options 274 | 275 | $(FUNCS_DIR)/: 276 | @$(info creating $(FUNCS_DIR)/ dir) 277 | mkdir -p $(FUNCS_DIR) 278 | 279 | $(CACHE_DIR)/options_in_use $(getopt) &: $(OPTIONS_FILE) | $(CACHE_DIR)/ 280 | @$(info parsing $(OPTIONS_FILE)) 281 | mkdir -p $(DOCS_DIR)/options 282 | gawk ' 283 | BEGIN { RS=" |\\n" ; longest = length("version")} 284 | 285 | /./ { 286 | if (match($$0,/^\[?--([^][|[:space:]]+)(([|]-)(\S))?\]?$$/,ma)) 287 | { 288 | gsub(/[][]/,"",$$0) 289 | opt_name = ma[1] 290 | if (length(opt_name) > longest) 291 | longest = length(opt_name) 292 | options[opt_name]["long_name"] = opt_name 293 | if (ma[4] ~ /./) 294 | options[opt_name]["short_name"] = ma[4] 295 | } 296 | 297 | else if (match($$0,/^\[?-(\S)([|]--([^][:space:]]+))?\]?$$/,ma)) 298 | { 299 | gsub(/[][]/,"",$$0) 300 | opt_name = ma[1] 301 | if (ma[3] ~ /./) 302 | { 303 | opt_name = ma[3] 304 | options[opt_name]["short_name"] = ma[1] 305 | options[opt_name]["long_name"] = opt_name 306 | } 307 | else 308 | options[opt_name]["short_name"] = opt_name 309 | 310 | } 311 | 312 | # ignore "Args" prefixed with an asterisk (*) 313 | else if (opt_name in options && !("arg" in options[opt_name]) && $$0 ~ /^[^*]/) 314 | { 315 | 316 | if ($$0 ~ /^[[]/) 317 | options[opt_name]["suffix"] = "::" 318 | else 319 | options[opt_name]["suffix"] = ":" 320 | 321 | gsub(/[][]/,"",$$0) 322 | if (length($$0) > longest_arg) 323 | longest_arg = length($$0) 324 | options[opt_name]["arg"] = $$0 325 | } 326 | } 327 | 328 | END { 329 | 330 | # sort array in alphabetical order 331 | # https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html 332 | PROCINFO["sorted_in"] = "@ind_num_asc" 333 | 334 | for (o in options) 335 | { 336 | 337 | docfile = "$(DOCS_DIR)/options/" o 338 | docfile_fragment = "$(CACHE_DIR)/options/" o 339 | options_in_use = options_in_use " " o 340 | 341 | if(o ~ /./) 342 | { 343 | if ("short_name" in options[o]) 344 | { 345 | out = "-" options[o]["short_name"] 346 | if ("long_name" in options[o]) 347 | out = out ", " 348 | else 349 | out = out sprintf("%-" longest "s", " ") 350 | } 351 | else 352 | out = "" 353 | 354 | if ("long_name" in options[o]) { 355 | string_lenght = longest + ("short_name" in options[o] ? 0 : 4) 356 | out = out sprintf ("--%-" string_lenght "s", options[o]["long_name"]) 357 | } 358 | 359 | if ("arg" in options[o]) 360 | out = out sprintf (" %-" longest_arg "s", gensub (/\|/,"\\\\|","g",options[o]["arg"])) 361 | 362 | # 6 = -s, -- 363 | # longest = longest long option name 364 | # 1 space after longoption 365 | # longest_arg + space 366 | fragment_length = 6+longest+1+longest_arg 367 | out = sprintf ("%-" fragment_length "s | ", out) 368 | print out > docfile_fragment 369 | 370 | if (system("[ ! -f " docfile " ]") == 0) 371 | print "short description " > docfile 372 | } 373 | 374 | if ("long_name" in options[o]) 375 | { 376 | long_options = long_options "," options[o]["long_name"] 377 | if ("suffix" in options[o]) 378 | long_options = long_options options[o]["suffix"] 379 | } 380 | 381 | if ("short_name" in options[o]) 382 | { 383 | short_options = short_options "," options[o]["short_name"] 384 | if ("suffix" in options[o]) 385 | short_options = short_options options[o]["suffix"] 386 | } 387 | } 388 | 389 | print options_in_use > "$(CACHE_DIR)/options_in_use" 390 | 391 | print "" 392 | print "declare -A $(OPTIONS_ARRAY_NAME)" 393 | print "" 394 | print "options=$$(getopt \\" 395 | print " --name \"[ERROR]:" name "\" \\" 396 | if (short_options ~ /./) 397 | printf (" --options \"%s\" \\\n", gensub(/^,/,"",1,short_options)) 398 | printf (" --longoptions \"%s\" -- \"$$@\"\n", gensub(/^,/,"",1,long_options)) 399 | print ") || exit 98" 400 | print "" 401 | print "eval set -- \"$$options\"" 402 | print "unset -v options" 403 | print "" 404 | print "while true; do" 405 | print " case \"$$1\" in" 406 | printf (" --%-" longest+1 "s| -%s ) __print_help && exit ;;\n", "help", "h") 407 | printf (" --%-" longest+1 "s| -%s ) __print_version && exit ;;\n", "version", "v") 408 | for (o in options) 409 | { 410 | if (o !~ /^(version|help)$$/) 411 | { 412 | if ("long_name" in options[o]) 413 | printf (" --%-" longest+1 "s", options[o]["long_name"]) 414 | else 415 | printf ("%-" longest+7 "s", "") 416 | 417 | if ("short_name" in options[o]) 418 | printf ("%s -%s ", ("long_name" in options[o] ? "|" : " "), options[o]["short_name"]) 419 | else 420 | printf ("%s", " ") 421 | 422 | if ("suffix" in options[o]) 423 | { 424 | if (options[o]["suffix"] == "::") 425 | printf (") _o[%s]=$${2:-1} ; shift ;;\n", o) 426 | else 427 | printf (") _o[%s]=$$2 ; shift ;;\n", o) 428 | } 429 | else 430 | printf (") _o[%s]=1 ;;\n", o) 431 | } 432 | } 433 | 434 | print " -- ) shift ; break ;;" 435 | print " * ) break ;;" 436 | print " esac" 437 | print " shift" 438 | print "done" 439 | print "" 440 | } 441 | ' $(OPTIONS_FILE) \ 442 | cache=$(CACHE_DIR) \ 443 | name=$(NAME) > $(getopt) 444 | 445 | $(CACHE_DIR)/copyright.txt: $(config_mak) 446 | @$(info making $@) 447 | year_created=$(CREATED) year_created=$${year_created%%-*} 448 | year_updated=$$(date +'%Y') 449 | author="$(AUTHOR)" org=$(ORGANISATION) 450 | 451 | copy_text="Copyright (c) " 452 | 453 | ((year_created == year_updated)) \ 454 | && copy_text+=$$year_created \ 455 | || copy_text+="$${year_created}-$${year_updated}" 456 | 457 | [[ $$author ]] && copy_text+=", $$author" 458 | [[ $$org ]] && copy_text+=" of $$org " 459 | 460 | printf '%s\n' \ 461 | "$$copy_text" "SPDX-License-Identifier: $(LICENSE)" > $@ 462 | 463 | .PHONY: check 464 | check: all 465 | shellcheck $(MONOLITH) 466 | 467 | 468 | 469 | 470 | other_maks := $(filter-out $(config_mak),$(wildcard *.mak)) 471 | -include $(other_maks) 472 | 473 | # by having all: last, it is possible to add CUSTOM_TARGETS 474 | # in 'other_maks', and have them automatically apply 475 | all: $(CUSTOM_TARGETS) $(MONOLITH) $(BASE) 476 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020,2023 budRich 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vivaldi-autoinject-custom-js-ui 2 | 3 | To manually add custom javascript modifications to 4 | the **vivaldi** web browser one needs to do the 5 | following: 6 | 7 | - Add the javascript file to vivaldis resource directory (on arch this is `/opt/vivaldi/resources/vivaldi`) 8 | - Add an entry in the window.html (pre vivaldi 6.2: browser.html) file in the same directory. 9 | 10 | This is not too complicated, but I have noticed 11 | that when **vivaldi** is being updated, the 12 | `window.html` file is overwritten, meaning that 13 | step 2 needs to be repeated after every update. 14 | 15 | It also gets a bit messy to manage multiple mods. 16 | 17 | If `vivaldi-autoinject-custom-js-ui` is launched 18 | without any command line arguments, it will update 19 | the `window.html` file to include all javascript 20 | files located in `PREFIX/share/vivaldi-UI-js`, 21 | (*PREFIX defaults to:* `/usr`). The 22 | **vivaldi-UI-js/** directory is automatically 23 | created by the script when new mods are added. 24 | 25 | Any files with `.js` extension passed as arguments 26 | will get added or updated. 27 | 28 | ## installation 29 | 30 | If you use **Arch Linux** you can get 31 | **vivaldi-autoinject-custom-js-ui** from 32 | [AUR](https://aur.archlinux.org/packages/vivaldi-autoinject-custom-js-ui/). 33 | 34 | The AUR package will also install a pacman hook that 35 | will execute the script whenever vivaldi is updated. 36 | 37 | --- 38 | 39 | 40 | Use the Makefile to do a systemwide installation 41 | of both the script and the manpage. 42 | 43 | (*configure the installation destination in the Makefile, if needed*) 44 | 45 | By default the generated and installed script will have 46 | the shbang: `#!/bin/bash` , this can be configured by 47 | using the `SHBANG` make macro. ( `make SHBANG='#!/usr/bin/env bash'` ) 48 | 49 | ``` 50 | $ git clone https://github.com/budlabs/vivaldi-autoinject-custom-js-ui.git 51 | $ cd vivaldi-autoinject-custom-js-ui 52 | # make install 53 | $ vivaldi-autoinject-custom-js-ui -v 54 | vivaldi-autoinject-custom-js-ui - version: 2020.11.22.7 55 | updated: 2020-11-22 by budRich 56 | ``` 57 | 58 | ## usage 59 | ``` 60 | vivaldi-autoinject-custom-js-ui [OPTIONS] [FILE...] 61 | -h, --help | Show help and exit 62 | -l, --list | Prints all installed js modifications 63 | -r, --remove FILENAME | Remove FILENAME 64 | -v, --version | Show version and exit 65 | ``` 66 | -------------------------------------------------------------------------------- /config.mak: -------------------------------------------------------------------------------- 1 | NAME := vivaldi-autoinject-custom-js-ui 2 | VERSION := 2023.09.05.1 3 | UPDATED := 2023-09-05 4 | CREATED := 2020-11-21 5 | AUTHOR := budRich 6 | CONTACT := github.com/budlabs/vivaldi-autoinject-custom-js-ui 7 | USAGE := vivaldi-autoinject-custom-js-ui [OPTIONS] [FILE...] 8 | DESCRIPTION := manage custom js UI mods for the vivaldi web browser 9 | ORGANISATION := budlabs 10 | LICENSE := BSD-2-Clause 11 | MONOLITH := _$(NAME) 12 | 13 | .PHONY: install uninstall manpage readme 14 | 15 | MANPAGE_DEPS = \ 16 | $(CACHE_DIR)/help_table.txt \ 17 | $(DOCS_DIR)/description.md \ 18 | $(CACHE_DIR)/copyright.txt 19 | 20 | manpage_section = 1 21 | MANPAGE = $(NAME).$(manpage_section) 22 | 23 | manpage: $(MANPAGE) 24 | readme: README.md 25 | 26 | $(MANPAGE): config.mak $(MANPAGE_DEPS) 27 | @$(info making $@) 28 | uppercase_name=$(NAME) 29 | uppercase_name=$${uppercase_name^^} 30 | { 31 | # this first "

" adds "corner" info to the manpage 32 | echo "# $$uppercase_name " \ 33 | "$(manpage_section) $(UPDATED)" \ 34 | "$(ORGANISATION) \"User Manuals\"" 35 | 36 | # main sections (NAME|OPTIONS..) should be "

" (##), sub (###) ... 37 | printf '%s\n' '## NAME' \ 38 | '$(NAME) - $(DESCRIPTION)' 39 | 40 | echo "## USAGE" 41 | echo '`$(USAGE)` ' 42 | cat $(DOCS_DIR)/description.md 43 | echo "## OPTIONS" 44 | sed 's/^/ /g' $(CACHE_DIR)/help_table.txt 45 | 46 | printf '%s\n' '## CONTACT' \ 47 | "Send bugs and feature requests to: " "$(CONTACT)/issues" 48 | 49 | printf '%s\n' '## COPYRIGHT' 50 | cat $(CACHE_DIR)/copyright.txt 51 | 52 | } | go-md2man > $@ 53 | 54 | README_DEPS = \ 55 | $(CACHE_DIR)/help_table.txt \ 56 | $(DOCS_DIR)/readme_installation.md \ 57 | $(DOCS_DIR)/description.md 58 | 59 | README.md: $(README_DEPS) 60 | @$(making $@) 61 | { 62 | echo "# $(NAME)" 63 | cat $(DOCS_DIR)/description.md 64 | echo "## installation" 65 | cat $(DOCS_DIR)/readme_installation.md 66 | echo "## usage" 67 | echo '```' 68 | echo '$(USAGE)' 69 | cat "$(CACHE_DIR)/help_table.txt" 70 | echo '```' 71 | } > $@ 72 | 73 | installed_manpage := \ 74 | $(DESTDIR)$(PREFIX)/share/man/man$(manpage_section)/$(MANPAGE) 75 | 76 | $(CACHE_DIR)/_$(NAME).out: $(MONOLITH) 77 | m4 -DPREFIX=$(PREFIX) $< >$@ 78 | 79 | install: $(CACHE_DIR)/_$(NAME).out $(MANPAGE) 80 | install -Dm755 $(CACHE_DIR)/_$(NAME).out $(DESTDIR)$(PREFIX)/bin/$(NAME) 81 | install -Dm644 $(MANPAGE) $(installed_manpage) 82 | 83 | uninstall: 84 | [[ -f $(DESTDIR)$(PREFIX)/bin/$(NAME) ]] && rm $(DESTDIR)$(PREFIX)/bin/$(NAME) 85 | [[ -f $(installed_manpage) ]] && rm $(installed_manpage) 86 | -------------------------------------------------------------------------------- /docs/description.md: -------------------------------------------------------------------------------- 1 | 2 | To manually add custom javascript modifications to 3 | the **vivaldi** web browser one needs to do the 4 | following: 5 | 6 | - Add the javascript file to vivaldis resource directory (on arch this is `/opt/vivaldi/resources/vivaldi`) 7 | - Add an entry in the window.html (pre vivaldi 6.2: browser.html) file in the same directory. 8 | 9 | This is not too complicated, but I have noticed 10 | that when **vivaldi** is being updated, the 11 | `window.html` file is overwritten, meaning that 12 | step 2 needs to be repeated after every update. 13 | 14 | It also gets a bit messy to manage multiple mods. 15 | 16 | If `vivaldi-autoinject-custom-js-ui` is launched 17 | without any command line arguments, it will update 18 | the `window.html` file to include all javascript 19 | files located in `PREFIX/share/vivaldi-UI-js`, 20 | (*PREFIX defaults to:* `/usr`). The 21 | **vivaldi-UI-js/** directory is automatically 22 | created by the script when new mods are added. 23 | 24 | Any files with `.js` extension passed as arguments 25 | will get added or updated. 26 | 27 | -------------------------------------------------------------------------------- /docs/options/help: -------------------------------------------------------------------------------- 1 | Show help and exit 2 | -------------------------------------------------------------------------------- /docs/options/list: -------------------------------------------------------------------------------- 1 | Prints all installed js modifications 2 | -------------------------------------------------------------------------------- /docs/options/remove: -------------------------------------------------------------------------------- 1 | Remove FILENAME 2 | -------------------------------------------------------------------------------- /docs/options/version: -------------------------------------------------------------------------------- 1 | Show version and exit 2 | -------------------------------------------------------------------------------- /docs/readme_installation.md: -------------------------------------------------------------------------------- 1 | 2 | If you use **Arch Linux** you can get 3 | **vivaldi-autoinject-custom-js-ui** from 4 | [AUR](https://aur.archlinux.org/packages/vivaldi-autoinject-custom-js-ui/). 5 | 6 | The AUR package will also install a pacman hook that 7 | will execute the script whenever vivaldi is updated. 8 | 9 | --- 10 | 11 | 12 | Use the Makefile to do a systemwide installation 13 | of both the script and the manpage. 14 | 15 | (*configure the installation destination in the Makefile, if needed*) 16 | 17 | By default the generated and installed script will have 18 | the shbang: `#!/bin/bash` , this can be configured by 19 | using the `SHBANG` make macro. ( `make SHBANG='#!/usr/bin/env bash'` ) 20 | 21 | ``` 22 | $ git clone https://github.com/budlabs/vivaldi-autoinject-custom-js-ui.git 23 | $ cd vivaldi-autoinject-custom-js-ui 24 | # make install 25 | $ vivaldi-autoinject-custom-js-ui -v 26 | vivaldi-autoinject-custom-js-ui - version: 2020.11.22.7 27 | updated: 2020-11-22 by budRich 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /docs/releasenotes/0_next.md: -------------------------------------------------------------------------------- 1 | ### 2023.09.02 2 | 3 | The arch pacman hookfile is not part of this 4 | repository anymore, it is instead included in the AUR 5 | package. One major benefit with this is that Arch users 6 | installing from aur, will also have the hook removed 7 | if they uninstall the package. It also actually fixes 8 | an issue for everyone #1 . 9 | 10 | Vivaldi have changed the name of the file that we needed 11 | to modify, from browser.html -> window.html . A test 12 | checking the version of vivaldi is now performed 13 | to correctly predict the name of the file to be modified. 14 | 15 | This release is also a rewrite and reorganisation of the 16 | code, previously development happened on the "dev" branch 17 | and required a not available build system. Now the "next" branch, 18 | which is also the default, is where development happens, 19 | and "master" is on the commit where releases happens. 20 | 21 | Thanks to @pncolvr and @coordinatio for helping out with this 22 | release! 23 | -------------------------------------------------------------------------------- /docs/releasenotes/2020.11.22.md: -------------------------------------------------------------------------------- 1 | #### 2020.11.22 2 | 3 | initial release 4 | -------------------------------------------------------------------------------- /func/ERR.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -E 4 | trap '[ "$?" -ne 98 ] || exit 98' ERR 5 | 6 | ERX() { >&2 echo "[ERROR] $*" ; exit 98 ;} 7 | # ERR() { >&2 echo "[WARNING] $*" ;} 8 | # ERM() { >&2 echo "$*" ;} 9 | -------------------------------------------------------------------------------- /func/addfiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | addfiles() { 4 | 5 | declare -a files 6 | 7 | # make sure all files to add have .js suffix 8 | for f in "$@" "$_data_directory"/*.js ; do 9 | [[ -f $f && $f =~ [.]js$ ]] && files+=("$f") 10 | done 11 | 12 | ((${#files[@]})) || ERX \ 13 | "could not find any js files to inject." \ 14 | "add files to $_data_directory" \ 15 | "or as arguments to this command" 16 | 17 | mkdir -p "$_data_directory" 18 | 19 | for f in "${files[@]}"; do 20 | printf -v str '' "${f##*/}" 21 | cp -f "$f" "$_browser_html" 22 | 23 | # files passed as arguments overwrites existing 24 | # files in /usr/share/vivaldi-UI-js 25 | [[ $f = "$_data_directory/${f##*/}" ]] \ 26 | || cp -f "$f" "$_data_directory" 27 | 28 | # adds entry in browser.html if it doesn't exist 29 | grep "$str" "$_tmp" >/dev/null \ 30 | || sed -ri "s|([[:space:]]*)()|\1\1$str\n\1\2|" "$_tmp" 31 | done 32 | } 33 | -------------------------------------------------------------------------------- /func/removefile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | removefile() { 4 | 5 | local trg=${1##*/} 6 | local sharef="$_data_directory/$trg" 7 | local optf="$_vivaldi_directory/$trg" 8 | local str 9 | 10 | [[ -f $sharef ]] || ERX "file $sharef not found" 11 | 12 | rm -f "$sharef" "$optf" 13 | 14 | printf -v str '' "$trg" 15 | 16 | grep -v "$str" "$_browser_html" > "$_tmp" 17 | } 18 | -------------------------------------------------------------------------------- /options: -------------------------------------------------------------------------------- 1 | [FILES ...] 2 | [--remove|-r FILENAME] 3 | --list|-l 4 | --help|-h 5 | --version|-v 6 | -------------------------------------------------------------------------------- /vivaldi-autoinject-custom-js-ui: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | main() { 4 | 5 | # in makefile m4 will expand PREFIX 6 | # before installation 7 | if [[ -d PREFIX ]] 8 | then _prefix='PREFIX' 9 | else _prefix=/usr 10 | fi 11 | 12 | _data_directory=$_prefix/share/vivaldi-UI-js 13 | 14 | if [[ ${_o[list]} && -d $_data_directory ]]; then 15 | ls -A "$_data_directory" 16 | exit 17 | elif ((EUID)); then 18 | ERX "script needs to be executed as root (sudo)" 19 | fi 20 | 21 | : "${_vivaldi:=$(realpath "$(command -v vivaldi-stable)")}" 22 | : "${_vivaldi:=$(realpath "$(command -v vivaldi-snapshot)")}" 23 | : "${_vivaldi:=$(realpath "$(command -v vivaldi)")}" 24 | 25 | [[ $_vivaldi ]] || ERX "could not find vivaldi, is it installed?" 26 | _vivaldi_directory=${_vivaldi%/*}/resources/vivaldi 27 | 28 | _vivaldi_version=$("$_vivaldi" --version 2>/dev/null) 29 | IFS=. read -rs major minor _ <<< "${_vivaldi_version//[^0-9.]/}" 30 | 31 | if ((major >= 6 && minor >= 2)) 32 | then _browser_html=$_vivaldi_directory/window.html 33 | else _browser_html=$_vivaldi_directory/browser.html 34 | fi 35 | 36 | unset _vivaldi_version major minor 37 | 38 | [[ -f $_browser_html ]] || ERX \ 39 | "could not find $_browser_html, is vivaldi installed?" 40 | 41 | _tmp=$(mktemp) 42 | trap 'rm -f "$_tmp"' EXIT SIGINT 43 | 44 | cp -f "$_browser_html" "$_tmp" 45 | 46 | if [[ -n ${_o[remove]} ]] 47 | then removefile "${_o[remove]}" 48 | else addfiles "$@" 49 | fi 50 | 51 | cp -f "$_tmp" "$_browser_html" 52 | 53 | exit 0 54 | } 55 | 56 | __dir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")") #bashbud 57 | source "$__dir/_init.sh" #bashbud 58 | -------------------------------------------------------------------------------- /vivaldi-autoinject-custom-js-ui.1: -------------------------------------------------------------------------------- 1 | .nh 2 | .TH VIVALDI-AUTOINJECT-CUSTOM-JS-UI 1 2023-09-03 budlabs "User Manuals" 3 | .SH NAME 4 | .PP 5 | vivaldi-autoinject-custom-js-ui - manage custom js UI mods for the vivaldi web browser 6 | 7 | .SH USAGE 8 | .PP 9 | \fB\fCvivaldi-autoinject-custom-js-ui [OPTIONS] [FILE...]\fR 10 | 11 | .PP 12 | To manually add custom javascript modifications to 13 | the \fBvivaldi\fP web browser one needs to do the 14 | following: 15 | 16 | .RS 17 | .IP \(bu 2 18 | Add the javascript file to vivaldis resource directory (on arch this is \fB\fC/opt/vivaldi/resources/vivaldi\fR) 19 | .IP \(bu 2 20 | Add an entry in the window.html (pre vivaldi 6.2: browser.html) file in the same directory. 21 | 22 | .RE 23 | 24 | .PP 25 | This is not too complicated, but I have noticed 26 | that when \fBvivaldi\fP is being updated, the 27 | \fB\fCwindow.html\fR file is overwritten, meaning that 28 | step 2 needs to be repeated after every update. 29 | 30 | .PP 31 | It also gets a bit messy to manage multiple mods. 32 | 33 | .PP 34 | If \fB\fCvivaldi-autoinject-custom-js-ui\fR is launched 35 | without any command line arguments, it will update 36 | the \fB\fCwindow.html\fR file to include all javascript 37 | files located in \fB\fCPREFIX/share/vivaldi-UI-js\fR, 38 | (\fIPREFIX defaults to:\fP \fB\fC/usr\fR). The 39 | \fBvivaldi-UI-js/\fP directory is automatically 40 | created by the script when new mods are added. 41 | 42 | .PP 43 | Any files with \fB\fC\&.js\fR extension passed as arguments 44 | will get added or updated. 45 | 46 | .SH OPTIONS 47 | .PP 48 | .RS 49 | 50 | .nf 51 | -h, --help | Show help and exit 52 | -l, --list | Prints all installed js modifications 53 | -r, --remove FILENAME | Remove FILENAME 54 | -v, --version | Show version and exit 55 | 56 | .fi 57 | .RE 58 | 59 | .SH CONTACT 60 | .PP 61 | Send bugs and feature requests to: 62 | .br 63 | github.com/budlabs/vivaldi-autoinject-custom-js-ui/issues 64 | 65 | .SH COPYRIGHT 66 | .PP 67 | Copyright (c) 2020-2023, budRich of budlabs 68 | .br 69 | SPDX-License-Identifier: BSD-2-Clause 70 | --------------------------------------------------------------------------------