Add Article properties and tests

This commit is contained in:
Annika Backstrom 2022-05-21 21:21:40 +01:00
parent e3e27708ef
commit 38da57caad
2 changed files with 137 additions and 4 deletions

View File

@ -7,20 +7,42 @@ namespace LogseqGem;
use League\CommonMark\Node\NodeWalker; use League\CommonMark\Node\NodeWalker;
use League\CommonMark\Node\Inline\Text; use League\CommonMark\Node\Inline\Text;
use League\CommonMark\Extension\CommonMark\Node\Inline\Link; use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock;
class ArticleParser extends Parser { class ArticleParser extends Parser {
public function convert() { private ?array $properties;
$gemtext = [];
$link = 0; public function convert(): string {
$gemtext = [];
$this->properties = [];
$in_frontmatter = true;
$walker = $this->document->walker(); $walker = $this->document->walker();
while ($event = $walker->next()) { while ($event = $walker->next()) {
$entering = $event->isEntering(); $entering = $event->isEntering();
$node = $event->getNode(); $node = $event->getNode();
if ($entering && $node instanceof ListBlock) {
$in_frontmatter = false;
continue;
}
if ($entering && $node instanceof Text) { 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) { if ($entering && $node instanceof Link) {
@ -30,9 +52,22 @@ class ArticleParser extends Parser {
} }
$gemtext[] = sprintf('=> %s %s', $node->getUrl(), $label->getLiteral()); $gemtext[] = sprintf('=> %s %s', $node->getUrl(), $label->getLiteral());
continue;
} }
} }
return implode("\n\n", $gemtext); 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');
}
} }

View File

@ -0,0 +1,98 @@
<?php
declare(strict_types=1);
namespace LogseqGem\Tests;
use InvalidArgumentException;
use Exception;
use PHPUnit\Framework\TestCase;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use LogseqGem\ArticleParser;
use RuntimeException;
use SebastianBergmann\RecursionContext\InvalidArgumentException as RecursionContextInvalidArgumentException;
use PHPUnit\Framework\ExpectationFailedException;
class ArticleParserTest extends TestCase {
private vfsStreamDirectory $root;
private ArticleParser $parser;
public function setUp(): void {
$this->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());
}
}