Merge remote-tracking branch 'misskey-dev/develop' into develop

This commit is contained in:
2022-07-13 22:14:40 +09:00
91 changed files with 1207 additions and 879 deletions

View File

@ -15,7 +15,7 @@
"@rollup/plugin-alias": "3.1.9",
"@rollup/plugin-json": "4.1.0",
"@syuilo/aiscript": "0.11.1",
"@vitejs/plugin-vue": "3.0.0-beta.1",
"@vitejs/plugin-vue": "3.0.0",
"@vue/compiler-sfc": "3.2.37",
"abort-controller": "3.0.0",
"autobind-decorator": "2.4.0",
@ -40,7 +40,7 @@
"json5": "2.2.1",
"katex": "0.15.6",
"matter-js": "0.18.0",
"mfm-js": "0.22.1",
"mfm-js": "0.23.0-canary.1",
"misskey-js": "0.0.14",
"mocha": "10.0.0",
"ms": "2.1.3",
@ -56,7 +56,7 @@
"random-seed": "0.3.0",
"reflect-metadata": "0.1.13",
"rndstr": "1.0.0",
"rollup": "2.75.7",
"rollup": "2.76.0",
"s-age": "1.1.2",
"sass": "1.53.0",
"seedrandom": "3.0.5",
@ -74,7 +74,7 @@
"uuid": "8.3.2",
"v-debounce": "0.1.2",
"vanilla-tilt": "1.7.2",
"vite": "3.0.0-beta.7",
"vite": "3.0.0",
"vue": "3.2.37",
"vue-prism-editor": "2.0.0-alpha.2",
"vuedraggable": "4.0.1",
@ -100,13 +100,13 @@
"@types/uuid": "8.3.4",
"@types/websocket": "1.0.5",
"@types/ws": "8.5.3",
"@typescript-eslint/eslint-plugin": "5.30.0",
"@typescript-eslint/parser": "5.30.0",
"@typescript-eslint/eslint-plugin": "5.30.6",
"@typescript-eslint/parser": "5.30.6",
"cross-env": "7.0.3",
"cypress": "10.3.0",
"eslint": "8.18.0",
"eslint": "8.19.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-vue": "9.1.1",
"eslint-plugin-vue": "9.2.0",
"start-server-and-test": "1.14.0"
}
}

View File

@ -316,7 +316,7 @@ const render = () => {
plugins: [{
id: 'vLine',
beforeDraw(chart, args, options) {
if (chart.tooltip._active && chart.tooltip._active.length) {
if (chart.tooltip?._active?.length) {
const activePoint = chart.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.element.x;

View File

@ -59,7 +59,7 @@ const isThumbnailAvailable = computed(() => {
display: flex;
background: var(--panel);
border-radius: 8px;
overflow: hidden; overflow: clip;
overflow: clip;
> .icon-sub {
position: absolute;

View File

@ -13,7 +13,7 @@
</template>
<script lang="ts" setup>
import { } from 'vue';
import { } from 'vue';
import * as Misskey from 'misskey-js';
import XDrive from './drive.vue';
import XWindow from '@/components/ui/window.vue';

View File

@ -41,7 +41,7 @@ import { useInterval } from '@/scripts/use-interval';
const props = defineProps<{
modelValue: string | number;
type?: 'text' | 'number' | 'password' | 'email' | 'url' | 'date' | 'time';
type?: 'text' | 'number' | 'password' | 'email' | 'url' | 'date' | 'time' | 'search';
required?: boolean;
readonly?: boolean;
disabled?: boolean;

View File

@ -189,7 +189,7 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => {
height: 3px;
background: rgba(0, 0, 0, 0.1);
border-radius: 999px;
overflow: hidden; overflow: clip;
overflow: clip;
> .highlight {
position: absolute;

View File

@ -1,5 +1,6 @@
<template>
<component :is="self ? 'MkA' : 'a'" ref="el" class="ieqqeuvs _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
<component
:is="self ? 'MkA' : 'a'" ref="el" class="ieqqeuvs _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
@contextmenu.stop="() => {}"
>
<template v-if="!self">
@ -23,14 +24,7 @@ import { toUnicode as decodePunycode } from 'punycode/';
import { url as local } from '@/config';
import * as os from '@/os';
import { useTooltip } from '@/scripts/use-tooltip';
function safeURIDecode(str: string) {
try {
return decodeURIComponent(str);
} catch {
return str;
}
}
import { safeURIDecode } from '@/scripts/safe-uri-decode';
export default defineComponent({
props: {
@ -42,7 +36,7 @@ export default defineComponent({
type: String,
required: false,
default: null,
}
},
},
setup(props) {
const self = props.url.startsWith(local);

View File

@ -76,7 +76,7 @@ export default {
<style lang="scss" module>
.wrap {
overflow: hidden; overflow: clip;
overflow: clip;
animation-play-state: running;
&:hover {

View File

@ -1,15 +1,15 @@
<template>
<MkA v-if="url.startsWith('/')" v-user-preview="canonical" :class="[$style.root, { isMe }]" :to="url" :style="{ background: bgCss }">
<img :class="$style.icon" :src="`/avatar/@${username}@${host}`" alt="">
<MkA v-if="url.startsWith('/')" v-user-preview="canonical" class="akbvjaqn" :class="{ isMe }" :to="url" :style="{ background: bgCss }">
<img class="icon" :src="`/avatar/@${username}@${host}`" alt="">
<span class="main">
<span class="username">@{{ username }}</span>
<span v-if="(host != localHost) || $store.state.showFullAcct" :class="$style.mainHost">@{{ toUnicode(host) }}</span>
<span v-if="(host != localHost) || $store.state.showFullAcct" class="host">@{{ toUnicode(host) }}</span>
</span>
</MkA>
<a v-else :class="$style.root" :href="url" target="_blank" rel="noopener" :style="{ background: bgCss }">
<a v-else class="akbvjaqn" :href="url" target="_blank" rel="noopener" :style="{ background: bgCss }">
<span class="main">
<span class="username">@{{ username }}</span>
<span :class="$style.mainHost">@{{ toUnicode(host) }}</span>
<span class="host">@{{ toUnicode(host) }}</span>
</span>
</a>
</template>
@ -41,8 +41,8 @@ const bgCss = bg.toRgbString();
useCssModule();
</script>
<style lang="scss" module>
.root {
<style lang="scss" scoped>
.akbvjaqn {
display: inline-block;
padding: 4px 8px 4px 4px;
border-radius: 999px;
@ -51,18 +51,18 @@ useCssModule();
&.isMe {
color: var(--mentionMe);
}
}
.icon {
width: 1.5em;
height: 1.5em;
object-fit: cover;
margin: 0 0.2em 0 0;
vertical-align: bottom;
border-radius: 100%;
}
> .icon {
width: 1.5em;
height: 1.5em;
object-fit: cover;
margin: 0 0.2em 0 0;
vertical-align: bottom;
border-radius: 100%;
}
.mainHost {
opacity: 0.5;
> .main > .host {
opacity: 0.5;
}
}
</style>

View File

@ -47,7 +47,7 @@ export default defineComponent({
render() {
if (this.text == null || this.text === '') return;
const ast = (this.plain ? mfm.parsePlain : mfm.parse)(this.text, { fnNameList: MFM_TAGS });
const ast = (this.plain ? mfm.parseSimple : mfm.parse)(this.text, { fnNameList: MFM_TAGS });
const validTime = (t: string | null | undefined) => {
if (t == null) return null;
@ -312,6 +312,10 @@ export default defineComponent({
})];
}
case 'plain': {
return [h('span', genEl(token.children))];
}
default: {
console.error('unrecognized ast type:', token.type);

View File

@ -27,7 +27,7 @@ const props = defineProps<{
display: flex;
margin: 0;
padding: 0;
overflow: hidden; overflow: clip;
overflow: clip;
font-size: 0.95em;
&.min-width_350px {

View File

@ -36,7 +36,7 @@ const showContent = $ref(false);
display: flex;
margin: 0;
padding: 0;
overflow: hidden; overflow: clip;
overflow: clip;
font-size: 0.95em;
&.min-width_350px {

View File

@ -293,7 +293,7 @@ function readPromo() {
position: relative;
transition: box-shadow 0.1s ease;
font-size: 1.05em;
overflow: hidden; overflow: clip;
overflow: clip;
contain: content;
// これらの指定はパフォーマンス向上には有効だが、ノートの高さは一定でないため、

View File

@ -71,7 +71,7 @@ defineExpose({
<style lang="scss" scoped>
.meijqfqm {
position: relative;
overflow: hidden; overflow: clip;
overflow: clip;
display: grid;
place-items: center;

View File

@ -54,7 +54,7 @@ onMounted(() => {
width: min-content;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
border-radius: 8px;
overflow: hidden; overflow: clip;
overflow: clip;
text-align: center;
pointer-events: none;

View File

@ -156,7 +156,7 @@ export default defineComponent({
text-decoration: none;
background: var(--buttonBg);
border-radius: 5px;
overflow: hidden; overflow: clip;
overflow: clip;
box-sizing: border-box;
transition: background 0.1s ease;

View File

@ -143,7 +143,7 @@ export default defineComponent({
.ukygtjoj {
position: relative;
overflow: hidden; overflow: clip;
overflow: clip;
contain: content;
&.naked {

View File

@ -10,7 +10,7 @@
</template>
<script lang="ts" setup>
import { nextTick, onMounted, computed, ref, watch, provide } from 'vue';
import { nextTick, onMounted, watch, provide } from 'vue';
import * as os from '@/os';
import { isTouchUsing } from '@/scripts/touch';
import { defaultStore } from '@/store';
@ -57,13 +57,13 @@ const emit = defineEmits<{
provide('modal', true);
const maxHeight = ref<number>();
const fixed = ref(false);
const transformOrigin = ref('center');
const showing = ref(true);
const content = ref<HTMLElement>();
let maxHeight = $ref<number>();
let fixed = $ref(false);
let transformOrigin = $ref('center');
let showing = $ref(true);
let content = $ref<HTMLElement>();
const zIndex = os.claimZIndex(props.zPriority);
const type = computed(() => {
const type = $computed(() => {
if (props.preferType === 'auto') {
if (!defaultStore.state.disableDrawer && isTouchUsing && deviceKind === 'smartphone') {
return 'drawer';
@ -80,7 +80,7 @@ let contentClicking = false;
const close = () => {
// eslint-disable-next-line vue/no-mutating-props
if (props.src) props.src.style.pointerEvents = 'auto';
showing.value = false;
showing = false;
emit('close');
};
@ -89,8 +89,8 @@ const onBgClick = () => {
emit('click');
};
if (type.value === 'drawer') {
maxHeight.value = window.innerHeight / 1.5;
if (type === 'drawer') {
maxHeight = window.innerHeight / 1.5;
}
const keymap = {
@ -101,22 +101,21 @@ const MARGIN = 16;
const align = () => {
if (props.src == null) return;
if (type.value === 'drawer') return;
if (type.value === 'dialog') return;
if (type === 'drawer') return;
if (type === 'dialog') return;
const popover = content.value!;
if (popover == null) return;
if (content == null) return;
const srcRect = props.src.getBoundingClientRect();
const width = popover.offsetWidth;
const height = popover.offsetHeight;
const width = content!.offsetWidth;
const height = content!.offsetHeight;
let left;
let top;
const x = srcRect.left + (fixed.value ? 0 : window.pageXOffset);
const y = srcRect.top + (fixed.value ? 0 : window.pageYOffset);
const x = srcRect.left + (fixed ? 0 : window.pageXOffset);
const y = srcRect.top + (fixed ? 0 : window.pageYOffset);
if (props.anchor.x === 'center') {
left = x + (props.src.offsetWidth / 2) - (width / 2);
@ -134,7 +133,7 @@ const align = () => {
top = y + props.src.offsetHeight;
}
if (fixed.value) {
if (fixed) {
// 画面から横にはみ出る場合
if (left + width > window.innerWidth) {
left = window.innerWidth - width;
@ -147,16 +146,16 @@ const align = () => {
if (top + height > (window.innerHeight - MARGIN)) {
if (props.noOverlap && props.anchor.x === 'center') {
if (underSpace >= (upperSpace / 3)) {
maxHeight.value = underSpace;
maxHeight = underSpace;
} else {
maxHeight.value = upperSpace;
maxHeight = upperSpace;
top = (upperSpace + MARGIN) - height;
}
} else {
top = (window.innerHeight - MARGIN) - height;
}
} else {
maxHeight.value = underSpace;
maxHeight = underSpace;
}
} else {
// 画面から横にはみ出る場合
@ -171,16 +170,16 @@ const align = () => {
if (top + height - window.pageYOffset > (window.innerHeight - MARGIN)) {
if (props.noOverlap && props.anchor.x === 'center') {
if (underSpace >= (upperSpace / 3)) {
maxHeight.value = underSpace;
maxHeight = underSpace;
} else {
maxHeight.value = upperSpace;
maxHeight = upperSpace;
top = window.pageYOffset + ((upperSpace + MARGIN) - height);
}
} else {
top = (window.innerHeight - MARGIN) - height + window.pageYOffset - 1;
}
} else {
maxHeight.value = underSpace;
maxHeight = underSpace;
}
}
@ -195,29 +194,29 @@ const align = () => {
let transformOriginX = 'center';
let transformOriginY = 'center';
if (top >= srcRect.top + props.src.offsetHeight + (fixed.value ? 0 : window.pageYOffset)) {
if (top >= srcRect.top + props.src.offsetHeight + (fixed ? 0 : window.pageYOffset)) {
transformOriginY = 'top';
} else if ((top + height) <= srcRect.top + (fixed.value ? 0 : window.pageYOffset)) {
} else if ((top + height) <= srcRect.top + (fixed ? 0 : window.pageYOffset)) {
transformOriginY = 'bottom';
}
if (left >= srcRect.left + props.src.offsetWidth + (fixed.value ? 0 : window.pageXOffset)) {
if (left >= srcRect.left + props.src.offsetWidth + (fixed ? 0 : window.pageXOffset)) {
transformOriginX = 'left';
} else if ((left + width) <= srcRect.left + (fixed.value ? 0 : window.pageXOffset)) {
} else if ((left + width) <= srcRect.left + (fixed ? 0 : window.pageXOffset)) {
transformOriginX = 'right';
}
transformOrigin.value = `${transformOriginX} ${transformOriginY}`;
transformOrigin = `${transformOriginX} ${transformOriginY}`;
popover.style.left = left + 'px';
popover.style.top = top + 'px';
content.style.left = left + 'px';
content.style.top = top + 'px';
};
const onOpened = () => {
emit('opened');
// モーダルコンテンツにマウスボタンが押され、コンテンツ外でマウスボタンが離されたときにモーダルバックグラウンドクリックと判定させないためにマウスイベントを監視しフラグ管理する
const el = content.value!.children[0];
const el = content!.children[0];
el.addEventListener('mousedown', ev => {
contentClicking = true;
window.addEventListener('mouseup', ev => {
@ -235,7 +234,7 @@ onMounted(() => {
// eslint-disable-next-line vue/no-mutating-props
props.src.style.pointerEvents = 'none';
}
fixed.value = (type.value === 'drawer') || (getFixedContainer(props.src) != null);
fixed = (type === 'drawer') || (getFixedContainer(props.src) != null);
await nextTick();
@ -243,10 +242,9 @@ onMounted(() => {
}, { immediate: true });
nextTick(() => {
const popover = content.value;
new ResizeObserver((entries, observer) => {
align();
}).observe(popover!);
}).observe(content!);
});
});
@ -391,7 +389,7 @@ defineExpose({
left: 0;
width: 100%;
height: 100%;
overflow: hidden; overflow: clip;
overflow: clip;
> .content {
position: fixed;

View File

@ -30,7 +30,7 @@ export default defineComponent({
props: {
def: {
type: Array,
required: true
required: true,
},
grid: {
type: Boolean,
@ -64,7 +64,7 @@ export default defineComponent({
box-sizing: border-box;
padding: 10px 16px 10px 8px;
border-radius: 9px;
font-size: 0.95em;
font-size: 0.9em;
&:hover {
text-decoration: none;

View File

@ -105,7 +105,7 @@ function choose(visibility: typeof misskey.noteVisibilities[number]): void {
}
&.active {
color: #fff;
color: var(--fgOnAccent);
background: var(--accent);
}

View File

@ -4,7 +4,7 @@
<header>
<MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--margin)" class="mk-widget-select">
<template #label>{{ $ts.selectWidget }}</template>
<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ $t(`_widgets.${widget}`) }}</option>
<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ i18n.t(`_widgets.${widget}`) }}</option>
</MkSelect>
<MkButton inline primary class="mk-widget-add" @click="addWidget"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton>
<MkButton inline @click="$emit('exit')">{{ $ts.close }}</MkButton>
@ -26,79 +26,91 @@
</template>
</XDraggable>
</template>
<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)"/>
<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" :ref="el => widgetRefs[widget.id] = el" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/>
</div>
</template>
<script lang="ts">
import { defineComponent, defineAsyncComponent, reactive, ref, computed } from 'vue';
<script lang="ts" setup>
import { defineAsyncComponent, reactive, ref, computed } from 'vue';
import { v4 as uuid } from 'uuid';
import MkSelect from '@/components/form/select.vue';
import MkButton from '@/components/ui/button.vue';
import { widgets as widgetDefs } from '@/widgets';
import * as os from '@/os';
import { i18n } from '@/i18n';
export default defineComponent({
components: {
XDraggable: defineAsyncComponent(() => import('vuedraggable')),
MkSelect,
MkButton,
},
const XDraggable = defineAsyncComponent(() => import('vuedraggable'));
props: {
widgets: {
type: Array,
required: true,
},
edit: {
type: Boolean,
required: true,
},
},
type Widget = {
name: string;
id: string;
data: Record<string, any>;
};
emits: ['updateWidgets', 'addWidget', 'removeWidget', 'updateWidget', 'exit'],
const props = defineProps<{
widgets: Widget[];
edit: boolean;
}>();
setup(props, context) {
const widgetRefs = reactive({});
const configWidget = (id: string) => {
widgetRefs[id].configure();
};
const widgetAdderSelected = ref(null);
const addWidget = () => {
if (widgetAdderSelected.value == null) return;
const emit = defineEmits<{
(ev: 'updateWidgets', widgets: Widget[]): void;
(ev: 'addWidget', widget: Widget): void;
(ev: 'removeWidget', widget: Widget): void;
(ev: 'updateWidget', widget: Partial<Widget>): void;
(ev: 'exit'): void;
}>();
context.emit('addWidget', {
name: widgetAdderSelected.value,
id: uuid(),
data: {},
});
const widgetRefs = {};
const configWidget = (id: string) => {
widgetRefs[id].configure();
};
const widgetAdderSelected = ref(null);
const addWidget = () => {
if (widgetAdderSelected.value == null) return;
widgetAdderSelected.value = null;
};
const removeWidget = (widget) => {
context.emit('removeWidget', widget);
};
const updateWidget = (id, data) => {
context.emit('updateWidget', { id, data });
};
const widgets_ = computed({
get: () => props.widgets,
set: (value) => {
context.emit('updateWidgets', value);
},
});
emit('addWidget', {
name: widgetAdderSelected.value,
id: uuid(),
data: {},
});
return {
widgetRefs,
configWidget,
widgetAdderSelected,
widgetDefs,
addWidget,
removeWidget,
updateWidget,
widgets_,
};
widgetAdderSelected.value = null;
};
const removeWidget = (widget) => {
emit('removeWidget', widget);
};
const updateWidget = (id, data) => {
emit('updateWidget', { id, data });
};
const widgets_ = computed({
get: () => props.widgets,
set: (value) => {
emit('updateWidgets', value);
},
});
function onContextmenu(widget: Widget, ev: MouseEvent) {
const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
};
if (isLink(ev.target)) return;
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return;
if (window.getSelection()?.toString() !== '') return;
os.contextMenu([{
type: 'label',
text: i18n.t(`_widgets.${widget.name}`),
}, {
icon: 'fas fa-cog',
text: i18n.ts.settings,
action: () => {
configWidget(widget.id);
},
}], ev);
}
</script>
<style lang="scss" scoped>

View File

@ -27,8 +27,8 @@ function getClassOrder(width: number, queue: Value): ClassOrder {
...(queue.min ? queue.min.filter(v => width >= v).map(getMinClass) : []),
],
remove: [
...(queue.max ? queue.max.filter(v => width > v).map(getMaxClass) : []),
...(queue.min ? queue.min.filter(v => width < v).map(getMinClass) : []),
...(queue.max ? queue.max.filter(v => width > v).map(getMaxClass) : []),
...(queue.min ? queue.min.filter(v => width < v).map(getMinClass) : []),
]
};
}

View File

@ -39,304 +39,305 @@ import { reactionPicker } from '@/scripts/reaction-picker';
import { getUrlWithoutLoginId } from '@/scripts/login-id';
import { getAccountFromId } from '@/scripts/get-account-from-id';
console.info(`Misskey v${version}`);
(async () => {
console.info(`Misskey v${version}`);
if (_DEV_) {
console.warn('Development mode!!!');
if (_DEV_) {
console.warn('Development mode!!!');
console.info(`vue ${vueVersion}`);
console.info(`vue ${vueVersion}`);
(window as any).$i = $i;
(window as any).$store = defaultStore;
(window as any).$i = $i;
(window as any).$store = defaultStore;
window.addEventListener('error', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled error',
text: event.message
window.addEventListener('error', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled error',
text: event.message
});
*/
});
*/
window.addEventListener('unhandledrejection', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled promise rejection',
text: event.reason
});
*/
});
}
// タッチデバイスでCSSの:hoverを機能させる
document.addEventListener('touchend', () => {}, { passive: true });
// 一斉リロード
reloadChannel.addEventListener('message', path => {
if (path !== null) location.href = path;
else location.reload();
});
window.addEventListener('unhandledrejection', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled promise rejection',
text: event.reason
});
*/
});
}
// タッチデバイスでCSSの:hoverを機能させる
document.addEventListener('touchend', () => {}, { passive: true });
// 一斉リロード
reloadChannel.addEventListener('message', path => {
if (path !== null) location.href = path;
else location.reload();
});
//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
// TODO: いつの日にか消したい
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
window.addEventListener('resize', () => {
//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
// TODO: いつの日にか消したい
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
//#endregion
window.addEventListener('resize', () => {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
//#endregion
// If mobile, insert the viewport meta tag
if (['smartphone', 'tablet'].includes(deviceKind)) {
const viewport = document.getElementsByName('viewport').item(0);
viewport.setAttribute('content',
`${viewport.getAttribute('content')}, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover`);
}
//#region Set lang attr
const html = document.documentElement;
html.setAttribute('lang', lang);
//#endregion
//#region loginId
const params = new URLSearchParams(location.search);
const loginId = params.get('loginId');
if (loginId) {
const target = getUrlWithoutLoginId(location.href);
if (!$i || $i.id !== loginId) {
const account = await getAccountFromId(loginId);
if (account) {
await login(account.token, target);
}
// If mobile, insert the viewport meta tag
if (['smartphone', 'tablet'].includes(deviceKind)) {
const viewport = document.getElementsByName('viewport').item(0);
viewport.setAttribute('content',
`${viewport.getAttribute('content')}, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover`);
}
history.replaceState({ misskey: 'loginId' }, '', target);
}
//#region Set lang attr
const html = document.documentElement;
html.setAttribute('lang', lang);
//#endregion
//#endregion
//#region loginId
const params = new URLSearchParams(location.search);
const loginId = params.get('loginId');
//#region Fetch user
if ($i && $i.token) {
if (_DEV_) {
console.log('account cache found. refreshing...');
}
if (loginId) {
const target = getUrlWithoutLoginId(location.href);
refreshAccount();
} else {
if (_DEV_) {
console.log('no account cache found.');
}
// 連携ログインの場合用にCookieを参照する
const i = (document.cookie.match(/igi=(\w+)/) || [null, null])[1];
if (i != null && i !== 'null') {
if (_DEV_) {
console.log('signing...');
}
try {
document.body.innerHTML = '<div>Please wait...</div>';
await login(i);
} catch (err) {
// Render the error screen
// TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな)
document.body.innerHTML = '<div id="err">Oops!</div>';
}
} else {
if (_DEV_) {
console.log('not signed in');
}
}
}
//#endregion
const fetchInstanceMetaPromise = fetchInstance();
fetchInstanceMetaPromise.then(() => {
localStorage.setItem('v', instance.version);
// Init service worker
initializeSw();
});
const app = createApp(
window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
!$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) :
ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) :
ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) :
defineAsyncComponent(() => import('@/ui/universal.vue')),
);
if (_DEV_) {
app.config.performance = true;
}
app.config.globalProperties = {
$i,
$store: defaultStore,
$instance: instance,
$t: i18n.t,
$ts: i18n.ts,
};
widgets(app);
directives(app);
components(app);
const splash = document.getElementById('splash');
// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す))
if (splash) splash.addEventListener('transitionend', () => {
splash.remove();
});
// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210
// なぜかinit.tsの内容が2回実行されることがあるため、mountするdivを1つに制限する
const rootEl = (() => {
const MISSKEY_MOUNT_DIV_ID = 'misskey_app';
const currentEl = document.getElementById(MISSKEY_MOUNT_DIV_ID);
if (currentEl) {
console.warn('multiple import detected');
return currentEl;
}
const rootEl = document.createElement('div');
rootEl.id = MISSKEY_MOUNT_DIV_ID;
document.body.appendChild(rootEl);
return rootEl;
})();
app.mount(rootEl);
// boot.jsのやつを解除
window.onerror = null;
window.onunhandledrejection = null;
reactionPicker.init();
if (splash) {
splash.style.opacity = '0';
splash.style.pointerEvents = 'none';
}
// クライアントが更新されたか?
const lastVersion = localStorage.getItem('lastVersion');
if (lastVersion !== version) {
localStorage.setItem('lastVersion', version);
// テーマリビルドするため
localStorage.removeItem('theme');
try { // 変なバージョン文字列来るとcompareVersionsでエラーになるため
if (lastVersion != null && compareVersions(version, lastVersion) === 1) {
// ログインしてる場合だけ
if ($i) {
popup(defineAsyncComponent(() => import('@/components/updated.vue')), {}, {}, 'closed');
if (!$i || $i.id !== loginId) {
const account = await getAccountFromId(loginId);
if (account) {
await login(account.token, target);
}
}
} catch (err) {
history.replaceState({ misskey: 'loginId' }, '', target);
}
}
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
watch(defaultStore.reactiveState.darkMode, (darkMode) => {
applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
}, { immediate: localStorage.theme == null });
//#endregion
const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme'));
const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme'));
//#region Fetch user
if ($i && $i.token) {
if (_DEV_) {
console.log('account cache found. refreshing...');
}
watch(darkTheme, (theme) => {
if (defaultStore.state.darkMode) {
applyTheme(theme);
}
});
watch(lightTheme, (theme) => {
if (!defaultStore.state.darkMode) {
applyTheme(theme);
}
});
//#region Sync dark mode
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', isDeviceDarkmode());
}
window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', mql.matches);
}
});
//#endregion
fetchInstanceMetaPromise.then(() => {
if (defaultStore.state.themeInitial) {
if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme));
if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme));
defaultStore.set('themeInitial', false);
}
});
watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none');
}, { immediate: true });
watch(defaultStore.reactiveState.useBlurEffect, v => {
if (v) {
document.documentElement.style.removeProperty('--blur');
refreshAccount();
} else {
document.documentElement.style.setProperty('--blur', 'none');
}
}, { immediate: true });
if (_DEV_) {
console.log('no account cache found.');
}
let reloadDialogShowing = false;
stream.on('_disconnected_', async () => {
if (defaultStore.state.serverDisconnectedBehavior === 'reload') {
location.reload();
} else if (defaultStore.state.serverDisconnectedBehavior === 'dialog') {
if (reloadDialogShowing) return;
reloadDialogShowing = true;
const { canceled } = await confirm({
type: 'warning',
title: i18n.ts.disconnectedFromServer,
text: i18n.ts.reloadConfirm,
});
reloadDialogShowing = false;
if (!canceled) {
location.reload();
// 連携ログインの場合用にCookieを参照する
const i = (document.cookie.match(/igi=(\w+)/) || [null, null])[1];
if (i != null && i !== 'null') {
if (_DEV_) {
console.log('signing...');
}
try {
document.body.innerHTML = '<div>Please wait...</div>';
await login(i);
} catch (err) {
// Render the error screen
// TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな)
document.body.innerHTML = '<div id="err">Oops!</div>';
}
} else {
if (_DEV_) {
console.log('not signed in');
}
}
}
});
//#endregion
stream.on('emojiAdded', emojiData => {
// TODO
//store.commit('instance/set', );
});
const fetchInstanceMetaPromise = fetchInstance();
for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) {
import('./plugin').then(({ install }) => {
install(plugin);
fetchInstanceMetaPromise.then(() => {
localStorage.setItem('v', instance.version);
// Init service worker
initializeSw();
});
}
const hotkeys = {
'd': (): void => {
defaultStore.set('darkMode', !defaultStore.state.darkMode);
},
's': search,
};
const app = createApp(
window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
!$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) :
ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) :
ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) :
defineAsyncComponent(() => import('@/ui/universal.vue')),
);
if (!$i) {
if (_DEV_) {
app.config.performance = true;
}
app.config.globalProperties = {
$i,
$store: defaultStore,
$instance: instance,
$t: i18n.t,
$ts: i18n.ts,
};
widgets(app);
directives(app);
components(app);
const splash = document.getElementById('splash');
// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す))
if (splash) splash.addEventListener('transitionend', () => {
splash.remove();
});
// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210
// なぜかinit.tsの内容が2回実行されることがあるため、mountするdivを1つに制限する
const rootEl = (() => {
const MISSKEY_MOUNT_DIV_ID = 'misskey_app';
const currentEl = document.getElementById(MISSKEY_MOUNT_DIV_ID);
if (currentEl) {
console.warn('multiple import detected');
return currentEl;
}
const rootEl = document.createElement('div');
rootEl.id = MISSKEY_MOUNT_DIV_ID;
document.body.appendChild(rootEl);
return rootEl;
})();
app.mount(rootEl);
// boot.jsのやつを解除
window.onerror = null;
window.onunhandledrejection = null;
reactionPicker.init();
if (splash) {
splash.style.opacity = '0';
splash.style.pointerEvents = 'none';
}
// クライアントが更新されたか?
const lastVersion = localStorage.getItem('lastVersion');
if (lastVersion !== version) {
localStorage.setItem('lastVersion', version);
// テーマリビルドするため
localStorage.removeItem('theme');
try { // 変なバージョン文字列来るとcompareVersionsでエラーになるため
if (lastVersion != null && compareVersions(version, lastVersion) === 1) {
// ログインしてる場合だけ
if ($i) {
popup(defineAsyncComponent(() => import('@/components/updated.vue')), {}, {}, 'closed');
}
}
} catch (err) {
}
}
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
watch(defaultStore.reactiveState.darkMode, (darkMode) => {
applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
}, { immediate: localStorage.theme == null });
const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme'));
const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme'));
watch(darkTheme, (theme) => {
if (defaultStore.state.darkMode) {
applyTheme(theme);
}
});
watch(lightTheme, (theme) => {
if (!defaultStore.state.darkMode) {
applyTheme(theme);
}
});
//#region Sync dark mode
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', isDeviceDarkmode());
}
window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', mql.matches);
}
});
//#endregion
fetchInstanceMetaPromise.then(() => {
if (defaultStore.state.themeInitial) {
if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme));
if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme));
defaultStore.set('themeInitial', false);
}
});
watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none');
}, { immediate: true });
watch(defaultStore.reactiveState.useBlurEffect, v => {
if (v) {
document.documentElement.style.removeProperty('--blur');
} else {
document.documentElement.style.setProperty('--blur', 'none');
}
}, { immediate: true });
let reloadDialogShowing = false;
stream.on('_disconnected_', async () => {
if (defaultStore.state.serverDisconnectedBehavior === 'reload') {
location.reload();
} else if (defaultStore.state.serverDisconnectedBehavior === 'dialog') {
if (reloadDialogShowing) return;
reloadDialogShowing = true;
const { canceled } = await confirm({
type: 'warning',
title: i18n.ts.disconnectedFromServer,
text: i18n.ts.reloadConfirm,
});
reloadDialogShowing = false;
if (!canceled) {
location.reload();
}
}
});
stream.on('emojiAdded', emojiData => {
// TODO
//store.commit('instance/set', );
});
for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) {
import('./plugin').then(({ install }) => {
install(plugin);
});
}
const hotkeys = {
'd': (): void => {
defaultStore.set('darkMode', !defaultStore.state.darkMode);
},
's': search,
};
if (!$i) {
localStorage.setItem('wallpaper', 'https://simkey.net/files/c2f30819-64f7-42df-91b6-0e7fb122a413');
}
@ -344,100 +345,101 @@ if ($i) {
// only add post shortcuts if logged in
hotkeys['p|n'] = post;
if ($i.isDeleted) {
alert({
type: 'warning',
text: i18n.ts.accountDeletionInProgress,
if ($i.isDeleted) {
alert({
type: 'warning',
text: i18n.ts.accountDeletionInProgress,
});
}
const lastUsed = localStorage.getItem('lastUsed');
if (lastUsed) {
const lastUsedDate = parseInt(lastUsed, 10);
// 二時間以上前なら
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
toast(i18n.t('welcomeBackWithName', {
name: $i.name || $i.username,
}));
}
}
localStorage.setItem('lastUsed', Date.now().toString());
if ('Notification' in window) {
// 許可を得ていなかったらリクエスト
if (Notification.permission === 'default') {
Notification.requestPermission();
}
}
const main = markRaw(stream.useChannel('main', null, 'System'));
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
updateAccount(i);
});
main.on('readAllNotifications', () => {
updateAccount({ hasUnreadNotification: false });
});
main.on('unreadNotification', () => {
updateAccount({ hasUnreadNotification: true });
});
main.on('unreadMention', () => {
updateAccount({ hasUnreadMentions: true });
});
main.on('readAllUnreadMentions', () => {
updateAccount({ hasUnreadMentions: false });
});
main.on('unreadSpecifiedNote', () => {
updateAccount({ hasUnreadSpecifiedNotes: true });
});
main.on('readAllUnreadSpecifiedNotes', () => {
updateAccount({ hasUnreadSpecifiedNotes: false });
});
main.on('readAllMessagingMessages', () => {
updateAccount({ hasUnreadMessagingMessage: false });
});
main.on('unreadMessagingMessage', () => {
updateAccount({ hasUnreadMessagingMessage: true });
sound.play('chatBg');
});
main.on('readAllAntennas', () => {
updateAccount({ hasUnreadAntenna: false });
});
main.on('unreadAntenna', () => {
updateAccount({ hasUnreadAntenna: true });
sound.play('antenna');
});
main.on('readAllAnnouncements', () => {
updateAccount({ hasUnreadAnnouncement: false });
});
main.on('readAllChannels', () => {
updateAccount({ hasUnreadChannel: false });
});
main.on('unreadChannel', () => {
updateAccount({ hasUnreadChannel: true });
sound.play('channel');
});
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {
signout();
});
}
const lastUsed = localStorage.getItem('lastUsed');
if (lastUsed) {
const lastUsedDate = parseInt(lastUsed, 10);
// 二時間以上前なら
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
toast(i18n.t('welcomeBackWithName', {
name: $i.name || $i.username,
}));
}
}
localStorage.setItem('lastUsed', Date.now().toString());
if ('Notification' in window) {
// 許可を得ていなかったらリクエスト
if (Notification.permission === 'default') {
Notification.requestPermission();
}
}
const main = markRaw(stream.useChannel('main', null, 'System'));
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
updateAccount(i);
});
main.on('readAllNotifications', () => {
updateAccount({ hasUnreadNotification: false });
});
main.on('unreadNotification', () => {
updateAccount({ hasUnreadNotification: true });
});
main.on('unreadMention', () => {
updateAccount({ hasUnreadMentions: true });
});
main.on('readAllUnreadMentions', () => {
updateAccount({ hasUnreadMentions: false });
});
main.on('unreadSpecifiedNote', () => {
updateAccount({ hasUnreadSpecifiedNotes: true });
});
main.on('readAllUnreadSpecifiedNotes', () => {
updateAccount({ hasUnreadSpecifiedNotes: false });
});
main.on('readAllMessagingMessages', () => {
updateAccount({ hasUnreadMessagingMessage: false });
});
main.on('unreadMessagingMessage', () => {
updateAccount({ hasUnreadMessagingMessage: true });
sound.play('chatBg');
});
main.on('readAllAntennas', () => {
updateAccount({ hasUnreadAntenna: false });
});
main.on('unreadAntenna', () => {
updateAccount({ hasUnreadAntenna: true });
sound.play('antenna');
});
main.on('readAllAnnouncements', () => {
updateAccount({ hasUnreadAnnouncement: false });
});
main.on('readAllChannels', () => {
updateAccount({ hasUnreadChannel: false });
});
main.on('unreadChannel', () => {
updateAccount({ hasUnreadChannel: true });
sound.play('channel');
});
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {
signout();
});
}
// shortcut
document.addEventListener('keydown', makeHotkey(hotkeys));
// shortcut
document.addEventListener('keydown', makeHotkey(hotkeys));
})();

View File

@ -3,6 +3,7 @@
import { EventEmitter } from 'eventemitter3';
import { Ref, Component, ref, shallowRef, ShallowRef } from 'vue';
import { pleaseLogin } from '@/scripts/please-login';
import { safeURIDecode } from '@/scripts/safe-uri-decode';
type RouteDef = {
path: string;
@ -116,7 +117,7 @@ export class Router extends EventEmitter<{
}
if (p.wildcard) {
if (parts.length !== 0) {
props.set(p.name, parts.join('/'));
props.set(p.name, safeURIDecode(parts.join('/')));
parts = [];
}
break pathMatchLoop;
@ -124,10 +125,12 @@ export class Router extends EventEmitter<{
if (p.startsWith) {
if (parts[0] == null || !parts[0].startsWith(p.startsWith)) continue forEachRouteLoop;
props.set(p.name, parts[0].substring(p.startsWith.length));
props.set(p.name, safeURIDecode(parts[0].substring(p.startsWith.length)));
parts.shift();
} else {
props.set(p.name, parts[0]);
if (parts[0]) {
props.set(p.name, safeURIDecode(parts[0]));
}
parts.shift();
}
}
@ -137,7 +140,7 @@ export class Router extends EventEmitter<{
if (parts.length !== 0) continue forEachRouteLoop;
if (route.hash != null && hash != null) {
props.set(route.hash, hash);
props.set(route.hash, safeURIDecode(hash));
}
if (route.query != null && queryString != null) {
@ -147,7 +150,7 @@ export class Router extends EventEmitter<{
for (const q in route.query) {
const as = route.query[q];
if (queryObject[q]) {
props.set(as, queryObject[q]);
props.set(as, safeURIDecode(queryObject[q]));
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<div style="overflow: hidden; overflow: clip;">
<div style="overflow: clip;">
<MkSpacer :content-max="600" :margin-min="20">
<div class="_formRoot znqjceqz">
<div id="debug"></div>

View File

@ -138,7 +138,7 @@ definePageMetadata(computed(() => ({
.fwhjspax {
text-align: center;
border-radius: 10px;
overflow: hidden; overflow: clip;
overflow: clip;
background-size: cover;
background-position: center center;

View File

@ -58,7 +58,7 @@ let view = $ref(null);
let el = $ref(null);
let pageProps = $ref({});
let noMaintainerInformation = isEmpty(instance.maintainerName) || isEmpty(instance.maintainerEmail);
let noBotProtection = !instance.enableHcaptcha && !instance.enableRecaptcha;
let noBotProtection = !instance.disableRegistration && !instance.enableHcaptcha && !instance.enableRecaptcha;
let noEmailServer = !instance.enableEmail;
let thereIsUnresolvedAbuseReport = $ref(false);

View File

@ -355,7 +355,7 @@ async function renderChart() {
plugins: [{
id: 'vLine',
beforeDraw(chart, args, options) {
if (chart.tooltip._active && chart.tooltip._active.length) {
if (chart.tooltip?._active?.length) {
const activePoint = chart.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.element.x;
@ -561,7 +561,7 @@ definePageMetadata({
> .body {
background: var(--panel);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
}
@ -620,7 +620,7 @@ definePageMetadata({
> .body {
background: var(--panel);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
}
}

View File

@ -110,7 +110,7 @@ definePageMetadata(computed(() => antenna ? {
> .tl {
background: var(--bg);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
&.min-width_800px {

View File

@ -1,5 +1,9 @@
<template>
<MkSpacer :content-max="1200">
<MkTab v-model="origin" style="margin-bottom: var(--margin);">
<option value="local">{{ $ts.local }}</option>
<option value="remote">{{ $ts.remote }}</option>
</MkTab>
<div v-if="origin === 'local'">
<template v-if="tag == null">
<MkFolder class="_gap" persist-key="explore-pinned-users">
@ -57,16 +61,17 @@
import { computed, watch } from 'vue';
import XUserList from '@/components/user-list.vue';
import MkFolder from '@/components/ui/folder.vue';
import MkTab from '@/components/tab.vue';
import number from '@/filters/number';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { instance } from '@/instance';
const props = defineProps<{
origin: 'local' | 'remote';
tag?: string;
}>();
let origin = $ref('local');
let tagsEl = $ref<InstanceType<typeof MkFolder>>();
let tagsLocal = $ref([]);
let tagsRemote = $ref([]);

View File

@ -5,11 +5,8 @@
<div v-if="tab === 'featured'">
<XFeatured/>
</div>
<div v-else-if="tab === 'localUsers'">
<XUsers origin="local"/>
</div>
<div v-else-if="tab === 'remoteUsers'">
<XUsers origin="remote"/>
<div v-else-if="tab === 'users'">
<XUsers/>
</div>
<div v-else-if="tab === 'search'">
<MkSpacer :content-max="1200">
@ -75,13 +72,9 @@ const headerTabs = $computed(() => [{
icon: 'fas fa-bolt',
title: i18n.ts.featured,
}, {
key: 'localUsers',
key: 'users',
icon: 'fas fa-users',
title: i18n.ts.users,
}, {
key: 'remoteUsers',
icon: 'fas fa-users',
title: i18n.ts.remote,
}, {
key: 'search',
title: i18n.ts.search,

View File

@ -188,7 +188,7 @@ definePageMetadata({
background-size: cover;
background-position: center;
border-radius: 10px;
overflow: hidden; overflow: clip;
overflow: clip;
> .avatar {
display: inline-block;

View File

@ -181,7 +181,7 @@ definePageMetadata({
> .toggleWrapper {
display: inline-block;
text-align: left;
overflow: hidden; overflow: clip;
overflow: clip;
padding: 0 100px;
input {

View File

@ -177,7 +177,7 @@ definePageMetadata(computed(() => ({
> .tl {
// background: var(--bg);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
}
</style>

View File

@ -103,7 +103,7 @@ definePageMetadata(computed(() => list ? {
> .tl {
background: var(--bg);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
&.min-width_800px {

View File

@ -90,7 +90,7 @@ export default defineComponent({
> .img {
height: 128px;
border-radius: 6px;
overflow: hidden; overflow: clip;
overflow: clip;
}
}

View File

@ -286,7 +286,7 @@ function showMenu(ev) {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
border-radius: 999px;
overflow: hidden; overflow: clip;
overflow: clip;
width: 800px;
padding: 8px 0;

View File

@ -8,4 +8,6 @@ export type UnicodeEmojiDef = {
}
// initial converted from https://github.com/muan/emojilib/commit/242fe68be86ed6536843b83f7e32f376468b38fb
export const emojilist = (await import('../emojilist.json')).default as UnicodeEmojiDef[];
import _emojilist from '../emojilist.json';
export const emojilist = _emojilist as UnicodeEmojiDef[];

View File

@ -16,7 +16,7 @@ export type TextValue = ExprBase & {
value: string;
};
export type MultiLineTextValue = ExprBase & {
export type MultiLineTextValue = ExprBase & {
type: 'multiLineText';
value: string;
};

View File

@ -11,16 +11,15 @@ const fallbackName = (key: string) => `idbfallback::${key}`;
let idbAvailable = typeof window !== 'undefined' ? !!window.indexedDB : true;
if (idbAvailable) {
try {
await iset('idb-test', 'test');
} catch (err) {
iset('idb-test', 'test').catch(err => {
console.error('idb error', err);
console.error('indexedDB is unavailable. It will use localStorage.');
idbAvailable = false;
}
});
} else {
console.error('indexedDB is unavailable. It will use localStorage.');
}
if (!idbAvailable) console.error('indexedDB is unavailable. It will use localStorage.');
export async function get(key: string) {
if (idbAvailable) return iget(key);
return JSON.parse(localStorage.getItem(fallbackName(key)));

View File

@ -0,0 +1,7 @@
export function safeURIDecode(str: string): string {
try {
return decodeURIComponent(str);
} catch {
return str;
}
}

View File

@ -1,6 +1,6 @@
import { ref } from 'vue';
import { globalEvents } from '@/events';
import tinycolor from 'tinycolor2';
import { globalEvents } from '@/events';
export type Theme = {
id: string;
@ -35,11 +35,11 @@ export const getBuiltinThemes = () => Promise.all(
'd-astro',
'd-future',
'd-botanical',
'd-green-lime',
'd-green-orange',
'd-cherry',
'd-ice',
'd-pumpkin',
'd-black',
].map(name => import(`../themes/${name}.json5`).then(({ default: _default }): Theme => _default))
].map(name => import(`../themes/${name}.json5`).then(({ default: _default }): Theme => _default)),
);
export const getBuiltinThemesRef = () => {

View File

@ -252,7 +252,7 @@ hr {
._panel {
// background: var(--panel);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
backdrop-filter: var(--blur, blur(8px));
-webkit-backdrop-filter: var(--blur, blur(8px));
}

View File

@ -1,17 +0,0 @@
{
id: '8c539dc1-0fab-4d47-9194-39c508e9bfe1',
name: 'Mi Black',
author: 'syuilo',
base: 'dark',
props: {
divider: '#2d2d2d',
panel: '#131313',
panelHeaderBg: '@panel',
panelHeaderDivider: '@divider',
shadow: 'rgba(255, 255, 255, 0.05)',
modalBg: 'rgba(255, 255, 255, 0.1)',
},
}

View File

@ -0,0 +1,24 @@
{
id: '02816013-8107-440f-877e-865083ffe194',
name: 'Mi Green+Lime Dark',
author: 'syuilo',
base: 'dark',
props: {
accent: '#b4e900',
bg: '#0C1210',
fg: '#dee7e4',
fgHighlighted: '#fff',
fgOnAccent: '#192320',
divider: '#e7fffb24',
panel: '#192320',
panelHeaderBg: '@panel',
panelHeaderDivider: '@divider',
popup: '#293330',
renote: '@accent',
mentionMe: '#ffaa00',
link: '#24d7ce',
},
}

View File

@ -0,0 +1,24 @@
{
id: 'dc489603-27b5-424a-9b25-1ff6aec9824a',
name: 'Mi Green+Orange Dark',
author: 'syuilo',
base: 'dark',
props: {
accent: '#e97f00',
bg: '#0C1210',
fg: '#dee7e4',
fgHighlighted: '#fff',
fgOnAccent: '#192320',
divider: '#e7fffb24',
panel: '#192320',
panelHeaderBg: '@panel',
panelHeaderDivider: '@divider',
popup: '#293330',
renote: '@accent',
mentionMe: '#b4e900',
link: '#24d7ce',
},
}

View File

@ -1,88 +0,0 @@
{
id: '0b64fef3-02c7-20b5-dd87-b3f77e2b4301',
name: 'Mi Pumpkin Dark',
author: 'syuilo',
base: 'dark',
props: {
X2: ':darken<2<@panel',
X3: 'rgba(255, 255, 255, 0.05)',
X4: 'rgba(255, 255, 255, 0.1)',
X5: 'rgba(255, 255, 255, 0.05)',
X6: 'rgba(255, 255, 255, 0.15)',
X7: 'rgba(255, 255, 255, 0.05)',
X8: ':lighten<5<@accent',
X9: ':darken<5<@accent',
bg: 'rgb(37, 32, 47)',
fg: '#e0d5c0',
X10: ':alpha<0.4<@accent',
X11: 'rgba(0, 0, 0, 0.3)',
X12: 'rgba(255, 255, 255, 0.1)',
X13: 'rgba(255, 255, 255, 0.15)',
X14: ':alpha<0.5<@navBg',
X15: ':alpha<0<@panel',
X16: ':alpha<0.7<@panel',
X17: ':alpha<0.8<@bg',
cwBg: '#687390',
cwFg: '#393f4f',
link: 'rgb(172, 193, 68)',
warn: '#ecb637',
badge: '#31b1ce',
error: '#ec4137',
focus: ':alpha<0.3<@accent',
navBg: '@panel',
navFg: '@fg',
panel: ':lighten<3<@bg',
popup: ':lighten<3<@panel',
accent: 'rgb(242, 133, 36)',
header: ':alpha<0.7<@panel',
infoBg: '#253142',
infoFg: '#fff',
renote: 'rgb(110, 179, 72)',
shadow: 'rgba(0, 0, 0, 0.3)',
divider: 'rgba(255, 255, 255, 0.1)',
hashtag: 'rgb(188, 90, 255)',
mention: 'rgb(72, 179, 139)',
modalBg: 'rgba(0, 0, 0, 0.5)',
success: '#86b300',
buttonBg: 'rgba(255, 255, 255, 0.05)',
switchBg: 'rgba(255, 255, 255, 0.15)',
acrylicBg: ':alpha<0.5<@bg',
cwHoverBg: '#707b97',
indicator: '@accent',
mentionMe: '@accent',
messageBg: '@bg',
navActive: '@accent',
accentedBg: ':alpha<0.15<@accent',
fgOnAccent: '#000',
infoWarnBg: '#42321c',
infoWarnFg: '#ffbd3e',
navHoverFg: ':lighten<17<@fg',
dateLabelFg: '@fg',
inputBorder: 'rgba(255, 255, 255, 0.1)',
panelBorder: '" solid 1px var(--divider)',
accentDarken: ':darken<10<@accent',
acrylicPanel: ':alpha<0.5<@panel',
navIndicator: '@indicator',
accentLighten: ':lighten<10<@accent',
buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':lighten<3<@fg',
fgTransparent: ':alpha<0.5<@fg',
panelHeaderBg: ':lighten<3<@panel',
panelHeaderFg: '@fg',
buttonGradateA: '@accent',
buttonGradateB: ':hue<20<@accent',
htmlThemeColor: '@bg',
panelHighlight: ':lighten<3<@panel',
listItemHoverBg: 'rgba(255, 255, 255, 0.03)',
scrollbarHandle: 'rgba(255, 255, 255, 0.2)',
inputBorderHover: 'rgba(255, 255, 255, 0.2)',
wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
fgTransparentWeak: ':alpha<0.75<@fg',
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
scrollbarHandleHover: 'rgba(255, 255, 255, 0.4)',
},
}

View File

@ -64,7 +64,7 @@ const XUserList = defineAsyncComponent(() => import('./statusbar-user-list.vue')
width: 100%;
line-height: var(--height);
height: var(--height);
overflow: hidden; overflow: clip;
overflow: clip;
contain: strict;
> .name {

View File

@ -241,7 +241,7 @@ onMounted(() => {
border-left: solid 1px var(--divider);
border-right: solid 1px var(--divider);
border-radius: 0;
overflow: hidden; overflow: clip;
overflow: clip;
--margin: 12px;
}

View File

@ -9,7 +9,7 @@
</template>
<script lang="ts" setup>
import { } from 'vue';
import { } from 'vue';
import XColumn from './column.vue';
import XTimeline from '@/components/timeline.vue';
import * as os from '@/os';

View File

@ -39,15 +39,15 @@ let pointsRenote: any = $ref(null);
let pointsTotal: any = $ref(null);
function dragListen(fn) {
window.addEventListener('mousemove', fn);
window.addEventListener('mousemove', fn);
window.addEventListener('mouseleave', dragClear.bind(null, fn));
window.addEventListener('mouseup', dragClear.bind(null, fn));
window.addEventListener('mouseup', dragClear.bind(null, fn));
}
function dragClear(fn) {
window.removeEventListener('mousemove', fn);
window.removeEventListener('mousemove', fn);
window.removeEventListener('mouseleave', dragClear);
window.removeEventListener('mouseup', dragClear);
window.removeEventListener('mouseup', dragClear);
}
function onMousedown(ev) {

View File

@ -49,6 +49,7 @@ export default defineConfig(({ command, mode }) => {
'chrome100',
'firefox100',
'safari15',
'es2017', // TODO: そのうち消す
],
manifest: 'manifest.json',
rollupOptions: {

View File

@ -515,14 +515,14 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.0.tgz#524a11e15c09701733033c96943ecf33f55d9ca1"
integrity sha512-lvhRJ2pGe2V9MEU46ELTdiHgiAFZPKtLhiU5wlnaYpMc2+c1R8fh8i80ZAa665drvjHKUJyRRGg3gEm1If54ow==
"@typescript-eslint/eslint-plugin@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz#9c6017b6c1d04894141b4a87816388967f64c359"
integrity sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==
dependencies:
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/type-utils" "5.30.0"
"@typescript-eslint/utils" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/type-utils" "5.30.6"
"@typescript-eslint/utils" "5.30.6"
debug "^4.3.4"
functional-red-black-tree "^1.0.1"
ignore "^5.2.0"
@ -530,69 +530,69 @@
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/parser@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.0.tgz#a2184fb5f8ef2bf1db0ae61a43907e2e32aa1b8f"
integrity sha512-2oYYUws5o2liX6SrFQ5RB88+PuRymaM2EU02/9Ppoyu70vllPnHVO7ioxDdq/ypXHA277R04SVjxvwI8HmZpzA==
"@typescript-eslint/parser@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.6.tgz#add440db038fa9d777e4ebdaf66da9e7fb7abe92"
integrity sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==
dependencies:
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/typescript-estree" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
debug "^4.3.4"
"@typescript-eslint/scope-manager@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.0.tgz#bf585ee801ab4ad84db2f840174e171a6bb002c7"
integrity sha512-3TZxvlQcK5fhTBw5solQucWSJvonXf5yua5nx8OqK94hxdrT7/6W3/CS42MLd/f1BmlmmbGEgQcTHHCktUX5bQ==
"@typescript-eslint/scope-manager@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz#ce1b49ff5ce47f55518d63dbe8fc9181ddbd1a33"
integrity sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
"@typescript-eslint/type-utils@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.0.tgz#98f3af926a5099153f092d4dad87148df21fbaae"
integrity sha512-GF8JZbZqSS+azehzlv/lmQQ3EU3VfWYzCczdZjJRxSEeXDQkqFhCBgFhallLDbPwQOEQ4MHpiPfkjKk7zlmeNg==
"@typescript-eslint/type-utils@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz#a64aa9acbe609ab77f09f53434a6af2b9685f3af"
integrity sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==
dependencies:
"@typescript-eslint/utils" "5.30.0"
"@typescript-eslint/utils" "5.30.6"
debug "^4.3.4"
tsutils "^3.21.0"
"@typescript-eslint/types@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.0.tgz#db7d81d585a3da3801432a9c1d2fafbff125e110"
integrity sha512-vfqcBrsRNWw/LBXyncMF/KrUTYYzzygCSsVqlZ1qGu1QtGs6vMkt3US0VNSQ05grXi5Yadp3qv5XZdYLjpp8ag==
"@typescript-eslint/types@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.6.tgz#86369d0a7af8c67024115ac1da3e8fb2d38907e1"
integrity sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==
"@typescript-eslint/typescript-estree@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.0.tgz#4565ee8a6d2ac368996e20b2344ea0eab1a8f0bb"
integrity sha512-hDEawogreZB4n1zoqcrrtg/wPyyiCxmhPLpZ6kmWfKF5M5G0clRLaEexpuWr31fZ42F96SlD/5xCt1bT5Qm4Nw==
"@typescript-eslint/typescript-estree@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz#a84a0d6a486f9b54042da1de3d671a2c9f14484e"
integrity sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.0.tgz#1dac771fead5eab40d31860716de219356f5f754"
integrity sha512-0bIgOgZflLKIcZsWvfklsaQTM3ZUbmtH0rJ1hKyV3raoUYyeZwcjQ8ZUJTzS7KnhNcsVT1Rxs7zeeMHEhGlltw==
"@typescript-eslint/utils@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.6.tgz#1de2da14f678e7d187daa6f2e4cdb558ed0609dc"
integrity sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==
dependencies:
"@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/typescript-estree" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.0.tgz#07721d23daca2ec4c2da7f1e660d41cd78bacac3"
integrity sha512-6WcIeRk2DQ3pHKxU1Ni0qMXJkjO/zLjBymlYBy/53qxe7yjEFSvzKLDToJjURUhSl2Fzhkl4SMXQoETauF74cw==
"@typescript-eslint/visitor-keys@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz#94dd10bb481c8083378d24de1742a14b38a2678c"
integrity sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/types" "5.30.6"
eslint-visitor-keys "^3.3.0"
"@ungap/promise-all-settled@1.1.2":
@ -600,10 +600,10 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@vitejs/plugin-vue@3.0.0-beta.1":
version "3.0.0-beta.1"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.0.0-beta.1.tgz#65a6be6ed619955a5edea6115dedcfc5da4ed3f6"
integrity sha512-cPVQHIKZkVEQ8qW7+BlbTrGJXNpP2aMKzVhQdTnWK9u6cSDmVdZOXHmKPO2KVvrNpFXXS8R7hHBXMsSApA+XOA==
"@vitejs/plugin-vue@3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.0.0.tgz#7081e2b3fbe04e291bb85107b9fb57a1fa5e6aeb"
integrity sha512-yWP34ArFh/jAeNUDkkLz/kVRLjf5ppJiq4L36f64Cp6dIrMQeYZGDP9xxdemlXfZR9ylN9JgHUl3GzfqOtgYDg==
"@vue/compiler-core@3.2.37":
version "3.2.37"
@ -1715,10 +1715,10 @@ eslint-plugin-import@2.26.0:
resolve "^1.22.0"
tsconfig-paths "^3.14.1"
eslint-plugin-vue@9.1.1:
version "9.1.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.1.1.tgz#341f7533cb041958455138834341d5be01f9f327"
integrity sha512-W9n5PB1X2jzC7CK6riG0oAcxjmKrjTF6+keL1rni8n57DZeilx/Fulz+IRJK3lYseLNAygN0I62L7DvioW40Tw==
eslint-plugin-vue@9.2.0:
version "9.2.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.2.0.tgz#b7ca02b2ce8218b7586346440fc61c2655db353a"
integrity sha512-W2hc+NUXoce8sZtWgZ45miQTy6jNyuSdub5aZ1IBune4JDeAyzucYX0TzkrQ1jMO52sNUDYlCIHDoaNePe0p5g==
dependencies:
eslint-utils "^3.0.0"
natural-compare "^1.4.0"
@ -1761,10 +1761,10 @@ eslint-visitor-keys@^3.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint@8.18.0:
version "8.18.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.18.0.tgz#78d565d16c993d0b73968c523c0446b13da784fd"
integrity sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==
eslint@8.19.0:
version "8.19.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.19.0.tgz#7342a3cbc4fbc5c106a1eefe0fd0b50b6b1a7d28"
integrity sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==
dependencies:
"@eslint/eslintrc" "^1.3.0"
"@humanwhocodes/config-array" "^0.9.2"
@ -2866,12 +2866,12 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
mfm-js@0.22.1:
version "0.22.1"
resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.22.1.tgz#ad5f0b95cc903ca5a5e414e2edf64ac4648dc8c2"
integrity sha512-UV5zvDKlWPpBFeABhyCzuOTJ3RwrNrmVpJ+zz/dFX6D/ntEywljgxkfsLamcy0ZSwUAr0O+WQxGHvAwyxUgsAQ==
mfm-js@0.23.0-canary.1:
version "0.23.0-canary.1"
resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.23.0-canary.1.tgz#1b7b7635f18bed9776054406b72e6bd613c8d0eb"
integrity sha512-SkMrW1rQAv+mFGtLKN9DSv6vxSREDu8ChmkBl1Ch5sQfp47BhuvcRg5EKGmt3WAQRAOylXYMg8wVYR7C5BHKeA==
dependencies:
twemoji-parser "14.0.x"
twemoji-parser "14.0.0"
micromatch@^4.0.2:
version "4.0.2"
@ -3649,7 +3649,14 @@ rndstr@1.0.0:
rangestr "0.0.1"
seedrandom "2.4.2"
rollup@2.75.7, rollup@^2.75.6:
rollup@2.76.0:
version "2.76.0"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.76.0.tgz#c69fe03db530ac53fcb9523b3caa0d3c0b9491a1"
integrity sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==
optionalDependencies:
fsevents "~2.3.2"
rollup@^2.75.6:
version "2.75.7"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.7.tgz#221ff11887ae271e37dcc649ba32ce1590aaa0b9"
integrity sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==
@ -4085,7 +4092,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
twemoji-parser@14.0.0, twemoji-parser@14.0.x:
twemoji-parser@14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-14.0.0.tgz#13dabcb6d3a261d9efbf58a1666b182033bf2b62"
integrity sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==
@ -4215,10 +4222,10 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vite@3.0.0-beta.7:
version "3.0.0-beta.7"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.0-beta.7.tgz#ded6483ef3b9b16dbe3a912a35accb9cc3498530"
integrity sha512-yjw154hB229qq5Bl6+/CJSTxC/yIDmDJbaAjE/pdracz3jytNEd2ovk5BvxgZT6+qPiUc2rRH3FgGqiZnweIFw==
vite@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.0.tgz#b4675cb9ab83ec0803b9c952ffa6519bcce033a7"
integrity sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==
dependencies:
esbuild "^0.14.47"
postcss "^8.4.14"