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

Front Yaml Laravel Package

mnapoli/front-yaml

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require mnapoli/front-yaml
    

    Add to composer.json if using Laravel’s autoloader:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Mni\\FrontYAML\\": "vendor/mnapoli/front-yaml/src/"
        }
    }
    

    Run composer dump-autoload.

  2. First Use Case: Parse a Markdown file with front matter (e.g., resources/markdown/blog-post.md):

    use Mni\FrontYAML\Parser;
    
    $parser = new Parser();
    $document = $parser->parse(file_get_contents('blog-post.md'));
    
    $metadata = $document->getYAML(); // Array of front matter
    $content = $document->getContent(); // Parsed HTML
    
  3. Where to Look First:

    • Parser Class: vendor/mnapoli/front-yaml/src/Parser.php for core logic.
    • Interfaces: YAMLParser and MarkdownParser in vendor/mnapoli/front-yaml/src/ for customization.
    • Bridge Classes: vendor/mnapoli/front-yaml/src/Bridge/ for parser integrations (e.g., CommonMarkParser).

Implementation Patterns

Core Workflows

  1. Parsing Markdown Files:

    • Use in Laravel’s AppServiceProvider to pre-process Markdown files (e.g., for a CMS or blog):
      public function boot()
      {
          $parser = new Parser();
          $posts = collect(storage_path('app/markdown/posts/*.md'))
              ->map(fn ($path) => $parser->parse(file_get_contents($path)))
              ->mapWithKeys(fn ($doc) => [$doc->getYAML()['slug'] => $doc->getContent()]);
      }
      
  2. Custom Parsers:

    • Replace Symfony’s YAML parser with spatie/array-to-xml for XML output:
      use Mni\FrontYAML\YAMLParser;
      use Spatie\ArrayToXml\ArrayToXml;
      
      $yamlParser = new class implements YAMLParser {
          public function parse($yaml) {
              return (new ArrayToXml)->convert(['data' => yaml_parse($yaml)]);
          }
      };
      $parser = new Parser($yamlParser);
      
  3. Markdown Processing:

    • Disable Markdown parsing for raw content (e.g., code blocks):
      $document = $parser->parse($content, false); // Returns raw Markdown
      
  4. Service Container Integration:

    • Bind the parser to Laravel’s IoC container in AppServiceProvider:
      $this->app->singleton(Parser::class, fn () => new Parser());
      
    • Inject via constructor:
      public function __construct(private Parser $parser) {}
      
  5. File System Integration:

    • Process files from storage/app/markdown/ dynamically:
      $files = Storage::files('markdown');
      $documents = collect($files)->map(fn ($file) =>
          $this->parser->parse(Storage::get($file))
      );
      

Integration Tips

  1. Laravel Blade Directives: Create a custom Blade directive to parse front matter in views:

    Blade::directive('frontmatter', function ($expression) {
        $parser = app(Parser::class);
        $content = $parser->parse($expression);
        return "<?php echo \$content->getContent(); ?>";
    });
    

    Usage in Blade:

    @frontmatter($markdownContent)
    
  2. API Responses: Serve parsed content as JSON:

    return response()->json([
        'metadata' => $document->getYAML(),
        'content' => $document->getContent(),
    ]);
    
  3. Validation: Validate front matter using Laravel’s Validator:

    $validator = Validator::make($document->getYAML(), [
        'title' => 'required|string|max:255',
        'author' => 'required|string',
    ]);
    
  4. Caching: Cache parsed documents to avoid reprocessing:

    $cacheKey = 'frontmatter_'.md5($content);
    $document = Cache::remember($cacheKey, now()->addHours(1), fn () =>
        $parser->parse($content)
    );
    
  5. Testing: Use Mockery to test custom parsers:

    $mockYamlParser = Mockery::mock(YAMLParser::class);
    $mockYamlParser->shouldReceive('parse')->andReturn(['key' => 'value']);
    $parser = new Parser($mockYamlParser);
    

Gotchas and Tips

Pitfalls

  1. Line Endings:

    • Windows (\r\n) vs. Unix (\n) line endings may cause parsing failures. Normalize input:
      $content = str_replace(["\r\n", "\r"], "\n", $content);
      
  2. Empty Front Matter:

    • Files with only --- (no content) may throw errors. Validate:
      if (empty(trim($content))) {
          throw new \InvalidArgumentException('Empty content provided.');
      }
      
  3. Markdown Parsing Quirks:

    • League CommonMark may misparse edge cases (e.g., nested lists). Use CommonMarkParser with custom extensions:
      use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
      use League\CommonMark\Environment;
      
      $env = new Environment();
      $env->addExtension(new CommonMarkCoreExtension());
      $parser = new \Mni\FrontYAML\Bridge\CommonMark\CommonMarkParser($env);
      
  4. YAML Syntax Errors:

    • Invalid YAML (e.g., unclosed quotes) will throw exceptions. Wrap parsing in a try-catch:
      try {
          $yaml = $parser->parse($content)->getYAML();
      } catch (\Symfony\Component\Yaml\Exception\ParseException $e) {
          report($e);
          $yaml = [];
      }
      
  5. Performance:

    • Parsing large files repeatedly is slow. Cache results or use lazy loading:
      $document = Cache::rememberForever("frontmatter_{$fileHash}", fn () =>
          $parser->parse($content)
      );
      

Debugging Tips

  1. Log Raw Input:

    • Log the raw content before parsing to debug issues:
      \Log::debug('Front matter input:', ['content' => $content]);
      
  2. Inspect Parsed Output:

    • Dump the parsed YAML and HTML to verify:
      \Log::debug('Parsed YAML:', $document->getYAML());
      \Log::debug('Parsed HTML:', $document->getContent());
      
  3. Custom Error Handling:

    • Extend the Parser class to add custom error handling:
      class CustomParser extends Parser {
          public function parse($content, $parseMarkdown = true) {
              try {
                  return parent::parse($content, $parseMarkdown);
              } catch (\Exception $e) {
                  \Log::error("FrontYAML parse error: {$e->getMessage()}");
                  throw new \RuntimeException('Failed to parse front matter.', 0, $e);
              }
          }
      }
      

Extension Points

  1. Custom Separators:

    • Override the default --- separator (e.g., for HTML comments):
      $parser = new Parser(null, null, ['separator' => '<!--', 'separatorClosing' => '-->']);
      
  2. Post-Processing:

    • Chain parsers or modify output:
      $document = $parser->parse($content);
      $content = Str::of($document->getContent())->replace('old', 'new');
      
  3. Event Dispatching:

    • Dispatch events before/after parsing (e.g., for analytics):
      event(new FrontMatterParsed($document->getYAML()));
      
  4. Middleware:

    • Create middleware to parse front matter in HTTP requests:
      public function handle($request, Closure $next) {
          $request->merge(['frontmatter' => $this->parser->parse($request->input('content'))]);
          return $next($request);
      }
      
  5. Artisan Commands:

    • Build a command to validate front matter across files:
      public function handle() {
          foreach (Storage::files('markdown') as $file) {
              $content = Storage::get($file);
              $this->parser->parse($content); // Throws on error
              $this->info("Valid: {$file}");
          }
      }
      
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.
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
spatie/mailcoach-vapor