60 lines
2.1 KiB
PHP
60 lines
2.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace KbAntoraImporter\AsciiDoc;
|
|
|
|
use KbAntoraImporter\Frontend\UrlBuilder;
|
|
|
|
final class ShortcodeTransformer
|
|
{
|
|
public function transformInline(string $text, array $context): string
|
|
{
|
|
$pattern = '/\b(xref|link):([^\[]+)\[([^\]]*)\]/';
|
|
$output = '';
|
|
$offset = 0;
|
|
|
|
if (! preg_match_all($pattern, $text, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
|
|
return esc_html($text);
|
|
}
|
|
|
|
foreach ($matches as $match) {
|
|
$start = (int) $match[0][1];
|
|
$output .= esc_html(substr($text, $offset, $start - $offset));
|
|
$output .= $this->renderLink((string) $match[1][0], (string) $match[2][0], (string) $match[3][0], $context);
|
|
$offset = $start + strlen((string) $match[0][0]);
|
|
}
|
|
|
|
$output .= esc_html(substr($text, $offset));
|
|
|
|
return $output;
|
|
}
|
|
|
|
private function renderLink(string $type, string $target, string $label, array $context): string
|
|
{
|
|
$target = trim($target);
|
|
$label = $label ?: basename($target);
|
|
|
|
if ('link' === $type && preg_match('#^https?://#i', $target)) {
|
|
return sprintf('<a href="%s" rel="nofollow noopener">%s</a>', esc_url($target), esc_html($label));
|
|
}
|
|
|
|
if (preg_match('#^https?://#i', $target)) {
|
|
return sprintf('<a href="%s" rel="nofollow noopener">%s</a>', esc_url($target), esc_html($label));
|
|
}
|
|
|
|
$target = preg_replace('/^[^:]+:/', '', $target) ?: $target;
|
|
$fragment = '';
|
|
|
|
if (str_contains($target, '#')) {
|
|
[$target, $fragment] = explode('#', $target, 2);
|
|
$fragment = '#' . sanitize_title($fragment);
|
|
}
|
|
|
|
$target = preg_replace('/\.adoc$/', '', $target) ?: $target;
|
|
$slug = in_array(basename($target), ['index', 'dokumentation'], true) ? '' : sanitize_title(basename($target));
|
|
$url = UrlBuilder::page((string) $context['product_slug'], (string) $context['version_slug'], $slug) . $fragment;
|
|
|
|
return sprintf('<a href="%s">%s</a>', esc_url($url), esc_html($label));
|
|
}
|
|
}
|