A package for Laravel that lets you run Laravel Validation and/or a handler function over markdown files in your application.
cassarco/markdown-tools is a Laravel package for a package for laravel that lets you run laravel validation and/or a handler function over markdown files in your application..
It currently has 0 GitHub stars and 14 downloads on Packagist (latest version v2.0.1).
Install it with composer require cassarco/markdown-tools.
Discover more Laravel packages by cassarco
or browse all Laravel packages to compare alternatives.
Last updated
A Laravel package for processing markdown files with validation and custom handlers.
Markdown files with YAML front-matter are a great way to manage content. They're version-controlled, portable, and easy to edit. But when your Laravel application needs that content in the database, you need a reliable way to import it.
This package lets you:
Define one or more schemes in your configuration file, then run the bundled command to process them.
Install the package via composer:
composer require cassarco/markdown-tools
Run the install command to publish the config and action stubs:
php artisan markdown-tools:install
This publishes:
config/markdown-tools.php - configuration fileapp/Actions/MarkdownFileHandler.php - handler for processing markdown filesapp/Actions/MarkdownFileRules.php - validation rules for front-matterAlternatively, publish them separately:
php artisan vendor:publish --tag=markdown-tools-config
php artisan vendor:publish --tag=markdown-tools-actions
The published config file defines your schemes:
use App\Actions\MarkdownFileHandler;
use App\Actions\MarkdownFileRules;
return [
'schemes' => [
'default' => [
'path' => resource_path('markdown'),
'rules' => MarkdownFileRules::class,
'handler' => MarkdownFileHandler::class,
],
],
'common-mark' => [
// League/CommonMark settings...
],
];
Edit app/Actions/MarkdownFileRules.php to specify validation rules for front-matter properties:
<?php
namespace App\Actions;
use Cassarco\MarkdownTools\Contracts\MarkdownFileRules as MarkdownFileRulesContract;
class MarkdownFileRules implements MarkdownFileRulesContract
{
public function __invoke(): array
{
return [
'uuid' => 'required|uuid',
'title' => 'required|string|max:255',
];
}
}
Edit app/Actions/MarkdownFileHandler.php to process each markdown file:
<?php
namespace App\Actions;
use App\Models\Article;
use Cassarco\MarkdownTools\Contracts\MarkdownFileHandler as MarkdownFileHandlerContract;
use Cassarco\MarkdownTools\MarkdownFile;
use function Laravel\Prompts\info;
class MarkdownFileHandler implements MarkdownFileHandlerContract
{
public function __invoke(MarkdownFile $file): void
{
Article::updateOrCreate([
'uuid' => $file->frontMatter()['uuid'],
], [
'uuid' => $file->frontMatter()['uuid'],
'title' => $file->frontMatter()['title'],
]);
info("Processed: {$file->pathname()}");
}
}
Run the bundled command:
php artisan markdown-tools:process

If files fail validation, you'll see Laravel validation errors:

The handler receives a MarkdownFile instance with these methods:
$file->frontMatter() // Front-matter as a PHP array
$file->markdown() // Raw markdown content
$file->html() // HTML without table of contents
$file->toc() // Table of contents HTML
$file->htmlWithToc() // HTML with embedded table of contents
$file->pathname() // File path
Here's how I use this package to sync markdown files to my database:
<?php
namespace App\Actions;
use App\Models\Article;
use Cassarco\MarkdownTools\Contracts\MarkdownFileHandler as MarkdownFileHandlerContract;
use Cassarco\MarkdownTools\MarkdownFile;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use function Laravel\Prompts\info;
class MarkdownFileHandler implements MarkdownFileHandlerContract
{
public function __invoke(MarkdownFile $file): void
{
Article::updateOrCreate([
'uuid' => $file->frontMatter()['uuid'],
], [
'uuid' => $file->frontMatter()['uuid'],
'title' => $file->frontMatter()['title'],
'slug' => $file->frontMatter()['slug'] ?? Str::slug($file->frontMatter()['title']),
'description' => $file->frontMatter()['description'],
'table_of_contents' => $file->toc(),
'content' => $file->html(),
'image' => $file->frontMatter()['image'],
'tags' => collect($file->frontMatter()['tags']),
'published_at' => Carbon::make($file->frontMatter()['published_at']),
'deleted_at' => Carbon::make($file->frontMatter()['deleted_at']),
'created_at' => Carbon::make($file->frontMatter()['created_at']),
'updated_at' => Carbon::make($file->frontMatter()['updated_at']),
]);
info("Processing {$file->frontMatter()['title']}");
}
}
Version 2.0 introduces breaking changes to support config caching. Handlers and rules are now class-based instead of closures.
composer require cassarco/markdown-tools:^2.0
This requires Laravel 11+ and PHP 8.3+.
php artisan vendor:publish --tag=markdown-tools-actions
This creates app/Actions/MarkdownFileHandler.php and app/Actions/MarkdownFileRules.php.
Move your closure logic from the config file to the new handler class.
Before (v1):
// config/markdown-tools.php
'handler' => function (MarkdownFile $file) {
Article::updateOrCreate(
['uuid' => $file->frontMatter()['uuid']],
['title' => $file->frontMatter()['title']]
);
},
After (v2):
// app/Actions/MarkdownFileHandler.php
public function __invoke(MarkdownFile $file): void
{
Article::updateOrCreate(
['uuid' => $file->frontMatter()['uuid']],
['title' => $file->frontMatter()['title']]
);
}
Move your rules array to the new rules class.
Before (v1):
// config/markdown-tools.php
'rules' => [
'title' => 'required',
],
After (v2):
// app/Actions/MarkdownFileRules.php
public function __invoke(): array
{
return [
'title' => 'required',
];
}
Replace closures with class references:
// config/markdown-tools.php
use App\Actions\MarkdownFileHandler;
use App\Actions\MarkdownFileRules;
'schemes' => [
'default' => [
'path' => resource_path('markdown'),
'rules' => MarkdownFileRules::class,
'handler' => MarkdownFileHandler::class,
],
],
Note: The default scheme was renamed from 'markdown' to 'default'.
composer test
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
If you find a bug that impacts the security of this package please send an email to [email protected] instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.