diff options
Diffstat (limited to 'src/Gemtext.php')
-rw-r--r-- | src/Gemtext.php | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/Gemtext.php b/src/Gemtext.php new file mode 100644 index 0000000..d382c45 --- /dev/null +++ b/src/Gemtext.php @@ -0,0 +1,99 @@ +<?php + +namespace GeminiFoundation; + +class Gemtext +{ + protected string $input; + protected array $output; + + protected string $preformattedMode = 'off'; + + public function __construct(string $input) + { + $this->input = $input; + } + + public function parse(): array + { + $input = fopen('php://temp', 'r+'); + fputs($input, $this->input); + rewind($input); + + $output = []; + while ($line = fgets($input)) { + $output[] = $this->parseLine($line); + } + + fclose($input); + + return $this->output = $output; + } + + private function parseLine(string $input) + { + $line = [ + 'raw' => $input, + ]; + + $input = ltrim($input); + + if (str_starts_with($input, '```')) { + $this->preformattedMode = $this->preformattedMode === 'on' ? 'off' : 'on'; + + $line['type'] = $this->preformattedMode === 'on' ? 'preformatted_on' : 'preformatted_off'; + $line['text'] = $line['alt'] = trim(substr($input, 3)); + } + else if ($this->preformattedMode === 'on') { + $line['type'] = 'preformatted'; + $line['text'] = $line['raw']; + } + + else if (str_starts_with($input, '#')) { + $firstWhitespacePosition = $this->findWhitespace($input); + + $line['type'] = 'heading'; + $line['size'] = substr_count( + haystack: $input, + needle: '#', + length: min($firstWhitespacePosition, 3) + ); + $line['text'] = trim(substr( + string: $input, + offset: min($firstWhitespacePosition, 3) + )); + } + else if (str_starts_with($input, '*')) { + $line['type'] = 'listitem'; + $line['text'] = trim(substr($input, 1)); + } + else if (str_starts_with($input, '>')) { + $line['type'] = 'quote'; + $line['text'] = trim(substr($input, 1)); + } + else if (str_starts_with($input, '=>')) { + $whitespacePosition = $this->findWhitespace($input, 3); + + $link = substr(string: $input, offset: 2, length: $whitespacePosition - 2); + $text = substr(string: $input, offset: $whitespacePosition); + + $line['type'] = 'link'; + $line['link'] = trim($link); + $line['text'] = trim($text); + } + else { + $line['type'] = 'text'; + $line['text'] = rtrim($input); + } + + return $line; + } + + private function findWhitespace(string $input, int $offset = 0): int + { + $space = strpos($input, ' ', $offset); + $tab = strpos($input, "\t", $offset); + + return $space === false ? ($tab === false ? PHP_INT_MAX : $tab) : $space; + } +} |