diff --git a/config/install/extlink.settings.yml b/config/install/extlink.settings.yml index b53f607..3f4ee30 100644 --- a/config/install/extlink.settings.yml +++ b/config/install/extlink.settings.yml @@ -1,5 +1,6 @@ extlink_use_external_js_file: false extlink_target: false +extlink_target_append_new_window: false extlink_target_no_override: false extlink_nofollow: false extlink_follow_no_override: false diff --git a/config/schema/extlink.schema.yml b/config/schema/extlink.schema.yml index d073420..0662d85 100644 --- a/config/schema/extlink.schema.yml +++ b/config/schema/extlink.schema.yml @@ -10,6 +10,9 @@ extlink.settings: extlink_target: type: boolean label: 'Open external links in a new tab' + extlink_target_append_new_window: + type: boolean + label: 'Add "(New window)" in the title of links that should open in new window' extlink_target_no_override: type: boolean label: 'Do not override target="*" if set' diff --git a/extlink.install b/extlink.install index 1d1c385..99a8b84 100644 --- a/extlink.install +++ b/extlink.install @@ -23,3 +23,13 @@ function extlink_update_8101() { $config->set('extlink_mailto_label', '(link sends email)'); $config->save(TRUE); } + +/** + * Add extlink_target_append_new_window to the default configuration. + */ +function extlink_update_8102() { + $config_factory = \Drupal::configFactory(); + $config = $config_factory->getEditable('extlink.settings'); + $config->set('extlink_target_append_new_window', FALSE); + $config->save(TRUE); +} diff --git a/extlink.js b/extlink.js index b2d6ef8..f8da4c0 100644 --- a/extlink.js +++ b/extlink.js @@ -19,7 +19,7 @@ if (drupalSettings.data.extlink.extIconPlacement && drupalSettings.data.extlink.extIconPlacement != '0') { extIconPlacement = drupalSettings.data.extlink.extIconPlacement; } - + // Strip the host name down, removing ports, subdomains, or www. var pattern = /^(([^\/:]+?\.)*)([^\.:]{1,})((\.[a-z0-9]{1,253})*)(:[0-9]{1,5})?$/; var host = window.location.host.replace(pattern, '$2$3$6'); @@ -244,6 +244,21 @@ $link[icon_placement]('' + drupalSettings.data.extlink.extLabel + ''); } } + + // Add to the title attr of ext link a 'New window' value for screen + // reader. + if (drupalSettings.data.extlink.extTargetAppendNewWindow && $link.attr('target') === '_blank') { + if ($link.attr('title') !== undefined) { + var old_title = $link.attr('title'); + // Check if the attribute title has already the 'New window' value. + if (old_title.indexOf(Drupal.t('New window')) === -1) { + $link.attr('title', old_title + ' ' + Drupal.t('(New window)')); + } + } + else { + $link.attr('title', Drupal.t('(New window)')); + } + } } }; diff --git a/extlink.module b/extlink.module index 14e217c..cc9f95e 100644 --- a/extlink.module +++ b/extlink.module @@ -84,27 +84,28 @@ function _extlink_get_settings_from_config(Config $config) { $fa_mailto_classes = array_map($callback, explode(' ', $fa_mailto_classes)); return [ - 'extTarget' => ((isset($settings['extlink_target'])) ? $settings['extlink_target'] : FALSE), - 'extTargetNoOverride' => ((isset($settings['extlink_target_no_override'])) ? $settings['extlink_target_no_override'] : FALSE), - 'extNofollow' => ((isset($settings['extlink_nofollow'])) ? $settings['extlink_nofollow'] : FALSE), - 'extFollowNoOverride' => ((isset($settings['extlink_follow_no_override'])) ? $settings['extlink_follow_no_override'] : FALSE), - 'extClass' => ((isset($settings['extlink_class'])) ? $settings['extlink_class'] : 'ext'), - 'extLabel' => ((isset($settings['extlink_label'])) ? Html::escape($settings['extlink_label']) : t('(link is external)')), - 'extImgClass' => ((isset($settings['extlink_img_class'])) ? $settings['extlink_img_class'] : FALSE), - 'extSubdomains' => ((isset($settings['extlink_subdomains'])) ? $settings['extlink_subdomains'] : TRUE), - 'extExclude' => ((isset($settings['extlink_exclude'])) ? $settings['extlink_exclude'] : ''), - 'extInclude' => ((isset($settings['extlink_include'])) ? $settings['extlink_include'] : ''), - 'extCssExclude' => ((isset($settings['extlink_css_exclude'])) ? $settings['extlink_css_exclude'] : ''), - 'extCssExplicit' => ((isset($settings['extlink_css_explicit'])) ? $settings['extlink_css_explicit'] : ''), - 'extAlert' => ((isset($settings['extlink_alert'])) ? $settings['extlink_alert'] : FALSE), - 'extAlertText' => ((isset($settings['extlink_alert_text'])) ? Html::escape($settings['extlink_alert_text']) : t('This link will take you to an external web site. We are not responsible for their content.')), - 'mailtoClass' => ((isset($settings['extlink_mailto_class'])) ? $settings['extlink_mailto_class'] : 'mailto'), - 'mailtoLabel' => ((isset($settings['extlink_mailto_label'])) ? Html::escape($settings['extlink_mailto_label']) : t('(link sends email)')), - 'extUseFontAwesome' => ((isset($settings['extlink_use_font_awesome'])) ? $settings['extlink_use_font_awesome'] : FALSE), - 'extIconPlacement' => ((!empty($settings['extlink_icon_placement'])) ? $settings['extlink_icon_placement'] : 'append'), - 'extFaLinkClasses' => implode(' ', $fa_link_classes), - 'extFaMailtoClasses' => implode(' ', $fa_mailto_classes), - 'whitelistedDomains' => $config->get('whitelisted_domains'), + 'extTarget' => ((isset($settings['extlink_target'])) ? $settings['extlink_target'] : FALSE), + 'extTargetAppendNewWindow' => ((isset($settings['extlink_target_append_new_window'])) ? $settings['extlink_target_append_new_window'] : FALSE), + 'extTargetNoOverride' => ((isset($settings['extlink_target_no_override'])) ? $settings['extlink_target_no_override'] : FALSE), + 'extNofollow' => ((isset($settings['extlink_nofollow'])) ? $settings['extlink_nofollow'] : FALSE), + 'extFollowNoOverride' => ((isset($settings['extlink_follow_no_override'])) ? $settings['extlink_follow_no_override'] : FALSE), + 'extClass' => ((isset($settings['extlink_class'])) ? $settings['extlink_class'] : 'ext'), + 'extLabel' => ((isset($settings['extlink_label'])) ? Html::escape($settings['extlink_label']) : t('(link is external)')), + 'extImgClass' => ((isset($settings['extlink_img_class'])) ? $settings['extlink_img_class'] : FALSE), + 'extSubdomains' => ((isset($settings['extlink_subdomains'])) ? $settings['extlink_subdomains'] : TRUE), + 'extExclude' => ((isset($settings['extlink_exclude'])) ? $settings['extlink_exclude'] : ''), + 'extInclude' => ((isset($settings['extlink_include'])) ? $settings['extlink_include'] : ''), + 'extCssExclude' => ((isset($settings['extlink_css_exclude'])) ? $settings['extlink_css_exclude'] : ''), + 'extCssExplicit' => ((isset($settings['extlink_css_explicit'])) ? $settings['extlink_css_explicit'] : ''), + 'extAlert' => ((isset($settings['extlink_alert'])) ? $settings['extlink_alert'] : FALSE), + 'extAlertText' => ((isset($settings['extlink_alert_text'])) ? Html::escape($settings['extlink_alert_text']) : t('This link will take you to an external web site. We are not responsible for their content.')), + 'mailtoClass' => ((isset($settings['extlink_mailto_class'])) ? $settings['extlink_mailto_class'] : 'mailto'), + 'mailtoLabel' => ((isset($settings['extlink_mailto_label'])) ? Html::escape($settings['extlink_mailto_label']) : t('(link sends email)')), + 'extUseFontAwesome' => ((isset($settings['extlink_use_font_awesome'])) ? $settings['extlink_use_font_awesome'] : FALSE), + 'extIconPlacement' => ((!empty($settings['extlink_icon_placement'])) ? $settings['extlink_icon_placement'] : 'append'), + 'extFaLinkClasses' => implode(' ', $fa_link_classes), + 'extFaMailtoClasses' => implode(' ', $fa_mailto_classes), + 'whitelistedDomains' => $config->get('whitelisted_domains'), ]; } diff --git a/src/Form/ExtlinkAdminSettingsForm.php b/src/Form/ExtlinkAdminSettingsForm.php index 3efe55e..c6d1fcf 100644 --- a/src/Form/ExtlinkAdminSettingsForm.php +++ b/src/Form/ExtlinkAdminSettingsForm.php @@ -143,6 +143,17 @@ class ExtlinkAdminSettingsForm extends ConfigFormBase { '#description' => $this->t('A link will open in a new window or tab (depending on which web browser is used and how it is configured).'), ]; + $form['extlink_target_append_new_window'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Add "(New window)" in the title of links that should open in new window.'), + '#default_value' => $config->get('extlink_target_append_new_window'), + '#states' => [ + 'visible' => [ + ':input[name="extlink_target"]' => ['checked' => TRUE], + ], + ], + ]; + $form['extlink_target_no_override'] = [ '#type' => 'checkbox', '#title' => $this->t('Do not alter links with a default target value'), diff --git a/tests/src/FunctionalJavascript/ExtlinkTestTarget.php b/tests/src/FunctionalJavascript/ExtlinkTestTarget.php index c9b5755..1465305 100644 --- a/tests/src/FunctionalJavascript/ExtlinkTestTarget.php +++ b/tests/src/FunctionalJavascript/ExtlinkTestTarget.php @@ -90,4 +90,60 @@ class ExtlinkTestTarget extends ExtlinkTestBase { $this->assertTrue($link->getAttribute('rel') === 'noopener noreferrer' || $link->getAttribute('rel') === 'noreferrer noopener', 'ExtLink rel attribute is not "noopener noreferrer".'); } + /** + * Checks to see if extlink adds (New window) in the title. + */ + public function testExtlinkTargetNewWindow() { + // Target Enabled. + $this->config('extlink.settings')->set('extlink_target', TRUE)->save(); + $this->config('extlink.settings')->set('extlink_target_append_new_window', TRUE)->save(); + + // Login. + $this->drupalLogin($this->adminUser); + + // Create a node with an external link. + $settings = [ + 'type' => 'page', + 'title' => 'test page', + 'body' => [ + [ + 'value' => '

Google!Google with title!

', + 'format' => $this->emptyFormat->id(), + ], + ], + ]; + $node = $this->drupalCreateNode($settings); + + // Get the page. + $this->drupalGet($node->toUrl()); + $page = $this->getSession()->getPage(); + $this->createScreenshot(\Drupal::root() . '/sites/default/files/simpletest/' . __FUNCTION__ . '.png'); + $this->assertTrue($page->hasLink('Google!')); + $this->assertTrue($page->hasLink('Google with title!')); + + // Test that the page has the external link svg. + $externalLink = $page->find('xpath', self::EXTLINK_EXT_XPATH); + $this->assertTrue(!is_null($externalLink) && $externalLink->isVisible(), 'External Link does not exist.'); + $link = $page->findLink('Google!'); + + // Link should have target attribute. + $this->assertTrue($link->getAttribute('target') === '_blank', 'ExtLink target attribute is not "_blank".'); + + // Link should have rel attribute 'noopener noreferrer'. + $this->assertTrue($link->getAttribute('rel') === 'noopener noreferrer' || $link->getAttribute('rel') === 'noreferrer noopener', 'ExtLink rel attribute is not "noopener noreferrer".'); + + // Link should have a title '(New window)'. + $this->assertTrue($link->getAttribute('title') === '(New window)', 'ExtLink title attribute is "(New window)".'); + + $link = $page->findLink('Google with title!'); + // Link should have target attribute. + $this->assertTrue($link->getAttribute('target') === '_blank', 'ExtLink target attribute is not "_blank".'); + + // Link should have rel attribute 'noopener noreferrer'. + $this->assertTrue($link->getAttribute('rel') === 'noopener noreferrer' || $link->getAttribute('rel') === 'noreferrer noopener', 'ExtLink rel attribute is not "noopener noreferrer".'); + + // Link should have a title '(New window)'. + $this->assertTrue($link->getAttribute('title') === 'My link title (New window)', 'ExtLink title attribute is "(New window)".'); + } + }