Readme / Highlighter / Custom highlighter
If you need more than just replace links by html tags. There are 2 options available for your choice:
- Extend HtmlHighlighter, bundled with library.
- Create highlighter implementing HighlighterInterface. Gives more flexibility, but could be complicated.
💡 Tip: Check HtmlHighlighter constructor. There is simple configuration available, possibly covering your case.
In most of the cases it would be enough to extend HtmlHighlighter. It's highly customizable providing variety of protected methods which gives ability to change any part of highlighting process.
Let's say you want to display only hostname as link text and add nofollow
attribute for external websites.
To achieve this, you need is to create a custom highlighter and override 2 methods:
<?php
use VStelmakh\UrlHighlight\Highlighter\HtmlHighlighter;
use VStelmakh\UrlHighlight\Matcher\UrlMatch;
class CustomHighlighter extends HtmlHighlighter
{
protected function getText(UrlMatch $match): string
{
return $match->getHost();
}
protected function getAttributes(UrlMatch $match): string
{
return $match->getHost() === 'your-website.com'
? ''
: ' rel="nofollow"';
}
}
💡 Tip: UrlMatch gives you access to all properties of current url match. Check class public methods for more details.
Then you need to configure UrlHighlight to use CustomHighlighter
. This could be done via dependency injection:
<?php
use VStelmakh\UrlHighlight\UrlHighlight;
$customHighlighter = new CustomHighlighter();
$urlHighlight = new UrlHighlight(null, $customHighlighter);
echo $urlHighlight->highlightUrls('Follow http://your-website.com/welcome not http://other-website.com.');
// Output:
// Follow <a href="http://your-website.com/welcome">your-website.com</a> not
// <a href="http://other-website.com" rel="nofollow">other-website.com</a>.
// line break added for readability
For all the possibilities check protected methods in HtmlHighlighter. It's well documented in doc-blocks itself.
If you need completely custom behaviour or need to highlight urls using not HTML syntax - implementing HighlighterInterface
could be the option in this case.
This way is more complicated, but gives you ability to create completely custom behaviour.
💡 Tip: If you need custom highligter aware of HTML syntax, you could extend HtmlHighlighter, but completely change highlighting logic. See MarkdownHighlighter for example.
For example, you want to hide all the urls from string input:
<?php
use VStelmakh\UrlHighlight\Highlighter\HighlighterInterface;
use VStelmakh\UrlHighlight\Matcher\UrlMatch;
use VStelmakh\UrlHighlight\Replacer\ReplacerInterface;
class CustomHighlighter implements HighlighterInterface
{
public function highlight(string $string, ReplacerInterface $replacer): string
{
// replaceCallback expects string input and callback accepting UrlMatch as argument
// Callback should return string replacement for provided url match
return $replacer->replaceCallback($string, function (UrlMatch $match) {
// There is no reason to care about encoded input at this point.
// Replacer internally using encoder provided to UrlHighlight constructor.
return '%censored%';
});
}
}
💡 Tip: You could use private class method as a callback using
\Closure
, see HtmlHighlighter::doHighlight for example.
<?php
use VStelmakh\UrlHighlight\UrlHighlight;
$customHighlighter = new CustomHighlighter();
$urlHighlight = new UrlHighlight(null, $customHighlighter);
echo $urlHighlight->highlightUrls('Visit http://example.com and http://example2.com.');
// Output:
// Visit %censored% and %censored%.
To test HighlighterInterface::highlight()
you need to provide 2 arguments: input string
and instance of ReplacerInterface.
Usually there is no problem to find a test string, but for ReplacerInterface you need a real object or mock.
That's the point where it could be confusing.
Mocking ReplacerInterface is not easy and unnecessary. Use ReplacerFactory to get a real object implementing ReplacerInterface. It's simple and gives you same behaviour as Url highlight library do. So you can focus on testing your custom highlighter logic, instead of building complex mocks.
<?php
use PHPUnit\Framework\TestCase;
use VStelmakh\UrlHighlight\Replacer\ReplacerFactory;
class CustomHighlighterTest extends TestCase
{
public function testHighlight(): void
{
$input = 'http://exmple.com';
$expected = '<a href="http://exmple.com">http://exmple.com</a>';
$htmlHighlighter = new CustomHighlighter();
$replacer = ReplacerFactory::createReplacer();
$actual = $htmlHighlighter->highlight($input, $replacer);
self::assertSame($expected, $actual);
}
}
💡 Tip: See HtmlHighlighterTest and MarkdownHighlighterTest for additional examples.