PHP code example of birdcar / markdown-php

1. Go to this page and download the library: Download birdcar/markdown-php library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

birdcar / markdown-php example snippets


use Birdcar\Markdown\Environment\BfmEnvironmentFactory;
use League\CommonMark\MarkdownConverter;

$environment = BfmEnvironmentFactory::create();
$converter = new MarkdownConverter($environment);

echo $converter->convert(<<<'MD'
---
title: Sprint Planning
tags:
  - engineering
---

- [>] Call the dentist //due:2025-03-01
- [!] File taxes //due:2025-04-15 //hard
- [x] Buy groceries

@callout type=warning title="Heads Up"
Don't forget to bring your **insurance card**.
@endcallout

Hey @sarah, can you review this? #urgent
MD);

use Illuminate\Support\Str;

// Render BFM to HTML
$html = Str::bfm('- [>] Call dentist //due:2025-03-01');

// Inline rendering (no wrapping <p> tags)
$html = Str::inlineBfm('Hey @sarah');

// Access the configured converter directly
$converter = app(\League\CommonMark\MarkdownConverter::class);

// config/bfm.php
return [
    'profile' => 'html',  // 'html', 'email', or 'plain'
    'resolvers' => [
        'mention' => \App\Markdown\UserMentionResolver::class,
        'embed'   => \App\Markdown\OEmbedResolver::class,
    ],
];

use Birdcar\Markdown\Filament\Forms\Components\BfmEditor;
use Birdcar\Markdown\Filament\Tables\Columns\BfmTextColumn;
use Birdcar\Markdown\Filament\Infolists\Components\BfmTextEntry;

// Form field with live BFM preview
BfmEditor::make('content')
    ->previewDebounce(300);

// Table column that renders BFM
BfmTextColumn::make('content');

// Infolist entry that renders BFM
BfmTextEntry::make('content');

use Birdcar\Markdown\Environment\BfmEnvironmentFactory;
use Birdcar\Markdown\Environment\RenderProfile;

$environment = BfmEnvironmentFactory::create(
    profile: RenderProfile::Html,           // Html (default), Email, or Plain
    embedResolver: $myEmbedResolver,        // optional — implements EmbedResolverInterface
    mentionResolver: $myMentionResolver,    // optional — implements MentionResolverInterface
    

use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\MarkdownConverter;
use Birdcar\Markdown\Inline\Task\TaskExtension;
use Birdcar\Markdown\Inline\TaskModifier\TaskModifierExtension;

$environment = new Environment();
$environment->addExtension(new CommonMarkCoreExtension());
$environment->addExtension(new TaskExtension());
$environment->addExtension(new TaskModifierExtension());

$converter = new MarkdownConverter($environment);
echo $converter->convert('- [>] Call dentist //due:2025-03-01');

use Birdcar\Markdown\Contracts\MentionResolverInterface;

class UserMentionResolver implements MentionResolverInterface
{
    public function resolve(string $identifier): ?array
    {
        $user = User::where('username', $identifier)->first();

        return $user ? [
            'label' => $user->display_name,
            'url' => route('profile.show', $user),
        ] : null;
    }
}

use Birdcar\Markdown\Contracts\EmbedResolverInterface;

class OEmbedResolver implements EmbedResolverInterface
{
    public function resolve(string $url): ?array
    {
        $response = Http::get('https://noembed.com/embed', ['url' => $url]);

        return $response->successful() ? $response->json() : null;
    }
}

use Birdcar\Markdown\Contracts\IncludeResolverInterface;

class FileIncludeResolver implements IncludeResolverInterface
{
    public function resolve(string $src, ?string $type, ?string $lines): ?string
    {
        $path = base_path($src);
        return file_exists($path) ? file_get_contents($path) : null;
    }
}

use Birdcar\Markdown\Contracts\QueryResolverInterface;
use League\CommonMark\Node\Block\Document;

class TaskQueryResolver implements QueryResolverInterface
{
    public function resolve(array $params, Document $document): array
    {
        return Task::query()
            ->when($params['state'] ?? null, fn ($q, $state) => $q->where('state', $state))
            ->when($params['tag'] ?? null, fn ($q, $tag) => $q->withTag($tag))
            ->limit($params['limit'] ?? 10)
            ->get()
            ->toArray();
    }
}

use Birdcar\Markdown\Contracts\ComputedFieldResolverInterface;
use League\CommonMark\Node\Block\Document;

class ReadabilityResolver implements ComputedFieldResolverInterface
{
    public function resolve(Document $document, array $frontmatter, array $builtins): array
    {
        return [
            'isLongRead' => $builtins['wordCount'] > 1000,
        ];
    }
}

use Birdcar\Markdown\Environment\BfmEnvironmentFactory;
use Birdcar\Markdown\Metadata\MetadataExtractor;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\Parser\MarkdownParser;

$environment = BfmEnvironmentFactory::create();
$parser = new MarkdownParser($environment);

$document = $parser->parse(<<<'MD'
---
title: My Post
tags:
  - bfm
---

A post about #typescript with a [link](https://example.com).

- [x] Write draft
- [ ] Publish //due:2025-06-01
MD);

$extractor = new MetadataExtractor();
$meta = $extractor->extract($document);

$meta->frontmatter;          // ['title' => 'My Post', 'tags' => ['bfm']]
$meta->computed['wordCount']; // 9
$meta->computed['readingTime']; // 1
$meta->computed['tags'];      // ['bfm', 'typescript']
$meta->computed['tasks'];     // TaskCollection with ->open, ->done, ->all, etc.
$meta->computed['links'];     // [LinkReference { url, title, line }]

$extractor = new MetadataExtractor(
    resolvers: [new ReadabilityResolver()],
);

$meta = $extractor->extract($document);
$meta->custom['isLongRead']; // false

use Birdcar\Markdown\Merge\BfmDocument;
use Birdcar\Markdown\Merge\DocumentMerger;
use Birdcar\Markdown\Merge\MergeOptions;
use Birdcar\Markdown\Merge\MergeStrategy;

$a = new BfmDocument(frontmatter: ['tags' => ['a']], body: 'Content A');
$b = new BfmDocument(frontmatter: ['tags' => ['b'], 'title' => 'B'], body: 'Content B');

$merger = new DocumentMerger();
$merged = $merger->merge([$a, $b]);
// $merged->frontmatter = ['tags' => ['a', 'b'], 'title' => 'B']
// $merged->body = "Content A\n\nContent B"

// Configurable strategies
$merger->merge([$a, $b], new MergeOptions(strategy: MergeStrategy::FirstWins));
$merger->merge([$a, $b], new MergeOptions(strategy: MergeStrategy::Error));  // throws on scalar conflicts
$merger->merge([$a, $b], new MergeOptions(
    strategy: fn (string $key, mixed $existing, mixed $incoming) => $existing . $incoming,
));
$merger->merge([$a, $b], new MergeOptions(separator: "\n---\n"));  // custom body separator
bash
php artisan vendor:publish --tag=bfm-config
bash
php artisan vendor:publish --tag=bfm-assets
markdown
@figure src="photo.jpg" alt="A photo" id="fig-1"
Caption text with **markdown**.
@endfigure