diff --git a/README.md b/README.md index 7d6870e..60d979a 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,80 @@ - ![Add-on icon](misc/spot64.png) Enlight -======================================== + ![Add-on icon](icons/spot64.png) Enlight +========================================= -Firefox add-on providing syntax highlighting for raw code, based on the -highlight.js project. +Enlight is a Firefox add-on providing syntax highlighting for raw source code +files, based on the highlight.js project. -Syntax highlighting relies on highlight.js project (see [project -homepage][hljs]. Currently packaged with the add-on is the version +Syntax highlighting relies on the highlight.js library (see [project +homepage][hljs]). Currently packaged with the add-on is the version 9.12.0 of highlight.js, which provides 78 color themes and syntax for 175 languages. ## Install -\>>> [Get it from Mozilla add-ons platform][amo]. <<< +▶▶▶ [Get it from Mozilla add-ons platform][amo]! ◀◀◀ As a general rule, it is no longer possible to manually install the version provided here with the vanilla Firefox release. See [Mozilla policy on add-ons -signature][signing] for details. On some specific Firefox versions where add-on +signature][policy] for details. On some specific Firefox versions where add-on signing has been disabled (_Developer Edition_ or _Nightly_ with the option manually deactivated, or on special stable releases), it may be possible to use -a version of the add-on coming from this repository. +a version of the add-on coming from this repository ([see also Mozilla's +wiki][signing]). -If you run one of those specific versions: just open the -`enlight_highlightjs@jetpack-.xpi` file (`File->Open`) in Firefox. -Confirm you want to install, and you're done. +If you run one of those specific versions and want to run or build the add-on, +use the [web-ext tool][webext-start]. To test it with a temporary Firefox +profile, use: -To build the add-on, one needs the `jpm` tool ([documentation][jpm]). If you -wish to build from sources, the `xpi` add-on file itself can easily be -generated with a `jpm xpi` command from the Mozilla add-on SDK (see -[documentation on MDN][sdk]). + web-ext run -Building with `cfx` is no longer supported. I intend to work on a version based -on WebExtensions, … when I can find some spare time! +Or to compile an add-on `.xpi` file, use instead: + + web-ext build + +See the [documentation for web-ext tool][webext-ref] if you need more +information about the available commands and options. + +Building with `cfx` or `jpm` (used for older versions) is no longer supported. ## Usage ### Basics -On install, a new button with a ~~spotlight~~ light bulb -![buttonOff](data/lightbulb_off-32.png) (yes, it's supposed to be a -~~spotlight~~ light bulb − but the magnificent spotlight remains the add-on -icon in the add-on manager tab for now) should appear in Firefox toolbar. +On install, a new button with a light bulb +![button](icons/lightbulb-dark-19x32.png) should appear in Firefox toolbar. To highlight raw source code in the active tab, click on this button and select the language syntax you want to use (or “Autodetect” for automatic detection). -If you want to undo highlighting, just click again on the button -![buttonOn](data/lightbulb_on-32.png) (reloading the page also works). +If you want to undo highlighting, just click again on the button. Reloading the +page also works. ### Options You can also customize some options through Firefox add-on manager tab: + * Color theme selection (_default: Solarized Dark_): change the CSS theme in use for syntax highlight. * Automatic highlighting (_default: off_): check it to automatically trigger syntax highlighting for all plain text files. -* Alternate icon set (_default: off_): use white icons; useful if you use a - dark theme for Firefox, such as the default theme for Developer Edition -* Adapt background body color (_default: on_): remove white border due to - body background color. There is no reason to deactivate this, unless you try - to highlight non-plain text pages and get strange background modification. * Add line numbers (_default: off_): add line numbers on the left of file content. Line numbers are created with CSS and are not part of the file contents. -When line numbering is enabled, it is possible to jump to line passed through -URL (_default: on_): scroll to e.g. line 27 and select it if a suffix such as +When line numbering is enabled, it is possible to jump to the line passed +through URL: e.g. scroll to line 27 and select it if a suffix such as `#Line27` or `#line27` or `#L27` or `#l27` is appended to the URL **before** the script loads (this does not relies on HTML anchors and cannot be triggered -by simple URL modification; reload the script for current page if you added the -suffix afterward). +by simple URL modification; reload syntax highlighting for current page if you +added the suffix afterward). + +### New languages, color schemes + +Enlight relies on highlight.js library for coloring the code. It does not +modify this library, nor does it add support for additional languages or color +schemes. Therefore, fixes for language syntax and auto-detection accuracy, +suggestions or contributions to new languages and styles should be addressed to +the [highlight.js project community][hljs]. ## License @@ -82,15 +88,16 @@ for details). ## Miscellaneous Other than on the [hilight.js homesite][hljs], you can find a list of supported -languages in [data/languages-all.json][languages], and of available color schemes in -[package.json][package]. +languages in [data/languages-all.json][languages], and of available color +schemes in [package.json][package]. [hljs]: https://highlightjs.org -[signing]: https://blog.mozilla.org/addons/2015/02/10/extension-signing-safer-experience +[policy]: https://blog.mozilla.org/addons/2015/02/10/extension-signing-safer-experience +[signing]: https://wiki.mozilla.org/Add-ons/Extension_Signing [amo]: https://addons.mozilla.org/firefox/addon/enlight -[sdk]: https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Getting_started +[webext-start]: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext +[webext-ref]: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/web-ext_command_reference [mpl]: https://github.com/Qeole/Enlight/blob/master/LICENSE [bsd]: https://github.com/isagalaev/highlight.js/blob/master/LICENSE [languages]: https://github.com/Qeole/Enlight/blob/master/data/languages-all.json [package]: https://github.com/Qeole/Enlight/blob/master/package.json -[jpm]: https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm diff --git a/_locales/en/messages.json b/_locales/en/messages.json index ad5bf0f..37b0302 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1,31 +1,6 @@ -# Vim: set spelllang=en: - -# Metadata -# Currently in master branch of add-on SDK, but not in current stable v1.17 -addon_description = Syntax highlight for raw source code. - -# Preferences -style_title = Color theme -style_description = Select the color theme you want to use for syntax highlighting. -autohl_title = Auto-highlight source code files -autohl_description = Automatically apply highlighting to pages detected as source code (technically, detection occurs when HTML body contains a single child of name
).
-invert_title            = Alternate icon set
-invert_description      = Use white (instead of dark gray) icons for the button, for a better contrast on dark themes.
-bgColor_title           = Adapt body background color
-bgColor_description     = Make HTML body background color the same as background color for the code block. Should remove white border around highlighted code. Disable if you use the add-on on web pages other than plain text source code files.
-lineNumbers_title       = Add line numbering
-lineNumbers_description = Display line numbers on the left of highlighted content. When this option is enabled, one can also scroll to e.g. line 27 and select it if a suffix such as “#Line27” or “#line27” or “#L27” or “#l27” is appended to the URL BEFORE the script loads (this does not relies on HTML anchors and cannot be triggered by simple URL modification; reload the script for current page if you added the suffix afterward).
-
-# Button
-button_label      = Highlight raw source code
-
-# Language selection panel
-autodetect        = Auto-detect
-no_language       = None
-
-# Logs
-log_highlight     = Let's (try to) highlight code for language “%s” with style “%s”.
-log_undo          = Oh, well, let's get back to initial content.
-log_toggleoff     = Received toggle off request from content script for reason “%s”.
-log_toff_r1       = nothing to work on in this document
-log_toff_r2       = document is unloaded
+{
+    "description": {
+        "message": "Syntax highlighting for raw source code files.",
+        "description": "Description of the extension."
+    }
+}
diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json
index d623fad..81a242b 100644
--- a/_locales/fr/messages.json
+++ b/_locales/fr/messages.json
@@ -1,31 +1,6 @@
-# Vim: set spelllang=fr:
-
-# Métadata
-# Currently in master branch of add-on SDK, but not in current stable v1.17
-addon_description = Coloration syntaxique sur code source brut.
-
-# Préférences
-style_title             = Thème
-style_description       = Sélectionnez le jeu de couleurs à utiliser pour la coloration syntaxique.
-autohl_title            = Coloration automatique du code source
-autohl_description      = Lance automatiquement la coloration syntaxique à l'ouverture des pages détectées comme étant des fichiers sources (du point de vue technique, cette détection survient lorsque l'élément HTML body contient un unique nœud, de type 
).
-invert_title            = Icônes alternatives
-invert_description      = Utiliser des icônes blanches (plutôt que gris foncé) pour le bouton, pour un meilleur contraste sur un thème foncé.
-bgColor_title           = Adapter la couleur d'arrière-plan de l'élément body
-bgColor_description     = Étend la couleur d'arrière plan du bloc de code coloré à l'élément body du document HTML. Cela permet en principe de retirer la bordure blanche qui apparaît autour du bloc coloré. Désactivez cette option si vous utilisez cette extension pour des pages web autres que contenant seulement du code source au format texte.
-lineNumbers_title       = Numéroter les lignes
-lineNumbers_description = Affiche le numéro de chaque ligne à gauche du contenu coloré. Lorsque cette option est activée, il est possible de sauter à la ligne fournie, par exemple 27, et de la mettre en surbrillance si l'URL comporte un suffixe de la forme « #Line27 » ou « #line27 » ou « #L27 » ou « #l27 ». Ce suffixe doit être ajouté AVANT le chargement du script (la fonctionnalité ne repose pas sur les ancres HTML et ne peut pas détecter une simple modification de l'URL. Si le suffixe est ajouté après le chargement du script pour la page en cours, il suffit de recharger ce dernier).
-
-# Bouton
-button_label      = Coloration syntaxique de code
-
-# Panneau de sélection du langage
-autodetect        = Détection auto
-no_language       = Aucun
-
-# Logs
-log_highlight     = Essayons la coloration syntaxique pour le langage « %s » avec le thème « %s ».
-log_undo          = Retour au contenu initial du document.
-log_toggleoff     = Le script de contenu signale l'absence de coloration pour la raison « %s ».
-log_toff_r1       = aucun bloc sur lequel travailler dans ce document
-log_toff_r2       = le document est déchargé du navigateur
+{
+    "description": {
+        "message": "Coloration syntaxique pour code source brut.",
+        "description": "Description of the extension."
+    }
+}
diff --git a/icons/lightbulb-dark-19x32.png b/icons/lightbulb-dark-19x32.png
new file mode 100644
index 0000000..5916c66
Binary files /dev/null and b/icons/lightbulb-dark-19x32.png differ
diff --git a/icons/lightbulb-dark.svg b/icons/lightbulb-dark.svg
new file mode 100644
index 0000000..290371d
--- /dev/null
+++ b/icons/lightbulb-dark.svg
@@ -0,0 +1,76 @@
+
+
+
+
+  
+  
+  
+    
+      
+        image/svg+xml
+        
+        
+      
+    
+  
+  
+    
+  
+
diff --git a/icons/lightbulb-light.svg b/icons/lightbulb-light.svg
new file mode 100644
index 0000000..5fe9ac8
--- /dev/null
+++ b/icons/lightbulb-light.svg
@@ -0,0 +1,76 @@
+
+
+
+
+  
+  
+  
+    
+      
+        image/svg+xml
+        
+        
+      
+    
+  
+  
+    
+  
+
diff --git a/manifest.json b/manifest.json
index e5c136b..e9396b1 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,360 +1,49 @@
 {
-  "name": "enlight",
-  "title": "Enlight",
-  "id": "enlight_highlightjs@jetpack",
-  "author": "Qeole",
-  "homepage": "https://github.com/Qeole/Enlight",
-  "repository": "https://github.com/Qeole/Enlight",
-  "license": "MPL-2.0",
-  "version": "1.16.0",
-  "description": "Syntax highlight for raw source code.",
-  "permissions": {
-    "multiprocess": true
+
+  "manifest_version": 2,
+  "name": "Enlight",
+  "version": "2.0.9.12",
+  "homepage_url": "https://github.com/Qeole/Enlight",
+  "description": "__MSG_description__",
+  "default_locale": "en",
+  "icons": {
+    "64": "icons/spot64.png"
   },
-  "preferences": [
-  {
-    "name": "style",
-    "type": "menulist",
-    "title": "Color theme",
-    "value": "solarized-dark",
-    "options": [
-    {
-      "value": "agate",
-      "label": "Agate"
-    },
-    {
-      "value": "androidstudio",
-      "label": "Android Studio"
-    },
-    {
-      "value": "arduino-light",
-      "label": "Arduino Light"
-    },
-    {
-      "value": "arta",
-      "label": "Arta"
-    },
-    {
-      "value": "ascetic",
-      "label": "Ascetic"
-    },
-    {
-      "value": "atelier-cave-dark",
-      "label": "Atelier Cave Dark"
-    },
-    {
-      "value": "atelier-cave-light",
-      "label": "Atelier Cave Light"
-    },
-    {
-      "value": "atelier-dune-dark",
-      "label": "Atelier Dune Dark"
-    },
-    {
-      "value": "atelier-dune-light",
-      "label": "Atelier Dune Light"
-    },
-    {
-      "value": "atelier-estuary-dark",
-      "label": "Atelier Estuary Dark"
-    },
-    {
-      "value": "atelier-estuary-light",
-      "label": "Atelier Estuary Light"
-    },
-    {
-      "value": "atelier-forest-dark",
-      "label": "Atelier Forest Dark"
-    },
-    {
-      "value": "atelier-forest-light",
-      "label": "Atelier Forest Light"
-    },
-    {
-      "value": "atelier-heath-dark",
-      "label": "Atelier Heath Dark"
-    },
-    {
-      "value": "atelier-heath-light",
-      "label": "Atelier Heath Light"
-    },
-    {
-      "value": "atelier-lakeside-dark",
-      "label": "Atelier Lakeside Dark"
-    },
-    {
-      "value": "atelier-lakeside-light",
-      "label": "Atelier Lakeside Light"
-    },
-    {
-      "value": "atelier-plateau-dark",
-      "label": "Atelier Plateau Dark"
-    },
-    {
-      "value": "atelier-plateau-light",
-      "label": "Atelier Plateau Light"
-    },
-    {
-      "value": "atelier-savanna-dark",
-      "label": "Atelier Savanna Dark"
-    },
-    {
-      "value": "atelier-savanna-light",
-      "label": "Atelier Savanna Light"
-    },
-    {
-      "value": "atelier-seaside-dark",
-      "label": "Atelier Seaside Dark"
-    },
-    {
-      "value": "atelier-seaside-light",
-      "label": "Atelier Seaside Light"
-    },
-    {
-      "value": "atelier-sulphurpool-dark",
-      "label": "Atelier Sulphurpool Dark"
-    },
-    {
-      "value": "atelier-sulphurpool-light",
-      "label": "Atelier Sulphurpool Light"
-    },
-    {
-      "value": "atom-one-dark",
-      "label": "Atom One Dark"
-    },
-    {
-      "value": "atom-one-light",
-      "label": "Atom One Light"
-    },
-    {
-      "value": "brown-paper",
-      "label": "Brown Paper"
-    },
-    {
-      "value": "codepen-embed",
-      "label": "Codepen Embed"
-    },
-    {
-      "value": "color-brewer",
-      "label": "Color Brewer"
-    },
-    {
-      "value": "darcula",
-      "label": "Darcula"
-    },
-    {
-      "value": "dark",
-      "label": "Dark"
-    },
-    {
-      "value": "default",
-      "label": "Default"
-    },
-    {
-      "value": "docco",
-      "label": "Docco"
-    },
-    {
-      "value": "dracula",
-      "label": "Dracula"
-    },
-    {
-      "value": "far",
-      "label": "Far"
-    },
-    {
-      "value": "foundation",
-      "label": "Foundation"
-    },
-    {
-      "value": "github",
-      "label": "Github"
-    },
-    {
-      "value": "github-gist",
-      "label": "Github Gist"
-    },
-    {
-      "value": "googlecode",
-      "label": "Googlecode"
-    },
-    {
-      "value": "grayscale",
-      "label": "Grayscale"
-    },
-    {
-      "value": "gruvbox-dark",
-      "label": "Gruvbox Dark"
-    },
-    {
-      "value": "gruvbox-light",
-      "label": "Gruvbox Light"
-    },
-    {
-      "value": "hopscotch",
-      "label": "Hopscotch"
-    },
-    {
-      "value": "hybrid",
-      "label": "Hybrid"
-    },
-    {
-      "value": "idea",
-      "label": "Idea"
-    },
-    {
-      "value": "ir-black",
-      "label": "Ir Black"
-    },
-    {
-      "value": "kimbie-dark",
-      "label": "Kimbie Dark"
-    },
-    {
-      "value": "kimbie-light",
-      "label": "Kimbie Light"
-    },
-    {
-      "value": "magula",
-      "label": "Magula"
-    },
-    {
-      "value": "mono-blue",
-      "label": "Mono Blue"
-    },
-    {
-      "value": "monokai",
-      "label": "Monokai"
-    },
-    {
-      "value": "monokai-sublime",
-      "label": "Monokai Sublime"
-    },
-    {
-      "value": "obsidian",
-      "label": "Obsidian"
-    },
-    {
-      "value": "ocean",
-      "label": "Ocean Dark"
-    },
-    {
-      "value": "paraiso-dark",
-      "label": "Paraiso Dark"
-    },
-    {
-      "value": "paraiso-light",
-      "label": "Paraiso Light"
-    },
-    {
-      "value": "pojoaque",
-      "label": "Pojoaque"
-    },
-    {
-      "value": "purebasic",
-      "label": "PureBASIC"
-    },
-    {
-      "value": "qtcreator_dark",
-      "label": "Qt Creator Dark"
-    },
-    {
-      "value": "qtcreator_light",
-      "label": "Qt Creator Light"
-    },
-    {
-      "value": "railscasts",
-      "label": "Railscasts"
-    },
-    {
-      "value": "rainbow",
-      "label": "Rainbow"
-    },
-    {
-      "value": "routeros",
-      "label" : "RouterOS (MikroTik)"
-    },
-    {
-      "value": "school-book",
-      "label": "School Book"
-    },
-    {
-      "value": "solarized-dark",
-      "label": "Solarized Dark"
-    },
-    {
-      "value": "solarized-light",
-      "label": "Solarized Light"
-    },
-    {
-      "value": "sunburst",
-      "label": "Sunburst"
-    },
-    {
-      "value": "tomorrow",
-      "label": "Tomorrow"
-    },
-    {
-      "value": "tomorrow-night-blue",
-      "label": "Tomorrow Night Blue"
-    },
-    {
-      "value": "tomorrow-night-bright",
-      "label": "Tomorrow Night Bright"
-    },
-    {
-      "value": "tomorrow-night",
-      "label": "Tomorrow Night"
-    },
-    {
-      "value": "tomorrow-night-eighties",
-      "label": "Tomorrow Night Eighties"
-    },
-    {
-      "value": "vs",
-      "label": "VS"
-    },
-    {
-      "value": "vs2015",
-      "label": "VisualStudio 2015 Dark"
-    },
-    {
-      "value": "xcode",
-      "label": "XCode"
-    },
-    {
-      "value": "xt256",
-      "label": "xt256"
-    },
-    {
-      "value": "zenburn",
-      "label": "Zenburn"
-    }
+
+  "browser_action": {
+    "browser_style": true,
+    "default_title": "Enlight",
+    "default_popup": "popup/languages.html",
+    "theme_icons": [
+      {
+        "dark": "icons/lightbulb-dark.svg",
+        "light": "icons/lightbulb-light.svg",
+        "size": 64
+      }
     ]
   },
-  {
-    "name": "autohl",
-    "type": "bool",
-    "title": "Auto-highlight source code files",
-    "value": false
-  },
-  {
-    "name": "invert",
-    "type": "bool",
-    "title": "Alternate icon set",
-    "value": false
+
+  "background": {
+    "scripts": ["scripts/enlight-background.js"]
   },
-  {
-    "name": "bgColor",
-    "type": "bool",
-    "title": "Adapt body background color",
-    "value": true
+
+  "options_ui": {
+    "browser_style": true,
+    "page": "options/ui.html"
   },
-  {
-    "name": "lineNumbers",
-    "type": "bool",
-    "title": "Add line numbering",
-    "value": false
+
+  "permissions": [
+    "",
+    "activeTab",
+    "tabs",
+    "storage"
+  ],
+
+  "applications": {
+    "gecko": {
+      "id": "enlight_highlightjs@jetpack",
+      "strict_min_version": "56.0"
+    }
   }
-  ]
+
 }
diff --git a/misc/web-ext_build_cmd.sh b/misc/web-ext_build_cmd.sh
new file mode 100644
index 0000000..e2b1dcb
--- /dev/null
+++ b/misc/web-ext_build_cmd.sh
@@ -0,0 +1 @@
+web-ext build -i env.sh -i misc/* --overwrite-dest
diff --git a/misc/web-ext_env.sh b/misc/web-ext_env.sh
new file mode 100644
index 0000000..7117dd1
--- /dev/null
+++ b/misc/web-ext_env.sh
@@ -0,0 +1 @@
+alias web-ext='node_modules/web-ext/bin/web-ext'
diff --git a/options/fill-css-list.js b/options/fill-css-list.js
new file mode 100644
index 0000000..441e7cb
--- /dev/null
+++ b/options/fill-css-list.js
@@ -0,0 +1,97 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+const styles = [
+    { "file": "agate.css",                     "name" : "Agate"                     },
+    { "file": "androidstudio.css",             "name" : "Android Studio"            },
+    { "file": "arduino-light.css",             "name" : "Arduino Light"             },
+    { "file": "arta.css",                      "name" : "Arta"                      },
+    { "file": "ascetic.css",                   "name" : "Ascetic"                   },
+    { "file": "atelier-cave-dark.css",         "name" : "Atelier Cave Dark"         },
+    { "file": "atelier-cave-light.css",        "name" : "Atelier Cave Light"        },
+    { "file": "atelier-dune-dark.css",         "name" : "Atelier Dune Dark"         },
+    { "file": "atelier-dune-light.css",        "name" : "Atelier Dune Light"        },
+    { "file": "atelier-estuary-dark.css",      "name" : "Atelier Estuary Dark"      },
+    { "file": "atelier-estuary-light.css",     "name" : "Atelier Estuary Light"     },
+    { "file": "atelier-forest-dark.css",       "name" : "Atelier Forest Dark"       },
+    { "file": "atelier-forest-light.css",      "name" : "Atelier Forest Light"      },
+    { "file": "atelier-heath-dark.css",        "name" : "Atelier Heath Dark"        },
+    { "file": "atelier-heath-light.css",       "name" : "Atelier Heath Light"       },
+    { "file": "atelier-lakeside-dark.css",     "name" : "Atelier Lakeside Dark"     },
+    { "file": "atelier-lakeside-light.css",    "name" : "Atelier Lakeside Light"    },
+    { "file": "atelier-plateau-dark.css",      "name" : "Atelier Plateau Dark"      },
+    { "file": "atelier-plateau-light.css",     "name" : "Atelier Plateau Light"     },
+    { "file": "atelier-savanna-dark.css",      "name" : "Atelier Savanna Dark"      },
+    { "file": "atelier-savanna-light.css",     "name" : "Atelier Savanna Light"     },
+    { "file": "atelier-seaside-dark.css",      "name" : "Atelier Seaside Dark"      },
+    { "file": "atelier-seaside-light.css",     "name" : "Atelier Seaside Light"     },
+    { "file": "atelier-sulphurpool-dark.css",  "name" : "Atelier Sulphurpool Dark"  },
+    { "file": "atelier-sulphurpool-light.css", "name" : "Atelier Sulphurpool Light" },
+    { "file": "atom-one-dark.css",             "name" : "Atom One Dark"             },
+    { "file": "atom-one-light.css",            "name" : "Atom One Light"            },
+    { "file": "brown-paper.css",               "name" : "Brown Paper"               },
+    { "file": "codepen-embed.css",             "name" : "Codepen Embed"             },
+    { "file": "color-brewer.css",              "name" : "Color Brewer"              },
+    { "file": "darcula.css",                   "name" : "Darcula"                   },
+    { "file": "dark.css",                      "name" : "Dark"                      },
+    { "file": "darkula.css",                   "name" : "Darkula"                   },
+    { "file": "default.css",                   "name" : "Default"                   },
+    { "file": "docco.css",                     "name" : "Docco"                     },
+    { "file": "dracula.css",                   "name" : "Dracula"                   },
+    { "file": "far.css",                       "name" : "Far"                       },
+    { "file": "foundation.css",                "name" : "Foundation"                },
+    { "file": "github.css",                    "name" : "Github"                    },
+    { "file": "github-gist.css",               "name" : "Github Gist"               },
+    { "file": "googlecode.css",                "name" : "Googlecode"                },
+    { "file": "grayscale.css",                 "name" : "Grayscale"                 },
+    { "file": "gruvbox-dark.css",              "name" : "Gruvbox Dark"              },
+    { "file": "gruvbox-light.css",             "name" : "Gruvbox Light"             },
+    { "file": "hopscotch.css",                 "name" : "Hopscotch"                 },
+    { "file": "hybrid.css",                    "name" : "Hybrid"                    },
+    { "file": "idea.css",                      "name" : "Idea"                      },
+    { "file": "ir-black.css",                  "name" : "Ir Black"                  },
+    { "file": "kimbie.dark.css",               "name" : "Kimbie Dark"               },
+    { "file": "kimbie.light.css",              "name" : "Kimbie Light"              },
+    { "file": "magula.css",                    "name" : "Magula"                    },
+    { "file": "mono-blue.css",                 "name" : "Mono Blue"                 },
+    { "file": "monokai.css",                   "name" : "Monokai"                   },
+    { "file": "monokai-sublime.css",           "name" : "Monokai Sublime"           },
+    { "file": "obsidian.css",                  "name" : "Obsidian"                  },
+    { "file": "ocean.css",                     "name" : "Ocean"                     },
+    { "file": "paraiso-dark.css",              "name" : "Paraiso Dark"              },
+    { "file": "paraiso-light.css",             "name" : "Paraiso Light"             },
+    { "file": "pojoaque.css",                  "name" : "Pojoaque"                  },
+    { "file": "purebasic.css",                 "name" : "PureBASIC"                 },
+    { "file": "qtcreator_dark.css",            "name" : "Qt Creator Dark"           },
+    { "file": "qtcreator_light.css",           "name" : "Qt Creator Light"          },
+    { "file": "railscasts.css",                "name" : "Railscasts"                },
+    { "file": "rainbow.css",                   "name" : "Rainbow"                   },
+    { "file": "routeros.css",                  "name" : "RouterOS (MikroTik)"       },
+    { "file": "school-book.css",               "name" : "School Book"               },
+    { "file": "solarized-dark.css",            "name" : "Solarized Dark"            },
+    { "file": "solarized-light.css",           "name" : "Solarized Light"           },
+    { "file": "sunburst.css",                  "name" : "Sunburst"                  },
+    { "file": "tomorrow.css",                  "name" : "Tomorrow"                  },
+    { "file": "tomorrow-night-blue.css",       "name" : "Tomorrow Night Blue"       },
+    { "file": "tomorrow-night-bright.css",     "name" : "Tomorrow Night Bright"     },
+    { "file": "tomorrow-night.css",            "name" : "Tomorrow Night"            },
+    { "file": "tomorrow-night-eighties.css",   "name" : "Tomorrow Night Eighties"   },
+    { "file": "vs.css",                        "name" : "VisualStudio"              },
+    { "file": "vs2015.css",                    "name" : "VisualStudio 2015 Dark"    },
+    { "file": "xcode.css",                     "name" : "XCode"                     },
+    { "file": "xt256.css",                     "name" : "xt256"                     },
+    { "file": "zenburn.css",                   "name" : "Zenburn"                   }
+];
+let list = document.getElementById("hlstyle");
+for (let s of styles) {
+    let item = document.createElement("option");
+    item.value = s.file;
+    item.textContent = s.name;
+    list.appendChild(item);
+}
diff --git a/options/save-restore.js b/options/save-restore.js
new file mode 100644
index 0000000..c39ba86
--- /dev/null
+++ b/options/save-restore.js
@@ -0,0 +1,40 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+function saveOptions(e) {
+    e.preventDefault();
+
+    browser.storage.local.set({
+        hlstyle: document.getElementById("hlstyle").value,
+        autohl: document.getElementById("autohl").checked,
+        linenumbers: document.getElementById("linenumbers").checked,
+    });
+}
+
+function onError(error) {
+    console.error("[enlight]: Error:", error);
+}
+
+function restoreOption(aId, aDefault) {
+    let gettingItem = browser.storage.local.get(aId);
+    gettingItem.then((res) => {
+        document.getElementById(aId).value = res[aId] || aDefault;
+    }, onError);
+}
+
+function restoreAllOptions() {
+    restoreOption("hlstyle", "solarized-dark.css");
+    restoreOption("autohl", false);
+    restoreOption("linenumbers", false);
+}
+
+document.addEventListener('DOMContentLoaded', restoreAllOptions);
+document.getElementById("hlstyle").addEventListener("change", saveOptions);
+document.getElementById("autohl").addEventListener("change", saveOptions);
+document.getElementById("linenumbers").addEventListener("change", saveOptions);
diff --git a/options/ui.html b/options/ui.html
new file mode 100644
index 0000000..f1ec3b4
--- /dev/null
+++ b/options/ui.html
@@ -0,0 +1,34 @@
+
+
+  
+    
+    
+  
+  
+    
+
+ Preferences + +

+ Color Scheme + +

+ +

+ + Autodetect and automatically highlight all raw files + +

+ +

+ + Add line numbers on the left + +

+ +
+
+ + + + diff --git a/popup/languages.html b/popup/languages.html index a1cf8b0..1c89209 100644 --- a/popup/languages.html +++ b/popup/languages.html @@ -1,6 +1,7 @@ + - + - + diff --git a/popup/languages.js b/popup/languages.js new file mode 100644 index 0000000..81ac274 --- /dev/null +++ b/popup/languages.js @@ -0,0 +1,81 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Ask background script whether popup should be opened. + */ +function handleResponse(aMsg) { + if (!aMsg.shouldOpen) + window.close(); +} +function handleError(error) { + console.log("[enlight] Error:", error); +} +browser.runtime.sendMessage({shouldOpenPopup: "query"}) + .then(handleResponse, handleError); + +/* + * Parse JSON file to load the names of supported languages. + */ +function loadJSON(aCallback) { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open("GET", "languages-list_all.json", true); + xobj.onreadystatechange = function () { + if (xobj.readyState == 4 && xobj.status == "200") { + /* + * Required use of an anonymous callback as .open will NOT return a value + * but simply returns undefined in asynchronous mode. + */ + aCallback(xobj.responseText); + } + }; + xobj.send(null); +} + +/* + * Print list of languages. + */ +function generateList(aResponse) { + var languageList = JSON.parse(aResponse); + var keys = Object.keys(languageList); + + for (var i in keys) { + var element = document.createElement("div"); + + element.id = keys[i]; + if (keys[i] == "auto") { + element.className = "auto"; + //element.setAttribute("data-l10n-id", "autodetect"); + element.appendChild(document.createTextNode("Auto-detect")); + } + else { + element.className = "lang"; + element.textContent = languageList[keys[i]]; + } + document.body.appendChild(element); + } +} + +/* + * Do load JSON and print list now. + */ +loadJSON(generateList); + +/* + * On user click, send selected language id to background script, then close + * popup. + */ +window.addEventListener("click", function(event) { + let t = event.target; + if (t.nodeName == "DIV") { + browser.runtime.sendMessage({"languageId": t.id}); + window.close(); + } +}, false); diff --git a/scripts/enlight-background.js b/scripts/enlight-background.js index 31df1d1..3473505 100644 --- a/scripts/enlight-background.js +++ b/scripts/enlight-background.js @@ -1,269 +1,222 @@ -/* vim: set ts=8 sts=2 et sw=2 tw=80 cc=80: */ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -var self = require("sdk/self"); -var buttons = require("sdk/ui/button/toggle"); -var tabs = require("sdk/tabs"); -var panels = require("sdk/panel"); -var spref = require("sdk/simple-prefs"); -var xhr = require("sdk/net/xhr"); -var _ = require("sdk/l10n").get; // Localization +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ /* - * Paths (under data/) + * Paths. */ -var gHJSPath = "highlightjs"; // directory for highlight.js -var gHJSScript = "highlight.js"; // highlight.js lib, under gHJSPath/ -var gContentScript = "enlightscript.js"; // Enlight content script +var gHLJSPath = "highlightjs/highlight.pack.js"; +var gContentScript = "scripts/enlight-content.js"; +var gLanguagePath = "popup/languages-list_all.json"; /* - * List of supported languages (for display in button label) + * List of supported languages (for display in button label). */ -var gLanguagePath = "languages-all.json" // language list, under data/ var gLanguageList = {}; /* - * Icon sets for toggle button + * Current page status: highlighted, or not. */ -var gIconInit; -var gIconOff; -var gIconOn; +var isHighlighted = false; -function setIcons () { - var invert = spref.prefs["invert"] ? ".invert" : ""; - gIconInit = { // actually links towards ./lightbulb_off-xx(.invert)?.png - "16": "./lightbulb_init-16" + invert + ".png", - "32": "./lightbulb_init-32.png", - "64": "./lightbulb_init-64.png" - }; - gIconOff = { - "16": "./lightbulb_off-16" + invert + ".png", - "32": "./lightbulb_off-32.png", - "64": "./lightbulb_off-64.png" - }; - gIconOn = { - "16": "./lightbulb_on-16" + invert + ".png", - "32": "./lightbulb_on-32.png", - "64": "./lightbulb_on-64.png" - }; +/* + * Options, hardcoded for now. + */ +var options = { + hlstyle: "solarized-dark.css", + autohl: false, + linenumbers: false, +}; + +/* + * Callback. + */ +function onError(error) { + console.error("[enlight]: Error:", error); } -setIcons(); /* - * Update preferences + * Reload one option from storage. */ -spref.on("", onPrefChange); -function onPrefChange(aPref) { - switch (aPref) { - case "invert": - setIcons(); - button.icon = gIconInit; - break; - default: - break; - } +function reloadOption(aId, aDefault) { + let gettingItem = browser.storage.local.get(aId); + return gettingItem.then((res) => { + if (res[aId] != undefined) + options[aId] = res[aId]; + }, onError); } /* - * Toggle button + * Update button tooltip label ("title"). */ -var button = buttons.ToggleButton({ - id : "Highlighter", - label : _("button_label"), - icon : gIconInit, - onClick : handleClick -}); +function updateTitle(aLanguageId) { + if (aLanguageId) + browser.browserAction.setTitle({ + title: "Enlight [" + gLanguageList[aLanguageId] + "]" + }); + else + browser.browserAction.setTitle({title: "Enlight"}); +} /* - * Language selection panel + * Actually trigger syntax highlighting by injecting content scripts. */ -function panelSelect() { - window.addEventListener("click", function(event) { - let t = event.target; - if (t.nodeName == "DIV") { - self.port.emit("click-lang", t.getAttribute("id")); - } - }, false); +function doHighlight(aLanguageId) { + browser.tabs.executeScript({ + file: gHLJSPath + }).then(() => { + browser.tabs.executeScript({ + code: + "window.enlightContentScriptOptions = {" + + " language: '" + aLanguageId + "'," + + " lineNumbers: " + options.linenumbers + + "};" + }).then(() => { + browser.tabs.executeScript({ + file: gContentScript + }).then(() => { + if (aLanguageId == "undo") + return browser.tabs.removeCSS({ + file: "/highlightjs/styles/" + options.hlstyle + }); + else + return browser.tabs.insertCSS({ + file: "/highlightjs/styles/" + options.hlstyle + }); + }); + }); + }); } -var panel = panels.Panel({ - contentURL : self.data.url("panel.html"), - contentScript : "(" + panelSelect.toString() + ")()", - onHide : function() { - if (panel.languageId == "" || panel.languageId == undefined) { - button.state("tab", {"icon" : gIconOff, "checked" : false, - "label" : _("button_label")}); +/* + * Listener. Communicate with popup. + */ +function popupListener(aMsg, aSender, aSendResponse) { + if (aMsg.languageId) { + console.debug("[enlight] Required language:", aMsg.languageId); + doHighlight(aMsg.languageId); + isHighlighted = true; + updateTitle(aMsg.languageId); + } else if (aMsg.shouldOpenPopup) { + aSendResponse({shouldOpen: !isHighlighted}); + if (isHighlighted) { + doHighlight("undo"); + isHighlighted = false; + updateTitle(); } } -}); - -panel.port.on("click-lang", function(languageId) { - panel.languageId = languageId; - panel.hide(); - doHighlight(languageId); -}); +} /* - * Auto-highlight source code pages - * condition: document.body has single
 child node
+ * Injected script. Check page contents, for auto-highlighting.
  */
 function checkBody() {
-  if (document.body && document.body.childNodes.length == 1 &&
-      document.body.firstChild.nodeName == "PRE" &&
-      document.location.toString()
-        .slice(0,"view-source:".length) != "view-source:") {
-    self.port.emit("isCodeBlock");
-  }
-};
-(function setAutoHighlight() {
-  tabs.on("ready", function(aTab) {
-    if (spref.prefs["autohl"]) {
-      let worker = aTab.attach({
-        contentScript: "(" + checkBody.toString() + ")()",
-      });
-      worker.port.on("isCodeBlock", function() {
-        button.state("tab", {"icon" : gIconOn, "checked" : true});
-        doHighlight("", aTab);
-      });
-    }
-  });
-})();
+  let port = browser.runtime.connect({name:"checkBodyPort"});
+  if (
+    document.body &&
+    document.body.childNodes.length == 1 &&
+    document.body.firstChild.nodeName == "PRE" &&
+    document.location.toString()
+      .slice(0,"view-source:".length) != "view-source:"
+  )
+    port.postMessage({isCodeBlock: true});
+  else
+    port.postMessage({isCodeBlock: false});
+  port.disconnect();
+}
 
 /*
- * Callbacks
+ * Listen to injected script to see if it detects a code block in the page.
  */
-function handleClick(state) {
-  /*
-   * Classic behavior (window-wise) would be:
-   *    // checked is false: clicking a first time set it to true
-   *    if (checked)      // i.e. we just clicked an odd time
-   *      do highlight
-   *    else              // we just clicked an even time
-   *      undo highlight
-   *    fi
-   * But here we toggle tab-wise, so we need to check "manually".
-   *
-   * Also first time we click tab.checked is false, click does not set it to
-   * true. Hence we need a way to know if it's the first time for this tab:
-   * here we change the icon path (actually is a link to same PNG file).
-   */
-  button.state("window", {"checked" : false});
-  if (button.state("tab").icon["16"] == gIconInit["16"]) {
-    button.state("tab", {"icon" : gIconOn, "checked" : false});
-  }
-
-  if (!button.state("tab").checked) {
-    button.state("tab", {"icon" : gIconOn, "checked" : true});
-    panel.languageId = "";
-    panel.show({
-      position: button
-    });
-  }
-  else {
-    button.state("tab", {"icon" : gIconOff, "checked" : false,
-                 "label" : _("button_label")});
-    undoHighlight();
+function checkBodyListener(p) {
+  switch (p.name) {
+    case "checkBodyPort":
+      p.onMessage.addListener((m) => {
+        console.debug("[enlight] Do we detect a code block?", m.isCodeBlock);
+        doHighlight("auto");
+        isHighlighted = true;
+      });
+      break;
+    case "detectedLanguage":
+      p.onMessage.addListener((m) => {
+        console.debug("[enlight] Content script detected language:",
+          m.language);
+        updateTitle(m.language);
+      });
+      break;
+    default: {};
   }
 }
 
-function doHighlight(aLanguageId, aTab=tabs.activeTab) {
-  console.debug(_("log_highlight", aLanguageId, spref.prefs["style"]));
-
-  let worker = aTab.attach({
-    contentScriptOptions: {
-      "stylesheet"  : self.data.url(gHJSPath + "/styles/" +
-                      spref.prefs["style"] + ".css"),
-      "bgColor"     : spref.prefs["bgColor"],
-      "language"    : aLanguageId,
-      "lineNumbers" : spref.prefs["lineNumbers"]
-    },
-    contentScriptFile: [
-      self.data.url(gHJSPath + "/" + gHJSScript),
-      self.data.url(gContentScript)
-    ]
-  });
-
-  worker.port.on("toggle_off", function(reason) {
-    /*
-     * For some reason document content is not highlighted.
-     * Need to toggle button off.
-     */
-    if (!button.state("tab").checked) {
-      return;
-    }
-    let logToggleOffReason = _("log_toff_r" + reason);
-    console.debug(_("log_toggleoff", logToggleOffReason));
-    button.state("tab", {"icon" : gIconOff, "checked" : false,
-                 "label" : _("button_label")});
-  });
-
+/*
+ * Listener. If auto-highlighting is selected, highlight all raw text pages.
+ */
+function tabUpdateListener(aTabId, aChangeInfo, aTabInfo) {
+  if (!aChangeInfo.url)
+    return;
   /*
-   * Add language ID to button's label if we know it
+   * Auto-highlight!
    */
-  if (aLanguageId && aLanguageId != "auto") {
-    button.state("tab", {"icon" : gIconOn, "checked" : true,
-                 "label" : _("button_label") +
-                   " [" + gLanguageList[aLanguageId] + "]"});
-  }
-  else {
-    worker.port.on("detected_language", function(aId) {
-      /*
-       * We launched language auto-detection, and content script is telling us
-       * what language was detected: update button label
-       */
-      button.state("tab", {"icon" : gIconOn, "checked" : true,
-                   "label" : _("button_label") +
-                     " [" + gLanguageList[aId] + "]"});
-    });
-  }
-
-  aTab.on("ready", function () {
-    /*
-     * Content document has been changed/reloaded.
-     * Need to toggle button off.
-     */
-    if (!button.state("tab").checked) {
-      return;
-    }
-    console.debug(_("log_toggleoff", "log_toff_r2"));
-    button.state("tab", {"icon" : gIconOff, "checked" : false});
-    aTab.on("ready", function () {});
-  });
-}
-
-function undoHighlight() {
-  console.debug(_("log_undo"));
-  tabs.activeTab.attach({
-    contentScriptFile: [
-      self.data.url("enlightscript.js")
-    ]
+  browser.tabs.executeScript({
+    code: "(" + checkBody.toString() + ")()"
   });
 }
 
 /*
- * Functions used to parse JSON list of languages (so that we can display name
- * of detected language in button label)
+ * Parse JSON list of languages so that we can display the name of detected
+ * languages in button label.
  */
 function loadJSON(aCallback) {
-  var xobj = new xhr.XMLHttpRequest();
-  xobj.overrideMimeType("application/json");
-  xobj.open("GET", self.data.url(gLanguagePath), true);
-  xobj.onreadystatechange = function () {
-    if (xobj.readyState == 4 && xobj.status == "200") {
-      aCallback(xobj.responseText);
-    }
-  };
-  xobj.send(null);
+    var xobj = new XMLHttpRequest();
+    xobj.overrideMimeType("application/json");
+    xobj.open("GET", gLanguagePath, true);
+    xobj.onreadystatechange = function () {
+        if (xobj.readyState == 4 && xobj.status == "200") {
+            aCallback(xobj.responseText);
+        }
+    };
+    xobj.send(null);
 }
 
+/*
+ * Callback.
+ */
 function parseResponse(aResponse) {
   gLanguageList = JSON.parse(aResponse);
 }
 
-loadJSON(parseResponse);
+/*
+ * Load all options, and set up auto-highlighting if required.
+ */
+function init() {
+  if (options.autohl) {
+    browser.runtime.onConnect.removeListener(checkBodyListener);
+    browser.tabs.onUpdated.removeListener(tabUpdateListener);
+  }
+
+  reloadOption("autohl")
+    .then(reloadOption("linenumbers"))
+    .then(reloadOption("hlstyle"))
+    .then(() => {
+      if (options.autohl) {
+        browser.runtime.onConnect.addListener(checkBodyListener);
+        browser.tabs.onUpdated.addListener(tabUpdateListener);
+      }
+    });
+}
 
 /*
- * Exports for unit tests
+ * Perform these operations at add-on start-up:
  */
-exports.button      = button;
-exports.panel       = panel;
-exports.doHighlight = doHighlight;
+
+browser.runtime.onMessage.addListener(popupListener);
+
+browser.storage.onChanged.addListener(init);
+init();
+
+loadJSON(parseResponse);
diff --git a/scripts/enlight-content.js b/scripts/enlight-content.js
index 4b62640..0d96177 100644
--- a/scripts/enlight-content.js
+++ b/scripts/enlight-content.js
@@ -1,4 +1,11 @@
-/* vim: set ts=8 sts=2 et sw=2 tw=80 cc=80: */
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
 
 /*
  * Syntax highlighting addition/removal handlers (content scripts).
@@ -14,20 +21,25 @@
  */
 
 /*****************************************************************************/
+var options = {};
 
 /*
- * Execute this at startup
+ * Run the main function at startup.
  */
 var enlight = function () {
+  /*
+   * Get options attached as window.enlightContentScriptOptions by previous
+   * content script.
+   */
+  options = enlightContentScriptOptions;
+
   /*
    * If there is no 
 HTML block, there's nothing to work on: get
    * out of here.
    */
   if (!document.body ||
-       document.body.getElementsByTagName("pre").item(0) === null) {
-    self.port.emit("toggle_off", 1);
+       document.body.getElementsByTagName("pre").item(0) === null)
     return;
-  }
 
   var initDocumentDiv = document.getElementById("enlightInitDocument");
   /*
@@ -39,9 +51,8 @@ var enlight = function () {
   /*
    * If option is set, activate “gotoline” functionality.
    */
-  if (self.options && self.options.lineNumbers) {
+  if (options && options.lineNumbers)
     gotoline();
-  }
 } ();
 
 /*****************************************************************************/
@@ -49,12 +60,14 @@ var enlight = function () {
 function dohl() {
   var preList = document.getElementsByTagName("pre");
   /*
-   * If self.options is undefined we shouldn't be there. Page has probably been
-   * changed since a former highlight: get out as well.
+   * If options is empty we shouldn't be there. Page has probably been changed
+   * since a former highlight: get out as well.
+   * If options.language is "undo", we want to undo highlighting. If we
+   * triggered dohl() in that case, we probably messed up somewhere in keeping
+   * track of page status. Stop the mess here and return.
    */
-  if (!self.options) {
+  if (!options || options == {} || options.language == "undo")
     return;
-  }
 
   /*
    * Back up initial document
@@ -65,17 +78,6 @@ function dohl() {
   idoc.setAttribute("id", "enlightInitDocument");
   idoc.appendChild(clone);
 
-  /*
-   * Add link to CSS stylesheet
-   */
-  var css = document.createElement("link");
-  var style = self.options.stylesheet;
-  css.setAttribute("href",  style != undefined ? style : "");
-  css.setAttribute("rel",  "stylesheet");
-  css.setAttribute("type", "text/css");
-  css.setAttribute("id",   "enlightStylesheet");
-  document.head.appendChild(css);
-
   /*
    * If needed, add CSS rules for line numbering
    */
@@ -84,9 +86,8 @@ function dohl() {
   /*
    * Deal with language
    */
-  var language = (self.options.language != "" &&
-                  self.options.language != "auto") ?
-                    " " + self.options.language :
+  var language = (options.language != "" && options.language != "auto") ?
+                    " " + options.language :
                     "";
 
   /*
@@ -96,9 +97,7 @@ function dohl() {
     var firstChild = pre.firstChild;
     var code = document.createElement("code");
     code.setAttribute("class", "hljs" + language);
-    if (self.options.bgColor) {
-      code.style = "padding: 0;";
-    }
+    code.style = "padding: 0;";
     code.appendChild(firstChild);
     pre.appendChild(code);
   }
@@ -111,37 +110,35 @@ function dohl() {
   /*
    * Add line numbers if needed.
    */
-  if (self.options.lineNumbers) {
+  if (options.lineNumbers)
     for (var pre of preList) {
       var code = pre.firstChild;
       addLineNumbers(code);
     }
-  }
 
   /*
-   * There's a remaining white border because of body background color.
-   * If option is set, remove it.
+   * There's a remaining white border because of body background color. Remove
+   * it by copying background color of highlighted code area.
    */
-  if (self.options.bgColor) {
-    setTimeout(function () { // Wait for CSS to be computed
-      let codeBG = getComputedStyle(preList[0].firstChild)["background-color"];
-      if (codeBG &&
-          codeBG!="white" &&
-          codeBG!="#FFFFFF" &&
-          codeBG!="#ffffff") {
-        document.body.style.backgroundColor = codeBG;
-      }
-    }, 50);
-  }
+  setTimeout(function () { // Wait for CSS to be computed
+    let codeBG = getComputedStyle(preList[0].firstChild)["background-color"];
+    if (codeBG &&
+        codeBG!="white" &&
+        codeBG!="#FFFFFF" &&
+        codeBG!="#ffffff")
+      document.body.style.backgroundColor = codeBG;
+  }, 50);
 
   /*
    * If we launched language auto-detection, tell main script about detected
    * language
    */
-  if (self.options.language == "" || self.options.language == "auto") {
-    let languageClass = document.querySelectorAll('pre code')[0].className;
+  if (options.language == "" || options.language == "auto") {
+    let languageClass = document.querySelectorAll("pre code")[0].className;
     let languageId = languageClass.slice("hljs ".length);
-    self.port.emit('detected_language', languageId);
+    let port = browser.runtime.connect({name: "detectedLanguage"});
+    port.postMessage({language: languageId});
+    port.disconnect();
   }
 
   /*
@@ -184,9 +181,9 @@ function addLineNumbers(aCode) {
  * https://github.com/isagalaev/highlight.js/compare/master...line-numbers
  */
 function addLineNumberStyle() {
-  if (!self.options.lineNumbers) {
+  if (!options.lineNumbers)
     return;
-  }
+
   var styleContent = " \
     pre { \
       counter-reset: lines; \
@@ -222,20 +219,18 @@ function gotoline() {
   /*
    * Get "#line27" or "#Line27" or "#L27" or "#l27" -like sequence from URL
    */
-  let nb = (window.location + '').match(/#(?:[Ll](?:ine)?)?(\d+)/i)
-  if (nb === null) {
+  let nb = (window.location + "").match(/#(?:[Ll](?:ine)?)?(\d+)/i)
+  if (nb === null)
     return;
-  }
 
   /*
    * Fetch associated line. Note that we fetch the “absolute” nth line of
    * highlighted code in the file, which is not necessarily the nth line of its
    * block if there are several highlighted blocks of code.
    */
-  let target = document.getElementsByClassName('line')[nb[1]-1]
-  if (target === undefined) {
+  let target = document.getElementsByClassName("line")[nb[1]-1]
+  if (target === undefined)
     return;
-  }
 
   /*
    * Scroll to that line
@@ -248,7 +243,7 @@ function gotoline() {
   let selection = window.getSelection();
   let range = document.createRange();
   range.setStartAfter(target);
-  let next = document.getElementsByClassName('line')[nb[1]];
+  let next = document.getElementsByClassName("line")[nb[1]];
   next !== undefined ?
     range.setEndBefore(next) :
     range.setEndAfter(target.parentNode);