Skip to content

Commit

Permalink
Improve frontmatter parsing (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
samwilson authored Jun 25, 2022
1 parent 0731e20 commit 4ead05c
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 16 deletions.
50 changes: 34 additions & 16 deletions src/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,33 +101,51 @@ public function getFilename(): string
return $this->site->getDir() . '/content' . $this->getId() . $this->site->getExt();
}

/**
* @return mixed[] With 'metadata' and 'body' keys.
*/
private function parseContents(): array
{
$contents = $this->getContents();
$defaultMetadata = ['template' => 'index'];
preg_match('/^(---+)/', $contents, $hyphenMatches);
if (isset($hyphenMatches[1])) {
$hyphenCount = strlen($hyphenMatches[1]);
$frontmatterClosePos = strpos($contents, $hyphenMatches[1], $hyphenCount);
$frontmatterData = trim(substr($contents, $hyphenCount, $frontmatterClosePos - $hyphenCount));
try {
$parsedMetadata = Yaml::parse($frontmatterData, Yaml::PARSE_DATETIME);
} catch (Throwable $throwable) {
CommandBase::writeln(
'Error reading metadata from ' . $this->getId() . "\n> " . $throwable->getMessage()
);
$parsedMetadata = $defaultMetadata;
}
$metadata = array_merge($defaultMetadata, $parsedMetadata);
$body = substr($contents, $frontmatterClosePos + $hyphenCount);
} else {
$metadata = $defaultMetadata;
$body = $contents;
}
return [
'metadata' => $metadata,
'body' => trim($body),
];
}

/**
* Get a file's metadata.
*
* @return string[]
*/
public function getMetadata(): array
{
$contents = $this->getContents();
preg_match("/---+[\n\r]+(.*)[\n\r]+---+/ms", $contents, $matches);
$defaultMetadata = ['template' => 'index'];
if (!isset($matches[1])) {
return $defaultMetadata;
}
try {
$parsedMetadata = Yaml::parse($matches[1], Yaml::PARSE_DATETIME);
} catch (Throwable $exception) {
CommandBase::writeln('Error reading metadata from ' . $this->getId() . "\n> " . $exception->getMessage());
return $defaultMetadata;
}
return array_merge($defaultMetadata, $parsedMetadata);
return $this->parseContents()['metadata'];
}

public function getBody(): string
{
$contents = $this->getContents();
preg_match("/---+[\n\r]+.*[\n\r]+---+[\n\r]?(.*)/ms", $contents, $matches);
return isset($matches[1]) ? trim($matches[1]) : $contents;
return $this->parseContents()['body'];
}

/**
Expand Down
58 changes: 58 additions & 0 deletions tests/PageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,62 @@ public function testWrite(): void
unlink($newPage->getFilename());
unlink($newPage2->getFilename());
}

/**
* @covers Page::write()
* @dataProvider provideWriting
*
* @param mixed[] $metadata
*/
public function testWriting(string $pageText, array $metadata, string $body): void
{
$site = new Site(__DIR__ . '/test_site');
file_put_contents($site->getDir() . '/content/test_writing.txt', $pageText);
$page = new Page($site, '/test_writing');
static::assertSame($metadata, $page->getMetadata());
static::assertSame($body, $page->getBody());
$page->write($metadata, $body);
static::assertSame($metadata, $page->getMetadata());
static::assertSame($body, $page->getBody());
unlink($page->getFilename());
}

/**
* @return mixed[][]
*/
public function provideWriting(): array
{
return [
'only Yaml no newline' => [
"---\ntemplate: lorem\n---",
['template' => 'lorem'],
'',
],
'only Yaml with multiple newlines' => [
"---\ntemplate: lorem\n---\n\n",
['template' => 'lorem'],
'',
],
'only frontmatter, four hyphens' => [
"----\ntemplate: lorem\n----",
['template' => 'lorem'],
'',
],
'only body no newline' => [
'lorem ipsum',
['template' => 'index'],
'lorem ipsum',
],
'only body multiple newlines' => [
"\n\nlorem ipsum\n\n\n",
['template' => 'index'],
'lorem ipsum',
],
'both Yaml and body' => [
"---\ntemplate: lorem\n---\nIpsum.\n",
['template' => 'lorem'],
'Ipsum.',
],
];
}
}

0 comments on commit 4ead05c

Please sign in to comment.