ehyiah / ux-quill
Symfony UX Bundle,用于使用Quill JS wysiwyg文本编辑器,支持全面且易于定制的功能
Requires
- php: >=8.1.0
- symfony/form: ^6.1|^7.0
- symfony/html-sanitizer: ^6.1|^7.0
- symfony/stimulus-bundle: ^2.9.1
- symfony/twig-bundle: ^6.1|^7.0
- twig/extra-bundle: ^2.12|^3.0
Requires (Dev)
- dg/bypass-finals: ^1.6
- easycorp/easyadmin-bundle: ^4.7
- friendsofphp/php-cs-fixer: ^3.1
- friendsoftwig/twigcs: ^6.4
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
- phpstan/phpstan-symfony: ^1.3
- phpunit/phpunit: ^9.5
- symfony/asset-mapper: ^6.3|^7.0
- symfony/browser-kit: ^6.1|^7.0
- symfony/framework-bundle: ^6.1|^7.0
README
Symfony UX Bundle实现Quill JS Wysiwyg https://quilljs.com/
如果您需要一个易于使用的WYSIWYG(无需复杂配置)并将其集成到symfony项目中,这就是您需要的。
2.x.x标签覆盖了新的Quill v2
1.x.x标签覆盖了Quill v1.3.7
安装
第1步:要求bundle
composer require ehyiah/ux-quill
如果您正在使用AssetMapper组件,您已完成!
第2步:接下来运行(如果您正在使用webpack encore,使用AssetMapper时不需要)
yarn install --force yarn watch
或者
npm install --force npm run watch
已完成,您现在可以使用QuillType来构建QuillJs WYSIWYG
您可以在同一页面上添加任意多的WYSIWYG字段,就像任何普通字段一样。
基本用法
在表单中使用QuillType。它就像一个经典的Type一样工作,但它有更多的选项:例如
use Ehyiah\QuillJsBundle\Form\QuillType; public function buildForm(FormBuilderInterface $builder, array $options) { $builder // ... ->add('myField', QuillType::class) ; }
显示结果
在一个twig模板中
- 如果您使用默认的类样式选项,您可能需要将内容封装起来,以便quill样式表能够应用,如下所示
<div class="ql-snow">
<div class="ql-editor">
{{ myField|raw }}
</div>
</div>
- 如果您使用内联样式选项,只需
<div>{{ myField|raw }}</div>
当然,您可以根据安全原因对HTML进行清理,但不要忘记根据您的需求进行配置,因为默认情况下会移除许多HTML标签和样式元素。同样也适用于您的表单配置
'sanitize_html' => false,
'sanitizer' => 'my_awesome_sanitizer_config
对于最基本的情况,您只需这样做。
自定义选项
use Ehyiah\QuillJsBundle\Form\QuillType; public function buildForm(FormBuilderInterface $builder, array $options) { $builder // ... ->add('myField', QuillType::class, [ 'quill_extra_options' => [ 'height' => '780px', 'theme' => 'snow', 'placeholder' => 'Hello Quill WYSIWYG', ], 'quill_options' => [ // this is where you customize the WYSIWYG by creating one or many Groups // if you create many groups, they will be separated by a space in the toolbar // you can also build your groups using a classic array but many classes are covering every Quill available Fields (see below for detailed list) QuillGroup::build( new BoldField(), new ItalicField(), // and many more ), QuillGroup::build( new HeaderField(HeaderField::HEADER_OPTION_1), new HeaderField(HeaderField::HEADER_OPTION_2), // and many more ), // Or add all available fields at once QuillGroup::buildWithAllFields() ] ]) ; }
quill_options
在这里,您将选择在WYSIWYG中显示哪些元素。您可以构建一个数组,就像您遵循QuillJs官方文档那样做,或者使用更方便的自动完成,使用此bundle中的许多Fields对象。
QuillGroup::build(
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
)
此示例将显示并排的h1和h2标题选项
QuillGroup::build(
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
)
QuillGroup::build(
new BoldField(),
new ItalicField(),
)
此示例将显示并排的h1和h2标题选项,以及包含粗体和斜体字段的另一个组
您可以添加任意多的组,或者如果您不需要WYSIWYG选项之间有间隔,只需添加一个即可。
可用字段
- 以下是从QuillJS (https://v2.quilljs.com/docs/formats)提供的可用字段列表
- 以下是从社区提供的字段列表,这些字段在QuillJS中不可用
quill_extra_options
图像上传处理
在ImageField中:QuillJS默认将图像转换为base64编码的文件以保存您的文件。但是,您可以指定一个自定义端点来处理图像上传,并通过响应传递整个公开URL以显示图像。
- 目前处理
- 在json中发送数据以base64编码
- 或者
- 在multipart/form-data中
'quill_extra_options' => [
///
'upload_handler' => [
'type' => 'json',
// or 'type' => 'form',
'path' => '/my-custom-endpoint/upload',
]
],
- 您的端点必须返回文件的完整URL,例如
https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/JavaScript-logo.png/480px-JavaScript-logo.png
- 在json模式下,通过调用$request->getContent()和content-type头部中的application/json获取的数据将如下所示
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlgAAAJYCAQAAAAUb1BXAAAABGdBTUEAALGPC/xhBQAAACyygyyioiBqFCUIKC64x..."
- 在表单模式下,您将在content-type头部中找到multipart/form-data,并且文件将存在于$request->files中,名称为file
- 然后您就可以像处理FileType一样处理它。
模块
https://quilljs.com/docs/modules
您可以在此选项字段中添加/自定义quill模块。您可以创建自己的模块类,它们需要实现ModuleInterface
并添加名称和选项属性。
扩展Quill stimulus控制器
如果您需要扩展内置控制器的默认行为,这是可能的。例如:您需要修改模块注册和/或添加自定义JavaScript来修改quill的行为。
一些模块,如Keyboard
和Clipboard
,需要编写自定义JavaScript。这样做最简单的方法是创建一个自定义刺激控制器来扩展默认行为。
在您的项目中创建一个新的刺激控制器
// quill_extended_controller.js import { Controller } from '@hotwired/stimulus'; export default class extends Controller { connect() { this.element.addEventListener('quill:connect', this._onConnect); } disconnect() { this.element.removeEventListener('quill:connect', this._onConnect); } _onConnect(event) { // The quill has been created console.log(event.detail); // You can access the quill instance using the event detail let quill = event.detail; // e.g : if you want to add a new keyboard binding quill.keyboard.addBinding({ key: 'b', shortKey: true }, function(range, context) { this.quill.formatText(range, 'bold', true); }); // e.g if you want to add a custom clipboard quill.clipboard.addMatcher(Node.TEXT_NODE, (node, delta) => { return new Delta().insert(node.data); }); } }
然后在您的表单中
use Ehyiah\QuillJsBundle\Form\QuillType; public function buildForm(FormBuilderInterface $builder, array $options) { $builder // ... ->add('myField', QuillType::class, [ 'attr' => [ 'data-controller' => 'quill-extended', ] // ... ; }
Easyadmin集成
- 首先在assets目录中创建一个quill-admin.js
// start the Stimulus application
import './bootstrap';
当使用AssetMapper时
在importmap.php中创建一个新的条目(键必须为quill-admin,因为它是内置QuillAdminField使用的名称)
'quill-admin' => [
'path' => './assets/quill-admin.js',
'entrypoint' => true,
],
这样就完成了。但请参阅以下内容
警告 => 目前似乎easyadmin与->addAssetMapperEntries()函数存在一个问题,因为我无法让它按预期工作。一个快速的解决方案是在您的crudControllers中添加
public function configureAssets(Assets $assets): Assets
{
$assets->addAssetMapperEntry('quill-admin');
return parent::configureAssets($assets); // TODO: Change the autogenerated stub
}
或者
在您的仪表板中
public function configureAssets(): Assets
{
$assets = Assets::new();
$assets->addAssetMapperEntry('quill-admin');
return $assets;
}
当使用webpack时
- 在webpack.config中创建一个新条目(条目名称必须是quill-admin,因为它是内置QuillAdminField使用的名称)
.addEntry('quill-admin', './assets/quill-admin.js')
别忘了重新编译资源(yarn build/watch或npm等效)。
EasyAdmin
然后您可以使用QuillAdminField如下所示
QuillAdminField::new('quill')
或者添加自定义选项,就像处理普通类型一样
QuillAdminField::new('quill')
->setFormTypeOptions([
'quill_options' =>
QuillGroup::build(
new BoldField(),
new ItalicField(),
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
)
])