2022-05-21 16:26:52 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace LogseqGem;
|
|
|
|
|
2022-05-21 17:44:11 +00:00
|
|
|
use League\CommonMark\Node\Inline\Text;
|
|
|
|
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
|
2022-05-21 20:21:40 +00:00
|
|
|
use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock;
|
2022-05-24 17:43:03 +00:00
|
|
|
use League\CommonMark\Extension\CommonMark\Node\Block\ListItem;
|
2022-05-21 17:44:11 +00:00
|
|
|
|
2022-05-21 16:26:52 +00:00
|
|
|
class ArticleParser extends Parser {
|
2022-05-21 20:21:40 +00:00
|
|
|
private ?array $properties;
|
|
|
|
|
|
|
|
public function convert(): string {
|
2022-05-21 17:44:11 +00:00
|
|
|
$gemtext = [];
|
2022-05-21 20:21:40 +00:00
|
|
|
$this->properties = [];
|
2022-05-21 17:44:11 +00:00
|
|
|
|
2022-05-21 20:21:40 +00:00
|
|
|
$in_frontmatter = true;
|
2022-05-21 17:44:11 +00:00
|
|
|
|
2022-05-24 17:43:03 +00:00
|
|
|
$node = null; //current node
|
|
|
|
$last_node = null; //updated every time
|
|
|
|
$previous_node = null; // we only update this for significant nodes
|
2022-05-22 09:15:00 +00:00
|
|
|
|
2022-05-24 20:56:15 +00:00
|
|
|
$block_level = 0;
|
|
|
|
$list_item = 0;
|
|
|
|
|
2022-05-21 17:44:11 +00:00
|
|
|
$walker = $this->document->walker();
|
|
|
|
while ($event = $walker->next()) {
|
|
|
|
$entering = $event->isEntering();
|
2022-05-24 17:43:03 +00:00
|
|
|
$last_node = $node;
|
2022-05-21 17:44:11 +00:00
|
|
|
$node = $event->getNode();
|
|
|
|
|
2022-05-24 17:43:03 +00:00
|
|
|
// treat empty node as a newline
|
|
|
|
if ($node instanceof ListItem && $last_node === $node && !$entering) {
|
|
|
|
$gemtext[] = '';
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-05-22 09:15:00 +00:00
|
|
|
if (!$entering) {
|
2022-05-24 20:56:15 +00:00
|
|
|
if ($node instanceof ListBlock) {
|
|
|
|
$block_level -= 1;
|
|
|
|
$list_item = 0;
|
|
|
|
}
|
|
|
|
|
2022-05-22 09:15:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($node instanceof ListBlock) {
|
2022-05-24 20:56:15 +00:00
|
|
|
$block_level += 1;
|
2022-05-21 20:21:40 +00:00
|
|
|
$in_frontmatter = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-05-22 09:15:00 +00:00
|
|
|
if ($node instanceof Text) {
|
2022-05-21 20:21:40 +00:00
|
|
|
$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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-24 20:56:15 +00:00
|
|
|
if ($block_level > 1) {
|
|
|
|
$list_item += 1;
|
|
|
|
|
|
|
|
$leader = $list_item === 1 ? "\n" : "";
|
|
|
|
$gemtext[] = $leader . '* ' . $text;
|
|
|
|
} else {
|
|
|
|
$leader = $previous_node ? "\n" : "";
|
|
|
|
$gemtext[] = $leader . $text;
|
|
|
|
}
|
2022-05-22 09:15:00 +00:00
|
|
|
|
|
|
|
$previous_node = $node;
|
2022-05-21 20:21:40 +00:00
|
|
|
|
|
|
|
continue;
|
2022-05-21 17:44:11 +00:00
|
|
|
}
|
|
|
|
|
2022-05-22 09:15:00 +00:00
|
|
|
if ($node instanceof Link) {
|
2022-05-21 17:44:11 +00:00
|
|
|
$label = $walker->next()->getNode();
|
|
|
|
if (!$label instanceof Text) {
|
|
|
|
throw new \Exception('Expected next node in Link to be Text, got ' . get_class($label));
|
|
|
|
}
|
|
|
|
|
2022-05-22 09:15:00 +00:00
|
|
|
$leader = ($previous_node && !$previous_node instanceof Link) ? "\n" : "";
|
|
|
|
$gemtext[] = $leader . sprintf("=> %s %s", $node->getUrl(), $label->getLiteral());
|
|
|
|
|
|
|
|
$previous_node = $node;
|
2022-05-21 20:21:40 +00:00
|
|
|
|
|
|
|
continue;
|
2022-05-21 17:44:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-22 09:15:00 +00:00
|
|
|
return implode("\n", $gemtext);
|
2022-05-21 17:44:11 +00:00
|
|
|
}
|
2022-05-21 20:21:40 +00:00
|
|
|
|
|
|
|
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');
|
|
|
|
}
|
2022-05-21 16:26:52 +00:00
|
|
|
}
|