yggverse
5 months ago
4 changed files with 0 additions and 1106 deletions
@ -1,277 +0,0 @@ |
|||||||
<?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 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; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,154 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
declare(strict_types=1); |
|
||||||
|
|
||||||
namespace Yggverse\Gemini\Dokuwiki; |
|
||||||
|
|
||||||
class Helper |
|
||||||
{ |
|
||||||
private \Yggverse\Gemini\Dokuwiki\Filesystem $_filesystem; |
|
||||||
private \Yggverse\Gemini\Dokuwiki\Reader $_reader; |
|
||||||
|
|
||||||
public function __construct( |
|
||||||
\Yggverse\Gemini\Dokuwiki\Filesystem $filesystem, |
|
||||||
\Yggverse\Gemini\Dokuwiki\Reader $reader |
|
||||||
) { |
|
||||||
$this->_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; |
|
||||||
} |
|
||||||
} |
|
@ -1,412 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
declare(strict_types=1); |
|
||||||
|
|
||||||
namespace Yggverse\Gemini\Dokuwiki; |
|
||||||
|
|
||||||
use dekor\ArrayToTextTable; |
|
||||||
|
|
||||||
class Reader |
|
||||||
{ |
|
||||||
private array $_macros = |
|
||||||
[ |
|
||||||
'~URL:base~' => 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 |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue