TinyMCE

TinyMCE là một trình soạn thảo WYSIWYG được xây dựng trên nền tảng Javascript, được phát triển dưới dạng mã nguồn mở theo giấy phép MIT bởi Tiny Technologies Inc.

TinyMCE cho phép người dùng tạo và định dạng văn bản trực tiếp trên trình duyệt web. 

TinyMCE được thiết kế để tích hợp với các thư viện JavaScript như React, Vue.js, AngularJS và Bootstrap cũng như các hệ thống quản lý nội dung như Joomla và WordPress.

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 TinyMCE 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 TinyMCE 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 TinyMCE 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

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 là 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 TinyMCE

Chúng ta cần phải thêm plugin Image và Media vào TinyMCE. Để làm được điều này, chúng ta sẽ import plugin Image và Media vào tập tin tinymce.js trong thư mục /resources/js:

import 'tinymce/plugins/image';
import 'tinymce/plugins/media';

Tiếp theo, chúng ta sẽ tiến hành viết mã nguồn để tích hợp elFinder vào TinyMCE. Đoạn mã nguồn này sẽ được sử dụng cho tùy chọn file_picker_callback của TinyMCE:

/* Import TinyMCE */
import tinymce from 'tinymce';

/* Default icons are required. After that, import custom icons if applicable */
import 'tinymce/icons/default/icons.min.js';

/* Required TinyMCE components */
import 'tinymce/themes/silver/theme.min.js';
import 'tinymce/models/dom/model.min.js';

/* Import a skin (can be a custom skin instead of the default) */
import 'tinymce/skins/ui/oxide/skin.js';

/* Import plugins */
import 'tinymce/plugins/advlist';
import 'tinymce/plugins/code';
import 'tinymce/plugins/emoticons';
import 'tinymce/plugins/emoticons/js/emojis';
import 'tinymce/plugins/link';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/table';
import 'tinymce/plugins/image';
import 'tinymce/plugins/media';

/* content UI CSS is required */
import 'tinymce/skins/ui/oxide/content.js';

/* The default content CSS can be changed or replaced with appropriate CSS for the editor content. */
import 'tinymce/skins/content/default/content.js';


window.addEventListener('DOMContentLoaded', () => {
    const elfinder_browser = async (callback, value, meta) => {
        try {
            const details = await new Promise((resolve, reject) => {
                tinymce.activeEditor.windowManager.openUrl({
                    title: 'elFinder (ManhDanBlogs)',
                    url: '/elfinder/tinymce5',
                    onMessage: (dialogApi, details) => {
                        resolve(details);
                        dialogApi.close();
                    },
                });
            });
            if (details.mceAction === 'fileSelected') {
                const file = details.data.file;
                // Make file info
                const info = file.name;
                // Provide file and text for the link dialog
                if (meta.filetype === 'file') {
                    callback(file.url, {text: info, title: info});
                }
                // Provide image and alt text for the image dialog
                if (meta.filetype === 'image') {
                    callback(file.url, {alt: info});
                }
                // Provide alternative source and posted for the media dialog
                if (meta.filetype === 'media') {
                    callback(file.url);
                }
            }
        } catch (error) {
            console.error("Error:", error);
        }
    };
    tinymce.init({
        selector: 'textarea#tinymce',
        height: 500,
        plugins: 'advlist code emoticons link lists table image media',
        toolbar: 'bold italic | bullist numlist | link emoticons | image media',
        skin_url: 'default',
        content_css: 'default',
        file_picker_callback : elfinder_browser
    });
});

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

Sau khi đã hoàn thành các bước trên, giờ là lúc để chúng ta cùng nhau khám phá thành quả công sức của mình.

Hãy thực thi lệnh sau để tiến hành build TinyMCE 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 Has Many Through Eloquent Relationship

Laravel Has Many Through Eloquent Relationship

Has Many Through Relationship hơi phức tạp để hiểu một cách đơn giản, nó sẽ cung cấp cho chúng ta một con đường tắt để có thể truy cập dữ liệu của một quan hệ xa xôi thông qua một mối quan hệ trung gi...

Integrating elFinder Into CKEditor 5 In Laravel

Integrating elFinder Into CKEditor 5 In Laravel

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...

Laravel TinyMCE 6 Image Upload

Laravel TinyMCE 6 Image Upload

TinyMCE TinyMCE là một trình soạn thảo  WYSIWYG  được xây dựng trên nền tảng Javascript, được phát triển dưới dạng mã nguồn mở theo giấy phép  MIT  bởi Tiny Technologies Inc. TinyMCE cho phép ngư...

Laravel UI Password Reset Expired

Laravel UI Password Reset Expired

Trong thư viện laravel/ui, thì chức năng password reset dù cho token có hết hạn thì vẫn có truy cập vào trang password reset, đến khi bạn submit form thì mới thông báo là token đã hết hạn. Nhưng có mộ...

Google Drive as Filesystem in Laravel

Google Drive as Filesystem in Laravel

Đối với một số dự án, bạn cần phải sử dụng Google Drive (với tài khoản @gmail.com cá nhân hoặc tài khoản G Suite) làm nhà cung cấp bộ nhớ trong các dự án Laravel. Trong bài đăng này, tôi sẽ hướng d...

Integrating Google Gemini AI in Laravel

Integrating Google Gemini AI in Laravel

Google Gemini Gemini là một mô hình trí tuệ nhân tạo mới mạnh mẽ từ Google không chỉ có khả năng hiểu văn bản mà còn có thể hiểu cả hình ảnh, video và âm thanh. Gemini là một mô hình đa phương ti...

Laravel Socialite Login With Github

Laravel Socialite Login With Github

GitHub GitHub là một nền tảng phát triển phần mềm trực tuyến. Nó được sử dụng để lưu trữ, theo dõi và cộng tác trong các dự án phần mềm. Nó giúp các nhà phát triển dễ dàng chia sẻ các tập tin mã...

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 Jobs Batching

Laravel Jobs Batching

Phiên bản Laravel 8 đã được phát hành với một tính năng mà rất nhiều người trong chúng ta đã chờ đợi rất lâu đó là Jobs Batching, nó cho phép chúng ta thực hiện nhiều công việc trong cùng một lúc và t...

ManhDanBlogs