Skip to content

Commit e68d1c4

Browse files
authored
Merge pull request #1149 from phpDocumentor/feature/front-matter
[FEAT] add support for front matter
2 parents 51bae55 + 3f55613 commit e68d1c4

File tree

12 files changed

+341
-3
lines changed

12 files changed

+341
-3
lines changed

composer.lock

Lines changed: 75 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/guides-markdown/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"require": {
2424
"php": "^8.1",
2525
"league/commonmark": "^2.4",
26-
"phpdocumentor/guides": "^1.0 || ^2.0"
26+
"phpdocumentor/guides": "^1.0 || ^2.0",
27+
"symfony/yaml": "^6.4 || ^7.0"
2728
},
2829
"extra": {
2930
"branch-alias": {

packages/guides-markdown/resources/config/guides-markdown.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use phpDocumentor\Guides\Markdown\MarkupLanguageParser;
66
use phpDocumentor\Guides\Markdown\Parsers\BlockQuoteParser;
77
use phpDocumentor\Guides\Markdown\Parsers\CodeBlockParser;
8+
use phpDocumentor\Guides\Markdown\Parsers\FrontMatter\TitleParser;
9+
use phpDocumentor\Guides\Markdown\Parsers\FrontMatterParser;
810
use phpDocumentor\Guides\Markdown\Parsers\HeaderParser;
911
use phpDocumentor\Guides\Markdown\Parsers\HtmlParser;
1012
use phpDocumentor\Guides\Markdown\Parsers\InlineParsers\EmphasisParser;
@@ -82,6 +84,13 @@
8284
->set(NewLineParser::class)
8385
->tag('phpdoc.guides.markdown.parser.inlineParser')
8486

87+
->set(FrontMatterParser::class)
88+
->arg('$fieldParsers', tagged_iterator('phpdoc.guides.markdown.front_matter', 'fieldName'))
89+
->tag('phpdoc.guides.markdown.parser.blockParser')
90+
91+
->set(TitleParser::class)
92+
->tag('phpdoc.guides.markdown.front_matter')
93+
8594
->set(MarkupLanguageParser::class)
8695
->arg('$parsers', tagged_iterator('phpdoc.guides.markdown.parser.blockParser'))
8796
->tag('phpdoc.guides.parser.markupLanguageParser');

packages/guides-markdown/src/Markdown/MarkupLanguageParser.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use League\CommonMark\Environment\Environment as CommonMarkEnvironment;
1717
use League\CommonMark\Extension\Autolink\AutolinkExtension;
1818
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
19+
use League\CommonMark\Extension\FrontMatter\Data\SymfonyYamlFrontMatterParser;
20+
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
1921
use League\CommonMark\Extension\Table\TableExtension;
2022
use League\CommonMark\Node\Block\Document;
2123
use League\CommonMark\Node\NodeWalker;
@@ -54,6 +56,7 @@ public function __construct(
5456
$cmEnvironment->addExtension(new CommonMarkCoreExtension());
5557
$cmEnvironment->addExtension(new TableExtension());
5658
$cmEnvironment->addExtension(new AutolinkExtension());
59+
$cmEnvironment->addExtension(new FrontMatterExtension(new SymfonyYamlFrontMatterParser()));
5760
$this->markdownParser = new MarkdownParser($cmEnvironment);
5861
// if for backward compatibility reasons no settings manager was passed, use the defaults
5962
$this->settingsManager = $settingsManager ?? new SettingsManager(new ProjectSettings());
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\Markdown;
15+
16+
use phpDocumentor\Guides\Nodes\TextNode;
17+
18+
final class NullNode extends TextNode
19+
{
20+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\Markdown\Parsers\FrontMatter;
15+
16+
use phpDocumentor\Guides\Nodes\DocumentNode;
17+
use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode;
18+
use phpDocumentor\Guides\Nodes\Metadata\AuthorNode;
19+
20+
final class AuthorParser implements Parser
21+
{
22+
/** {@inheritDoc} */
23+
public function process(DocumentNode $document, mixed $value, array $frontMatter): void
24+
{
25+
$value = '' . $value;
26+
$document->addHeaderNode(new AuthorNode($value, [new PlainTextInlineNode($value)]));
27+
}
28+
29+
public function field(): string
30+
{
31+
return 'title';
32+
}
33+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\Markdown\Parsers\FrontMatter;
15+
16+
use phpDocumentor\Guides\Nodes\DocumentNode;
17+
18+
interface Parser
19+
{
20+
public function field(): string;
21+
22+
/** @param array<string, mixed> $frontMatter */
23+
public function process(DocumentNode $document, mixed $value, array $frontMatter): void;
24+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\Markdown\Parsers\FrontMatter;
15+
16+
use phpDocumentor\Guides\Nodes\DocumentNode;
17+
18+
final class TitleParser implements Parser
19+
{
20+
/** {@inheritDoc} */
21+
public function process(DocumentNode $document, mixed $value, array $frontMatter): void
22+
{
23+
$document->setMetaTitle('' . $value);
24+
}
25+
26+
public function field(): string
27+
{
28+
return 'title';
29+
}
30+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\Markdown\Parsers;
15+
16+
use League\CommonMark\Node\Block\Document;
17+
use League\CommonMark\Node\Node as CommonMarkNode;
18+
use League\CommonMark\Node\NodeWalker;
19+
use League\CommonMark\Node\NodeWalkerEvent;
20+
use phpDocumentor\Guides\Markdown\NullNode;
21+
use phpDocumentor\Guides\Markdown\ParserInterface;
22+
use phpDocumentor\Guides\Markdown\Parsers\FrontMatter\Parser as FieldParser;
23+
use phpDocumentor\Guides\MarkupLanguageParser as GuidesParser;
24+
use phpDocumentor\Guides\Nodes\Node;
25+
26+
use function array_key_exists;
27+
use function is_array;
28+
29+
/** @implements ParserInterface<NullNode> */
30+
final class FrontMatterParser implements ParserInterface
31+
{
32+
/** @var array<string, FieldParser> */
33+
private array $fieldParsers;
34+
35+
/** @param iterable<string, FieldParser> $fieldParsers */
36+
public function __construct(iterable $fieldParsers)
37+
{
38+
foreach ($fieldParsers as $parser) {
39+
$this->fieldParsers[$parser->field()] = $parser;
40+
}
41+
}
42+
43+
public function parse(GuidesParser $parser, NodeWalker $walker, CommonMarkNode $current): Node
44+
{
45+
$frontMatter = $current->data->get('front_matter', []);
46+
if (is_array($frontMatter) === false) {
47+
return new NullNode('');
48+
}
49+
50+
foreach ($frontMatter as $field => $value) {
51+
if (!array_key_exists($field, $this->fieldParsers)) {
52+
continue;
53+
}
54+
55+
$this->fieldParsers[$field]->process($parser->getDocument(), $value, $frontMatter);
56+
}
57+
58+
return new NullNode('');
59+
}
60+
61+
public function supports(NodeWalkerEvent $event): bool
62+
{
63+
return $event->getNode() instanceof Document;
64+
}
65+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!DOCTYPE html>
2+
<html class="no-js" lang="en">
3+
<head>
4+
<title>Front Matter</title>
5+
<!-- Required meta tags -->
6+
<meta charset="utf-8">
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
9+
</head>
10+
<body>
11+
<header class="">
12+
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
13+
<div class="container">
14+
<a class="navbar-brand" href="#">Navbar</a>
15+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
16+
<span class="navbar-toggler-icon"></span>
17+
</button>
18+
<div class="collapse navbar-collapse" id="navbarSupportedContent">
19+
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
20+
</ul>
21+
</div>
22+
</div>
23+
</nav>
24+
</header>
25+
<main id="main-content">
26+
<div class="container">
27+
<div class="container">
28+
<div class="row">
29+
<div class="col-lg-3">
30+
<nav class="nav flex-column">
31+
<ul class="menu-level-main">
32+
</ul>
33+
</nav>
34+
</div>
35+
<div class="col-lg-9">
36+
<nav aria-label="breadcrumb">
37+
<ol class="breadcrumb">
38+
<li class="breadcrumb-item"><a href="#">Document Title</a></li>
39+
</ol>
40+
</nav>
41+
<!-- content start -->
42+
<div class="section" id="document-title">
43+
<h1>Document Title</h1>
44+
<p>Lorem Ipsum Dolor.</p>
45+
</div>
46+
<!-- content end -->
47+
</div>
48+
</div>
49+
</div>
50+
</div>
51+
</main>
52+
<!-- Optional JavaScript; choose one of the two! -->
53+
<!-- Option 1: Bootstrap Bundle with Popper -->
54+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
55+
<!-- Option 2: Separate Popper and Bootstrap JS -->
56+
<!--
57+
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
58+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
59+
-->
60+
</body>
61+
</html>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<guides xmlns="https://www.phpdoc.org/guides"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="https://www.phpdoc.org/guides packages/guides-cli/resources/schema/guides.xsd"
5+
theme="bootstrap"
6+
input-format="md"
7+
links-are-relative="1"
8+
automatic-menu="true"
9+
>
10+
<extension class="phpDocumentor\Guides\Bootstrap"/>
11+
</guides>

0 commit comments

Comments
 (0)