_Editor.cshtml 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <link rel="stylesheet" href="/lib/ckeditor/ckeditor5/ckeditor5.css" asp-append-version="true" />
  2. <script type="importmap">
  3. {
  4. "imports": {
  5. "ckeditor5": "/lib/ckeditor/ckeditor5/ckeditor5.js",
  6. "ckeditor5/": "/lib/ckeditor/ckeditor5/"
  7. }
  8. }
  9. </script>
  10. <script type="module">
  11. import {
  12. ClassicEditor, Essentials, Paragraph, Bold, Italic, Underline, Strikethrough, Code, Subscript, Superscript, RemoveFormat, List, TodoList,
  13. Indent, Heading, Font, Highlight, Alignment, Link, Image, ImageToolbar, ImageCaption, ImageStyle, ImageResize, ImageUpload, MediaEmbed, CodeBlock,
  14. HtmlEmbed, SpecialCharacters, HorizontalLine, PageBreak, SourceEditing, FindAndReplace, SelectAll, BlockQuote, Table, TableToolbar, TextPartLanguage
  15. } from 'ckeditor5';
  16. class CustomUploadAdapter {
  17. constructor(loader) {
  18. this.loader = loader;
  19. }
  20. // 업로드 시작
  21. upload() {
  22. return this.loader.file.then(file => {
  23. return new Promise((resolve, reject) => {
  24. const reader = new FileReader();
  25. reader.onload = () => {
  26. resolve({
  27. default: reader.result
  28. });
  29. };
  30. reader.onerror = error => reject(error);
  31. reader.readAsDataURL(file);
  32. });
  33. });
  34. }
  35. // 취소 또는 정리 작업
  36. abort() {
  37. console.log('업로드가 취소되었습니다.');
  38. }
  39. }
  40. // CKEditor 초기화
  41. document.querySelectorAll('.ck-editor').forEach(e => {
  42. ClassicEditor
  43. .create(e, {
  44. licenseKey: 'GPL',
  45. plugins: [
  46. Essentials, Paragraph, Bold, Italic, Underline, Strikethrough, Code,
  47. Subscript, Superscript, RemoveFormat, List, TodoList, Indent, Heading,
  48. Font, Highlight, Alignment, Link, Image, ImageToolbar, ImageCaption,
  49. ImageStyle, ImageResize, ImageUpload, MediaEmbed, CodeBlock, HtmlEmbed,
  50. SpecialCharacters, HorizontalLine, PageBreak, SourceEditing,
  51. FindAndReplace, SelectAll, BlockQuote, Table, TableToolbar, TextPartLanguage
  52. ],
  53. toolbar: {
  54. items: [
  55. 'findAndReplace', 'selectAll', '|',
  56. 'heading', '|',
  57. 'bold', 'italic', 'strikethrough', 'underline', 'code', 'subscript', 'superscript', 'removeFormat', '|',
  58. 'bulletedList', 'numberedList', 'todoList', '|',
  59. 'outdent', 'indent', '|',
  60. 'undo', 'redo', '|',
  61. 'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'highlight', '|',
  62. 'alignment', '|',
  63. 'link', 'insertImage', 'blockQuote', 'insertTable', 'mediaEmbed', 'codeBlock', 'htmlEmbed', '|',
  64. 'specialCharacters', 'horizontalLine', 'pageBreak', '|',
  65. 'textPartLanguage', '|',
  66. 'sourceEditing'
  67. ],
  68. shouldNotGroupWhenFull: true
  69. },
  70. list: {
  71. properties: {
  72. styles: true,
  73. startIndex: true,
  74. reversed: true
  75. }
  76. },
  77. heading: {
  78. options: [
  79. { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
  80. { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
  81. { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
  82. { model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' },
  83. { model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' },
  84. { model: 'heading5', view: 'h5', title: 'Heading 5', class: 'ck-heading_heading5' },
  85. { model: 'heading6', view: 'h6', title: 'Heading 6', class: 'ck-heading_heading6' }
  86. ]
  87. },
  88. placeholder: '내용을 입력해주세요.',
  89. fontFamily: {
  90. options: [
  91. 'default',
  92. 'Arial, Helvetica, sans-serif',
  93. 'Courier New, Courier, monospace',
  94. 'Georgia, serif',
  95. 'Lucida Sans Unicode, Lucida Grande, sans-serif',
  96. 'Tahoma, Geneva, sans-serif',
  97. 'Times New Roman, Times, serif',
  98. 'Trebuchet MS, Helvetica, sans-serif',
  99. 'Verdana, Geneva, sans-serif'
  100. ],
  101. supportAllValues: true
  102. },
  103. fontSize: {
  104. options: [10, 12, 14, 'default', 18, 20, 22],
  105. supportAllValues: true
  106. },
  107. htmlSupport: {
  108. allow: [
  109. {
  110. name: /.*/,
  111. attributes: true,
  112. classes: true,
  113. styles: true
  114. }
  115. ]
  116. },
  117. htmlEmbed: {
  118. showPreviews: true
  119. },
  120. link: {
  121. decorators: {
  122. addTargetToExternalLinks: true,
  123. defaultProtocol: 'https://',
  124. toggleDownloadable: {
  125. mode: 'manual',
  126. label: 'Downloadable',
  127. attributes: {
  128. download: 'file'
  129. }
  130. }
  131. }
  132. },
  133. image: {
  134. toolbar: [
  135. 'imageStyle:inline', 'imageStyle:block', 'imageStyle:side', '|',
  136. 'toggleImageCaption', 'imageTextAlternative'
  137. ]
  138. },
  139. table: {
  140. contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells']
  141. },
  142. simpleUpload: {
  143. uploadUrl: null
  144. }
  145. })
  146. .then(editor => {
  147. editor.plugins.get('FileRepository').createUploadAdapter = loader => {
  148. return new CustomUploadAdapter(loader);
  149. };
  150. console.log('Editor initialized', editor);
  151. })
  152. .catch(error => {
  153. console.error('Error initializing CKEditor:', error);
  154. });
  155. });
  156. </script>