[ci skip] Fix more rules

上级 615f1927
......@@ -37,6 +37,16 @@
"import/no-commonjs": "error",
"no-multiple-empty-lines": ["error", { "max": 1 }],
"promise/catch-or-return": "error",
"no-underscore-dangle": ["error", { "allow": ["__"]}]
"no-underscore-dangle": ["error", { "allow": ["__"]}],
"vue/html-self-closing": ["error", {
"html": {
"void": "always",
"normal": "any",
"component": "always"
},
"svg": "always",
"math": "any"
}]
}
}
<script>
export default {
name: 'modal',
props: {
title: {
type: String,
required: false,
},
text: {
type: String,
required: false,
},
hideFooter: {
type: Boolean,
required: false,
default: false,
},
kind: {
type: String,
required: false,
default: 'primary',
},
modalDialogClass: {
type: String,
required: false,
default: '',
},
closeKind: {
type: String,
required: false,
default: 'default',
},
closeButtonLabel: {
type: String,
required: false,
default: 'Cancel',
},
primaryButtonLabel: {
type: String,
required: false,
default: '',
},
submitDisabled: {
type: Boolean,
required: false,
default: false,
export default {
name: 'Modal',
props: {
title: {
type: String,
required: false,
default: '',
},
text: {
type: String,
required: false,
default: '',
},
hideFooter: {
type: Boolean,
required: false,
default: false,
},
kind: {
type: String,
required: false,
default: 'primary',
},
modalDialogClass: {
type: String,
required: false,
default: '',
},
closeKind: {
type: String,
required: false,
default: 'default',
},
closeButtonLabel: {
type: String,
required: false,
default: 'Cancel',
},
primaryButtonLabel: {
type: String,
required: false,
default: '',
},
submitDisabled: {
type: Boolean,
required: false,
default: false,
},
},
},
computed: {
btnKindClass() {
return {
[`btn-${this.kind}`]: true,
};
computed: {
btnKindClass() {
return {
[`btn-${this.kind}`]: true,
};
},
btnCancelKindClass() {
return {
[`btn-${this.closeKind}`]: true,
};
},
},
btnCancelKindClass() {
return {
[`btn-${this.closeKind}`]: true,
};
},
},
methods: {
close() {
this.$emit('toggle', false);
},
emitSubmit(status) {
this.$emit('submit', status);
methods: {
close() {
this.$emit('toggle', false);
},
emitSubmit(status) {
this.$emit('submit', status);
},
},
},
};
};
</script>
<template>
<div class="modal-open">
<div
class="modal show"
role="dialog"
tabindex="-1"
>
<div class="modal-open">
<div
:class="modalDialogClass"
class="modal-dialog"
role="document"
class="modal show"
role="dialog"
tabindex="-1"
>
<div class="modal-content">
<div class="modal-header">
<slot name="header">
<h4 class="modal-title pull-left">
{{this.title}}
</h4>
<div
:class="modalDialogClass"
class="modal-dialog"
role="document"
>
<div class="modal-content">
<div class="modal-header">
<slot name="header">
<h4 class="modal-title pull-left">
{{ this.title }}
</h4>
<button
type="button"
class="close pull-right"
@click="close"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</slot>
</div>
<div class="modal-body">
<slot name="body">
</slot>
</div>
<div
class="modal-footer"
v-if="!hideFooter"
>
<button
type="button"
class="close pull-right"
@click="close"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
class="btn pull-left"
:class="btnCancelKindClass"
@click="close">
{{ closeButtonLabel }}
</button>
</slot>
</div>
<div class="modal-body">
<slot name="body" :text="text">
<p>{{this.text}}</p>
</slot>
</div>
<div class="modal-footer" v-if="!hideFooter">
<button
type="button"
class="btn pull-left"
:class="btnCancelKindClass"
@click="close">
{{ closeButtonLabel }}
</button>
<button
v-if="primaryButtonLabel"
type="button"
class="btn pull-right js-primary-button"
:disabled="submitDisabled"
:class="btnKindClass"
@click="emitSubmit(true)">
{{ primaryButtonLabel }}
</button>
<button
v-if="primaryButtonLabel"
type="button"
class="btn pull-right js-primary-button"
:disabled="submitDisabled"
:class="btnKindClass"
@click="emitSubmit(true)">
{{ primaryButtonLabel }}
</button>
</div>
</div>
</div>
</div>
<div class="modal-backdrop fade in"></div>
</div>
<div class="modal-backdrop fade in" />
</div>
</template>
......@@ -45,7 +45,7 @@
this.$emit('onChangeTab', tab.scope);
},
},
};
};
</script>
<template>
<ul class="nav-links scrolling-tabs">
......@@ -55,21 +55,20 @@
:class="{
active: tab.isActive,
}"
>
>
<a
role="button"
@click="onTabClick(tab)"
:class="`js-${scope}-tab-${tab.scope}`"
>
>
{{ tab.name }}
<span
v-if="shouldRenderBadge(tab.count)"
class="badge"
>
{{tab.count}}
>
{{ tab.count }}
</span>
</a>
</li>
</ul>
......
......@@ -20,16 +20,16 @@
import userAvatarLink from '../user_avatar/user_avatar_link.vue';
export default {
name: 'placeholderNote',
name: 'PlaceholderNote',
components: {
userAvatarLink,
},
props: {
note: {
type: Object,
required: true,
},
},
components: {
userAvatarLink,
},
computed: {
...mapGetters([
'getUserData',
......@@ -46,7 +46,7 @@
:link-href="getUserData.path"
:img-src="getUserData.avatar_url"
:img-size="40"
/>
/>
</div>
<div
:class="{ discussion: !note.individual_note }"
......@@ -54,14 +54,14 @@
<div class="note-header">
<div class="note-header-info">
<a :href="getUserData.path">
<span class="hidden-xs">{{getUserData.name}}</span>
<span class="note-headline-light">@{{getUserData.username}}</span>
<span class="hidden-xs">{{ getUserData.name }}</span>
<span class="note-headline-light">@{{ getUserData.username }}</span>
</a>
</div>
</div>
<div class="note-body">
<div class="note-text">
<p>{{note.body}}</p>
<p>{{ note.body }}</p>
</div>
</div>
</div>
......
......@@ -8,7 +8,7 @@
* />
*/
export default {
name: 'placeholderSystemNote',
name: 'PlaceholderSystemNote',
props: {
note: {
type: Object,
......@@ -20,10 +20,10 @@
<template>
<li class="note system-note timeline-entry being-posted fade-in-half">
<div class="timeline-entry-inner">
<div class="timeline-content">
<em>{{note.body}}</em>
</div>
</div>
<div class="timeline-entry-inner">
<div class="timeline-content">
<em>{{ note.body }}</em>
</div>
</div>
</li>
</template>
......@@ -21,16 +21,16 @@
import { spriteIcon } from '../../../lib/utils/common_utils';
export default {
name: 'systemNote',
name: 'SystemNote',
components: {
noteHeader,
},
props: {
note: {
type: Object,
required: true,
},
},
components: {
noteHeader,
},
computed: {
...mapGetters([
'targetNoteHash',
......
<script>
export default {
props: {
startSize: {
type: Number,
required: true,
export default {
props: {
startSize: {
type: Number,
required: true,
},
side: {
type: String,
required: true,
},
minSize: {
type: Number,
required: false,
default: 0,
},
maxSize: {
type: Number,
required: false,
default: Number.MAX_VALUE,
},
enabled: {
type: Boolean,
required: false,
default: true,
},
},
side: {
type: String,
required: true,
data() {
return {
size: this.startSize,
};
},
minSize: {
type: Number,
required: false,
default: 0,
computed: {
className() {
return `drag${this.side}`;
},
cursorStyle() {
if (this.enabled) {
return { cursor: 'ew-resize' };
}
return {};
},
},
maxSize: {
type: Number,
required: false,
default: Number.MAX_VALUE,
},
enabled: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
size: this.startSize,
};
},
computed: {
className() {
return `drag${this.side}`;
},
cursorStyle() {
if (this.enabled) {
return { cursor: 'ew-resize' };
}
return {};
},
},
methods: {
resetSize(e) {
e.preventDefault();
this.size = this.startSize;
this.$emit('update:size', this.size);
},
startDrag(e) {
if (this.enabled) {
methods: {
resetSize(e) {
e.preventDefault();
this.startPos = e.clientX;
this.currentStartSize = this.size;
document.addEventListener('mousemove', this.drag);
document.addEventListener('mouseup', this.endDrag, { once: true });
this.$emit('resize-start', this.size);
}
},
drag(e) {
e.preventDefault();
let moved = e.clientX - this.startPos;
if (this.side === 'left') moved = -moved;
let newSize = this.currentStartSize + moved;
if (newSize < this.minSize) {
newSize = this.minSize;
} else if (newSize > this.maxSize) {
newSize = this.maxSize;
}
this.size = newSize;
this.size = this.startSize;
this.$emit('update:size', this.size);
},
startDrag(e) {
if (this.enabled) {
e.preventDefault();
this.startPos = e.clientX;
this.currentStartSize = this.size;
document.addEventListener('mousemove', this.drag);
document.addEventListener('mouseup', this.endDrag, { once: true });
this.$emit('resize-start', this.size);
}
},
drag(e) {
e.preventDefault();
let moved = e.clientX - this.startPos;
if (this.side === 'left') moved = -moved;
let newSize = this.currentStartSize + moved;
if (newSize < this.minSize) {
newSize = this.minSize;
} else if (newSize > this.maxSize) {
newSize = this.maxSize;
}
this.size = newSize;
this.$emit('update:size', newSize);
},
endDrag(e) {
e.preventDefault();
document.removeEventListener('mousemove', this.drag);
this.$emit('resize-end', this.size);
this.$emit('update:size', newSize);
},
endDrag(e) {
e.preventDefault();
document.removeEventListener('mousemove', this.drag);
this.$emit('resize-end', this.size);
},
},
},
};
};
</script>
<template>
<div
<div
class="dragHandle"
:class="className"
:style="cursorStyle"
......
......@@ -3,7 +3,7 @@
import { parsePikadayDate, pikadayToString } from '../../lib/utils/datefix';
export default {
name: 'datePicker',
name: 'DatePicker',
props: {
label: {
type: String,
......@@ -23,14 +23,6 @@
required: false,
},
},
methods: {
selected(dateText) {
this.$emit('newDateSelected', this.calendar.toString(dateText));
},
toggled() {
this.$emit('hidePicker');
},
},
mounted() {
this.calendar = new Pikaday({
field: this.$el.querySelector('.dropdown-menu-toggle'),
......@@ -53,6 +45,14 @@
beforeDestroy() {
this.calendar.destroy();
},
methods: {
selected(dateText) {
this.$emit('newDateSelected', this.calendar.toString(dateText));
},
toggled() {
this.$emit('hidePicker');
},
},
};
</script>
......@@ -66,7 +66,7 @@
@click="toggled"
>
<span class="dropdown-toggle-text">
{{label}}
{{ label }}
</span>
<i
class="fa fa-chevron-down"
......
<script>
/* This is a re-usable vue component for rendering a project avatar that
does not need to link to the project's profile. The image and an optional
tooltip can be configured by props passed to this component.
/* This is a re-usable vue component for rendering a project avatar that
does not need to link to the project's profile. The image and an optional
tooltip can be configured by props passed to this component.
Sample configuration:
Sample configuration:
<project-avatar-image
:lazy="true"
:img-src="projectAvatarSrc"
:img-alt="tooltipText"
:tooltip-text="tooltipText"
tooltip-placement="top"
/>
<project-avatar-image
:lazy="true"
:img-src="projectAvatarSrc"
:img-alt="tooltipText"
:tooltip-text="tooltipText"
tooltip-placement="top"
/>
*/
*/
import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '../../../lazy_loader';
import tooltip from '../../directives/tooltip';
import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '../../../lazy_loader';
import tooltip from '../../directives/tooltip';
export default {
name: 'ProjectAvatarImage',
props: {
lazy: {
type: Boolean,
required: false,
default: false,
},
imgSrc: {
type: String,
required: false,
default: defaultAvatarUrl,
},
cssClasses: {
type: String,
required: false,
default: '',
},
imgAlt: {
type: String,
required: false,
default: 'project avatar',
},
size: {
type: Number,
required: false,
default: 20,
},
tooltipText: {
type: String,
required: false,
default: '',
},
tooltipPlacement: {
type: String,
required: false,
default: 'top',
},
},
directives: {
tooltip,
},
computed: {
// API response sends null when gravatar is disabled and
// we provide an empty string when we use it inside project avatar link.
// In both cases we should render the defaultAvatarUrl
sanitizedSource() {
return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
},
resultantSrcAttribute() {
return this.lazy ? placeholderImage : this.sanitizedSource;
export default {
name: 'ProjectAvatarImage',
directives: {
tooltip,
},
tooltipContainer() {
return this.tooltipText ? 'body' : null;
props: {
lazy: {
type: Boolean,
required: false,
default: false,
},
imgSrc: {
type: String,
required: false,
default: defaultAvatarUrl,
},
cssClasses: {
type: String,
required: false,
default: '',
},
imgAlt: {
type: String,
required: false,
default: 'project avatar',
},
size: {
type: Number,
required: false,
default: 20,
},
tooltipText: {
type: String,
required: false,
default: '',
},
tooltipPlacement: {
type: String,
required: false,
default: 'top',
},
},
avatarSizeClass() {
return `s${this.size}`;
computed: {
// API response sends null when gravatar is disabled and
// we provide an empty string when we use it inside project avatar link.
// In both cases we should render the defaultAvatarUrl
sanitizedSource() {
return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
},
resultantSrcAttribute() {
return this.lazy ? placeholderImage : this.sanitizedSource;
},
tooltipContainer() {
return this.tooltipText ? 'body' : null;
},
avatarSizeClass() {
return `s${this.size}`;
},
},
},
};
};
</script>
<template>
......@@ -87,7 +87,7 @@ export default {
v-tooltip
class="avatar"
:class="{
lazy,
lazy: lazy,
[avatarSizeClass]: true,
[cssClasses]: true
}"
......
......@@ -2,8 +2,10 @@
import modal from './modal.vue';
export default {
name: 'recaptcha-modal',
name: 'RecaptchaModal',
components: {
modal,
},
props: {
html: {
type: String,
......@@ -18,11 +20,14 @@ export default {
scriptSrc: 'https://www.google.com/recaptcha/api.js',
};
},
components: {
modal,
watch: {
html() {
this.appendRecaptchaScript();
},
},
mounted() {
window.recaptchaDialogCallback = this.submit.bind(this);
},
methods: {
appendRecaptchaScript() {
this.removeRecaptchaScript();
......@@ -51,35 +56,26 @@ export default {
this.$el.querySelector('form').submit();
},
},
watch: {
html() {
this.appendRecaptchaScript();
},
},
mounted() {
window.recaptchaDialogCallback = this.submit.bind(this);
},
};
</script>
<template>
<modal
kind="warning"
class="recaptcha-modal js-recaptcha-modal"
:hide-footer="true"
:title="__('Please solve the reCAPTCHA')"
@toggle="close"
>
<div slot="body">
<p>
{{__('We want to be sure it is you, please confirm you are not a robot.')}}
</p>
<div
ref="recaptcha"
v-html="html"
></div>
</div>
</modal>
<modal
kind="warning"
class="recaptcha-modal js-recaptcha-modal"
:hide-footer="true"
:title="__('Please solve the reCAPTCHA')"
@toggle="close"
>
<div slot="body">
<p>
{{ __('We want to be sure it is you, please confirm you are not a robot.') }}
</p>
<div
ref="recaptcha"
v-html="html"
>
</div>
</div>
</modal>
</template>
<script>
export default {
name: 'collapsedCalendarIcon',
name: 'CollapsedCalendarIcon',
props: {
containerClass: {
type: String,
......
......@@ -4,7 +4,11 @@
import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
export default {
name: 'sidebarCollapsedGroupedDatePicker',
name: 'SidebarCollapsedGroupedDatePicker',
components: {
toggleSidebar,
collapsedCalendarIcon,
},
props: {
collapsed: {
type: Boolean,
......@@ -30,10 +34,6 @@
default: false,
},
},
components: {
toggleSidebar,
collapsedCalendarIcon,
},
computed: {
hasMinAndMaxDates() {
return this.minDate && this.maxDate;
......
......@@ -6,7 +6,13 @@
import { dateInWords } from '../../../lib/utils/datetime_utility';
export default {
name: 'sidebarDatePicker',
name: 'SidebarDatePicker',
components: {
datePicker,
toggleSidebar,
loadingIcon,
collapsedCalendarIcon,
},
props: {
collapsed: {
type: Boolean,
......@@ -51,12 +57,6 @@
editing: false,
};
},
components: {
datePicker,
toggleSidebar,
loadingIcon,
collapsedCalendarIcon,
},
computed: {
selectedAndEditable() {
return this.selectedDate && this.editable;
......
<script>
export default {
name: 'toggleSidebar',
name: 'ToggleSidebar',
props: {
collapsed: {
type: Boolean,
......@@ -25,6 +25,6 @@
aria-label="toggle collapse"
class="fa"
:class="{ 'fa-angle-double-right': !collapsed, 'fa-angle-double-left': collapsed }"
></i>
/>
</button>
</template>
<script>
import { s__ } from '../../locale';
const PAGINATION_UI_BUTTON_LIMIT = 4;
const UI_LIMIT = 6;
const SPREAD = '...';
const PREV = s__('Pagination|Prev');
const NEXT = s__('Pagination|Next');
const FIRST = s__('Pagination|« First');
const LAST = s__('Pagination|Last »');
export default {
props: {
/**
This function will take the information given by the pagination component
Here is an example `change` method:
change(pagenum) {
gl.utils.visitUrl(`?page=${pagenum}`);
import { s__ } from '../../locale';
const PAGINATION_UI_BUTTON_LIMIT = 4;
const UI_LIMIT = 6;
const SPREAD = '...';
const PREV = s__('Pagination|Prev');
const NEXT = s__('Pagination|Next');
const FIRST = s__('Pagination|« First');
const LAST = s__('Pagination|Last »');
export default {
props: {
/**
This function will take the information given by the pagination component
*/
change: {
type: Function,
required: true,
},
*/
change: {
type: Function,
required: true,
},
/**
pageInfo will come from the headers of the API call
in the `.then` clause of the VueResource API call
there should be a function that contructs the pageInfo for this component
This is an example:
const pageInfo = headers => ({
perPage: +headers['X-Per-Page'],
page: +headers['X-Page'],
total: +headers['X-Total'],
totalPages: +headers['X-Total-Pages'],
nextPage: +headers['X-Next-Page'],
previousPage: +headers['X-Prev-Page'],
});
*/
pageInfo: {
type: Object,
required: true,
},
},
methods: {
changePage(e) {
if (e.target.parentElement.classList.contains('disabled')) return;
const text = e.target.innerText;
const { totalPages, nextPage, previousPage } = this.pageInfo;
switch (text) {
case SPREAD:
break;
case LAST:
this.change(totalPages);
break;
case NEXT:
this.change(nextPage);
break;
case PREV:
this.change(previousPage);
break;
case FIRST:
this.change(1);
break;
default:
this.change(+text);
break;
}
},
},
computed: {
prev() {
return this.pageInfo.previousPage;
},
next() {
return this.pageInfo.nextPage;
/**
pageInfo will come from the headers of the API call
in the `.then` clause of the VueResource API call
there should be a function that contructs the pageInfo for this component
This is an example:
const pageInfo = headers => ({
perPage: +headers['X-Per-Page'],
page: +headers['X-Page'],
total: +headers['X-Total'],
totalPages: +headers['X-Total-Pages'],
nextPage: +headers['X-Next-Page'],
previousPage: +headers['X-Prev-Page'],
});
*/
pageInfo: {
type: Object,
required: true,
},
},
getItems() {
const total = this.pageInfo.totalPages;
const page = this.pageInfo.page;
const items = [];
if (page > 1) {
items.push({ title: FIRST, first: true });
}
if (page > 1) {
items.push({ title: PREV, prev: true });
} else {
items.push({ title: PREV, disabled: true, prev: true });
}
if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total);
for (let i = start; i <= end; i += 1) {
const isActive = i === page;
items.push({ title: i, active: isActive, page: true });
}
if (total - page > PAGINATION_UI_BUTTON_LIMIT) {
items.push({ title: SPREAD, separator: true, page: true });
}
if (page === total) {
items.push({ title: NEXT, disabled: true, next: true });
} else if (total - page >= 1) {
items.push({ title: NEXT, next: true });
}
if (total - page >= 1) {
items.push({ title: LAST, last: true });
}
return items;
computed: {
prev() {
return this.pageInfo.previousPage;
},
next() {
return this.pageInfo.nextPage;
},
getItems() {
const total = this.pageInfo.totalPages;
const page = this.pageInfo.page;
const items = [];
if (page > 1) {
items.push({ title: FIRST, first: true });
}
if (page > 1) {
items.push({ title: PREV, prev: true });
} else {
items.push({ title: PREV, disabled: true, prev: true });
}
if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total);
for (let i = start; i <= end; i += 1) {
const isActive = i === page;
items.push({ title: i, active: isActive, page: true });
}
if (total - page > PAGINATION_UI_BUTTON_LIMIT) {
items.push({ title: SPREAD, separator: true, page: true });
}
if (page === total) {
items.push({ title: NEXT, disabled: true, next: true });
} else if (total - page >= 1) {
items.push({ title: NEXT, next: true });
}
if (total - page >= 1) {
items.push({ title: LAST, last: true });
}
return items;
},
showPagination() {
return this.pageInfo.totalPages > 1;
},
},
showPagination() {
return this.pageInfo.totalPages > 1;
methods: {
changePage(e) {
if (e.target.parentElement.classList.contains('disabled')) return;
const text = e.target.innerText;
const { totalPages, nextPage, previousPage } = this.pageInfo;
switch (text) {
case SPREAD:
break;
case LAST:
this.change(totalPages);
break;
case NEXT:
this.change(nextPage);
break;
case PREV:
this.change(previousPage);
break;
case FIRST:
this.change(1);
break;
default:
this.change(+text);
break;
}
},
},
},
};
};
</script>
<template>
<div
......@@ -135,7 +129,8 @@ export default {
>
<ul class="pagination clearfix">
<li
v-for="item in getItems"
v-for="(item, index) in getItems"
:key="index"
:class="{
page: item.page,
'js-previous-button': item.prev,
......@@ -145,8 +140,11 @@ export default {
separator: item.separator,
active: item.active,
disabled: item.disabled
}">
<a @click.prevent="changePage($event)">{{item.title}}</a>
}"
>
<a @click.prevent="changePage($event)">
{{ item.title }}
</a>
</li>
</ul>
</div>
......
......@@ -40,6 +40,6 @@ export default {
:height="size"
:width="size"
v-html="svg"
/>
/>
</template>
......@@ -2372,9 +2372,9 @@ eslint-plugin-filenames@^1.1.0:
lodash.kebabcase "4.0.1"
lodash.snakecase "4.0.1"
eslint-plugin-html@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-4.0.1.tgz#fc70072263cc938496fbbc9cf648660e41fa269a"
eslint-plugin-html@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-2.0.1.tgz#3a829510e82522f1e2e44d55d7661a176121fce1"
dependencies:
htmlparser2 "^3.8.2"
......@@ -2419,9 +2419,9 @@ eslint-visitor-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
eslint@^3.10.1:
version "3.19.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
eslint@3.18.0:
version "3.18.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.18.0.tgz#647e985c4ae71502d20ac62c109f66d5104c8a4b"
dependencies:
babel-code-frame "^6.16.0"
chalk "^1.1.3"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册