Skip to content

bschwede/linkenhancer

Repository files navigation

webtrees module LinkEnhancer

TL;DR | Description | webtrees | Requirements | Installation | Contributing | Translation | Support | License

License: GPL v3 webtrees major version Latest Release Downloads

Important

Primary Repository: https://codeberg.org/bschwede/linkenhancer

All activity happens on Codeberg:

Mirror Repository: https://github.com/bschwede/linkenhancer

TL;DR

Cross-references to Gedcom datasets, Markdown editor, context-sensitive link to the GenWiki Webtrees manual

What you can expect from the module, illustrated with screenshots:

Screenshots Screenshots
note with links site title as link

small menu with help link
note with enhanced links and
image from media record
site title as home link
small menu with help link
Markdown editor Markdown Help
markdown editor markdown help

Here are the available options that can be set on the admin page of this module:

admin page

Description

This module wraps up some examples mentioned in the German Webtrees Manual and improves the application of these features - each component can be activated individually.

The main purpose of this module is to make links to data records stored in family trees more convenient. This avoids having to store fully qualified links, which impairs the portability of Gedcom data. By linking the notes to the GEDCOM data records (persons, families, sources, etc.) from the text makes story telling much easier and thus also save this information in the GEDCOM file (maybe this is an alternative for the stories module). The option of embedding the images already inserted in the family tree in the notes rounds off this approach. The link function is controlled via the anchor part of the URI, so it's no problem, if this module is not active - the url just points to the current webtrees page.

Additionally there are some goodies more or less related with links:

Enhanced links

Although webtrees replaces XREFs such as @I2@ in notes with a cross-reference and it's appropriate display name, this is not so flexible. You can't determine the display name, which means that in the event of an error (due to XREF renumbering or typing error), it is not easy or possible to resolve the cross-reference to the corresponding data record without any doubt. Unfortunately, this does not work in the HTML block on the start page if you want to refer to a data record in the continuous text without inserting absolute references (such absolute references could be entered in the source code of the HTML block as follows, for example: <a href="https://mytree.somewhere/tree/mytree/individual/I2">Jon Doe</a>).

Tip

The custom module webtrees-mitalteli-show-xref can help you find the XREF reference of personal data records.

The enhanced links function is implemented via Javascript and searches in the rendered output of webtrees for <a> tags whose href attribute values begin with #@. This way it is possible to handle links in markdown and html markup. Because it is processed in the browser on client side, the existence of the cross-referenced data records in webtrees is not checked in advance. Errors only occur when the link is clicked (e. g. if the access to the ressource is restricted).

As a bonus different destinations can be addressed with one link definition, whereby the cross-reference is always the first link (if set) and the others are represented by attached clickable icons only. Included are the following predefined external targets (the parameter keys are listed in parentheses):

Each parameter key can be specified multiple times – but you shouldn’t overdo it for the sake of clarity.

Syntax:

  • Markdown: In general, an enhanced link looks like this [Link display title](#@param1&paramN) so that one or more targets can be addressed at once. For cross-references in webtrees a record type and the XREF is expected, the parameter looks as follows
    • wt=n@XREF@ - standard link to note with XREF in the current tree
      available record types:
      • i=individual
      • f=family
      • s=source
      • r=repository
      • n=note
      • l=sharedPlace
    • wt=i@XREF@othertree+dia - link to record type individual with XREF from tree "othertree" and also link to Interactive tree of this person
    • wt=@XREF@ - simplified standard link without given record type - access to record page via redirect url
  • HTML: The same applies to html links: <a href="#@wt=i@I1@">Link display title</a> So this is also useable in cooperation with the name badge function of the “⚶ Vesta Classic Look & Feel” module in the HTML snippet field: <a href="#@fsft=<ref/>"></a> for linking to a record in the Family Search Family Tree. It's also possible to embed those links in news articles of Tywed's news-menu module or in FAQ articles.

The syntax of the external targets is listed by the markdown help function of this module. In most cases, only one key-value parameter pair needs to be specified, consisting of the short name of the desired target and the ID of the data record located there.

After a lot of theory: How does it looks like in webtrees?! In the upper part of the image we can see the edit mode of a note record, below how it ist rendered in view mode:

Note with enhanced links - edit and view

Additional external targets can be configured by providing a custom JavaScript object on the admin page of this module. Here two example entries from predefined targets to illustrate the principle:

{
  "fsft": {
      name: 'Family Search Tree - $ID',
      url: 'https://www.familysearch.org/tree/person/details/',
      cname: 'icon-fsft'
  },
  "wp": {
      name: 'Wikipedia',
      url: (id, title) => {
          let parts = id.split('/');
          if (parts.length < 2) {
              title = title + " - " + options.i18n('syntax error') + "!";
              return { url: '', title };
          }
          let subdomain = parts[0];
          let article = parts.slice(1).join('/');
          title = `${title} - ` + decodeURIComponent(article) + ` (${subdomain})`;
          return { url: `https://${subdomain}.wikipedia.org/wiki/${article}`, title };
      },
      cname: 'icon-wp',
      help: [
          { n: options.i18n('wp-help1'), e: 'de/Webtrees' },
          { n: options.i18n('wp-help2'), e: 'en/Webtrees' },
          { n: options.i18n('wp-help3'), e: 'other-subdomain/Webtrees' },
      ]
  }
}

Now some explanation for the used properties in the code snippet above (as a reminder, how the syntax of a base enhanced link looks like: #@param-key=param-value):

  • key = is the above mentioned short name or query parameter key (param-key)
  • name = title or label to be displayed as link title;
    standard: the placeholder $ID will be replaced by the given id (param-value)
  • url = service url to be called
    standard: the parameter value / given record id (param-value) will be appended to the end of the url It can also be a function provided, that accepts as parameter (id, title) and returns an object { url, title }. This returned title will be set instead of the name-property.
  • cname = CSS class name(s) whitespace separated
  • help = optional array of objects [{n:'', e:''},..] to illustrate the use of a non standard target (where the url-property is a function) by examples (in e), provided with explanatory text (in n). This information is listed in the markdown help.

options.i18n is a function passed through from this module in order to provide translated strings.

Any CSS rules required are best added via the “CSS and JS” module. Only the definition of the icon (size 30 x 30 pixels is sufficient) as a background image is actually needed - referencing as data: URL (see also: mdn web docs - data: URLs).
For example: .icon-whatever { background-image: url(...) }

Note

When Webtrees provides better support for UID, referencing via UID will probably also be implemented in this module, as this will make links more fail-safe. See also:

Markdown

Markdown is a simple system of formatting, used on websites such as Wikipedia or Github. It uses unobtrusive punctuation characters to create headings and sub-headings, bold and italic text, lists, tables, etc.

Webtrees uses a CommonMark implementation and supports a subset of the markup. It is optionally supported in note records on a per tree basis.

On the subject of markdown see also:

Note

For the Markdown Image Support and the additional Markdown Extensions the MarkDownFactory class needs to be extended by this module. This replacement class also fixes fisharebest/webtrees#4841, so that a pre-formatted markdown block is not rendered as a single line any more.

Markdown Image Support

note with links

This feature allows you to easily embed images from GEDCOM media records (first image), which reside behind the media firewall or from the public directory into notes. If restriction rules apply to the record, instead of the image, a message is displayed.

Syntax:

  • ![alternate text for gedcom object](#@id=@M1@)
  • ![alternate text for picture in public folder](#@public=webtrees.png "title")
  • ![picture with defined height, width and additional css class](#@id=@M1@&h=200&w=200&cname=float-right)

Technically the images are packed into a div container together with an image subtitle - which is also a link to the media data set for GEDCOM objects. The display can be customized as required using the standard CSS classes or per image additional CSS classes (e.g. float-start or float-end from webtrees vendor.css).

Markdown editor

You can also enable a visual markdown editor for note textareas. Under the hood the project “TinyMDE - A tiny, dependency-free embeddable HTML/JavaScript Markdown editor” is used - see also: https://github.com/jefago/tiny-markdown-editor

Markdown editor

Besides syntax highlighting it ships with an icon bar for common format commands, a help popup and line numbering.

Markdown Help

Note

Unfortunately, the on-screen keyboard does NOT work as before with the previous text input field. The selected characters end up as an intermediate step in the small text field below the Markdown editor and then must be copied manually to the desired position.

Markdown Extensions

Warning

Please keep in mind when using this extensions, you are deviating from the smallest common markdown dialect set. If the library used to render markdown in HTML needs to be changed for any reason, there is a possibility that not all of the extended markup used here will be supported. (see also #32). Since the markup is not intrusive, the impact should not be serious – of course, it's a minor drawback.

The package League\CommonMarkdown used for processing Markdown texts offers several useful extensions that can be activated optionally:

You can activate all or a few selected of these extensions. As far as possible they are of course integrated with the markdown editor and you find additional information in the markdown help.

Footnotes can be placed near their references (there can be one or many references to one footnote) or everywhere you want. For the overview, it is advisable to place them at the bottom. When rendering, the footnote container resides at the end of the content. If your text is structured with headings, it is a good choice to activate the table of contents extension. The table of contents is generated automatically and included into the content above the very first heading or instead of a placeholder.

Table cell height control

For longer markdown note texts it's sometimes a pain to scroll through if you are interested in the next facts beneath them at the moment. This feature should come in handy here: By activating the checkbox in the top right corner of the title cell (first table column), the maximum height of the content cell with the long note is set to about 80% of the view port height. This makes the content itself scrollable. Where applicable, the function can be activated by default (or simply made available) and can also be deactivated independently.

Markdown table cell height control

In combination with the table of contents extension (position = dropdown), you can navigate through the text easily - assuming the text is structured with headings.

You can decide, if the checkbox is always visible or hidden until you hover the fact title cell with the mouse cursor. If the text length of the content cell doesn't exceed the defined maximum height, the checkbox can not be activated.

German webtrees manual

small menu with help link

A context sensitive help link to the german webtrees manual can be added to the small navigation menu. Context links are also available for components on pages provided by custom extensions (e.g. on the individuals page, the start page or items in the main menu) – these can be identified by the i symbols in a circle.

WTHB subcontext help

To ensure that this function is also available in the admin backend a modified version of views/layouts/administration.phtml must be registered. This module attempts to use the custom module vesta_common (if installed and enabled) or its own version of the view layout file. Alternatively, patch P002 could also be applied to the core code.

If the webtrees page is displayed in a language other than german, it is possible to open the webtrees manual URL via a translation service (Google Translate). This can be enabled or disabled as a site setting or delegated to the visitor to decide.

WTHB user setting

The settings dialogue can be accessed via the help submenu in the top menu. When this option is enabled, you will also find a link to a dialogue box that displays a full-text search in the german webtrees manual (using various search engines) and the table of contents.

WTHB full-text search and toc

Note

This module comes with a local copy of the german webtrees manual table of contents. An automatic update is not implemented so far. If you wish to update it without updating this module, you can use the utility script update-wthb-toc.sh.

In addition, the submenu contains an overview of the help topics included in Webtrees and customisable external help links (e.g. Webtrees FAQ and forum, GitHub repo, etc.). The top menu item can be split into two links - one to directly open the context help article and the other to open the submenu.

WTHB submenu and split menu item

The module contains some standard external help links, that are defined in JSON - array of objects with the following members:

  • title: display text for the link, can also contain html (string, mandatory), language should be en-US, for standard link titles translations are provided
  • url: link to web resource (string, mandatory)
  • class : additional css class names; (string, optional)
  • self : if set, link target is _self (opens in place), otherwise _blank (any type, optional)
  • i18n : overwrite title with user defined translation for given language tags (object, optional; keys are language tags, values translated title)

Example:

[
  {"title":"webtrees FAQ <i class=\"fa-solid fa-circle-question\"></i>",
   "url":"https://webtrees.net/faq/",
   "i18n": { "de": "webtrees Häufig-gestellte-Fragen <i class=\"fa-solid fa-circle-question\"></i>" }
  }
]

The mapping of routes to help articles in the manual is stored in the database table route_help_map. This module comes with predefined mapping rules. If there is something missing or you find an issue, don't hesitate to share it. I'll include it in the next release.

Technical background information follows now.
The table has the following headers (the headers required in a CSV file for import are marked with !!):

  • id: automatic key - not relevant, the data field is only used to make it easier to identify the data record during editing.
  • path !!: route path - corresponds to the path of webtres pretty urls
  • handler !!: usually corresponds to the php class name of the code that handles the request
  • method !!: web request method (GET, POST, HEAD)
    Only GET routes are generally relevant for assignment to manual sections.
  • extras !!: php class name of access level (Fisharebest\Webtrees\Http\Middleware\Auth*)
  • subcontext !!: CSS selector string or JSON object string to address a component/subcontext topic on the given page
  • category: string value for better grouping data rows; only value 'generic' has a special meaning
  • order !!: arbitrary numerical sort key, matching data rows are sorted in ascending order standard value is 10
  • url !!: path of the url to the webtrees manual (then it's concated with the given GenWiki base/domain url) also fully qualified url to other web ressources are possible and supported (for example to Github repo readmes or wikis of custom modules, that aren't documented in the manual yet)
  • updated_at: timestamp of last update this helps to identify possibly outdated data rows

As we can see in app/Http/Routes/WebRoutes.php, where standard webtrees routes are defined, for a route the following information is mandatory:

  1. path
  2. handler
  3. method

Optionally extras can be provided. If none of those four mentioned fields is set, the data row ist filtered by the seeder. On import category and order are set automatically if not set.

In order to get a first class match with the current route those four fields have to match.

Normally, it is only necessary to assign GET routes to an article. We also have a few redirect routes and ajax helper routes (which provide data for form controls) that can be ignored.

Special cases are the paths beginning with /module/{module}/{action} or /tree/{tree}/data-fix/{data_fix}: they are handled by an integrated proxy class that addresses the custom module by a route attribute:

For mapping such a route to a specific custom module help article the handler is set to the above mentioned routes attribut value (e.g. _vesta_classic_look_and_feel_). For a more generic rule, path can also be empty (then one rule can be used for both cases).

Fallback rules for access levels are matched by category='generic' and the specific Auth classname in extras.

In ascending order the first rule where subcontext = '' is selected for the top menu link. If nothing else applies, the link points to the startpage of the manual.

If activated, subcontext topics on a page can be provided with an additional help link. You can set a CSS selector string or a JSON object string with the following properties:

  • p: position of popover, optional (default is top, other possible values: left, right, bottom)
  • f: css selector/filter string (only necessary if you want the popover to be positioned differently) OR
  • e: javascript expression string

This is useful, if there are components on the page that require more detailed information than offered by the help link in the top menu (e.g. for custom module functions on the individuals page). This help link is displayed in a popover (because an additional link does not always work in bootstrap tabs, accordeon headers or menu titles). Set category='generic' for rules that should apply to more than one page.

On the admin page of this module it is possible to import routes registered in webtrees on demand. This make it easier to cover individual custom module configurations. Further more you can import and export data in csv format in order to make changes more convenient. You can define the separator and for import the character encoding (on export it is always utf-8). You can see at a glance how many data rows are stored in the table and how many of them have an url assigned.

admin page data table

In case of discrepancies the context help can be more easily adjusted by activating the option "Output of debug information on the JS console". This provides you with information on the active route and, if applicable, data table entries found for matching routing to help topics.

Home link

The site title can be a link to the tree homepage or the user my page.

site title as link

Dynamic CSS styles can be applied to match the current theme, ensuring that the display contrasts well. Of course it is not limited to the home link use case.

On the admin page of this module you can configure a JSON object to achieve this:

{ 
  "*": ".homelink { color: #039; }",
  "colors_nocturnal": ".homelink { color: antiquewhite; }"
}

Explanation: The object key name is set to the theme name to be matched, and the string value contains one or more css style rules. In this example we have a fallback rule with key * that matches all themes unless there is a specific key. Theme colors is a special case, where we also have palettes. In order to address this combination the key is set to theme name_palette name. The Key colors matches to all subthemes.

Just activate the option "Output of debug information on the JS console" in order to figure out the correct values.

Patches

The patches can be applied additionally — the module also works without them!

The util subfolder contains minor patches for the webtrees core. These are diff-files that can be easily applied or removed using shell from within the installed module folder (necessary for auto detecting webtrees sources):

Usage: util/wt-patch.sh [-R] [FILTER]
  -R                  undo Patch (patch -R)
  FILTER              '*' for all or specific (e.g. '01')

Don't forget to reapply the patches after updating webtrees.

These are minor bug fixes or functional enhancements — usually in a single file — that are intended to bridge the gap until they are officially fixed/implemented in the webtrees core.

# Description applies to version
P001 Backlink for level 1 shared notes #5181
/app/Fact.php
2.2.1 -
P002 Enable headContent/bodyContent for this module on admin backend in order to show the context help link #5214
resources/views/layouts/administration.phtml
2.2.1 -
P003 Record has multiple uid fields #4828
app/Services/GedcomEditService.php
2.2.1

webtrees

webtrees is an online collaborative genealogy application. This can be hosted on your own server by following the Install instructions.

Requirements

This module requires webtrees version 2.2. This module has the same requirements as webtrees#system-requirements.

This module was tested with webtrees version 2.2.4 and build-in themes and some other custom modules.

Installation

  • Install and use Custom Module Manager for an easy and convenient installation of webtrees custom modules.
  • Open the Custom Module Manager view in webtrees, select "linkenhancer", and click on the "Install Module" button.

Manual installation:

  1. Download the latest release of the module.
  2. Upload the downloaded file to your web server.
  3. Unzip the package into your modules_v4 directory.
  4. Rename the folder to linkenhancer

If everything was successful, you should see a subdirectory linkenhancer with the unpacked content in the modules_v4 directory.

During the initial installation, the following problem may occur: "PDO error - There is no active transaction" - for more details see known issues.

Contributing

If you'd like to contribute to this module, great! You can contribute by

  • Contributing code - check out the issues for things that need attention. If you have changes you want to make not listed in an issue, please create one, then you can link your pull request.
  • Testing - it's all manual currently, please create an issue for any bugs you find.

Translation

You can contribute to this project on Codeberg Weblate.

Updated translations will be included in the next release of this module.

Beside English the following languages are available:

  • Catalan (by Bernat Josep Banyuls i Sala)
  • Dutch (by TheDutchJewel)
  • Español (by Bernat Josep Banyuls i Sala)
  • German

Support

  • Issues: for any ideas you have, or when finding a bug you can raise an issue.

  • Forum: general webtrees support can be found at the webtrees forum.

License

  • Copyright (C) 2026 Bernd Schwendinger
  • Derived from webtrees - Copyright 2025 webtrees development team.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.


About

webtrees custom module - cross-references, Markdown, context-sensitive link to the GenWiki Webtrees manual

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors