mirror of
https://github.com/YGGverse/gemini-php.git
synced 2025-02-10 22:24:19 +00:00
implement filesystem, update api version
This commit is contained in:
parent
9ea658a3fc
commit
1bb20c2f18
110
README.md
110
README.md
@ -4,14 +4,116 @@ PHP 8 Library for Gemini Protocol
|
|||||||
|
|
||||||
## DokuWiki
|
## DokuWiki
|
||||||
|
|
||||||
### Convert
|
Toolkit provides DokuWiki integration API for Gemini.
|
||||||
|
|
||||||
|
Allows to simple deploy new apps or make existing website mirror.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
* [DokuWiki Server for Gemini Protocol](https://github.com/YGGverse/dokuwiki-gemini-server)
|
||||||
|
|
||||||
|
### Reader
|
||||||
|
|
||||||
|
Read DokuWiki and convert to Gemini
|
||||||
|
|
||||||
```
|
```
|
||||||
$dokuwiki = new \Yggverse\Gemini\Dokuwiki();
|
$reader = new \Yggverse\Gemini\Dokuwiki\Reader(
|
||||||
|
// optional regex rule set array
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
echo $dokuwiki->toGemini(
|
#### Reader::getRules
|
||||||
|
#### Reader::setRules
|
||||||
|
#### Reader::getRule
|
||||||
|
#### Reader::setRule
|
||||||
|
|
||||||
|
Get or change existing regex rule (or just skip by using build-in set)
|
||||||
|
|
||||||
|
```
|
||||||
|
echo $reader->setRule(
|
||||||
|
'/subject/ui',
|
||||||
|
'replacement'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Reader::toGemini
|
||||||
|
|
||||||
|
Convert DokuWiki to Gemini markup
|
||||||
|
|
||||||
|
```
|
||||||
|
echo $reader->toGemini(
|
||||||
file_get_contents(
|
file_get_contents(
|
||||||
'data/pages/index.txt'
|
'/host/data/pages/index.txt'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Reader::getH1
|
||||||
|
|
||||||
|
Get document title
|
||||||
|
|
||||||
|
```
|
||||||
|
echo $reader->getH1(
|
||||||
|
file_get_contents(
|
||||||
|
'/host/data/pages/index.txt'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filesystem
|
||||||
|
|
||||||
|
Provides methods for simple and secure interaction with DokuWiki file storage
|
||||||
|
|
||||||
|
```
|
||||||
|
$filesystem = new \Yggverse\Gemini\Dokuwiki\Filesystem(
|
||||||
|
'/host/data' // storage location
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filesystem::getList
|
||||||
|
|
||||||
|
Return simple array of all files in storage
|
||||||
|
|
||||||
|
```
|
||||||
|
var_dump (
|
||||||
|
$filesystem->getList(
|
||||||
|
'hello:world'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filesystem::getTree
|
||||||
|
|
||||||
|
Return all files under the storage folder in tree format
|
||||||
|
|
||||||
|
```
|
||||||
|
var_dump (
|
||||||
|
$filesystem->getTree(
|
||||||
|
'hello:world'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filesystem::getPagePathByUri
|
||||||
|
|
||||||
|
Return absolute path to stored page file
|
||||||
|
|
||||||
|
```
|
||||||
|
var_dump (
|
||||||
|
$filesystem->getPagePathByUri(
|
||||||
|
'hello:world'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filesystem::getPageUriByPath
|
||||||
|
|
||||||
|
Return page URI in `dokuwiki:format`
|
||||||
|
|
||||||
|
```
|
||||||
|
var_dump (
|
||||||
|
$filesystem->getPageUriByPath(
|
||||||
|
'/full/path/to/page.txt'
|
||||||
|
)
|
||||||
|
)
|
||||||
```
|
```
|
116
src/Dokuwiki.php
116
src/Dokuwiki.php
@ -1,116 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Yggverse\Gemini;
|
|
||||||
|
|
||||||
class Dokuwiki
|
|
||||||
{
|
|
||||||
private array $_dictionary =
|
|
||||||
[
|
|
||||||
// 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,
|
|
||||||
|
|
||||||
// Links
|
|
||||||
'/\{\{([^:]+):([^\}]+)\}\}/' => PHP_EOL . '=> $1 $1' . PHP_EOL, // @TODO
|
|
||||||
'/\{\{indexmenu\>:([^\}]+)\}\}/' => PHP_EOL . '=> $1 $1' . PHP_EOL, // @TODO
|
|
||||||
'/\[\[wp([A-z]{2})\>([^\|]+)\|([^\]\]]+)\]\]/' => PHP_EOL . '=> https://$1.wikipedia.org/wiki/$2 $3' . PHP_EOL,
|
|
||||||
'/\[\[wp\>([^\|]+)\|([^\]\]]+)\]\]/' => PHP_EOL . '=> https://en.wikipedia.org/wiki/$1 $2' . PHP_EOL,
|
|
||||||
'/\[\[([^|]+)\|([^\]\]]+)\]\]/' => PHP_EOL . '=> $1 $2' . PHP_EOL,
|
|
||||||
|
|
||||||
// Tags
|
|
||||||
'/<code>/i' => '```',
|
|
||||||
'/<\/code>/i' => '```',
|
|
||||||
'/<wrap[^>]+>([^<]?)/i' => '$1',
|
|
||||||
'/<\/wrap>/i' => '$1',
|
|
||||||
|
|
||||||
'/<file>/i' => '```',
|
|
||||||
'/<file[\s]+-[\s]+([^>]+)>/i' => '$1```',
|
|
||||||
'/<\/file>/i' => '```',
|
|
||||||
|
|
||||||
//'/[*]+([^*]+)[*]+/' => '$1', // @TODO bugged, e.g. crontab tasks
|
|
||||||
'/\'\'([^\']+)\'\'/' => '$1',
|
|
||||||
'/%%([^%]+)%%/' => '$1',
|
|
||||||
'/\/\/^:([^\/]+)\/\//' => '$1',
|
|
||||||
|
|
||||||
// List
|
|
||||||
'/^[\s]?-/' => '* ',
|
|
||||||
'/^[\s]+\*/' => '*',
|
|
||||||
|
|
||||||
// Separators
|
|
||||||
'/[\\\]{2}/' => PHP_EOL,
|
|
||||||
|
|
||||||
// Plugins
|
|
||||||
'/~~DISCUSSION~~/' => '', // @TODO
|
|
||||||
|
|
||||||
// Final corrections
|
|
||||||
'/[\n\r]+[.,;:]+/' => PHP_EOL
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __construct(?array $dictionary = null)
|
|
||||||
{
|
|
||||||
if ($dictionary)
|
|
||||||
{
|
|
||||||
$this->_dictionary = $dictionary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDictionary(): array
|
|
||||||
{
|
|
||||||
$this->_dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setDictionary(array $dictionary)
|
|
||||||
{
|
|
||||||
$this->_dictionary = $dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRule(string $key, string $value): ?string
|
|
||||||
{
|
|
||||||
$this->_dictionary[$key] = isset($this->_dictionary[$key]) ? $value : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRule(string $key, string $value): void
|
|
||||||
{
|
|
||||||
$this->_dictionary[$key] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toGemini(string $data): string
|
|
||||||
{
|
|
||||||
$lines = [];
|
|
||||||
|
|
||||||
foreach ((array) explode(PHP_EOL, $data) as $line)
|
|
||||||
{
|
|
||||||
$lines[] = preg_replace(
|
|
||||||
array_keys(
|
|
||||||
$this->_dictionary
|
|
||||||
),
|
|
||||||
array_values(
|
|
||||||
$this->_dictionary
|
|
||||||
),
|
|
||||||
$line
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return preg_replace(
|
|
||||||
'/[\n\r]{2,}/',
|
|
||||||
PHP_EOL . PHP_EOL,
|
|
||||||
implode(
|
|
||||||
PHP_EOL,
|
|
||||||
$lines
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
129
src/Dokuwiki/Filesystem.php
Normal file
129
src/Dokuwiki/Filesystem.php
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Yggverse\Gemini\Dokuwiki;
|
||||||
|
|
||||||
|
class Filesystem
|
||||||
|
{
|
||||||
|
private $_path;
|
||||||
|
private $_tree = [];
|
||||||
|
private $_list = [];
|
||||||
|
|
||||||
|
public function __construct(string $path)
|
||||||
|
{
|
||||||
|
$this->_path = rtrim(
|
||||||
|
$path,
|
||||||
|
'/'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->_index(
|
||||||
|
$this->_path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTree(): array
|
||||||
|
{
|
||||||
|
return $this->_tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getList(): array
|
||||||
|
{
|
||||||
|
return $this->_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPagePathByUri(string $uri): ?string
|
||||||
|
{
|
||||||
|
$uri = urldecode(
|
||||||
|
$uri
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = sprintf(
|
||||||
|
'%s/pages/%s.txt',
|
||||||
|
$this->_path,
|
||||||
|
str_replace(
|
||||||
|
':',
|
||||||
|
'/',
|
||||||
|
$uri
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!in_array($path, $this->_list) || !is_file($path) || !is_readable($path))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPageUriByPath(string $path): ?string
|
||||||
|
{
|
||||||
|
$path = str_replace(
|
||||||
|
sprintf(
|
||||||
|
'%s/pages/',
|
||||||
|
$this->_path
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
$path
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = trim(
|
||||||
|
$path,
|
||||||
|
'/'
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = basename(
|
||||||
|
$path
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = str_replace(
|
||||||
|
[
|
||||||
|
'/',
|
||||||
|
'.txt'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
':',
|
||||||
|
null
|
||||||
|
],
|
||||||
|
$path
|
||||||
|
);
|
||||||
|
|
||||||
|
return urlencode(
|
||||||
|
$path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _index(string $path): void
|
||||||
|
{
|
||||||
|
foreach ((array) scandir($path) as $file)
|
||||||
|
{
|
||||||
|
if (in_array($file, ['.', '..']))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = sprintf(
|
||||||
|
'%s/%s',
|
||||||
|
$path,
|
||||||
|
$file
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (true)
|
||||||
|
{
|
||||||
|
case is_dir($file):
|
||||||
|
|
||||||
|
$this->_index($file);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case is_file($file):
|
||||||
|
|
||||||
|
$this->_tree[$path][] = $file;
|
||||||
|
|
||||||
|
$this->_list[] = $file;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
138
src/Dokuwiki/Reader.php
Normal file
138
src/Dokuwiki/Reader.php
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Yggverse\Gemini\Dokuwiki;
|
||||||
|
|
||||||
|
class Reader
|
||||||
|
{
|
||||||
|
private array $_rules =
|
||||||
|
[
|
||||||
|
// 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
|
||||||
|
'/<code>/i' => PHP_EOL . '```' . PHP_EOL,
|
||||||
|
'/<\/code>/i' => PHP_EOL . '```' . PHP_EOL,
|
||||||
|
|
||||||
|
'/<file>/i' => PHP_EOL . '```' . PHP_EOL,
|
||||||
|
'/<file[\s]?[-]?[\s]?([^>]+)>/i' => '$1' . PHP_EOL . '```' . PHP_EOL,
|
||||||
|
'/<\/file>/i' => '```',
|
||||||
|
|
||||||
|
'/\*\*([^\*]{2,})\*\*/' => '$1',
|
||||||
|
'/\'\'([^\']{2,})\'\'/' => '$1',
|
||||||
|
'/\%\%([^\%]{2,})\%\%/' => '$1',
|
||||||
|
'/[^:]{1}\/\/([^\/]{2,})\/\//' => '$1',
|
||||||
|
|
||||||
|
// Links
|
||||||
|
'/\{\{([^:]+):([^\}]{2,})\}\}/' => PHP_EOL . '=> $1 $1' . PHP_EOL, // @TODO
|
||||||
|
'/\{\{indexmenu\>:([^\}]{2,})\}\}/' => PHP_EOL . '=> $1 $1' . PHP_EOL, // @TODO
|
||||||
|
'/\[\[wp([A-z]{2})\>([^\|]+)\|([^\]]{2,})\]\]/' => PHP_EOL . '=> https://$1.wikipedia.org/wiki/$2 $3' . PHP_EOL,
|
||||||
|
'/\[\[wp\>([^\|]+)\|([^\]]{2,})\]\]/' => PHP_EOL . '=> https://en.wikipedia.org/wiki/$1 $2' . PHP_EOL,
|
||||||
|
'/\[\[([^|]+)\|([^\]]{2,})\]\]/' => PHP_EOL . '=> $1 $2' . PHP_EOL,
|
||||||
|
//'/((gemini|https?):\/\/[^\s]+)/' => PHP_EOL . '=> $1' . PHP_EOL, // @TODO incorrect
|
||||||
|
|
||||||
|
// List
|
||||||
|
'/^[\s]?-/' => '* ',
|
||||||
|
'/^[\s]+\*/' => '*',
|
||||||
|
|
||||||
|
// Separators
|
||||||
|
'/[\\\]{2}/' => PHP_EOL,
|
||||||
|
|
||||||
|
// Plugins
|
||||||
|
'/~~DISCUSSION~~/' => '', // @TODO
|
||||||
|
|
||||||
|
// Final corrections
|
||||||
|
'/[\n\r]+[.,;:]+/' => PHP_EOL
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(?array $rules = null)
|
||||||
|
{
|
||||||
|
if ($rules)
|
||||||
|
{
|
||||||
|
$this->_rules = $rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRules(): array
|
||||||
|
{
|
||||||
|
$this->_rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRules(array $rules)
|
||||||
|
{
|
||||||
|
$this->_rules = $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRule(string $key, string $value): ?string
|
||||||
|
{
|
||||||
|
$this->_rules[$key] = isset($this->_rules[$key]) ? $value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRule(string $key, string $value): void
|
||||||
|
{
|
||||||
|
$this->_rules[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toGemini(string $data): string
|
||||||
|
{
|
||||||
|
$lines = [];
|
||||||
|
|
||||||
|
foreach ((array) explode(PHP_EOL, $data) as $line)
|
||||||
|
{
|
||||||
|
$lines[] = preg_replace(
|
||||||
|
array_keys(
|
||||||
|
$this->_rules
|
||||||
|
),
|
||||||
|
array_values(
|
||||||
|
$this->_rules
|
||||||
|
),
|
||||||
|
$line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_replace(
|
||||||
|
'/[\n\r]{2,}/',
|
||||||
|
PHP_EOL . PHP_EOL,
|
||||||
|
strip_tags(
|
||||||
|
implode(
|
||||||
|
PHP_EOL,
|
||||||
|
$lines
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getH1(string $data): ?string
|
||||||
|
{
|
||||||
|
foreach ((array) explode(PHP_EOL, $data) as $line)
|
||||||
|
{
|
||||||
|
preg_match_all(
|
||||||
|
'/^[\s]?#([^#]+)/',
|
||||||
|
$line,
|
||||||
|
$matches
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($matches[1]))
|
||||||
|
{
|
||||||
|
return trim(
|
||||||
|
$matches[1]
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user