summaryrefslogtreecommitdiff
path: root/src/Gemtext.php
diff options
context:
space:
mode:
authorDaniel Weipert <code@drogueronin.de>2023-11-12 11:16:56 +0100
committerDaniel Weipert <code@drogueronin.de>2023-11-20 17:30:04 +0100
commit6df3d321d9b67c4541f50158b087d37c4b22e886 (patch)
tree06031988bb4b957b76f051af366ced448a48545f /src/Gemtext.php
initial commit
Diffstat (limited to 'src/Gemtext.php')
-rw-r--r--src/Gemtext.php99
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;
+ }
+}