Frontmatter parser
, (*1)
[WIP] Frontmatter Jekyll style parser, (*2)
Available parsers:, (*3)
Install
Via Composer, (*4)
``` bash
$ composer require devster/frontmatter, (*5)
And add extra packages that built-in parsers use:
```bash
# 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, (*6)
Usage
Basic usage
``` php
require '../vendor/autoload.php';, (*7)
$parser = new Devster\Frontmatter\Parser('yaml', 'markdown');, (*8)
$content = <<<EOF
title: My Content, (*9)
description: "This is a description"
This is Markdown content
EOF;, (*10)
$frontmatter = $parser->parse($content);, (*11)
echo $frontmatter->head['title']; // My content
echo $frontmatter->getBody(); // This is Markdown content, (*12)
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:
```php
$content = <<<EOF
--- title: My Title ---
# Title 1
## Title 2
EOF;
$content = <<<EOF
---
title: My Title ---
# Title 1
## Title 2
EOF;
Just parse frontmatter, and don't process head and body
$p = new Parser;
$result = $p->parseFrontmatter($content);
echo $result['head'];
echo $result['body'];
Customize the frontmatter delimiter
$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);
Guess parsers from filename
The frontmatter parsers can be guessed from a filename, based on the extensions., (*13)
Take a look at these examples below:, (*14)
-
my_file.json.md: Head in Json and Body in Markdown
-
my_file.md: Head will be parse with the parser set in the constructor, Body in Markdown
-
my_file.unknown: An exception will be thrown
-
my_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'))
;
Guess body parser from head
You can also define explicitly in the head which parser the body should be parsed with., (*15)
$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, (*16)
If the parser could not be fetch from the head, the default body parser will be use., (*17)
More complex usage
$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
}
}
Testing
bash
$ vendor/bin/phpunit, (*18)
Roadmap
- 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
Contributing
Please see CONTRIBUTING for details., (*19)
Credits
Special thank to Etienne Zannelli for his help on Regex ❤, (*20)
License
The MIT License (MIT). Please see License File for more information., (*21)