aboutsummaryrefslogtreecommitdiff
path: root/lib_build.sh
diff options
context:
space:
mode:
Diffstat (limited to 'lib_build.sh')
-rwxr-xr-xlib_build.sh300
1 files changed, 300 insertions, 0 deletions
diff --git a/lib_build.sh b/lib_build.sh
new file mode 100755
index 0000000..c808f03
--- /dev/null
+++ b/lib_build.sh
@@ -0,0 +1,300 @@
+#!/bin/sh
+
+# Copyright (C) 2021 Wojtek Kosior
+# Redistribution terms are gathered in the `copyright' file.
+
+. ./shell_utils.sh
+
+handle_export_line() {
+ if [ "x$1" = "xEXPORTS_START" ]; then
+ if [ "$STATE" = "before_block" ]; then
+ STATE="in_block"
+ fi
+ elif [ "x$1" = "xEXPORT" ]; then
+ if [ "$STATE" != "in_block" ]; then
+ return
+ fi
+
+ EXPORTCODE="${EXPORTCODE}window.killtheweb.$2 = $2;$ENDL"
+
+ PREVIOUS_FILE="$(map_get EXPORTS $2)"
+ if [ "x$PREVIOUS_FILE" != "x" ]; then
+ errcho "export $2 present in both $PREVIOUS_FILE and $FILE"
+ return 1
+ fi
+
+ map_set_instr EXPORTS $2 "$FILE"
+
+ elif [ "x$1" = "xEXPORTS_END" ]; then
+ if [ "$STATE" = "in_block" ]; then
+ STATE="after_block"
+ fi
+ fi
+}
+
+translate_exports() {
+ STATE="before_block"
+ EXPORTCODE=''
+
+ while read EXPORT_LINE; do
+ handle_export_line $EXPORT_LINE || return 1
+ done
+
+ map_set_instr EXPORTCODES $FILEKEY "$EXPORTCODE"
+}
+
+add_exports() {
+ FILE="$1"
+ FILEKEY="$(sanitize "$FILE")"
+
+ eval "$(grep -o 'EXPORT.\+' "$1" | translate_exports || exit 1)"
+}
+
+handle_import_line() {
+ if [ "x$1" = "xIMPORTS_START" ]; then
+ if [ "$STATE" = "before_block" ]; then
+ STATE="in_block"
+ fi
+ elif [ "x$1" = "xIMPORT" ]; then
+ if [ "$STATE" != "in_block" ]; then
+ return
+ fi
+
+ IMPORTCODE="${IMPORTCODE}const $2 = window.killtheweb.$2;$ENDL"
+
+ IMPORTS="$IMPORTS $2"
+
+ elif [ "x$1" = "xIMPORTS_END" ]; then
+ if [ "$STATE" = "in_block" ]; then
+ STATE="after_block"
+ fi
+ fi
+}
+
+translate_imports() {
+ STATE="before_block"
+ IMPORTCODE=''
+ IMPORTS=''
+
+ while read IMPORT_LINE; do
+ handle_import_line $IMPORT_LINE || return 1
+ done
+
+ map_set_instr IMPORTCODES $FILEKEY "$IMPORTCODE"
+ map_set_instr IMPORTS $FILEKEY "$IMPORTS"
+}
+
+add_imports() {
+ FILE="$1"
+ FILEKEY="$(sanitize "$FILE")"
+
+ eval "$(grep -o 'IMPORT.\+' "$1" | translate_imports || exit 1)"
+}
+
+compute_scripts_list_rec() {
+ local FILE="$1"
+ local FILEKEY=$(sanitize "$1")
+
+ local FILESTATE="$(map_get FILESTATES $FILEKEY)"
+ if [ "xprocessed" = "x$FILESTATE" ]; then
+ return
+ fi
+ if [ "xprocessing" = "x$FILESTATE" ]; then
+ errcho "import loop on $FILE"
+ return 1
+ fi
+
+ USED="$USED $FILEKEY"
+
+ map_set FILESTATES $FILEKEY "processing"
+
+ local IMPORT
+ for IMPORT in $(map_get IMPORTS $FILEKEY); do
+ NEXT_FILE="$(map_get EXPORTS $IMPORT)"
+ if [ "x" = "x$NEXT_FILE" ]; then
+ errcho "nothing exports $IMPORT, required by $FILE"
+ return 1
+ fi
+ if ! compute_scripts_list_rec "$NEXT_FILE"; then
+ errcho "when satisfying $IMPORT for $FILE"
+ return 1
+ fi
+ done
+
+ [ "x$FILE" = "xexports_init.js" ] || echo $FILE # exports_init.js is hardcoded to load first; the entire export system depends on it
+ map_set FILESTATES $FILEKEY "processed"
+}
+
+compute_scripts_list() {
+ USED=''
+ echo COMPUTED_SCRIPTS=\"exports_init.js
+ compute_scripts_list_rec "$1"
+ echo \"
+
+ for FILEKEY in $USED; do
+ map_set_instr USED $FILEKEY yes
+ done
+}
+
+as_json_list() {
+ while true; do
+ if [ "x" = "x$2" ]; then
+ echo -n '\\n'"\t\t\"$1\""'\\n\t'
+ return
+ fi
+ echo -n '\\n'"\t\t\"$1\","
+ shift
+ done
+}
+
+as_html_list() {
+ while [ "x" != "x$1" ]; do
+ echo -n '\\n'" <script src=\"/$1\"></script>"
+ shift
+ done
+}
+
+main() {
+ # placate importers of these, as they are exported by the yet-to-be-created exports_init.js
+ EXPORTS__browser=exports_init.js
+ EXPORTS__is_chrome=exports_init.js
+ EXPORTS__is_mozilla=exports_init.js
+
+ SCRIPTDIRS='background html common content'
+
+ SCRIPTS=$(find $SCRIPTDIRS -name '[^.#]*.js')
+
+ for SCRIPT in $SCRIPTS; do
+ add_exports $SCRIPT
+ add_imports $SCRIPT
+ done
+
+ eval "$(compute_scripts_list background/main.js || exit 1)"
+ BGSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
+ eval "$(compute_scripts_list content/main.js || exit 1)"
+ CONTENTSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
+ eval "$(compute_scripts_list html/display-panel.js || exit 1)"
+ POPUPSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
+ eval "$(compute_scripts_list html/options_main.js || exit 1)"
+ OPTIONSSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
+
+ rm -rf $BUILDDIR
+ mkdir $BUILDDIR
+ for DIR in $(find $SCRIPTDIRS -type d); do
+ mkdir -p $BUILDDIR/$DIR
+ done
+
+ CHROMIUM_KEY=''
+ GECKO_APPLICATIONS=''
+
+ if [ "$BROWSER" = "chromium" ]; then
+ CHROMIUM_KEY="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64)"
+ CHROMIUM_KEY=$(echo chromium-key-dummy-file-$CHROMIUM_KEY | tr / -)
+ touch $BUILDDIR/$CHROMIUM_KEY
+
+ CHROMIUM_KEY="\n\
+ // WARNING!!!\n\
+ // EACH USER SHOULD REPLACE DUMMY FILE's VALUE WITH A UNIQUE ONE!!!\n\
+ // OTHERWISE, SECURITY CAN BE TRIVIALLY COMPROMISED!\n\
+ // Only relevant to users of chrome-based browsers.\n\
+ // Users of Firefox forks are safe.\n\
+ \"$CHROMIUM_KEY\"\
+"
+ else
+ GECKO_APPLICATIONS="\n\
+ \"applications\": {\n\
+ \"gecko\": {\n\
+ \"id\": \"{6fe13369-88e9-440f-b837-5012fb3bedec}\",\n\
+ \"strict_min_version\": \"60.0\"\n\
+ }\n\
+ },"
+ fi
+
+ sed "\
+s^_GECKO_APPLICATIONS_^$GECKO_APPLICATIONS^
+s^_CHROMIUM_KEY_^$CHROMIUM_KEY^
+s^_BGSCRIPTS_^$BGSCRIPTS^
+s^_CONTENTSCRIPTS_^$CONTENTSCRIPTS^" \
+ < manifest.json > $BUILDDIR/manifest.json
+
+ ./process_html_file.sh html/display-panel.html |
+ sed "s^_POPUPSCRIPTS_^$POPUPSCRIPTS^" \
+ > $BUILDDIR/html/display-panel.html
+
+ ./process_html_file.sh html/options.html |
+ sed "s^_OPTIONSSCRIPTS_^$OPTIONSSCRIPTS^" \
+ > $BUILDDIR/html/options.html
+
+ for FILE in $SCRIPTS; do
+ FILEKEY=$(sanitize "$FILE")
+ if [ "xyes" != "x$(map_get USED $FILEKEY)" ]; then
+ errcho "WARNING! $FILE not used"
+ else
+ (echo "\
+\"use strict\";
+
+({fun: (function() {
+$(map_get IMPORTCODES $FILEKEY)
+
+";
+
+# A hack to insert the contents of default_settings.json at the appropriate location in background/main.js
+if [ "$FILE" = "background/main.js" ]; then
+ # Uses an internal sed expression to escape and indent the JSON file for use in the external sed expression
+ sed 's/^ `DEFAULT SETTINGS`$/'"$(sed -E 's/([\\\&\/])/\\\1/g; s/^/ /; s/$/\\/' < default_settings.json) "/g < "$FILE"
+else
+ cat $FILE
+fi
+
+echo "
+
+$(map_get EXPORTCODES $FILEKEY)
+})}).fun();") > $BUILDDIR/$FILE
+ fi
+ done
+
+ if [ "$BROWSER" = "chromium" ]; then
+ cat > $BUILDDIR/exports_init.js <<EOF
+window.killtheweb={is_chrome: true, browser: window.chrome};
+EOF
+ else
+ cat > $BUILDDIR/exports_init.js <<EOF
+/* Polyfill for IceCat 60. */
+String.prototype.matchAll = String.prototype.matchAll || function(regex) {
+ if (regex.flags.search("g") === -1)
+ throw new TypeError("String.prototype.matchAll called with a non-global RegExp argument");
+
+ for (const matches = [];;) {
+ if (matches[matches.push(regex.exec(this)) - 1] === null)
+ return matches.splice(0, matches.length - 1);
+ }
+}
+
+window.killtheweb={is_mozilla: true, browser: this.browser};
+EOF
+ fi
+
+ cp -r copyright licenses/ $BUILDDIR
+ cp html/*.css $BUILDDIR/html
+ mkdir $BUILDDIR/icons
+ cp icons/*.png $BUILDDIR/icons
+
+ if [ "$BROWSER" = "chromium" ]; then
+ for MOZILLA_FILE in $(find $BUILDDIR -name "MOZILLA_*"); do
+ echo > "$MOZILLA_FILE"
+ done
+ fi
+ if [ "$BROWSER" = "mozilla" ]; then
+ for CHROMIUM_FILE in $(find $BUILDDIR -name "CHROMIUM_*"); do
+ echo > "$CHROMIUM_FILE"
+ done
+ fi
+}
+
+make_zip() (
+ cd "$BUILDDIR"
+ case $BROWSER in
+ mozilla) $ZIP_COMMAND build.zip *;;
+ chromium) exit 92;; # Still to do
+ esac
+)