Skip to content

Commit

Permalink
Merge pull request #115 from froschdesign/feature/markdown-parser
Browse files Browse the repository at this point in the history
Updates Markdown parser to use existing extensions for parsing front matter and table of contents
  • Loading branch information
weierophinney committed Nov 2, 2022
2 parents e876529 + 3be62e0 commit f5538d3
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 124 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"forum": "https://discourse.laminas.dev"
},
"require": {
"php": "~8.1.12",
"php": "~8.1.0",
"ext-pdo": "*",
"dflydev/fig-cookies": "^3.0",
"laminas/laminas-cli": "^1.7",
Expand Down
18 changes: 10 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 16 additions & 13 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.28.0@52e96bea381e6cb07a672aefec791a5817694a26">
<files psalm-version="4.29.0@7ec5ffbd5f68ae03782d7fd33fff0c45a69f95b3">
<file src="bin/clear-config-cache.php">
<MixedArgument occurrences="5">
<code>$config['config_cache_path']</code>
Expand Down Expand Up @@ -64,13 +64,11 @@
<code>static::FOLDER_COLLECTION</code>
</MixedOperand>
</file>
<file src="src/App/FrontMatter/Document.php">
<MixedInferredReturnType occurrences="1">
<file src="src/App/ContentParser/Document.php">
<MixedReturnTypeCoercion occurrences="2">
<code>(array) $this-&gt;renderedContent-&gt;getFrontMatter()</code>
<code>array</code>
</MixedInferredReturnType>
<MixedReturnStatement occurrences="1">
<code>$this-&gt;document-&gt;matter()</code>
</MixedReturnStatement>
</MixedReturnTypeCoercion>
</file>
<file src="src/App/Handler/StaticPageHandler.php">
<PossiblyFalseArgument occurrences="1">
Expand Down Expand Up @@ -142,16 +140,14 @@
</RedundantConditionGivenDocblockType>
</file>
<file src="src/Blog/CreateBlogPostFromDataArray.php">
<MixedArgument occurrences="9">
<DocblockTypeContradiction occurrences="1">
<code>explode('|', trim((string) $post['tags'], '|'))</code>
</DocblockTypeContradiction>
<MixedArgument occurrences="4">
<code>$metadata['email'] ?? ''</code>
<code>$metadata['name'] ?? '[email protected]'</code>
<code>$metadata['uri'] ?? ''</code>
<code>$post['author']</code>
<code>$post['created']</code>
<code>$post['id']</code>
<code>$post['path']</code>
<code>$post['title']</code>
<code>$post['updated']</code>
</MixedArgument>
<MixedArrayAccess occurrences="3">
<code>$metadata['email']</code>
Expand All @@ -161,6 +157,13 @@
<MixedAssignment occurrences="1">
<code>$metadata</code>
</MixedAssignment>
<RedundantCastGivenDocblockType occurrences="2">
<code>(bool) $post['draft']</code>
<code>(bool) $post['public']</code>
</RedundantCastGivenDocblockType>
<RedundantConditionGivenDocblockType occurrences="1">
<code>is_array($post['tags'])</code>
</RedundantConditionGivenDocblockType>
</file>
<file src="src/Blog/Handler/DisplayPostHandler.php">
<MixedArgument occurrences="1">
Expand Down
12 changes: 6 additions & 6 deletions src/App/AbstractCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace App;

use App\FrontMatter\ParserInterface;
use App\ContentParser\ParserInterface;
use RuntimeException;

use function file_exists;
Expand All @@ -25,7 +25,7 @@ abstract class AbstractCollection

protected array $collection = [];

public function __construct(protected ParserInterface $frontMatterParser)
public function __construct(protected ParserInterface $contentParser)
{
if (empty(static::CACHE_FILE)) {
throw new RuntimeException('The cache file path is not defined!');
Expand All @@ -48,8 +48,8 @@ public function getFromFile(string $file): array
{
$result = [];
if (file_exists($file)) {
$doc = $this->frontMatterParser->parse($file);
$result = $doc->getYAML();
$doc = $this->contentParser->parse($file);
$result = $doc->getFrontMatter();
$result['body'] = $doc->getContent();
}
return $result;
Expand All @@ -62,8 +62,8 @@ protected function buildCache(): void
}

foreach (glob(static::FOLDER_COLLECTION . '/*.md') as $file) {
$doc = $this->frontMatterParser->parse($file);
$fields = $doc->getYAML();
$doc = $this->contentParser->parse($file);
$fields = $doc->getFrontMatter();
$this->collection[$file] = $fields;
}

Expand Down
31 changes: 31 additions & 0 deletions src/App/ContentParser/Document.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace App\ContentParser;

use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;

final class Document implements DocumentInterface
{
public function __construct(
private readonly RenderedContentWithFrontMatter $renderedContent,
private readonly ?string $tableOfContents
) {
}

public function getFrontMatter(): array
{
return (array) $this->renderedContent->getFrontMatter();
}

public function getTableOfContents(): ?string
{
return $this->tableOfContents;
}

public function getContent(): string
{
return $this->renderedContent->getContent();
}
}
26 changes: 26 additions & 0 deletions src/App/ContentParser/DocumentInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\ContentParser;

interface DocumentInterface
{
/**
* @return array{
* id: string,
* author: string,
* title: string,
* draft: bool,
* public: bool,
* created: string,
* updated: string,
* tags: list<string>
* }
*/
public function getFrontMatter(): array;

public function getTableOfContents(): ?string;

public function getContent(): string;
}
96 changes: 96 additions & 0 deletions src/App/ContentParser/Parser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

declare(strict_types=1);

namespace App\ContentParser;

use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\DefaultAttributes\DefaultAttributesExtension;
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
use League\CommonMark\Extension\Table\Table;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
use League\CommonMark\Extension\TableOfContents\TableOfContentsExtension;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\Node\Query;
use League\CommonMark\Parser\MarkdownParser;
use League\CommonMark\Renderer\HtmlRenderer;

use function file_get_contents;

final class Parser implements ParserInterface
{
private readonly MarkdownConverter $converter;

private readonly MarkdownParser $parser;

private readonly HtmlRenderer $renderer;

public function __construct()
{
// Create default converter
$environment = new Environment(
[
'default_attributes' => [
Table::class => [
'class' => 'table table-striped table-bordered table-hover',
],
],
'heading_permalink' => [
'insert' => 'after',
'min_heading_level' => 1,
'max_heading_level' => 2,
],
]
);
$environment->addExtension(new CommonMarkCoreExtension());
$environment->addExtension(new DefaultAttributesExtension());
$environment->addExtension(new FrontMatterExtension());
$environment->addExtension(new HeadingPermalinkExtension());
$environment->addExtension(new TableExtension());

$this->converter = new MarkdownConverter($environment);

// Create parser and renderer for table of contents
$environment = new Environment(
[
'table_of_contents' => [
'min_heading_level' => 2,
'max_heading_level' => 2,
],
]
);
$environment->addExtension(new CommonMarkCoreExtension());
$environment->addExtension(new FrontMatterExtension());
$environment->addExtension(new HeadingPermalinkExtension());
$environment->addExtension(new TableOfContentsExtension());

$this->parser = new MarkdownParser($environment);
$this->renderer = new HtmlRenderer($environment);
}

public function parse(string $file): DocumentInterface
{
$markdown = file_get_contents($file);

// Render markdown content
/** @var RenderedContentWithFrontMatter $renderedContent */
$renderedContent = $this->converter->convert($markdown);

// Extract table of contents
$document = $this->parser->parse($markdown);
$node = (new Query())
->where(Query::type(TableOfContents::class))
->findOne($document);

$tableOfContents = null;
if ($node) {
$tableOfContents = $this->renderer->renderNodes([$node]);
}

return new Document($renderedContent, $tableOfContents);
}
}
2 changes: 1 addition & 1 deletion src/App/FrontMatter/ParserInterface.php → src/App/ContentParser/ParserInterface.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace App\FrontMatter;
namespace App\ContentParser;

interface ParserInterface
{
Expand Down
Loading

0 comments on commit f5538d3

Please sign in to comment.