1/** 2 * Reference Linker Module 3 * Automatically detects DOI and IZLIK identifiers in page content and converts them to clickable links. 4 * 5 * File: public/js/reference-linker.js 6 */ 7(function ($) { 8 'use strict'; 9 10 function linkReferences() { 11 // default to empty if not set, to prevent breaking 12 const doiBase = 'https://doi.org/'; 13 const izBase = 'https://izlik.org/' 14 //'https://izlik.org/'; 15 16 // Helper: Ensure URL ends with slash 17 const ensureSlash = (url) => url && !url.endsWith('/') ? url + '/' : url; 18 const cleanDoiBase = ensureSlash(doiBase); 19 const cleanIzBase = ensureSlash(izBase); 20 21 // 2. Define Regex Patterns 22 // Matches: doi:10.x, https://doi.org/10.x, or just 10.x 23 // Excludes matches that are already part of an HTML attribute or tag 24 // Added [^.,] at the end to ensure the DOI doesn't end with a dot or comma 25 const doiPattern = /(?:doi\s*:?\s*|https?:\/\/doi\.org\/)?(10\.\d+\/(?:[^\s()\[\]{}<>"]+|\([^\s()<>"]*\)|\[[^\s\[\]<>"]*\]|\{[^\s\{\}<>"]*\})+(?<![.,;:]))/gi; 26 27 // Matches: iz:JA47XA73TL or http://host.docker.internal:8080/JA47XA73TL or izlik.org/JA47XA73TL 28 const izPattern = /(?:iz\s*:?\s*|http:\/\/host\.docker\.internal:8080\/|https:\/\/izlik\.org\/)?([A-Za-z]{2}[0-9]{2}[A-Za-z]{2}[0-9]{2}[A-Za-z]{2})/gi; 29 30 // 3. Define Selector 31 // We target citation text AND main article bodies/abstracts 32 const targetSelector = '.kt-portlet__body p, .article-abstract p, .article-body, .cite-table td, .abstract-text, .citation-text'; 33 34 $(targetSelector).each(function () { 35 const $el = $(this); 36 let html = $el.html(); 37 38 // Skip if the element contains LaTeX delimiters to avoid breaking rendering 39 if (html.includes('$') || html.includes('\\(') || html.includes('\\[') || $el.hasClass('latex')) { 40 return; 41 } 42 43 const originalHtml = html; 44 45 // --- Process DOIs --- 46 html = html.replace(doiPattern, function (match, cleanDoi) { 47 // Safety: Match must resemble a DOI structure 48 if (!cleanDoi.startsWith('10.')) return match; 49 50 // Safety: Do not replace if inside an HTML tag (e.g. <a href="...">) 51 if (match.includes('<a') || match.includes('href=') || match.includes('src=')) return match; 52 53 const link = cleanDoiBase + cleanDoi; 54 return `<a href="${link}" target="_blank" rel="noopener noreferrer" class="reference-link doi-link">${match}</a>`; 55 }); 56 57 html = html.replace(izPattern, function (match, izId) { 58 // Safety: Do not replace if inside an HTML tag 59 if (match.includes('<a') || match.includes('href=') || match.includes('src=')) return match; 60 61 // Strict format check: 2+ uppercase letters followed by 6+ alphanumeric characters 62 if (!/^[A-Z]{2,}[A-Z0-9]{6,}$/.test(izId)) return match; 63 64 const link = cleanIzBase + izId; 65 return `<a href="${link}" target="_blank" rel="noopener noreferrer" class="reference-link iz-link">${match}</a>`; 66 }); 67 68 // Only update DOM if we actually made changes 69 if (html !== originalHtml) { 70 $el.html(html); 71 } 72 }); 73 } 74 75 $(document).ready(function () { 76 linkReferences(); 77 }); 78 79})(jQuery);
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.