### Install and Configure NodeMoverModule
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/node-mover.md
Example of how to install and configure the NodeMoverModule in a Quill editor form. Customize selection and drop indicator colors.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\NodeMoverModule;
use Ehyiah\QuillJsBundle\Form\QuillType;
$builder->add('content', QuillType::class, [
'modules' => [
new NodeMoverModule([
'borderColor' => '#007bff', // Optional: customize the selection frame color
'dropIndicatorColor' => '#ff0000' // Optional: customize the drop line color
]),
],
]);
```
--------------------------------
### Example: Rich Toolbar Configuration
Source: https://context7.com/ehyiah/ux-quill/llms.txt
This example demonstrates a comprehensive toolbar configuration using various QuillGroup::build instances for different functionalities. Ensure all necessary DTOs and modules are imported.
```php
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\AlignField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\BackgroundColorField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\ColorField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\DirectionField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\FontField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\HeaderField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\HeaderGroupField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\IndentField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\ListField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\ScriptField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\SizeField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\BlockQuoteField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\BoldField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\CleanField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\CodeBlockField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\CodeField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\DividerField; // auto-imports DividerModule
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\EmojiField; // auto-imports EmojiModule
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\FormulaField; // requires KaTeX
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ImageField; // auto-imports ImageSelectionModule
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ImageGalleryField; // auto-imports ImageGalleryModule
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ItalicField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\LinkField; // auto-imports LinkAttributesModule
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\PageBreakField; // auto-imports PageBreakModule
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\StrikeField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\TableField; // auto-imports TableModule
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\UnderlineField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\VideoField;
// Example: rich toolbar
'quill_options' => [
QuillGroup::build(
new BoldField(),
new ItalicField(),
new UnderlineField(),
new StrikeField(),
new BlockQuoteField(),
new CodeField(),
),
QuillGroup::build(
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
new SizeField(),
new AlignField(AlignField::ALIGN_FIELD_OPTION_CENTER),
),
QuillGroup::build(
new ListField(ListField::LIST_FIELD_OPTION_ORDERED),
new ListField(ListField::LIST_FIELD_OPTION_BULLET),
new ListField(ListField::LIST_FIELD_OPTION_CHECK),
new IndentField(IndentField::INDENT_FIELD_OPTION_PLUS),
new IndentField(IndentField::INDENT_FIELD_OPTION_MINUS),
),
QuillGroup::build(
new LinkField(),
new ImageField(),
new VideoField(),
new TableField(),
new EmojiField(),
new FormulaField(),
new DividerField(),
new PageBreakField(),
new CleanField(),
),
],
```
--------------------------------
### Install ehyiah/ux-quill Bundle
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Steps to install the bundle using Composer and configure for AssetMapper or Webpack Encore.
```bash
# Step 1 – require the PHP package
composer require ehyiah/ux-quill
# Step 2a – AssetMapper (no further steps needed)
# The importmap is populated automatically.
# Step 2b – Webpack Encore (recompile assets)
yarn install --force && yarn watch
# or
npm install --force && npm run watch
```
--------------------------------
### Configuration: JSON Upload Handler
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/image-upload.md
Example configuration for setting up a JSON upload handler. This specifies the upload endpoint and how to extract the image URL from the JSON response.
```php
'quill_extra_options' => [
'upload_handler' => [
'type' => 'json',
'upload_endpoint' => '/my-custom-endpoint/upload',
'json_response_file_path' => 'file.url'
]
],
```
--------------------------------
### Install Dependencies with NPM
Source: https://github.com/ehyiah/ux-quill/blob/main/README.md
If you are using webpack encore, run these commands after composer require. Not needed with AssetMapper.
```sh
npm install --force
npm run watch
```
--------------------------------
### QuillJS Configuration with Image Gallery
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/image-gallery.md
Example of how to configure the Quill editor to include the Image Gallery module and its toolbar button.
```APIDOC
## QuillJS Configuration with Image Gallery
This example demonstrates how to add the Image Gallery module to your Quill editor configuration.
### Usage
```php
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ImageGalleryField;
use Ehyiah\QuillJsBundle\DTO\Modules\ImageGalleryModule;
use Ehyiah\QuillJsBundle\Form\QuillType;
$builder->add('content', QuillType::class, [
'quill_options' => [
['bold', 'italic'],
[new ImageGalleryField()], // Position the button in the toolbar
],
'modules' => [
new ImageGalleryModule(options: [
'listEndpoint' => '/api/media/list',
'searchEndpoint' => '/api/media/search',
'buttonTitle' => 'Browse Media Library',
'messageTitleOption' => 'Select an image for your article',
]),
],
]);
```
### Parameters
- **quill_options**: An array of toolbar options, including the `ImageGalleryField` to display the button.
- **modules**: Configuration for the `ImageGalleryModule` with specific API endpoints and display options.
```
--------------------------------
### Build Toolbar Group with Headers and Text Formatting
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/quill-options.md
Create multiple toolbar groups to organize different types of fields. This example demonstrates a group for headers and another for bold and italic text.
```php
QuillGroup::build(
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
)
QuillGroup::build(
new BoldField(),
new ItalicField(),
)
```
--------------------------------
### Configure ReadTimeModule with Custom Options
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/read-time.md
Example of how to instantiate the ReadTimeModule with custom words per minute and a target element for displaying the reading time. Ensure this module is added to the 'modules' option.
```php
'modules' => [
new ReadTimeModule([
'wpm' => '250',
'target' => '#reading-time-display',
]),
],
```
--------------------------------
### Install Dependencies with Yarn
Source: https://github.com/ehyiah/ux-quill/blob/main/README.md
If you are using webpack encore, run these commands after composer require. Not needed with AssetMapper.
```sh
yarn install --force
yarn watch
```
--------------------------------
### Install QuillJs Bundle with Composer
Source: https://github.com/ehyiah/ux-quill/blob/main/README.md
Use this command to require the bundle in your Symfony project.
```sh
composer require ehyiah/ux-quill
```
--------------------------------
### Configure SmartLinksModule with Custom Regex
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/smart-links.md
Manually add the SmartLinksModule to your application's modules and provide a custom regular expression to detect links. This example shows how to configure the `linkRegex` option.
```php
'modules' => [
new SmartLinksModule(options: [
'linkRegex' => '/https?:\]\[^\]\]+/',
]),
],
```
--------------------------------
### Listening to Image Gallery Events
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/image-gallery.md
Example of how to attach an event listener to the Quill container to react when an image is selected from the gallery.
```javascript
document.querySelector('.ql-container').addEventListener('quill:gallery:image-inserted', (e) => {
console.log('Image selected:', e.detail.image);
});
```
--------------------------------
### Symfony Controller for Image Gallery API
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/image-gallery.md
Example Symfony controller implementing the listing and search API endpoints required by the Image Gallery module.
```APIDOC
## Symfony Controller for Image Gallery API
This controller provides the necessary API endpoints for the Image Gallery module to list and search media.
### Endpoints
#### `GET /api/media/gallery/list`
Lists media items with pagination.
##### Parameters
- **page** (int) - Optional - The page number to retrieve. Defaults to 1.
##### Response (Success - 200)
- **data** (array) - An array of media objects, each containing `url`, `thumbnail`, and `title`.
- **links** (object) - Contains `next` and `prev` URLs for pagination.
##### Response Example
```json
{
"data": [
{
"url": "https://picsum.photos/id/11/400/400",
"thumbnail": "https://picsum.photos/id/11/200/200",
"title": "Image #1"
}
],
"links": {
"next": "/api/media/gallery/list?page=2",
"prev": null
}
}
```
#### `GET /api/media/gallery/search`
Searches for media items. In this example, it defaults to the list endpoint.
##### Parameters
- **term** (string) - Optional - The search term.
- **page** (int) - Optional - The page number to retrieve. Defaults to 1.
##### Response (Success - 200)
Returns the same structure as the list endpoint.
```
--------------------------------
### Extend Quill Controller with Custom Keyboard and Clipboard
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/advanced/extend-stimulus-controller.md
Create a custom Stimulus controller that extends the default Quill controller. This example demonstrates adding a new keyboard binding for bold text and a custom clipboard matcher.
```javascript
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 instance 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);
});
}
}
```
--------------------------------
### Build Toolbar Group with Headers
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/quill-options.md
Use QuillGroup::build to create a toolbar group containing header fields. This example shows how to add two different header options side by side.
```php
QuillGroup::build(
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
)
```
--------------------------------
### Configure STTModule in Quill Editor
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/stt.md
This example shows how to integrate the STTModule into a Quill editor form. It demonstrates setting various configuration options for language, continuous recognition, visualizer, and custom button/label texts. Ensure the Web Speech API is supported by the browser.
```php
use Ehyiah\QuillJsBundle\Form\QuillType;
use Ehyiah\QuillJsBundle\DTO\Modules\STTModule;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content', QuillType::class, [
'quill_options' => [
QuillGroup::buildWithAllFields()
],
'modules' => [
new STTModule(
language: 'fr-FR', // French language recognition
continuous: true, // Auto-restart after pauses
visualizer: true, // Show audio visualizer
waveformColor: '#4285f4', // Blue gradient color
histogramColor: '#25D366', // Green accent color
debug: false, // Disable debug logs
buttonTitleStart: 'Start voice dictation',
buttonTitleStop: 'Stop voice dictation',
titleInactive: 'Voice recognition inactive',
titleStarting: 'Initializing...',
titleActive: 'Listening to your voice...',
),
],
])
;
}
```
--------------------------------
### Configure Quill Modules in PHP
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules.md
Example of how to instantiate and configure Quill modules directly within a PHP form configuration array. This includes custom modules like SyntaxModules and parameterized modules like TableModule.
```php
'modules' => [
new SyntaxModules(),
new TableModule(
'menus' => ['column', 'row', 'merge', 'table', 'cell', 'wrap', 'copy', 'delete'],
'toolbarTable' => 'true', // must be set to true to show the table toolbar options in TableModule
'language' => 'fr_FR',
),
],
```
--------------------------------
### Configuration: JSON Upload Handler with JWT Security
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/image-upload.md
Example configuration for a JSON upload handler that includes JWT authentication. This adds an 'Authorization: Bearer' header to the upload request.
```php
'quill_extra_options' => [
'upload_handler' => [
'type' => 'json',
'upload_endpoint' => '/my-custom-endpoint/upload',
'json_response_file_path' => 'file.url',
'security' => [
'type' => 'jwt',
'jwt_token' => 'my_jwt_token',
],
]
],
```
--------------------------------
### Configure AutosaveModule with Custom Options
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/autosave.md
Example of how to add the AutosaveModule to Quill's modules with custom options for interval, restore type, and notification text.
```php
'modules' => [
new AutosaveModule(options: [
'interval' => 3000,
'restore_type' => 'manual',
'notificationText' => 'Un texte non enregistré a été trouvé.',
'restoreButtonLabel' => 'Restaurer',
'ignoreButtonLabel' => 'Ignorer',
]),
],
```
--------------------------------
### Configure LinkAttributeModule with Custom Labels
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/link-attributes.md
This example shows how to configure the LinkAttributeModule with custom labels for the 'Open in new tab', 'No follow', and 'OK' buttons. This is useful for internationalization or specific UI requirements.
```php
[
new LinkAttributesModule(options: [
'openInNewTabLabel' => 'Ouvrir dans un nouvel onglet',
'noFollowLabel' => 'Lien No-follow (SEO)',
'saveButtonLabel' => 'Valider',
]),
],
?>
```
--------------------------------
### PHP: Returning Simple JSON Response
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/image-upload.md
Example of returning a simple JSON HTTP response containing only the image URL. This is used when 'json_response_file_path' is null and the response is a direct JSON string.
```php
return new JsonResponse('https://my-website/public/assets/my-uploaded-image.jpg');
```
--------------------------------
### Multiple Mention Modules with Unique Names
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/mention.md
Implement multiple Mention Modules for different purposes (e.g., users and tags) by providing unique names starting with 'mention-'. This allows distinct triggers and data sources for each.
```php
'modules' => [
new MentionModule(name: 'mention-users', options: [
'trigger' => '@',
'remote_url' => '/api/users/search?q={query}',
]),
new MentionModule(name: 'mention-tags', options: [
'trigger' => '#',
'data' => [
['id' => 'tech', 'value' => 'technology'],
['id' => 'news', 'value' => 'news'],
],
]),
],
```
--------------------------------
### Enable Markdown Shortcuts with MarkdownModule
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules.md
Integrate MarkdownModule to enable automatic formatting for headers, lists, and blockquotes as you type.
```php
new MarkdownModule(),
```
--------------------------------
### Configure QuillType in Symfony Form
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Example of using QuillType in a Symfony form, defining toolbar options and editor-level settings.
```php
use Ehyiah\QuillJsBundle\Form\QuillType;
use Ehyiah\QuillJsBundle\DTO\QuillGroup;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\BoldField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ItalicField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\LinkField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ImageField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\HeaderField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\AlignField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\ListField;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ArticleFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('content', QuillType::class, [
// Toolbar: two groups separated by a visual divider
'quill_options' => [
QuillGroup::build(
new BoldField(),
new ItalicField(),
new LinkField(),
),
QuillGroup::build(
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
new AlignField(),
new ListField(ListField::LIST_FIELD_OPTION_ORDERED),
new ListField(ListField::LIST_FIELD_OPTION_BULLET),
),
QuillGroup::build(new ImageField()),
],
// Editor-level settings
'quill_extra_options' => [
'height' => '400px',
'theme' => 'snow', // 'snow' or 'bubble'
'placeholder' => 'Write your article here…',
'style' => 'class', // 'class' or 'inline'
'read_only' => false,
],
]);
}
}
```
--------------------------------
### Configure ImageGalleryModule
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Set up the ImageGalleryModule to open a modal for image selection and upload. Configure the list and search endpoints, and customize modal titles and placeholders. Requires ImageGalleryField in quill_options.
```php
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ImageGalleryField;
use Ehyiah\QuillJsBundle\DTO\Modules\ImageGalleryModule;
$builder->add('content', QuillType::class, [
'quill_options' => [
['bold', 'italic'],
[new ImageGalleryField()],
],
'modules' => [
new ImageGalleryModule(options: [
'listEndpoint' => '/api/media/list', // mandatory
'searchEndpoint' => '/api/media/search', // optional
'messageTitleOption' => 'Media Library',
'messageSearchPlaceholderOption' => 'Search images…',
'buttonTitle' => 'Browse Media',
]),
],
]);
// Required API response format for listEndpoint / searchEndpoint:
// GET /api/media/list?page=1
// {
// "data": [
// { "url": "https://…/full.jpg", "thumbnail": "https://…/thumb.jpg", "title": "Sunset" }
// ],
// "links": { "next": "/api/media/list?page=2", "prev": null }
// }
// Gallery events (JavaScript):
// document.querySelector('.ql-container').addEventListener('quill:gallery:image-inserted', e => {
// console.log('Inserted image:', e.detail.image);
// });
```
--------------------------------
### Configure ReadTimeModule with Custom Options
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules.md
Instantiate ReadTimeModule with custom words per minute and a target element for displaying the reading time.
```php
new ReadTimeModule([
'wpm' => '250',
'target' => '#reading-time-display',
]),
```
--------------------------------
### Initialize Counter Module with Custom Labels
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/counter.md
Configure the Counter module to display both word and character counts with custom labels. Ensure the module is added to the editor's modules option.
```php
'modules' => [
new CounterModule(options: [
'words' => true,
'words_label' => 'Mots : ',
'characters' => true,
'characters_label' => 'Caractères : ',
]),
],
```
--------------------------------
### Mention Module with Remote Search (AJAX)
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/mention.md
Set up the Mention Module to fetch suggestions dynamically from a remote URL using AJAX. Configure the trigger character, remote URL with a {query} placeholder, minimum characters for triggering, and maximum results.
```php
'modules' => [
new MentionModule(options: [
'trigger' => '#',
'remote_url' => '/api/tags/search?q={query}',
'min_chars' => 2,
'max_results' => 5,
]),
],
```
--------------------------------
### Configure MentionModule with Multiple Triggers
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Enable multiple mention triggers (e.g., '@' for users and '#' for tags) by instantiating MentionModule multiple times with distinct names and configurations.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\MentionModule;
// Multiple triggers (@users and #tags)
$builder->add('content', QuillType::class, [
'modules' => [
new MentionModule(name: 'mention-users', options: [
'trigger' => '@',
'remote_url' => '/api/users/search?q={query}',
]),
new MentionModule(name: 'mention-tags', options: [
'trigger' => '#',
'data' => [
['id' => 'php', 'value' => 'PHP'],
['id' => 'ux', 'value' => 'Symfony UX'],
],
]),
],
]);
```
--------------------------------
### QuillAdminField with Custom Options
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/easyadmin.md
Demonstrates how to use QuillAdminField with custom options, building a specific Quill toolbar configuration using QuillGroup and various field types.
```php
QuillAdminField::new('quill')
->setFormTypeOptions([
'quill_options' =>
QuillGroup::build(
new BoldField(),
new ItalicField(),
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
)
])
```
--------------------------------
### Integrating Quill Modules in a Form
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/index.md
Example of how to add custom and built-in modules to a Quill editor instance within a Symfony form. Ensure necessary module classes are imported.
```php
use Ehyiah\QuillJsBundle\Form\QuillType;
use Ehyiah\QuillJsBundle\DTO\Modules\STTModule;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content', QuillType::class, [
'quill_options' => [
//
],
'modules' => [
new SyntaxModules(),
new TableModule(
'menus' => ['column', 'row', 'merge', 'table', 'cell', 'wrap', 'copy', 'delete'],
'toolbarTable' => 'true', // must be set to true to show the table toolbar options in TableModule
'language' => 'fr_FR',
),
],
//
])
;
}
```
--------------------------------
### Basic Mention Module with Static Data
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/mention.md
Configure the Mention Module to use a predefined list of items for suggestions. Ensure the data items have 'id' and 'value' properties.
```php
'modules' => [
new MentionModule(options: [
'trigger' => '@',
'data' => [
['id' => 1, 'value' => 'Matthieu'],
['id' => 2, 'value' => 'Gemini'],
['id' => 3, 'value' => 'Symfony'],
],
]),
],
```
--------------------------------
### Configure CounterModule for Word and Character Counts
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Use CounterModule to display real-time word and character counts. Configure which counts to display, their labels, and optionally, the DOM elements for display. Listen to count updates via JavaScript events.
```php
$builder->add('content', QuillType::class, [
'modules' => [
new CounterModule(options: [
'words' => true,
'words_label' => 'Words: ',
'words_container' => 'word-count-display', // DOM element ID (optional)
'characters' => true,
'characters_label' => 'Characters: ',
'characters_container' => '', // empty = auto-created below editor
]),
],
]);
```
```javascript
// document.addEventListener('quill:counter:words-update', e => console.log(e.detail.value));
// document.addEventListener('quill:counter:characters-update', e => console.log(e.detail.value));
```
--------------------------------
### PHP: Returning JSON Response with Nested URL
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/image-upload.md
Example of returning a JSON HTTP response where the image URL is nested within a JSON object. The 'json_response_file_path' option should be set to 'file.url' to extract the URL.
```php
return new JsonResponse([
'file' => [
'url' => 'https://my-website/public/assets/my-uploaded-image.jpg',
]
]);
```
--------------------------------
### Configure SmartLinksModule for Auto-Converting URLs
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Automatically converts typed URLs into clickable links when the user presses Space, Enter, or Tab. Uses a default link pattern, which can be customized via 'linkRegex'.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\SmartLinksModule;
$builder->add('content', QuillType::class, [
'modules' => [
new SmartLinksModule(options: [
'linkRegex' => '/https?:\[^\s]+/', // default pattern
]),
],
]);
```
--------------------------------
### PHP: Returning Plain Text Response
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/image-upload.md
Example of returning a plain text HTTP response containing the image URL. This is used when the upload endpoint directly returns the URL without a JSON structure.
```php
return new Response('https://my-website/public/assets/my-uploaded-image.jpg');
```
--------------------------------
### Configure MentionModule for Static Data
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Set up the MentionModule to trigger autocomplete suggestions with static data. Specify the trigger character, data, minimum characters to type, and maximum results.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\MentionModule;
// Static data
$builder->add('content', QuillType::class, [
'modules' => [
new MentionModule(options: [
'trigger' => '@',
'data' => [
['id' => 1, 'value' => 'Alice'],
['id' => 2, 'value' => 'Bob'],
],
'min_chars' => 1,
'max_results' => 5,
]),
],
]);
```
--------------------------------
### Configure FullScreenModule for Editor Maximization
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Adds a fullscreen toggle button to the toolbar using the quill-toggle-fullscreen-button library. Customize the button title and optionally provide custom SVG HTML for the icon.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\FullScreenModule;
$builder->add('content', QuillType::class, [
'modules' => [
new FullScreenModule([
'buttonTitle' => 'Maximize editor',
'buttonHTML' => '', // optional custom icon
]),
],
]);
```
--------------------------------
### Use Legacy ResizeModule with ImageSelectionModule Disabled
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Disable the default ImageSelectionModule and enable the legacy ResizeModule by setting ImageSelectionModule options to false and adding ResizeModule.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\ImageSelectionModule;
use Ehyiah\QuillJsBundle\DTO\Modules\ResizeModule;
// Use the legacy resize module instead
$builder->add('content', QuillType::class, [
'modules' => [
new ImageSelectionModule(['options' => false]), // disable new module
new ResizeModule(), // enable old one
],
]);
```
--------------------------------
### Customize Mention Appearance with CSS
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/mention.md
Style the inserted mentions and the suggestion list using CSS. The default classes are `.ql-mention`, `.ql-mention-list`, `.ql-mention-item`, and `.ql-mention-item.selected`.
```css
.ql-editor .ql-mention {
background-color: #fce4ec;
color: #c2185b;
}
```
--------------------------------
### Configure Quill Editor in a Form
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/quill-options.md
Integrate Quill editor into a Symfony form by defining 'quill_options'. This example shows how to add multiple toolbar groups, including inline fields, header fields, and a custom image gallery field.
```php
use Ehyiah\QuillJsBundle\Form\QuillType;
use Ehyiah\QuillJsBundle\DTO\QuillGroup;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\BoldField;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\ItalicField;
use Ehyiah\QuillJsBundle\DTO\Fields\BlockField\HeaderField;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('myField', QuillType::class, [
'quill_options' => [
QuillGroup::build(
new BoldField(),
new ItalicField(),
),
QuillGroup::build(
new HeaderField(HeaderField::HEADER_OPTION_1),
new HeaderField(HeaderField::HEADER_OPTION_2),
),
// Add all built-in available fields at once (includes Table, Emoji, etc.)
QuillGroup::build(
new ImageGalleryField(),
),
]
])
;
}
```
--------------------------------
### Configure NodeMoverModule for Block Reordering
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Provides a gutter toolbar for selected blocks, enabling drag-and-drop reordering, duplication, and deletion. Can be customized with colors and options, or disabled entirely.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\NodeMoverModule;
// Default (always on) – no configuration needed.
// Customise options:
$builder->add('content', QuillType::class, [
'modules' => [
new NodeMoverModule([
'borderColor' => '#007bff',
'dropIndicatorColor'=> '#ff0000',
'duplicate' => true,
]),
],
]);
// Disable entirely:
$builder->add('content', QuillType::class, [
'modules' => [
new NodeMoverModule(['active' => false]),
],
]);
```
--------------------------------
### MentionModule with Remote Search and Custom Options
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules.md
Configure MentionModule for remote data fetching via AJAX. Specify the remote URL, minimum characters for triggering, and maximum results.
```php
new MentionModule(options: [
'trigger' => '#',
'remote_url' => '/api/tags/search?q={query}',
'min_chars' => 2,
'max_results' => 5,
]),
```
--------------------------------
### Initialize PasteSanitizerModule with plain_text option
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/paste-sanitizer.md
Configure the PasteSanitizerModule to always paste content as plain text by setting the `plain_text` option to `true`. This module must be manually added to the `modules` array.
```php
'modules' => [
new PasteSanitizerModule(options: [
'plain_text' => true,
]),
],
```
--------------------------------
### Implement Custom Inline and Module Fields
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Implement `QuillInlineFieldInterface` for custom toolbar buttons and `QuillFieldModuleInterface` to auto-register required modules. The `getOption()` method must return the Quill format/blot name.
```php
namespace App\Quill\Fields;
use Ehyiah\QuillJsBundle\DTO\Fields\Interfaces\QuillInlineFieldInterface;
use Ehyiah\QuillJsBundle\DTO\Fields\Interfaces\QuillFieldModuleInterface;
use App\Quill\Modules\CustomHighlightModule;
// Simple inline field (no module dependency)
class HighlightField implements QuillInlineFieldInterface
{
public function getOption(): string
{
return 'highlight'; // must match the Quill format/blot name
}
}
// Field that auto-imports a module
class CustomEmojiField implements QuillInlineFieldInterface, QuillFieldModuleInterface
{
public function getOption(): string
{
return 'custom-emoji';
}
public static function importModules(): array
{
return [CustomHighlightModule::class]; // ModuleInterface implementations
}
}
```
```php
// Usage
$builder->add('content', QuillType::class, [
'quill_options' => [
QuillGroup::build(
new HighlightField(),
new CustomEmojiField(),
),
],
]);
```
```javascript
// Corresponding JavaScript (register the blot/module before Quill init):
// import Quill from 'quill';
// Quill.register('formats/highlight', HighlightBlot);
// Quill.register('modules/customHighlight', CustomHighlightModule);
```
--------------------------------
### Configure HtmlEditModule with Custom Options
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/html-edit.md
Instantiate the HtmlEditModule with custom options for button text and labels. This module must be manually added to the 'modules' option.
```php
'modules' => [
new HtmlEditModule(options: [
'buttonTitle' => 'Source HTML',
'okText' => 'Enregistrer',
'cancelText' => 'Annuler',
]),
],
```
--------------------------------
### Configure MentionModule for Remote AJAX Search
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Integrate the MentionModule with a remote AJAX endpoint for dynamic suggestions. Define the trigger character, the URL for the search query, and the minimum characters required to initiate the search.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\MentionModule;
// Remote AJAX search
// GET /api/users/search?q={query} → [{"id":1,"value":"Alice"},…]
$builder->add('content', QuillType::class, [
'modules' => [
new MentionModule(options: [
'trigger' => '@',
'remote_url' => '/api/users/search?q={query}',
'min_chars' => 2,
]),
],
]);
```
--------------------------------
### Configure Quill Editor Options
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Use 'quill_extra_options' to control the global appearance, behavior, and upload handler of a Quill editor instance. Options include theme, placeholder, read-only mode, custom icons, and asset injection.
```php
use Ehyiah\QuillJsBundle\Form\QuillType;
$builder->add('body', QuillType::class, [
'quill_extra_options' => [
// Visual
'height' => '350px', // CSS height (px, em, %, etc.)
'theme' => 'snow', // 'snow' (toolbar) | 'bubble' (inline)
'placeholder' => 'Start typing…',
'style' => 'inline', // 'class' (default) | 'inline' (for emails/RSS)
// Behavior
'debug' => 'error', // 'error' | 'warn' | 'log' | 'info'
'read_only' => false,
'use_semantic_html' => false, // use getSemanticHTML() instead of innerHTML
// Custom toolbar icons (SVG strings, keyed by format name)
'custom_icons' => [
'bold' => '',
'italic' => '',
],
// Inject additional CSS/JS (avoid with Turbo — inject directly instead)
'assets' => [
'styleSheets' => ['https://cdn.example.com/custom-quill.css'],
'scripts' => ['https://cdn.example.com/custom-quill.js'],
],
// Image upload handler (see Image Upload section)
'upload_handler' => [
'type' => 'json',
'upload_endpoint' => '/api/upload/image',
'json_response_file_path'=> 'file.url',
],
],
]);
```
--------------------------------
### Inject Custom CSS and JS Assets
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/configuration/extra-options.md
Configure custom stylesheets and scripts to be injected into the editor. Be cautious of race conditions with turbo.
```php
'quill_extra_options' => [
'assets' => [
'styleSheets' => [
"https://example.com/custom.css",
],
'scripts' => [
"https://example.com/custom.js",
]
],
]
```
--------------------------------
### Configure ReadTimeModule
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Use the ReadTimeModule to estimate and display reading time. Configure words per minute, labels, and thresholds for different read time statuses.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\ReadTimeModule;
$builder->add('content', QuillType::class, [
'modules' => [
new ReadTimeModule([
'wpm' => 250,
'label' => '⏱ Est. read: ~ ',
'suffix' => ' min',
'readTimeOk' => 5, // ≤5 min → green
'readTimeMedium' => 8, // ≤8 min → orange, >8 min → red
'target' => '#reading-time-display', // DOM element ID
]),
],
]);
```
--------------------------------
### Initialize Stimulus Application
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/easyadmin.md
This JavaScript snippet initializes the Stimulus application. It's typically placed in a main admin JavaScript file.
```javascript
// start the Stimulus application
import './bootstrap';
```
--------------------------------
### Configure TableModule for Table Functionality
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Provides full table support, auto-imported when TableField is used. Configure table menus, toolbar visibility, and language. Requires 'quill-table-better' and TableField in quill_options.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\TableModule;
use Ehyiah\QuillJsBundle\DTO\Fields\InlineField\TableField;
$builder->add('content', QuillType::class, [
'quill_options' => [
QuillGroup::build(new TableField()),
],
'modules' => [
new TableModule(options: [
'menus' => ['column', 'row', 'merge', 'table', 'cell', 'wrap', 'copy', 'delete'],
'toolbarTable' => true, // show table toolbar
'language' => 'en_US',
]),
],
]);
```
--------------------------------
### Disable ImageSelectionModule and Enable ResizeModule
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/image-selection.md
Disable the ImageSelectionModule by setting its options to false and enable the legacy ResizeModule if the old image resizing behavior is preferred. This allows for a fallback to previous functionality.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\ImageSelectionModule;
use Ehyiah\QuillJsBundle\DTO\Modules\ResizeModule;
// ...
'modules' => [
new ImageSelectionModule(['options' => false]), // Disable the new module
new ResizeModule(), // Enable the old one
],
```
--------------------------------
### Configure HistoryModule for Undo/Redo Behavior
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Manages Quill's native undo/redo functionality. Options include setting the delay for grouping changes, the maximum number of undo steps, and whether to track only user-initiated changes.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\HistoryModule;
$builder->add('content', QuillType::class, [
'modules' => [
new HistoryModule(options: [
'delay' => 1000, // ms to group changes into one undo step
'maxStack' => 100, // maximum undo steps
'userOnly' => true, // only track user-initiated changes
]),
],
]);
```
--------------------------------
### Configure ImageSelectionModule with Custom Options
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/image-selection.md
Manually configure the ImageSelectionModule with custom options for border color, button labels, and alignment tooltips. This is useful when the module is not auto-imported or when specific customizations are needed.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\ImageSelectionModule;
// ...
'modules' => [
new ImageSelectionModule([
'borderColor' => '#ff0000',
'buttonBeforeLabel' => 'Insert Before',
'alignLabels' => [
'center' => 'Centrer l\'image',
],
]),
],
```
--------------------------------
### Configure JSON Image Upload Handler
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Set up a JSON upload handler for images, specifying the endpoint, the JSON path to the returned URL, and security details like JWT. This allows server-side image storage instead of base64 encoding.
```php
$builder->add('content', QuillType::class, [
'quill_extra_options' => [
'upload_handler' => [
'type' => 'json', // 'json' | 'form'
'upload_endpoint' => '/api/media/upload',
'json_response_file_path' => 'data.url', // JSON path to the returned URL
'security' => [
'type' => 'jwt', // 'jwt' | 'basic' | 'custom_header'
'jwt_token' => 'eyJhbGciOiJIUz…',
],
],
],
]);
```
--------------------------------
### Symfony Controller for Image Gallery API
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules/image-gallery.md
Implement a Symfony controller to handle image listing and search requests for the Image Gallery module. Includes pagination logic for the list endpoint.
```php
get('page', 1);
$perPage = 10;
$total = 30; // Total images in your database
$images = [];
for ($i = 0; $i < $perPage; $i++) {
$id = (($page - 1) * $perPage) + $i + 1;
if ($id > $total) break;
$images[] = [
'url' => sprintf('https://picsum.photos/id/%d/400/400', 10 + $id),
'thumbnail' => sprintf('https://picsum.photos/id/%d/200/200', 10 + $id),
'title' => "Image #$id",
];
}
$baseUrl = '/api/media/gallery/list';
$hasNext = ($page * $perPage) < $total;
$hasPrev = $page > 1;
return new JsonResponse([
'data' => $images,
'links' => [
'next' => $hasNext ? "$baseUrl?page=" . ($page + 1) : null,
'prev' => $hasPrev ? "$baseUrl?page=" . ($page - 1) : null,
],
]);
}
#[Route('/search', name: 'api_media_search')]
public function search(Request $request): JsonResponse
{
$term = $request->get('term', '');
$page = (int) $request->get('page', 1);
// In a real application, you would filter your query with $term
// and return the appropriate paginated results.
// Example with mock data:
return $this->list($request);
}
}
```
--------------------------------
### Basic QuillAdminField Usage
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/easyadmin.md
This is the basic usage of the QuillAdminField in your EasyAdmin configuration. It assumes the asset is correctly configured.
```php
QuillAdminField::new('quill')
```
--------------------------------
### Configure STTModule for Speech-to-Text
Source: https://context7.com/ehyiah/ux-quill/llms.txt
Adds a microphone button for real-time voice dictation using the Web Speech API. Requires Chrome, Edge, or Safari. Emits various JavaScript events for listening status and results.
```php
use Ehyiah\QuillJsBundle\DTO\Modules\STTModule;
$builder->add('content', QuillType::class, [
'modules' => [
new STTModule(
language: 'en-US',
continuous: true,
visualizer: true,
waveformColor: '#4285f4',
histogramColor: '#25D366',
debug: false,
buttonTitleStart: 'Start dictation',
buttonTitleStop: 'Stop dictation',
titleInactive: 'Voice: off',
titleStarting: 'Initializing…',
titleActive: 'Listening…',
),
],
]);
// JavaScript events emitted:
// quill:stt:result → { text: string, isFinal: bool }
// quill:stt:listening-start → {}
// quill:stt:listening-stop → {}
// quill:stt:error → { error: any }
```
--------------------------------
### Configure AutosaveModule
Source: https://github.com/ehyiah/ux-quill/blob/main/docs/guide/modules.md
Use AutosaveModule to automatically save editor content to localStorage. Configure the save interval and restoration behavior.
```php
'modules' => [
new AutosaveModule(options: [
'interval' => 3000,
'restore_type' => 'manual',
]),
],
```