getkirby / kirby

Kirby's core application folder
https://getkirby.com
Other
1.32k stars 168 forks source link

Link field File URL (Website in Subfolders) #6245

Open tan3ot opened 9 months ago

tan3ot commented 9 months ago

If a file is inserted via the link field, the URL path begins with a slash. For a Kirby installation that is located in subfolders, the link will not work.

Expected

Normally in Kirby URLs are absolute. Why is it different here?

Screenshots

Link-Field-URL

rasteiner commented 9 months ago

I guess it's because the writer field saves the content as HTML. When rendering that content in a template, there is no further processing (unlike kirbytext which is processed by the template).

This means the writer field would need to store the absolute url already in the panel, but that would break for all those situations where you write content on one host (e.g. localhost) and then deploy it to another host (e.g. example.com): all those links would then still point to localhost.

All content in a typical Kirby installation doesn't actually ever store the absolute url (unless you explicitly do so), but it's calculated on the fly when rendering the template.

I guess the writer field would need a processing step to rewrite all the links, but that might be expensive (because to do it right, it would need to parse the HTML, traverse it, render new HTML). Another approach would be to store the content not as HTML, but as a prose mirror node tree. The rendering of the actual HTML would then again happen on the server, but that would be a rather big breaking change. My point is: it's not as easy as it might seem.

As a workaround, you could write your own processing step, one that simply replaces the links with a regex (not formally correct, but it might be enough for you):

<?php 
function fixLinks(?string $text) {
  return preg_replace_callback(
    '/href="\/@\/(file|page)\/([\w-]+)"/m', 
    fn($m) => 'href="' . url($m[1] . '://' . $m[2]) . '"',
    $text ?? ''
  );
}
?>

<?= fixLinks($site->text()->value()) ?>

of course you could wrap this into a field method.

medienbaecker commented 9 months ago

There's already a permalinksToUrls() method for this. I'd wait until 4.2.0 to use it however, see this issue.