From 38da57caad73aa2d70f2ce726d2969ac94106b52 Mon Sep 17 00:00:00 2001 From: Annika Backstrom Date: Sat, 21 May 2022 21:21:40 +0100 Subject: [PATCH] Add Article properties and tests --- src/ArticleParser.php | 43 ++++++++++++++-- tests/ArticleParserTest.php | 98 +++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 tests/ArticleParserTest.php diff --git a/src/ArticleParser.php b/src/ArticleParser.php index 187303d..9a89d76 100644 --- a/src/ArticleParser.php +++ b/src/ArticleParser.php @@ -7,20 +7,42 @@ namespace LogseqGem; use League\CommonMark\Node\NodeWalker; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Extension\CommonMark\Node\Inline\Link; +use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; class ArticleParser extends Parser { - public function convert() { - $gemtext = []; + private ?array $properties; - $link = 0; + public function convert(): string { + $gemtext = []; + $this->properties = []; + + $in_frontmatter = true; $walker = $this->document->walker(); while ($event = $walker->next()) { $entering = $event->isEntering(); $node = $event->getNode(); + if ($entering && $node instanceof ListBlock) { + $in_frontmatter = false; + continue; + } + if ($entering && $node instanceof Text) { - $gemtext[] = $node->getLiteral(); + $text = $node->getLiteral(); + + if ($in_frontmatter) { + if (preg_match('/^([A-Za-z-]+):: (.*)/', $text, $matches)) { + $this->properties[$matches[1]] = $matches[2]; + continue; + } else { + $in_frontmatter = false; + } + } + + $gemtext[] = $text; + + continue; } if ($entering && $node instanceof Link) { @@ -30,9 +52,22 @@ class ArticleParser extends Parser { } $gemtext[] = sprintf('=> %s %s', $node->getUrl(), $label->getLiteral()); + + continue; } } return implode("\n\n", $gemtext); } + + public function getProperties(): array { + if (is_null($this->properties)) { + throw new \Exception("Cannot get properties before converting a document"); + } + return $this->properties; + } + + public function isPublished(): bool { + return (($this->getProperties()['status'] ?? '') === 'published'); + } } diff --git a/tests/ArticleParserTest.php b/tests/ArticleParserTest.php new file mode 100644 index 0000000..32d4fe7 --- /dev/null +++ b/tests/ArticleParserTest.php @@ -0,0 +1,98 @@ +parser = new ArticleParser; + $this->root = vfsStream::setup(); + } + + private function setArticleText(string $text) { + vfsStream::newFile('article.md') + ->withContent($text) + ->at($this->root); + } + + public function testConvertSimple() { + $this->setArticleText("- This is a test line."); + $this->parser->load(vfsStream::url('root/article.md')); + $this->assertSame('This is a test line.', $this->parser->convert()); + } + + public function testConvertLink() { + $this->setArticleText("- [foo](bar)"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->assertSame('=> bar foo', $this->parser->convert()); + } + + public function testMultiParagraph() { + $this->setArticleText("- Block 1\n- Block 2"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->assertSame("Block 1\n\nBlock 2", $this->parser->convert()); + } + + public function testEmpty() { + $this->setArticleText("-"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->assertSame("", $this->parser->convert()); + } + + public function testInterleavedParagraphsAndLinks() { + $this->setArticleText("- Block 1\n- [foo](bar)\n- Block 2"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->assertSame("Block 1\n\n=> bar foo\n\nBlock 2", $this->parser->convert()); + } + + public function testSequentialLinks() { + $this->markTestSkipped('not yet implemented'); + $this->setArticleText("\n- [foo](bar)\n- [bar](foo)"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->assertSame("=> bar foo\n=> foo bar", $this->parser->convert()); + } + + public function testFrontmatter() { + $this->setArticleText("foo:: bar\nanother:: prop\n\n- first line"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->assertSame("first line", $this->parser->convert()); + $this->assertSame(["foo" => "bar", "another" => "prop"], $this->parser->getProperties()); + } + + public function testDraftIsNotPublished() { + $this->setArticleText("status:: draft\n\n- my article"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->parser->convert(); + $this->assertFalse($this->parser->isPublished()); + } + + public function testMissingStatusIsNotPublished() { + $this->setArticleText("status:: draft\n\n- my article"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->parser->convert(); + $this->assertFalse($this->parser->isPublished()); + } + + public function testPublished() { + $this->setArticleText("status:: published\n\n- my article"); + $this->parser->load(vfsStream::url('root/article.md')); + $this->parser->convert(); + $this->assertTrue($this->parser->isPublished()); + } +}