diff --git a/.gitignore b/.gitignore
index 3aee263..1582433 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.idea
.DS_Storecss/*.map
+node_modules
diff --git a/.jshintignore b/.jshintignore
new file mode 100644
index 0000000..cc541db
--- /dev/null
+++ b/.jshintignore
@@ -0,0 +1,2 @@
+js/vendor
+js/lib/passwordgen.js
\ No newline at end of file
diff --git a/.jshintrc b/.jshintrc
index 4bf3f27..27b7455 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -5,6 +5,9 @@
"angular": true,
"PassmanImporter": true,
"C_Promise": true,
- "window": true
+ "window": true,
+ "PAPI": true,
+ "API": true,
+ "OTP": true
} // additional predefined global variables
}
\ No newline at end of file
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..5ef9a57
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,45 @@
+module.exports = function (grunt) {
+ var jsResources = [];
+ // Project configuration.
+ grunt.initConfig({
+ jsResources: [],
+ cssResources: [],
+ pkg: grunt.file.readJSON('package.json'),
+ jshint: {
+ options: {
+ reporter: require('jshint-stylish'),
+ curly: false,
+ eqeqeq: true,
+ eqnull: true,
+ browser: true,
+ globals: {
+ "angular": true,
+ "PassmanImporter": true,
+ "PassmanExporter": true,
+ "OC": true,
+ "window": true,
+ "console": true,
+ "CRYPTO": true,
+ "C_Promise": true,
+ "forge": true,
+ "sjcl": true,
+ "jQuery": true,
+ "$": true,
+ "_": true,
+ "oc_requesttoken": true
+ }
+ },
+ all: ['js/*','!js/vendor']
+ }
+
+ });
+
+ // Load the plugin that provides the "uglify" task.
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+
+
+ // Default task(s).
+
+ grunt.registerTask('hint', ['jshint']);
+
+};
\ No newline at end of file
diff --git a/js/background/inject/inject.js b/js/background/inject/inject.js
index 779ff56..090cb20 100644
--- a/js/background/inject/inject.js
+++ b/js/background/inject/inject.js
@@ -229,11 +229,13 @@ $j(document).ready(function () {
for (var i = 0; i < logins.length; i++) {
var login = logins[i];
var row = $j('
' + login.label + '
' + login.username + '
');
+ /* jshint ignore:start */
row.click((function (login) {
return function () {
enterLoginDetails(login);
};
})(login));
+ /* jshint ignore:end*/
picker.find('.tab-list-content').append(row);
}
@@ -336,10 +338,7 @@ $j(document).ready(function () {
return;
}
var picker = $j('#password_picker');
- if (!picker.is(e.target)
- && picker.has(e.target).length === 0
-
- ) {
+ if (!picker.is(e.target) && picker.has(e.target).length === 0) {
if (picker) {
picker.remove();
}
@@ -468,11 +467,13 @@ $j(document).ready(function () {
createPasswordPicker(loginFields[i], form);
}
//Password miner
+ /* jshint ignore:start */
$j(form).submit((function (loginFields) {
return function () {
formSubmitted(loginFields);
};
})(loginFields[i]));
+ /* jshint ignore:end */
}
var url = window.location.href; //@TODO use a extension function
diff --git a/js/background/service/background.js b/js/background/service/background.js
index e810350..37bf878 100644
--- a/js/background/service/background.js
+++ b/js/background/service/background.js
@@ -419,7 +419,7 @@
if (error === "Data not found") {
getSettings();
}
- })
+ });
}());
diff --git a/js/background/service/contextMenu.js b/js/background/service/contextMenu.js
index 2e79c2b..80c713c 100644
--- a/js/background/service/contextMenu.js
+++ b/js/background/service/contextMenu.js
@@ -112,16 +112,18 @@ window.contextMenu = (function () {
login.autoFill = (!login.hasOwnProperty('autoFill')) ? true : login.autoFill;
for (f = 0; f < fields.length; f++) {
field = fields[f];
- if (field['field'] === 'totp' && login.otp) {
+ if (field.field === 'totp' && login.otp) {
login.totp = login.otp.secret;
}
- if (login[field['field']]) {
+ if (login[field.field]) {
fields[f].found = true;
- createMenuItem(field['menu'], field['menu'] + ':' + login.guid, login.label, (function (field, login) {
+ /* jshint ignore:start */
+ createMenuItem(field.menu, field.menu + ':' + login.guid, login.label, (function (field, login) {
return function () {
itemClickCallback(field, login);
};
})(field, login));
+ /* jshint ignore:end */
}
}
}
diff --git a/js/lib/API/base.js b/js/lib/API/base.js
index 96c9b90..0e022af 100644
--- a/js/lib/API/base.js
+++ b/js/lib/API/base.js
@@ -6,14 +6,13 @@
/* global browser, chrome */
-
-'use strict';
if (typeof API === "undefined") {
var API = {};
}
-
+/* jshint ignore:start */
API.api;
API.promise = true; // Chrome does not return promises
+/* jshint ignore:end */
// Workaround chrome's uniqueness
if (typeof browser === 'undefined') {
diff --git a/js/lib/API/browser_action.js b/js/lib/API/browser_action.js
index bcc4f86..535072c 100644
--- a/js/lib/API/browser_action.js
+++ b/js/lib/API/browser_action.js
@@ -6,7 +6,6 @@
/* global API */
-'use strict';
API.browserAction = {
setTitle: API.api.browserAction.setTitle,
diff --git a/js/lib/API/cookies.js b/js/lib/API/cookies.js
index ce42565..c2039e1 100644
--- a/js/lib/API/cookies.js
+++ b/js/lib/API/cookies.js
@@ -6,7 +6,6 @@
/* global API */
-'use strict';
API.cookies = {
get: function (details) {
diff --git a/js/lib/API/runtime.js b/js/lib/API/runtime.js
index 4313de3..a35b2ce 100644
--- a/js/lib/API/runtime.js
+++ b/js/lib/API/runtime.js
@@ -6,7 +6,6 @@
/* global API */
-'use strict';
API.runtime = {
getBackgroundPage: function() {
if (API.promise) {
diff --git a/js/lib/API/storage.js b/js/lib/API/storage.js
index 17526f2..f02d3ea 100644
--- a/js/lib/API/storage.js
+++ b/js/lib/API/storage.js
@@ -1,6 +1,5 @@
/* global browser, chrome */
-'use strict';
if (typeof API === "undefined") {
var API = {};
}
@@ -19,9 +18,11 @@ API.Storage = function() {
return new C_Promise(function(){
if (API.promise) {
localStorage.get(key).then((function(item){
+ /* jshint ignore:start */
if (typeof key === "[object Array]") {
this.call_then(item);
}
+
else {
if (item[key] === undefined) {
this.call_error("Data not found");
@@ -30,15 +31,18 @@ API.Storage = function() {
this.call_then(item[key]);
}
}
+ /* jshint ignore:end */
}).bind(this), (function(error){
this.call_error(error);
}).bind(this));
}
else{
localStorage.get(key, (function(item){
+ /* jshint ignore:start */
if (typeof key === "[object Array]") {
this.call_then(item);
}
+
else {
if (item[key] === undefined) {
this.call_error("Data not found");
@@ -47,6 +51,7 @@ API.Storage = function() {
this.call_then(item[key]);
}
}
+ /* jshint ignore:end */
}).bind(this));
}
});
diff --git a/js/lib/API/tabs.js b/js/lib/API/tabs.js
index 09ebe8a..6cfa98b 100644
--- a/js/lib/API/tabs.js
+++ b/js/lib/API/tabs.js
@@ -6,7 +6,6 @@
/* global API */
-'use strict';
API.tabs = {
connect: function(tabId, connectInfo) {
diff --git a/js/lib/font-awesome.js b/js/lib/font-awesome.js
index 2136b68..965f3e0 100644
--- a/js/lib/font-awesome.js
+++ b/js/lib/font-awesome.js
@@ -7,7 +7,6 @@ function insertFontCSS() {
"font-weight: normal;",
"font-style: normal;",
"}"];
- var browser = jQuery.browser;
if (window.navigator.userAgent.indexOf('Firefox') !== -1) {
fontCss[2] = "src: url('" + fontPath + "fonts/fontawesome-webfont.eot?v=4.7.0');";
fontCss[3] = "src: url('" + fontPath + "fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('" + fontPath + "fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('" + fontPath + "fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('" + fontPath + "fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('" + fontPath + "fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');";
diff --git a/js/lib/jQuerytoObject.js b/js/lib/jQuerytoObject.js
index a388e23..0aa405e 100644
--- a/js/lib/jQuerytoObject.js
+++ b/js/lib/jQuerytoObject.js
@@ -3,15 +3,16 @@ jQuery.fn.serializeObject = function()
var o = {};
var a = this.serializeArray();
jQuery.each(a, function() {
+ var value;
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
- var value = (this.value === 'on') ? true : this.value;
+ value = (this.value === 'on') ? true : this.value;
value = (value === 'off') ? false : value;
o[this.name].push(value || '');
} else {
- var value = (this.value === 'on') ? true : this.value;
+ value = (this.value === 'on') ? true : this.value;
value = (value === 'off') ? false : value;
o[this.name] = value;
}
diff --git a/js/ui/popup/factories/debounce.js b/js/ui/popup/factories/debounce.js
index 115346b..b06ce02 100644
--- a/js/ui/popup/factories/debounce.js
+++ b/js/ui/popup/factories/debounce.js
@@ -41,6 +41,6 @@
});
}
};
- });;
+ });
}());
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..60a8b6d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "passman-web-extension",
+ "version": "1.0.0",
+ "description": "Tested on: - Chrome - Firefox - Safari",
+ "main": "Gruntfile.js",
+ "dependencies": {
+ "grunt": "~0.4.5",
+ "grunt-cli": "~1.2.0",
+ "grunt-contrib-jshint": "^0.12.0",
+ "jshint-stylish": "^2.2.1"
+ },
+ "devDependencies": {},
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/nextcloud/passman-webextension.git"
+ },
+ "author": "",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/nextcloud/passman-webextension/issues"
+ },
+ "homepage": "https://github.com/nextcloud/passman-webextension#readme"
+}