summaryrefslogtreecommitdiff
path: root/packages/frontend/src/scripts/mfm-function-picker.ts
blob: 9938e534c139e72d0c57c748fbf3f10811158bdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
 * SPDX-FileCopyrightText: syuilo and misskey-project
 * SPDX-License-Identifier: AGPL-3.0-only
 */

import { Ref, nextTick } from 'vue';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { MFM_TAGS } from '@/const.js';
import type { MenuItem } from '@/types/menu.js';

/**
 * MFMの装飾のリストを表示する
 */
export function mfmFunctionPicker(src: HTMLElement | EventTarget | null, textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>) {
	os.popupMenu([{
		text: i18n.ts.addMfmFunction,
		type: 'label',
	}, ...getFunctionList(textArea, textRef)], src);
}

function getFunctionList(textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>): MenuItem[] {
	return MFM_TAGS.map(tag => ({
		text: tag,
		icon: 'ti ti-icons',
		action: () => add(textArea, textRef, tag),
	}));
}

function add(textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>, type: string) {
	const caretStart: number = textArea.selectionStart as number;
	const caretEnd: number = textArea.selectionEnd as number;

	MFM_TAGS.forEach(tag => {
		if (type === tag) {
			if (caretStart === caretEnd) {
				// 単純にFunctionを追加
				const trimmedText = `${textRef.value.substring(0, caretStart)}$[${type} ]${textRef.value.substring(caretEnd)}`;
				textRef.value = trimmedText;
			} else {
				// 選択範囲を囲むようにFunctionを追加
				const trimmedText = `${textRef.value.substring(0, caretStart)}$[${type} ${textRef.value.substring(caretStart, caretEnd)}]${textRef.value.substring(caretEnd)}`;
				textRef.value = trimmedText;
			}
		}
	});

	const nextCaretStart: number = caretStart + 3 + type.length;
	const nextCaretEnd: number = caretEnd + 3 + type.length;

	// キャレットを戻す
	nextTick(() => {
		textArea.focus();
		textArea.setSelectionRange(nextCaretStart, nextCaretEnd);
	});
}