172 lines
5.9 KiB
Vue
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>
|