Closed jeffreyzant closed 5 years ago
How do you use a custom plugin with Vue Froala Wysiwyg ?
Hey, thanks for replying. I suppose by adding them to the webpack file. But that would mean i'll have to fork this and change the package. There has to be a better way to do this? I've looked in the repo you mentioned but I could not find any helpful examples.
I've tried a couple of things to make it work, but maybe i'm just missing out on a small piece.
To help with this question, I need to know how you created a custom plugin and use it without Nova. Maybe you used specific tutorial etc. In Nova you can add additional scripts and styles like this:
Nova::serving(function (ServingNova $event) {
Nova::style('custom-styles', public_path('css/nova/custom-styles.css'));
Nova::script('custom-script', public_path('js/nova/custom-script.js'));
});
I am trying to use this plugin: https://github.com/ecoach-lms/froala-audio
I have tried adding the .css and .js after I ran the javascript through webpack to add jQuery. But I am receiving a JS error that the Froala Editor is not found (or not accessible).
froala-audio-script:87 Uncaught TypeError: Cannot read property 'POPUP_TEMPLATES' of undefined
at froala-audio-script:87
at Object.<anonymous> (froala-audio-script:815)
at Object.405 (froala-audio-script:816)
at __webpack_require__ (froala-audio-script:20)
at Object.404 (froala-audio-script:71)
at __webpack_require__ (froala-audio-script:20)
at froala-audio-script:63
at froala-audio-script:66
$.extend($.FE.POPUP_TEMPLATES, {
'audio.insert': '[_BUTTONS_][_BY_URL_LAYER_][_UPLOAD_LAYER_][_PROGRESS_BAR_]',
'audio.edit': '[_BUTTONS_]'
});
I'm using the following code:
mix.styles('node_modules/froala-audio/froala-audio.css', 'public/css/vendor/froala_audio.min.css');
mix.js('node_modules/froala-audio/froala-audio.js', 'public/js/vendor/froala_audio.min.js')
.autoload({
jquery: ['$', 'jQuery', 'jquery', 'window.jQuery'],
});`
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
parent::boot();
Nova::serving(function (ServingNova $event) {
Nova::style('froala-audio-styles', public_path('css/vendor/froala_audio.min.css'));
Nova::script('froala-audio-script', public_path('js/vendor/froala_audio.min.js'));
});
}
Looks like this plugin not working properly with vue-froala-wysiwyg
. I have tried to include it directly into the nova-froala-field
package (which use vue-froala-wysiwyg
) and it crashed with TypeError: $ is undefined
. It depends on jQuery without any checks.
That's cause within your webpack.mix.js you are only including jQuery on $ and on jQuery. But this plugin requires it as window.jQuery. You'll only have to add that to your Webpack file to make that part (jQuery) work..
Just npm install froala-audio
Add this to the PluginsLoader.js
await import(
'froala-audio/froala-audio'
)
Change the webpack file to:
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
})
npm run production
And it will work.
You are right. But as I can see webpack has some limitations for dynamic imports to be able to easy import of custom plugins without changing PluginsLoader.js
directly.
Will investigate this question deeper and welcome any implementation ideas here or in PR.
I've thought about a couple of solutions, but I don't think it's doable without compiling the assets outside the package. Would using an Artisan command to (re)compile the assets and publishing them to the /public folder be a likeable solution?
@jeffreyzant Will try to find a less complex solution
There is no way for simple integration of the 3rd party or hand-made plugin. You'll have to re-compile the assets of this extension with manual adjustments.
I have developed the following console command to do so:
<?php
namespace App\Nova\Extensions\Froala\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
/**
* BuildFroalaAssets builds custom assets for "froala/nova-froala-field" extension.
*
* Unfortunally this is the only way to apply custom plugins to the Froala editor.
*
* ```php
* class NovaServiceProvider extends NovaApplicationServiceProvider
* {
* public function boot()
* {
* parent::boot();
*
* Nova::serving(function (ServingNova $event) {
* Nova::script('nova-froala-field', storage_path('nova/froala/dist/js/field.js'));
* });
* }
*
* public function register()
* {
* $this->commands([
* BuildFroalaAssets::class,
* ]);
* }
* }
* ```
*
* @see https://novapackages.com/packages/froala/nova-froala-field
*/
class BuildFroalaAssets extends Command
{
/**
* {@inheritdoc}
*/
protected $signature = 'nova:build-froala-assets';
/**
* {@inheritdoc}
*/
protected $description = 'Build custom assets for Nova Froala editor field';
/**
* @var string path to the Nova Froala field extension.
*/
protected $srcPath;
/**
* @var string path used for the assets build.
*/
protected $buildPath;
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct();
$this->srcPath = base_path('vendor/froala/nova-froala-field');
$this->buildPath = storage_path('nova/froala');
}
public function handle()
{
$this->info('Building Froala assets...');
$this->prepareSourceFiles();
$this->patchSourceFiles();
$this->buildAssets();
$this->info('...complete.');
}
protected function prepareSourceFiles()
{
$this->info('Prepare source files...');
if (! file_exists($this->buildPath)) {
File::makeDirectory($this->buildPath, 0775, true);
}
$names = [
'resources',
'.babelrc',
'package.json',
'webpack.mix.js',
];
foreach ($names as $name) {
$srcName = $this->srcPath.DIRECTORY_SEPARATOR.$name;
$dstName = $this->buildPath.DIRECTORY_SEPARATOR.$name;
if (is_dir($srcName)) {
File::copyDirectory($srcName, $dstName);
} else {
File::copy($srcName, $dstName);
}
}
$resourcePath = realpath(__DIR__.'/../..');
$names = [
'resources/js/custom-plugins.js',
];
foreach ($names as $name) {
File::copy($resourcePath.DIRECTORY_SEPARATOR.$name, $this->buildPath.DIRECTORY_SEPARATOR.$name);
}
$this->info('...done.');
}
protected function patchSourceFiles()
{
$this->info('Patching source files...');
$fieldSrcFile = $this->buildPath.'/resources/js/field.js';
$patchContent = "\n\nrequire('./custom-plugins');";
file_put_contents($fieldSrcFile, file_get_contents($fieldSrcFile).$patchContent);
$this->info('...done.');
}
protected function buildAssets()
{
$this->info('Building assets...');
passthru('(cd '.escapeshellarg($this->buildPath).'; yarn install; yarn run prod;)');
}
}
Custom plugin JS code placed at 'custom-plugins.js' may look like following:
/**
* @see https://www.froala.com/wysiwyg-editor/docs/concepts/custom/button
*/
import FroalaEditor from 'froala-editor';
FroalaEditor.DefineIcon('insert', {NAME: 'plus', SVG_KEY: 'add'});
FroalaEditor.RegisterCommand('insert', {
title: 'Insert HTML',
focus: true,
undo: true,
refreshAfterCallback: true,
callback: function () {
this.html.insert('My New HTML');
}
});
Great! I think it will be useful If you need to integrate a custom plugin.
Is it possible to include custom third party Froala plugins? So this means not only embedly etc.
Sadly, I can't find anything for this in the documentation.