/* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ import { defineAsyncComponent } from 'vue'; import { v4 as uuid } from 'uuid'; import type { EmbedParams, EmbeddableEntity } from '@@/js/embed-page.js'; import { url } from '@@/js/config.js'; import * as os from '@/os.js'; import { copyToClipboard } from '@/scripts/copy-to-clipboard.js'; import { defaultEmbedParams, embedRouteWithScrollbar } from '@@/js/embed-page.js'; const MOBILE_THRESHOLD = 500; /** * パラメータを正規化する(埋め込みコード作成用) * @param params パラメータ * @returns 正規化されたパラメータ */ export function normalizeEmbedParams(params: EmbedParams): Record { // paramsのvalueをすべてstringに変換。undefinedやnullはプロパティごと消す const normalizedParams: Record = {}; for (const key in params) { // デフォルトの値と同じならparamsに含めない if (params[key] == null || params[key] === defaultEmbedParams[key]) { continue; } switch (typeof params[key]) { case 'number': normalizedParams[key] = params[key].toString(); break; case 'boolean': normalizedParams[key] = params[key] ? 'true' : 'false'; break; default: normalizedParams[key] = params[key]; break; } } return normalizedParams; } /** * 埋め込みコードを生成(iframe IDの発番もやる) */ export function getEmbedCode(path: string, params?: EmbedParams): string { const iframeId = 'v1_' + uuid(); // 将来embed.jsのバージョンが上がったとき用にv1_を付けておく let paramString = ''; if (params) { const searchParams = new URLSearchParams(normalizeEmbedParams(params)); paramString = searchParams.toString() === '' ? '' : '?' + searchParams.toString(); } const iframeCode = [ ``, ``, ]; return iframeCode.join('\n'); } /** * 埋め込みコードを生成してコピーする(カスタマイズ機能つき) * * カスタマイズ機能がいらない場合(事前にパラメータを指定する場合)は getEmbedCode を直接使ってください */ export function genEmbedCode(entity: EmbeddableEntity, id: string, params?: EmbedParams) { const _params = { ...params }; if (embedRouteWithScrollbar.includes(entity) && _params.maxHeight == null) { _params.maxHeight = 700; } // PCじゃない場合はコードカスタマイズ画面を出さずにそのままコピー if (window.innerWidth < MOBILE_THRESHOLD) { copyToClipboard(getEmbedCode(`/embed/${entity}/${id}`, _params)); os.success(); } else { const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkEmbedCodeGenDialog.vue')), { entity, id, params: _params, }, { closed: () => dispose(), }); } }