diff --git a/README.md b/README.md
index 6bfa299..39de76d 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,12 @@
PHP 8 Library for [Gemini Protocol](https://geminiprotocol.net)
+_For optimization reasons, some experimental features like `Dokuwiki` and `GTK3/Pango` was dropped from `1.0.0` release, but available in [previous versions](https://github.com/YGGverse/gemini-php/releases/tag/0.10.1). `Gemtext` component re-implemented as separated library (see [Extras](#extras))_
+
+## Extras
+
+* [gemtext-php](https://github.com/YGGverse/gemtext-php) - Object-oriented PHP 8 library for Gemini / Gemtext operations
+
## Usage
```
@@ -109,397 +115,9 @@ var_dump(
);
```
-## Gemtext
-
-Object-oriented API for Gemtext
-
-**Deprecated and will be removed in future releases! Use [gemtext-php](https://github.com/YGGverse/gemtext-php) instead.**
-
-### Body
-
-Basic methods to work with `text/gemini` documents
-
-``` php
-$body = new \Yggverse\Gemini\Gemtext\Body(
- $response->getBody() // gemtext body from client response or .gmi file content
-);
-```
-
-#### Body::getLines
-#### Body::getLine
-#### Body::getH1
-#### Body::getH2
-#### Body::getH3
-#### Body::getQuote
-#### Body::getCode
-#### Body::getLinks
-
-``` php
-var_dump(
- $body->getLinks() // returns array of links (with line number in key)
-);
-```
-
-#### Body::findLinks
-
-Find context links by protocol as argument, `gemini` by default
-
-``` php
-var_dump(
- $body->findLinks('http') // returns array of http links only (with line number in key)
-);
-```
-
-#### Body::skipTags
-
-Strip gemini tags from Gemini document
-
-``` php
-var_dump(
- $body->skipTags() // strip all tags
-);
-
-var_dump(
- $body->skipTags(
- [ // 1- and 2- level headers only
- "##",
- "###"
- ]
- )
-);
-```
-
-### Link
-
-Inline links parser.
-
-Allows to extract address, date with timestamp and alt text from link line given
-
-``` php
-foreach ($body->getLinks() as $line)
-{
- $link = new \Yggverse\Gemini\Gemtext\Link(
- $line
- );
-
- var_dump(
- $link->getAddress()
- );
-
- var_dump(
- $link->getAlt()
- );
-}
-```
-
-#### Link::getAddress
-#### Link::getDate
-
-This method also validates time format and returns the unix timestamp as linked argument
-
-``` php
-var_dump(
- $link->getDate(
- $timestamp // get unix time from this variable
- )
-);
-
-var_dump(
- $timestamp
-);
-```
-
-#### Link::getAlt
-
-## GTK3
-
-### Pango
-
-Converter to GTK3-compatible Pango format
-
-#### Pango::fromGemtext
-
-``` php
-$pango = \Yggverse\Gemini\Pango::fromGemtext(
- $gemtext
-);
-```
-
-#### Pango::fromGemtextBody
-
-``` php
-$pango = \Yggverse\Gemini\Pango::fromGemtextBody(
- new \Yggverse\Gemini\Gemtext\Body(
- $gemtext
- )
-);
-```
-
-## DokuWiki
-
-Toolkit provides DokuWiki API for Gemini.
-
-Allows to simple deploy new apps or make existing website mirror
-
-### Examples
-
-* [β-Doku](https://github.com/YGGverse/bdoku) - DokuWiki Satellite for Gemini Protocol
-
-### Reader
-
-Read DokuWiki and convert to Gemini
-
-``` php
-$reader = new \Yggverse\Gemini\Dokuwiki\Reader(
- // optional regex rule set array
-);
-```
-
-#### Reader::getRules
-#### Reader::setRules
-#### Reader::getRule
-#### Reader::setRule
-
-Get or change existing regex rule (or just skip by using build-in set)
-
-``` php
-echo $reader->setRule(
- '/subject/ui',
- 'replacement'
-);
-```
-
-#### Reader::getMacroses
-#### Reader::setMacroses
-#### Reader::getMacros
-#### Reader::setMacros
-
-``` php
-echo $reader->setMacros(
- '~my-macros-key~',
- '~my-macros-value~',
-);
-```
-
-#### Reader::toGemini
-
-Convert DokuWiki text to Gemini markup
-
-As wiki has lot of inline links, to make converted document well-readable, this method does not replace links with new line `=>` macros, but uses inline context: `Name ( URL )`. This model useful with `Reader::getLinks` method, that for example appends all those related links to the document footer.
-
-If you don't like this implementation, feel free to change it by `Reader::setRule` method!
-
-``` php
-echo $reader->toGemini(
- file_get_contents(
- '/host/data/pages/index.txt'
- )
-);
-```
-
-#### Reader::getH1
-
-Get document title
-
-``` php
-$gemini = $reader->toGemini(
- file_get_contents(
- '/host/data/pages/index.txt'
- )
-);
-
-echo $reader->getH1(
- $gemini
-);
-```
-
-#### Reader::getLinks
-
-Get document links
-
-``` php
-$gemini = $reader->toGemini(
- file_get_contents(
- '/host/data/pages/index.txt'
- )
-);
-
-echo $reader->getLinks(
- $gemini
-);
-```
-
-### Filesystem
-
-Provides methods for simple and secure interaction with DokuWiki file storage
-
-``` php
-$filesystem = new \Yggverse\Gemini\Dokuwiki\Filesystem(
- '/host/data' // storage location
-);
-```
-
-#### Filesystem::getList
-
-Return simple array of all files in storage
-
-``` php
-var_dump (
- $filesystem->getList(
- 'hello:world'
- )
-);
-```
-
-#### Filesystem::getTree
-
-Return all files under the storage folder in tree format
-
-``` php
-var_dump (
- $filesystem->getTree(
- 'hello:world'
- )
-);
-```
-
-#### Filesystem::getPagePathsByPath
-
-Return pages under the given data directory
-
-``` php
-var_dump (
- $filesystem->getPagePathsByPath(
- // absolute path to target data directory (e.g. Filesystem::getDirectoryPathByUri)
- )
-);
-```
-
-#### Filesystem::getDirectoryPathByUri
-#### Filesystem::getPagePathByUri
-
-Return absolute path to stored page file
-
-``` php
-var_dump (
- $filesystem->getPagePathByUri(
- 'hello:world'
- )
-);
-```
-
-#### Filesystem::getDirectoryUriByPath
-#### Filesystem::getPageUriByPath
-
-Return page URI in `dokuwiki:format`
-
-``` php
-var_dump (
- $filesystem->getPageUriByPath(
- '/full/path/to/page.txt'
- )
-);
-```
-
-#### Filesystem::getMediaPathByUri
-
-Return absolute path to stored media file
-
-``` php
-var_dump (
- $filesystem->getMediaPathByUri(
- 'hello:world'
- )
-);
-```
-
-#### Filesystem::getMimeByPath
-
-Return file MIME if path match storage item
-
-``` php
-var_dump (
- $filesystem->getMimeByPath(
- '/full/path/to/page.txt'
- )
-);
-```
-
-#### Filesystem::getDataByPath
-
-Return file content if path match storage item
-
-``` php
-var_dump (
- $filesystem->getDataByPath(
- '/full/path/to/page.txt'
- )
-);
-```
-
-#### Filesystem::isPath
-
-Check path exist and match storage item
-
-``` php
-var_dump (
- $filesystem->isPath(
- '/full/path/to/page.txt'
- )
-);
-```
-
-### Helper
-
-Useful methods to minify controller codebase
-
-``` php
-$helper = new \Yggverse\Gemini\Dokuwiki\Helper(
- new \Yggverse\Gemini\Dokuwiki\Filesystem(),
- new \Yggverse\Gemini\Dokuwiki\Reader()
-);
-```
-
-#### Helper::getChildrenSectionLinksByUri
-
-Return simple array of children section links in Gemini format
-
-``` php
-var_dump (
- $helper->getChildrenSectionLinksByUri(
- 'hello:world'
- )
-);
-```
-
-#### Helper::getChildrenPageLinksByUri
-
-Return simple array of children page links in Gemini format
-
-``` php
-var_dump (
- $helper->getChildrenPageLinksByUri(
- 'hello:world'
- )
-);
-```
-
-#### Helper::getPageLinkByPath
-
-Return page link (that contain document name) in Gemini format
-
-``` php
-var_dump (
- $helper->getPageLinkByPath(
- $filesystem->getPagePathByUri(
- 'hello:world'
- )
- )
-);
-```
-
## Integrations
-* [β-Doku is DokuWiki Satellite for Gemini Protocol](https://github.com/YGGverse/bdoku)
-* [Yo! Crawler for different networks](https://github.com/YGGverse/Yo/tree/gemini)
-* [Yoda - PHP-GTK browser for Gemini Protocol](https://github.com/YGGverse/Yoda)
\ No newline at end of file
+* [gemini-dl](https://github.com/YGGverse/gemini-dl) - CLI Batch downloader for Gemini Protocol
+* [Yo!](https://github.com/YGGverse/Yo/tree/gemini) - Crawler for different networks
+* [Yoda](https://github.com/YGGverse/Yoda) - PHP-GTK browser for Gemini Protocol
+* [β-Doku](https://github.com/YGGverse/bdoku) - DokuWiki Satellite for Gemini Protocol
\ No newline at end of file
diff --git a/composer.json b/composer.json
index efc7aa6..33c1ae1 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "yggverse/gemini",
"description": "PHP 8 Library for Gemini Protocol",
- "keywords": [ "yggverse", "gemini", "wiki", "dokuwiki", "markdown" ],
+ "keywords": [ "yggverse", "gemini", "gemini-protocol", "client", "request", "response" ],
"homepage": "https://github.com/yggverse/gemini-php",
"type": "library",
"license": "MIT",
@@ -10,7 +10,5 @@
"Yggverse\\Gemini\\": "src/"
}
},
- "require": {
- "dekor/php-array-table": "^2.0"
- }
+ "require": {}
}
diff --git a/src/Client/Request.php b/src/Client/Request.php
index 560a1fd..183ce56 100644
--- a/src/Client/Request.php
+++ b/src/Client/Request.php
@@ -17,8 +17,10 @@ class Request
[
'ssl' =>
[
- 'verify_peer' => false,
- 'verify_peer_name' => false
+ 'allow_self_signed' => true,
+ 'disable_compression' => true,
+ 'verify_peer_name' => false,
+ 'verify_peer' => false
]
];
@@ -184,7 +186,10 @@ class Request
$this->_host,
$this->_port,
$this->_path,
- $this->_query
+ $this->_query ? sprintf(
+ '?%s',
+ $this->_query
+ ) : null
)
);
diff --git a/src/Dokuwiki/Filesystem.php b/src/Dokuwiki/Filesystem.php
deleted file mode 100644
index 33b79c2..0000000
--- a/src/Dokuwiki/Filesystem.php
+++ /dev/null
@@ -1,277 +0,0 @@
-_path = rtrim(
- $path,
- '/'
- );
-
- $this->_index(
- $this->_path
- );
- }
-
- public function getTree(): array
- {
- return $this->_tree;
- }
-
- public function getList(): array
- {
- return $this->_list;
- }
-
- public function getPagePathsByPath(string $path): ?array
- {
- if (isset($this->_tree[$path]))
- {
- return $this->_tree[$path];
- }
-
- return null;
- }
-
- public function getPagePathByUri(string $uri): ?string
- {
- $path = sprintf(
- '%s/pages/%s.txt',
- $this->_path,
- str_replace(
- ':',
- '/',
- mb_strtolower(
- urldecode(
- $uri
- )
- )
- )
- );
-
- if (!$this->isPath($path))
- {
- return null;
- }
-
- return $path;
- }
-
- public function getPageUriByPath(string $path): ?string
- {
- if (!$this->isPath($path))
- {
- return null;
- }
-
- $path = str_replace(
- sprintf(
- '%s/pages/',
- $this->_path
- ),
- '',
- $path
- );
-
- $path = trim(
- $path,
- '/'
- );
-
- $path = str_replace(
- [
- '/',
- '.txt'
- ],
- [
- ':',
- null
- ],
- $path
- );
-
- return $path;
- }
-
- public function getDirectoryPathByUri(string $uri = ''): ?string
- {
- $path = rtrim(
- sprintf(
- '%s/pages/%s',
- $this->_path,
- str_replace(
- ':',
- '/',
- mb_strtolower(
- urldecode(
- $uri
- )
- )
- )
- ),
- '/'
- );
-
- if (!isset($this->_tree[$path]) || !is_dir($path) || !is_readable($path))
- {
- return null;
- }
-
- return $path;
- }
-
- public function getDirectoryUriByPath(string $path): ?string
- {
- if (!isset($this->_tree[$path]) || !is_dir($path) || !is_readable($path))
- {
- return null;
- }
-
- $path = str_replace(
- sprintf(
- '%s/pages',
- $this->_path
- ),
- '',
- $path
- );
-
- $path = trim(
- $path,
- '/'
- );
-
- $path = str_replace(
- [
- '/'
- ],
- [
- ':'
- ],
- $path
- );
-
- return $path;
- }
-
- public function getMediaPathByUri(string $uri): ?string
- {
- $path = sprintf(
- '%s/media/%s',
- $this->_path,
- str_replace(
- ':',
- '/',
- mb_strtolower(
- urldecode(
- $uri
- )
- )
- )
- );
-
- if (!$this->isPath($path))
- {
- return null;
- }
-
- return $path;
- }
-
- public function getMimeByPath(?string $path): ?string
- {
- if ($this->isPath($path))
- {
- if ($mime = mime_content_type($path))
- {
- return $mime;
- }
- }
-
- return null;
- }
-
- public function getDataByPath(?string $path): ?string
- {
- if ($this->isPath($path))
- {
- if ($data = file_get_contents($path))
- {
- return $data;
- }
- }
-
- return null;
- }
-
- public function isPath(?string $path): bool
- {
- if (in_array($path, $this->_list) && is_file($path) && is_readable($path))
- {
- return true;
- }
-
- return false;
- }
-
- private function _index(
- string $path,
- ?array $blacklist = ['sidebar.txt', '__template.txt']
- ): void
- {
- foreach ((array) scandir($path) as $file)
- {
- if (str_starts_with($file, '.'))
- {
- continue;
- }
-
- if (is_link($file))
- {
- continue;
- }
-
- if (in_array($file, $blacklist))
- {
- continue;
- }
-
- $file = sprintf(
- '%s/%s',
- $path,
- $file
- );
-
- switch (true)
- {
- case is_dir($file):
-
- if (!isset($this->_tree[$path]))
- {
- $this->_tree[$path] = [];
- }
-
- $this->_index($file);
-
- break;
-
- case is_file($file):
-
- $this->_tree[$path][] = $file;
-
- $this->_list[] = $file;
-
- break;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Dokuwiki/Helper.php b/src/Dokuwiki/Helper.php
deleted file mode 100644
index 232b10f..0000000
--- a/src/Dokuwiki/Helper.php
+++ /dev/null
@@ -1,154 +0,0 @@
-_filesystem = $filesystem;
- $this->_reader = $reader;
- }
-
- public function getChildrenSectionLinksByUri(?string $uri = ''): array
- {
- $sections = [];
-
- if ($directory = $this->_filesystem->getDirectoryPathByUri($uri))
- {
- foreach ((array) $this->_filesystem->getTree() as $path => $files)
- {
- if (str_starts_with($path, $directory) && $path != $directory)
- {
- // Init link name
- $h1 = null;
-
- // Init this directory URI
- $thisUri = $this->_filesystem->getDirectoryUriByPath(
- $path
- );
-
- // Skip sections deeper this level
- if (substr_count($thisUri, ':') > ($uri ? substr_count($uri, ':') + 1 : 0))
- {
- continue;
- }
-
- // Get section names
- $segments = [];
-
- foreach ((array) explode(':', $thisUri) as $segment)
- {
- $segments[] = $segment;
-
- // Find section index if exists
- if ($file = $this->_filesystem->getPagePathByUri(implode(':', $segments) . ':' . $segment))
- {
- $h1 = $this->_reader->getH1(
- $this->_reader->toGemini(
- $this->_filesystem->getDataByPath(
- $file
- )
- )
- );
- }
-
- // Find section page if exists
- else if ($file = $this->_filesystem->getPagePathByUri(implode(':', $segments)))
- {
- $h1 = $this->_reader->getH1(
- $this->_reader->toGemini(
- $this->_filesystem->getDataByPath(
- $file
- )
- )
- );
- }
-
- // Reset title of undefined segment
- else
- {
- $h1 = null;
- }
- }
-
- // Register section link
- $sections[] = sprintf(
- '=> /%s %s',
- $thisUri,
- $h1
- );
- }
- }
- }
-
- // Keep unique
- $sections = array_unique(
- $sections
- );
-
- // Sort asc
- sort(
- $sections
- );
-
- return $sections;
- }
-
- public function getChildrenPageLinksByUri(?string $uri = ''): array
- {
- $pages = [];
-
- if ($directory = $this->_filesystem->getDirectoryPathByUri($uri))
- {
- foreach ((array) $this->_filesystem->getPagePathsByPath($directory) as $file)
- {
- if ($link = $this->getPageLinkByPath($file))
- {
- $pages[] = $link;
- }
- }
- }
-
- // Keep unique
- $pages = array_unique(
- $pages
- );
-
- // Sort asc
- sort(
- $pages
- );
-
- return $pages;
- }
-
- public function getPageLinkByPath(string $path): ?string
- {
- if (in_array($path, $this->_filesystem->getList()) && is_file($path) && is_readable($path))
- {
- return sprintf(
- '=> /%s %s',
- $this->_filesystem->getPageUriByPath(
- $path
- ),
- $this->_reader->getH1(
- $this->_reader->toGemini(
- $this->_filesystem->getDataByPath(
- $path
- )
- )
- )
- );
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/src/Dokuwiki/Reader.php b/src/Dokuwiki/Reader.php
deleted file mode 100644
index 95accef..0000000
--- a/src/Dokuwiki/Reader.php
+++ /dev/null
@@ -1,412 +0,0 @@
- null,
- '~IPv6:open~' => '[',
- '~IPv6:close~' => ']',
- '~LINE:break~' => PHP_EOL
- ];
-
- private array $_rule =
- [
- // Headers
- '/^([\s]*)#([^#]+)/' => '$1#$2' . PHP_EOL,
- '/^([\s]*)##([^#]+)/' => '$1##$2' . PHP_EOL,
- '/^([\s]*)###([^#]+)/' => '$1###$2' . PHP_EOL,
- '/^([\s]*)####([^#]+)/' => '$1###$2' . PHP_EOL,
- '/^([\s]*)#####([^#]+)/' => '$1###$2' . PHP_EOL,
- '/^([\s]*)######([^#]+)/' => '$1###$2' . PHP_EOL,
-
- '/^[\s]*[=]{6}([^=]+)[=]{6}/' => '# $1' . PHP_EOL,
- '/^[\s]*[=]{5}([^=]+)[=]{5}/' => '## $1' . PHP_EOL,
- '/^[\s]*[=]{4}([^=]+)[=]{4}/' => '### $1' . PHP_EOL,
- '/^[\s]*[=]{3}([^=]+)[=]{3}/' => '### $1' . PHP_EOL,
- '/^[\s]*[=]{2}([^=]+)[=]{2}/' => '### $1' . PHP_EOL,
- '/^[\s]*[=]{1}([^=]+)[=]{1}/' => '### $1' . PHP_EOL,
-
- // Tags
- '/\*\*/' => '',
- '/\'\'/' => '',
- '/\%\%/' => '',
- '/(? '',
-
- // Remove extra spaces
- '/(\s)\s+/' => '$1',
-
- // Links
-
- /// Detect IPv6 (used as no idea how to resolve square quotes in rules below)
- '/\[\[([^\[]+)\[([A-f:0-9]*)\]([^\]]+)\]\]/' => '$1~IPv6:open~$2~IPv6:close~$3',
-
- /// Remove extra chars
- '/\[\[\s*\:?([^\|]+)\s*\|\s*([^\]]+)\s*\]\]/' => '[[$1|$2]]',
- '/\[\[\s*\:?([^\]]+)\s*\]\]/' => '[[$1]]',
-
- '/\{\{\s*\:?([^\|]+)\s*\|\s*([^\}]+)\s*\}\}/' => '{{$1|$2}}',
- '/\{\{\s*\:?([^\}]+)\s*\}\}/' => '{{$1}}',
-
- /// Wikipedia
- '/\[\[wp([A-z]{2,})>([^\|]+)\|([^\]]+)\]\]/ui' => '$3 ( https://$1.wikipedia.org/wiki/$2 )',
- '/\[\[wp>([^\|]+)\|([^\]]+)\]\]/i' => '$2 ( https://en.wikipedia.org/wiki/$1 )',
- '/\[\[wp([A-z]{2,})>([^\]]+)\]\]/i' => '$2 ( https://$1.wikipedia.org/wiki/$2 )',
- '/\[\[wp>([^\]]+)\]\]/i' => '$1 ( https://en.wikipedia.org/wiki/$1 )',
-
- /// Dokuwiki
- '/\[\[doku>([^\|]+)\|([^\]]+)\]\]/i' => '$2( https://www.dokuwiki.org/$1 )',
- '/\[\[doku>([^\]]+)\]\]/i' => '$1( https://www.dokuwiki.org/$1 )',
-
- /// Index
- /// Useful with src/Dokuwiki/Helper.php
- '/\{\{indexmenu>:([^\}]+)\}\}/i' => '',
- '/\{\{indexmenu_n>[\d]+\}\}/i' => '',
-
- // Related
- '/\[\[this>([^\|]+)\|([^\]]+)\]\]/i' => '$2',
-
- /// Relative
- '/\[\[(?!https?:|this|doku|wp[A-z]{0,2})([^\|]+)\|([^\]]+)\]\]/i' => ' $2$3 ( ~URL:base~$1 )',
- '/\[\[(?!https?:|this|doku|wp[A-z]{0,2})([^\]]+)\]\]/i' => ' $2 ( ~URL:base~$1 )',
-
- /// Absolute
- '/\[\[(https?:)([^\|]+)\|([^\]]+)\]\]/i' => '$3 ( $1$2 )',
- '/\[\[(https?:)([^\]]+)\]\]/i' => '$1$2', // @TODO
-
- /// Media
- '/\{\{(?!https?:)([^\|]+)\|([^\}]+)\}\}/i' => PHP_EOL . '=> /$1$2' . PHP_EOL,
- '/\{\{(?!https?:)([^\}]+)\}\}/i' => PHP_EOL . '=> /$1$2' . PHP_EOL,
-
- // List
- '/^[\s]?-/' => '* ',
- '/^[\s]+\*/' => '*',
-
- // Separators
- '/[\\\]{2}/' => '~LINE:break~',
-
- // Plugins
- '/~~DISCUSSION~~/' => '', // @TODO
- '/~~INFO:syntaxplugins~~/' => '', // @TODO
-
- // Final corrections
- '/[\n\r]+[.,;:]+/' => PHP_EOL
- ];
-
- public function __construct(?array $rules = null)
- {
- if ($rules)
- {
- $this->_rule = $rules;
- }
- }
-
- // Macros operations
- public function getMacroses(): array
- {
- $this->_macros;
- }
-
- public function setMacroses(array $macros)
- {
- $this->_macros = $macros;
- }
-
- public function getMacros(string $key, string $value): ?string
- {
- $this->_macros[$key] = isset($this->_macros[$key]) ? $value : null;
- }
-
- public function setMacros(string $key, ?string $value): void
- {
- if ($value)
- {
- $this->_macros[$key] = $value;
- }
-
- else
- {
- unset(
- $this->_macros[$key]
- );
- }
- }
-
- // Rule operations
- public function getRules(): array
- {
- $this->_rule;
- }
-
- public function setRules(array $rules)
- {
- $this->_rule = $rules;
- }
-
- public function getRule(string $key, string $value): ?string
- {
- $this->_rule[$key] = isset($this->_rule[$key]) ? $value : null;
- }
-
- public function setRule(string $key, ?string $value): void
- {
- if ($value)
- {
- $this->_rule[$key] = $value;
- }
-
- else
- {
- unset(
- $this->_rule[$key]
- );
- }
- }
-
- // Convert DokuWiki text to Gemini
- public function toGemini(?string $data, ?array &$lines = []): ?string
- {
- if (empty($data))
- {
- return null;
- }
-
- $raw = false;
-
- $lines = [];
-
- foreach ((array) explode(PHP_EOL, $data) as $line)
- {
- // Skip any formatting in lines between code tag
- if (!$raw && preg_match('/<(code|file)([^>]*)>/i', $line, $matches))
- {
- // Prepend tag meta or filename as plain description
- if (!empty($matches[0]))
- {
- $lines[] = preg_replace(
- '/<(code|file)[\s-]*([^>]*)>/i',
- '$2',
- $matches[0]
- );
- }
-
- $lines[] = '```';
- $lines[] = preg_replace(
- '/<\/?(code|file)[^>]*>/i',
- '',
- $line
- );
-
- $raw = true;
-
- // Make sure inline tag closed
- if (preg_match('/<\/(code|file)>/i', $line))
- {
- $lines[] = '```';
-
- $raw = false;
-
- continue;
- }
-
- continue;
- }
-
- if ($raw && preg_match('/<\/(code|file)>/i', $line))
- {
- $lines[] = preg_replace(
- '/<\/(code|file)>/i',
- '',
- $line
- );
-
- $lines[] = '```';
-
- $raw = false;
-
- continue;
- }
-
- if ($raw)
- {
- $lines[] = preg_replace(
- '/^```/',
- ' ```',
- $line
- );
-
- continue;
- }
-
- // Apply config
- $lines[] = preg_replace(
- array_keys(
- $this->_rule
- ),
- array_values(
- $this->_rule
- ),
- strip_tags(
- $line
- )
- );
- }
-
- // ASCII table
- $table = false;
-
- $rows = [];
-
- $th = [];
-
- foreach ($lines as $index => $line)
- {
- // Strip line breaks
- $line = str_replace(
- '~LINE:break~',
- ' ',
- $line
- );
-
- // Header
- if (!$table && preg_match_all('/\^([^\^]+)/', $line, $matches))
- {
- if (!empty($matches[1]))
- {
- $table = true;
-
- $rows = [];
-
- $th = [];
-
- foreach ($matches[1] as $value)
- {
- $th[] = trim(
- $value
- );
- }
-
- unset(
- $lines[$index]
- );
-
- continue;
- }
- }
-
- // Body
- if ($table)
- {
- $table = false;
-
- if (preg_match(sprintf('/%s\|/', str_repeat('\|(.*)', count($th))), $line, $matches))
- {
- if (count($matches) == count($th) + 1)
- {
- $table = true;
-
- $row = [];
- foreach ($th as $offset => $column)
- {
- $row[$column] = trim(
- $matches[$offset + 1]
- );
- }
-
- $rows[] = $row;
-
- unset(
- $lines[$index]
- );
- }
- }
-
- if (!$table && $rows)
- {
- $builder = new ArrayToTextTable(
- $rows
- );
-
- $lines[$index] = '```' . PHP_EOL . $builder->render() . PHP_EOL . '```';
- }
- }
- }
-
- // Merge lines
- return preg_replace(
- '/[\n\r]{2,}/',
- PHP_EOL . PHP_EOL,
- str_replace(
- array_keys(
- $this->_macros
- ),
- array_values(
- $this->_macros
- ),
- implode(
- PHP_EOL,
- $lines
- )
- )
- );
- }
-
- public function getH1(?string $gemini, ?string $regex = '/^[\s]?#([^#]+)/'): ?string
- {
- foreach ((array) explode(PHP_EOL, (string) $gemini) as $line)
- {
- preg_match(
- $regex,
- $line,
- $matches
- );
-
- if (!empty($matches[1]))
- {
- return trim(
- $matches[1]
- );
-
- break;
- }
- }
-
- return null;
- }
-
- public function getLinks(?string $gemini, ?string $regex = '/(https?|gemini):\/\/\S+/'): array
- {
- $links = [];
-
- if (empty($gemini))
- {
- return $links;
- }
-
- preg_match_all(
- $regex,
- $gemini,
- $matches
- );
-
- if (!empty($matches[0]))
- {
- foreach ((array) $matches[0] as $link)
- {
- $links[] = trim(
- $link
- );
- }
- }
-
- return array_unique(
- $links
- );
- }
-}
\ No newline at end of file
diff --git a/src/Gemtext/Body.php b/src/Gemtext/Body.php
deleted file mode 100644
index 3cfa3fb..0000000
--- a/src/Gemtext/Body.php
+++ /dev/null
@@ -1,235 +0,0 @@
- $line)
- {
- $this->_lines[$index] = $line;
- }
- }
-
- public function getLine(int $index): ?int
- {
- return isset($this->_lines[$index]) ? $this->_lines[$index] : null;
- }
-
- public function getLines(): array
- {
- return $this->_lines;
- }
-
- public function getH1(): array
- {
- $matches = [];
-
- foreach ($this->_lines as $index => $line)
- {
- if (preg_match('/^#([^#]+)/', trim($line), $match))
- {
- $matches[$index] = trim(
- $match[1]
- );
- }
- }
-
- return $matches;
- }
-
- public function getH2(): array
- {
- $matches = [];
-
- foreach ($this->_lines as $index => $line)
- {
- if (preg_match('/^##([^#]+)/', trim($line), $match))
- {
- $matches[$index] = trim(
- $match[1]
- );
- }
- }
-
- return $matches;
- }
-
- public function getH3(): array
- {
- $matches = [];
-
- foreach ($this->_lines as $index => $line)
- {
- if (preg_match('/^###([^#]+)/', trim($line), $match))
- {
- $matches[$index] = trim(
- $match[1]
- );
- }
- }
-
- return $matches;
- }
-
- public function getLinks(): array
- {
- $matches = [];
-
- foreach ($this->_lines as $index => $line)
- {
- if (preg_match('/^=>(.*)/', trim($line), $match))
- {
- $matches[$index] = trim(
- $match[1]
- );
- }
- }
-
- return $matches;
- }
-
- public function getQuote(): array
- {
- $matches = [];
-
- foreach ($this->_lines as $index => $line)
- {
- if (preg_match('/^>(.*)/', trim($line), $match))
- {
- $matches[$index] = trim(
- $match[1]
- );
- }
- }
-
- return $matches;
- }
-
- public function getCode(): array
- {
- $matches = [];
-
- foreach ($this->_lines as $index => $line)
- {
- if (preg_match('/^```(.*)/', trim($line), $match))
- {
- $matches[$index] = empty($match[1]) ? null : trim($match[1]);
- }
- }
-
- return $matches;
- }
-
- public function findLinks(string $protocol = 'gemini'): array
- {
- $matches = [];
-
- foreach ($this->_lines as $index => $line)
- {
- if (preg_match('/' . $protocol . ':\/\/(.*)[\s\S\'"]*/', trim($line), $match))
- {
- $matches[$index] =
- sprintf(
- '%s://%s',
- $protocol,
- trim(
- $match[1]
- )
- );
- }
- }
-
- return $matches;
- }
-
- public function skipTags(array $tags = []): string
- {
- $lines = [];
-
- foreach ($this->_lines as $line)
- {
- $line = trim(
- $line
- );
-
- if ($tags)
- {
- foreach ($tags as $tag)
- {
- if(!in_array($tag, ['#', '##', '###', '=>', '*', '```']))
- {
- continue;
- }
-
- switch (true)
- {
- case str_starts_with($line, '#'):
-
- $line = preg_replace(
- sprintf(
- '/^%s([^#]+)/ui',
- $tag
- ),
- '$1',
- $line
- );
-
- break;
-
- case str_starts_with($line, '*'):
-
- $line = preg_replace(
- '/^\*(.*)/ui',
- '$1',
- $line
- );
-
- break;
-
- default:
-
- $line = preg_replace(
- sprintf(
- '/^%s(.*)/ui',
- $tag
- ),
- '$1',
- $line
- );
- }
- }
- }
-
- else
- {
- $line = preg_replace(
- [
- '/^#([^#]+)/ui',
- '/^##([^#]+)/ui',
- '/^###([^#]+)/ui',
- '/^=>(.*)/ui',
- '/^\*(.*)/ui',
- '/^```(.*)/ui',
- ],
- '$1',
- $line
- );
- }
-
- $lines[] = trim(
- $line
- );
- }
-
- return implode(
- PHP_EOL,
- $lines
- );
- }
-}
\ No newline at end of file
diff --git a/src/Gemtext/Link.php b/src/Gemtext/Link.php
deleted file mode 100644
index 6557391..0000000
--- a/src/Gemtext/Link.php
+++ /dev/null
@@ -1,69 +0,0 @@
-_line = preg_replace(
- '/^\s*=>(.*)/',
- '$1',
- trim(
- $line
- )
- );
- }
-
- public function getAddress(): ?string
- {
- if (preg_match('/^\s*([^\s]+)/', trim($this->_line), $match))
- {
- return trim(
- $match[1]
- );
- }
-
- return null;
- }
-
- public function getDate(?int &$timestamp = null): ?string
- {
- if (preg_match('/\s([\d]+-[\d+]+-[\d]+)\s/', trim($this->_line), $match))
- {
- if ($result = strtotime($match[1]))
- {
- $timestamp = $result;
-
- return trim(
- $match[1]
- );
- }
- }
-
- return null;
- }
-
- public function getAlt(): ?string
- {
- if (preg_match('/\s[\d]+-[\d+]+-[\d]+\s(.*)$/', trim($this->_line), $match))
- {
- return trim(
- $match[1]
- );
- }
-
- else if (preg_match('/\s(.*)$/', trim($this->_line), $match))
- {
- return trim(
- $match[1]
- );
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/src/Gtk3/Pango.php b/src/Gtk3/Pango.php
deleted file mode 100644
index 3a8099a..0000000
--- a/src/Gtk3/Pango.php
+++ /dev/null
@@ -1,225 +0,0 @@
-getLines();
-
- $raw = [];
-
- $escaped = [];
-
- // Code
- $code = $body->getCode();
-
- if (count($code) % 2 == 0) // make sure tags has pairs
- {
- $i = 1;
-
- foreach ($code as $index => $capture)
- {
- // Replace code tags
- if ($i % 2 == 0)
- {
- $lines[$index] = '';
-
- // Skip code format inside the tags by raw registry
- foreach (array_slice($lines, $offset, $index - $offset) as $start => $line)
- {
- $raw[$start + $offset] = $line;
- }
- }
-
- else
- {
- if ($capture)
- {
- $lines[$index] = sprintf(
- '%s',
- self::escape(
- $capture
- )
- );
- }
-
- else
- {
- $lines[$index] = '';
- }
-
- $offset = $index + 1;
- }
-
- $escaped[] = $index;
-
- $i++;
- }
- }
-
- // H1
- foreach ($body->getH1() as $index => $value)
- {
- if (!isset($raw[$index]))
- {
- $lines[$index] = sprintf(
- '%s',
- self::escape(
- $value
- )
- );
-
- $escaped[] = $index;
- }
- }
-
- // H2
- foreach ($body->getH2() as $index => $value)
- {
- if (!isset($raw[$index]))
- {
- $lines[$index] = sprintf(
- '%s',
- self::escape(
- $value
- )
- );
-
- $escaped[] = $index;
- }
- }
-
- // H3
- foreach ($body->getH3() as $index => $value)
- {
- if (!isset($raw[$index]))
- {
- $lines[$index] = sprintf(
- '%s',
- self::escape(
- $value
- )
- );
-
- $escaped[] = $index;
- }
- }
-
- // Quote
- foreach ($body->getQuote() as $index => $value)
- {
- if (!isset($raw[$index]))
- {
- $lines[$index] = sprintf(
- '%s',
- self::escape(
- $value
- )
- );
-
- $escaped[] = $index;
- }
- }
-
- // Links
- foreach ($body->getLinks() as $index => $line)
- {
- if (!isset($raw[$index]))
- {
- $link = new \Yggverse\Gemini\Gemtext\Link(
- $line
- );
-
- if (!$address = $link->getAddress())
- {
- continue;
- }
-
- if (!$alt = $link->getAlt())
- {
- if (!$alt = $link->getDate())
- {
- $alt = urldecode(
- $address
- );
- }
- }
-
- if ($alt == $address)
- {
- $lines[$index] = sprintf(
- '%s',
- self::escape(
- $address
- ),
- self::escape(
- $alt
- )
- );
- }
-
- else
- {
- $lines[$index] = sprintf(
- '%s',
- self::escape(
- $address
- ),
- self::escape(
- urldecode(
- $address
- )
- ),
- self::escape(
- $alt
- )
- );
- }
-
- $escaped[] = $index;
- }
- }
-
- // Escape special chars for non escaped lines
- foreach ($body->getLines() as $index => $value)
- {
- if (!in_array($index, $escaped))
- {
- $lines[$index] = self::escape(
- $value
- );
- }
- }
-
- return implode(
- PHP_EOL,
- $lines
- );
- }
-
- public static function escape(
- string $value
- ): string
- {
- return htmlspecialchars(
- $value
- );
- }
-}
\ No newline at end of file