[WIP] Frontmatter Jekyll style parser
Available parsers:
- yaml (use symfony/yaml)
- Markdown (use erusev/parsedown-extra)
- Json (use seld/jsonlint)
Via Composer
$ composer require devster/frontmatter
And add extra packages that built-in parsers use:
# YAML
$ composer require symfony/yaml
# Markdown
$ composer require erusev/parsedown-extra
# Json
$ composer require seld/jsonlint
These packages are not required by default to minimize the footprint and speed up your install if you only need few of them
require '../vendor/autoload.php';
$parser = new Devster\Frontmatter\Parser('yaml', 'markdown');
$content = <<<EOF
---
title: My Content
description: "This is a description"
---
This is *Markdown* content
EOF;
$frontmatter = $parser->parse($content);
echo $frontmatter->head['title']; // My content
echo $frontmatter->getBody(); // This is <em>Markdown</em> content
And because the frontmatter format is not only used by developers, this parser is quite permissive
All content examples above are parsed like normal frontmatter content:
$content = <<<EOF
--- title: My Title ---
# Title 1
## Title 2
EOF;
$content = <<<EOF
---
title: My Title ---
# Title 1
## Title 2
EOF;
$p = new Parser;
$result = $p->parseFrontmatter($content);
echo $result['head'];
echo $result['body'];
$p = new Parser('json', 'markdown', '##');
$p->parse(<<<EOF
##
{ "title": "My title" }
##
Body content
EOF);
// You can also let your user use its own delimiter
$p = new Parser;
$p
->guessDelimiter()
->parse(<<<EOF
~~X~~
head
~~X~~
body
EOF);
The frontmatter parsers can be guessed from a filename, based on the extensions.
Take a look at these examples below:
my_file.json.md
: Head in Json and Body in Markdownmy_file.md
: Head will be parse with the parser set in the constructor, Body in Markdownmy_file.unknown
: An exception will be thrownmy_file.yml.unknown
: An exception will be thrown
$p = new Parser;
$p
->guessParsersFromFilename('my_file.yml.md')
->parse(file_gets_content('my_file.yml.md'))
;
// Or you can set the default head parser
$p = new Parser('json');
$p
->guessParsersFromFilename('my_file.md')
->parse(file_gets_content('my_file.md'))
;
You can also define explicitly in the head which parser the body should be parsed with.
$p = new Parser('yaml');
$p
->guessBodyParserFromHead('[options][format]')
->parse(<<<EOF
---
title: My Title
options:
format: json
---
{
"body": "This is my body"
}
EOF);
Internally the Property Access Component from symfony is used. Refer to its documentation to find the path that will be used to grab the parser from the head
If the parser could not be fetch from the head, the default body parser will be use.
$p = new Devster\Frontmatter\Parser('yml', 'md');
$p
->guessDelimiter()
->guessParsersFromFilename('my_file.md')
->guessBodyParserFromHead('[format]')
;
try {
$p->parse($content);
} catch (Devster\Frontmatter\Exception\Exception $e) {
if ($e instanceof Devster\Frontmatter\Exception\ParserNotFoundException) {
// The head or the body parser is not found
}
if ($e instanceof Devster\Frontmatter\Exception\ParsingException) {
// Unable to parse the frontmatter content
// or
// an error occured in head or body parsing
}
}
$ vendor/bin/phpunit
- Rename head to header
- Add an INI parser
- Allow to not parse the body to avoid the creation of a new custom parser if the need is not built-in
- Add a validate feature
- Add dumping feature
Please see CONTRIBUTING for details.
Special thank to Etienne Zannelli for his help on Regex ❤
The MIT License (MIT). Please see License File for more information.