Weave Code
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

Commonmark Wire Navigate Laravel Package

spatie/commonmark-wire-navigate

CommonMark extension that adds a wire:navigate attribute to links rendered from Markdown, enabling Livewire SPA navigation. Install via Composer and register WireNavigateExtension in your CommonMark environment or spatie/laravel-markdown config.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require spatie/commonmark-wire-navigate
    
  2. Register the extension in your CommonMark instance (typically in a service provider or AppServiceProvider):
    use Spatie\CommonMarkWireNavigate\CommonMarkWireNavigateExtension;
    use League\CommonMark\CommonMarkConverter;
    
    $converter = new CommonMarkConverter();
    $converter->getEnvironment()->addExtension(new CommonMarkWireNavigateExtension());
    
  3. First use case: Convert a Markdown string with Livewire links:
    $markdown = '# [Click Me](#)';
    echo $converter->convert($markdown);
    
    Output:
    <h1><a href="#" wire:navigate>Click Me</a></h1>
    

Where to Look First


Implementation Patterns

Core Workflow

  1. Integrate with your Markdown pipeline:
    // In a service provider or helper
    public function markdownConverter()
    {
        $converter = new CommonMarkConverter();
        $converter->getEnvironment()->addExtension(new CommonMarkWireNavigateExtension());
        return $converter;
    }
    
  2. Use in Blade templates:
    {!! $this->markdownConverter()->convert($markdownContent) !!}
    
  3. Dynamic configuration (if needed): Override the extension to customize behavior (e.g., exclude certain links):
    $extension = new CommonMarkWireNavigateExtension();
    $extension->shouldAddWireNavigateToLink = function ($link) {
        return !str_contains($link->getUrl(), ['external.com', '#']);
    };
    $converter->getEnvironment()->addExtension($extension);
    

Common Use Cases

  • Livewire SPA mode: Enable seamless navigation in Markdown-rendered content (e.g., docs, wikis, or admin panels).
  • Dynamic content: Render Markdown from a database or API where links need wire:navigate for SPA compatibility.
  • Reusable components: Wrap the converter in a helper or service for consistency across the app.

Integration Tips

  • Livewire compatibility: Ensure your Livewire components are in SPA mode (wire:navigate only works in SPA mode).
  • Fallback for non-SPA: Use conditional logic to add wire:navigate only in SPA contexts:
    $extension = new CommonMarkWireNavigateExtension();
    $extension->shouldAddWireNavigate = fn () => app()->environment('spa');
    
  • Testing: Mock the converter in tests to avoid rendering HTML:
    $converter = $this->app->make(CommonMarkConverter::class);
    $html = $converter->convert('# [Test](#)');
    $this->assertStringContainsString('wire:navigate', $html);
    

Gotchas and Tips

Pitfalls

  1. SPA Mode Requirement:

    • wire:navigate only works in Livewire SPA mode. Forgetting to enable SPA mode (<livewire:component wire:navigate />) will make links behave like traditional anchor tags.
    • Debug tip: Check browser dev tools for wire:navigate attributes. If missing, verify SPA mode is active.
  2. Link URL Validation:

    • The extension adds wire:navigate to all links by default, including:
      • Anchor links (#section).
      • Mailto/telephone links (mailto:, tel:).
      • Relative/absolute URLs.
    • Fix: Override shouldAddWireNavigateToLink to filter links (e.g., exclude external URLs):
      $extension->shouldAddWireNavigateToLink = function ($link) {
          return !str_starts_with($link->getUrl(), ['http://', 'https://', 'mailto:', 'tel:']);
      };
      
  3. Nested Markdown Parsers:

    • If using multiple CommonMark extensions (e.g., spatie/laravel-markdown), ensure this extension is added last to avoid conflicts:
      $converter->getEnvironment()->addExtension(new CommonMarkWireNavigateExtension()); // Last!
      
  4. Performance:

    • The extension adds minimal overhead, but parsing large Markdown strings in loops (e.g., for comments) may impact performance.
    • Tip: Cache converted Markdown where possible.

Debugging

  • Missing Attributes:

    • Verify the extension is registered:
      $converter->getEnvironment()->hasExtension(CommonMarkWireNavigateExtension::class);
      
    • Check for typos in the extension class name or namespace.
  • Unexpected Links:

    • Use dd($link->getUrl()) in a custom shouldAddWireNavigateToLink callback to inspect problematic links.

Extension Points

  1. Customize Link Filtering:

    $extension->shouldAddWireNavigateToLink = function ($link) {
        return $link->getUrl() === '#' || str_contains($link->getUrl(), '/admin/');
    };
    
  2. Add Additional Attributes: Extend the extension to include other Livewire attributes (e.g., wire:click):

    use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
    use League\CommonMark\Renderer\NodeRendererInterface;
    
    class CustomWireNavigateExtension extends CommonMarkWireNavigateExtension
    {
        public function register(NodeRendererInterface $renderer): void
        {
            $renderer->addRenderer(
                Link::class,
                fn (Link $link, RenderContext $context) => '<a href="' . $link->getUrl() . '" wire:navigate wire:click="customAction">...</a>'
            );
        }
    }
    
  3. Conditional Activation:

    $extension = new CommonMarkWireNavigateExtension();
    $extension->shouldAddWireNavigate = fn () => auth()->check() && auth()->user()->is_admin;
    

Configuration Quirks

  • Environment Awareness: The extension doesn’t automatically detect SPA mode. Explicitly configure it if needed:
    $extension->shouldAddWireNavigate = fn () => request()->hasHeader('x-spa-mode');
    
  • HTML Output: The extension preserves existing HTML attributes on links. To replace them:
    $extension->shouldReplaceExistingAttributes = true;
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport