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" +}