diff options
Diffstat (limited to 'Digitigrade/Page.php')
| -rw-r--r-- | Digitigrade/Page.php | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/Digitigrade/Page.php b/Digitigrade/Page.php new file mode 100644 index 0000000..963a27d --- /dev/null +++ b/Digitigrade/Page.php @@ -0,0 +1,75 @@ +<?php +namespace Digitigrade; + +use Digitigrade\FormattingProvider\CommonMark; +use Digitigrade\FormattingProvider\SanitisedHtml; +use Digitigrade\Model\Note; + +class Page implements \JsonSerializable { + public string $title; + public array $content; + /** @var PageLink[] */ + public array $links; + + public static function create(string $title, array $content) { + $page = new self(); + $page->title = $title; + $page->content = $content; + $page->links = []; + return $page; + } + + /** + * Gets the best available formatted content (or plain if there aren't any) + * and converts it to sanitised HTML + * @return string HTML that is hopefully safe to include directly + */ + public function getBestContentAsHtml(): string { + if (isset($this->content['text/html'])) { + return SanitisedHtml::getInstance()->renderToHtml($this->insertLinks($this->content['text/html'], 'text/html')); + } elseif (isset($this->content['text/markdown'])) { + return CommonMark::getInstance()->renderToHtml($this->insertLinks($this->content['text/markdown'], 'text/markdown')); + } + return htmlspecialchars($this->insertLinks($this->content['text/plain'] ?? __('placeholder'), 'text/plain')); + } + + private function insertLinks(string $originalContent, string $mediaType): string { + $result = $originalContent; + $offset = 0; + + foreach ($this->links as $link) { + $range = $link->range[$mediaType] ?? null; + $targetNote = Note::findByUri($link->target); + if ($range == null || $targetNote == null) + continue; + $target = path_to_uri(htmlspecialchars($targetNote->getLocalUiHref(true))); + $before = mb_substr($result, 0, $range->start, 'utf-8'); + $label = mb_substr($result, $range->start, $range->end - $range->start, 'utf-8'); + $after = mb_substr($result, $range->end, null, 'utf-8'); + $startTag = match ($mediaType) { + 'text/html' => '<a href="' . htmlspecialchars($target) . '">', + 'text/markdown' => '[', + 'text/plain' => '', + default => '' + }; + $endTag = match ($mediaType) { + 'text/html' => '</a>', + 'text/markdown' => '](' . htmlspecialchars($target) . ')', + 'text/plain' => " ($target)", + default => '' + }; + $result = $before . $startTag . $label . $endTag . $after; + $offset += strlen($startTag) + strlen($endTag); + } + + return $result; + } + + public function jsonSerialize(): array { + return [ + 'title' => $this->title, + 'content' => $this->content, + 'links' => $this->links + ]; + } +}
\ No newline at end of file |
