Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Reference



STEP 1. Download CK Editor

We have to options

CKEditor5

The first option is to use online builder at Option 1) Download through CK Editor online builder: https://ckeditor.com/ckeditor-5/online-builder/You can select features what you want to have.

  • The benefit of the online-builder is that you

...

  • do not need to install NPM and all other necessary binaries to get what you want.
  • The below is the one I acquired at the online builder that does not include premium libraries that have to pay by the cases.
    ckeditor5-40.1.0_2023_12_09.zip
    ckeditor5-40.2.0-2023_12_22i.zip (Excluding Markdown, General HTML Support, Text part language, Style, Word Count, Watchdog)


By the model there are some options basically included as below:

Image Added

Reference link: https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/predefined-builds.html



STEP 2. Implement Code


Below is the simple test code. Note that you should change <the_folder_where_you_saved> to the correct location.

Unfortunately this does not gave me the correct result.

Option 2) Download through NPM

Below is my script to download the necessary assets

Code Block
#!/bin/bash
npm install --save @ckeditor/ckeditor5-build-classic

STEP 2.

Example of the simple editor from CDN

Code Block
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>CKEditor 5 – Classic editor</title>
    <script src="https://cdn.ckeditor.com/ckeditor5/40.1.0/classic/ckeditor.js"></script>
</<the_folder_where_you_saved>/ckeditor.js"></script>
</head>
<body>
    <h1>Classic editor</h1>
    <div id="editor">
        <p>This is some sample content.</p>
    </div>
    <script>
        ClassicEditor
            .create( document.querySelector( '#editor' ) )
            .catch( error => {
                console.error( error );
            } );
    </script>
</body>
</html>

Example of the full-featured editor from CDN


Below is including file uploading feature.

Code Block
languagexml
titleindex.html
<html>
	<head>
		<title>CKEditor 5 ClassicEditor build</title>
		
Code Block
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="stylesheet" type="text/css" href="styles.css">
	</head>
    	<body>
        <style>
            #container {
                width: 1000px;
                margin: 20px auto;
            }
            .ck-editor__editable[role="textbox"] {
                /* editing area */
                min-height: 200px;
            }
            .ck-content .image {
                /* block images */
                max-width: 80%;
                margin: 20px auto;
            }
        </style>
        <div id="container">
            <div id="editor">
            </div>
        </div>
        <!--
            The "super-build" of CKEditor 5 served via CDN contains a large set of plugins and multiple editor types.
            See https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/quick-start.html#running-a-full-featured-editor-from-cdn
        -->
        <script src="https://cdn.ckeditor.com/ckeditor5/40.1.0/super-build/ckeditor.js"></script>
        <!--
            Uncomment to load the Spanish translation
            <script src="https://cdn.ckeditor.com/ckeditor5/40.1.0/super-build/translations/es.js"></script>
        -->
        <script>
            // This sample still does not showcase all CKEditor 5 features (!)
            // Visit https://ckeditor.com/docs/ckeditor5/latest/features/index.html to browse all the features.
            CKEDITOR.ClassicEditor.create(document.getElementById("editor"), {
                // https://ckeditor.com/docs/ckeditor5/latest/features/toolbar/toolbar.html#extended-toolbar-configuration-format
                toolbar: {
                    items: [
                        'exportPDF','exportWord', '|',
                        'findAndReplace', 'selectAll', '|',
                        'heading', '|',
                        'bold', 'italic', 'strikethrough', 'underline', 'code', 'subscript', 'superscript', 'removeFormat', '|',
                        'bulletedList', 'numberedList', 'todoList', '|',
                        'outdent', 'indent', '|',
                        'undo', 'redo',
                        '-',
                        'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'highlight', '|',
                        'alignment', '|',
                        'link', 'insertImage', 'blockQuote', 'insertTable', 'mediaEmbed', 'codeBlock', 'htmlEmbed', '|',
                        'specialCharacters', 'horizontalLine', 'pageBreak', '|',
                        'textPartLanguage', '|',
                        'sourceEditing'
                    ],
                    shouldNotGroupWhenFull: true
                },
                // Changing the language of the interface requires loading the language file using the <script> tag.
                // language: 'es',
                list: {
                    properties: {
                        styles: true,
                        startIndex: true,
                        reversed: true
                    }
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#configuration
                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' }
                    ]
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/editor-placeholder.html#using-the-editor-configuration
                placeholder: 'Welcome to CKEditor 5!',
                // https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-family-feature
                fontFamily: {
                    options: [
                        'default',
                        'Arial, Helvetica, sans-serif',
                        'Courier New, Courier, monospace',
                        'Georgia, serif',
                        'Lucida Sans Unicode, Lucida Grande, sans-serif',
                        'Tahoma, Geneva, sans-serif',
                        'Times New Roman, Times, serif',
                        'Trebuchet MS, Helvetica, sans-serif',
                        'Verdana, Geneva, sans-serif'
                    ],
                    supportAllValues: true
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/font.html#configuring-the-font-size-feature
                fontSize: {
                    options: [ 10, 12, 14, 'default', 18, 20, 22 ],
                    supportAllValues: true
                },
                // Be careful with the setting below. It instructs CKEditor to accept ALL HTML markup.
                // https://ckeditor.com/docs/ckeditor5/latest/features/general-html-support.html#enabling-all-html-features
                htmlSupport: {
                    allow: [
                        {
                            name: /.*/,
                            attributes: true,
                            classes: true,
                            styles: true
                        }
                    ]
                },
                // Be careful with enabling previews
                // https://ckeditor.com/docs/ckeditor5/latest/features/html-embed.html#content-previews
                htmlEmbed: {
                    showPreviews: true
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/link.html#custom-link-attributes-decorators
                link: {
                    decorators: {
                        addTargetToExternalLinks: true,
                        defaultProtocol: 'https://',
                        toggleDownloadable: {
                            mode: 'manual',
                            label: 'Downloadable',
                            attributes: {
                                download: 'file'
                            }
                        }
                    }
                },
                // https://ckeditor.com/docs/ckeditor5/latest/features/mentions.html#configuration
                mention: {
                    feeds: [
                        {
                            marker: '@',
                            feed: [
                                '@apple', '@bears', '@brownie', '@cake', '@cake', '@candy', '@canes', '@chocolate', '@cookie', '@cotton', '@cream',
                                '@cupcake', '@danish', '@donut', '@dragée', '@fruitcake', '@gingerbread', '@gummi', '@ice', '@jelly-o',
                                '@liquorice', '@macaroon', '@marzipan', '@oat', '@pie', '@plum', '@pudding', '@sesame', '@snaps', '@soufflé',
                                '@sugar', '@sweet', '@topping', '@wafer'
                            ],
                            minimumCharacters: 1
                        }
                    ]
                },
                // The "super-build" contains more premium features that require additional configuration, disable them below.
                // Do not turn them on unless you read the documentation and know how to configure them and setup the editor.
                removePlugins: [
                    // These two are commercial, but you can try them out without registering to a trial.
                    // 'ExportPdf',
                    // 'ExportWord',
                    'AIAssistant',
                    'CKBox',
                    'CKFinder',
                    'EasyImage',
                    // This sample uses the Base64UploadAdapter to handle image uploads as it requires no configuration.
                    // https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/base64-upload-adapter.html
                    // Storing images as Base64 is usually a very bad idea.
                    // Replace it on production website with other solutions:
                    // https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/image-upload.html
                    // 'Base64UploadAdapter',
                    'RealTimeCollaborativeComments',
                    'RealTimeCollaborativeTrackChanges',
                    'RealTimeCollaborativeRevisionHistory',
                    'PresenceList',
                    'Comments',
                    'TrackChanges',
                    'TrackChangesData',
                    'RevisionHistory',
                    'Pagination',
                    'WProofreader',
                    // Careful, with the Mathtype plugin CKEditor will not load when loading this sample
                    // from a local file system (file://) - load this site via HTTP server if you enable MathType.
                    'MathType',
                    // The following features are part of the Productivity Pack and require additional license.
                    'SlashCommand',
                    'Template',
                    'DocumentOutline',
                    'FormatPainter',
                    'TableOfContents',
                    'PasteFromOfficeEnhanced'
                ]
            });
        </script>
    </body>
</html>

Implementing upload feature with CKEditor 5

		<div id="editor">
			
		</div>
		<script src="ck/ckeditor.js"></script>
		<script>
			ClassicEditor
				.create( document.querySelector( '#editor' ), {
					simpleUpload: {
						// The URL that the images are uploaded to.
						uploadUrl: 'upload.php',
					}
				} )
				.then( editor => {
					window.editor = editor;
				} )
				.catch( err => {
					console.error( err.stack );
				} );
		</script>
	</body>
</html>

You will need to have following upload.php to save the necessary files as planned.

Code Block
languagephp
titleupload.php
<?php
// Define file upload path 
$upload_dir = array( 
    'img'=> './', 
); 
 
// Allowed image properties  
$imgset = array( 
    'maxsize' => 5000, 
    'maxwidth' => 4096, 
    'maxheight' => 3000, 
    'minwidth' => 10, 
    'minheight' => 10, 
    'type' => array('bmp', 'gif', 'jpg', 'jpeg', 'png'), 
); 
 
// If 0, will OVERWRITE the existing file 
define('RENAME_F', 1); 
 
$site = ''; 
 
/** 
 * Set filename 
 * If the file exists, and RENAME_F is 1, set "img_name_1" 
 * 
 * $p = dir-path, $fn=filename to check, $ex=extension $i=index to rename 
 */ 
function setFName($p, $fn, $ex, $i){ 
    if(RENAME_F ==1 && file_exists($p .$fn .$ex)){ 
        return setFName($p, F_NAME .'_'. ($i +1), $ex, ($i +1)); 
    }else{ 
        return $fn .$ex; 
    } 
} 
 
$re = ''; 
if(isset($_FILES['upload']) && strlen($_FILES['upload']['name']) > 1) { 
 
    define('F_NAME', preg_replace('/\.(.+?)$/i', '', basename($_FILES['upload']['name'])));   
 
    // Get filename without extension 
    $sepext = explode('.', strtolower($_FILES['upload']['name'])); 
    $type = end($sepext);    /** gets extension **/ 
     
    // Upload directory 
    $upload_dir = in_array($type, $imgset['type']) ? $upload_dir['img'] : $upload_dir['audio']; 
    $upload_dir = trim($upload_dir, '/') .'/'; 
 
    // Validate file type 
    if(in_array($type, $imgset['type'])){ 
        // Image width and height 
        list($width, $height) = getimagesize($_FILES['upload']['tmp_name']); 
 
        if(isset($width) && isset($height)) { 
            if($width > $imgset['maxwidth'] || $height > $imgset['maxheight']){ 
                $re .= ' Width x Height = '. $width .' x '. $height .' >>> The maximum Width x Height must be: '. $imgset['maxwidth']. ' x '. $imgset['maxheight']; 
 
Code Block
languagexml
titleindex.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CKEditor 5 File Upload</title>
    <script src="https://cdn.ckeditor.com/ckeditor5/44.0.0/classic/ckeditor.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>
<body>
    <textarea id="editor"></textarea>

    <script>
        ClassicEditor
            .create(document.querySelector('#editor'), {
           } 
 
   // CKEditor configuration options
      if($width < $imgset['minwidth'] || $height  })< $imgset['minheight']){ 
            .catch(error => {
   $re .= ' Width x Height = '. $width .' x '. $height console.error(error);
            });

.' >>> The minimum Width x Height must be: '. $imgset['minwidth']. ' x '. $imgset['minheight']; 
           function uploadFile(file)} {
 
           const formData = new FormData();
 if($_FILES['upload']['size'] > $imgset['maxsize']*1000){ 
             formData.append('file', file);

            $.ajax({   $re .= ' >>> Maximum file size must be: '. $imgset['maxsize']. ' KB.'; 
            } 
   url: 'upload.php', // Your PHP script for handling} uploads
    }else{ 
        $re .= 'The typefile: 'POST',
                data: formData,'. $_FILES['upload']['name']. ' has not the allowed extension type.'; 
    } 
     
    // File upload processData:path false,
    $f_name = setFName($_SERVER['DOCUMENT_ROOT'] .'/'. $upload_dir, F_NAME, ".$type", 0); 
    $uploadpath contentType: false,
    = $upload_dir . $f_name; 
 
    // If no errors, upload the image, else, success:output functionthe (data)errors {
    if($re == ''){ 
             console.log('File uploaded successfully:', data);
  if(move_uploaded_file($_FILES['upload']['tmp_name'], $uploadpath)) { 
            $url  },
   = $upload_dir . $f_name; 
            $msg error: function (error) {
                    console.error('Error uploading file:', error);= F_NAME .'.'. $type .' successfully uploaded! >>> Size: '. number_format($_FILES['upload']['size']/1024, 2, '.', '') .' KB'; 
            $response = [ 
 }
            });
   'url' => $url 
  }

        // Listen for]; the
 'change' event on the file input in the}else{ editor
        document.querySelector('#editor input[type="file"]').addEventListener('change', (event) => {
$response = [ 
         const file = event.target.files[0];
    'error' => [ 
     if (file) {
             'message' =>  uploadFile(file);
   'Unable to upload the file!' 
         }
       ] });
    </script>
</body>
</html>
Code Block
languagephp
titleupload.php
<?php
// Check if the file was uploaded without errors
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
]; 
       $uploadDir = 'uploads/'; // Adjust the upload directory} 
    }else{ 
    $uploadFile   = $uploadDir$response .= basename($_FILES['file']['name']);

[ 
       // Move the uploaded file to the desired directory'error' => [ 
    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadFile)) {
        echo json_encode(['successmessage' => true,'Error: 'url' => $uploadFile]);
    } else {
.$re 
         echo json_encode(['success' => false, 'error' => 'Failed to move the uploaded file.']);   ] 
        ]; 
    } 
} else
 {
// Return response in JSON format 
echo json_encode(['success' => false, 'error' => 'File upload failed.']$response); 
}
?>