diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..37f3e66
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,3 @@
+**/node_modules/**
+react-es6-popup/**/dist
+mocha-client-tests
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..bd5191f
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,22 @@
+{
+ "root": true,
+ "parserOptions": {
+ "ecmaVersion": 6
+ },
+ "env": {
+ "browser": true,
+ "es6": true,
+ "webextensions": true
+ },
+ "extends": [
+ "eslint:recommended"
+ ],
+ "rules": {
+ "no-console": 0,
+ "no-unused-vars": ["warn", { "vars": "all", "args": "all" } ],
+ "no-undef": ["warn"],
+ "no-proto": ["error"],
+ "prefer-arrow-callback": ["warn"],
+ "prefer-spread": ["warn"]
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..96c06b2
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,7 @@
+language: node_js
+node_js:
+ - "8"
+sudo: false
+
+script:
+ - "npm test"
diff --git a/README.md b/README.md
index 505ef63..426b57a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# webextensions-examples
+# webextensions-examples [](https://travis-ci.org/mdn/webextensions-examples)
[https://github.com/mdn/webextensions-examples](https://github.com/mdn/webextensions-examples)
diff --git a/annotate-page/sidebar/panel.js b/annotate-page/sidebar/panel.js
index f4fdb46..2af8505 100644
--- a/annotate-page/sidebar/panel.js
+++ b/annotate-page/sidebar/panel.js
@@ -4,14 +4,14 @@ const contentBox = document.querySelector("#content");
/*
Make the content box editable as soon as the user mouses over the sidebar.
*/
-window.addEventListener("mouseover", (e) => {
+window.addEventListener("mouseover", () => {
contentBox.setAttribute("contenteditable", true);
});
/*
When the user mouses out, save the current contents of the box.
*/
-window.addEventListener("mouseout", (e) => {
+window.addEventListener("mouseout", () => {
contentBox.setAttribute("contenteditable", false);
browser.tabs.query({windowId: myWindowId, active: true}).then((tabs) => {
let contentToStore = {};
diff --git a/apply-css/background.js b/apply-css/background.js
index 7e936a0..3c0b1aa 100644
--- a/apply-css/background.js
+++ b/apply-css/background.js
@@ -51,7 +51,7 @@ When first loaded, initialize the page action for all tabs.
*/
var gettingAllTabs = browser.tabs.query({});
gettingAllTabs.then((tabs) => {
- for (tab of tabs) {
+ for (let tab of tabs) {
initializePageAction(tab);
}
});
diff --git a/chill-out/background.js b/chill-out/background.js
index bbf453f..d29d949 100644
--- a/chill-out/background.js
+++ b/chill-out/background.js
@@ -69,6 +69,6 @@ browser.alarms.onAlarm.addListener((alarm) => {
/*
On page action click, navigate the corresponding tab to the cat gifs.
*/
-browser.pageAction.onClicked.addListener(function () {
+browser.pageAction.onClicked.addListener(() => {
browser.tabs.update({url: CATGIFS});
});
diff --git a/commands/background.js b/commands/background.js
index 825c559..a54dc95 100644
--- a/commands/background.js
+++ b/commands/background.js
@@ -12,7 +12,7 @@
*/
var gettingAllCommands = browser.commands.getAll();
gettingAllCommands.then((commands) => {
- for (command of commands) {
+ for (let command of commands) {
console.log(command);
}
});
diff --git a/context-menu-copy-link-with-types/background.js b/context-menu-copy-link-with-types/background.js
index b8d1505..9152745 100644
--- a/context-menu-copy-link-with-types/background.js
+++ b/context-menu-copy-link-with-types/background.js
@@ -3,7 +3,7 @@ browser.contextMenus.create({
title: "Copy link to clipboard",
contexts: ["link"],
});
-browser.contextMenus.onClicked.addListener(function(info, tab) {
+browser.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === "copy-link-to-clipboard") {
// Examples: text and HTML to be copied.
const text = "This is text: " + info.linkUrl;
@@ -22,7 +22,7 @@ browser.contextMenus.onClicked.addListener(function(info, tab) {
browser.tabs.executeScript({
code: "typeof copyToClipboard === 'function';",
- }).then(function(results) {
+ }).then((results) => {
// The content script's last expression will be true if the function
// has been defined. If this is not the case, then we need to run
// clipboard-helper.js to define function copyToClipboard.
@@ -31,11 +31,11 @@ browser.contextMenus.onClicked.addListener(function(info, tab) {
file: "clipboard-helper.js",
});
}
- }).then(function() {
+ }).then(() => {
return browser.tabs.executeScript(tab.id, {
code,
});
- }).catch(function(error) {
+ }).catch((error) => {
// This could happen if the extension is not allowed to run code in
// the page, for example if the tab is a privileged page.
console.error("Failed to copy text: " + error);
diff --git a/context-menu-demo/background.js b/context-menu-demo/background.js
index 98f43a1..359c57b 100644
--- a/context-menu-demo/background.js
+++ b/context-menu-demo/background.js
@@ -2,7 +2,7 @@
Called when the item has been created, or when creation failed due to an error.
We'll just log success/failure here.
*/
-function onCreated(n) {
+function onCreated() {
if (browser.runtime.lastError) {
console.log(`Error: ${browser.runtime.lastError}`);
} else {
@@ -127,7 +127,7 @@ function updateCheckUncheck() {
The click event listener, where we perform the appropriate action given the
ID of the menu item that was clicked.
*/
-browser.contextMenus.onClicked.addListener(function(info, tab) {
+browser.contextMenus.onClicked.addListener((info, tab) => {
switch (info.menuItemId) {
case "log-selection":
console.log(info.selectionText);
diff --git a/embedded-webextension-bootstrapped/.eslintrc.json b/embedded-webextension-bootstrapped/.eslintrc.json
new file mode 100644
index 0000000..30e26e9
--- /dev/null
+++ b/embedded-webextension-bootstrapped/.eslintrc.json
@@ -0,0 +1,8 @@
+{
+ "env": {
+ "browser": true,
+ "es6": true,
+ "amd": true,
+ "webextensions": true
+ }
+}
diff --git a/embedded-webextension-sdk/.eslintrc.json b/embedded-webextension-sdk/.eslintrc.json
new file mode 100644
index 0000000..30e26e9
--- /dev/null
+++ b/embedded-webextension-sdk/.eslintrc.json
@@ -0,0 +1,8 @@
+{
+ "env": {
+ "browser": true,
+ "es6": true,
+ "amd": true,
+ "webextensions": true
+ }
+}
diff --git a/emoji-substitution/emojiMap.js b/emoji-substitution/emojiMap.js
index 16c689e..b2f1b9e 100644
--- a/emoji-substitution/emojiMap.js
+++ b/emoji-substitution/emojiMap.js
@@ -2,6 +2,8 @@
* This file contains the Map of word --> emoji substitutions.
*/
+/* exported sortedEmojiMap */
+
let dictionary = new Map();
dictionary.set('apple', '🍎');
dictionary.set('banana', '🍌');
diff --git a/emoji-substitution/substitute.js b/emoji-substitution/substitute.js
index c886063..39203db 100644
--- a/emoji-substitution/substitute.js
+++ b/emoji-substitution/substitute.js
@@ -3,6 +3,8 @@
* all occurrences of each mapped word with its emoji counterpart.
*/
+/*global sortedEmojiMap*/
+
// emojiMap.js defines the 'sortedEmojiMap' variable.
// Referenced here to reduce confusion.
const emojiMap = sortedEmojiMap;
diff --git a/google-userinfo/background/authorize.js b/google-userinfo/background/authorize.js
index 633c41b..b49bb72 100644
--- a/google-userinfo/background/authorize.js
+++ b/google-userinfo/background/authorize.js
@@ -1,3 +1,5 @@
+/* exported getAccessToken */
+
const REDIRECT_URL = browser.identity.getRedirectURL();
const CLIENT_ID = "YOUR-CLIENT-ID";
const SCOPES = ["openid", "email", "profile"];
diff --git a/google-userinfo/background/main.js b/google-userinfo/background/main.js
index ac70222..9ddf1fb 100644
--- a/google-userinfo/background/main.js
+++ b/google-userinfo/background/main.js
@@ -1,3 +1,5 @@
+/*global getAccessToken*/
+
function notifyUser(user) {
browser.notifications.create({
"type": "basic",
diff --git a/google-userinfo/background/userinfo.js b/google-userinfo/background/userinfo.js
index 84a5427..5f7ac1d 100644
--- a/google-userinfo/background/userinfo.js
+++ b/google-userinfo/background/userinfo.js
@@ -2,6 +2,9 @@
Fetch the user's info, passing in the access token in the Authorization
HTTP request header.
*/
+
+/* exported getUserInfo */
+
function getUserInfo(accessToken) {
const requestURL = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
const requestHeaders = new Headers();
diff --git a/history-deleter/history.js b/history-deleter/history.js
index 11a1dff..798f8db 100644
--- a/history-deleter/history.js
+++ b/history-deleter/history.js
@@ -7,7 +7,7 @@ function get_hostname(url) {
}
function set_domain(domain) {
- spans = document.getElementsByClassName('domain');
+ const spans = document.getElementsByClassName('domain');
[].slice.call(spans).forEach((span) => {
span.textContent = domain;
});
@@ -65,7 +65,7 @@ function clearAll(e) {
// Loop through them and delete them one by one.
var searchingHistory = browser.history.search({text: hostname})
searchingHistory.then((results) => {
- for (k = 0; k < results.length; k++) {
+ for (let k of results) {
browser.history.deleteUrl({url: results[k].url});
}
// Clear out the UI.
diff --git a/list-cookies/cookies.js b/list-cookies/cookies.js
index 74c5a84..db2fc8e 100644
--- a/list-cookies/cookies.js
+++ b/list-cookies/cookies.js
@@ -1,6 +1,6 @@
function showCookiesForTab(tabs) {
//get the first tab object in the array
- tab = tabs.pop();
+ let tab = tabs.pop();
//get all cookies in the domain
var gettingAllCookies = browser.cookies.getAll({url: tab.url});
@@ -14,22 +14,22 @@ function showCookiesForTab(tabs) {
if (cookies.length > 0) {
//add an
item with the name and value of the cookie to the list
- for (cookie of cookies) {
- var li = document.createElement("li");
- var content = document.createTextNode(cookie.name + ": "+ cookie.value);
+ for (let cookie of cookies) {
+ let li = document.createElement("li");
+ let content = document.createTextNode(cookie.name + ": "+ cookie.value);
li.appendChild(content);
cookieList.appendChild(li);
}
} else {
- var p = document.createElement("p");
- var content = document.createTextNode("No cookies in this tab.");
- var parent = cookieList.parentNode;
+ let p = document.createElement("p");
+ let content = document.createTextNode("No cookies in this tab.");
+ let parent = cookieList.parentNode;
p.appendChild(content);
parent.appendChild(p);
}
});
-};
+}
//get active tab to run an callback function.
//it sends to our callback an array of tab objects
diff --git a/mocha-client-tests/.eslintrc.json b/mocha-client-tests/.eslintrc.json
new file mode 100644
index 0000000..30e26e9
--- /dev/null
+++ b/mocha-client-tests/.eslintrc.json
@@ -0,0 +1,8 @@
+{
+ "env": {
+ "browser": true,
+ "es6": true,
+ "amd": true,
+ "webextensions": true
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..019418f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "webextensions-examples",
+ "title": "WebExtensions Examples",
+ "version": "1.0.0",
+ "description": "Example Firefox add-ons created using the WebExtensions API",
+ "devDependencies": {
+ "eslint": "^3.19.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/mdn/webextensions-examples.git"
+ },
+ "scripts": {
+ "test": "eslint .",
+ "lint": "eslint ."
+ },
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/mdn/webextensions-examples/issues"
+ },
+ "keywords": [
+ "webextensions",
+ "webextensions-apis",
+ "mdn",
+ "firefox",
+ "mozilla"
+ ],
+ "homepage": "https://developer.mozilla.org/Add-ons/WebExtensions/Examples",
+ "dependencies": {
+ "babel-eslint": "^7.2.3"
+ }
+}
diff --git a/page-to-extension-messaging/content-script.js b/page-to-extension-messaging/content-script.js
index 01646c9..418fa46 100644
--- a/page-to-extension-messaging/content-script.js
+++ b/page-to-extension-messaging/content-script.js
@@ -2,7 +2,7 @@
Listen for messages from the page.
If the message was from the page script, show an alert.
*/
-window.addEventListener("message", function(event) {
+window.addEventListener("message", (event) => {
if (event.source == window &&
event.data &&
event.data.direction == "from-page-script") {
diff --git a/permissions/.eslintrc.json b/permissions/.eslintrc.json
new file mode 100644
index 0000000..22c3ada
--- /dev/null
+++ b/permissions/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "parserOptions": {
+ "ecmaVersion": 8
+ }
+}
diff --git a/proxy-blocker/background/proxy-handler.js b/proxy-blocker/background/proxy-handler.js
index 098089c..aabcd89 100644
--- a/proxy-blocker/background/proxy-handler.js
+++ b/proxy-blocker/background/proxy-handler.js
@@ -15,7 +15,7 @@ browser.proxy.onProxyError.addListener(error => {
});
// Initialize the proxy
-function handleInit(message) {
+function handleInit() {
// update the proxy whenever stored settings change
browser.storage.onChanged.addListener((newSettings) => {
browser.runtime.sendMessage(newSettings.blockedHosts.newValue, {toProxyScript: true});
diff --git a/proxy-blocker/proxy/proxy-script.js b/proxy-blocker/proxy/proxy-script.js
index 135295c..31343e6 100644
--- a/proxy-blocker/proxy/proxy-script.js
+++ b/proxy-blocker/proxy/proxy-script.js
@@ -1,3 +1,5 @@
+/* exported FindProxyForURL */
+
var blockedHosts = [];
const allow = "DIRECT 1234";
const deny = "PROXY 127.0.0.1:65535";
diff --git a/quicknote/popup/quicknote.js b/quicknote/popup/quicknote.js
index b94c29e..04d5a81 100644
--- a/quicknote/popup/quicknote.js
+++ b/quicknote/popup/quicknote.js
@@ -27,7 +27,7 @@ function initialize() {
var gettingAllStorageItems = browser.storage.local.get(null);
gettingAllStorageItems.then((results) => {
var noteKeys = Object.keys(results);
- for(noteKey of noteKeys) {
+ for (let noteKey of noteKeys) {
var curValue = results[noteKey];
displayNote(noteKey,curValue);
}
@@ -88,8 +88,8 @@ function displayNote(title, body) {
/* set up listener for the delete functionality */
- deleteBtn.addEventListener('click',function(e){
- evtTgt = e.target;
+ deleteBtn.addEventListener('click',(e) => {
+ const evtTgt = e.target;
evtTgt.parentNode.parentNode.parentNode.removeChild(evtTgt.parentNode.parentNode);
browser.storage.local.remove(title);
})
@@ -125,24 +125,24 @@ function displayNote(title, body) {
/* set up listeners for the update functionality */
- noteH.addEventListener('click',function(){
+ noteH.addEventListener('click',() => {
noteDisplay.style.display = 'none';
noteEdit.style.display = 'block';
})
- notePara.addEventListener('click',function(){
+ notePara.addEventListener('click',() => {
noteDisplay.style.display = 'none';
noteEdit.style.display = 'block';
})
- cancelBtn.addEventListener('click',function(){
+ cancelBtn.addEventListener('click',() => {
noteDisplay.style.display = 'block';
noteEdit.style.display = 'none';
noteTitleEdit.value = title;
noteBodyEdit.value = body;
})
- updateBtn.addEventListener('click',function(){
+ updateBtn.addEventListener('click',() => {
if(noteTitleEdit.value !== title || noteBodyEdit.value !== body) {
updateNote(title,noteTitleEdit.value,noteBodyEdit.value);
note.parentNode.removeChild(note);
diff --git a/react-es6-popup/.eslintrc.json b/react-es6-popup/.eslintrc.json
new file mode 100644
index 0000000..bc30d96
--- /dev/null
+++ b/react-es6-popup/.eslintrc.json
@@ -0,0 +1,15 @@
+{
+ "parserOptions": {
+ "ecmaVersion": 6,
+ "sourceType": "module",
+ "ecmaFeatures": {
+ "jsx": true
+ }
+ },
+ "env": {
+ "browser": true,
+ "es6": true,
+ "amd": true,
+ "webextensions": true
+ }
+}
diff --git a/selection-to-clipboard/content-script.js b/selection-to-clipboard/content-script.js
index 8fb2598..1b78c5b 100644
--- a/selection-to-clipboard/content-script.js
+++ b/selection-to-clipboard/content-script.js
@@ -1,7 +1,7 @@
/*
copy the selected text to clipboard
*/
-function copySelection(e) {
+function copySelection() {
var selectedText = window.getSelection().toString().trim();
if (selectedText) {
diff --git a/tabs-tabs-tabs/tabs.js b/tabs-tabs-tabs/tabs.js
index dba3dfc..27e7a1b 100644
--- a/tabs-tabs-tabs/tabs.js
+++ b/tabs-tabs-tabs/tabs.js
@@ -47,7 +47,7 @@ function getCurrentWindowTabs() {
return browser.tabs.query({currentWindow: true});
}
-document.addEventListener("click", function(e) {
+document.addEventListener("click", (e) => {
function callOnActiveTab(callback) {
getCurrentWindowTabs().then((tabs) => {
for (var tab of tabs) {
@@ -163,7 +163,7 @@ document.addEventListener("click", function(e) {
// Currently (11/2/2016) only supported by Chrome
else if (e.target.id === "tabs-highlight") { // highlights current tab and next tab (cycles back to first tab if current tab is the last one)
callOnActiveTab((tab, tabs) => {
- next = (tab.index+1) % tabs.length;
+ let next = (tab.index+1) % tabs.length;
browser.tabs.highlight({tabs:[tab.index, next]});
});
}
@@ -173,7 +173,7 @@ document.addEventListener("click", function(e) {
chrome.tabs.query({
currentWindow: true
- }, function(tabs) {
+ }, (tabs) => {
for (var tab of tabs) {
if (tab.id === tabId) {
chrome.tabs.update(tabId, {
@@ -188,7 +188,7 @@ document.addEventListener("click", function(e) {
});
//onRemoved listener. fired when tab is removed
-browser.tabs.onRemoved.addListener(function(tabId, removeInfo){
+browser.tabs.onRemoved.addListener((tabId, removeInfo) => {
console.log(`The tab with id: ${tabId}, is closing`);
if(removeInfo.isWindowClosing) {
@@ -199,7 +199,7 @@ browser.tabs.onRemoved.addListener(function(tabId, removeInfo){
});
//onMoved listener. fired when tab is moved into the same window
-browser.tabs.onMoved.addListener(function(tabId, moveInfo){
+browser.tabs.onMoved.addListener((tabId, moveInfo) => {
var startIndex = moveInfo.fromIndex;
var endIndex = moveInfo.toIndex;
console.log(`Tab with id: ${tabId} moved from index: ${startIndex} to index: ${endIndex}`);
diff --git a/user-agent-rewriter/popup/choose_ua.js b/user-agent-rewriter/popup/choose_ua.js
index baaddaf..91dbbc9 100644
--- a/user-agent-rewriter/popup/choose_ua.js
+++ b/user-agent-rewriter/popup/choose_ua.js
@@ -4,7 +4,7 @@ If the user clicks on an element which has the class "ua-choice":
* fetch the element's textContent: for example, "IE 11"
* pass it into the background page's setUaString() function
*/
-document.addEventListener("click", function(e) {
+document.addEventListener("click", (e) => {
if (!e.target.classList.contains("ua-choice")) {
return;
}
diff --git a/webpack-modules/.eslintrc.json b/webpack-modules/.eslintrc.json
new file mode 100644
index 0000000..30e26e9
--- /dev/null
+++ b/webpack-modules/.eslintrc.json
@@ -0,0 +1,8 @@
+{
+ "env": {
+ "browser": true,
+ "es6": true,
+ "amd": true,
+ "webextensions": true
+ }
+}
diff --git a/window-manipulator/window.js b/window-manipulator/window.js
index d6e36eb..a659b48 100644
--- a/window-manipulator/window.js
+++ b/window-manipulator/window.js
@@ -26,48 +26,48 @@ document.addEventListener("click", (e) => {
}
else if (e.target.id === "window-create-normal") {
- var createData = {};
- var creating = browser.windows.create(createData);
+ let createData = {};
+ let creating = browser.windows.create(createData);
creating.then(() => {
console.log("The normal window has been created");
});
}
else if (e.target.id === "window-create-incognito") {
- var createData = {
+ let createData = {
incognito: true,
};
- var creating = browser.windows.create(createData);
+ let creating = browser.windows.create(createData);
creating.then(() => {
console.log("The incognito window has been created");
});
}
else if (e.target.id === "window-create-panel") {
- var createData = {
+ let createData = {
type: "panel",
};
- var creating = browser.windows.create(createData);
+ let creating = browser.windows.create(createData);
creating.then(() => {
console.log("The panel has been created");
});
}
else if (e.target.id === "window-create-detached-panel") {
- var createData = {
+ let createData = {
type: "detached_panel",
};
- var creating = browser.windows.create(createData);
+ let creating = browser.windows.create(createData);
creating.then(() => {
console.log("The detached panel has been created");
});
}
else if (e.target.id === "window-create-popup") {
- var createData = {
+ let createData = {
type: "popup",
};
- var creating = browser.windows.create(createData);
+ let creating = browser.windows.create(createData);
creating.then(() => {
console.log("The popup has been created");
});