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

Markitup Bundle Laravel Package

sonata-project/markitup-bundle

Sonata MarkItUpBundle integrates the markItUp! universal markup editor into Symfony applications, offering a ready-to-use form type and Sonata Admin integration for configurable rich text and markup editing.

View on GitHub
Deep Wiki
Context7

Getting Started

The first thing to internalize: this is not a Laravel package. It is a deprecated, archived Symfony2 bundle (1 star, 0 dependents) that does one job — ship the markItUp jQuery editor into a Symfony app and wire it to a form type and a config tree. There is no service provider, no facade, no config publish, and composer require sonata-project/markitup-bundle in a Laravel project will pull Symfony wiring you cannot boot.

So "getting started" means treating it as an asset source and a reference implementation, not a dependency.

Minimal steps:

  1. Read the repo's Resources/public/ directory first. That is where the actual value lives: jquery.markitup.js, the skins (simple, markitup), and the sets (markdown, html, bbcode, dotclear, textile). Nothing else in the bundle matters to you.
  2. Copy the JS/CSS/sets you need into resources/js/vendor/markitup/ and resources/css/vendor/markitup/ — do not vendor the whole bundle.
  3. Install the real runtime dependency, jQuery, since markItUp has no vanilla-JS build:
    npm i jquery
    
  4. Initialize it against a plain <textarea>, not a Symfony form field:
    import $ from 'jquery';
    import '/resources/js/vendor/markitup/jquery.markitup.js';
    import markdownSet from '/resources/js/vendor/markitup/sets/markdown/set.js';
    
    $(function () {
        $('.markitup').markItUp(markdownSet);
    });
    
  5. Your first real use case: a Markdown body field on an Article/Post form, with a toolbar (bold, link, image, preview). Ship the textarea, let markItUp decorate it, and handle preview separately (see below).

If you opened this repo hoping for a drop-in Laravel editor integration, stop here and read the Gotchas section first — the maintenance math is bad. The rest of this document assumes you are deliberately extracting the editor anyway (legacy parity, a client's existing markup, or you genuinely like markItUp's sets model).

Implementation Patterns

Pattern 1 — Blade component wrapper. Encapsulate markup + init so pages stay clean.

{{-- resources/views/components/markdown-editor.blade.php --}}
@props(['name', 'value' => ''])
<textarea name="{{ $name }}" class="markitup" rows="12">{{ $value }}</textarea>

Then a single app.js that calls $('.markitup').markItUp(markdownSet). Keep the selector class-based so every editor on the page is covered by one call.

Pattern 2 — Per-set configuration. markItUp's entire configuration surface is the set object (mySettings). Do not try to replicate the Symfony bundle's YAML config tree (sonata_markitup.sets, default skin, etc.) in a Laravel config file — just export a JS object:

// resources/js/vendor/markitup/sets/markdown/custom.js
export default {
    nameSpace: 'markdown',
    previewParserPath: '/markdown/preview',
    previewParserVar: 'data',
    markupSet: [
        { name: 'Bold', key: 'B', openWith: '**', closeWith: '**' },
        { name: 'Link', key: 'L', openWith: '[', closeWith: '](url)' },
        { name: 'Preview', call: 'preview' },
    ],
};

This is the bundle's real extension point, and it survives outside Symfony untouched.

Pattern 3 — Server-side preview endpoint. previewParserPath expects a URL that accepts POSTed text and returns HTML. In Laravel:

Route::post('/markdown/preview', function (Request $request) {
    $html = Str::markdown($request->string('data')->toString());
    return HtmlString::from($html); // or a sanitizer
});

Note the CSRF implication: markItUp POSTs via jQuery, so either include the token in $.ajaxSetup headers or exclude this route from CSRF (bootstrap/app.php → validateCsrfTokens(except: ['markdown/preview'])). Prefer the token.

Pattern 4 — Preview is cosmetic, rendering is authoritative. markItUp's preview is a convenience. Persist raw Markdown, convert on read (or on write into a body_html column), and always sanitize. The bundle does none of this for you — the Symfony side only rendered the textarea.

// FormRequest
'body' => ['required', 'string', 'max:65535'],

Pattern 5 — File/image insertion. If you wire the "image" toolbar button, it will insert a URL into the textarea. That means a separate upload endpoint returning { url }, and the button's beforeInsert/afterInsert callbacks doing the async work. This is the one place where markItUp's aging callback API gets awkward; budget time for it.

Pattern 6 — Incremental adoption. Do not retrofit every textarea. Add .markitup only to fields that store Markdown, and leave short fields (titles, slugs) plain — the toolbar is wasted UI there.

Gotchas and Tips

  • Deprecated and archived is not a soft warning. No security patches, no browser-compat fixes, and the underlying markItUp library is similarly dormant. If your threat model includes "editor XSS in 2027," this is not the choice. Treat the extracted JS as your code you now own.

  • Don't install the bundle to get the assets. Install it only if you want to git clone and copy; otherwise pull from the upstream markItUp repo. Composer-installing a Symfony bundle into Laravel adds dead Symfony packages to vendor/ and confuses composer why.

  • jQuery is non-negotiable. markItUp predates modern bundlers and frameworks. If your stack is Alpine + Livewire, you are now shipping two reactivity models on one page. Also make sure window.$/window.jQuery are set before the markItUp script executes — module load order is the #1 cause of "toolbar renders but does nothing."

  • Livewire / Turbo will break it. Any DOM morph or page swap replaces the textarea and drops the editor chrome. Re-initialize on navigation:

    document.addEventListener('livewire:navigated', () => $('.markitup').markItUp(markdownSet));
    

    And avoid wire:model on the same textarea if the editor mutates the DOM — bind to the underlying textarea on submit instead.

  • Vite asset handling. The sets reference skins via relative paths baked into the JS (/markitup/skins/simple/style.css). Either rewrite those paths in the copied files or publish the skins to public/ untouched. Vite's hashed filenames will break the internal path assumptions; static public/ placement is the pragmatic fix.

  • The Symfony config tree does not map. If you're porting an existing Symfony app, note that the bundle's YAML (default set, skin, per-form-type settings) was resolved server-side at render time. In Laravel you'll be doing it client-side in JS — accept that and keep one set file per editor flavour rather than inventing a config abstraction.

  • Debugging checklist, in order: (1) is jQuery loaded before markItUp? (2) does .markitup match an element at init time? (3) is the set object exported correctly (CommonJS vs ESM mismatch is common when copying legacy files)? (4) do the skin CSS files return 200 in the network tab? Most "broken editor" reports are one of these four.

  • Extension points beyond sets don't exist. There is no plugin API. If you need autosave, character counters, or drag-and-drop upload, you're writing it alongside the editor and hooking keyup/change on the textarea — exactly as you would with a bare textarea.

  • Migration path is cheap; keep it open. Because markItUp is a thin textarea decorator, swapping to EasyMDE or Toast UI later is a one-file change if you never let markItUp concepts leak into your Laravel code. Keep the contract: a <textarea> in, Markdown out, preview via HTTP endpoint. Do that and the deprecated dependency stays a replaceable implementation detail rather than a load-bearing wall.

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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels