Writer field - Use regular links instead of permalinks


In a writer field, when creating a link to a internal page, as href value in the template is it possible to display the regular page link instead of the permalink ?

I’m trying Kirby 4 and it’s great. The new link dialog makes it possible to link any word(s) to a page, but the href attribute contains a permalink, wich is problematic in my case.
Otherwise, in the context of a blocks field, I don’t see any other option than to use the markdown field, wich is way less convenient for the user. But maybe you see one ?

Thanks for your help.

For me linking from internal pages does not work.
After assignment source code looks like this:
The href attribute is missing.
If I call the page in the panel again, the link is not recognized at all.
Is this a (known) bug?
I use the starterkit with 4.0.0-beta.1

I don’t think so, works for me. Where are you using this, in a text block?

External links work. Internal page links do not work.
I have tested a block field in the Starterkit.

As I wrote above, I cannot reproduce this in a fresh K4 beta 1 Starterkit, but if you want to report a bug, please do so in the GitHub kirby repo.

I don’t see this bug neither.

@texnixe any idea concerning my question ?

Hm, I don’t think so, looking at the source code, Kirby recognizes links via the file:// or page:// patterns. So it wouldn’t work with this disabled.

What you can do is disable the pages option and use a custom option, i.e. just insert /notes.

Is it possible to hook the render so that it gets the regular link from the permalink ?

A hook that replaces the link and actually stores the result in the content wouldn’t be useful (because of what I wrote above), what you can do is replace those links when rendering, via a custom field method.

Ok thank you :slight_smile:

I’ll try this approach.

It works !

Here is the method :

Kirby::plugin('adrienpayet/process-links', [
  'fieldMethods' => [
      'processLinks' => function ($field) {
          $dom = new DOMDocument();
          @$dom->loadHTML(mb_convert_encoding($field->value(), 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
          $anchorTags = $dom->getElementsByTagName('a');
          $site = site();

          foreach ($anchorTags as $anchorTag) {
              $href = $anchorTag->getAttribute('href');
              $getIdPattern = '/@\/page\/(.*)/';
              $regexResult = preg_match($getIdPattern, $href, $matches);
              $isInternalPageLink = $regexResult && isset($matches[1]);
              $targetId = $matches[1];

              if ($isInternalPageLink) {
                try {
                  $targetPage = $site->find('page://' . $targetId);
                  if (!$targetPage) {
                      throw new Exception("No internal page found.");
                  $attributes = [
                      'href' => $targetPage->url(),
                      'class' => 'internal-link',
                      'data-size' => formatSize($targetPage->size()->toInt())
                  foreach ($attributes as $key => $value) {
                      $anchorTag->setAttribute($key, $value);
                } catch (Exception $e) {
          return $dom->saveHTML();