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

Livewire Markdown Editor Laravel Package

mckenziearts/livewire-markdown-editor

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require mckenziearts/livewire-markdown-editor
    npm install @github/markdown-toolbar-element github-text-expander-element
    

    Publish assets:

    php artisan vendor:publish --tag=livewire-markdown-editor-assets
    
  2. Basic Usage Add the component to a Livewire blade:

    <livewire:markdown-editor :content="$content" />
    

    Initialize in a Livewire component:

    public $content = "# Hello World";
    
    public function mount()
    {
        $this->content = "# Default Markdown";
    }
    
  3. First Use Case Create a blog post editor:

    // BlogPostController.php
    public function edit(BlogPost $post)
    {
        return view('posts.edit', [
            'post' => $post
        ]);
    }
    
    <!-- posts/edit.blade.php -->
    <livewire:markdown-editor :content="$post->content" wire:model="content" />
    

Implementation Patterns

Core Workflows

  1. Basic Editing

    <livewire:markdown-editor
        wire:model="postContent"
        :toolbar-options="['bold', 'italic', 'heading']"
    />
    
    • Use wire:model for two-way binding with Livewire properties.
  2. File Uploads

    // Livewire component
    public function handleFileUpload($fileId, $fileName)
    {
        $path = $fileId . '.' . $fileName->extension();
        $fileName->storeAs('uploads', $path);
    
        return "[![Image]($path)](uploads/$path)";
    }
    
    <livewire:markdown-editor
        :file-upload-handler="handleFileUpload"
    />
    
  3. Dark Mode Integration

    <livewire:markdown-editor
        dark-mode="{{ request()->wantsDarkMode() }}"
    />
    

    Sync with Laravel's dark mode middleware or user preference.

  4. Custom Toolbar

    public function getToolbarOptions()
    {
        return [
            'bold', 'italic', 'heading',
            ['label' => 'Custom', 'icon' => '✨', 'action' => 'customAction']
        ];
    }
    

    Pass via props:

    <livewire:markdown-editor :toolbar-options="getToolbarOptions()" />
    
  5. Code Highlighting Ensure Spatie Shiki is configured in config/shiki.php:

    'themes' => [
        'light' => 'github-light',
        'dark' => 'github-dark',
    ],
    

Integration Tips

  • Validation: Use Laravel validation rules for markdown content:
    use Illuminate\Validation\Rule;
    
    $rules = [
        'content' => ['required', Rule::max(10000)],
    ];
    
  • Sanitization: Sanitize output before saving:
    use League\HTMLSanitizer\HTMLSanitizer;
    
    $sanitizer = new HTMLSanitizer();
    $cleanContent = $sanitizer->sanitize($this->content);
    
  • Livewire Hooks: Extend functionality with Livewire events:
    protected $listeners = ['contentUpdated' => 'handleContentUpdate'];
    
    public function handleContentUpdate($content)
    {
        // Log or process content changes
    }
    

Gotchas and Tips

Common Pitfalls

  1. Asset Loading

    • Ensure @github/markdown-toolbar-element and github-text-expander-element are included in your layout:
      @vite(['resources/js/github-markdown-toolbar.js'])
      
    • If using Vite, add to vite.config.js:
      import { defineConfig } from 'vite';
      import laravel from 'laravel-vite-plugin';
      
      export default defineConfig({
          plugins: [
              laravel({
                  input: [
                      'resources/js/app.js',
                      'node_modules/@github/markdown-toolbar-element/dist/github-markdown-toolbar.js',
                  ],
                  refresh: true,
              }),
          ],
      });
      
  2. Dark Mode Sync

    • If dark mode doesn’t switch, ensure Alpine.js is properly initialized:
      <script src="//unpkg.com/alpinejs" defer></script>
      
    • Manually trigger updates:
      document.addEventListener('alpine:init', () => {
          Alpine.data('markdownEditor', () => ({
              init() {
                  this.$watch('darkMode', (value) => {
                      this.$el.querySelector('.markdown-preview').classList.toggle('dark', value);
                  });
              }
          }));
      });
      
  3. File Upload Quirks

    • CORS Issues: If uploading fails, configure CORS in config/cors.php:
      'paths' => ['api/*', 'sanctum/csrf-cookie', 'uploads/*'],
      
    • File Size Limits: Adjust in config/filesystems.php:
      'disks' => [
          'local' => [
              'driver' => 'local',
              'max_file_size' => '10m', // Adjust as needed
          ],
      ],
      
  4. Toolbar Customization

    • Hidden Elements: Some toolbar elements may require additional Alpine.js initialization:
      Alpine.store('markdownToolbar', {
          init() {
              this.$nextTick(() => {
                  const toolbar = document.querySelector('github-markdown-toolbar');
                  if (toolbar) {
                      toolbar.init();
                  }
              });
          }
      });
      
    • Dynamic Options: Use Alpine to toggle toolbar options:
      <livewire:markdown-editor
          :toolbar-options="[
              @json($showAdvanced ? ['bold', 'italic', 'link', 'code'] : ['bold', 'italic'])
          ]"
      />
      

Debugging Tips

  1. Console Logs Add debug logs in Livewire component:

    public function updatedContent($value)
    {
        \Log::debug('Markdown content updated:', ['content' => $value]);
    }
    

    Check logs with:

    tail -f storage/logs/laravel.log
    
  2. Alpine.js Debugging Enable Alpine debug mode:

    <script src="//unpkg.com/alpinejs" defer data-turbolinks-eval="false" data-turbolinks-track="reload" data-alpine-debug="true"></script>
    
  3. Livewire Wire:ignore If the editor flickers, wrap it in wire:ignore and manually sync:

    <div wire:ignore>
        <livewire:markdown-editor :content="$content" />
    </div>
    
    document.addEventListener('livewire:init', () => {
        Livewire.hook('element.updated', (el) => {
            if (el.querySelector('livewire-markdown-editor')) {
                el.querySelector('livewire-markdown-editor').dispatchEvent(new CustomEvent('contentUpdated'));
            }
        });
    });
    

Extension Points

  1. Custom Markdown Processing Extend the MarkdownEditor class to add pre/post-processing:

    use Mckenziearts\LivewireMarkdownEditor\MarkdownEditor;
    
    class CustomMarkdownEditor extends MarkdownEditor
    {
        public function processContent($content)
        {
            // Add custom logic (e.g., auto-links, placeholders)
            return str_replace('# ', '# ', $content); // Example: Ensure heading spacing
        }
    
        public function render()
        {
            $this->content = $this->processContent($this->content);
            return parent::render();
        }
    }
    

    Register the component in AppServiceProvider:

    Livewire::component('markdown-editor', CustomMarkdownEditor::class);
    
  2. Plugin System Use Livewire’s wire:model events to create plugins:

    // Example: Auto-save plugin
    public function updatedContent($value)
    {
        if ($this->autoSave) {
            $this->saveDraft($value);
        }
    }
    
    <livewire:markdown-editor
        wire:model="content"
        auto-save="true"
    />
    
  3. Shiki Themes Dynamically switch themes based on user preference:

    public function getShikiTheme()
    {
        return auth()->user()->prefers_dark_mode() ? 'github-dark' : 'github-light';
    }
    

    Pass to the component:

    <livewire:markdown-editor :shiki-theme="getShikiTheme()" />
    
  4. Toolbar Extensions Add custom toolbar buttons via Alpine:

    document.add
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky