localhost-front/src/components/editor/TEditor.vue
2024-12-17 10:16:27 +09:00

172 lines
5.9 KiB
Vue

<template>
<Editor v-model="content"
:api-key="editorKey" :init="init" />
</template>
<script setup>
import Editor from '@tinymce/tinymce-vue';
import { reactive, ref, watch, watchEffect } from 'vue';
import { wait } from '@/common/utils';
const emit = defineEmits(['update:data']);
const content = ref('');
const editorKey = '71nhna4fusscfsf8qvo9cg3ul4uydwt346izxa6ra6zwjsz7';
const init = reactive({
menubar: false,
toolbar_mode: 'sliding',
selector: 'textarea',
plugins: [
'code',
'anchor',
'autolink',
'charmap',
'codesample',
'emoticons',
'image',
'link',
'lists',
'media',
'searchreplace',
'table',
'visualblocks',
'wordcount',
],
//하단바 설정
statusbar: false,
//code sample 세팅
codesample_content_css: 'pre { white-space: pre-wrap; word-wrap: break-word; }',
tabsize: 4,
tabfocus: false,
tabnavigation: false,
//메뉴바 시작
toolbar: [
'undo redo | fontfamily fontsize | blockquote h1 h2 h3 h4 h5 h6 | bold italic underline alignleft aligncenter alignright alignjustify indent outdent',
'checklist numlist bullist | link image table | codesample emoticons code',
],
style_format_merge: true,
//custom menu format
font_family_formats: `
Arial=arial,helvetica,sans-serif;
Courier New=courier new,courier,monospace;
AkrutiKndPadmini=Akpdmi-n;
Consolas=consolas,monaco,monospace;
나눔고딕=NanumGothic,나눔고딕,AppleSDGothicNeo,sans-serif;
맑은 고딕=Malgun Gothic,맑은 고딕,AppleSDGothicNeo,sans-serif;
돋움=Dotum,돋움,sans-serif;
D2Coding=D2Coding,D2CodingBold,monospace;`,
formats: {
blockquote: {
block: 'blockquote',
styles: { 'font-style': 'italic', 'border-left': '4px solid #ccc', 'padding-left': '10px' },
},
paragraph: {
block: 'p',
styles: { 'margin-bottom': '1em', 'font-size': '1em' },
},
heading1: {
block: 'h1',
styles: { 'font-size': '2em', 'font-weight': 'bold', 'margin-top': '1em', 'margin-bottom': '0.5em' },
},
heading2: {
block: 'h2',
styles: { 'font-size': '1.75em', 'font-weight': 'bold', 'margin-top': '1em', 'margin-bottom': '0.5em' },
},
heading3: {
block: 'h3',
styles: { 'font-size': '1.5em', 'font-weight': 'bold', 'margin-top': '1em', 'margin-bottom': '0.5em' },
},
heading4: {
block: 'h4',
styles: { 'font-size': '1.25em', 'font-weight': 'bold', 'margin-top': '1em', 'margin-bottom': '0.5em' },
},
heading5: {
block: 'h5',
styles: { 'font-size': '1em', 'font-weight': 'bold', 'margin-top': '1em', 'margin-bottom': '0.5em' },
},
heading6: {
block: 'h6',
styles: { 'font-size': '0.875em', 'font-weight': 'bold', 'margin-top': '1em', 'margin-bottom': '0.5em' },
},
alignleft: {
selector: 'p,h1,h2,h3,h4,h5,h6,div',
styles: { 'text-align': 'left' },
},
aligncenter: {
selector: 'p,h1,h2,h3,h4,h5,h6,div',
styles: { 'text-align': 'center' },
},
alignright: {
selector: 'p,h1,h2,h3,h4,h5,h6,div',
styles: { 'text-align': 'right' },
},
alignjustify: {
selector: 'p,h1,h2,h3,h4,h5,h6,div',
styles: { 'text-align': 'justify' },
},
},
setup(editor) {
editor.on('init', async () => {
//가상돔 로딩 기다리기
await wait(500);
const targetElement = document.querySelector('[aria-label="Insert/edit code sample"]');
//editor.notificationManager <-- editor 경고문 띄우는 용도
targetElement.addEventListener('click', async () => {
// 클릭 후 기다리기
await wait(200);
const textEle = document.querySelector('.tox-textarea-wrap');
const textarea = textEle.querySelector('textarea');
if (textarea) {
// tab 키 이벤트 처리 함수 등록
const handleTabKey = event => {
if (event.key === 'Tab') {
event.preventDefault(); // 기본 탭 동작(포커스 이동) 막기
// 커서 위치 가져오기
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
// 현재 텍스트에서 공백 4칸 추가
const text = textarea.value;
textarea.value = text.substring(0, start) + ' ' + text.substring(end);
const newCursorPos = start + 4;
// 포커스를 설정하고 커서 위치를 업데이트
setTimeout(() => {
textarea.focus(); // 포커스 설정
// 커서 위치를 다시 설정
textarea.selectionStart = textarea.selectionEnd = newCursorPos;
}, 0);
}
};
// 이미 이벤트 리스너가 등록되어 있다면 제거하여 중복 등록을 방지
textarea.removeEventListener('keydown', handleTabKey);
// keydown 이벤트 리스너 추가
textarea.addEventListener('keydown', handleTabKey);
}
});
});
},
});
watchEffect(() =>{
emit('update:data', content.value)
})
// emit 이랑 file 처리해야됨 ~
</script>
<style scoped>
</style>