├── .gitignore ├── license.txt ├── project.clj ├── readme-orig.md ├── readme.md ├── resources ├── release │ ├── background.html │ ├── images │ ├── manifest.json │ └── popup.html ├── shared │ └── images │ │ ├── icon128.png │ │ ├── icon16.png │ │ ├── icon19.png │ │ ├── icon38.png │ │ └── icon48.png └── unpacked │ ├── background.html │ ├── background.js │ ├── images │ ├── manifest.json │ ├── popup.html │ ├── popup.js │ └── setup.js ├── scripts ├── config.sh ├── ensure-checkouts.sh ├── launch-test-browser.sh └── package.sh └── src ├── background └── chromex_sample │ ├── background.cljs │ └── background │ ├── core.cljs │ └── storage.cljs ├── content_script └── chromex_sample │ ├── content_script.cljs │ └── content_script │ └── core.cljs └── popup └── chromex_sample ├── popup.cljs └── popup └── core.cljs /.gitignore: -------------------------------------------------------------------------------- 1 | .lein* 2 | /resources/unpacked/compiled 3 | /resources/release.crx 4 | /resources/release.pem 5 | /resources/release/compiled 6 | /releases 7 | /.idea 8 | /target 9 | /checkouts 10 | /.tmp 11 | .figwheel*.log 12 | .chrome-profile 13 | .test-dirac-chrome-profile -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) BinaryAge Limited and contributors 2 | https://github.com/binaryage/chromex-sample/graphs/contributors 3 | 4 | MIT License 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject binaryage/chromex-sample "0.1.0-SNAPSHOT" 2 | :dependencies [[org.clojure/clojure "1.10.1"] 3 | [org.clojure/clojurescript "1.10.520"] 4 | [org.clojure/core.async "0.4.500"] 5 | [binaryage/chromex "0.8.1"] 6 | [binaryage/devtools "0.9.10"] 7 | [figwheel "0.5.19"] 8 | [environ "1.1.0"]] 9 | 10 | :plugins [[lein-cljsbuild "1.1.7"] 11 | [lein-figwheel "0.5.19"] 12 | [lein-shell "0.5.0"] 13 | [lein-environ "1.1.0"] 14 | [lein-cooper "1.2.2"]] 15 | 16 | :source-paths ["src/background" 17 | "src/popup" 18 | "src/content_script"] 19 | 20 | :clean-targets ^{:protect false} ["target" 21 | "resources/unpacked/compiled" 22 | "resources/release/compiled"] 23 | 24 | :cljsbuild {:builds {}} ; prevent https://github.com/emezeske/lein-cljsbuild/issues/413 25 | 26 | :profiles {:unpacked 27 | {:cljsbuild {:builds 28 | {:background 29 | {:source-paths ["src/background"] 30 | :figwheel true 31 | :compiler {:output-to "resources/unpacked/compiled/background/main.js" 32 | :output-dir "resources/unpacked/compiled/background" 33 | :asset-path "compiled/background" 34 | :preloads [devtools.preload figwheel.preload] 35 | :main chromex-sample.background 36 | :optimizations :none 37 | :source-map true}} 38 | :popup 39 | {:source-paths ["src/popup"] 40 | :figwheel true 41 | :compiler {:output-to "resources/unpacked/compiled/popup/main.js" 42 | :output-dir "resources/unpacked/compiled/popup" 43 | :asset-path "compiled/popup" 44 | :preloads [devtools.preload figwheel.preload] 45 | :main chromex-sample.popup 46 | :optimizations :none 47 | :source-map true}}}}} 48 | :unpacked-content-script 49 | {:cljsbuild {:builds 50 | {:content-script 51 | {:source-paths ["src/content_script"] 52 | :compiler {:output-to "resources/unpacked/compiled/content-script/main.js" 53 | :output-dir "resources/unpacked/compiled/content-script" 54 | :asset-path "compiled/content-script" 55 | :main chromex-sample.content-script 56 | ;:optimizations :whitespace ; content scripts cannot do eval / load script dynamically 57 | :optimizations :advanced ; let's use advanced build with pseudo-names for now, there seems to be a bug in deps ordering under :whitespace mode 58 | :pseudo-names true 59 | :pretty-print true}}}}} 60 | :checkouts 61 | ; DON'T FORGET TO UPDATE scripts/ensure-checkouts.sh 62 | {:cljsbuild {:builds 63 | {:background {:source-paths ["checkouts/cljs-devtools/src/lib" 64 | "checkouts/chromex/src/lib" 65 | "checkouts/chromex/src/exts"]} 66 | :popup {:source-paths ["checkouts/cljs-devtools/src/lib" 67 | "checkouts/chromex/src/lib" 68 | "checkouts/chromex/src/exts"]}}}} 69 | :checkouts-content-script 70 | ; DON'T FORGET TO UPDATE scripts/ensure-checkouts.sh 71 | {:cljsbuild {:builds 72 | {:content-script {:source-paths ["checkouts/cljs-devtools/src/lib" 73 | "checkouts/chromex/src/lib" 74 | "checkouts/chromex/src/exts"]}}}} 75 | 76 | :figwheel 77 | {:figwheel {:server-port 6888 78 | :server-logfile ".figwheel.log" 79 | :repl true}} 80 | 81 | :disable-figwheel-repl 82 | {:figwheel {:repl false}} 83 | 84 | :cooper 85 | {:cooper {"content-dev" ["lein" "content-dev"] 86 | "fig-dev-no-repl" ["lein" "fig-dev-no-repl"] 87 | "browser" ["scripts/launch-test-browser.sh"]}} 88 | 89 | :release 90 | {:env {:chromex-elide-verbose-logging "true"} 91 | :cljsbuild {:builds 92 | {:background 93 | {:source-paths ["src/background"] 94 | :compiler {:output-to "resources/release/compiled/background.js" 95 | :output-dir "resources/release/compiled/background" 96 | :asset-path "compiled/background" 97 | :main chromex-sample.background 98 | :optimizations :advanced 99 | :elide-asserts true}} 100 | :popup 101 | {:source-paths ["src/popup"] 102 | :compiler {:output-to "resources/release/compiled/popup.js" 103 | :output-dir "resources/release/compiled/popup" 104 | :asset-path "compiled/popup" 105 | :main chromex-sample.popup 106 | :optimizations :advanced 107 | :elide-asserts true}} 108 | :content-script 109 | {:source-paths ["src/content_script"] 110 | :compiler {:output-to "resources/release/compiled/content-script.js" 111 | :output-dir "resources/release/compiled/content-script" 112 | :asset-path "compiled/content-script" 113 | :main chromex-sample.content-script 114 | :optimizations :advanced 115 | :elide-asserts true}}}}}} 116 | 117 | :aliases {"dev-build" ["with-profile" "+unpacked,+unpacked-content-script,+checkouts,+checkouts-content-script" "cljsbuild" "once"] 118 | "fig" ["with-profile" "+unpacked,+figwheel" "figwheel" "background" "popup"] 119 | "content" ["with-profile" "+unpacked-content-script" "cljsbuild" "auto" "content-script"] 120 | "fig-dev-no-repl" ["with-profile" "+unpacked,+figwheel,+disable-figwheel-repl,+checkouts" "figwheel" "background" "popup"] 121 | "content-dev" ["with-profile" "+unpacked-content-script,+checkouts-content-script" "cljsbuild" "auto"] 122 | "devel" ["with-profile" "+cooper" "do" ; for mac only 123 | ["shell" "scripts/ensure-checkouts.sh"] 124 | ["cooper"]] 125 | "release" ["with-profile" "+release" "do" 126 | ["clean"] 127 | ["cljsbuild" "once" "background" "popup" "content-script"]] 128 | "package" ["shell" "scripts/package.sh"]}) 129 | -------------------------------------------------------------------------------- /readme-orig.md: -------------------------------------------------------------------------------- 1 | # chromex-sample [![GitHub license](https://img.shields.io/github/license/binaryage/chromex-sample.svg)](license.txt) 2 | 3 | ### An example extension using Chromex library 4 | 5 | This project acts as a code example for [chromex library](https://github.com/binaryage/chromex) but also as a skeleton 6 | with project configuration following best practices. We recommend to use it as a starting point when starting development 7 | of your own extension. 8 | 9 | #### **chromex-sample** has a minimalist **background page**, **popup button** and **content script**: 10 | 11 | * background page listens for connections from popup buttons and content scripts (there can be multiple of them) 12 | * popup button connects to the background page and sends a simple "HELLO" message after connection 13 | * content script connects to the background page and sends a simple "HELLO" message after connection 14 | * content script does a simple page analysis upon launch (it counts number of script tags) and sends an info message to the background page 15 | * background page listens to tab creation events and notifies all connected clients about new tabs being created 16 | 17 | #### **chromex-sample** project has following configuration: 18 | 19 | * uses [leiningen](http://leiningen.org) + [lein-cljsbuild](https://github.com/emezeske/lein-cljsbuild) 20 | * integrates [cljs-devtools](https://github.com/binaryage/cljs-devtools) 21 | * integrates [figwheel](https://github.com/bhauman/lein-figwheel) (for background page and popup buttons) 22 | * under `:unpacked` profile (development) 23 | * background page and popup button 24 | * compiles with `optimizations :none` 25 | * namespaces are included as individual files and source maps work as expected 26 | * figwheel works 27 | * content script 28 | * due to [security restrictions](https://github.com/binaryage/chromex-sample/issues/2), content script has to be provided as a single file 29 | * compiles with `:optimizations :whitespace` and `:pretty-print true` 30 | * figwheel cannot be used in this context (eval is not allowed) 31 | * under `:release` profile 32 | * background page, popup button and content script compile with `optimizations :advanced` 33 | * elides asserts 34 | * no figwheel support 35 | * no cljs-devtools support 36 | * `lein package` task is provided for building an extension package for release 37 | 38 | ### Local setup 39 | 40 | #### Extension development 41 | 42 | We assume you are familiar with ClojureScript tooling and you have your machine in a good shape running recent versions of 43 | java, maven, leiningen, etc. 44 | 45 | * clone this repo somewhere: 46 | ```bash 47 | git clone https://github.com/binaryage/chromex-sample.git 48 | cd chromex-sample 49 | ``` 50 | * chromex sample is gets built into `resources/unpacked/compiled` folder. 51 | 52 | In one terminal session run (will build background and popup pages using figwheel): 53 | ```bash 54 | lein fig 55 | ``` 56 | In a second terminal session run (will auto-build content-script): 57 | ```bash 58 | lein content 59 | ``` 60 | * use latest Chrome Canary with [Custom Formatters](https://github.com/binaryage/cljs-devtools#enable-custom-formatters-in-your-chrome-canary) enabled 61 | * In Chrome Canary, open `chrome://extensions` and add `resources/unpacked` via "Load unpacked extension..." 62 | 63 | ##### Debugging 64 | 65 | Chrome extension development is more complex than regular ClojureScript front-end 66 | work. You are writing (and debugging) multiple parallel communicating processes: your 67 | background page, your popup, and all the browser pages running your content script. 68 | 69 | Amazingly, the ClojureScript tooling and Figwheel live coding remain very usable in this 70 | environment. But, you need to be aware of a few things, particularly in regard to 71 | compiler warnings: 72 | 73 | Most warnings do not appear in the repls. Figwheel intercepts them for display in the 74 | browser. Warning will appear in the Chrome console and, when possible, as an overlay in 75 | the browser window. But, the exact behavior depends upon which part of your code has the 76 | error: 77 | 78 | _Content script_: Warnings and errors will appear in the repl running `lein content`. 79 | 80 | _popup_: Chrome normally closes the popup anytime focus leaves Chrome. So, if you are 81 | working in your editor, the popup is closed and you will not see any error messages 82 | anywhere. This can be very frustrating but is easy to fix. When you first open the 83 | popup, right click on its icon and select `Inspect popup`. This opens the Chrome 84 | inspector/console and keeps the popup open while the inspector remains open. Any errrors 85 | will appear in both the console and as the Figwheel overlay in your popup window. Also, 86 | of course, this gives you niceties of Figwheel live coding. Your changes will appear 87 | immediately, with no need to close and reopen the popup. 88 | 89 | _background_: The background code is running under Figwheel, so no messages will appear 90 | in the repl. It also has no visibile window, so no Figwheel overlay can appear. You will 91 | only see warnings in the Chrome console. You can open the inspector/console from 92 | `chrome://extensions`. Under your extension, click on the `Inspect Views` line. 93 | 94 | In summary, effective live debugging requires up to five open windows on your screen: 95 | - Your editor; 96 | - The shell running `lein content`, if you are making changes to content script code; 97 | - The web browser, with open popup and/or content page; 98 | - A Chrome inspector console, watching the background page; and 99 | - A Chrome inspector console, watching the popup page. 100 | 101 | 102 | 103 | #### Extension packaging 104 | 105 | [Leiningen project](project.clj) has defined "release" profile for compilation in advanced mode. Run: 106 | ```bash 107 | lein release 108 | ``` 109 | 110 | This will build an optimized build into [resources/release](resources/release). You can add this folder via "Load unpacked extension..." 111 | to test it. 112 | 113 | When satisfied, you can run: 114 | ```bash 115 | lein package 116 | ``` 117 | 118 | This will create a folder `releases/chromex-sample-0.1.0` where 0.1.0 will be current version from [project.clj](project.clj). 119 | This folder will contain only files meant to be packaged. 120 | 121 | Finally you can use Chrome's "Pack extension" tool to prepare the final package (.crx and .pem files). 122 | 123 | ### Code discussion 124 | 125 | Before reading the code below you should get familiar with [Chrome Extension System architecture](https://developer.chrome.com/extensions/overview#arch). 126 | 127 | #### Popup page 128 | 129 | Let's start with [popup button code](src/popup/chromex_sample/popup/core.cljs): 130 | 131 | ```clojure 132 | ; -- a message loop ------------------------------------------------------------------------------- 133 | 134 | (defn process-message! [message] 135 | (log "POPUP: got message:" message)) 136 | 137 | (defn run-message-loop! [message-channel] 138 | (log "POPUP: starting message loop...") 139 | (go-loop [] 140 | (when-some [message (clj` and `clj->js` would come handy at many places. 179 | 180 | ##### Message loop 181 | 182 | It is worth noting that core.async channel [returns `nil` when closed](https://clojure.github.io/core.async/#clojure.core.async/ -------------------------------------------------------------------------------- /resources/release/images: -------------------------------------------------------------------------------- 1 | ../shared/images -------------------------------------------------------------------------------- /resources/release/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chromex-sample", 3 | "version": "0.1.0", 4 | "browser_action": { 5 | "default_title": "Show the popup", 6 | "default_popup": "popup.html", 7 | "default_icon": { 8 | "19": "images/icon19.png", 9 | "38": "images/icon38.png" 10 | } 11 | }, 12 | "icons": { 13 | "16": "images/icon16.png", 14 | "48": "images/icon48.png", 15 | "128": "images/icon128.png" 16 | }, 17 | "content_scripts": [ 18 | { 19 | "matches": [ 20 | "" 21 | ], 22 | "js": [ 23 | "compiled/content-script.js" 24 | ], 25 | "run_at": "document_end" 26 | } 27 | ], 28 | "background": { 29 | "page": "background.html", 30 | "persistent": false 31 | }, 32 | "permissions": [ 33 | "storage" 34 | ], 35 | "manifest_version": 2 36 | } 37 | -------------------------------------------------------------------------------- /resources/release/popup.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/shared/images/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryage/chromex-sample/5d526435dad33cfbac1abd0b6687590bfc63a53a/resources/shared/images/icon128.png -------------------------------------------------------------------------------- /resources/shared/images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryage/chromex-sample/5d526435dad33cfbac1abd0b6687590bfc63a53a/resources/shared/images/icon16.png -------------------------------------------------------------------------------- /resources/shared/images/icon19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryage/chromex-sample/5d526435dad33cfbac1abd0b6687590bfc63a53a/resources/shared/images/icon19.png -------------------------------------------------------------------------------- /resources/shared/images/icon38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryage/chromex-sample/5d526435dad33cfbac1abd0b6687590bfc63a53a/resources/shared/images/icon38.png -------------------------------------------------------------------------------- /resources/shared/images/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryage/chromex-sample/5d526435dad33cfbac1abd0b6687590bfc63a53a/resources/shared/images/icon48.png -------------------------------------------------------------------------------- /resources/unpacked/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/unpacked/background.js: -------------------------------------------------------------------------------- 1 | goog.require("devtools.preload"); 2 | goog.require("figwheel.preload"); 3 | goog.require("chromex_sample.background"); 4 | -------------------------------------------------------------------------------- /resources/unpacked/images: -------------------------------------------------------------------------------- 1 | ../shared/images -------------------------------------------------------------------------------- /resources/unpacked/manifest.json: -------------------------------------------------------------------------------- 1 | /* this manifest is for development only 2 | we include all files individually 3 | also we allow unsafe eval for figwheel 4 | */ 5 | { 6 | "name": "chromex-sample-dev", 7 | "version": "0.1.0", 8 | "browser_action": { 9 | "default_title": "Show the popup", 10 | "default_popup": "popup.html", 11 | "default_icon": { 12 | "19": "images/icon19.png", 13 | "38": "images/icon38.png" 14 | } 15 | }, 16 | "icons": { 17 | "16": "images/icon16.png", 18 | "48": "images/icon48.png", 19 | "128": "images/icon128.png" 20 | }, 21 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", 22 | "content_scripts": [ 23 | { 24 | "matches": [ 25 | "" 26 | ], 27 | "js": [ 28 | "compiled/content-script/main.js" 29 | ], 30 | "run_at": "document_end" 31 | } 32 | ], 33 | "background": { 34 | "page": "background.html", 35 | "persistent": false 36 | }, 37 | "permissions": [ 38 | "storage" 39 | ], 40 | "manifest_version": 2 41 | } 42 | -------------------------------------------------------------------------------- /resources/unpacked/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/unpacked/popup.js: -------------------------------------------------------------------------------- 1 | goog.require("devtools.preload"); 2 | goog.require("figwheel.preload"); 3 | goog.require("chromex_sample.popup"); 4 | -------------------------------------------------------------------------------- /resources/unpacked/setup.js: -------------------------------------------------------------------------------- 1 | goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', true); -------------------------------------------------------------------------------- /scripts/config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pushd () { 4 | command pushd "$@" > /dev/null 5 | } 6 | 7 | popd () { 8 | command popd "$@" > /dev/null 9 | } 10 | 11 | pushd . 12 | 13 | cd "$(dirname "${BASH_SOURCE[0]}")"; cd .. 14 | 15 | ROOT=`pwd` 16 | BROWSER_USER_PROFILE="$ROOT/.chrome-profile" 17 | DEV_EXTENSION_PATH="$ROOT/resources/unpacked" 18 | 19 | popd -------------------------------------------------------------------------------- /scripts/ensure-checkouts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # checkouts folders mentioned in :source-paths must exist for cljs compiler to be happy 4 | # they can be empty and that should be perfectly fine 5 | 6 | set -e 7 | 8 | pushd `dirname "${BASH_SOURCE[0]}"` > /dev/null 9 | source "./config.sh" 10 | 11 | pushd "$ROOT" 12 | 13 | mkdir -p "checkouts/cljs-devtools/src" 14 | mkdir -p "checkouts/chromex/src/lib" 15 | mkdir -p "checkouts/chromex/src/exts" 16 | 17 | popd 18 | -------------------------------------------------------------------------------- /scripts/launch-test-browser.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | pushd `dirname "${BASH_SOURCE[0]}"` > /dev/null 6 | source "./config.sh" 7 | 8 | pushd "$ROOT" 9 | 10 | if [ ! -d "$BROWSER_USER_PROFILE" ] ; then 11 | mkdir -p "$BROWSER_USER_PROFILE" 12 | fi 13 | 14 | EXE="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary" 15 | if [ -n "$USE_CHROME" ] ; then 16 | EXE="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" 17 | fi 18 | if [ -n "$USE_CHROMIUM" ] ; then 19 | EXE="/Applications/Chromium.app/Contents/MacOS/Chromium" 20 | fi 21 | 22 | # we want wait to compilation of our extensions, so that --load-extension param does not fail 23 | 24 | SECS_TO_WAIT=120 25 | echo "waiting $SECS_TO_WAIT seconds before launching Chrome to give cljs compiler time to build the extension" 26 | sleep "$SECS_TO_WAIT" 27 | 28 | echo "launching Chrome from $EXE" 29 | 30 | set -x 31 | "$EXE" \ 32 | --user-data-dir="$BROWSER_USER_PROFILE" \ 33 | --no-first-run \ 34 | --enable-experimental-extension-apis \ 35 | --disk-cache-dir=/dev/null \ 36 | --media-cache-dir=/dev/null \ 37 | --disable-hang-monitor \ 38 | --disable-prompt-on-repost \ 39 | --dom-automation \ 40 | --full-memory-crash-report \ 41 | --no-default-browser-check \ 42 | --load-extension="$DEV_EXTENSION_PATH" 43 | 44 | set +x 45 | 46 | popd 47 | -------------------------------------------------------------------------------- /scripts/package.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pushd `dirname "${BASH_SOURCE[0]}"` > /dev/null 4 | source "./config.sh" 5 | 6 | pushd "$ROOT" 7 | 8 | RELEASES="$ROOT/releases" 9 | RELEASE_BUILD="$ROOT/resources/release" 10 | RELEASE_BUILD_COMPILED="$RELEASE_BUILD/compiled" 11 | 12 | if [ ! -d "$RELEASE_BUILD" ] ; then 13 | echo "'$RELEASE_BUILD' does not exist, run 'lein release' first" 14 | exit 1 15 | fi 16 | 17 | if [ ! -d "$RELEASE_BUILD_COMPILED" ] ; then 18 | echo "'$RELEASE_BUILD_COMPILED' does not exist, run 'lein release' to fully build the project" 19 | exit 2 20 | fi 21 | 22 | if [ ! -d "$RELEASES" ] ; then 23 | mkdir -p "$RELEASES" 24 | fi 25 | 26 | VERSION_WITH_QUOTES=`cat project.clj | grep "defproject" | cut -d' ' -f3` 27 | VERSION=`echo "${VERSION_WITH_QUOTES//\"}"` 28 | 29 | PACKAGE_DIR="$RELEASES/chromex-sample-$VERSION" 30 | 31 | if [ -d "$PACKAGE_DIR" ] ; then 32 | rm -rf "$PACKAGE_DIR" 33 | fi 34 | 35 | # this will copy actual files, not symlinks 36 | # Tread carefully here, this is system-dependent 37 | # -r works on Mac but not Linux 38 | # -rL works on Linux (tested on Ubuntu 16.04) but not Mac 39 | # -RL works on both 40 | cp -RL "$RELEASE_BUILD" "$PACKAGE_DIR" 41 | 42 | 43 | # prune release directory from extra files/folders 44 | rm -rf "$PACKAGE_DIR/compiled/background" 45 | rm -rf "$PACKAGE_DIR/compiled/content_script" 46 | rm -rf "$PACKAGE_DIR/compiled/popup" 47 | 48 | echo "'$PACKAGE_DIR' prepared for packing" 49 | echo " use Chrome's Window -> Extensions -> 'Pack extension...' to package it" 50 | echo " or => https://developer.chrome.com/extensions/packaging#packaging" 51 | 52 | popd 53 | -------------------------------------------------------------------------------- /src/background/chromex_sample/background.cljs: -------------------------------------------------------------------------------- 1 | (ns chromex-sample.background 2 | (:require-macros [chromex.support :refer [runonce]]) 3 | (:require [chromex-sample.background.core :as core])) 4 | 5 | (runonce 6 | (core/init!)) 7 | -------------------------------------------------------------------------------- /src/background/chromex_sample/background/core.cljs: -------------------------------------------------------------------------------- 1 | (ns chromex-sample.background.core 2 | (:require-macros [cljs.core.async.macros :refer [go go-loop]]) 3 | (:require [goog.string :as gstring] 4 | [goog.string.format] 5 | [cljs.core.async :refer [