Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fm Summernote Bundle Laravel Package

helios-ag/fm-summernote-bundle

Symfony bundle that integrates the Summernote WYSIWYG editor with FM (FormManager), providing a ready-to-use form type and frontend assets for adding rich-text editing to textareas with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

This is still a Symfony bundle, not a Laravel package — 1.0 does not change that. There is no service provider, no config/summernote.php, and no package auto-discovery. The release notes are a Symfony-upgrade changelog (Add symfony bundle config, Symfony5 changes, Updates for sf6), not a Laravel feature drop. As a Laravel developer you still cannot meaningfully composer require this into a Laravel app: it pulls symfony/form, symfony/http-kernel, and Twig. Treat it as a reference implementation of "how to wire Summernote into a form framework."

What 1.0 does change: it is the first version that targets Symfony 5/6, and it finally ships a real bundle config tree instead of hardcoded defaults. That means there is now a config/packages/fm_summernote.yaml to configure — the thing that was previously guesswork.

If you are in a Symfony codebase (the audience this package actually serves):

composer require helios-ag/fm-summernote-bundle
  1. Register the bundle in config/bundles.php:

    FM\SummernoteBundle\FMSummernoteBundle::class => ['all' => true],
    
  2. Configure it under config/packages/fm_summernote.yaml. As of 1.0 the known keys are:

    • base_path — renamed from basePath in this release (see Gotchas)
    • language — new in 1.0, sets the editor UI language
    • include_jquery / include_bootstrap — asset injection toggles
    • front — new in 1.0, lets you supply a custom front/template

    Verify key names against vendor/helios-ag/fm-summernote-bundle/README.md — the README was touched in this release but has historically lagged the code.

  3. Render the editor assets once in your base layout, then swap a textarea for the bundle's form type:

    $builder->add('body', SummernoteType::class, ['attr' => ['rows' => 10]]);
    

First use case: identical to before — replacing a <textarea> in an admin CRUD form with a rich-text field, storing the resulting HTML in a TEXT column, and posting images to an upload endpoint. The new language option is the only thing that meaningfully changes day-one setup.

For the Laravel equivalent, skip the bundle entirely and take the 20-minute path: npm i summernote (or the CDN build), a Blade component, and a @push('scripts') init:

{{-- resources/views/components/summernote.blade.php --}}
<textarea name="{{ $name }}" id="{{ $id }}" {{ $attributes }}>{{ $slot }}</textarea>
@push('scripts')
<script>
  $('#{{ $id }}').summernote({
    height: {{ $height ?? 300 }},
    lang: '{{ $lang ?? 'en-US' }}',
    callbacks: {
      onImageUpload: files => uploadToLaravel(files, '#{{ $id }}')
    }
  });
</script>
@endpush

Note the parity: the bundle's new language config maps to Summernote's lang option plus a summernote-{lang}.js include, so if you replicate the feature in Blade you have to load that file yourself.

Implementation Patterns

Form-type pattern (Symfony). The bundle's core value is a SummernoteType that renders the textarea and emits the init script, so validation and data binding stay inside the Form component. Options you pass as attr typically bubble down to the JS init call, which is the cleanest way to vary toolbar per form.

Asset inclusion. Symfony bundles in this family usually expose a Twig helper or rely on you including the built assets manually — now governed by include_jquery / include_bootstrap / base_path in config. The safest pattern is to publish/copy the Summernote dist into your own asset pipeline once, set include_jquery: false, and only use the bundle for the form type. That avoids double-loading if you also add Summernote via npm/Encore/Webpack. The 1.0 config makes this easier to express than 0.2 did, but it still requires you to own the decision.

Language handling. New in 1.0: set language once in fm_summernote.yaml for the whole app. Summernote ships one JS file per locale, so if you disable the bundle's asset injection you must add the matching summernote-{lang}.js to your bundle yourself — the config key alone will not fetch it.

Custom front. Also new in 1.0: front lets you point the bundle at your own template instead of the shipped init.html.twig. This supersedes the old advice about overriding templates via templates/bundles/FMSummernoteBundle/ for most cases — prefer the config key, since it survives composer update without file-tree shadowing.

Image uploads. Summernote's onImageUpload callback expects a JSON response shaped like {"url": "https://.../image.jpg"} and nothing else. Two integration options:

  • Pair with FMElfinderBundle (same author, helios-ag) and point the callback at the elFinder connector route — this is the intended combination and the main reason people install this bundle.
  • Roll your own controller that persists the upload and returns ['url' => Storage::url($path)].

Laravel version of the upload callback, with the CSRF handling that Summernote does not do for you:

async function uploadToLaravel(files, editor) {
  for (const file of files) {
    const data = new FormData();
    data.append('image', file);
    const res = await fetch('/admin/uploads', {
      method: 'POST',
      headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content },
      body: data,
    });
    const { url } = await res.json();
    $(editor).summernote('insertImage', url);
  }
}

Storage and output. Always store the raw HTML and sanitize on render, never the reverse. In Laravel that means a purifier step (mews/purifier or symfony/html-sanitizer) in an accessor or Blade component, and {!! !!} only on the purified value. Symfony users should install html-sanitizer since the form type does not sanitize anything — 1.0 adds no sanitization.

Livewire / SPA interop. Because Summernote mutates the DOM behind the framework's back, bind it explicitly: initialize on Livewire.hook('morph.updated'), and push the editor's HTML back with $wire.set('body', $('#editor').summernote('code')) on change. Otherwise Livewire re-renders will silently discard edits.

Validation. Add a required rule plus a normalizer — an "empty" Summernote field submits <p><br></p>, not '':

protected function prepareForValidation(): void
{
    $this->merge([
        'body' => trim(strip_tags($this->body ?? '')) === '' ? null : $this->body,
    ]);
}

Gotchas and Tips

  • The basePath → base_path rename is the breaking change in 1.0. If you are upgrading from 0.2 and had basePath in your bundle config, the new config tree will ignore it — likely silently, leaving assets pointed at the wrong path. Grep your config/packages/ for basePath before anything else, and expect the failure mode to be "editor loads but plugins/CSS 404."
  • Still the wrong ecosystem. 1.0 is a maintenance release by the original author plus drive-by contributors; it is still a ~7-star, zero-dependent package with no community to lean on. Symfony 7/8 is not covered by these release notes (Symfony 5/6 only). Pin the version and read the changelog before every Symfony upgrade; do not plan an LTS migration around it.
  • jQuery 2.x compatibility is additive, not a modernisation. 1.0 explicitly added jQuery 2.x support — which tells you it is still a jQuery-era bundle. Classic Summernote (v1.x) is jQuery-based and some themes want Bootstrap. If your app is Alpine/Vue/React, you are adding jQuery back into the page for one widget — consider Summernote Lite (v0.8, no jQuery) or a modern editor instead.
  • Config key names are the moving target. This release renamed a key, added two, and shipped a whole new config tree. Dump your resolved config after upgrading (bin/console config:dump-reference fm_summernote) rather than trusting the README; documentation changes in this release were a single README.md edit.
  • Double-initialization. The most common failure is $(...).summernote is not a function, which almost always means the init script ran before summernote.min.js loaded. In Laravel, @push('scripts') ordering vs. your Vite bundle is the usual culprit; make the init a module import rather than an inline script.
  • Duplicate assets. If include_jquery/include_bootstrap are on and you bundle Summernote yourself, you get two copies and confusing "plugin already registered" errors. Pick one owner of the assets — with 1.0 that decision is now a config flag, so make it explicit.
  • CSRF on uploads. Summernote's default AJAX upload does not attach Laravel's token or Symfony's _token. A 419/403 on image upload with everything else working is this, 100% of the time.
  • {url: ...} shape is strict. Returning {"location": ...} or a bare string makes uploads fail silently with no console error. Log the response body when debugging.
  • front is the new extension point, and it is untested-by-the-community. Supplying a custom template is cleaner than shadowing templates/bundles/FMSummernoteBundle/, but it is a first-release feature with a single contributor and no docs beyond the config key. Diff your template against the shipped init.html.twig (which itself got a typo and a bracket fix in this release) so you do not inherit a bug that was just patched upstream.
  • Sanitization is on you. Neither framework nor this bundle sanitizes editor output, and 1.0 does not change that. XSS through a WYSIWYG is the single highest-risk item here; purify on output and restrict allowed tags (drop script, iframe, on* attributes) at the sanitizer config level.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel