CKEditor 5 

CKEditor 5 là một trình soạn thảo văn bản phong phú JavaScript với nhiều tính năng và khả năng tùy chỉnh.

CKEditor 5 có kiến trúc MVC hiện đại, mô hình dữ liệu tùy chỉnh và DOM ảo, mang lại hiệu suất và khả năng mở rộng vượt trội.

Tích hợp gốc với Angular, React và Vue.js có sẵn để thuận tiện cho bạn cũng như tương thích với Electron và các thiết bị di động (Android, iOS).

elFinder

elFinder là một trình quản lý tập tin mã nguồn mở dành cho web, được viết bằng JavaScript sử dụng jQuery UI.

elFinder được phát triển dựa trên cảm hứng từ sự tiện lợi và đơn giản của chương trình Finder trong hệ điều hành Mac OS X.

Để tìm hiểu thêm, bạn có thể tham khảo tại địa chỉ sau: https://github.com/Studio-42/elFinder

Thực hiện tích hợp elFinder vào CKEditor trong Laravel

Trước khi, bắt đầu thực hiện tính năng nay, bạn cần phải tích hợp CKEditor vào Laravel bằng Laravel Vite (Phiên bản được áp dụng trong bài viết là Laravel 10).

Nếu bạn chưa thực hiện thì có thể tham khảo lại bài viết Integrating CKEditor 5 In Laravel 10 Using Vite.

Cài đặt và cấu hình elFinder trong Laravel

Đầu tiên, chúng ta sẽ cài đặt thư viện Laravel elFinder vào dự án Laravel bằng lệnh sau:

composer require barryvdh/laravel-elfinder

Tiếp theo, chúng ta sẽ thêm ServiceProvider bên dưới vào phần providers trong tập tin cấu hình config/app.php:

Barryvdh\Elfinder\ElfinderServiceProvider::class

Trong trường hợp nếu dự án của bạn sử dụng Laravel 11.x trở lên, thì providers sẽ không còn được đăng kí trong tập tin config/app.php nữa, mà thay vào đó sẽ được đăng kí trong tập tin bootstrap/providers.php như sau:

<?php

return [
    App\Providers\AppServiceProvider::class,
    Barryvdh\Elfinder\ElfinderServiceProvider::class

];

Chúng ta sẽ sao chép assets của elFinder vào thư mục public của Laravel bằng lệnh sau:

php artisan elfinder:publish

Để dễ dàng thay đổi các cấu hình của elFinder trong tương lai, chúng ta nên sao chép tập tin cấu hình của elFinder vào thư mục config của Laravel bằng lệnh sau:

php artisan vendor:publish --provider='Barryvdh\Elfinder\ElfinderServiceProvider' --tag=config

✷ Sau khi chạy lệnh trên, nó sẽ tạo ra tập tin cấu hình config/elfinder.php 

Trong bài viết này, tôi sử dụng storage của Laravel, do đó cần phải tạo symbolic link từ thư mục public/storage đến storage/app/public bằng lệnh sau:

php artisan storage:link

Tiếp theo, chúng ta sẽ tiến hành bổ sung disk public vào phần disks trong tập tin cấu hình config/elfinder.php như sau:

/*
|--------------------------------------------------------------------------
| Filesystem disks (Flysytem)
|--------------------------------------------------------------------------
|
| Define an array of Filesystem disks, which use Flysystem.
| You can set extra options, example:
|
| 'my-disk' => [
|        'URL' => url('to/disk'),
|        'alias' => 'Local storage',
|    ]
*/
'disks' => [
     'public',
],

Trong bài viết này, chúng ta sẽ không tập trung vào thực hiện chức năng Authentication trong Laravel.

Vì vậy, chúng ta cần phải loại bỏ tùy chọn auth ra khỏi phần middleware trong tập tin cấu hình config/elfinder.php. Sau khi thực hiện, cấu hình sẽ được cập nhật như sau:

/*
|--------------------------------------------------------------------------
| Routes group config
|--------------------------------------------------------------------------
|
| The default group settings for the elFinder routes.
|
*/

'route' => [
    'prefix' => 'elfinder',
    'middleware' => array('web'), //Set to null to disable middleware filter
],

Tích hợp elFinder vào CKEditor

Phiên bản CKEditor 5, chúng ta sẽ không thể cài đặt trực tiếp elFinder được, mà chúng ta sẽ phải cài đặt elFinder thông qua plugin CKFinder.

Dưới đây là một danh sách plugin cần thiết cho mục đích này:

npm install --save @ckeditor/ckeditor5-image \
  @ckeditor/ckeditor5-adapter-ckfinder \
  @ckeditor/ckeditor5-ckfinder 

Tiếp theo, chúng ta sẽ chỉnh sửa tập tin ckeditor.js trong thư mục resources/js với nội dung như sau:

import { ClassicEditor as ClassicEditorBase } from '@ckeditor/ckeditor5-editor-classic';
import { Essentials } from '@ckeditor/ckeditor5-essentials';
import { Autoformat } from '@ckeditor/ckeditor5-autoformat';
import { Bold, Italic } from '@ckeditor/ckeditor5-basic-styles';
import { BlockQuote } from '@ckeditor/ckeditor5-block-quote';
import { Heading } from '@ckeditor/ckeditor5-heading';
import { Link } from '@ckeditor/ckeditor5-link';
import { List } from '@ckeditor/ckeditor5-list';
import { Paragraph } from '@ckeditor/ckeditor5-paragraph';
import { Image, ImageUpload } from '@ckeditor/ckeditor5-image';
import { CKFinderUploadAdapter} from '@ckeditor/ckeditor5-adapter-ckfinder';
import { CKFinder } from '@ckeditor/ckeditor5-ckfinder';


export default class ClassicEditor extends ClassicEditorBase {}

ClassicEditor.builtinPlugins = [
    Essentials,
    Autoformat,
    Bold,
    Italic,
    BlockQuote,
    Heading,
    Link,
    List,
    Paragraph,
    Image,
    ImageUpload,
    CKFinderUploadAdapter,
    CKFinder,
];

ClassicEditor.defaultConfig = {
    toolbar: {
        items: [
            'heading',
            '|',
            'bold',
            'italic',
            'link',
            'bulletedList',
            'numberedList',
            'blockQuote',
            'undo',
            'redo',
            'ckfinder'
        ]
    },
    language: 'en'
};

window['ClassicEditor'] = ClassicEditor;

Do thư viện Laravel elFinder chưa có hỗ trợ cài đặt cho CKEditor 5, nên mình đã viết thêm mã nguồn bổ sung để có thể cài đặt elFinder cho CKEditor 5 dễ dàng hơn.

Để tìm hiểu thêm về mã nguồn trên, bạn có thể tham khảo tại Github sau: https://github.com/manh-dan/laravel-elfinder-ckeditor

Đầu tiên, chúng ta sẽ download mã nguồn cài đặt elFinder cho CKEditor 5, bạn hãy thực hiện lệnh sau ở thư mục root của dự án Laravel:

curl https://raw.githubusercontent.com/manh-dan/laravel-elfinder-ckeditor/main/build.sh | bash

Tiếp theo, chúng ta sẽ sử dụng hàm include() của Laravel, để có thể include các tập tin CSS và JavaScript chính của elFinder.

@include('elfinder.setup')

Sau khi include các tập tin cần thiết, chúng ta mở tập tin welcome.blade.php trong thư mục resources/views và khởi tạo CKEditor kèm theo elFinder bằng mã nguồn bên dưới:

window.addEventListener("load", (e)=> {
    ClassicEditor
        .create(document.querySelector('#editor') , {
            toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'imageUpload', 'ckfinder', 'blockQuote', 'insertTable', 'mediaEmbed', 'undo', 'redo']
        } )
        .then(editor => {
            elFinder(editor)
        })
        .catch(error => {
            console.error( error );
        });
});

Cuối cùng, cũng trong tập tin welcome.blade.php, chúng ta thêm thẻ meta bên dưới vào thẻ head như sau:

<!DOCTYPE html>
<html lang="en">
<head>
    ...
    <meta name="csrf-token" content="{{ csrf_token() }}">
    ...
</head>
<body>
    ...
</body>
</html>

Sau khi thực hiện các thao tác trên, thì mã nguồn hoàn chỉnh của tập tin welcome.blade.php sẽ như sau:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="ManhDan Blogs">
    <meta name="author" content="ManhDan Blogs">
    <meta name="generator" content="ManhDan Blogs 0.84.0">
    <title>CKEditor 5 – Classic Editor</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link rel="icon" href="https://manhdandev.com/web/img/favicon.webp" type="image/x-icon"/>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    @include('elfinder.setup')
    @vite(['resources/css/ckeditor.css', 'resources/js/ckeditor.js'])
</head>
<body>
    <div class="col-lg-8 mx-auto p-3 py-md-5">
    <header class="d-flex align-items-center pb-3 mb-3 border-bottom">
        <a href="https://manhdandev.com" class="d-flex align-items-center text-dark text-decoration-none" target="_blank">
            <img src="https://manhdandev.com/web/img/logo.webp" width="100px" height="100px">
        </a>
    </header>
    <main>
        <div id="editor">
            <p>This is some sample content.</p>
        </div>
    </main>
    <footer class="pt-5 my-5 text-muted border-top">
        &copy;Copyright &copy;2023 All rights reserved | This template is made with
        <i class="fa fa-heart-o"></i> by <a href="https://blog.dane.dev/" rel="noopener" target="_blank">ManhDanBlogs</a>
    </footer>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        window.addEventListener("load", (e)=> {
            ClassicEditor
                .create(document.querySelector('#editor') , {
                    toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'imageUpload', 'ckfinder', 'blockQuote', 'insertTable', 'mediaEmbed', 'undo', 'redo']
                } )
                .then(editor => {
                    elFinder(editor)
                })
                .catch(error => {
                    console.error( error );
                });
        });
    </script>
</body>
</html>

Kết quả của công việc bạn đã làm đang chờ bạn khám phá!

Sau khi đã cùng nhau hoàn thành những bước trên, giờ đây chúng ta hãy cùng nhau khám phá và tận hưởng thành quả của công sức mình.

Hãy thực thi lệnh sau để tiến hành build CKEditor sử dụng Laravel Vite:

npm run build

Cuối cùng, chúng ta hãy mở trình duyệt lên và truy cập vào địa chỉ  http://127.0.0.1 để chiêm ngưỡng kết quả do chính bản thân chúng ta tạo ra 🤤🤤🤤🏆🍨🍨🍨.

CÓ THỂ BẠN QUAN TÂM

Laravel Queue Workers With Systemd

Laravel Queue Workers With Systemd

Systemd chủ yếu được sử dụng để quản lý các service trên môi trường Linux, nhưng nó cũng cho phép chúng ta quản lý các service với quyền không phải là root. Điều này, làm cho systemd trở thành một giả...

Laravel Many to Many Polymorphic Relationship

Laravel Many to Many Polymorphic Relationship

Many to many Polymorphic Relationship cũng hơi phức tạp để hiểu. Ví dụ: nếu bạn có bài post, video và tag, bạn cần kết nối với nhau theo yêu cầu là mọi bài đăng đều có nhiều tag và video cũng như vậy....

Generate PDF with Header and Footer on every page in Laravel

Generate PDF with Header and Footer on every page in Laravel

Hôm nay, trong bài viết này mình sẽ chia sẻ với các bạn cách dompdf mà header và footer sẽ được hiển thị ở tất cả các trang. Đây cũng là một vấn đề khá phổ biến, khi chúng ta phát triển các tính năng...

Laravel User Authentication

Laravel User Authentication

Trong hướng dẫn này, tôi sẽ hướng dẫn bạn xây dựng chức năng đăng nhập trong Laravel. Công bằng mà nói thì bạn có thể sử dụng Laravel UI hoặc JetStream để tự động tạo ra chức năng đăng nhập trong Lara...

Integrating CKFinder into CKEditor 5 in Laravel 11

Integrating CKFinder into CKEditor 5 in Laravel 11

CKEditor 5 CKEditor 5 là một trình soạn thảo văn bản phong phú JavaScript với nhiều tính năng và khả năng tùy chỉnh. CKEditor 5 có kiến trúc MVC hiện đại, mô hình dữ liệu tùy chỉnh và DOM ảo, mang...

How To Optimize Your Site With GZIP Compression

How To Optimize Your Site With GZIP Compression

GZIP là công nghệ nén thường được sử dụng để truyền dữ liệu một cách nhanh chóng qua Insternet. Hiện nay, GZIP là một tiêu chuẩn để nén các file trên trang web, đa số các website hiện nay hơn 99% sử d...

Laravel Validate Video Duration

Laravel Validate Video Duration

Đôi khi trong dự án, chúng ta cần xác định thời lượng video được phép upload lên server. Nhưng rất tiếc, Laravel không cung cấp validate xác định thời lượng video để chúng ta thực hiện được. Vì vậy, t...

Laravel Socialite Login With Gitlab

Laravel Socialite Login With Gitlab

GitLab GitLab là kho lưu trữ Git dựa trên web cung cấp các kho lưu trữ mở và riêng tư miễn phí, các khả năng theo dõi vấn đề và wiki. Đây là một nền tảng DevOps hoàn chỉnh cho phép các chuyên gia...

Laravel CKEditor 5 Image Upload

Laravel CKEditor 5 Image Upload

CKEditor 5CKEditor 5 là một trình soạn thảo văn bản phong phú JavaScript với nhiều tính năng và khả năng tùy chỉnh. CKEditor 5 có kiến trúc MVC hiện đại, mô hình dữ liệu tùy chỉnh và DOM ảo, mang...

ManhDanBlogs