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.
    • 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.
  • Prefer oldest or newest page in the case of duplicate titles.
  • Queries the database directly for improved performance.
    • Only queries the database once per request & language.

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!

Edited by MoritzLost
Updated features section to include most recent additions
  • Like 7

Share this post


Link to post
Share on other sites

Changelog

Version 2.1.0

  • Feature: Prefer the oldest or the most recent page for automatic linking, in the case that two or more pages have the same title. Defaults to linking the oldest page. This is technically backwards-incompatible, as previously the selection of the linked page was pseudo-random in this case, but it's a pretty niche case.
  • Feature: Set the minimum length for linkable pages. If you have pages with very short titles that appear commonly in different places, you might not want those linked every time. For example, if you set the minimum length to 5 characters, pages whose title is only four characters or shorter will never be linked.
    • Tiny caveat: The length detection doesn't work correctly with emoji (or probably any 4-byte UTF8 character in the title). No idea why, the query uses CHAR_LENGTH which is supposed to accurately report multi-byte string length. If you know more about this, let me know!
  • Bugfix: Version 2.0.0 changed the query in a way that would cause errors on older versions of MySQL, this is now fixed. Previous version might have thrown errors depending on the MySQL configuration (specifically, if ONLY_FULL_GROUP_BY was active), this should also¬† not happen anymore.
  • Miscellaneous
    • I expanded the README, it now has a section about how to use the formatter manually. There are a couples of gotchas to this, so it could be helpful to beginners.
    • The attribute settings are now parsed using preg_split instead of explode. This should prevent potential issues with windows-style CRLF linebreaks.

Version 2.0.0

  • Backward incompatible changes
    • Version 2.0.0 changes how titles are selected from the database and matched in text fields (see below for details). This is why this gets a major version number bump.
    • The previous CSS classes setting has been removed in favour of the more general attributes setting (see below).
  • Feature: Better HTML detection and edge case prevention
    • The module got much better at checking the surroundings of a title to make sure it doesn't produce invalid HTML. In particular, it will now detect the following scenarios leave those as-is:
      • If a page title is already inside anchor-tags.
      • If a page title is inside attributes of other tags (for example, the description in a title-attribute.
    • That said,¬† the module still uses regex to find and replace titles, so it will never be able to cover all scenarios. For example, it will not detect if a page title is inside other tags that are not anchor tags (e.g. spans) which are in turn inside another anchor. So this module shouldn't be used on text fields where you need lots of custom HTML and intricate HTML structures.
  • Feature: Configure arbitrary attributes to include in the created links
    • You can now add attributes such as title, class, target, custom data-* attributes or anything you want to the links. This includes standalone attributes (without a value).
    • For the attribute values, you can use replacement patterns that are passed to $page->getText(). For example, you can annotate the links with descriptive titles for accessibility or generate a class absed on the template of the linked page. Check out the examples on the module settings page!
  • Feature: Longer titles get linked preferrentially
    • If the title of one page is contained within the title of another page, the page with the longer title will get linked, not the shorter one. For example, if you have two pages titled "Content" and "Content Management System", the entire phrase "Content Management System" will be linked to the corresponding page. The page "Content" will not be linked in that instance. Of course, if in another part of the text you only have the word "Content", it will still be linked to the page as usual.
    • This change was made possible by the detection of the edge cases mentioned above. Previously, the module would create the shorter links first to avoid creating nested links.
    • The reason for this change is that longer titles tend to be more relevant for internal links. For example, in the previous case, the word "Content" could appear in many contexts not necessarily related to the page "Content", whereas the phrase "Content Management System" is much more specific. I may make this behaviour optional if there is a usecase for it. If you need this for some reason, let me know.
  • Feature: Unicode support
    • Now works with diacritics and emoji in the titles. To be fair, it was mostly working already, but now the regex includes the u Flag to explicitly turn off UTF-8 compatible functionality.
    • There's still an edge case regarding diacritics (try creating two pages "Apfel" and "√Ąpfel" and you'll see it ...). I don't have a fix for it at this point, but it only occurs in very specific scenarios, so for now it'll do.
  • Bug fixes
    • Correctly detects multilanguage sites. Previously it would fail on a multilanguage site that used a non-multilangue title field.
    • Adjusted the main database query to not produce warnings when fed directly to MySQL in certain configurations.
Edited by MoritzLost
Added version 2.1.0 information
  • 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

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 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 Mike Rockett
      TextformatterTypographer (0.4.0 Beta)
      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.
      Learn more on my blog
      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.
      Please do test it out and let me know what you think.
      Also note that I have indicated support for PW 2.8, but I haven't tested there as yet. This was built on PW 3.0.42/62.
    • 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/
    • By Lex Sanchez
      Video or Social Post Embed
      Based on the TextformatterVideoEmbed module developed by Ryan Cramer, we have added the possibility to embed publications of the main social networks Facebook, Twitter and Instagram.
      ProcessWire Textformatter module that enables translation of YouTube, Vimeo, Instagram, Facebook, Twitter or Issuu URLs to full embed codes, resulting in a viewable video or social post in textarea fields you apply it to.
      How to install
      Download or Clone from Github: https://github.com/lexsanchez/VideoOrSocialPostEmbed
      Copy the VideoOrSocialPostEmbed.module file to your /site/modules/ directory (or place it in /site/modules/VideoOrSocialPostEmbed/).
      Click check for new modules in ProcessWire Admin Modules screen. Click install for the module labeled: "Video or Social Post Embed".
      Now you will be on the module config screen. Please make note of the config options and set as you see fit.
      How to use
      Edit your body field in Setup > Fields (or whatever field(s) you will be placing videos in). On the details tab, find the Text Formatters field and select "Video or Social Post Embed". Save.
      Edit a page using the field you edited and paste in YouTube, Vimeo, Facebook, Twitter, Instagram and/or Issuu URLs each on their own paragraph.
      Example
      How it might look in your editor (like TinyMCE):
      How it works
      This module uses YouTube, Vimeo, Instagram, Facebook, Twitter and Issuu oEmbed services to generate the embed codes populated in your content. After these services are queried the first time, the embed code is cached so that it doesn't need to be pulled again.
      Configuration
      You may want to update the max width and max height settings on the module's configuration screen. You should make these consistent with what is supported by your site design.
      If you change these max width / max height settings you may also want to check the box to clear cache, so that YouTube/Vimeo/Facebook/Twitter/Instagram/Issuu oembed services will generate new embed codes for you.
      Using with Markdown, Textile or other LML
      This text formatter is looking for a YouTube, Vimeo, Instagram, Facebook, Twitter or Issuu video URL surrounded by paragraph tags. As a result, if you are using Markdown or Textile (or something else like it) you want that text formatter to run before this one. That ensures that the expected paragraph tags will be present when VideoOrSocialPostEmbed runs. You can control the order that text formatters are run in by drag/drop sorting in the field editor.
      Copyright 2018 by Ryan Cramer / Updated by Lex Sanchez