Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f0fd55c9a | ||
|
|
0e9b496deb | ||
|
|
8294c18e70 | ||
|
|
39575b4696 | ||
|
|
29e9801d5c | ||
|
|
eaf83bffb0 | ||
|
|
bb25ece745 | ||
|
|
754b5629e4 | ||
|
|
ee63403548 | ||
|
|
87edeb41da | ||
|
|
41fe804587 | ||
|
|
02466acc4b | ||
|
|
8470a64e6b | ||
|
|
9939e0f9a9 | ||
|
|
ce5f552d0c | ||
|
|
7d4c535233 | ||
|
|
57cd0fb93f | ||
|
|
a15299ae53 | ||
|
|
1df7abfbb9 | ||
|
|
85a0f696bc | ||
|
|
ba3c62bf9c | ||
|
|
c17e97b6a6 | ||
|
|
2d80cd0e7b | ||
|
|
eedc572f0c | ||
|
|
2de1df3514 | ||
|
|
2d96af1255 | ||
|
|
163325ef89 |
@@ -154,3 +154,6 @@ id: 'aid'
|
|||||||
|
|
||||||
# Media Proxy
|
# Media Proxy
|
||||||
#mediaProxy: https://example.com/proxy
|
#mediaProxy: https://example.com/proxy
|
||||||
|
|
||||||
|
# Sign to ActivityPub GET request (default: false)
|
||||||
|
#signToActivityPubGet: true
|
||||||
|
|||||||
@@ -585,6 +585,7 @@ regenerateLoginTokenDescription: "ログインに使用される内部トーク
|
|||||||
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
|
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
|
||||||
fileIdOrUrl: "ファイルIDまたはURL"
|
fileIdOrUrl: "ファイルIDまたはURL"
|
||||||
chatOpenBehavior: "チャットを開くときの動作"
|
chatOpenBehavior: "チャットを開くときの動作"
|
||||||
|
sample: "サンプル"
|
||||||
|
|
||||||
_serverDisconnectedBehavior:
|
_serverDisconnectedBehavior:
|
||||||
reload: "自動でリロード"
|
reload: "自動でリロード"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||||
"version": "12.48.0",
|
"version": "12.48.2",
|
||||||
"codename": "indigo",
|
"codename": "indigo",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -138,6 +138,7 @@
|
|||||||
"file-type": "15.0.1",
|
"file-type": "15.0.1",
|
||||||
"fluent-ffmpeg": "2.1.2",
|
"fluent-ffmpeg": "2.1.2",
|
||||||
"glob": "7.1.6",
|
"glob": "7.1.6",
|
||||||
|
"got": "11.7.0",
|
||||||
"gulp": "4.0.2",
|
"gulp": "4.0.2",
|
||||||
"gulp-rename": "2.0.0",
|
"gulp-rename": "2.0.0",
|
||||||
"gulp-replace": "1.0.0",
|
"gulp-replace": "1.0.0",
|
||||||
|
|||||||
3
src/client/@types/vuex-shim.d.ts
vendored
3
src/client/@types/vuex-shim.d.ts
vendored
@@ -2,10 +2,11 @@ import { ComponentCustomProperties } from 'vue';
|
|||||||
import { Store } from 'vuex';
|
import { Store } from 'vuex';
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
|
// tslint:disable-next-line:no-empty-interface
|
||||||
interface State {
|
interface State {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
$store: Store<State>
|
$store: Store<State>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -344,6 +344,7 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
line-height: $header-height;
|
line-height: $header-height;
|
||||||
|
height: $header-height;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
color: var(--panelHeaderFg);
|
color: var(--panelHeaderFg);
|
||||||
|
|||||||
@@ -708,6 +708,7 @@ export default defineComponent({
|
|||||||
os.modalMenu([{
|
os.modalMenu([{
|
||||||
text: this.$t('unrenote'),
|
text: this.$t('unrenote'),
|
||||||
icon: faTrashAlt,
|
icon: faTrashAlt,
|
||||||
|
danger: true,
|
||||||
action: () => {
|
action: () => {
|
||||||
os.api('notes/delete', {
|
os.api('notes/delete', {
|
||||||
noteId: this.note.id
|
noteId: this.note.id
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<XWindow ref="window" :initial-width="400" :initial-height="450" :can-resize="true" @closed="$emit('closed')">
|
<XWindow ref="window" :initial-width="400" :initial-height="500" :can-resize="true" @closed="$emit('closed')">
|
||||||
<template #header>
|
<template #header>
|
||||||
<XHeader :info="pageInfo" :with-back="false"/>
|
<XHeader :info="pageInfo" :with-back="false"/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import * as os from '@/os';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
@@ -44,14 +44,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
upload() {
|
upload() {
|
||||||
return new Promise((ok) => {
|
const promise = new Promise((ok) => {
|
||||||
const dialog = os.dialog({
|
|
||||||
type: 'waiting',
|
|
||||||
text: this.$t('uploading') + '...',
|
|
||||||
showOkButton: false,
|
|
||||||
showCancelButton: false,
|
|
||||||
cancelableByBgClick: false
|
|
||||||
});
|
|
||||||
const canvas = this.hpml.canvases[this.value.canvasId];
|
const canvas = this.hpml.canvases[this.value.canvasId];
|
||||||
canvas.toBlob(blob => {
|
canvas.toBlob(blob => {
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
@@ -67,11 +60,12 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(f => {
|
.then(f => {
|
||||||
dialog.close();
|
|
||||||
ok(f);
|
ok(f);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
os.promiseDialog(promise);
|
||||||
|
return promise;
|
||||||
},
|
},
|
||||||
async post() {
|
async post() {
|
||||||
this.posting = true;
|
this.posting = true;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import MkTextarea from '../ui/textarea.vue';
|
import MkTextarea from '../ui/textarea.vue';
|
||||||
import * as os from '@/os';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { faHeart } from '@fortawesome/free-regular-svg-icons';
|
|||||||
import XBlock from './page.block.vue';
|
import XBlock from './page.block.vue';
|
||||||
import { Hpml } from '@/scripts/hpml/evaluator';
|
import { Hpml } from '@/scripts/hpml/evaluator';
|
||||||
import { url } from '@/config';
|
import { url } from '@/config';
|
||||||
import * as os from '@/os';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ import MkInput from './ui/input.vue';
|
|||||||
import MkSelect from './ui/select.vue';
|
import MkSelect from './ui/select.vue';
|
||||||
import MkSwitch from './ui/switch.vue';
|
import MkSwitch from './ui/switch.vue';
|
||||||
import MkButton from './ui/button.vue';
|
import MkButton from './ui/button.vue';
|
||||||
import * as os from '@/os';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@@ -78,8 +77,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
choices: ['', ''],
|
choices: this.poll.choices,
|
||||||
multiple: false,
|
multiple: this.poll.multiple,
|
||||||
expiration: 'infinite',
|
expiration: 'infinite',
|
||||||
atDate: formatDateTimeString(addTime(new Date(), 1, 'day'), 'yyyy-MM-dd'),
|
atDate: formatDateTimeString(addTime(new Date(), 1, 'day'), 'yyyy-MM-dd'),
|
||||||
atTime: '00:00',
|
atTime: '00:00',
|
||||||
@@ -90,26 +89,6 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
poll: {
|
|
||||||
handler(poll) {
|
|
||||||
if (poll == null) return;
|
|
||||||
if (poll.choices.length == 0) return;
|
|
||||||
this.choices = poll.choices;
|
|
||||||
if (poll.choices.length == 1) this.choices = this.choices.concat('');
|
|
||||||
this.multiple = poll.multiple;
|
|
||||||
if (poll.expiresAt) {
|
|
||||||
this.expiration = 'at';
|
|
||||||
this.atDate = this.atTime = poll.expiresAt;
|
|
||||||
} else if (typeof poll.expiredAfter === 'number') {
|
|
||||||
this.expiration = 'after';
|
|
||||||
this.after = poll.expiredAfter;
|
|
||||||
} else {
|
|
||||||
this.expiration = 'infinite';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
immediate: true
|
|
||||||
},
|
|
||||||
choices: {
|
choices: {
|
||||||
handler() {
|
handler() {
|
||||||
this.$emit('updated', this.get());
|
this.$emit('updated', this.get());
|
||||||
@@ -136,6 +115,24 @@ export default defineComponent({
|
|||||||
this.$emit('updated', this.get());
|
this.$emit('updated', this.get());
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
unit: {
|
||||||
|
handler() {
|
||||||
|
this.$emit('updated', this.get());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
const poll = this.poll;
|
||||||
|
if (poll.expiresAt) {
|
||||||
|
this.expiration = 'at';
|
||||||
|
this.atDate = this.atTime = poll.expiresAt;
|
||||||
|
} else if (typeof poll.expiredAfter === 'number') {
|
||||||
|
this.expiration = 'after';
|
||||||
|
this.after = poll.expiredAfter / 1000;
|
||||||
|
} else {
|
||||||
|
this.expiration = 'infinite';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
116
src/client/components/sample.vue
Normal file
116
src/client/components/sample.vue
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<div class="_card">
|
||||||
|
<div class="_content">
|
||||||
|
<MkInput v-model:value="text">
|
||||||
|
<span>Text</span>
|
||||||
|
</MkInput>
|
||||||
|
<MkSwitch v-model:value="flag">
|
||||||
|
<span>Switch is now {{ flag ? 'on' : 'off' }}</span>
|
||||||
|
</MkSwitch>
|
||||||
|
<div style="margin: 32px 0;">
|
||||||
|
<MkRadio v-model="radio" value="misskey">Misskey</MkRadio>
|
||||||
|
<MkRadio v-model="radio" value="mastodon">Mastodon</MkRadio>
|
||||||
|
<MkRadio v-model="radio" value="pleroma">Pleroma</MkRadio>
|
||||||
|
</div>
|
||||||
|
<MkButton inline>This is</MkButton>
|
||||||
|
<MkButton inline primary>the button</MkButton>
|
||||||
|
</div>
|
||||||
|
<div class="_content">
|
||||||
|
<Mfm :text="mfm"/>
|
||||||
|
</div>
|
||||||
|
<div class="_content">
|
||||||
|
<MkButton inline primary @click="openMenu">Open menu</MkButton>
|
||||||
|
<MkButton inline primary @click="openDialog">Open dialog</MkButton>
|
||||||
|
<MkButton inline primary @click="openForm">Open form</MkButton>
|
||||||
|
<MkButton inline primary @click="openDrive">Open drive</MkButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import MkButton from '@/components/ui/button.vue';
|
||||||
|
import MkInput from '@/components/ui/input.vue';
|
||||||
|
import MkSwitch from '@/components/ui/switch.vue';
|
||||||
|
import MkTextarea from '@/components/ui/textarea.vue';
|
||||||
|
import MkRadio from '@/components/ui/radio.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
import * as config from '@/config';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
MkButton,
|
||||||
|
MkInput,
|
||||||
|
MkSwitch,
|
||||||
|
MkTextarea,
|
||||||
|
MkRadio,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
text: '',
|
||||||
|
flag: false,
|
||||||
|
radio: 'misskey',
|
||||||
|
mfm: `Hello world! This is an @example mention. BTW you are @${this.$store.state.i.username}.\nAlso, here is ${config.url} and [example link](${config.url}). for more details, see https://example.com.\nAs you know #misskey is open-source software.`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async openDialog() {
|
||||||
|
os.dialog({
|
||||||
|
type: 'warning',
|
||||||
|
title: 'Oh my Aichan',
|
||||||
|
text: 'Lorem ipsum dolor sit amet, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async openForm() {
|
||||||
|
os.form('Example form', {
|
||||||
|
foo: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: true,
|
||||||
|
label: 'This is a boolean property'
|
||||||
|
},
|
||||||
|
bar: {
|
||||||
|
type: 'number',
|
||||||
|
default: 300,
|
||||||
|
label: 'This is a number property'
|
||||||
|
},
|
||||||
|
baz: {
|
||||||
|
type: 'string',
|
||||||
|
default: 'Misskey makes you happy.',
|
||||||
|
label: 'This is a string property'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async openDrive() {
|
||||||
|
os.selectDriveFile();
|
||||||
|
},
|
||||||
|
|
||||||
|
async selectUser() {
|
||||||
|
os.selectUser();
|
||||||
|
},
|
||||||
|
|
||||||
|
async openMenu(ev) {
|
||||||
|
os.modalMenu([{
|
||||||
|
type: 'label',
|
||||||
|
text: 'Fruits'
|
||||||
|
}, {
|
||||||
|
text: 'Create some apples',
|
||||||
|
action: () => {},
|
||||||
|
}, {
|
||||||
|
text: 'Read some oranges',
|
||||||
|
action: () => {},
|
||||||
|
}, {
|
||||||
|
text: 'Update some melons',
|
||||||
|
action: () => {},
|
||||||
|
}, null, {
|
||||||
|
text: 'Delete some bananas',
|
||||||
|
danger: true,
|
||||||
|
action: () => {},
|
||||||
|
}], ev.currentTarget || ev.target);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
|
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
|
||||||
import * as os from '@/os';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
@@ -377,6 +377,7 @@ export default defineComponent({
|
|||||||
$height: 50px;
|
$height: 50px;
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
box-shadow: 0px 1px var(--divider);
|
box-shadow: 0px 1px var(--divider);
|
||||||
cursor: move;
|
cursor: move;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<MkModal ref="modal" @click="type === 'success' ? done() : () => {}" @closed="$emit('closed')">
|
<MkModal ref="modal" @click="success ? done() : () => {}" @closed="$emit('closed')">
|
||||||
<div class="iuyakobc" :class="type">
|
<div class="iuyakobc" :class="{ iconOnly: (text == null) || success }">
|
||||||
<Fa class="icon" v-if="type === 'success'" :icon="faCheck"/>
|
<Fa class="icon success" v-if="success" :icon="faCheck"/>
|
||||||
<Fa class="icon" v-else-if="type === 'waiting'" :icon="faSpinner" pulse/>
|
<Fa class="icon waiting" v-else :icon="faSpinner" pulse/>
|
||||||
|
<div class="text" v-if="text && !success">{{ text }}<MkEllipsis/></div>
|
||||||
</div>
|
</div>
|
||||||
</MkModal>
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
@@ -18,12 +19,18 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
type: {
|
success: {
|
||||||
required: true
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
showing: {
|
showing: {
|
||||||
required: true
|
type: Boolean,
|
||||||
}
|
required: true,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['done', 'closed'],
|
emits: ['done', 'closed'],
|
||||||
@@ -57,7 +64,19 @@ export default defineComponent({
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
width: initial;
|
width: 250px;
|
||||||
|
|
||||||
|
&.iconOnly {
|
||||||
|
padding: 0;
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .icon {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
|
|
||||||
&.success {
|
&.success {
|
||||||
@@ -65,9 +84,12 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.waiting {
|
&.waiting {
|
||||||
> .icon {
|
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -62,17 +62,39 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
|
|||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function apiWithDialog(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined, onSuccess?: (res: any) => void, onFailure?: (e: Error) => void) {
|
export function apiWithDialog(
|
||||||
const showing = ref(true);
|
endpoint: string,
|
||||||
const state = ref('waiting');
|
data: Record<string, any> = {},
|
||||||
|
token?: string | null | undefined,
|
||||||
|
onSuccess?: (res: any) => void,
|
||||||
|
onFailure?: (e: Error) => void,
|
||||||
|
) {
|
||||||
const promise = api(endpoint, data, token);
|
const promise = api(endpoint, data, token);
|
||||||
|
promiseDialog(promise, onSuccess, onFailure ? onFailure : (e) => {
|
||||||
|
dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e.message + '\n' + (e as any).id,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function promiseDialog<T extends Promise<any>>(
|
||||||
|
promise: T,
|
||||||
|
onSuccess?: (res: any) => void,
|
||||||
|
onFailure?: (e: Error) => void,
|
||||||
|
text?: string,
|
||||||
|
): T {
|
||||||
|
const showing = ref(true);
|
||||||
|
const success = ref(false);
|
||||||
|
|
||||||
promise.then(res => {
|
promise.then(res => {
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
onSuccess(res);
|
onSuccess(res);
|
||||||
} else {
|
} else {
|
||||||
state.value = 'success';
|
success.value = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
@@ -89,9 +111,10 @@ export function apiWithDialog(endpoint: string, data: Record<string, any> = {},
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
popup(defineAsyncComponent(() => import('@/components/icon-dialog.vue')), {
|
popup(defineAsyncComponent(() => import('@/components/waiting-dialog.vue')), {
|
||||||
type: state,
|
success: success,
|
||||||
showing: showing
|
showing: showing,
|
||||||
|
text: text,
|
||||||
}, {}, 'closed');
|
}, {}, 'closed');
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
@@ -161,8 +184,8 @@ export function success() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
popup(defineAsyncComponent(() => import('@/components/icon-dialog.vue')), {
|
popup(defineAsyncComponent(() => import('@/components/waiting-dialog.vue')), {
|
||||||
type: 'success',
|
success: true,
|
||||||
showing: showing
|
showing: showing
|
||||||
}, {
|
}, {
|
||||||
done: () => resolve(),
|
done: () => resolve(),
|
||||||
@@ -173,8 +196,8 @@ export function success() {
|
|||||||
export function waiting() {
|
export function waiting() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
popup(defineAsyncComponent(() => import('@/components/icon-dialog.vue')), {
|
popup(defineAsyncComponent(() => import('@/components/waiting-dialog.vue')), {
|
||||||
type: 'waiting',
|
success: false,
|
||||||
showing: showing
|
showing: showing
|
||||||
}, {
|
}, {
|
||||||
done: () => resolve(),
|
done: () => resolve(),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="channel">
|
<div v-if="channel" class="_section">
|
||||||
<div class="wpgynlbz _panel _vMargin" :class="{ hide: !showBanner }">
|
<div class="wpgynlbz _content _panel _vMargin" :class="{ hide: !showBanner }">
|
||||||
<XChannelFollow-button :channel="channel" :full="true" class="subscribe"/>
|
<XChannelFollowButton :channel="channel" :full="true" class="subscribe"/>
|
||||||
<button class="_button toggle" @click="() => showBanner = !showBanner">
|
<button class="_button toggle" @click="() => showBanner = !showBanner">
|
||||||
<template v-if="showBanner"><Fa :icon="faAngleUp"/></template>
|
<template v-if="showBanner"><Fa :icon="faAngleUp"/></template>
|
||||||
<template v-else><Fa :icon="faAngleDown"/></template>
|
<template v-else><Fa :icon="faAngleDown"/></template>
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div :style="{ backgroundImage: channel.bannerUrl ? `url(${channel.bannerUrl})` : null }" class="banner">
|
<div :style="{ backgroundImage: channel.bannerUrl ? `url(${channel.bannerUrl})` : null }" class="banner">
|
||||||
<div class="status">
|
<div class="status">
|
||||||
<div><Fa :icon="faUsers" fixed-width/><i18n path="_channel.usersCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.usersCount }}</b></template></i18n></div>
|
<div><Fa :icon="faUsers" fixed-width/><i18n-t keypath="_channel.usersCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.usersCount }}</b></template></i18n-t></div>
|
||||||
<div><Fa :icon="faPencilAlt" fixed-width/><i18n path="_channel.notesCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.notesCount }}</b></template></i18n></div>
|
<div><Fa :icon="faPencilAlt" fixed-width/><i18n-t keypath="_channel.notesCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.notesCount }}</b></template></i18n-t></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="fade"></div>
|
<div class="fade"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<XPostForm :channel="channel" class="post-form _panel _vMargin" fixed/>
|
<XPostForm :channel="channel" class="post-form _content _panel _vMargin" fixed/>
|
||||||
|
|
||||||
<XTimeline class="_vMargin" src="channel" :channel="channelId" @before="before" @after="after"/>
|
<XTimeline class="_content _vMargin" src="channel" :channel="channelId" @before="before" @after="after"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -91,6 +91,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.wpgynlbz {
|
.wpgynlbz {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
> .subscribe {
|
> .subscribe {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|||||||
@@ -6,26 +6,24 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import parseAcct from '../../misc/acct/parse';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
created() {
|
created() {
|
||||||
const acct = new URL(location.href).searchParams.get('acct');
|
const acct = new URL(location.href).searchParams.get('acct');
|
||||||
if (acct == null) return;
|
if (acct == null) return;
|
||||||
|
|
||||||
const dialog = os.dialog({
|
let promise;
|
||||||
type: 'waiting',
|
|
||||||
text: this.$t('fetchingAsApObject') + '...',
|
|
||||||
showOkButton: false,
|
|
||||||
showCancelButton: false,
|
|
||||||
cancelableByBgClick: false
|
|
||||||
});
|
|
||||||
|
|
||||||
if (acct.startsWith('https://')) {
|
if (acct.startsWith('https://')) {
|
||||||
os.api('ap/show', {
|
promise = os.api('ap/show', {
|
||||||
uri: acct
|
uri: acct
|
||||||
}).then(res => {
|
});
|
||||||
|
promise.then(res => {
|
||||||
if (res.type == 'User') {
|
if (res.type == 'User') {
|
||||||
this.follow(res.object);
|
this.follow(res.object);
|
||||||
|
} else if (res.type === 'Note') {
|
||||||
|
this.$router.push(`/notes/${res.object.id}`);
|
||||||
} else {
|
} else {
|
||||||
os.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -34,30 +32,15 @@ export default defineComponent({
|
|||||||
window.close();
|
window.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).catch(e => {
|
|
||||||
os.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: e
|
|
||||||
}).then(() => {
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
}).finally(() => {
|
|
||||||
dialog.close();
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
os.api('users/show', parseAcct(acct)).then(user => {
|
promise = os.api('users/show', parseAcct(acct));
|
||||||
|
promise.then(user => {
|
||||||
this.follow(user);
|
this.follow(user);
|
||||||
}).catch(e => {
|
|
||||||
os.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: e
|
|
||||||
}).then(() => {
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
}).finally(() => {
|
|
||||||
dialog.close();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os.promiseDialog(promise, null, null, this.$t('fetchingAsApObject'));
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
@@ -73,19 +56,8 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
os.api('following/create', {
|
os.apiWithDialog('following/create', {
|
||||||
userId: user.id
|
userId: user.id
|
||||||
}).then(() => {
|
|
||||||
os.success().then(() => {
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
}).catch(e => {
|
|
||||||
os.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: e
|
|
||||||
}).then(() => {
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,8 @@
|
|||||||
<button class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="edit(emoji)">
|
<button class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="edit(emoji)">
|
||||||
<img :src="emoji.url" class="img" :alt="emoji.name"/>
|
<img :src="emoji.url" class="img" :alt="emoji.name"/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<span class="name">{{ emoji.name }}</span>
|
<div class="name">{{ emoji.name }}</div>
|
||||||
<span class="info">
|
<div class="info">{{ emoji.category }}</div>
|
||||||
<span class="category">{{ emoji.category }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -36,8 +34,8 @@
|
|||||||
<div class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="remoteMenu(emoji, $event)">
|
<div class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="remoteMenu(emoji, $event)">
|
||||||
<img :src="emoji.url" class="img" :alt="emoji.name"/>
|
<img :src="emoji.url" class="img" :alt="emoji.name"/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<span class="name">{{ emoji.name }}</span>
|
<div class="name">{{ emoji.name }}</div>
|
||||||
<span class="info">{{ emoji.host }}</span>
|
<div class="info">{{ emoji.host }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -106,24 +104,13 @@ export default defineComponent({
|
|||||||
async add(e) {
|
async add(e) {
|
||||||
const files = await selectFile(e.currentTarget || e.target, null, true);
|
const files = await selectFile(e.currentTarget || e.target, null, true);
|
||||||
|
|
||||||
const dialog = os.dialog({
|
const promise = Promise.all(files.map(file => os.api('admin/emoji/add', {
|
||||||
type: 'waiting',
|
|
||||||
text: this.$t('doing') + '...',
|
|
||||||
showOkButton: false,
|
|
||||||
showCancelButton: false,
|
|
||||||
cancelableByBgClick: false
|
|
||||||
});
|
|
||||||
|
|
||||||
Promise.all(files.map(file => os.api('admin/emoji/add', {
|
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
})))
|
})));
|
||||||
.then(() => {
|
promise.then(() => {
|
||||||
this.$refs.emojis.reload();
|
this.$refs.emojis.reload();
|
||||||
os.success();
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
dialog.cancel();
|
|
||||||
});
|
});
|
||||||
|
os.promiseDialog(promise);
|
||||||
},
|
},
|
||||||
|
|
||||||
async edit(emoji) {
|
async edit(emoji) {
|
||||||
@@ -193,13 +180,14 @@ export default defineComponent({
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
> .name {
|
> .name {
|
||||||
display: block;
|
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .info {
|
> .info {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,14 +221,12 @@ export default defineComponent({
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
> .name {
|
> .name {
|
||||||
display: block;
|
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .info {
|
> .info {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
display: block;
|
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="thvuemwp" :class="{ isMe }">
|
<div class="thvuemwp" :class="{ isMe }" v-size="{ max: [400, 500] }">
|
||||||
<MkAvatar class="avatar" :user="message.user"/>
|
<MkAvatar class="avatar" :user="message.user"/>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="balloon" :class="{ noText: message.text == null }" >
|
<div class="balloon" :class="{ noText: message.text == null }" >
|
||||||
@@ -92,11 +92,6 @@ export default defineComponent({
|
|||||||
width: 54px;
|
width: 54px;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
transition: all 0.1s ease;
|
transition: all 0.1s ease;
|
||||||
|
|
||||||
@media (max-width: 400px) {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .content {
|
> .content {
|
||||||
@@ -175,14 +170,6 @@ export default defineComponent({
|
|||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
color: rgba(#000, 0.8);
|
color: rgba(#000, 0.8);
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
padding: 8px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 400px) {
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
& + .file {
|
& + .file {
|
||||||
> a {
|
> a {
|
||||||
border-radius: 0 0 16px 16px;
|
border-radius: 0 0 16px 16px;
|
||||||
@@ -326,5 +313,34 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.max-width_400px {
|
||||||
|
> .avatar {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .content {
|
||||||
|
> .balloon {
|
||||||
|
> .content {
|
||||||
|
> .text {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.max-width_500px {
|
||||||
|
> .content {
|
||||||
|
> .balloon {
|
||||||
|
> .content {
|
||||||
|
> .text {
|
||||||
|
padding: 8px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faBars, faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
|
import { faBars, faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
||||||
import * as os from '@/os';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||||
import { faPencilAlt, faPlug } from '@fortawesome/free-solid-svg-icons';
|
import { faPencilAlt, faPlug } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import XContainer from './page-editor.container.vue';
|
import XContainer from './page-editor.container.vue';
|
||||||
@@ -66,7 +66,8 @@ import * as os from '@/os';
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XContainer, MkTextarea
|
XContainer, MkTextarea,
|
||||||
|
XV: defineAsyncComponent(() => import('./page-editor.script-block.vue')),
|
||||||
},
|
},
|
||||||
|
|
||||||
inject: ['getScriptBlockList'],
|
inject: ['getScriptBlockList'],
|
||||||
@@ -135,10 +136,6 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeCreate() {
|
|
||||||
this.$options.components.XV = require('./page-editor.script-block.vue').default;
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
if (this.value.value == null) this.value.value = null;
|
if (this.value.value == null) this.value.value = null;
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,21 @@
|
|||||||
<div>
|
<div>
|
||||||
<MkTab v-model:value="tab" :items="[{ label: $t('_pages.my'), value: 'my', icon: faEdit }, { label: $t('_pages.liked'), value: 'liked', icon: faHeart }]"/>
|
<MkTab v-model:value="tab" :items="[{ label: $t('_pages.my'), value: 'my', icon: faEdit }, { label: $t('_pages.liked'), value: 'liked', icon: faHeart }]"/>
|
||||||
|
|
||||||
<div class="rknalgpo my" v-if="tab === 'my'">
|
<div class="_section">
|
||||||
|
<div class="rknalgpo _content my" v-if="tab === 'my'">
|
||||||
<MkButton class="new" @click="create()"><Fa :icon="faPlus"/></MkButton>
|
<MkButton class="new" @click="create()"><Fa :icon="faPlus"/></MkButton>
|
||||||
<MkPagination :pagination="myPagesPagination" #default="{items}">
|
<MkPagination :pagination="myPagesPagination" #default="{items}">
|
||||||
<MkPagePreview v-for="page in items" class="ckltabjg" :page="page" :key="page.id"/>
|
<MkPagePreview v-for="page in items" class="ckltabjg" :page="page" :key="page.id"/>
|
||||||
</MkPagination>
|
</MkPagination>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rknalgpo" v-if="tab === 'liked'">
|
<div class="rknalgpo _content" v-if="tab === 'liked'">
|
||||||
<MkPagination :pagination="likedPagesPagination" #default="{items}">
|
<MkPagination :pagination="likedPagesPagination" #default="{items}">
|
||||||
<MkPagePreview v-for="like in items" class="ckltabjg" :page="like.page" :key="like.page.id"/>
|
<MkPagePreview v-for="like in items" class="ckltabjg" :page="like.page" :key="like.page.id"/>
|
||||||
</MkPagination>
|
</MkPagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -64,8 +66,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.rknalgpo {
|
.rknalgpo {
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
&.my .ckltabjg:first-child {
|
&.my .ckltabjg:first-child {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export default defineComponent({
|
|||||||
this.exportTarget == 'following' ? 'i/export-following' :
|
this.exportTarget == 'following' ? 'i/export-following' :
|
||||||
this.exportTarget == 'blocking' ? 'i/export-blocking' :
|
this.exportTarget == 'blocking' ? 'i/export-blocking' :
|
||||||
this.exportTarget == 'user-lists' ? 'i/export-user-lists' :
|
this.exportTarget == 'user-lists' ? 'i/export-user-lists' :
|
||||||
|
this.exportTarget == 'mute' ? 'i/export-mute' :
|
||||||
null, {})
|
null, {})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
os.dialog({
|
os.dialog({
|
||||||
@@ -69,31 +70,15 @@ export default defineComponent({
|
|||||||
data.append('file', file);
|
data.append('file', file);
|
||||||
data.append('i', this.$store.state.i.token);
|
data.append('i', this.$store.state.i.token);
|
||||||
|
|
||||||
const dialog = os.dialog({
|
const promise = fetch(apiUrl + '/drive/files/create', {
|
||||||
type: 'waiting',
|
|
||||||
text: this.$t('uploading') + '...',
|
|
||||||
showOkButton: false,
|
|
||||||
showCancelButton: false,
|
|
||||||
cancelableByBgClick: false
|
|
||||||
});
|
|
||||||
|
|
||||||
fetch(apiUrl + '/drive/files/create', {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: data
|
body: data
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(f => {
|
.then(f => {
|
||||||
this.reqImport(f);
|
this.reqImport(f);
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
os.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: e
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
dialog.close();
|
|
||||||
});
|
});
|
||||||
|
os.promiseDialog(promise);
|
||||||
},
|
},
|
||||||
|
|
||||||
reqImport(file) {
|
reqImport(file) {
|
||||||
|
|||||||
@@ -106,6 +106,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="_card _vMargin">
|
||||||
|
<div class="_title">Waiting dialog</div>
|
||||||
|
<div class="_content">
|
||||||
|
<MkButton inline @click="openWaitingDialog()">icon only</MkButton>
|
||||||
|
<MkButton inline @click="openWaitingDialog('Doing')">with text</MkButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="_card _vMargin">
|
<div class="_card _vMargin">
|
||||||
<div class="_title">Messaging window</div>
|
<div class="_title">Messaging window</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
@@ -224,6 +232,13 @@ export default defineComponent({
|
|||||||
os.pageWindow('/my/messaging', defineAsyncComponent(() => import('@/pages/messaging/index.vue')));
|
os.pageWindow('/my/messaging', defineAsyncComponent(() => import('@/pages/messaging/index.vue')));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openWaitingDialog(text?) {
|
||||||
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
setTimeout(resolve, 2000);
|
||||||
|
});
|
||||||
|
os.promiseDialog(promise, null, null, text);
|
||||||
|
},
|
||||||
|
|
||||||
resetTutorial() {
|
resetTutorial() {
|
||||||
this.$store.dispatch('settings/set', { key: 'tutorial', value: 0 });
|
this.$store.dispatch('settings/set', { key: 'tutorial', value: 0 });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -75,6 +75,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section class="_section">
|
||||||
|
<details class="_content">
|
||||||
|
<summary>{{ $t('sample') }}</summary>
|
||||||
|
<MkSample/>
|
||||||
|
</details>
|
||||||
|
</section>
|
||||||
<section class="_section">
|
<section class="_section">
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<MkButton inline @click="preview">{{ $t('preview') }}</MkButton>
|
<MkButton inline @click="preview">{{ $t('preview') }}</MkButton>
|
||||||
@@ -88,16 +94,17 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faPalette, faChevronDown, faKeyboard } from '@fortawesome/free-solid-svg-icons';
|
import { faPalette, faChevronDown, faKeyboard } from '@fortawesome/free-solid-svg-icons';
|
||||||
import * as JSON5 from 'json5';
|
import * as JSON5 from 'json5';
|
||||||
|
import { toUnicode } from 'punycode';
|
||||||
|
|
||||||
import MkRadio from '@/components/ui/radio.vue';
|
import MkRadio from '@/components/ui/radio.vue';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import MkButton from '@/components/ui/button.vue';
|
||||||
import MkInput from '@/components/ui/input.vue';
|
import MkInput from '@/components/ui/input.vue';
|
||||||
import MkTextarea from '@/components/ui/textarea.vue';
|
import MkTextarea from '@/components/ui/textarea.vue';
|
||||||
import MkSelect from '@/components/ui/select.vue';
|
import MkSelect from '@/components/ui/select.vue';
|
||||||
|
import MkSample from '@/components/sample.vue';
|
||||||
|
|
||||||
import { convertToMisskeyTheme, ThemeValue, convertToViewModel, ThemeViewModel } from '@/scripts/theme-editor';
|
import { convertToMisskeyTheme, ThemeValue, convertToViewModel, ThemeViewModel } from '@/scripts/theme-editor';
|
||||||
import { Theme, applyTheme, lightTheme, darkTheme, themeProps, validateTheme } from '@/scripts/theme';
|
import { Theme, applyTheme, lightTheme, darkTheme, themeProps, validateTheme } from '@/scripts/theme';
|
||||||
import { toUnicode } from 'punycode';
|
|
||||||
import { host } from '@/config';
|
import { host } from '@/config';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
@@ -107,7 +114,8 @@ export default defineComponent({
|
|||||||
MkButton,
|
MkButton,
|
||||||
MkInput,
|
MkInput,
|
||||||
MkTextarea,
|
MkTextarea,
|
||||||
MkSelect
|
MkSelect,
|
||||||
|
MkSample,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|||||||
@@ -49,47 +49,63 @@ export default defineComponent({
|
|||||||
menuOpened: false,
|
menuOpened: false,
|
||||||
queue: 0,
|
queue: 0,
|
||||||
width: 0,
|
width: 0,
|
||||||
INFO: {
|
INFO: computed(() => {
|
||||||
header: [{
|
const header = [{
|
||||||
id: 'home',
|
id: 'home',
|
||||||
title: null,
|
title: null,
|
||||||
tooltip: this.$t('_timelines.home'),
|
tooltip: this.$t('_timelines.home'),
|
||||||
icon: faHome,
|
icon: faHome,
|
||||||
onClick: () => { this.src = 'home'; this.saveSrc(); },
|
onClick: () => { this.src = 'home'; this.saveSrc(); },
|
||||||
selected: computed(() => this.src === 'home')
|
selected: computed(() => this.src === 'home')
|
||||||
}, {
|
}];
|
||||||
|
|
||||||
|
if (!this.$store.state.instance.meta.disableLocalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin) {
|
||||||
|
header.push({
|
||||||
id: 'local',
|
id: 'local',
|
||||||
title: null,
|
title: null,
|
||||||
tooltip: this.$t('_timelines.local'),
|
tooltip: this.$t('_timelines.local'),
|
||||||
icon: faComments,
|
icon: faComments,
|
||||||
onClick: () => { this.src = 'local'; this.saveSrc(); },
|
onClick: () => { this.src = 'local'; this.saveSrc(); },
|
||||||
selected: computed(() => this.src === 'local')
|
selected: computed(() => this.src === 'local')
|
||||||
}, {
|
});
|
||||||
|
|
||||||
|
header.push({
|
||||||
id: 'social',
|
id: 'social',
|
||||||
title: null,
|
title: null,
|
||||||
tooltip: this.$t('_timelines.social'),
|
tooltip: this.$t('_timelines.social'),
|
||||||
icon: faShareAlt,
|
icon: faShareAlt,
|
||||||
onClick: () => { this.src = 'social'; this.saveSrc(); },
|
onClick: () => { this.src = 'social'; this.saveSrc(); },
|
||||||
selected: computed(() => this.src === 'social')
|
selected: computed(() => this.src === 'social')
|
||||||
}, {
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.$store.state.instance.meta.disableGlobalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin) {
|
||||||
|
header.push({
|
||||||
id: 'global',
|
id: 'global',
|
||||||
title: null,
|
title: null,
|
||||||
tooltip: this.$t('_timelines.global'),
|
tooltip: this.$t('_timelines.global'),
|
||||||
icon: faGlobe,
|
icon: faGlobe,
|
||||||
onClick: () => { this.src = 'global'; this.saveSrc(); },
|
onClick: () => { this.src = 'global'; this.saveSrc(); },
|
||||||
selected: computed(() => this.src === 'global')
|
selected: computed(() => this.src === 'global')
|
||||||
}, {
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
header.push({
|
||||||
id: 'other',
|
id: 'other',
|
||||||
title: null,
|
title: null,
|
||||||
icon: faEllipsisH,
|
icon: faEllipsisH,
|
||||||
onClick: this.choose,
|
onClick: this.choose,
|
||||||
indicate: computed(() => this.$store.state.i.hasUnreadAntenna || this.$store.state.i.hasUnreadChannel)
|
indicate: computed(() => this.$store.state.i.hasUnreadAntenna || this.$store.state.i.hasUnreadChannel)
|
||||||
}],
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
header,
|
||||||
action: {
|
action: {
|
||||||
icon: faPencilAlt,
|
icon: faPencilAlt,
|
||||||
handler: () => os.post()
|
handler: () => os.post()
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
}),
|
||||||
faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite, faSatelliteDish, faCircle
|
faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite, faSatelliteDish, faCircle
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -85,8 +85,8 @@
|
|||||||
|
|
||||||
<router-view :user="user"></router-view>
|
<router-view :user="user"></router-view>
|
||||||
<template v-if="$route.name == 'user'">
|
<template v-if="$route.name == 'user'">
|
||||||
<div class="_section" v-if="user.pinnedNotes.length > 0">
|
<div class="_section">
|
||||||
<div class="_content _vMargin">
|
<div class="_content _vMargin" v-if="user.pinnedNotes.length > 0">
|
||||||
<XNote v-for="note in user.pinnedNotes" class="note _vMargin" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :detail="true" :pinned="true"/>
|
<XNote v-for="note in user.pinnedNotes" class="note _vMargin" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :detail="true" :pinned="true"/>
|
||||||
</div>
|
</div>
|
||||||
<MkFolder :body-togglable="true" class="_content _vMargin" persist-key="user-images">
|
<MkFolder :body-togglable="true" class="_content _vMargin" persist-key="user-images">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { createAiScriptEnv } from '../aiscript/api';
|
|||||||
import { collectPageVars } from '../collect-page-vars';
|
import { collectPageVars } from '../collect-page-vars';
|
||||||
import { initLib } from './lib';
|
import { initLib } from './lib';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import { markRaw, ref, Ref } from 'vue';
|
||||||
|
|
||||||
type Fn = {
|
type Fn = {
|
||||||
slots: string[];
|
slots: string[];
|
||||||
@@ -23,7 +24,7 @@ export class Hpml {
|
|||||||
public aiscript?: AiScript;
|
public aiscript?: AiScript;
|
||||||
private pageVarUpdatedCallback;
|
private pageVarUpdatedCallback;
|
||||||
public canvases: Record<string, HTMLCanvasElement> = {};
|
public canvases: Record<string, HTMLCanvasElement> = {};
|
||||||
public vars: Record<string, any>;
|
public vars: Ref<Record<string, any>> = ref({});
|
||||||
public page: Record<string, any>;
|
public page: Record<string, any>;
|
||||||
|
|
||||||
private opts: {
|
private opts: {
|
||||||
@@ -38,7 +39,7 @@ export class Hpml {
|
|||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
|
|
||||||
if (this.opts.enableAiScript) {
|
if (this.opts.enableAiScript) {
|
||||||
this.aiscript = new AiScript({ ...createAiScriptEnv({
|
this.aiscript = markRaw(new AiScript({ ...createAiScriptEnv({
|
||||||
storageKey: 'pages:' + this.page.id
|
storageKey: 'pages:' + this.page.id
|
||||||
}), ...initLib(this)}, {
|
}), ...initLib(this)}, {
|
||||||
in: (q) => {
|
in: (q) => {
|
||||||
@@ -56,7 +57,7 @@ export class Hpml {
|
|||||||
},
|
},
|
||||||
log: (type, params) => {
|
log: (type, params) => {
|
||||||
},
|
},
|
||||||
});
|
}));
|
||||||
|
|
||||||
this.aiscript.scope.opts.onUpdated = (name, value) => {
|
this.aiscript.scope.opts.onUpdated = (name, value) => {
|
||||||
this.eval();
|
this.eval();
|
||||||
@@ -89,7 +90,7 @@ export class Hpml {
|
|||||||
@autobind
|
@autobind
|
||||||
public eval() {
|
public eval() {
|
||||||
try {
|
try {
|
||||||
this.vars = this.evaluateVars();
|
this.vars.value = this.evaluateVars();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//this.onError(e);
|
//this.onError(e);
|
||||||
}
|
}
|
||||||
@@ -99,7 +100,7 @@ export class Hpml {
|
|||||||
public interpolate(str: string) {
|
public interpolate(str: string) {
|
||||||
if (str == null) return null;
|
if (str == null) return null;
|
||||||
return str.replace(/{(.+?)}/g, match => {
|
return str.replace(/{(.+?)}/g, match => {
|
||||||
const v = this.vars ? this.vars[match.slice(1, -1).trim()] : null;
|
const v = this.vars[match.slice(1, -1).trim()];
|
||||||
return v == null ? 'NULL' : v.toString();
|
return v == null ? 'NULL' : v.toString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function popout(path: string, w?: HTMLElement) {
|
|||||||
`width=${width}, height=${height}, top=${y}, left=${x}`);
|
`width=${width}, height=${height}, top=${y}, left=${x}`);
|
||||||
} else {
|
} else {
|
||||||
const width = 400;
|
const width = 400;
|
||||||
const height = 450;
|
const height = 500;
|
||||||
const x = window.top.outerHeight / 2 + window.top.screenY - (height / 2);
|
const x = window.top.outerHeight / 2 + window.top.screenY - (height / 2);
|
||||||
const y = window.top.outerWidth / 2 + window.top.screenX - (width / 2);
|
const y = window.top.outerWidth / 2 + window.top.screenX - (width / 2);
|
||||||
window.open(url, url,
|
window.open(url, url,
|
||||||
|
|||||||
@@ -48,28 +48,19 @@ export async function search(q?: string | null | undefined) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (q.startsWith('https://')) {
|
if (q.startsWith('https://')) {
|
||||||
const dialog = os.dialog({
|
const promise = os.api('ap/show', {
|
||||||
type: 'waiting',
|
|
||||||
text: i18n.global.t('fetchingAsApObject') + '...',
|
|
||||||
showOkButton: false,
|
|
||||||
showCancelButton: false,
|
|
||||||
cancelableByBgClick: false
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await os.api('ap/show', {
|
|
||||||
uri: q
|
uri: q
|
||||||
});
|
});
|
||||||
dialog.cancel();
|
|
||||||
|
os.promiseDialog(promise, null, null, i18n.global.t('fetchingAsApObject'));
|
||||||
|
|
||||||
|
const res = await promise;
|
||||||
|
|
||||||
if (res.type === 'User') {
|
if (res.type === 'User') {
|
||||||
router.push(`/@${res.object.username}@${res.object.host}`);
|
router.push(`/@${res.object.username}@${res.object.host}`);
|
||||||
} else if (res.type === 'Note') {
|
} else if (res.type === 'Note') {
|
||||||
router.push(`/notes/${res.object.id}`);
|
router.push(`/notes/${res.object.id}`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
dialog.cancel();
|
|
||||||
// TODO: Show error
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,6 +293,10 @@ export default defineComponent({
|
|||||||
|
|
||||||
> .spacer {
|
> .spacer {
|
||||||
height: 82px;
|
height: 82px;
|
||||||
|
|
||||||
|
@media (min-width: ($widgets-hide-threshold + 1px)) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ export default defineComponent({
|
|||||||
.mk-app {
|
.mk-app {
|
||||||
$header-height: 52px;
|
$header-height: 52px;
|
||||||
$ui-font-size: 1em; // TODO: どこかに集約したい
|
$ui-font-size: 1em; // TODO: どこかに集約したい
|
||||||
$widgets-hide-threshold: 1090px;
|
|
||||||
|
|
||||||
// ほんとは単に 100vh と書きたいところだが... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
// ほんとは単に 100vh と書きたいところだが... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
||||||
min-height: calc(var(--vh, 1vh) * 100);
|
min-height: calc(var(--vh, 1vh) * 100);
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ export type Source = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
mediaProxy?: string;
|
mediaProxy?: string;
|
||||||
|
|
||||||
|
signToActivityPubGet?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import fetch, { HeadersInit } from 'node-fetch';
|
|||||||
import { HttpProxyAgent } from 'http-proxy-agent';
|
import { HttpProxyAgent } from 'http-proxy-agent';
|
||||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
import { URL } from 'url';
|
||||||
|
|
||||||
export async function getJson(url: string, accept = 'application/json, */*', timeout = 10000, headers?: HeadersInit) {
|
export async function getJson(url: string, accept = 'application/json, */*', timeout = 10000, headers?: HeadersInit) {
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
@@ -69,14 +70,14 @@ const _https = new https.Agent({
|
|||||||
* Get http proxy or non-proxy agent
|
* Get http proxy or non-proxy agent
|
||||||
*/
|
*/
|
||||||
export const httpAgent = config.proxy
|
export const httpAgent = config.proxy
|
||||||
? new HttpProxyAgent(config.proxy)
|
? new HttpProxyAgent(config.proxy) as unknown as http.Agent
|
||||||
: _http;
|
: _http;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get https proxy or non-proxy agent
|
* Get https proxy or non-proxy agent
|
||||||
*/
|
*/
|
||||||
export const httpsAgent = config.proxy
|
export const httpsAgent = config.proxy
|
||||||
? new HttpsProxyAgent(config.proxy)
|
? new HttpsProxyAgent(config.proxy) as unknown as https.Agent
|
||||||
: _https;
|
: _https;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import * as http from 'http';
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
import { sign } from 'http-signature';
|
import { sign } from 'http-signature';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
@@ -7,6 +8,9 @@ import { ILocalUser } from '../../models/entities/user';
|
|||||||
import { UserKeypairs } from '../../models';
|
import { UserKeypairs } from '../../models';
|
||||||
import { ensure } from '../../prelude/ensure';
|
import { ensure } from '../../prelude/ensure';
|
||||||
import { getAgentByUrl } from '../../misc/fetch';
|
import { getAgentByUrl } from '../../misc/fetch';
|
||||||
|
import { URL } from 'url';
|
||||||
|
import got from 'got';
|
||||||
|
import * as Got from 'got';
|
||||||
|
|
||||||
export default async (user: ILocalUser, url: string, object: any) => {
|
export default async (user: ILocalUser, url: string, object: any) => {
|
||||||
const timeout = 10 * 1000;
|
const timeout = 10 * 1000;
|
||||||
@@ -62,3 +66,96 @@ export default async (user: ILocalUser, url: string, object: any) => {
|
|||||||
req.end(data);
|
req.end(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get AP object with http-signature
|
||||||
|
* @param user http-signature user
|
||||||
|
* @param url URL to fetch
|
||||||
|
*/
|
||||||
|
export async function signedGet(url: string, user: ILocalUser) {
|
||||||
|
const timeout = 10 * 1000;
|
||||||
|
|
||||||
|
const keypair = await UserKeypairs.findOne({
|
||||||
|
userId: user.id
|
||||||
|
}).then(ensure);
|
||||||
|
|
||||||
|
const req = got.get<any>(url, {
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/activity+json, application/ld+json',
|
||||||
|
'User-Agent': config.userAgent,
|
||||||
|
},
|
||||||
|
responseType: 'json',
|
||||||
|
timeout,
|
||||||
|
hooks: {
|
||||||
|
beforeRequest: [
|
||||||
|
options => {
|
||||||
|
options.request = (url: URL, opt: http.RequestOptions, callback?: (response: any) => void) => {
|
||||||
|
// Select custom agent by URL
|
||||||
|
opt.agent = getAgentByUrl(url, false);
|
||||||
|
|
||||||
|
// Wrap original https?.request
|
||||||
|
const requestFunc = url.protocol === 'http:' ? http.request : https.request;
|
||||||
|
const clientRequest = requestFunc(url, opt, callback) as http.ClientRequest;
|
||||||
|
|
||||||
|
// HTTP-Signature
|
||||||
|
sign(clientRequest, {
|
||||||
|
authorizationHeaderName: 'Signature',
|
||||||
|
key: keypair.privateKey,
|
||||||
|
keyId: `${config.url}/users/${user.id}#main-key`,
|
||||||
|
headers: ['(request-target)', 'host', 'date', 'accept']
|
||||||
|
});
|
||||||
|
|
||||||
|
return clientRequest;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
retry: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await receiveResponce(req, 10 * 1024 * 1024);
|
||||||
|
|
||||||
|
return res.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive response (with size limit)
|
||||||
|
* @param req Request
|
||||||
|
* @param maxSize size limit
|
||||||
|
*/
|
||||||
|
export async function receiveResponce<T>(req: Got.CancelableRequest<Got.Response<T>>, maxSize: number) {
|
||||||
|
// 応答ヘッダでサイズチェック
|
||||||
|
req.on('response', (res: Got.Response) => {
|
||||||
|
const contentLength = res.headers['content-length'];
|
||||||
|
if (contentLength != null) {
|
||||||
|
const size = Number(contentLength);
|
||||||
|
if (size > maxSize) {
|
||||||
|
req.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 受信中のデータでサイズチェック
|
||||||
|
req.on('downloadProgress', (progress: Got.Progress) => {
|
||||||
|
if (progress.transferred > maxSize) {
|
||||||
|
req.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 応答取得 with ステータスコードエラーの整形
|
||||||
|
const res = await req.catch(e => {
|
||||||
|
if (e.name === 'HTTPError') {
|
||||||
|
const statusCode = (e as Got.HTTPError).response.statusCode;
|
||||||
|
const statusMessage = (e as Got.HTTPError).response.statusMessage;
|
||||||
|
throw {
|
||||||
|
name: `StatusError`,
|
||||||
|
statusCode,
|
||||||
|
message: `${statusCode} ${statusMessage}`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
import config from '../../config';
|
||||||
import { getJson } from '../../misc/fetch';
|
import { getJson } from '../../misc/fetch';
|
||||||
|
import { ILocalUser } from '../../models/entities/user';
|
||||||
|
import { getInstanceActor } from '../../services/instance-actor';
|
||||||
|
import { signedGet } from './request';
|
||||||
import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type';
|
import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type';
|
||||||
|
|
||||||
export default class Resolver {
|
export default class Resolver {
|
||||||
private history: Set<string>;
|
private history: Set<string>;
|
||||||
|
private user?: ILocalUser;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.history = new Set();
|
this.history = new Set();
|
||||||
@@ -39,7 +44,13 @@ export default class Resolver {
|
|||||||
|
|
||||||
this.history.add(value);
|
this.history.add(value);
|
||||||
|
|
||||||
const object = await getJson(value, 'application/activity+json, application/ld+json');
|
if (config.signToActivityPubGet && !this.user) {
|
||||||
|
this.user = await getInstanceActor();
|
||||||
|
}
|
||||||
|
|
||||||
|
const object = this.user
|
||||||
|
? await signedGet(value, this.user)
|
||||||
|
: await getJson(value, 'application/activity+json, application/ld+json');
|
||||||
|
|
||||||
if (object == null || (
|
if (object == null || (
|
||||||
Array.isArray(object['@context']) ?
|
Array.isArray(object['@context']) ?
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ export default define(meta, async (ps, me) => {
|
|||||||
throw new ApiError(meta.errors.accessDenied);
|
throw new ApiError(meta.errors.accessDenied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line:no-unnecessary-initializer
|
||||||
let banner = undefined;
|
let banner = undefined;
|
||||||
if (ps.bannerId != null) {
|
if (ps.bannerId != null) {
|
||||||
banner = await DriveFiles.findOne({
|
banner = await DriveFiles.findOne({
|
||||||
|
|||||||
17
src/services/instance-actor.ts
Normal file
17
src/services/instance-actor.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { createSystemUser } from './create-system-user';
|
||||||
|
import { ILocalUser } from '../models/entities/user';
|
||||||
|
import { Users } from '../models';
|
||||||
|
|
||||||
|
const ACTOR_USERNAME = 'instance.actor' as const;
|
||||||
|
|
||||||
|
export async function getInstanceActor(): Promise<ILocalUser> {
|
||||||
|
const user = await Users.findOne({
|
||||||
|
host: null,
|
||||||
|
username: ACTOR_USERNAME
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user) return user as ILocalUser;
|
||||||
|
|
||||||
|
const created = await createSystemUser(ACTOR_USERNAME);
|
||||||
|
return created as ILocalUser;
|
||||||
|
}
|
||||||
@@ -15,8 +15,9 @@ import { getFileInfo } from '../src/misc/get-file-info';
|
|||||||
describe('Get file info', () => {
|
describe('Get file info', () => {
|
||||||
it('Empty file', async (async () => {
|
it('Empty file', async (async () => {
|
||||||
const path = `${__dirname}/resources/emptyfile`;
|
const path = `${__dirname}/resources/emptyfile`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 0,
|
size: 0,
|
||||||
md5: 'd41d8cd98f00b204e9800998ecf8427e',
|
md5: 'd41d8cd98f00b204e9800998ecf8427e',
|
||||||
@@ -26,14 +27,14 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: undefined,
|
width: undefined,
|
||||||
height: undefined,
|
height: undefined,
|
||||||
blurhash: undefined
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('Generic JPEG', async (async () => {
|
it('Generic JPEG', async (async () => {
|
||||||
const path = `${__dirname}/resources/Lenna.jpg`;
|
const path = `${__dirname}/resources/Lenna.jpg`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 25360,
|
size: 25360,
|
||||||
md5: '091b3f259662aa31e2ffef4519951168',
|
md5: '091b3f259662aa31e2ffef4519951168',
|
||||||
@@ -43,14 +44,14 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: 512,
|
width: 512,
|
||||||
height: 512,
|
height: 512,
|
||||||
blurhash: 'yFLxJjH[NE}@^PRiN_}Y=aVZNvFxxZ#SwIt7Eg%KIp-ospv~Nex[R6t3xZI:iwt6kWxDafoySgsAfR$*oyM|S2t7$iV[tQNbaKn%xt'
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('Generic APNG', async (async () => {
|
it('Generic APNG', async (async () => {
|
||||||
const path = `${__dirname}/resources/anime.png`;
|
const path = `${__dirname}/resources/anime.png`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 1868,
|
size: 1868,
|
||||||
md5: '08189c607bea3b952704676bb3c979e0',
|
md5: '08189c607bea3b952704676bb3c979e0',
|
||||||
@@ -60,14 +61,14 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: 256,
|
width: 256,
|
||||||
height: 256,
|
height: 256,
|
||||||
blurhash: 'y8S?Mr-;=~~Xs;%foL?bWVs;xbR%NFay^ms;I-InI-xbs;%gofj[I-s;-WxbI-WUayxb$,NFR*~Wa{R%xbayNFI.oMj[oMNFWB$,WU'
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('Generic AGIF', async (async () => {
|
it('Generic AGIF', async (async () => {
|
||||||
const path = `${__dirname}/resources/anime.gif`;
|
const path = `${__dirname}/resources/anime.gif`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 2248,
|
size: 2248,
|
||||||
md5: '32c47a11555675d9267aee1a86571e7e',
|
md5: '32c47a11555675d9267aee1a86571e7e',
|
||||||
@@ -77,14 +78,14 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: 256,
|
width: 256,
|
||||||
height: 256,
|
height: 256,
|
||||||
blurhash: 'y8S?Mr-;=~~Xs;%foL?bWVs;xbR%NFay^ms;I-InI-xbs;%gofj[I-s;-WxbI-WUayxb$,NFR*~Wa{R%xbayNFI.oMj[oMNFWB$,WU'
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('PNG with alpha', async (async () => {
|
it('PNG with alpha', async (async () => {
|
||||||
const path = `${__dirname}/resources/with-alpha.png`;
|
const path = `${__dirname}/resources/with-alpha.png`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 3772,
|
size: 3772,
|
||||||
md5: 'f73535c3e1e27508885b69b10cf6e991',
|
md5: 'f73535c3e1e27508885b69b10cf6e991',
|
||||||
@@ -94,14 +95,14 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: 256,
|
width: 256,
|
||||||
height: 256,
|
height: 256,
|
||||||
blurhash: 'y74P29kDpdp{k?VDZ#krkCaefkf6fQf5HXZ$krkqadaKaJkCaKkXfkkCf5fkQ8kXZ#VDaKk?krZ~kCf6kDf6f5f6U]krZ#Z#aekrkq'
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('Generic SVG', async (async () => {
|
it('Generic SVG', async (async () => {
|
||||||
const path = `${__dirname}/resources/image.svg`;
|
const path = `${__dirname}/resources/image.svg`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 505,
|
size: 505,
|
||||||
md5: 'b6f52b4b021e7b92cdd04509c7267965',
|
md5: 'b6f52b4b021e7b92cdd04509c7267965',
|
||||||
@@ -111,15 +112,15 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: 256,
|
width: 256,
|
||||||
height: 256,
|
height: 256,
|
||||||
blurhash: 'yMEKyd1U1?=nZN-2EwofR*oHnijYX6S50J=m]WEVl9JE$SR*xHR;XSX8nQxB-WS6Nts*aKskWnaxR%s*i_n~X6S5=#NgOAs*enoIWU'
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('SVG with XML definition', async (async () => {
|
it('SVG with XML definition', async (async () => {
|
||||||
// https://github.com/syuilo/misskey/issues/4413
|
// https://github.com/syuilo/misskey/issues/4413
|
||||||
const path = `${__dirname}/resources/with-xml-def.svg`;
|
const path = `${__dirname}/resources/with-xml-def.svg`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 544,
|
size: 544,
|
||||||
md5: '4b7a346cde9ccbeb267e812567e33397',
|
md5: '4b7a346cde9ccbeb267e812567e33397',
|
||||||
@@ -129,14 +130,14 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: 256,
|
width: 256,
|
||||||
height: 256,
|
height: 256,
|
||||||
blurhash: 'yMEKyd1U1?=nZN-2EwofR*oHnijYX6S50J=m]WEVl9JE$SR*xHR;XSX8nQxB-WS6Nts*aKskWnaxR%s*i_n~X6S5=#NgOAs*enoIWU'
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('Dimension limit', async (async () => {
|
it('Dimension limit', async (async () => {
|
||||||
const path = `${__dirname}/resources/25000x25000.png`;
|
const path = `${__dirname}/resources/25000x25000.png`;
|
||||||
const info = await getFileInfo(path);
|
const info = await getFileInfo(path) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
|
delete info.blurhash;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 75933,
|
size: 75933,
|
||||||
md5: '268c5dde99e17cf8fe09f1ab3f97df56',
|
md5: '268c5dde99e17cf8fe09f1ab3f97df56',
|
||||||
@@ -146,7 +147,6 @@ describe('Get file info', () => {
|
|||||||
},
|
},
|
||||||
width: 25000,
|
width: 25000,
|
||||||
height: 25000,
|
height: 25000,
|
||||||
blurhash: undefined
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|||||||
154
yarn.lock
154
yarn.lock
@@ -236,6 +236,11 @@
|
|||||||
"@nodelib/fs.scandir" "2.1.3"
|
"@nodelib/fs.scandir" "2.1.3"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
|
"@sindresorhus/is@^3.1.1":
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-3.1.2.tgz#548650de521b344e3781fbdb0ece4aa6f729afb8"
|
||||||
|
integrity sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ==
|
||||||
|
|
||||||
"@sinonjs/commons@^1.7.0":
|
"@sinonjs/commons@^1.7.0":
|
||||||
version "1.7.2"
|
version "1.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.2.tgz#505f55c74e0272b43f6c52d81946bed7058fc0e2"
|
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.2.tgz#505f55c74e0272b43f6c52d81946bed7058fc0e2"
|
||||||
@@ -266,6 +271,13 @@
|
|||||||
stringz "2.1.0"
|
stringz "2.1.0"
|
||||||
uuid "7.0.3"
|
uuid "7.0.3"
|
||||||
|
|
||||||
|
"@szmarczak/http-timer@^4.0.5":
|
||||||
|
version "4.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152"
|
||||||
|
integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==
|
||||||
|
dependencies:
|
||||||
|
defer-to-connect "^2.0.0"
|
||||||
|
|
||||||
"@tokenizer/token@^0.1.0", "@tokenizer/token@^0.1.1":
|
"@tokenizer/token@^0.1.0", "@tokenizer/token@^0.1.1":
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.1.1.tgz#f0d92c12f87079ddfd1b29f614758b9696bc29e3"
|
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.1.1.tgz#f0d92c12f87079ddfd1b29f614758b9696bc29e3"
|
||||||
@@ -308,6 +320,16 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/ioredis" "*"
|
"@types/ioredis" "*"
|
||||||
|
|
||||||
|
"@types/cacheable-request@^6.0.1":
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976"
|
||||||
|
integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/http-cache-semantics" "*"
|
||||||
|
"@types/keyv" "*"
|
||||||
|
"@types/node" "*"
|
||||||
|
"@types/responselike" "*"
|
||||||
|
|
||||||
"@types/cbor@5.0.1":
|
"@types/cbor@5.0.1":
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/cbor/-/cbor-5.0.1.tgz#e147bbe09ada4db7000ec6c23eafb5f67f5422a5"
|
resolved "https://registry.yarnpkg.com/@types/cbor/-/cbor-5.0.1.tgz#e147bbe09ada4db7000ec6c23eafb5f67f5422a5"
|
||||||
@@ -488,6 +510,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.1.tgz#d775e93630c2469c2f980fc27e3143240335db3b"
|
resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.1.tgz#d775e93630c2469c2f980fc27e3143240335db3b"
|
||||||
integrity sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==
|
integrity sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==
|
||||||
|
|
||||||
|
"@types/http-cache-semantics@*":
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a"
|
||||||
|
integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==
|
||||||
|
|
||||||
"@types/ioredis@*":
|
"@types/ioredis@*":
|
||||||
version "4.14.9"
|
version "4.14.9"
|
||||||
resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.14.9.tgz#774387d44d3ad60e1b849044b2b28b96e5813866"
|
resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.14.9.tgz#774387d44d3ad60e1b849044b2b28b96e5813866"
|
||||||
@@ -539,6 +566,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
|
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
|
||||||
integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==
|
integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==
|
||||||
|
|
||||||
|
"@types/keyv@*":
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7"
|
||||||
|
integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/koa-bodyparser@4.3.0":
|
"@types/koa-bodyparser@4.3.0":
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz#54ecd662c45f3a4fa9de849528de5fc8ab269ba5"
|
resolved "https://registry.yarnpkg.com/@types/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz#54ecd662c45f3a4fa9de849528de5fc8ab269ba5"
|
||||||
@@ -798,6 +832,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/responselike@*", "@types/responselike@^1.0.0":
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
|
||||||
|
integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/rimraf@3.0.0":
|
"@types/rimraf@3.0.0":
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.0.tgz#b9d03f090ece263671898d57bb7bb007023ac19f"
|
resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.0.tgz#b9d03f090ece263671898d57bb7bb007023ac19f"
|
||||||
@@ -2045,6 +2086,24 @@ cache-content-type@^1.0.0:
|
|||||||
mime-types "^2.1.18"
|
mime-types "^2.1.18"
|
||||||
ylru "^1.2.0"
|
ylru "^1.2.0"
|
||||||
|
|
||||||
|
cacheable-lookup@^5.0.3:
|
||||||
|
version "5.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz#049fdc59dffdd4fc285e8f4f82936591bd59fec3"
|
||||||
|
integrity sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w==
|
||||||
|
|
||||||
|
cacheable-request@^7.0.1:
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58"
|
||||||
|
integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==
|
||||||
|
dependencies:
|
||||||
|
clone-response "^1.0.2"
|
||||||
|
get-stream "^5.1.0"
|
||||||
|
http-cache-semantics "^4.0.0"
|
||||||
|
keyv "^4.0.0"
|
||||||
|
lowercase-keys "^2.0.0"
|
||||||
|
normalize-url "^4.1.0"
|
||||||
|
responselike "^2.0.0"
|
||||||
|
|
||||||
cafy@15.2.1:
|
cafy@15.2.1:
|
||||||
version "15.2.1"
|
version "15.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/cafy/-/cafy-15.2.1.tgz#5a55eaeb721c604c7dca652f3d555c392e5f995a"
|
resolved "https://registry.yarnpkg.com/cafy/-/cafy-15.2.1.tgz#5a55eaeb721c604c7dca652f3d555c392e5f995a"
|
||||||
@@ -2415,6 +2474,13 @@ clone-buffer@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
|
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
|
||||||
integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg=
|
integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg=
|
||||||
|
|
||||||
|
clone-response@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
|
||||||
|
integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
|
||||||
|
dependencies:
|
||||||
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
clone-stats@^1.0.0:
|
clone-stats@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680"
|
resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680"
|
||||||
@@ -3115,6 +3181,11 @@ default-resolution@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684"
|
resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684"
|
||||||
integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=
|
integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=
|
||||||
|
|
||||||
|
defer-to-connect@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1"
|
||||||
|
integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==
|
||||||
|
|
||||||
define-properties@^1.1.2, define-properties@^1.1.3:
|
define-properties@^1.1.2, define-properties@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||||
@@ -4267,6 +4338,13 @@ get-stream@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pump "^3.0.0"
|
pump "^3.0.0"
|
||||||
|
|
||||||
|
get-stream@^5.1.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
|
||||||
|
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
|
||||||
|
dependencies:
|
||||||
|
pump "^3.0.0"
|
||||||
|
|
||||||
get-value@^2.0.3, get-value@^2.0.6:
|
get-value@^2.0.3, get-value@^2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||||
@@ -4413,6 +4491,23 @@ good-listener@^1.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
delegate "^3.1.2"
|
delegate "^3.1.2"
|
||||||
|
|
||||||
|
got@11.7.0:
|
||||||
|
version "11.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/got/-/got-11.7.0.tgz#a386360305571a74548872e674932b4ef70d3b24"
|
||||||
|
integrity sha512-7en2XwH2MEqOsrK0xaKhbWibBoZqy+f1RSUoIeF1BLcnf+pyQdDsljWMfmOh+QKJwuvDIiKx38GtPh5wFdGGjg==
|
||||||
|
dependencies:
|
||||||
|
"@sindresorhus/is" "^3.1.1"
|
||||||
|
"@szmarczak/http-timer" "^4.0.5"
|
||||||
|
"@types/cacheable-request" "^6.0.1"
|
||||||
|
"@types/responselike" "^1.0.0"
|
||||||
|
cacheable-lookup "^5.0.3"
|
||||||
|
cacheable-request "^7.0.1"
|
||||||
|
decompress-response "^6.0.0"
|
||||||
|
http2-wrapper "^1.0.0-beta.5.2"
|
||||||
|
lowercase-keys "^2.0.0"
|
||||||
|
p-cancelable "^2.0.0"
|
||||||
|
responselike "^2.0.0"
|
||||||
|
|
||||||
graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
|
graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
|
||||||
@@ -4734,6 +4829,11 @@ http-assert@^1.3.0:
|
|||||||
deep-equal "~1.0.1"
|
deep-equal "~1.0.1"
|
||||||
http-errors "~1.7.2"
|
http-errors "~1.7.2"
|
||||||
|
|
||||||
|
http-cache-semantics@^4.0.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||||
|
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||||
|
|
||||||
http-errors@1.7.3, http-errors@^1.6.3, http-errors@^1.7.3, http-errors@~1.7.2:
|
http-errors@1.7.3, http-errors@^1.6.3, http-errors@^1.7.3, http-errors@~1.7.2:
|
||||||
version "1.7.3"
|
version "1.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
|
||||||
@@ -4789,6 +4889,14 @@ http-signature@~1.2.0:
|
|||||||
jsprim "^1.2.2"
|
jsprim "^1.2.2"
|
||||||
sshpk "^1.7.0"
|
sshpk "^1.7.0"
|
||||||
|
|
||||||
|
http2-wrapper@^1.0.0-beta.5.2:
|
||||||
|
version "1.0.0-beta.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz#8b923deb90144aea65cf834b016a340fc98556f3"
|
||||||
|
integrity sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ==
|
||||||
|
dependencies:
|
||||||
|
quick-lru "^5.1.1"
|
||||||
|
resolve-alpn "^1.0.0"
|
||||||
|
|
||||||
http_ece@1.1.0:
|
http_ece@1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/http_ece/-/http_ece-1.1.0.tgz#74780c6eb32d8ddfe9e36a83abcd81fe0cd4fb75"
|
resolved "https://registry.yarnpkg.com/http_ece/-/http_ece-1.1.0.tgz#74780c6eb32d8ddfe9e36a83abcd81fe0cd4fb75"
|
||||||
@@ -5478,6 +5586,11 @@ jsdom@16.4.0:
|
|||||||
ws "^7.2.3"
|
ws "^7.2.3"
|
||||||
xml-name-validator "^3.0.0"
|
xml-name-validator "^3.0.0"
|
||||||
|
|
||||||
|
json-buffer@3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||||
|
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||||
|
|
||||||
json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
|
json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||||
@@ -5608,6 +5721,13 @@ keygrip@~1.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tsscmp "1.0.6"
|
tsscmp "1.0.6"
|
||||||
|
|
||||||
|
keyv@^4.0.0:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.3.tgz#4f3aa98de254803cafcd2896734108daa35e4254"
|
||||||
|
integrity sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==
|
||||||
|
dependencies:
|
||||||
|
json-buffer "3.0.1"
|
||||||
|
|
||||||
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||||
@@ -6086,6 +6206,11 @@ lower-case@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
|
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
|
||||||
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
|
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
|
||||||
|
|
||||||
|
lowercase-keys@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
|
||||||
|
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
|
||||||
|
|
||||||
lru-cache@^4.1.5:
|
lru-cache@^4.1.5:
|
||||||
version "4.1.5"
|
version "4.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
||||||
@@ -6314,6 +6439,11 @@ mimic-fn@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||||
|
|
||||||
|
mimic-response@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||||
|
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
|
||||||
|
|
||||||
mimic-response@^2.0.0:
|
mimic-response@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
|
||||||
@@ -6656,6 +6786,11 @@ normalize-url@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
|
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
|
||||||
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
|
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
|
||||||
|
|
||||||
|
normalize-url@^4.1.0:
|
||||||
|
version "4.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
|
||||||
|
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
|
||||||
|
|
||||||
now-and-later@^2.0.0:
|
now-and-later@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c"
|
resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c"
|
||||||
@@ -6913,7 +7048,7 @@ osenv@^0.1.4:
|
|||||||
os-homedir "^1.0.0"
|
os-homedir "^1.0.0"
|
||||||
os-tmpdir "^1.0.0"
|
os-tmpdir "^1.0.0"
|
||||||
|
|
||||||
p-cancelable@2.0.0:
|
p-cancelable@2.0.0, p-cancelable@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e"
|
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e"
|
||||||
integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==
|
integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==
|
||||||
@@ -8048,6 +8183,11 @@ querystring@0.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||||
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
|
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
|
||||||
|
|
||||||
|
quick-lru@^5.1.1:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
|
||||||
|
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
||||||
|
|
||||||
random-seed@0.3.0:
|
random-seed@0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/random-seed/-/random-seed-0.3.0.tgz#d945f2e1f38f49e8d58913431b8bf6bb937556cd"
|
resolved "https://registry.yarnpkg.com/random-seed/-/random-seed-0.3.0.tgz#d945f2e1f38f49e8d58913431b8bf6bb937556cd"
|
||||||
@@ -8434,6 +8574,11 @@ require-main-filename@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||||
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||||
|
|
||||||
|
resolve-alpn@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c"
|
||||||
|
integrity sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA==
|
||||||
|
|
||||||
resolve-cwd@^2.0.0:
|
resolve-cwd@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
||||||
@@ -8486,6 +8631,13 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0,
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-parse "^1.0.6"
|
path-parse "^1.0.6"
|
||||||
|
|
||||||
|
responselike@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723"
|
||||||
|
integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==
|
||||||
|
dependencies:
|
||||||
|
lowercase-keys "^2.0.0"
|
||||||
|
|
||||||
ret@~0.1.10:
|
ret@~0.1.10:
|
||||||
version "0.1.15"
|
version "0.1.15"
|
||||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||||
|
|||||||
Reference in New Issue
Block a user