Add search from trackers dialog (#46)

This commit is contained in:
Bogdan Bogdanov
2020-09-01 19:41:23 +03:00
committed by GitHub
parent bfe0ba0fd0
commit cae3b119ca
13 changed files with 455 additions and 203 deletions

View File

@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/camelcase */
import Axios, { AxiosInstance, AxiosResponse } from 'axios';
import { RssNode, RssRule } from '@/types';
import { RssNode, RssRule, SearchPlugin, ApiCategory, SearchTaskResponse } from '@/types';
class Api {
private axios: AxiosInstance;
constructor() {
@@ -126,7 +127,7 @@ class Api {
}
public setForceStartTorrents(hashes: string[]) {
return this.actionTorrents('setForceStart', hashes, {value:'true'});
return this.actionTorrents('setForceStart', hashes, { value: 'true' });
}
public reannounceTorrents(hashes: string[]) {
@@ -248,7 +249,7 @@ class Api {
return this.axios.post('/rss/moveItem', data).then(Api.handleResponse);
}
public getRssRules(): Promise<{[key: string]: RssRule}> {
public getRssRules(): Promise<{ [key: string]: RssRule }> {
return this.axios.get('/rss/rules').then(Api.handleResponse);
}
@@ -271,6 +272,41 @@ class Api {
return this.axios.post('/rss/removeRule', data).then(Api.handleResponse);
}
// Search page
public getSearchPlugins(): Promise<SearchPlugin[]> {
return this.axios.get('/search/plugins').then(Api.handleResponse);
}
/**
* @see getSearchCategories
* When there are no categories available/set
* @returns a Promise<{}> instead of Promise<[]>.
*/
public getSearchCategories(): Promise<ApiCategory> {
return this.axios.get('/torrents/categories').then(Api.handleResponse);
}
public startSearch(pattern: string | null, pluginName: string | null, categoryName: string | null): Promise<{ id: number }> {
const body = new URLSearchParams(
{
pattern: pattern || '',
category: categoryName || 'all',
plugins: pluginName || 'all'
});
return this.axios.post('/search/start', body).then(Api.handleResponse);
}
public stopSearch(id: number): AxiosResponse<any> | PromiseLike<AxiosResponse<any>> {
const body = new URLSearchParams({ id: id.toString() });
return this.axios.post('/search/stop', body);
}
public getSearchResults(id: number): Promise<SearchTaskResponse> {
return this.axios.get(`/search/results?id=${id}`).then(Api.handleResponse);
}
private actionTorrents(action: string, hashes: string[], extra?: any) {
const params: any = {
hashes: hashes.join('|'),

View File

@@ -33,6 +33,10 @@
v-model="drawerOptions.showRss"
@download-torrent="setPasteUrl({url: $event})"
/>
<SearchDialog
v-if="drawerOptions.showSearch"
v-model="drawerOptions.showSearch"
/>
<v-footer
app
@@ -64,6 +68,7 @@ import Torrents from './components/Torrents.vue';
import AppFooter from './components/Footer.vue';
import LogsDialog from './components/dialogs/LogsDialog.vue';
import RssDialog from './components/dialogs/RssDialog.vue';
import SearchDialog from './components/dialogs/SearchDialog.vue';
import DrawerFooter from './components/drawer/DrawerFooter.vue';
import api from './Api';
@@ -85,6 +90,7 @@ let appWrapEl: HTMLElement;
GlobalDialog,
GlobalSnackBar,
RssDialog,
SearchDialog,
DrawerFooter,
},
computed: {
@@ -213,4 +219,4 @@ export default class App extends Vue {
html {
overflow-y: hidden;
}
</style>
</style>

View File

@@ -7,14 +7,14 @@
fixed
right
small
@click="dialog = !dialog"
@click="openAddForm"
class="btn-add"
:class="{'with-footer': $vuetify.breakpoint.smAndUp}"
>
<v-icon>mdi-link-plus</v-icon>
</v-btn>
<v-dialog
v-model="dialog"
v-model="state.isOpen"
eager
persistent
scrollable
@@ -23,7 +23,7 @@
<v-card>
<v-card-title class="headline">
<v-icon class="mr-2">mdi-link-plus</v-icon>
<span>{{ $t('title.add_torrents') }}</span>
<span>{{ state.downloadItem && state.downloadItem.title || $t('title.add_torrents') }}</span>
</v-card-title>
<v-card-text class="pb-0">
<v-form
@@ -54,6 +54,7 @@
required
:autofocus="!phoneLayout"
:value="params.urls"
:readonly="state.downloadItem !== null"
@input="setParams('urls', $event)"
@click:append-outer="selectFiles"
/>
@@ -178,7 +179,7 @@
<v-spacer />
<v-btn
text
@click="dialog = false"
@click="closeAddForm"
>
{{ $t('cancel') }}
</v-btn>
@@ -200,12 +201,13 @@
<script lang="ts">
import { isNil } from 'lodash';
import Vue from 'vue';
import { mapState, mapGetters } from 'vuex';
import { mapState, mapGetters, mapMutations } from 'vuex';
import api from '../Api';
import Component from 'vue-class-component';
import { Watch } from 'vue-property-decorator';
import { Preferences, Category } from '../types';
import { AddFormState } from '@/store/types';
/* eslint-disable @typescript-eslint/camelcase */
const defaultParams = {
@@ -226,14 +228,20 @@ const defaultParams = {
...mapState({
pasteUrl: 'pasteUrl',
prefs: 'preferences',
state: 'addForm'
}),
...mapGetters({
allCategories: 'allCategories',
}),
...mapGetters([
'allCategories',
]),
},
methods: {
...mapMutations([
'closeAddForm',
'openAddForm',
]),
}
})
export default class AddForm extends Vue {
dialog = false
valid = false
files: FileList | [] = []
defaultParams = defaultParams
@@ -242,6 +250,7 @@ export default class AddForm extends Vue {
submitting = false
showMore = false
state!: AddFormState;
pasteUrl!: string | null
prefs!: Preferences
allCategories!: Category[]
@@ -251,7 +260,10 @@ export default class AddForm extends Vue {
file: any;
fileZone: HTMLElement;
}
openAddForm!: () => void;
closeAddForm!: () => void;
get params() {
return Object.assign({}, defaultParams, this.userParams);
}
@@ -285,6 +297,13 @@ export default class AddForm extends Vue {
this.$refs.fileZone.addEventListener('drop', this.onDrop, true);
}
@Watch('state', {deep: true})
onStateUpdate(state: AddFormState) {
if (state.downloadItem) {
this.setParams('urls', state.downloadItem.url);
}
}
beforeDestroy() {
this.$refs.fileZone.removeEventListener('drop', this.onDrop, true);
}
@@ -328,7 +347,7 @@ export default class AddForm extends Vue {
return;
}
this.dialog = false;
this.closeAddForm();
Vue.delete(this.userParams, 'urls');
this.files = [];
@@ -358,9 +377,9 @@ export default class AddForm extends Vue {
return;
}
if (!this.dialog) {
if (!this.state.isOpen) {
Vue.set(this.userParams, 'urls', v);
this.dialog = true;
this.openAddForm();
}
}

View File

@@ -167,16 +167,23 @@ export default class Drawer extends Vue {
torrentGroupByState!: {[state: string]: Torrent[]}
created() {
if (this.phoneLayout) {
return
const searchMenuItem = { icon: 'mdi-card-search-outline', title: 'Search', click: () => this.updateOptions('showSearch', true) };
if (this.phoneLayout) {
this.endItems = this.endItems.concat([
searchMenuItem
]);
return;
}
this.endItems = this.endItems.concat([
{ icon: 'mdi-rss-box', title: 'RSS', click: () => this.updateOptions('showRss', true) },
searchMenuItem,
{ icon: 'mdi-history', title: tr('label.switch_to_old_ui'), click: this.switchUi },
])
}
get phoneLayout() {
return this.$vuetify.breakpoint.smAndDown;
}

View File

@@ -495,7 +495,7 @@ export default class Torrents extends Vue {
}
async recheckTorrents() {
const v = await this.asyncShowDialog({
const v = await this.asyncShowDialog({ // TODO: update with i18n usage
title: 'Recheck Torrents',
text: 'Are you sure want to recheck torrents?',
type: DialogType.OkCancel,
@@ -649,7 +649,7 @@ export default class Torrents extends Vue {
max-width: 32em;
}
}
&::v-deep .v-data-footer {
margin-right: 4em;

View File

@@ -0,0 +1,262 @@
<template>
<div>
<v-dialog
:value="value"
@input="$emit('input', $event)"
scrollable
fullscreen
persistent
>
<v-card>
<v-card-title class="headline">
<v-icon class="mr-2">mdi-card-search-outline</v-icon>
<span>Search</span>
<v-spacer />
<v-btn
icon
@click="closeDialog"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<v-form
ref="form"
v-model="searchForm.valid"
lazy-validation
>
<v-container>
<v-row :align="'start'">
<v-col>
<v-select
v-model="searchForm.plugin"
:items="availablePlugins"
item-text="name"
:clearable="true"
:label="$t('plugin', 1)"
/>
</v-col>
<v-col class="col-12 col-sm-6 col-md-8">
<v-text-field
v-model="searchForm.pattern"
prepend-inner-icon="mdi-magnify"
:label="$t('search')"
/>
</v-col>
<v-col>
<v-select
v-model="searchForm.category"
:items="allCategories"
:clearable="true"
item-text="name"
:label="$t('category', 1)"
/>
</v-col>
<v-col :align-self="'center'">
<v-btn
@click="loading ? stopSearch() : triggerSearch()"
>
{{ loading ? $t('stop') : $t('search') }}
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
<v-data-table
:headers="grid.headers"
:items="grid.searchItems"
:items-per-page="10"
:loading="loading"
class="elevation-1"
>
<template v-slot:[`item.fileSize`]="{ item }">
{{ item.fileSize | formatSize }}
</template>
<template v-slot:[`item.actions`]="{ item }">
<v-icon
small
class="mr-2"
@click="downloadTorrent(item)"
>
mdi-download
</v-icon>
</template>
</v-data-table>
</v-card-text>
<v-card-actions />
</v-card>
</v-dialog>
</div>
</template>
<script lang="ts">
import api from "@/Api";
import Component from "vue-class-component";
import HasTask from "../../mixins/hasTask";
import { Prop, Emit } from "vue-property-decorator";
import { SearchPlugin, SearchTaskTorrent } from "@/types";
import { AxiosResponse } from "axios";
import { formatSize } from "../../filters";
import { mapGetters, mapMutations } from "vuex";
import { tr } from "@/locale";
interface GridConfig {
searchItems: SearchTaskTorrent[];
downloadItem: SearchTaskTorrent | null;
headers: { [key: string]: any }[];
}
@Component({
computed: {
...mapGetters({
allCategories: "allCategories",
preferences: "preferences",
}),
},
methods: {
...mapMutations(["openAddForm", "setPasteUrl", "addFormDownloadItem"]),
formatSize,
translate: tr,
},
})
export default class SearchDialog extends HasTask {
private _searchId = 0;
@Prop(Boolean)
readonly value!: boolean;
availablePlugins: SearchPlugin[] | null = null;
allCategories!: any;
formatSize!: (_: any) => string;
translate!: (_: any, __?: any) => string;
searchForm: {
valid: boolean;
category: string | null;
pattern: string | null;
plugin: string | null;
} = {
valid: false,
category: null,
pattern: null,
plugin: null,
};
grid: GridConfig = {
searchItems: [],
downloadItem: {
descrLink: "",
fileName: "",
fileSize: 0,
fileUrl: "",
nbLeechers: 0,
nbSeeders: 0,
siteUrl: "",
},
headers: [
{ text: this.translate("name"), value: "fileName" },
{ text: this.translate("size"), value: "fileSize" },
{ text: this.translate("seeds"), value: "nbSeeders" },
{ text: this.translate("peers"), value: "nbLeechers" },
{ text: this.translate("search_engine"), value: "siteUrl" },
{ text: this.translate("action", 2), value: "actions", sortable: false },
],
};
loading = false;
setPasteUrl!: (_: any) => void;
openAddForm!: () => void;
addFormDownloadItem!: (_: any) => void;
async mounted() {
this.availablePlugins = await this.getAvailablePlugins();
}
async downloadTorrent(item: SearchTaskTorrent) {
this.addFormDownloadItem({
downloadItem: {
title: item.fileName,
url: item.fileUrl,
},
});
this.openAddForm();
}
async getAvailablePlugins(): Promise<SearchPlugin[]> {
const availablePlugins = await api.getSearchPlugins();
return availablePlugins.filter((plugin) => plugin.enabled === true);
}
async triggerSearch() {
try {
this.grid.searchItems = []; // Clear the table
this.loading = true;
const response = await this._startSearch();
this._searchId = response.id;
this.setTaskAndRun(this.task(response.id));
} catch {
//
}
}
async stopSearch() {
this.cancelTask();
this._stopSearch(this._searchId);
this.loading = false;
}
async getResults(id: number): Promise<SearchTaskTorrent[]> {
const response = await api.getSearchResults(id);
return response.results;
}
@Emit("input")
closeDialog() {
return false;
}
private async _startSearch(): Promise<{ id: number }> {
const result = await api.startSearch(
this.searchForm.pattern,
this.searchForm.plugin,
this.searchForm.category
);
return result;
}
private async _stopSearch(id: number): Promise<AxiosResponse> {
return await api.stopSearch(id);
}
/**
* Does request until the plugins return data
*/
private task(responseId: number): CallableFunction {
return async () => {
const results = await this.getResults(responseId);
this.grid.searchItems = this.grid.searchItems.concat(results);
if (results && results.length) {
this.stopSearch();
return true;
}
};
}
}
</script>
<style lang="scss" scoped>
@import "~@/assets/styles.scss";
@include dialog-title;
</style>

View File

@@ -12,7 +12,7 @@ export function toPrecision(value: number, precision: number) {
return value.toFixed(precision - 1);
}
export function formatSize(value: number) {
export function formatSize(value: number): string {
const units = 'KMGTP';
let index = -1;
@@ -129,4 +129,4 @@ export function parseDate(str: string) {
return Date.parse(str) / 1000
}
Vue.filter('parseDate', parseDate)
Vue.filter('parseDate', parseDate)

View File

@@ -9,6 +9,8 @@ export default {
cancel: 'Cancel',
ok: 'OK',
start: 'Start',
stop: 'Stop',
submit: 'Submit',
edit: 'Edit',
delete: 'Delete',
@@ -55,6 +57,9 @@ export default {
more: 'More',
feed: 'Feed',
date: 'Date',
plugin: 'Plugin |||| Plugins',
action: 'Action |||| Actions',
search_engine: 'Search engine',
title: {
_: 'Title',

29
src/store/addForm.ts Normal file
View File

@@ -0,0 +1,29 @@
import { Module } from 'vuex';
import { AddFormState } from './types';
export const addFormStore: Module<AddFormState, any> = {
state() {
return {
isOpen: false,
downloadItem: null
};
},
getters: {
isOpen(state) {
return state.isOpen;
}
},
mutations: {
openAddForm(state) {
state.isOpen = true;
},
closeAddForm(state) {
state.isOpen = false;
state.downloadItem = null;
},
addFormDownloadItem(state, payload) {
const { downloadItem } = payload;
state.downloadItem = downloadItem;
}
},
};

View File

@@ -6,6 +6,7 @@ import { computed, Ref } from '@vue/composition-api';
import { configStore } from './config';
import { dialogStore } from './dialog';
import { snackBarStore } from './snackBar';
import { addFormStore } from './addForm';
import { AllStateTypes } from '../consts';
import { torrentIsState } from '../utils';
import { RootState } from './types';
@@ -17,6 +18,7 @@ const store = new Vuex.Store<RootState>({
config: configStore,
dialog: dialogStore,
snackBar: snackBarStore,
addForm: addFormStore
},
state: {
rid: 0,
@@ -59,6 +61,9 @@ const store = new Vuex.Store<RootState>({
/* eslint-enable no-param-reassign */
},
getters: {
savePath(state) {
return state.preferences['save_path'];
},
isDataReady(state) {
return !!state.mainData;
},

View File

@@ -8,6 +8,14 @@ export interface RootState {
pasteUrl: string | null;
}
export interface AddFormState {
isOpen: boolean;
downloadItem: {
title: string;
url: string;
} | null;
}
export interface TorrentFilter {
state: string;
category: string;

View File

@@ -54,6 +54,18 @@ export interface Category {
savePath?: string;
}
export interface ApiCategory {
[key: string]: {
name: string;
savePath?: string;
};
}
export interface SimpleCategory {
name: string | null;
savePath?: string;
}
export interface ServerState {
alltime_dl: number;
alltime_ul: number;
@@ -82,9 +94,9 @@ export interface ServerState {
}
export interface MainData {
categories: Record<string, Category>;
server_state: ServerState;
torrents: Record<string, BaseTorrent>;
categories: Record<string, Category>;
server_state: ServerState;
torrents: Record<string, BaseTorrent>;
}
export interface RssTorrent {
@@ -244,7 +256,7 @@ export interface Preferences {
rss_refresh_interval: number;
save_path: string;
save_path_changed_tmm_enabled: boolean;
scan_dirs: {[key: string]: string | number};
scan_dirs: { [key: string]: string | number };
schedule_from_hour: number;
schedule_from_min: number;
schedule_to_hour: number;
@@ -272,4 +284,29 @@ export interface Preferences {
web_ui_port: number;
web_ui_upnp: boolean;
web_ui_username: string;
}
}
export interface SearchPlugin {
enabled: boolean;
fullName: string;
name: string;
supportedCategories: { id: string; name: string }[];
url: string;
version: string;
}
export interface SearchTaskTorrent {
descrLink: string;
fileName: string;
fileSize: number;
fileUrl: string;
nbLeechers: number;
nbSeeders: number;
siteUrl: string;
}
export interface SearchTaskResponse {
results: SearchTaskTorrent[];
status: 'Running' | 'Stopped';
total: number;
}

186
yarn.lock
View File

@@ -2021,7 +2021,7 @@ anymatch@^3.0.3, anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
aproba@^1.0.3, aproba@^1.1.1:
aproba@^1.1.1:
version "1.2.0"
resolved "https://registry.npm.taobao.org/aproba/download/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
integrity sha1-aALmJk79GMeQobDVF/DyYnvyyUo=
@@ -2031,14 +2031,6 @@ arch@^2.1.1:
resolved "https://registry.npm.taobao.org/arch/download/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e"
integrity sha1-j1wnMao1owkpIhuwZA7tZRdeyE4=
are-we-there-yet@~1.1.2:
version "1.1.5"
resolved "https://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
integrity sha1-SzXClE8GKov82mZBB2A1D+nd/CE=
dependencies:
delegates "^1.0.0"
readable-stream "^2.0.6"
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -3202,11 +3194,6 @@ console-browserify@^1.1.0:
resolved "https://registry.npm.taobao.org/console-browserify/download/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
integrity sha1-ZwY871fOts9Jk6KrOlWECujEkzY=
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
consolidate@^0.15.1:
version "0.15.1"
resolved "https://registry.npm.taobao.org/consolidate/download/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7"
@@ -3639,7 +3626,7 @@ debug@=3.1.0:
dependencies:
ms "2.0.0"
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5:
version "3.2.6"
resolved "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha1-6D0X3hbYp++3cX7b5fsQE17uYps=
@@ -3680,11 +3667,6 @@ deep-equal@^1.0.1:
object-keys "^1.1.1"
regexp.prototype.flags "^1.2.0"
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.npm.taobao.org/deep-extend/download/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@@ -3769,11 +3751,6 @@ delayed-stream@~1.0.0:
resolved "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@@ -3792,11 +3769,6 @@ destroy@~1.0.4:
resolved "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
detect-libc@^1.0.2:
version "1.0.3"
resolved "https://registry.npm.taobao.org/detect-libc/download/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
detect-newline@^3.0.0:
version "3.1.0"
resolved "https://registry.npm.taobao.org/detect-newline/download/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
@@ -4799,13 +4771,6 @@ fs-extra@^7.0.1:
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-minipass@^1.2.5:
version "1.2.7"
resolved "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-1.2.7.tgz?cache=0&sync_timestamp=1579628584498&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-minipass%2Fdownload%2Ffs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
integrity sha1-zP+FcIQef+QmVpPaiJNsVa7X98c=
dependencies:
minipass "^2.6.0"
fs-minipass@^2.0.0:
version "2.1.0"
resolved "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-2.1.0.tgz?cache=0&sync_timestamp=1579628584498&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-minipass%2Fdownload%2Ffs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@@ -4851,20 +4816,6 @@ functional-red-black-tree@^1.0.1:
resolved "https://registry.npm.taobao.org/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
dependencies:
aproba "^1.0.3"
console-control-strings "^1.0.0"
has-unicode "^2.0.0"
object-assign "^4.1.0"
signal-exit "^3.0.0"
string-width "^1.0.1"
strip-ansi "^3.0.1"
wide-align "^1.1.0"
gensync@^1.0.0-beta.1:
version "1.0.0-beta.1"
resolved "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
@@ -5060,11 +5011,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1:
resolved "https://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.1.tgz?cache=0&sync_timestamp=1573950719586&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-symbols%2Fdownload%2Fhas-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg=
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
has-value@^0.3.1:
version "0.3.1"
resolved "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
@@ -5328,7 +5274,7 @@ human-signals@^1.1.1:
resolved "https://registry.npm.taobao.org/human-signals/download/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha1-xbHNFPUK6uCatsWf5jujOV/k36M=
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24"
resolved "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1579333981154&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=
@@ -5352,13 +5298,6 @@ iferr@^0.1.5:
resolved "https://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
ignore-walk@^3.0.1:
version "3.0.3"
resolved "https://registry.npm.taobao.org/ignore-walk/download/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
integrity sha1-AX4kRxhL/q3nwjjkrv3R6PlbHjc=
dependencies:
minimatch "^3.0.4"
ignore@^3.3.5:
version "3.3.10"
resolved "https://registry.npm.taobao.org/ignore/download/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
@@ -5458,7 +5397,7 @@ inherits@2.0.3:
resolved "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@^1.3.4, ini@~1.3.0:
ini@^1.3.4:
version "1.3.5"
resolved "https://registry.npm.taobao.org/ini/download/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=
@@ -7112,14 +7051,6 @@ minipass-pipeline@^1.2.2:
dependencies:
minipass "^3.0.0"
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
version "2.9.0"
resolved "https://registry.npm.taobao.org/minipass/download/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
integrity sha1-5xN2Ln0+Mv7YAxFc+T4EvKn8yaY=
dependencies:
safe-buffer "^5.1.2"
yallist "^3.0.0"
minipass@^3.0.0, minipass@^3.1.1:
version "3.1.1"
resolved "https://registry.npm.taobao.org/minipass/download/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
@@ -7127,13 +7058,6 @@ minipass@^3.0.0, minipass@^3.1.1:
dependencies:
yallist "^4.0.0"
minizlib@^1.2.1:
version "1.3.3"
resolved "https://registry.npm.taobao.org/minizlib/download/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
integrity sha1-IpDeloGKNMKVUcio0wEha9Zahh0=
dependencies:
minipass "^2.9.0"
mississippi@^3.0.0:
version "3.0.0"
resolved "https://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@@ -7163,7 +7087,7 @@ mkdirp@1.x, mkdirp@~1.0.3:
resolved "https://registry.npm.taobao.org/mkdirp/download/mkdirp-1.0.4.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha1-PrXtYmInVteaXw4qIh3+utdcL34=
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
version "0.5.5"
resolved "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=
@@ -7251,15 +7175,6 @@ natural-compare@^1.4.0:
resolved "https://registry.npm.taobao.org/natural-compare/download/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
needle@^2.2.1:
version "2.4.1"
resolved "https://registry.npm.taobao.org/needle/download/needle-2.4.1.tgz?cache=0&sync_timestamp=1585919797356&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fneedle%2Fdownload%2Fneedle-2.4.1.tgz#14af48732463d7475696f937626b1b993247a56a"
integrity sha1-FK9IcyRj10dWlvk3YmsbmTJHpWo=
dependencies:
debug "^3.2.6"
iconv-lite "^0.4.4"
sax "^1.2.4"
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@@ -7364,28 +7279,12 @@ node-polyglot@^2.4.0:
string.prototype.trim "^1.1.2"
warning "^4.0.3"
node-pre-gyp@*:
version "0.14.0"
resolved "https://registry.npm.taobao.org/node-pre-gyp/download/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
integrity sha1-mgWWUzuHcom8rU4UOYLKPZBN3IM=
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
needle "^2.2.1"
nopt "^4.0.1"
npm-packlist "^1.1.6"
npmlog "^4.0.2"
rc "^1.2.7"
rimraf "^2.6.1"
semver "^5.3.0"
tar "^4.4.2"
node-releases@^1.1.53:
version "1.1.53"
resolved "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4"
integrity sha1-LYIb+kme18Xf/F4vKMiOeKCO4/Q=
nopt@^4.0.1, nopt@^4.0.3:
nopt@^4.0.3:
version "4.0.3"
resolved "https://registry.npm.taobao.org/nopt/download/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
integrity sha1-o3XK2dAv2SEnjZVMIlTVqlfhXkg=
@@ -7440,27 +7339,6 @@ normalize-url@^3.0.0:
resolved "https://registry.npm.taobao.org/normalize-url/download/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
integrity sha1-suHE3E98bVd0PfczpPWXjRhlBVk=
npm-bundled@^1.0.1:
version "1.1.1"
resolved "https://registry.npm.taobao.org/npm-bundled/download/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"
integrity sha1-Ht1XCGWpTNsbyCIHdeKUZsn7I0s=
dependencies:
npm-normalize-package-bin "^1.0.1"
npm-normalize-package-bin@^1.0.1:
version "1.0.1"
resolved "https://registry.npm.taobao.org/npm-normalize-package-bin/download/npm-normalize-package-bin-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnpm-normalize-package-bin%2Fdownload%2Fnpm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
integrity sha1-bnmkHyP9I1wGIyGCKNp9nCO49uI=
npm-packlist@^1.1.6:
version "1.4.8"
resolved "https://registry.npm.taobao.org/npm-packlist/download/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
integrity sha1-Vu5swTW5+YrT1Rwcldoiu7my7z4=
dependencies:
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
npm-normalize-package-bin "^1.0.1"
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -7475,16 +7353,6 @@ npm-run-path@^4.0.0:
dependencies:
path-key "^3.0.0"
npmlog@^4.0.2:
version "4.1.2"
resolved "https://registry.npm.taobao.org/npmlog/download/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=
dependencies:
are-we-there-yet "~1.1.2"
console-control-strings "~1.1.0"
gauge "~2.7.3"
set-blocking "~2.0.0"
nth-check@^1.0.2, nth-check@~1.0.1:
version "1.0.2"
resolved "https://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
@@ -8652,16 +8520,6 @@ raw-body@2.4.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
rc@^1.2.7:
version "1.2.8"
resolved "https://registry.npm.taobao.org/rc/download/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=
dependencies:
deep-extend "^0.6.0"
ini "~1.3.0"
minimist "^1.2.0"
strip-json-comments "~2.0.1"
react-is@^16.12.0, react-is@^16.8.4:
version "16.13.1"
resolved "https://registry.npm.taobao.org/react-is/download/react-is-16.13.1.tgz?cache=0&sync_timestamp=1586484576689&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact-is%2Fdownload%2Freact-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@@ -8703,7 +8561,7 @@ read-pkg@^5.1.1, read-pkg@^5.2.0:
parse-json "^5.0.0"
type-fest "^0.6.0"
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.7"
resolved "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=
@@ -9128,7 +8986,7 @@ sass@^1.26.3:
dependencies:
chokidar ">=2.0.0 <4.0.0"
sax@^1.2.4, sax@~1.2.4:
sax@~1.2.4:
version "1.2.4"
resolved "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha1-KBYjTiN4vdxOU1T6tcqold9xANk=
@@ -9246,7 +9104,7 @@ serve-static@1.14.1:
parseurl "~1.3.3"
send "0.17.1"
set-blocking@^2.0.0, set-blocking@~2.0.0:
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
@@ -9690,7 +9548,7 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1:
string-width@^2.0.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=
@@ -9835,7 +9693,7 @@ strip-indent@^2.0.0:
resolved "https://registry.npm.taobao.org/strip-indent/download/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
strip-json-comments@^2.0.0, strip-json-comments@~2.0.1:
strip-json-comments@^2.0.0:
version "2.0.1"
resolved "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
@@ -9932,19 +9790,6 @@ tapable@^1.0.0, tapable@^1.1.3:
resolved "https://registry.npm.taobao.org/tapable/download/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha1-ofzMBrWNth/XpF2i2kT186Pme6I=
tar@^4.4.2:
version "4.4.13"
resolved "https://registry.npm.taobao.org/tar/download/tar-4.4.13.tgz?cache=0&sync_timestamp=1588021389848&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftar%2Fdownload%2Ftar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
integrity sha1-Q7NkvFKIjVVSmGN7ENYHkCVKtSU=
dependencies:
chownr "^1.1.1"
fs-minipass "^1.2.5"
minipass "^2.8.6"
minizlib "^1.2.1"
mkdirp "^0.5.0"
safe-buffer "^5.1.2"
yallist "^3.0.3"
terminal-link@^2.0.0:
version "2.1.1"
resolved "https://registry.npm.taobao.org/terminal-link/download/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
@@ -10918,13 +10763,6 @@ which@^2.0.1, which@^2.0.2:
dependencies:
isexe "^2.0.0"
wide-align@^1.1.0:
version "1.1.3"
resolved "https://registry.npm.taobao.org/wide-align/download/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
integrity sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=
dependencies:
string-width "^1.0.2 || 2"
word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
@@ -11029,7 +10867,7 @@ yallist@^2.1.2:
resolved "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
yallist@^3.0.2:
version "3.1.1"
resolved "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=