This plugin serves to capture keywords in plain text and render them as a rich element of your choosing such as a link, a popup or a widget.

Examples of use cases:

This plugin can handle an arbitrary large number of keywords. As a rule of thumb, on PHP 5.5 with OPcache running on commodity hardware it takes about 1.5 ms to search for the names of 13,638 Magic: The Gathering cards in a text of a thousand characters. However, performance is highly dependent on the list of keywords and the content of the text and it is recommended to benchmark your application accordingly.

Keywords are case-sensitive by default.

When not to use this plugin

In some cases, it might be preferable to use the Preg plugin. For instance, in a programming forum, instead of creating a list of every function name as keywords (in order to link them to a manual, for example) you may want to use the Preg plugin and simply capture any series of valid characters immediately followed by a parenthesis.

Examples

$configurator = new s9e\TextFormatter\Configurator;

// Add a couple of keywords
$configurator->Keywords->add('Bulbasaur');
$configurator->Keywords->add('Pikachu');

// Keywords are case-sensitive by default but you can make case-insensitive.
// This is not recommended if the list of keywords contain words that could
// appear in normal speech, e.g. "Fire", "Air", "The"
$configurator->Keywords->caseSensitive = false;

// Set the template that renders them
$configurator->Keywords->getTag()->template
    = '<a href="http://bulbapedia.bulbagarden.net/wiki/{@value}"><xsl:apply-templates/></a>';

// Get an instance of the parser and the renderer
extract($configurator->finalize());

$text = 'Bulbasaur and Pikachu';
$xml  = $parser->parse($text);
$html = $renderer->render($xml);

echo $html;
<a href="http://bulbapedia.bulbagarden.net/wiki/Bulbasaur">Bulbasaur</a> and <a href="http://bulbapedia.bulbagarden.net/wiki/Pikachu">Pikachu</a>

How to only capture the first occurence of each keyword

By default, every occurence of every keyword is captured by the plugin. In situations where keywords are used at a high frequency, this can create unwanted noise. In this case, you can configure the Keywords plugin to only capture the first occurence of each keyword by setting the onlyFirst property.

$configurator = new s9e\TextFormatter\Configurator;

// Add a couple of keywords
$configurator->Keywords->add('Pikachu');
$configurator->Keywords->add('Raichu');

// Set onlyFirst so that we only link the first occurence of each keyword
$configurator->Keywords->onlyFirst = true;

// Set the template that renders them
$configurator->Keywords->getTag()->template
    = '<a href="http://bulbapedia.bulbagarden.net/wiki/{@value}"><xsl:apply-templates/></a>';

// Get an instance of the parser and the renderer
extract($configurator->finalize());

$text = 'My Pikachu is the best Pikachu. Raichu sucks.';
$xml  = $parser->parse($text);
$html = $renderer->render($xml);

echo $html;
My <a href="http://bulbapedia.bulbagarden.net/wiki/Pikachu">Pikachu</a> is the best Pikachu. <a href="http://bulbapedia.bulbagarden.net/wiki/Raichu">Raichu</a> sucks.

How to use multiple keyword lists

One way to use multiple lists of keywords and map them to different tags is to rename the Keywords plugin to a different name by copying it and removing the original. Plugin names must start with a capital letter.

$configurator = new s9e\TextFormatter\Configurator;

$configurator->plugins->load('Keywords', ['tagName' => 'COLOR']);
$configurator->Colors = $configurator->Keywords;
unset($configurator->Keywords);

$configurator->plugins->load('Keywords', ['tagName' => 'SNACK']);
$configurator->Snacks = $configurator->Keywords;
unset($configurator->Keywords);

$configurator->Colors->add('blue');
$configurator->Colors->add('red');

$configurator->Snacks->add('Mars');
$configurator->Snacks->add('Twix');

extract($configurator->finalize());

$text = "blue red\nMars Twix";
$xml  = $parser->parse($text);

echo $xml;
<r><COLOR value="blue">blue</COLOR> <COLOR value="red">red</COLOR>
<SNACK value="Mars">Mars</SNACK> <SNACK value="Twix">Twix</SNACK></r>