diff --git a/README.md b/README.md index 11e4901..d24fd7a 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,116 @@ PHP 8 Library for Gemini Protocol ## 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 + +``` +$reader = new \Yggverse\Gemini\Dokuwiki\Reader( + // optional regex rule set array +); ``` -$dokuwiki = new \Yggverse\Gemini\Dokuwiki(); -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( - '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' + ) +) ``` \ No newline at end of file diff --git a/src/Dokuwiki.php b/src/Dokuwiki.php deleted file mode 100644 index 0332d40..0000000 --- a/src/Dokuwiki.php +++ /dev/null @@ -1,116 +0,0 @@ - '$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 - '//i' => '```', - '/<\/code>/i' => '```', - '/]+>([^<]?)/i' => '$1', - '/<\/wrap>/i' => '$1', - - '//i' => '```', - '/]+)>/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 - ) - ); - } -} \ No newline at end of file diff --git a/src/Dokuwiki/Filesystem.php b/src/Dokuwiki/Filesystem.php new file mode 100644 index 0000000..ddf30fc --- /dev/null +++ b/src/Dokuwiki/Filesystem.php @@ -0,0 +1,129 @@ +_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; + } + } + } +} \ No newline at end of file diff --git a/src/Dokuwiki/Reader.php b/src/Dokuwiki/Reader.php new file mode 100644 index 0000000..59bfb97 --- /dev/null +++ b/src/Dokuwiki/Reader.php @@ -0,0 +1,138 @@ + '$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 + '//i' => PHP_EOL . '```' . PHP_EOL, + '/<\/code>/i' => PHP_EOL . '```' . PHP_EOL, + + '//i' => PHP_EOL . '```' . PHP_EOL, + '/]+)>/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; + } + } + } +} \ No newline at end of file