Jump to content
MoritzLost

Automatically link page titles

Recommended Posts

This is a textformatter module that will automatically replace titles of other pages on your site with links to those pages. For example, if you have a template glossary-term, and mention the exact title of one page using that template in a textfield, the title will be automatically linked to that page (if the textfield uses that formatter). This is good for SEO, and saves you some manual labour. You can configure which templates should get automatically linked, and of course the formatter is only active for the fields you add this formatter to. Note that if you need more manual control over when and where titles are automatically linked, you're probably better of using Autolink from a Glossary by @mr-fan.

Features

  • Allows you to limit the automatic links by template.
  • Only includes published & visible pages by default, with an option to include hidden pages.
  • Automatically excludes the current page, with an option to change that behaviour.
  • Allows you to configure the minimum title length for linked pages.
  • Doesn't overwrite existing links, and detects most edge cases (titles inside other tag's attributes, titles inside existing links et c.).
  • Supports multi-language sites. Titles will only be linked if a title in the current language is set.
  • Can add configurable attributes to all automatically created links. This includes the ability to use page fields as replacement patterns for attributes. For example, you can create CSS classes that include the name of the template of the linked page.
  • Extensive options and hooks to change the generated markup completely. Need <mark> elements with a title attribute based on a page field instead of a link? No problem. See the example project below.
  • Prefer oldest or newest page in the case of duplicate titles.
  • Queries the database directly for improved performance.
  • Has options to switch between case sensitive and case insensitive modes, and force case sensitive behaviour even for case insensitive database collations.
  • Allows you to overwrite the module configuration via the API to call the module with different settings for different requirements on the same site.

Download & Documentation

The module is now available in the modules directory: https://modules.processwire.com/modules/textformatter-page-title-links/
You can download & install it through the backend using the classname TextformatterPageTitleLinks.

To install it manually, download or clone the module from the Github repository into your site/modules folder and install through the backend.

The complete documentation can be found in the README in the repository. Make sure to check out the module configuration page after installing the module.

Requirements

  • PHP 7.1 or higher
  • ProcessWire 3+ (it will probably work in older versions, I haven't tested those though).

This is my first module, I hope it may become useful to some of you 🙂

If you find any errors or have some other suggestions or feedback, let me know!

  • Like 11

Share this post


Link to post
Share on other sites

Changelog

The changelog can now be found in the module directory itself, see CHANGELOG.md.

Edited by MoritzLost
Added link to repository changelog
  • Like 5

Share this post


Link to post
Share on other sites

I just pushed version 2.1.0 to Github & the modules directory! Includes a minimum length settings for linkable titles, a preference to link the oldest or most recent page if multiple pages have the same title, and an important bugfix for older MySQL versions. Check out the full changelog above 🙂

Share this post


Link to post
Share on other sites

I just pushed a big update to the textformatter with version 3.0.0!
I'm not sure if anyone is actually using this module, but at least for my own projects it has been useful, and it's good training for MySQL intricacies, so I'm still updating it when I think of new stuff to add 🙂

With the updated version, it's now possible to overwrite any option from the module configuration when calling the module manually in your template code. That way, you can automatically link to pages of different templates in different contexts on the same site, or customize the behaviour of the textformatter any way you want! Also, there's now an option to toggle case insensitive behaviour, if needed, as well as an option to force case sensitive queries for case insensitive database collations. The changelog is now included in the repository itself, I also updated the readme with instructions on how to call the module manually. Make sure to check out the full changelog for version 3.0.0, as well as the readme section on manual usage.

Let me know if the module is or isn't working for you, and any suggestions you have on how to improve it!

  • Like 2

Share this post


Link to post
Share on other sites

I just published version 4.0.0 of this module, a large update that makes it possible to completely customize the markup created for detected page titles. For example, let's say you have a glossary and want glossary terms that appear anywhere on your site to display a popover with the term's definition. This update allows you to do that! Previously, the module always created an <a> tag with an href attribute, and always checked if the page was viewable before doing anything. This update comes with configuration options to change the HTML tag, disable the automatic href attribute and disable the visibility check. This allows you to use the module for a wider range of use-cases. If you need even more control, the methods the module uses to create markup are now hookable, so you can customize the output format even further! Here are some additional links to help you get started:

  • Like 2

Share this post


Link to post
Share on other sites

The new version 4.1.0 includes an important bug fix: The module will now exclude pages in the trash from being linked!

  • Like 1

Share this post


Link to post
Share on other sites

Ahoi @MoritzLost,

just installed your module/textformatter again in a new project. I knew it from previous installations but now... I can't get it working as expected. 

I set up the templates, added the textformatter to my textarea fields but there is no chance internal pages get any links.

What would be the best way to debug that?

I'm running a 3.0.165 on a PHP 7.4 and MySQL 5.6 environment.

I almost know that isn't a bug in the module itself but I really don't know how to trace down the problem.

Any ideas are welcome.

  • Like 1

Share this post


Link to post
Share on other sites

@wbmnfktr Hm, if you're using the latest version (4.1.0), there are a couple of settings you can check (Modules -> Configure -> TextformatterPageTitleLinks). Here's a list of all settings and what they do: https://github.com/MoritzLost/TextformatterPageTitleLinks#all-settings

A couple of possible reasons:

  • Have you selected the templates you want to be linkable? With no templates selected, the module does nothing.
  • In your template output, is output formatting turned on? With output formatting disabled, textformatters aren't applied.
  • Since you said "internal pages", are those visible (not hidden) and does the corresponding PHP template file exist? Templates without a template file are not viewable by default, so they won't get linked. In this case, you may need to check both Include hidden pages and Disable automatic visibility check.
  • There are other options that limit which pages may be linked, especially Minimum length for linkable titles and Use case insensitive mode, make sure none of those are the culprit.
  • Is your site multi-language? The module only links titles in the current language and doesn't fall back to the default language if the current language title is empty. So if you're checking in a non-default language and your pages have empty titles in that language, nothing will get linked.

If all those settings are correct, I'd start by checking which pages the module selects as candidates for automatic links. If you're using Tracy Debugger, you can check with barDump (otherwise, just use var_dump). Insert this in TextformatterPageTitleLinks.module#L101-L103:

// get all pages of the selected templates as an associative id => title array
$id_title_array = $this->getTitleIdArrayForCurrentLanguage($template_ids, $options);
bd($id_title_array);

This should dump the array of pages (keyed by page ID) to the Tracy Debugger bar. If you don't see anything, the textformatter isn't being executed at all. If you see an empty array or the pages you want to link to aren't there, the reason is likely one of the settings above.

If the pages you want to link to are included in the array but still don't get linked, it might just be the viewable check (see above). In this case, check what buildTitleMarkup returns in TextformatterPageTitleLinks.module#L147-L148.

Hope this helps! If it's still not working, please post the output of the debug statements and preferably a screenshot of your module settings and I'll take a look.

Share this post


Link to post
Share on other sites

So... even though it will embarass me to new heights... I will post the details to this issue and the details to resolve them.

I used and tried each and every measure @MoritzLost posted in his previous post BUT...

NO RESULTS at all or as Moritz would say The module isn't running at all.

His assumption was 100% correct. The module wasn't evoked, triggered or called at all. Lucky me... the jackpot.

All debug-measures resulted in zero results. So... I went back to the classic debugging once again (which I should have done before).

1. module setup defaults - fine!
2. field setup defaults - fine!
3. module setup details, each and every possible setup option tried - fine!
4. field setup details, each and every Textformatter enabled/disabled - whooops!!!

My body field (textarea, CKEditor) with Hanna, PrivacyWire and ALPT formatter didnt't play well together.
Re-Ordering each and every textformatter didn't help.
Removing all and re-assinging each of those, one after the other, worked out fine!

In my case ... in all setups and versions (based on the non-working setup) this helped:

  1. Deleting all Textformatters from field -> save field
  2. Adding ALPT -> save field
  3. Adding PrivacyWire -> save field
  4. Adding Hanna -> save field

Everything is working now as expected!

I don't know which textformatter might have been the issue or whatever details caused this BUT... if this happens again to me, I will probably reset, remove and add all textformatters to make it work again.

Thank you @MoritzLost - for the debugging details and the module again!

  • Like 1

Share this post


Link to post
Share on other sites

@wbmnfktr Thanks for the update, glad you got it working! Not sure how removing the textformatters and adding them again should change anything, but as long as it's working now ... 🙂

Share this post


Link to post
Share on other sites

To be honest... I don't know as well. This kind of behaviour is totally new to me but on the other side... I almost never have to deal with almost any textformatter plugins/modules/extensions.

I guess it was a huge hickup or some kind of this as it was the first time ever I had to deal with this kind of problem in any of my setups.

Nontheless your module does a pretty good job - as soon as it runs in a setup.

  • Thanks 1

Share this post


Link to post
Share on other sites

Hi,

Thanks for your module. It works really, maybe too much! 😉 I'm wondering if there a way I can limit to the first occurrence of a link in a page by a hook or something. I like the automatic behavior of the module, however I have pages where I repeat the same word each 2-3 sentences, rendering the paragraph looks as a big link to the same page.

Thanks

Mel

Share this post


Link to post
Share on other sites
5 hours ago, mel47 said:

Thanks for your module. It works really, maybe too much! 😉 I'm wondering if there a way I can limit to the first occurrence of a link in a page by a hook or something. I like the automatic behavior of the module, however I have pages where I repeat the same word each 2-3 sentences, rendering the paragraph looks as a big link to the same page.

Maybe this module would be a better fit then? 

 

Share this post


Link to post
Share on other sites
6 hours ago, mel47 said:

Thanks for your module. It works really, maybe too much! 😉 I'm wondering if there a way I can limit to the first occurrence of a link in a page by a hook or something. I like the automatic behavior of the module, however I have pages where I repeat the same word each 2-3 sentences, rendering the paragraph looks as a big link to the same page.

@mel47 Hi Mel, glad the module is working well for you! You can change the way links are created or prevent them entirely using the hook TextformatterPageTitleLinks::buildTitleMarkup (see the link for the documentation). This method is called for every title found in a text field and returns the HTML to replace the link. You can overwrite this to just return the title in certain conditions, which means no link will be created. Here's a hook that will keep track of which titles have already been linked and prevent more than one link per occurance of each page title:

// limit automatic links to one per individual title, even if the title appears multiple times on the page
wire()->addHookAfter('TextformatterPageTitleLinks::buildTitleMarkup', function (HookEvent $e) {
    $title = $e->arguments(0);
    $page = $e->arguments(1);
    $options = $e->arguments(2);

    // keep track of all the titles that have already been linked
    static $alreadyLinkedTitles = [];

    if (in_array($title, $alreadyLinkedTitles)) {
        // if the title has already been linked, overwrite the HTML markup with the plain title
        $e->return = $title;
    } else {
        // otherwise, just add the title to the array of linked titles
        $alreadyLinkedTitles[] = $title;
    }
});

A couple of caveats:

  1. The static array will not distinguish between fields, so this will limit the automatic links to one link per title on the whole page, not one link per title within one field (though it sounds like this is what you want).
  2. If you access the same field multiple times in your template, it will only contain links the first time.

Another solution, if the word you're repeating multiple times is very short, you can just use the minimum length setting to prevent it getting linked, or use the hook above to prevent automatic links for a few specific pages.

I hope this works for you! If you need even more fine control, it might be simpler to create the links manually or use another module as suggested by @bernhard.

  • Like 2

Share this post


Link to post
Share on other sites

Hi @MoritzLost

Thanks for making the module. It's really handy for sites that have majorly a lot of pages. 

I'm working on a game site where there are heroes and their special abilities, items, etc. . Was totally delighted that it was working on my test environment but I noticed that (sorry if it feels snobbish but itemizing helps me think lol)

  1.  hyperlinking only works on the Body textarea
  2.  it only works on one page template so it seems 

I have two templates - hero and hero-ability. They're both in the module settings. 

I've also counter checked that my textarea fields have the same settings as the Body textarea.

Did I do something wrong? Or did I misunderstand something? Thanks. 

screenshot-d2g-2020_12.22-23_26_26.thumb.png.59bccb50585a6579e28622a8339c1469.pngscreenshot-d2g-2020_12.22-23_28_50.thumb.png.c61da2491d25e4c923c8e5ed5c433203.png

1770033707_screenshot-d2g-2020_12.22-23_28_50(1).thumb.png.a577895c155f96dde17bf43310b4403b.png

1335448505_download(2).thumb.png.343aed1a4f9f9741ed95939fa416bd30.png

  • Like 1

Share this post


Link to post
Share on other sites

Hi @Pip, thanks for reaching out, I think I know what the problem is. The module should work with any number of templates and on any number of fields. However, before creating a link for a given title, the module checks if the page the title belongs to is actually viewable. I made this the default because for a "normal" use case it doesn't make sense to create a link to a page the current user can't actually view. Based on your screenshots it looks like you display all hero abilities on the page for that hero, so I'm guessing the hero abilities don't have their own sub-pages in the frontend? If there's no hero-ability.php template, no hero-ability pages will be viewable, so the module will not create any links for those.

In version 4.0.0 of the module I added a checkbox to disable the viewable checks for use cases like this one. Your screenshot looks like your site has an older version installed, so make sure to update to the latest version if you don't see the checkbox. After the update the option should appear in the new configuration fieldset Markup and output settings.

By the way if my assumption is correct, you may want to use the hook TextformatterPageTitleLinks::buildTitleMarkup to modify the link for hero-ability pages to point to that ability on the hero page instead (using anchor links). See my answer here for details.

If that doesn't solve the problem: I've written a bit about how to check what the module is doing in my answer here, use that to determine whether the module (a) is not finding the desired titles or (b) is finding the titles but not creating links for them. This can help you find out what's going wrong. Let me know if you need more help!

  • Like 2

Share this post


Link to post
Share on other sites
On 12/23/2020 at 1:41 AM, MoritzLost said:

Hi @Pip, thanks for reaching out, I think I know what the problem is. The module should work with any number of templates and on any number of fields. However, before creating a link for a given title, the module checks if the page the title belongs to is actually viewable. I made this the default because for a "normal" use case it doesn't make sense to create a link to a page the current user can't actually view. Based on your screenshots it looks like you display all hero abilities on the page for that hero, so I'm guessing the hero abilities don't have their own sub-pages in the frontend? If there's no hero-ability.php template, no hero-ability pages will be viewable, so the module will not create any links for those.

In version 4.0.0 of the module I added a checkbox to disable the viewable checks for use cases like this one. Your screenshot looks like your site has an older version installed, so make sure to update to the latest version if you don't see the checkbox. After the update the option should appear in the new configuration fieldset Markup and output settings.

By the way if my assumption is correct, you may want to use the hook TextformatterPageTitleLinks::buildTitleMarkup to modify the link for hero-ability pages to point to that ability on the hero page instead (using anchor links). See my answer here for details.

If that doesn't solve the problem: I've written a bit about how to check what the module is doing in my answer here, use that to determine whether the module (a) is not finding the desired titles or (b) is finding the titles but not creating links for them. This can help you find out what's going wrong. Let me know if you need more help!

Hi @MoritzLost Tried your recommendation. You're right the hero-ability.php was non existing. Recreated it and is now linking automatically! Thanks so much! Happy Holidays!

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Mike Rockett
      TextformatterTypographer
      A ProcessWire wrapper for the awesome PHP Typography class, originally authored by KINGdesk LLC and enhanced by Peter Putzer in wp-Typography. Like Smartypants, it supercharges text fields with enhanced typography and typesetting, such as smart quotations, hyphenation in 59 languages, ellipses, copyright-, trade-, and service-marks, math symbols, and more.
      It's based on the PHP-Typography library found over at wp-Typography, which is more frequently updated and feature rich that its original by KINGdesk LLC.
      The module itself is fully configurable. I haven't done extensive testing, but there is nothing complex about this, and so I only envisage a typographical bug here and there, if any.
    • By Robin S
      File Info
      A textformatter module for ProcessWire. The module can add information to local Pagefile links in two ways:
      As extra markup before, within or after the link As data attributes on the link (handy if you want to use a Javascript tooltip library, for instance) Screenshots
      Module config

      Example of output

      Installation
      Install the File Info module.
      Add the textformatter to one or more CKEditor fields.
      Configuration
      Add markup action (and general)
      Select "Add markup to links" Select the Pagefile attributes that will be retrieved. The attribute "filesizeStrCustom" is similar to the core "filesizeStr" attribute but allows for setting a custom number of decimal places. If you select the "modified" or "created" attributes then you can define a date format for the value. Enter a class string to add to the links if needed. Define the markup that will be added to the links. Surround Pagefile attribute names in {brackets}. Attributes must be selected in the "Pagefile attributes" section in order to be available in the added markup. If you want include a space character at the start or end of the markup then you'll need >= PW 3.0.128. Select where the markup should be added: prepended or appended within the link, before the link, or after the link. Add data attributes action
      Select "Add data attributes to links" Select the Pagefile attributes that will be retrieved. These attributes will be added to the file links as data attributes. Attributes with camelcase names will be converted to data attribute names that are all lowercase, i.e. filesizeStrCustom becomes data-filesizestrcustom. Hook
      If you want to customise or add to the attributes that are retrieved from the Pagefile you can hook TextformatterFileInfo::getFileAttributes(). For example:
      $wire->addHookAfter('TextformatterFileInfo::getFileAttributes', function(HookEvent $event) { $pagefile = $event->arguments(0); $page = $event->arguments(1); $field = $event->arguments(2); $attributes = $event->return; // Add a new attribute $attributes['sizeNote'] = $pagefile->filesize > 10000000 ? 'This file is pretty big' : 'This file is not so big'; $event->return = $attributes; });  
      https://github.com/Toutouwai/TextformatterFileInfo
      https://modules.processwire.com/modules/textformatter-file-info/
    • By MoritzLost
      UPDATE: I have published a stable version of this module!
      Discussion thread:
      Github: https://github.com/MoritzLost/TextformatterPageTitleLinks
      ---
      Hello there,
      I'm working on a tiny textformatter module that searches the text for titles of other pages on your site and creates hyperlinks to them. I'm not sure if something like this exists already, but I haven't found anything in the module directory, so I wrote my own solution 🙂
      It's not properly tested yet and is still missing some functionality I would like to implement, so at the moment it should be considered in BETA. Features include limiting the pages that will get searched by template, and adding a custom CSS class to the generated hyperlinks. As I'm writing this I noticed that it will probably include unpublished and hidden pages at the moment, so yeah ... it's still in development alright 😅
      You can download the module from Github:
      https://github.com/MoritzLost/TextformatterPageTitleLinks
      There's some more information in the readme as well.
      Anyway, let me know what you think! I'm happy about any feedback, possible improvements or ideas on how to improve the module. Cheers.
    • By Mike Rockett
      As I mentioned in this issue, I've create a new textformatter for ParsedownExtraPlugin, which adds some oomph to your markdown.
      Repo: Parsedown Extra Plugin
      Unlike the built-in textformatter for Parsedown and Parsedown Extra, this should be used when you want to use Extra with additional configuration/customisation.
      Some examples:
      ### Test {.heading} - A [external link](https://google.com/){.google} with `google` as a class that opens in a new tab if the config property is set. - [Another link](/page){target=_blank} that opens in a new tab even though it isn't external. ```html .html <p>Test</p> ``` There's some config options available to you, such as setting attributes on all/external images and links, setting table and table-cell alignment classes, adjusting footnote classes and IDs, adding <code> attributes to their parent <pre> elements, and changing the <code> class if your syntax highlighter does not use language-*.
      I was thinking about adding the ability to make links open in a new tab by appending a plus to the link syntax, but only external links should be opening in a new tab anyway. Further, this would add extra, unnecessary processing time.
      Please let me know if you bump into any problems. ☺️
    • By Robin S
      Remove Blocks
      A textformatter module for ProcessWire that removes blocks of text/markup between configurable delimiters from output. This allows you to "comment out" blocks of text/markup so they remain present in the field but are not shown in the front-end output.
      This can be handy if content needs to be removed temporarily and will later be reinstated. Or you could use a commented block as a placeholder to indicate to an editor where some content should be added.
      Installation
      Install the Remove Blocks module.
      Configure the open and close delimiters if needed. The default open delimiter is {{ and the default close delimiter is }}. Tip: don't use delimiter characters that CKEditor will encode to HTML entities, e.g. >.
      Usage
      Add the Remove Blocks textformatter to one or more fields.
      Add the open and close delimiters around any content that you want to be removed from output.

       
      https://github.com/Toutouwai/TextformatterRemoveBlocks
      http://modules.processwire.com/modules/textformatter-remove-blocks/
×
×
  • Create New...