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

Parsedown Bundle Laravel Package

bgaze/parsedown-bundle

Symfony 2 bundle adding Parsedown and Parsedown Extra Markdown parsing. Provides parsedown.standard and parsedown.extra services plus Twig filters md and mde to render Markdown/Markdown Extra in templates or PHP. Note: project is unmaintained.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation: Add to composer.json:

    "require": {
        "bgaze/parsedown-bundle": "dev-master"
    }
    

    Run composer update and enable the bundle in AppKernel.php:

    new Bgaze\ParsedownBundle\BgazeParsedownBundle(),
    
  2. First Use Case: Parse Markdown in a Twig template:

    {{ markdown_content|md }}  {# Standard Parsedown #}
    {{ markdown_content|mde }} {# Parsedown Extra #}
    

    Or in PHP:

    $parsed = $this->get('parsedown.standart')->text($markdown);
    
  3. Where to Look First:

    • Twig Filters: md and mde for quick template integration.
    • Services: parsedown.standart and parsedown.extra for programmatic use.
    • README.md: For basic usage and service names.

Implementation Patterns

Usage Patterns

  1. Twig Integration:

    • Use |md for standard Markdown (CommonMark).
    • Use |mde for extended syntax (tables, definition lists, fenced code blocks).
    • Example:
      <div class="content">
          {{ article.body|mde }}
      </div>
      
  2. Programmatic Parsing:

    • Inject services via dependency injection:
      use Symfony\Component\DependencyInjection\ContainerInterface;
      
      class PostService {
          protected $container;
      
          public function __construct(ContainerInterface $container) {
              $this->container = $container;
          }
      
          public function parseMarkdown($markdown) {
              return $this->container->get('parsedown.extra')->text($markdown);
          }
      }
      
  3. Dynamic Parser Selection:

    • Conditionally apply parsers based on content type or requirements:
      {% if content.requiresExtra %}
          {{ content.text|mde }}
      {% else %}
          {{ content.text|md }}
      {% endif %}
      
  4. Custom Parsing in Controllers:

    • Parse Markdown before passing to Twig:
      public function showAction($id) {
          $post = $this->postRepository->find($id);
          $html = $this->get('parsedown.extra')->text($post->getContent());
          return $this->render('post/show.html.twig', ['content' => $html]);
      }
      
  5. Reusable Parsing Logic:

    • Create a service to encapsulate parsing logic:
      namespace AppBundle\Service;
      
      use Symfony\Component\DependencyInjection\ContainerInterface;
      
      class MarkdownParser {
          protected $container;
      
          public function __construct(ContainerInterface $container) {
              $this->container = $container;
          }
      
          public function parse($markdown, $useExtra = false) {
              $service = $useExtra ? 'parsedown.extra' : 'parsedown.standart';
              return $this->container->get($service)->text($markdown);
          }
      }
      

Integration Tips

  • Caching Parsed Results: Use Symfony's cache system to avoid reprocessing static Markdown:

    $cache = $this->get('cache.app');
    $key = 'parsed_'.$markdownHash;
    $html = $cache->get($key, function() use ($markdown) {
        return $this->get('parsedown.extra')->text($markdown);
    });
    
  • Combining with Other Packages:

    • Use with KnpMenuBundle for dynamic menus from Markdown:
      {{ knp_menu_render('main_menu', {'parser': 'mde'}) }}
      
  • Custom Extensions:

    • Extend Parsedown by modifying the service configuration (if forking):
      # config.yml
      services:
          parsedown.extra:
              class: ParsedownExtra
              arguments:
                  - ['Tables', 'DefinitionLists', 'FencedCode']
      
  • Error Handling: Wrap parsing in try-catch blocks for robustness:

    try {
        $html = $this->get('parsedown.extra')->text($markdown);
    } catch (\Exception $e) {
        $html = '<p>Error parsing Markdown: '.$e->getMessage().'</p>';
    }
    

Gotchas and Tips

Pitfalls

  1. Unmaintained Package:

    • No updates since 2016; may break with PHP 7.2+ or Symfony 2.8+.
    • Workaround: Fork and update dependencies manually.
  2. Parsedown Version Limitations:

    • Uses Parsedown v1.x, which lacks support for modern Markdown features (e.g., GFM task lists, autolinks).
    • Workaround: Use Parsedown Extra (|mde) for extended features or migrate to league/commonmark.
  3. Twig Filter Overhead:

    • Twig filters are parsed on every request; avoid for performance-critical paths.
    • Workaround: Cache parsed results or use programmatic parsing.
  4. Service Naming Confusion:

    • parsedown.standart vs. parsedown.extra can be confusing.
    • Tip: Document service names in a central location (e.g., config/services.yml).
  5. PHP Version Incompatibility:

    • May fail on PHP 7.4+ due to deprecated functions or type hints.
    • Workaround: Fork and update the bundle for PHP 8.x compatibility.

Debugging Tips

  1. Check Parsed Output: Use var_dump() or browser dev tools to inspect parsed HTML:

    {{ dump(markdown_content|mde) }}
    
  2. Service Availability: Verify services are registered:

    $this->get('debug:container')->dump('parsedown.extra');
    
  3. Markdown Syntax Errors: Parsedown may silently fail on invalid Markdown. Validate input:

    if (!preg_match('/^[^\n]*\n.*$/', $markdown)) {
        throw new \InvalidArgumentException('Invalid Markdown format');
    }
    
  4. Caching Issues: Clear cache after updating Markdown content:

    php app/console cache:clear
    

Configuration Quirks

  1. Service Overrides: Override services in config.yml for custom behavior:

    services:
        parsedown.extra:
            class: ParsedownExtra
            arguments:
                - ['Tables', 'DefinitionLists']
    
  2. Twig Environment: Ensure Twig is properly configured to use the bundle’s filters:

    $twig = $this->get('twig');
    $twig->addFilter(new \Twig_SimpleFilter('md', [$this->get('parsedown.standart'), 'text']));
    
  3. Dependency Conflicts: Resolve conflicts with other bundles using parsedown:

    composer require erusev/parsedown:^1.7 --ignore-platform-reqs
    

Extension Points

  1. Custom Parsedown Extensions: Extend Parsedown by subclassing and overriding methods:

    namespace AppBundle\Service;
    
    use Parsedown;
    
    class CustomParsedown extends Parsedown {
        public function __construct() {
            parent::__construct();
            $this->setBreaksEnabled(true);
        }
    }
    

    Register the service in services.yml:

    services:
        custom.parsedown:
            class: AppBundle\Service\CustomParsedown
    
  2. Twig Filter Extensions: Add custom Twig filters for additional parsing logic:

    $twig->addFilter(new \Twig_SimpleFilter('custom_md', function($text) {
        return $this->get('custom.parsedown')->text($text);
    }));
    
  3. Event Listeners: Hook into Parsedown’s lifecycle (if extending):

    $parsedown->setEventDispatcher($dispatcher);
    

Performance Tips

  1. Avoid Redundant Parsing: Parse Markdown once and cache the result:

    $cacheKey = md5($markdown);
    $html = $cache->get($cacheKey, function() use ($markdown) {
        return $this->get('parsedown.extra')->text($markdown);
    });
    
  2. Minimize Twig Filters: Pre-parse Markdown in controllers to reduce template overhead:

    $html = $this->get('parsedown.extra')->text($markdown);
    return $this->render('template.twig', ['content' => $html]);
    
  3. Use Standard Parser for Simple Content: parsedown.standart is faster than parsedown.extra for basic Markdown.

Security Considerations

  1. Sanitize Input: Mark
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui