1/** 2 * @file 3 * Detects external links and adds a _blank attribute. 4 */ 5 6(function (Drupal, once) { 7 "use strict"; 8 9 Drupal.behaviors.rddsExternalLinks = { 10 onceName: "external-links", 11 attach: function attach(context) { 12 const [body] = once(this.onceName, document.body); 13 if (body) { 14 this.addExternalAttributes(body); 15 body.querySelectorAll('[data-target]').forEach(link => { 16 link.setAttribute('target', link.getAttribute('data-target')); 17 }); 18 body.querySelectorAll('[data-rel]').forEach(link => { 19 link.setAttribute('rel', link.getAttribute('data-rel')); 20 }); 21 } 22 }, 23 addExternalAttributes: function(context, tag = 'a', attribute = 'href') { 24 // If an href starts with one of this string, skip the blank attribute. 25 const exclusions = ['#', '/', '?', 'mailto:', 'tel:', 'javascript:']; 26 // Skip exludeUris and location.host. 27 context.querySelectorAll( 28 `${tag}[${attribute}]:not([${attribute}*="${location.host}"], ${exclusions.map(uri => `[${attribute}^="${uri}"]`).join(', ')})` 29 ).forEach(link => { 30 link.classList.add("external-link"); 31 link.setAttribute("data-rel", "noopener"); 32 }); 33 context.querySelectorAll(`${tag}[rel*="external"], ${tag}.external-link`).forEach(link => { 34 link.setAttribute("data-target", "_blank"); 35 }); 36 // blank attribute will be added if one of this file ext is found in href. 37 const blankExtensions = ['pdf', 'jpg', 'jpeg', 'png']; 38 context.querySelectorAll(blankExtensions.map(ext => `${tag}[${attribute}$="${ext}"]`).join(', ')).forEach(link => { 39 link.setAttribute("data-target", "_blank"); 40 }); 41 } 42 }; 43})(Drupal, once);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.