logseq2gemtext/src/ArticleParser.php

73 lines
2.0 KiB
PHP

<?php
declare(strict_types=1);
namespace LogseqGem;
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 {
private ?array $properties;
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) {
$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) {
$label = $walker->next()->getNode();
if (!$label instanceof Text) {
throw new \Exception('Expected next node in Link to be Text, got ' . get_class($label));
}
$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');
}
}