NoteEditor

ckeditor、summernote、quill

1.ckeditor:
@model Model //強型別的 Model 物件

@using (Html.BeginForm("action", "controller")) //後端存檔editor 內容
{
  <div id="editor" >
      @Model.value
  </div>
}

<style> //關閉版本提醒
      .cke_notifications_area {
          display: none;
      }
</style>

//引用 ckeditor
<script src="https://cdn.ckeditor.com/4.22.1/full/ckeditor.js" crossorigin="anonymous"></script>
<script type="text/javascript">
  CKEDITOR.replace('editor', {
   filebrowserImageUploadUrl: '', //後端圖片存檔
   width: 100, //寬
   height: 100, //高
  });
</script>

2.summernote:  https://summernote.org/

@model Model //強型別的 Model 物件

<div id="summernote" >
  @Model.value
</div>
<button type="button" onclick="save()">儲存</button>

//jQuery 3.5.1
<script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" crossorigin="anonymous"></script>
//bootstrap 4.4.1
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" crossorigin="anonymous"></script>
//summernote 0.8.18
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script>

<style> //Modal顯示位置
   .modal-dialog {
       position: static !important;
   }
</style>
<script type="text/javascript">

   $('#summernote').summernote({
       width: 500, //寬
       height: 300, //高                 
       focus: true, //編輯區
       callbacks: {
            //圖片上傳
           onImageUpload: function (image) {
                //後端存圖片
                var imgNode = $("<img>", { src: //後端圖片位置 }); //建立圖片 element
                $('#summernote').summernote('insertNode', imgNode[0]); //summernote 插入圖片
           }
       }
   });

   function save() {
       $('#summernote').summernote('code'); //取得 summernote html內容
   }
</script>

3.quill: https://quilljs.com/

*斷行 \r\n
@model Model //強型別的 Model 物件
// Quill formats https://quilljs.com/docs/formats
<div id="toolbar-container">
       <span class="ql-formats">
               <select class="ql-font"></select>
               <select class="ql-size"></select>
       </span>
       <span class="ql-formats">
               <button class="ql-bold"></button>
               <button class="ql-italic"></button>
               <button class="ql-underline"></button>
               <button class="ql-strike"></button>
       </span>
       <span class="ql-formats">
               <select class="ql-color"></select>
               <select class="ql-background"></select>
       </span>
       <span class="ql-formats">
               <button class="ql-script" value="sub"></button>
               <button class="ql-script" value="super"></button>
       </span>
       <span class="ql-formats">
               <button class="ql-header" value="1"></button>
               <button class="ql-header" value="2"></button>
               <button class="ql-blockquote"></button>
               <button class="ql-code-block"></button>
       </span>
       <span class="ql-formats">
               <button class="ql-list" value="ordered"></button>
               <button class="ql-list" value="bullet"></button>
               <button class="ql-indent" value="-1"></button>
               <button class="ql-indent" value="+1"></button>
       </span>
       <span class="ql-formats">
               <button class="ql-direction" value="rtl"></button>
               <select class="ql-align"></select>
       </span>
       <span class="ql-formats">
               <button class="ql-link"></button>
               <button class="ql-image"></button>
               <button class="ql-video"></button>
               <button class="ql-formula"></button>
       </span>
       <span class="ql-formats">
               <button class="ql-clean"></button>
       </span>
</div>
<div id="editor" ></div>
<button type="button" onclick="save()">儲存</button>

//quill css
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.snow.css" rel="stylesheet" />

//quill js
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.js"></script>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css" />
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" />

<style></style>
<script type="text/javascript">

    function imgHandler() {
       var input = document.createElement('input'); //建立 input file upload element

       input.setAttribute('type', 'file');
       input.setAttribute('accept', 'image/*');
       input.click();

       input.onchange = () => {
           var [file] = input.files;
           var range = this.quill.getSelection();

           if (/^image\//.test(file.type)) {
                 //後端上傳圖片
           }
       }
   }

   const quill = new Quill('#editor', {
       modules: {
           syntax: true,
           toolbar: {
               container: '#toolbar-container', // Quill formats
               handlers: { image: imgHandler } //綁定圖片上傳事件
           },
       },
       theme: 'snow'
   });

    //設定後端內容至Quill Contents
    var content = quill.clipboard.convert({ html: `@Html.Raw(@Model.htmltext.Replace("<br />","<p>"))` });
    quill.setContents(content, 'silent');

   function save() {
        quill.root.innerHTML; //取得 Quill html內容
   }      
</script>