@@ -31,6 +31,7 @@ | |||
"cross-env": "^5.2.0", | |||
"css-loader": "^3.0.0", | |||
"cypress": "^3.4.0", | |||
"cypress-plugin-tab": "^1.0.3", | |||
"express": "^4.17.1", | |||
"file-loader": "^4.0.0", | |||
"html-webpack-plugin": "^3.2.0", | |||
@@ -1,9 +1,6 @@ | |||
describe("Password Generation", function() { | |||
it("can't decrease counter under 0", function() { | |||
cy.visit("/"); | |||
cy.get(".showOptions__btn") | |||
.first() | |||
.click(); | |||
cy.get("#decreaseCounter__btn").click(); | |||
cy.get("#decreaseCounter__btn").click(); | |||
cy.get("#passwordCounter").should("have.value", "1"); | |||
@@ -28,9 +25,6 @@ describe("Password Generation", function() { | |||
cy.get("#fingerprint .fa-plane").should("be.visible"); | |||
cy.get("#generatePassword__btn").click(); | |||
cy.get("#generated-password").should("have.value", "hjV@\\5ULp3bIs,6B"); | |||
cy.get(".showOptions__btn") | |||
.first() | |||
.click(); | |||
cy.get("#decreaseLength__btn").click(); | |||
cy.get("#passwordLength").should("have.value", "15"); | |||
cy.get("#increaseLength__btn").click(); | |||
@@ -75,9 +69,6 @@ describe("Password Generation", function() { | |||
}); | |||
it("should have a min length of 5 and max length of 35", function() { | |||
cy.visit("/"); | |||
cy.get(".showOptions__btn") | |||
.first() | |||
.click(); | |||
cy.get("#passwordLength") | |||
.clear() | |||
.type("35"); | |||
@@ -94,9 +85,6 @@ describe("Password Generation", function() { | |||
cy.get("#siteField").type("site"); | |||
cy.get("#login").type("login"); | |||
cy.get("#passwordField").type("test"); | |||
cy.get(".showOptions__btn") | |||
.first() | |||
.click(); | |||
cy.get("#passwordCounter") | |||
.clear() | |||
.type("10"); | |||
@@ -140,4 +128,15 @@ describe("Password Generation", function() { | |||
cy.get("#copyPasswordButton").should("not.be.visible"); | |||
cy.get("#generatePassword__btn").should("be.visible"); | |||
}); | |||
it("should generate password with 2 tabs and enter", function() { | |||
cy.visit("/"); | |||
cy.get("#siteField") | |||
.type("lesspass.com") | |||
.tab() | |||
.type("test@lesspass.com") | |||
.tab() | |||
.type("test@lesspass.com") | |||
.type("{enter}"); | |||
cy.get("#generated-password").should("have.value", "hjV@\\5ULp3bIs,6B"); | |||
}); | |||
}); |
@@ -1 +1,2 @@ | |||
import "cypress-plugin-tab"; | |||
import "./commands"; |
@@ -58,10 +58,6 @@ button, | |||
.right-addon input { | |||
padding-right: 30px; | |||
} | |||
.border-blue { | |||
border-color: #007bff !important; | |||
} | |||
</style> | |||
<template> | |||
<div id="lesspass" class="card"> | |||
@@ -17,6 +17,7 @@ | |||
name="siteField" | |||
ref="siteField" | |||
class="form-control awesomplete" | |||
tabindex="0" | |||
autocorrect="off" | |||
autocapitalize="none" | |||
v-bind:placeholder="label" | |||
@@ -25,6 +25,7 @@ | |||
ref="passwordField" | |||
type="password" | |||
class="form-control" | |||
tabindex="0" | |||
autocorrect="off" | |||
autocapitalize="none" | |||
v-bind:value="value" | |||
@@ -32,7 +32,7 @@ | |||
<router-link class="white-link pl-3" :to="{ name: 'passwords'}" v-if="isAuthenticated"> | |||
<i class="fa fa-lg fa-key"></i> | |||
</router-link> | |||
<router-link class="white-link pl-3" :to="{ name: 'options'}" v-if="false"> | |||
<router-link class="white-link pl-3" :to="{ name: 'settings'}"> | |||
<i class="fa fa-lg fa-cog"></i> | |||
</router-link> | |||
<button class="white-link btn btn-link p-0 m-0 pl-3" type="button" v-if="isAuthenticated" | |||
@@ -1,13 +1,13 @@ | |||
<style> | |||
#options input[type="number"] { | |||
-moz-appearance: textfield; | |||
} | |||
#options input[type="number"] { | |||
-moz-appearance: textfield; | |||
} | |||
#options input[type="number"]::-webkit-outer-spin-button, | |||
#options input[type="number"]::-webkit-inner-spin-button { | |||
-webkit-appearance: none; | |||
margin: 0; | |||
} | |||
#options input[type="number"]::-webkit-outer-spin-button, | |||
#options input[type="number"]::-webkit-inner-spin-button { | |||
-webkit-appearance: none; | |||
margin: 0; | |||
} | |||
</style> | |||
<template> | |||
<div id="options"> | |||
@@ -15,41 +15,49 @@ | |||
<div class="col-12"> | |||
<div class="row"> | |||
<div class="col"> | |||
<label for="types">{{ $t('Advanced options') }}</label> | |||
<label for="types">{{ $t('Options') }}</label> | |||
</div> | |||
</div> | |||
<div id="types" class="row"> | |||
<div class="col-3"> | |||
<button id="lowercase__btn" | |||
type="button" class="btn btn-block btn-sm px-0" | |||
v-bind:class="{'btn-primary':password.lowercase===true, 'btn-secondary':password.lowercase===false}" | |||
v-on:click="password.lowercase=!password.lowercase"> | |||
a-z | |||
</button> | |||
<button | |||
id="lowercase__btn" | |||
type="button" | |||
class="btn btn-block btn-sm px-0" | |||
tabindex="1" | |||
v-bind:class="{'btn-primary':options.lowercase===true, 'btn-secondary':options.lowercase===false}" | |||
v-on:click="options.lowercase=!options.lowercase" | |||
>a-z</button> | |||
</div> | |||
<div class="col-3"> | |||
<button id="uppercase__btn" | |||
type="button" class="btn btn-block btn-sm px-0" | |||
v-bind:class="{'btn-primary':password.uppercase===true, 'btn-secondary':password.uppercase===false}" | |||
v-on:click="password.uppercase=!password.uppercase"> | |||
A-Z | |||
</button> | |||
<button | |||
id="uppercase__btn" | |||
type="button" | |||
class="btn btn-block btn-sm px-0" | |||
tabindex="1" | |||
v-bind:class="{'btn-primary':options.uppercase===true, 'btn-secondary':options.uppercase===false}" | |||
v-on:click="options.uppercase=!options.uppercase" | |||
>A-Z</button> | |||
</div> | |||
<div class="col-3"> | |||
<button id="numbers__btn" | |||
type="button" class="btn btn-block btn-sm px-0" | |||
v-bind:class="{'btn-primary':password.numbers===true,'btn-secondary':password.numbers===false}" | |||
v-on:click="password.numbers=!password.numbers"> | |||
0-9 | |||
</button> | |||
<button | |||
id="numbers__btn" | |||
type="button" | |||
class="btn btn-block btn-sm px-0" | |||
tabindex="1" | |||
v-bind:class="{'btn-primary':options.numbers===true,'btn-secondary':options.numbers===false}" | |||
v-on:click="options.numbers=!options.numbers" | |||
>0-9</button> | |||
</div> | |||
<div class="col-3"> | |||
<button id="symbols__btn" | |||
type="button" class="btn btn-block btn-sm px-0" | |||
v-bind:class="{'btn-primary':password.symbols===true,'btn-secondary':password.symbols===false}" | |||
v-on:click="password.symbols=!password.symbols"> | |||
%!@ | |||
</button> | |||
<button | |||
id="symbols__btn" | |||
type="button" | |||
class="btn btn-block btn-sm px-0" | |||
tabindex="1" | |||
v-bind:class="{'btn-primary':options.symbols===true,'btn-secondary':options.symbols===false}" | |||
v-on:click="options.symbols=!options.symbols" | |||
>%!@</button> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -58,48 +66,83 @@ | |||
<div class="col-5 col-sm-4"> | |||
<label for="passwordLength">{{ $t('Length') }}</label> | |||
<div class="input-group input-group-sm"> | |||
<span class="input-group-btn" v-on:click="password.length=decrement(password.length, {min: 5, max: 35})"> | |||
<button id="decreaseLength__btn" class="btn btn-primary btn-sm border-blue px-2" type="button"> | |||
<small><i class="fa fa-minus"></i></small> | |||
<span class="input-group-btn"> | |||
<button | |||
id="decreaseLength__btn" | |||
class="btn btn-primary btn-sm px-2" | |||
tabindex="1" | |||
type="button" | |||
v-on:click="options.length=decrement(options.length, {min: 5, max: 35})" | |||
> | |||
<small> | |||
<i class="fa fa-minus"></i> | |||
</small> | |||
</button> | |||
</span> | |||
<input id="passwordLength" | |||
class="form-control form-control-sm" | |||
type="number" | |||
min="5" | |||
max="35" | |||
v-model.number="password.length"> | |||
<span class="input-group-btn" | |||
v-on:click="password.length=increment(password.length, {min: 5, max: 35})"> | |||
<button id="increaseLength__btn" class="btn btn-primary btn-sm border-blue px-2" type="button"> | |||
<small><i class="fa fa-plus"></i></small> | |||
<input | |||
id="passwordLength" | |||
class="form-control form-control-sm" | |||
tabindex="1" | |||
type="number" | |||
min="5" | |||
max="35" | |||
v-model.number="options.length" | |||
/> | |||
<span class="input-group-btn"> | |||
<button | |||
id="increaseLength__btn" | |||
class="btn btn-primary btn-sm px-2" | |||
tabindex="1" | |||
type="button" | |||
v-on:click="options.length=increment(options.length, {min: 5, max: 35})" | |||
> | |||
<small> | |||
<i class="fa fa-plus"></i> | |||
</small> | |||
</button> | |||
</span> | |||
</div> | |||
</div> | |||
<div class="col-5 col-sm-4"> | |||
<label for="passwordCounter" | |||
data-balloon-length="large" | |||
v-bind:data-balloon="$t('CounterFieldHelp', 'Increment this value to change the generated password without changing your master password.')" | |||
data-balloon-pos="up"> | |||
{{$t('Counter')}} | |||
</label> | |||
<label | |||
for="passwordCounter" | |||
data-balloon-length="large" | |||
v-bind:data-balloon="$t('CounterFieldHelp', 'Increment this value to change the generated password without changing your master options.')" | |||
data-balloon-pos="up" | |||
>{{$t('Counter')}}</label> | |||
<div class="input-group input-group-sm"> | |||
<span id="decreaseCounter__btn" class="input-group-btn" | |||
v-on:click="password.counter=decrement(password.counter, {min: 1})"> | |||
<button class="btn btn-primary btn-sm border-blue px-2" type="button"> | |||
<small><i class="fa fa-minus"></i></small> | |||
<span class="input-group-btn"> | |||
<button | |||
id="decreaseCounter__btn" | |||
class="btn btn-primary btn-sm px-2" | |||
tabindex="1" | |||
type="button" | |||
v-on:click="options.counter=decrement(options.counter, {min: 1})" | |||
> | |||
<small> | |||
<i class="fa fa-minus"></i> | |||
</small> | |||
</button> | |||
</span> | |||
<input id="passwordCounter" | |||
class="form-control form-control-sm" | |||
type="number" | |||
min="1" | |||
v-model.number="password.counter"> | |||
<span id="increaseCounter__btn" class="input-group-btn" | |||
v-on:click="password.counter=increment(password.counter, {min: 1})"> | |||
<button class="btn btn-primary btn-sm border-blue px-2" type="button"> | |||
<small><i class="fa fa-plus"></i></small> | |||
<input | |||
id="passwordCounter" | |||
class="form-control form-control-sm" | |||
tabindex="1" | |||
type="number" | |||
min="1" | |||
v-model.number="options.counter" | |||
/> | |||
<span class="input-group-btn"> | |||
<button | |||
id="increaseCounter__btn" | |||
class="btn btn-primary btn-sm px-2" | |||
tabindex="1" | |||
type="button" | |||
v-on:click="options.counter=increment(options.counter, {min: 1})" | |||
> | |||
<small> | |||
<i class="fa fa-plus"></i> | |||
</small> | |||
</button> | |||
</span> | |||
</div> | |||
@@ -109,17 +152,16 @@ | |||
</template> | |||
<script type="text/ecmascript-6"> | |||
import {increment, decrement} from "../services/form-validator"; | |||
import { mapState} from 'vuex'; | |||
import { increment, decrement } from "../services/form-validator"; | |||
export default { | |||
name: 'options', | |||
computed: { | |||
...mapState(['password']), | |||
}, | |||
methods: { | |||
decrement, | |||
increment | |||
} | |||
export default { | |||
name: "options", | |||
props: { | |||
options: Object | |||
}, | |||
methods: { | |||
decrement, | |||
increment | |||
} | |||
}; | |||
</script> |
@@ -10,12 +10,3 @@ export const passwordURL = state => { | |||
const encodedPasswordProfile = encodeURIComponent(base64PasswordProfile); | |||
return `${state.baseURL}/#/?passwordProfileEncoded=${encodedPasswordProfile}`; | |||
}; | |||
export const isDefaultProfile = state => { | |||
for (let key in defaultOptions) { | |||
if (state.defaultPassword[key] !== state.password[key]) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
}; |
@@ -34,62 +34,6 @@ test("passwordURL encode uri component", () => { | |||
); | |||
}); | |||
test("isDefaultProfile", () => { | |||
const state = { | |||
password: { | |||
login: "test@example.org", | |||
site: "example.org", | |||
uppercase: true, | |||
lowercase: true, | |||
numbers: true, | |||
symbols: true, | |||
length: 16, | |||
counter: 1, | |||
version: 2 | |||
}, | |||
defaultPassword: { | |||
login: "", | |||
site: "", | |||
uppercase: true, | |||
lowercase: true, | |||
numbers: true, | |||
symbols: true, | |||
length: 16, | |||
counter: 1, | |||
version: 2 | |||
} | |||
}; | |||
expect(getters.isDefaultProfile(state)).toBe(true); | |||
}); | |||
test("isDefaultProfile false", () => { | |||
const state = { | |||
password: { | |||
login: "test@example.org", | |||
site: "example.org", | |||
uppercase: true, | |||
lowercase: true, | |||
numbers: true, | |||
symbols: false, | |||
length: 32, | |||
counter: 1, | |||
version: 1 | |||
}, | |||
defaultPassword: { | |||
login: "", | |||
site: "", | |||
uppercase: true, | |||
lowercase: true, | |||
numbers: true, | |||
symbols: true, | |||
length: 16, | |||
counter: 1, | |||
version: 2 | |||
} | |||
}; | |||
expect(getters.isDefaultProfile(state)).toBe(false); | |||
}); | |||
test("isAuthenticated", () => { | |||
const state = { | |||
authenticated: true | |||
@@ -34,6 +34,7 @@ div.awesomplete > ul { | |||
name="login" | |||
ref="login" | |||
class="form-control" | |||
tabindex="0" | |||
autocomplete="off" | |||
autocorrect="off" | |||
autocapitalize="none" | |||
@@ -50,75 +51,59 @@ div.awesomplete > ul { | |||
v-bind:label="$t('Master Password')" | |||
></master-password> | |||
</div> | |||
<div class="form-group" v-bind:class="{ 'mb-0': !showOptions }"> | |||
<div v-if="!passwordGenerated"> | |||
<button | |||
id="generatePassword__btn" | |||
type="submit" | |||
class="btn btn-primary border-blue" | |||
>{{ $t('Generate') }}</button> | |||
<button | |||
type="button" | |||
class="btn btn-secondary pull-right showOptions__btn" | |||
v-show="!passwordGenerated" | |||
v-on:click="showOptions =! showOptions" | |||
> | |||
<i class="fa fa-sliders"></i> | |||
</button> | |||
</div> | |||
<div class="btn-group" v-show="passwordGenerated"> | |||
<div class="input-group"> | |||
<span class="input-group-btn"> | |||
<button | |||
id="copyPasswordButton" | |||
class="btn btn-primary border-blue" | |||
type="button" | |||
v-on:click="copyPassword()" | |||
> | |||
<i class="fa fa-clipboard"></i> | |||
</button> | |||
</span> | |||
<input | |||
id="generated-password" | |||
type="password" | |||
class="form-control" | |||
tabindex="-1" | |||
ref="passwordGenerated" | |||
v-bind:value="passwordGenerated" | |||
/> | |||
<span class="input-group-btn"> | |||
<button | |||
id="revealGeneratedPassword" | |||
type="button" | |||
class="btn btn-secondary" | |||
v-on:click="togglePasswordType($refs.passwordGenerated)" | |||
> | |||
<i class="fa fa-eye"></i> | |||
</button> | |||
</span> | |||
<span class="input-group-btn"> | |||
<button | |||
id="sharePasswordProfileButton" | |||
type="button" | |||
class="btn btn-secondary" | |||
v-on:click="sharePasswordProfile()" | |||
> | |||
<i class="fa fa-share-alt pointer"></i> | |||
</button> | |||
</span> | |||
<span class="input-group-btn"> | |||
<button | |||
type="button" | |||
class="btn btn-secondary showOptions__btn" | |||
v-on:click="showOptions =! showOptions" | |||
> | |||
<i class="fa fa-sliders"></i> | |||
</button> | |||
</span> | |||
</div> | |||
<options v-bind:options="password"></options> | |||
<div class="form-group mt-4 mb-0"> | |||
<button | |||
id="generatePassword__btn" | |||
type="submit" | |||
tabindex="0" | |||
class="btn btn-primary btn-block" | |||
v-if="!passwordGenerated" | |||
>{{ $t('Generate') }}</button> | |||
<div class="input-group" v-show="passwordGenerated"> | |||
<span class="input-group-btn"> | |||
<button | |||
id="copyPasswordButton" | |||
class="btn btn-primary" | |||
tabindex="0" | |||
type="button" | |||
v-on:click="copyPassword()" | |||
> | |||
<i class="fa fa-clipboard"></i> | |||
</button> | |||
</span> | |||
<input | |||
id="generated-password" | |||
type="password" | |||
class="form-control" | |||
tabindex="-1" | |||
ref="passwordGenerated" | |||
v-bind:value="passwordGenerated" | |||
/> | |||
<span class="input-group-btn"> | |||
<button | |||
id="revealGeneratedPassword" | |||
type="button" | |||
class="btn btn-secondary" | |||
tabindex="0" | |||
v-on:click="togglePasswordType($refs.passwordGenerated)" | |||
> | |||
<i class="fa fa-eye"></i> | |||
</button> | |||
</span> | |||
<span class="input-group-btn"> | |||
<button | |||
id="sharePasswordProfileButton" | |||
type="button" | |||
class="btn btn-secondary" | |||
tabindex="0" | |||
v-on:click="sharePasswordProfile()" | |||
> | |||
<i class="fa fa-share-alt pointer"></i> | |||
</button> | |||
</span> | |||
</div> | |||
</div> | |||
<options v-if="showOptions || !isDefaultProfile"></options> | |||
</form> | |||
</template> | |||
<script type="text/ecmascript-6"> | |||
@@ -143,7 +128,7 @@ export default { | |||
}, | |||
computed: { | |||
...mapState(["password", "passwords"]), | |||
...mapGetters(["passwordURL", "isDefaultProfile"]) | |||
...mapGetters(["passwordURL"]) | |||
}, | |||
beforeMount() { | |||
this.$store.dispatch("getPasswords").then(() => { | |||
@@ -162,7 +147,6 @@ export default { | |||
}, | |||
data() { | |||
return { | |||
showOptions: false, | |||
masterPassword: "", | |||
passwordGenerated: "", | |||
cleanTimeout: null | |||
@@ -1,38 +1,47 @@ | |||
<template> | |||
<form id="lesspass-options-form" novalidate v-on:submit.prevent="saveAndExit"> | |||
<div class="form-group"> | |||
<label for="login" class="sr-only">{{ $t('Default login') }}</label> | |||
<div class="inner-addon left-addon"> | |||
<i class="fa fa-user"></i> | |||
<input | |||
id="login" | |||
type="text" | |||
name="login" | |||
ref="login" | |||
class="form-control" | |||
autocomplete="off" | |||
autocorrect="off" | |||
autocapitalize="none" | |||
v-bind:placeholder="$t('Default login')" | |||
v-model="defaultPassword.login" | |||
/> | |||
<div> | |||
<h5>{{$t('Options by default')}}</h5> | |||
<form id="lesspass-options-form" novalidate v-on:submit.prevent="saveAndExit"> | |||
<div class="form-group"> | |||
<label for="login">{{ $t('Login') }}</label> | |||
<div class="inner-addon left-addon"> | |||
<i class="fa fa-user"></i> | |||
<input | |||
id="login" | |||
type="text" | |||
name="login" | |||
ref="login" | |||
class="form-control" | |||
autocomplete="off" | |||
autocorrect="off" | |||
autocapitalize="none" | |||
v-bind:placeholder="$t('Login')" | |||
v-model="defaultPassword.login" | |||
/> | |||
</div> | |||
</div> | |||
</div> | |||
<button type="submit" class="btn btn-primary">{{$t('Save')}}</button> | |||
</form> | |||
<options v-bind:options="defaultPassword"></options> | |||
<button type="submit" class="btn btn-primary btn-block mt-4">{{$t('Save')}}</button> | |||
</form> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapState } from "vuex"; | |||
import Options from "../components/Options.vue"; | |||
import { mapState } from "vuex"; | |||
export default { | |||
computed: mapState(["defaultPassword"]), | |||
methods: { | |||
saveAndExit() { | |||
this.$store.dispatch('saveDefaultOptions', this.defaultPassword) | |||
.then(this.$store.dispatch('resetPassword')) | |||
.then(() => this.$router.push({name: 'home'})); | |||
} | |||
export default { | |||
computed: mapState(["defaultPassword"]), | |||
components: { | |||
Options | |||
}, | |||
methods: { | |||
saveAndExit() { | |||
this.$store | |||
.dispatch("saveDefaultOptions", this.defaultPassword) | |||
.then(this.$store.dispatch("resetPassword")) | |||
.then(() => this.$router.push({ name: "home" })); | |||
} | |||
} | |||
}; | |||
</script> |
@@ -232,7 +232,7 @@ | |||
esutils "^2.0.2" | |||
js-tokens "^4.0.0" | |||
"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.3", "@babel/parser@^7.6.4": | |||
"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.3", "@babel/parser@^7.6.4": | |||
version "7.6.4" | |||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81" | |||
integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A== | |||
@@ -739,7 +739,7 @@ | |||
"@babel/parser" "^7.6.0" | |||
"@babel/types" "^7.6.0" | |||
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3": | |||
"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3": | |||
version "7.6.3" | |||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9" | |||
integrity sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw== | |||
@@ -1547,17 +1547,6 @@ | |||
babel-loader "^8.0.6" | |||
webpack "^4.0.0" | |||
"@vue/cli-plugin-eslint@^4.0.4": | |||
version "4.0.4" | |||
resolved "https://registry.yarnpkg.com/@vue/cli-plugin-eslint/-/cli-plugin-eslint-4.0.4.tgz#7afddfdaf3bfdafdc826ed0c87edf41e67de3208" | |||
integrity sha512-YpQQLxHxzEVvTqs5zs4KSwqjGF6ILJ0OwD+4mPjCQL0Ms742RzzHb2MTLR1GF3bwcComwgNDNmmzzQERFiWajA== | |||
dependencies: | |||
"@vue/cli-shared-utils" "^4.0.4" | |||
eslint-loader "^2.1.2" | |||
globby "^9.2.0" | |||
webpack "^4.0.0" | |||
yorkie "^2.0.0" | |||
"@vue/cli-plugin-router@^4.0.4": | |||
version "4.0.4" | |||
resolved "https://registry.yarnpkg.com/@vue/cli-plugin-router/-/cli-plugin-router-4.0.4.tgz#e1010d3844519baad517f6050541711f6157942a" | |||
@@ -1898,7 +1887,7 @@ acorn@^5.5.0, acorn@^5.5.3: | |||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" | |||
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== | |||
acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.7, acorn@^6.1.1, acorn@^6.2.1: | |||
acorn@^6.0.1, acorn@^6.0.7, acorn@^6.1.1, acorn@^6.2.1: | |||
version "6.3.0" | |||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" | |||
integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== | |||
@@ -2050,6 +2039,14 @@ ajv@^5.1.0: | |||
fast-json-stable-stringify "^2.0.0" | |||
json-schema-traverse "^0.3.0" | |||
ally.js@^1.4.1: | |||
version "1.4.1" | |||
resolved "https://registry.yarnpkg.com/ally.js/-/ally.js-1.4.1.tgz#9fb7e6ba58efac4ee9131cb29aa9ee3b540bcf1e" | |||
integrity sha1-n7fmuljvrE7pExyymqnuO1QLzx4= | |||
dependencies: | |||
css.escape "^1.5.0" | |||
platform "1.3.3" | |||
alphanum-sort@^1.0.0: | |||
version "1.0.2" | |||
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" | |||
@@ -2551,18 +2548,6 @@ babel-core@7.0.0-bridge.0: | |||
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" | |||
integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== | |||
babel-eslint@^10.0.3: | |||
version "10.0.3" | |||
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" | |||
integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== | |||
dependencies: | |||
"@babel/code-frame" "^7.0.0" | |||
"@babel/parser" "^7.0.0" | |||
"@babel/traverse" "^7.0.0" | |||
"@babel/types" "^7.0.0" | |||
eslint-visitor-keys "^1.0.0" | |||
resolve "^1.12.0" | |||
babel-jest@^24.9.0: | |||
version "24.9.0" | |||
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" | |||
@@ -4325,6 +4310,11 @@ css-what@2.1, css-what@^2.1.2: | |||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" | |||
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== | |||
css.escape@^1.5.0: | |||
version "1.5.1" | |||
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" | |||
integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= | |||
css@^2.1.0: | |||
version "2.2.4" | |||
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" | |||
@@ -4454,6 +4444,13 @@ cyclist@^1.0.1: | |||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" | |||
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= | |||
cypress-plugin-tab@^1.0.3: | |||
version "1.0.3" | |||
resolved "https://registry.yarnpkg.com/cypress-plugin-tab/-/cypress-plugin-tab-1.0.3.tgz#8a64a4c189c5d180dc0a97175097c0cc937c1213" | |||
integrity sha512-uiadGT+IzoGxKCqYxQXyc5OhHkv4JAT5LWwNTs8R6pBJkBUUC/uZR2ys4jqhqX6mD/ZucAt5p+U9KMr8Ae4fQA== | |||
dependencies: | |||
ally.js "^1.4.1" | |||
cypress@^3.4.0: | |||
version "3.4.1" | |||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.4.1.tgz#ca2e4e9864679da686c6a6189603efd409664c30" | |||
@@ -5363,17 +5360,6 @@ escope@^3.6.0: | |||
esrecurse "^4.1.0" | |||
estraverse "^4.1.1" | |||
eslint-loader@^2.1.2: | |||
version "2.2.1" | |||
resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-2.2.1.tgz#28b9c12da54057af0845e2a6112701a2f6bf8337" | |||
integrity sha512-RLgV9hoCVsMLvOxCuNjdqOrUqIj9oJg8hF44vzJaYqsAHuY9G2YAeN3joQ9nxP0p5Th9iFSIpKo+SD8KISxXRg== | |||
dependencies: | |||
loader-fs-cache "^1.0.0" | |||
loader-utils "^1.0.2" | |||
object-assign "^4.0.1" | |||
object-hash "^1.1.4" | |||
rimraf "^2.6.1" | |||
eslint-plugin-no-unsafe-innerhtml@1.0.16: | |||
version "1.0.16" | |||
resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsafe-innerhtml/-/eslint-plugin-no-unsafe-innerhtml-1.0.16.tgz#7d02878c8e9bf7916b88836d5ac122b42f151932" | |||
@@ -5381,14 +5367,7 @@ eslint-plugin-no-unsafe-innerhtml@1.0.16: | |||
dependencies: | |||
eslint "^3.7.1" | |||
eslint-plugin-vue@^5.0.0: | |||
version "5.2.3" | |||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-5.2.3.tgz#3ee7597d823b5478804b2feba9863b1b74273961" | |||
integrity sha512-mGwMqbbJf0+VvpGR5Lllq0PMxvTdrZ/ZPjmhkacrCHbubJeJOt+T6E3HUzAifa2Mxi7RSdJfC9HFpOeSYVMMIw== | |||
dependencies: | |||
vue-eslint-parser "^5.0.0" | |||
eslint-scope@^4.0.0, eslint-scope@^4.0.3: | |||
eslint-scope@^4.0.3: | |||
version "4.0.3" | |||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" | |||
integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== | |||
@@ -5408,7 +5387,7 @@ eslint-visitor-keys@1.1.0, eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1. | |||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" | |||
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== | |||
eslint@5.16.0, eslint@^5.16.0: | |||
eslint@5.16.0: | |||
version "5.16.0" | |||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" | |||
integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== | |||
@@ -5508,15 +5487,6 @@ espree@^3.4.0: | |||
acorn "^5.5.0" | |||
acorn-jsx "^3.0.0" | |||
espree@^4.1.0: | |||
version "4.1.0" | |||
resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" | |||
integrity sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w== | |||
dependencies: | |||
acorn "^6.0.2" | |||
acorn-jsx "^5.0.0" | |||
eslint-visitor-keys "^1.0.0" | |||
espree@^5.0.1: | |||
version "5.0.1" | |||
resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" | |||
@@ -5667,19 +5637,6 @@ execa@^0.7.0: | |||
signal-exit "^3.0.0" | |||
strip-eof "^1.0.0" | |||
execa@^0.8.0: | |||
version "0.8.0" | |||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" | |||
integrity sha1-2NdrvBtVIX7RkP1t1J08d07PyNo= | |||
dependencies: | |||
cross-spawn "^5.0.1" | |||
get-stream "^3.0.0" | |||
is-stream "^1.1.0" | |||
npm-run-path "^2.0.0" | |||
p-finally "^1.0.0" | |||
signal-exit "^3.0.0" | |||
strip-eof "^1.0.0" | |||
execa@^1.0.0: | |||
version "1.0.0" | |||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" | |||
@@ -6090,15 +6047,6 @@ find-babel-config@^1.1.0: | |||
json5 "^0.5.1" | |||
path-exists "^3.0.0" | |||
find-cache-dir@^0.1.1: | |||
version "0.1.1" | |||
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" | |||
integrity sha1-yN765XyKUqinhPnjHFfHQumToLk= | |||
dependencies: | |||
commondir "^1.0.1" | |||
mkdirp "^0.5.1" | |||
pkg-dir "^1.0.0" | |||
find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: | |||
version "2.1.0" | |||
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" | |||
@@ -7604,7 +7552,7 @@ is-callable@^1.1.3, is-callable@^1.1.4: | |||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" | |||
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== | |||
is-ci@1.2.1, is-ci@^1.0.10: | |||
is-ci@1.2.1: | |||
version "1.2.1" | |||
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" | |||
integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== | |||
@@ -9078,14 +9026,6 @@ load-json-file@^4.0.0: | |||
pify "^3.0.0" | |||
strip-bom "^3.0.0" | |||
loader-fs-cache@^1.0.0: | |||
version "1.0.2" | |||
resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.2.tgz#54cedf6b727e1779fd8f01205f05f6e88706f086" | |||
integrity sha512-70IzT/0/L+M20jUlEqZhZyArTU6VKLRTYRDAYN26g4jfzpJqjipLL3/hgYpySqI9PwsVRHHFja0LfEmsx9X2Cw== | |||
dependencies: | |||
find-cache-dir "^0.1.1" | |||
mkdirp "0.5.1" | |||
loader-runner@^2.3.1, loader-runner@^2.4.0: | |||
version "2.4.0" | |||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" | |||
@@ -10116,11 +10056,6 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package- | |||
semver "2 || 3 || 4 || 5" | |||
validate-npm-package-license "^3.0.1" | |||
normalize-path@^1.0.0: | |||
version "1.0.0" | |||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" | |||
integrity sha1-MtDkcvkf80VwHBWoMRAY07CpA3k= | |||
normalize-path@^2.0.0, normalize-path@^2.1.1: | |||
version "2.1.1" | |||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" | |||
@@ -10260,11 +10195,6 @@ object-copy@^0.1.0: | |||
define-property "^0.2.5" | |||
kind-of "^3.0.3" | |||
object-hash@^1.1.4: | |||
version "1.3.1" | |||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" | |||
integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== | |||
object-inspect@^1.6.0: | |||
version "1.6.0" | |||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" | |||
@@ -11003,13 +10933,6 @@ pixelmatch@^4.0.0, pixelmatch@^4.0.2: | |||
dependencies: | |||
pngjs "^3.0.0" | |||
pkg-dir@^1.0.0: | |||
version "1.0.0" | |||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" | |||
integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= | |||
dependencies: | |||
find-up "^1.0.0" | |||
pkg-dir@^3.0.0: | |||
version "3.0.0" | |||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" | |||
@@ -11031,6 +10954,11 @@ pkg-up@^2.0.0: | |||
dependencies: | |||
find-up "^2.1.0" | |||
platform@1.3.3: | |||
version "1.3.3" | |||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.3.tgz#646c77011899870b6a0903e75e997e8e51da7461" | |||
integrity sha1-ZGx3ARiZhwtqCQPnXpl+jlHadGE= | |||
pluralize@^1.2.1: | |||
version "1.2.1" | |||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" | |||
@@ -12211,7 +12139,7 @@ resolve@1.1.7: | |||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" | |||
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= | |||
resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1: | |||
resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1: | |||
version "1.12.0" | |||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" | |||
integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== | |||
@@ -13343,11 +13271,6 @@ strip-indent@^1.0.1: | |||
dependencies: | |||
get-stdin "^4.0.1" | |||
strip-indent@^2.0.0: | |||
version "2.0.0" | |||
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" | |||
integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= | |||
strip-json-comments@2.0.1, strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: | |||
version "2.0.1" | |||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" | |||
@@ -14355,18 +14278,6 @@ void-elements@^2.0.0: | |||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" | |||
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= | |||
vue-eslint-parser@^5.0.0: | |||
version "5.0.0" | |||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz#00f4e4da94ec974b821a26ff0ed0f7a78402b8a1" | |||
integrity sha512-JlHVZwBBTNVvzmifwjpZYn0oPWH2SgWv5dojlZBsrhablDu95VFD+hriB1rQGwbD+bms6g+rAFhQHk6+NyiS6g== | |||
dependencies: | |||
debug "^4.1.0" | |||
eslint-scope "^4.0.0" | |||
eslint-visitor-keys "^1.0.0" | |||
espree "^4.1.0" | |||
esquery "^1.0.1" | |||
lodash "^4.17.11" | |||
vue-hot-reload-api@^2.3.0: | |||
version "2.3.4" | |||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" | |||
@@ -15149,16 +15060,6 @@ yeast@0.1.2: | |||
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" | |||
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= | |||
yorkie@^2.0.0: | |||
version "2.0.0" | |||
resolved "https://registry.yarnpkg.com/yorkie/-/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9" | |||
integrity sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw== | |||
dependencies: | |||
execa "^0.8.0" | |||
is-ci "^1.0.10" | |||
normalize-path "^1.0.0" | |||
strip-indent "^2.0.0" | |||
zip-dir@1.0.2: | |||
version "1.0.2" | |||
resolved "https://registry.yarnpkg.com/zip-dir/-/zip-dir-1.0.2.tgz#253f907aead62a21acd8721d8b88032b2411c051" | |||