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

Parsedown Extra Laravel Laravel Package

alfredo-ramos/parsedown-extra-laravel

Laravel integration for Parsedown Extra, bringing Markdown parsing with support for tables, footnotes, and other extended syntax to your Blade views and PHP code through a simple facade and service provider.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install into the Laravel app:

    composer require alfredo-ramos/parsedown-extra-laravel
    

    The package pulls in erusev/parsedown-extra, which itself extends erusev/parsedown.

  2. Register it:

    • Laravel 5.5+ uses package auto-discovery, so the service provider and facade alias are registered automatically.
    • On older Laravel versions, add the provider to config/app.php under providers and the facade under aliases.
  3. Publish the config (if the package exposes one):

    php artisan vendor:publish --tag=parsedown-extra
    

    This usually produces config/parsedown-extra.php, where you can toggle Parsedown Extra options such as line breaks, markup escaping, URL linking, and safe mode.

  4. Where to look first:

    • config/parsedown-extra.php — the supported knobs.
    • The package's src/ service provider — confirms the binding name and whether a Blade directive is registered.
    • The upstream Parsedown Extra docs — for the Markdown Extra feature set (tables, footnotes, definition lists, abbreviations, fenced code, etc.).
  5. First use case — render a Markdown body stored in a model into HTML inside a Blade view:

    {!! ParsedownExtra::text($post->body) !!}
    

    If the package registers a Blade directive (check the provider), you may also be able to write @markdown($post->body).

Implementation Patterns

Facade for one-off rendering. The most common pattern is calling the facade (or resolved singleton) wherever you need HTML:

$html = ParsedownExtra::text($markdown);

Parsedown's text() returns the rendered HTML string; line() handles a single line. The Extra subclass enables the extended syntax, so tables, footnotes, and definition lists work without extra configuration.

Dependency injection for testability. Instead of the facade, type-hint the Parsedown Extra instance in a service or controller so you can swap or mock it in tests. The container binding is a singleton, so repeated calls in one request reuse the same parser.

Keep Markdown and HTML separate. Store the raw Markdown in the database and render on read (or on write into a cached column). This preserves the source if you later change renderers or config, and makes search/rewrites easier. A common pattern is a body_markdown + body_html pair, with body_html regenerated by an observer or queue job when the Markdown changes.

Cache the output. Parsing is cheap but not free, and the output is deterministic for a given config. Wrap rendering:

$html = Cache::remember("post:{$post->id}:html", 3600, fn () => ParsedownExtra::text($post->body));

Flush the key in your model's saved/deleted events. For pages with many short snippets (comments, chat), batch-render or cache per fragment.

Tune behavior via config, not code. Rather than calling setters all over the app, configure defaults centrally in config/parsedown-extra.php (or by re-binding a configured instance in a service provider). If the package's config only covers a subset of Parsedown's options, extend it by resolving the singleton and applying setters in a AppServiceProvider::boot().

Custom rendering/extensions. If you need altered output — custom link targets, attribute injection, syntax highlighting of code blocks — subclass ParsedownExtra, override the relevant methods (element(), blockFencedCode(), etc.), and rebind the singleton in a service provider so the facade and any injected instances pick up your subclass.

Rendering untrusted content. For user-submitted Markdown (comments, profiles), enable safe mode and/or markup escaping in config so raw HTML is not passed through. For trusted editorial content, the defaults that allow inline HTML may be preferable. Decide per content type, not globally — often you want two configured instances (editorial vs user).

Blade integration. If the package registers a directive, use it for inline cases; for anything more complex (caching, safe-mode switching) prefer a helper/service so the logic is testable outside views.

Gotchas and Tips

  • License is GPL-3.0. This is a real constraint, not a footnote: distributing a Laravel app that includes this package can obligate you to GPL-compatible licensing. For commercial/closed-source products, verify with counsel or prefer league/commonmark (MIT/BSD) instead. This alone often decides adoption.
  • Parsedown Extra is effectively unmaintained upstream. Security fixes are sparse, which matters most when rendering user input. Combine safe mode with output sanitization (e.g., HTML Purifier) for untrusted content, and keep the pin reasonably tight.
  • Safe mode is not a full sanitizer. setSafeMode(true) blocks some vectors but has had bypasses historically. Treat it as defense-in-depth, not the only layer.
  • Line-break semantics surprise people. With breaks disabled (Parsedown's default), single newlines don't create <br>; writers used to GitHub-flavored rendering will be confused. Enable breaks in config if that's the expectation — and document it.
  • Raw HTML passes through by default. If tables are rendered but user-supplied <script> is also surviving, you forgot markup escaping or safe mode. Check with a payload like <img src=x onerror=alert(1)>.
  • Facade alias collisions. A generic alias (e.g., Markdown or Parsedown) can clash with other packages. If you install a second Markdown integration, verify which alias wins in config/app.php.
  • Config caching. After editing the published config, run php artisan config:clear (and config:cache in production). A stale cached config is a classic "my setting didn't apply" debugging trap.
  • Publishing tags vary. If vendor:publish with a tag fails, run it without --tag and inspect the provider's publishes() call to find the correct key.
  • Extension point is the subclass, not config. Most desired customizations (custom elements, code-block hooks) require subclassing Parsedown Extra and rebinding; the package's config is typically a thin wrapper over Parsedown's setters. Confirm what the singleton binding name is before rebinding, or the facade and injected instances may resolve differently.
  • Performance is fine, but do not re-parse in loops. Rendering inside a Blade @foreach over hundreds of items without caching is a common accidental hot path. Render once, cache, or precompute on save.
  • Version pinning. With low star count and zero dependents, the ecosystem signal is weak. Pin a known-good version in composer.json and add a rendering test (tables, footnotes, fenced code, safe-mode payload) so an upstream or transitive bump is caught by CI rather than by users.
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.
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
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager