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

Markdown Bundle Laravel Package

northernco/markdown-bundle

Northern Co's Markdown Bundle brings CommonMark-powered Markdown rendering to Laravel and PHP apps. Configure extensions, sanitize user input, and render Markdown in Blade views with simple helpers via a publishable config file. Composer-installable and framework-friendly, it keeps content parsing c...

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require northernco/markdown-bundle. This is a Symfony bundle, not a Laravel package, so Composer only gives you the classes — nothing auto-registers in a Laravel app.
  • Read in this order: README.md (for the Twig extension name and config keys), src/*Bundle.php, DependencyInjection/Configuration.php (the canonical config schema, e.g. html_input, allow_unsafe_links, max_nesting_level), and Resources/config/services.* (the actual service IDs and constructor arguments you'll need to reproduce).
  • First usable case: a body_markdown column on a Post model rendered to HTML in a Blade view. Wire the bundle's converter class manually in a service provider:
// config/markdown.php
return [
    'html_input' => 'strip',
    'allow_unsafe_links' => false,
];

// app/Providers/MarkdownServiceProvider.php
public function register(): void
{
    $this->app->singleton(Converter::class, function ($app) {
        return new Converter(config('markdown'));   // class from the bundle
    });
}
  • First render: {!! app(Converter::class)->convert($post->body_markdown) !!} — then immediately add sanitization (see Gotchas) before you ship.

Implementation Patterns

Service provider bridge. The bundle's Extension class builds a container definition you cannot reuse directly in Laravel. Two options: (a) port the few services.yaml definitions into a Laravel provider by hand — usually 1–3 lines of constructor arguments; or (b) boot a tiny ContainerBuilder, load the bundle's *Extension, and pull the service out. Option (a) is far less fragile for a 0-star bundle.

Blade ergonomics. Expose it as a directive and a helper so views stay readable:

Blade::directive('markdown', fn ($expr) => "<?php echo app(\\...\\Converter::class)->convert($expr); ?>");

Eloquent cast for the rendered form. Cache rendered HTML in a body_html column via an attribute cast or an updating observer, so list pages and APIs never parse on read:

protected static function booted(): void
{
    static::saving(function (Post $post) {
        $post->body_html = app(Converter::class)->convert($post->body_markdown);
    });
}

Versioned cache for expensive documents. Key on sha1($source . json_encode(config('markdown'))) so a config tweak (a new extension, changed html_input) invalidates output automatically instead of silently serving stale HTML.

Custom syntax. If the bundle exposes the underlying CommonMark environment, register custom inline/block parsers and extensions there; keep those registrations in one provider so both web and queue workers get identical output.

Reuse across channels. Notifications, mail templates, PDF export, and the API's content_html field should all go through the same singleton — divergent converters are the most common source of "looks right in the browser, broken in email" bugs.

Gotchas and Tips

  • It will not auto-discover. Symfony bundles register through config/bundles.php; Laravel ignores that. If you composer require and expect NorthernMarkdown to appear in the container, you'll get a Target class does not exist or a silently missing binding. Always wire manually.
  • Config keys are nested and snake-cased. Symfony config is northern_markdown: { html_input: strip }; Laravel's config('markdown.html_input') won't map automatically unless you publish/flatten it yourself. Mismatched keys are silent — the converter just falls back to defaults.
  • Raw HTML is the security boundary. Most markdown converters default to passing HTML through. For any user-authored content, set html_input to strip/escape and run the output through HTMLPurifier (mews/purist) before {!! !!}. Never widen this "just for the embed feature" without a whitelist.
  • 0 stars, 0 dependents, no support net. Pin an exact version in composer.json, commit a lockfile, and write your own integration test asserting a handful of known inputs (headings, links, fenced code, tables). If a release breaks you, be prepared to fork — the surface area is small.
  • Release date is in the future (2026-03-18). Check composer show northernco/markdown-bundle --all for the actual tag list and whether a stable constraint exists; you may be forced onto dev-main.
  • Singleton or nothing. Parser construction is the expensive part. If you new the converter per render (easy to do inside a Blade directive), long pages with inline markdown drop in throughput noticeably. Resolve from the container once.
  • Debugging the wiring. In Symfony you'd debug:container; here, php artisan tinker → app(Converter::class) plus dd(app()->getBindings()) confirms what actually registered. If the underlying class name differs from the README (common in low-traffic packages), search vendor/northernco/markdown-bundle/src for class .*Converter rather than trusting docs.
  • Extension points worth knowing: html_input, allow_unsafe_links, max_nesting_level, and any custom parser registration. Set max_nesting_level low (e.g. 20) to blunt pathological-input CPU attacks on public comment fields.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource