class LinkRenderer in Markdown 3.0.x
Plugin annotation
@MarkdownExtension(
id = "enhanced_links",
label = @Translation("Enhanced Links"),
installed = TRUE,
description = @Translation("Extends CommonMark to provide additional enhancements when rendering links."),
parsers = {"thephpleague/commonmark", "thephpleague/commonmark-gfm"},
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\markdown\Plugin\Markdown\Extension\BaseExtension implements MarkdownExtensionInterface uses MarkdownStatesTrait
- class \Drupal\markdown\Plugin\Markdown\Extension\CommonMarkExtension implements CommonMarkExtensionInterface
- class \Drupal\markdown\Plugin\Markdown\Extension\LinkRenderer implements \League\CommonMark\Inline\Renderer\InlineRendererInterface, CommonMarkRendererInterface, MarkdownGuidelinesAlterInterface
- class \Drupal\markdown\Plugin\Markdown\Extension\CommonMarkExtension implements CommonMarkExtensionInterface
- class \Drupal\markdown\Plugin\Markdown\Extension\BaseExtension implements MarkdownExtensionInterface uses MarkdownStatesTrait
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of LinkRenderer
File
- src/
Plugin/ Markdown/ Extension/ LinkRenderer.php, line 25
Namespace
Drupal\markdown\Plugin\Markdown\ExtensionView source
class LinkRenderer extends CommonMarkExtension implements CommonMarkRendererInterface, InlineRendererInterface, MarkdownGuidelinesAlterInterface {
/**
* {@inheritdoc}
*/
public function alterGuidelines(array &$guides = []) {
if (!isset($guides['links']['items'][0]['description'])) {
$guides['links']['items'][0]['description'] = [];
}
elseif (isset($guides['links']['items'][0]['description']) && !is_array($guides['links']['items'][0]['description'])) {
$guides['links']['items'][0]['description'] = [
$guides['links']['items'][0]['description'],
];
}
if ($this
->getSetting('external_new_window')) {
$guides['links']['items'][0]['description'][] = '<p>' . $this
->t('All external links will open in a new window or tab.') . '</p>';
$guides['links']['items'][0]['tags']['a'][] = '[' . $this
->t('External link opens in new window') . '](http://example.com)';
}
else {
$guides['links']['items'][0]['tags']['a'][] = '[' . $this
->t('External link') . '](http://example.com)';
}
if ($this
->getSetting('no_follow') === 'all') {
$guides['links']['items'][0]['description'][] = '<p>' . $this
->t('All links will have the <code>rel="nofollow"</code> attribute applied to it.') . '</p>';
}
elseif ($this
->getSetting('no_follow') === 'external') {
$guides['links']['items'][0]['description'][] = '<p>' . $this
->t('All external links will have the <code>rel="nofollow"</code> attribute applied to it.') . '</p>';
}
elseif ($this
->getSetting('no_follow') === 'internal') {
$guides['links']['items'][0]['description'][] = '<p>' . $this
->t('All internal links will have the <code>rel="nofollow"</code> attribute applied to it.') . '</p>';
}
// Determine the internal whitelist host names.
$hosts = preg_split("/\r\n|\n/", $this
->getSetting('internal_host_whitelist'), -1, PREG_SPLIT_NO_EMPTY);
// Ensure that the site's base url host name is always in this whitelist.
$base_host = \Drupal::request()
->getHost();
$key = array_search($base_host, $hosts);
if ($key === FALSE) {
$hosts[] = $base_host;
}
// Only show this description if there are multiple host names.
if (count($hosts) > 1) {
foreach ($hosts as &$host) {
$host = '<code>' . Html::escape($host) . '</code>';
}
$guides['links']['items'][0]['description'][] = '<p>' . $this
->t('Links with the following URL host names will be treated as "internal" links: !hosts.', [
'!hosts' => implode(', ', $hosts),
]) . '</p>';
}
$base_url = Url::fromRoute('<front>', [], [
'absolute' => TRUE,
])
->toString();
$site_name = \Drupal::config('system.site')
->get('name');
$guides['links']['items'][] = [
'title' => $this
->t('Manual links (using raw HTML)'),
'description' => $this
->t('The above examples are only for links using the Markdown syntax. Manually defined links using raw HTML are always processed "as is". You will be responsible for adding all attributes and values. Suffice it to say, it is always best to avoid using raw HTML and instead use the Markdown syntax whenever possible.'),
'tags' => [
'a' => [
"<a href=\"{$base_url}\">{$site_name}</a>",
"<a href=\"http://example.com\">External link</a>",
"<a href=\"{$base_url}\" target=\"_blank\" rel=\"nofollow\">{$site_name}</a>",
"<a href=\"http://example.com\" target=\"_blank\" rel=\"nofollow\">External link</a>",
],
],
];
}
/**
* {@inheritdoc}
*/
public function defaultSettings() {
return [
'external_new_window' => TRUE,
'internal_host_whitelist' => \Drupal::request()
->getHost(),
'no_follow' => 'external',
];
}
/**
* {@inheritdoc}
*/
public function rendererClass() {
return 'Link';
}
/**
* {@inheritdoc}
*/
public function render(AbstractInline $inline, ElementRendererInterface $html_renderer) {
if (!$inline instanceof Link) {
throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline));
}
$attributes = $inline
->getData('attributes', []);
// Retrieve the URL.
$url = $inline
->getUrl();
$external = $this
->isExternalUrl($url);
$attributes['href'] = $url;
// Make external links open in a new window.
if ($this
->getSetting('external_new_window') && $external) {
$attributes['target'] = '_blank';
}
// Add rel="nofollow".
$no_follow = $this
->getSetting('no_follow');
if ($no_follow === 'all' || $external && $no_follow === 'external' || !$external && $no_follow === 'internal') {
$attributes['rel'] = 'nofollow';
}
if (isset($inline->data['title'])) {
$attributes['title'] = Html::escape($inline->data['title']);
}
return new HtmlElement('a', $attributes, $html_renderer
->renderInlines($inline
->children()));
}
/**
* Determines if a URL is external to current host.
*
* @param string $url
* The URL to verify.
*
* @return bool
* TRUE or FALSE
*/
private function isExternalUrl($url) {
$url_host = parse_url($url, PHP_URL_HOST);
// Only process URLs that actually have a host (e.g. not fragments).
if (!isset($url_host) || empty($url_host)) {
return FALSE;
}
// The environment can be reset, this too would be reset and would re-parse
// the hosts again. Save some time during the same environment instance.
static $hosts;
// Parse the whitelist of internal hosts.
if (!isset($hosts)) {
$hosts = preg_split("/\r\n|\n/", $this
->getSetting('internal_host_whitelist'), -1, PREG_SPLIT_NO_EMPTY);
// Ensure that the site's base url host name is always in this whitelist.
$base_host = parse_url($GLOBALS['base_url'], PHP_URL_HOST);
$key = array_search($base_host, $hosts);
if ($key === FALSE) {
$hosts[] = $base_host;
}
}
// Iterate through the internal host whitelist.
$internal = FALSE;
foreach ($hosts as $host) {
if ($host === $url_host) {
$internal = TRUE;
break;
}
}
return !$internal;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $element, FormStateInterface $formState, MarkdownFilterInterface $filter) {
$element = parent::settingsForm($element, $formState, $filter);
if (!empty($element['#description'])) {
$element['#description'] = '<p>' . $element['#description'] . '</p>';
}
elseif (!isset($element['#description'])) {
$element['#description'] = '';
}
$element['#description'] .= '<p><strong>' . $this
->t('NOTE: These settings ONLY apply to CommonMark Markdown links, if a user manually enters an <code><a></code> tag, then these settings will not be processed on them.') . '</strong></p>';
$element['internal_host_whitelist'] = [
'#type' => 'textarea',
'#title' => $this
->t('Internal Host Whitelist'),
'#description' => $this
->t('Allows additional host names to be treated as "internal" when they would normally be considered as "external". This is useful in cases where a multi-site is using different sub-domains. The current host name, %host, will always be considered "internal" (even if removed from this list). Enter one host name per line. No regular expressions are allowed, just exact host name matches.', [
'%host' => \Drupal::request()
->getHost(),
]),
'#default_value' => $this
->getSetting('internal_host_whitelist'),
];
$element['external_new_window'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Open external links in new windows'),
'#description' => $this
->t('When this setting is enabled, any link that does not contain one of the above internal whitelisted host names will automatically be considered as an "external" link. All external links will then have the <code>target="_blank"</code> attribute and value added to it.'),
'#default_value' => $this
->getSetting('external_new_window'),
];
$element['no_follow'] = [
'#type' => 'select',
'#title' => $this
->t('Add <code>rel="nofollow"</code> to'),
'#description' => $this
->t('The rel="nofollow" attribute and value instructs some search engines that the link should not influence the ranking of the link\'s target in the search engine\'s index.'),
'#default_value' => $this
->getSetting('no_follow'),
'#options' => [
'' => $this
->t('None of the links'),
'all' => $this
->t('All of the links'),
'external' => $this
->t('External links only'),
'internal' => $this
->t('Internal links only'),
],
];
return $element;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
BaseExtension:: |
protected | function | Returns generic default configuration for markdown extension plugins. | |
BaseExtension:: |
public | function | ||
BaseExtension:: |
public | function | ||
BaseExtension:: |
public | function | ||
BaseExtension:: |
public | function |
Retrieves the description of the plugin, if set. Overrides MarkdownInstallablePluginInterface:: |
|
BaseExtension:: |
public | function |
Displays the human-readable label of the plugin. Overrides MarkdownInstallablePluginInterface:: |
|
BaseExtension:: |
public | function |
Retrieves a setting. Overrides MarkdownExtensionInterface:: |
|
BaseExtension:: |
public | function |
Retrieves the current settings. Overrides MarkdownExtensionInterface:: |
|
BaseExtension:: |
public | function |
Retrieves the URL of the plugin, if set. Overrides MarkdownInstallablePluginInterface:: |
|
BaseExtension:: |
public | function |
The current version of the parser. Overrides MarkdownInstallablePluginInterface:: |
|
BaseExtension:: |
public static | function |
Indicates whether the parser is installed. Overrides MarkdownInstallablePluginInterface:: |
|
BaseExtension:: |
public | function |
Indicates whether the extension is being used. Overrides MarkdownExtensionInterface:: |
|
BaseExtension:: |
public | function |
Indicates whether the parser is installed. Overrides MarkdownInstallablePluginInterface:: |
|
BaseExtension:: |
public | function | ||
BaseExtension:: |
public | function | ||
BaseExtension:: |
public | function |
Sets a specific setting. Overrides MarkdownExtensionInterface:: |
|
BaseExtension:: |
public | function |
Provides settings to an extension. Overrides MarkdownExtensionInterface:: |
|
BaseExtension:: |
public static | function |
Retrieves the version of the installed parser. Overrides MarkdownInstallablePluginInterface:: |
|
BaseExtension:: |
public | function |
Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase:: |
|
CommonMarkExtension:: |
public | function |
Retrieves the name of the extension. Overrides CommonMarkExtensionInterface:: |
|
DependencySerializationTrait:: |
protected | property | ||
DependencySerializationTrait:: |
protected | property | ||
DependencySerializationTrait:: |
public | function | 2 | |
DependencySerializationTrait:: |
public | function | 2 | |
LinkRenderer:: |
public | function |
Alters existing guides on how to use the Markdown Parser. Overrides MarkdownGuidelinesAlterInterface:: |
|
LinkRenderer:: |
public | function |
Retrieves the default settings. Overrides BaseExtension:: |
|
LinkRenderer:: |
private | function | Determines if a URL is external to current host. | |
LinkRenderer:: |
public | function | ||
LinkRenderer:: |
public | function |
Retrieves the AST class used to parse the document for the renderer. Overrides CommonMarkRendererInterface:: |
|
LinkRenderer:: |
public | function |
Returns the configuration form elements specific to this plugin. Overrides BaseExtension:: |
|
MarkdownStatesTrait:: |
protected static | function | Retrieves the ancestry of the extension in a form/render array. | |
MarkdownStatesTrait:: |
protected static | function | Retrieves a states selector to use based on the form/render array parents. | |
MessengerTrait:: |
protected | property | The messenger. | 27 |
MessengerTrait:: |
public | function | Gets the messenger. | 27 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
2 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 4 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |