394 lines
8.1 KiB
Vue
394 lines
8.1 KiB
Vue
<template>
|
|
<ClientOnly>
|
|
<div ref="el"></div>
|
|
</ClientOnly>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
|
import 'ckeditor5/ckeditor5.css';
|
|
import 'ckeditor5-premium-features/ckeditor5-premium-features.css';
|
|
|
|
const el = ref(null);
|
|
let editor = null;
|
|
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
});
|
|
const emit = defineEmits(['update:modelValue']);
|
|
const content = ref(props.modelValue || '');
|
|
|
|
onMounted(async () => {
|
|
if (!process.client) return;
|
|
|
|
const {
|
|
ClassicEditor,
|
|
AccessibilityHelp,
|
|
Autoformat,
|
|
AutoImage,
|
|
AutoLink,
|
|
Autosave,
|
|
BalloonToolbar,
|
|
BlockQuote,
|
|
BlockToolbar,
|
|
Bold,
|
|
CKBox,
|
|
CKBoxImageEdit,
|
|
CloudServices,
|
|
Essentials,
|
|
FontBackgroundColor,
|
|
FontColor,
|
|
FontFamily,
|
|
FontSize,
|
|
Heading,
|
|
Highlight,
|
|
ImageBlock,
|
|
ImageCaption,
|
|
ImageInline,
|
|
ImageInsert,
|
|
ImageInsertViaUrl,
|
|
ImageResize,
|
|
ImageStyle,
|
|
ImageTextAlternative,
|
|
ImageToolbar,
|
|
ImageUpload,
|
|
Indent,
|
|
IndentBlock,
|
|
Italic,
|
|
Link,
|
|
LinkImage,
|
|
List,
|
|
ListProperties,
|
|
MediaEmbed,
|
|
Mention,
|
|
PageBreak,
|
|
Paragraph,
|
|
PasteFromOffice,
|
|
PictureEditing,
|
|
RemoveFormat,
|
|
SelectAll,
|
|
SpecialCharacters,
|
|
SpecialCharactersArrows,
|
|
SpecialCharactersCurrency,
|
|
SpecialCharactersEssentials,
|
|
SpecialCharactersLatin,
|
|
SpecialCharactersMathematical,
|
|
SpecialCharactersText,
|
|
Subscript,
|
|
Superscript,
|
|
Table,
|
|
TableCaption,
|
|
TableCellProperties,
|
|
GeneralHtmlSupport,
|
|
TableColumnResize,
|
|
TableProperties,
|
|
TableToolbar,
|
|
TextTransformation,
|
|
TodoList,
|
|
Underline,
|
|
Alignment,
|
|
Undo,
|
|
} = await import('ckeditor5');
|
|
const { ExportPdf, ExportWord, ImportWord } = await import('ckeditor5-premium-features');
|
|
|
|
editor = await ClassicEditor.create(el.value, {
|
|
// licenseKey: 'GPL',
|
|
|
|
plugins: [
|
|
AccessibilityHelp,
|
|
Autoformat,
|
|
AutoImage,
|
|
AutoLink,
|
|
Autosave,
|
|
BalloonToolbar,
|
|
BlockQuote,
|
|
BlockToolbar,
|
|
Bold,
|
|
CKBox,
|
|
CKBoxImageEdit,
|
|
CloudServices,
|
|
Essentials,
|
|
ExportPdf,
|
|
ExportWord,
|
|
FontBackgroundColor,
|
|
FontColor,
|
|
FontFamily,
|
|
FontSize,
|
|
Heading,
|
|
Highlight,
|
|
ImageBlock,
|
|
ImageCaption,
|
|
ImageInline,
|
|
ImageInsert,
|
|
ImageInsertViaUrl,
|
|
ImageResize,
|
|
ImageStyle,
|
|
ImageTextAlternative,
|
|
ImageToolbar,
|
|
ImageUpload,
|
|
ImportWord,
|
|
Indent,
|
|
IndentBlock,
|
|
Italic,
|
|
Link,
|
|
LinkImage,
|
|
List,
|
|
ListProperties,
|
|
MediaEmbed,
|
|
Mention,
|
|
PageBreak,
|
|
Paragraph,
|
|
PasteFromOffice,
|
|
PictureEditing,
|
|
RemoveFormat,
|
|
SelectAll,
|
|
SpecialCharacters,
|
|
SpecialCharactersArrows,
|
|
SpecialCharactersCurrency,
|
|
SpecialCharactersEssentials,
|
|
SpecialCharactersLatin,
|
|
SpecialCharactersMathematical,
|
|
SpecialCharactersText,
|
|
Subscript,
|
|
Superscript,
|
|
Table,
|
|
TableCaption,
|
|
TableCellProperties,
|
|
TableColumnResize,
|
|
TableProperties,
|
|
TableToolbar,
|
|
TextTransformation,
|
|
TodoList,
|
|
Underline,
|
|
Alignment,
|
|
GeneralHtmlSupport,
|
|
Undo,
|
|
],
|
|
|
|
toolbar: [
|
|
'undo',
|
|
'redo',
|
|
'|',
|
|
'importWord',
|
|
'exportWord',
|
|
'exportPdf',
|
|
'|',
|
|
'heading',
|
|
'|',
|
|
'fontSize',
|
|
'fontFamily',
|
|
'fontColor',
|
|
'fontBackgroundColor',
|
|
'|',
|
|
'bold',
|
|
'italic',
|
|
'underline',
|
|
'subscript',
|
|
'superscript',
|
|
'removeFormat',
|
|
'|',
|
|
'alignment', // 👈 THÊM
|
|
'|',
|
|
'specialCharacters',
|
|
'pageBreak',
|
|
'link',
|
|
'insertImage',
|
|
'insertImageViaUrl',
|
|
'ckbox',
|
|
'mediaEmbed',
|
|
'insertTable',
|
|
'highlight',
|
|
'blockQuote',
|
|
'|',
|
|
'bulletedList',
|
|
'numberedList',
|
|
'todoList',
|
|
'outdent',
|
|
'indent',
|
|
],
|
|
exportPdf: {
|
|
stylesheets: [
|
|
'https://cdn.ckeditor.com/ckeditor5/43.2.0/ckeditor5.css',
|
|
'https://cdn.ckeditor.com/ckeditor5-premium-features/43.2.0/ckeditor5-premium-features.css',
|
|
],
|
|
fileName: 'export-pdf-demo.pdf',
|
|
converterOptions: {
|
|
format: 'Tabloid',
|
|
margin_top: '20mm',
|
|
margin_bottom: '20mm',
|
|
margin_right: '24mm',
|
|
margin_left: '24mm',
|
|
page_orientation: 'portrait',
|
|
},
|
|
},
|
|
exportWord: {
|
|
stylesheets: [
|
|
'https://cdn.ckeditor.com/ckeditor5/43.2.0/ckeditor5.css',
|
|
'https://cdn.ckeditor.com/ckeditor5-premium-features/43.2.0/ckeditor5-premium-features.css',
|
|
],
|
|
fileName: 'export-word-demo.docx',
|
|
converterOptions: {
|
|
document: {
|
|
orientation: 'portrait',
|
|
size: 'Tabloid',
|
|
margins: {
|
|
top: '20mm',
|
|
bottom: '20mm',
|
|
right: '24mm',
|
|
left: '24mm',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
balloonToolbar: ['bold', 'italic','fontFamily','fontSize', '|', 'alignment', 'link', 'insertImage', '|', 'bulletedList', 'numberedList'],
|
|
blockToolbar: [
|
|
'fontSize',
|
|
'fontColor',
|
|
'fontBackgroundColor',
|
|
'|',
|
|
'bold',
|
|
'italic',
|
|
'|',
|
|
'link',
|
|
'insertImage',
|
|
'insertTable',
|
|
'|',
|
|
'bulletedList',
|
|
'numberedList',
|
|
'outdent',
|
|
'indent',
|
|
],
|
|
fontFamily: {
|
|
supportAllValues: true,
|
|
},
|
|
fontSize: {
|
|
options: [10, 12,13, 14, 'default', 18, 20, 22],
|
|
supportAllValues: true,
|
|
},
|
|
heading: {
|
|
options: [
|
|
{
|
|
model: 'paragraph',
|
|
title: 'Paragraph',
|
|
class: 'ck-heading_paragraph',
|
|
},
|
|
{
|
|
model: 'heading1',
|
|
view: 'h1',
|
|
title: 'Heading 1',
|
|
class: 'ck-heading_heading1',
|
|
},
|
|
{
|
|
model: 'heading2',
|
|
view: 'h2',
|
|
title: 'Heading 2',
|
|
class: 'ck-heading_heading2',
|
|
},
|
|
{
|
|
model: 'heading3',
|
|
view: 'h3',
|
|
title: 'Heading 3',
|
|
class: 'ck-heading_heading3',
|
|
},
|
|
{
|
|
model: 'heading4',
|
|
view: 'h4',
|
|
title: 'Heading 4',
|
|
class: 'ck-heading_heading4',
|
|
},
|
|
{
|
|
model: 'heading5',
|
|
view: 'h5',
|
|
title: 'Heading 5',
|
|
class: 'ck-heading_heading5',
|
|
},
|
|
{
|
|
model: 'heading6',
|
|
view: 'h6',
|
|
title: 'Heading 6',
|
|
class: 'ck-heading_heading6',
|
|
},
|
|
],
|
|
},
|
|
image: {
|
|
toolbar: [
|
|
'toggleImageCaption',
|
|
'imageTextAlternative',
|
|
'|',
|
|
'imageStyle:inline',
|
|
'imageStyle:wrapText',
|
|
'imageStyle:breakText',
|
|
'|',
|
|
'resizeImage',
|
|
'|',
|
|
'ckboxImageEdit',
|
|
],
|
|
},
|
|
link: {
|
|
addTargetToExternalLinks: true,
|
|
defaultProtocol: 'https://',
|
|
decorators: {
|
|
toggleDownloadable: {
|
|
mode: 'manual',
|
|
label: 'Downloadable',
|
|
attributes: {
|
|
download: 'file',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
list: {
|
|
properties: {
|
|
styles: true,
|
|
startIndex: true,
|
|
reversed: true,
|
|
},
|
|
},
|
|
mention: {
|
|
feeds: [
|
|
{
|
|
marker: '@',
|
|
feed: [],
|
|
},
|
|
],
|
|
},
|
|
menuBar: {
|
|
isVisible: true,
|
|
},
|
|
table: {
|
|
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties'],
|
|
},
|
|
alignment: {
|
|
options: ['left', 'center', 'right', 'justify'],
|
|
},
|
|
});
|
|
|
|
// set data ban đầu
|
|
editor.setData(props.modelValue || '');
|
|
|
|
// khi thay đổi → emit ra ngoài
|
|
editor.model.document.on('change:data', () => {
|
|
const data = editor.getData();
|
|
emit('update:modelValue', data);
|
|
});
|
|
});
|
|
|
|
watch(
|
|
() => props.modelValue,
|
|
(val) => {
|
|
if (editor && val !== editor.getData()) {
|
|
editor.setData(val || '');
|
|
}
|
|
},
|
|
);
|
|
onBeforeUnmount(async () => {
|
|
if (editor) {
|
|
await editor.destroy();
|
|
editor = null;
|
|
}
|
|
});
|
|
</script>
|