1// Expression helpers 2$.expr[':'].block = function (element) { 3 return $(element).css('display') === 'block' || 4 $(element).css('display') === 'inline-block' || 5 $(element).css('display') === 'table' || 6 $(element).is('li,code'); 7}; 8$.expr[':'].heading = function (element) { 9 return $(element).is('h1,h2,h3,h4,h5,h6'); 10}; 11$.expr[':'].next = function (element) { 12 return !!$(element).next().length; 13}; 14// Functions 15function MoveCaretToElement(e) { 16 const range = document.createRange(); 17 const sel = window.getSelection(); 18 range.selectNodeContents($(e)[0]); 19 range.collapse(true); 20 sel.removeAllRanges(); 21 sel.addRange(range); 22} 23 24function RevertElement(btn) { 25 let input = $(btn).parent().next(); 26 let o = $(input).next(); 27 if (o.is('editable-element-original')) { 28 let editingCode = ($(input).attr('data-format') == 'code'); 29 if (editingCode) DisableCodeEditor(input); 30 $(input).html(o.html()); 31 if (editingCode) EnableCodeEditor(input); 32 SetEditorClean(input); 33 } else { 34 Toast('Revert Failed', 'There was an error attempting to revert the content.', 'bg-danger text-light', 'bi-alert-triangle') 35 } 36 $(input).html(); 37} 38function DeleteElement(btn) { 39 let input = $(btn).parent().next(); 40 $(input).empty(); 41} 42/* 43function DeselectElement() { 44 $('.editor-selected').removeClass('editor-selected'); 45 selectedElement = null; 46} 47function SelectElement(e) { 48 let editor = $(e).parents('[contenteditable][data-editor-style="full"]'); 49 if(editor.length>0) { 50 SetDirty({target: editor}); 51 selectedElement = e; 52 $(selectedElement).addClass('editor-selected'); 53 } 54} 55*/ 56function UniqueID(prefix = '') { 57 let lastUniqueID = prefix + '_' + (Math.random() + 1).toString(36).substring(7); 58 return lastUniqueID; 59} 60function UnixTime() { 61 return Math.floor(Date.now() / 1000); 62} 63 64function Clamp(number, min, max) { 65 return Math.min(Math.max(number, min), max); 66} 67 68function getClassInteger(element, prefix) {
69 let classes = $(element).attr('class').split(' '); 70 for (let i = 0; i < classes.length; i++) { 71 let match = classes[i].match(new RegExp('^' + prefix + '-(\\d+)$')); 72 if (match) { 73 return parseInt(match[1]); 74 } 75 } 76 return null; 77} 78 79function decodeHtml(html) { 80 let doc = new DOMParser().parseFromString(html, "text/html"); 81 return doc.documentElement.textContent; 82} 83 84function EmphasizeAPATitle(html) { 85 if(html.includes('<em>')) return html; 86 if((html.match(/\(/g) || []).length<2 || html.includes('(Ed')) return html; // Only apply to fully formed journal articles 87 let arr = html.split(/([.?])/); 88 html = ''; 89 let yearEnded = 0; 90 let titleStarted = false; 91 let titleEnded = false; 92 for(let item of arr) { 93 if(titleStarted && !titleEnded && item.endsWith('.')) { 94 html += '</em>'; 95 titleEnded = true; 96 } 97 if(yearEnded > 3 && !titleStarted) { 98 html += '<em>'; 99 titleStarted = true; 100 101 if(item.includes('(')) { 102 item = item.replace('(','</em>('); 103 item += '</em>'; 104 titleEnded = true; 105 } 106 } 107 html += item; 108 if(yearEnded>0) yearEnded++; 109 if(item.endsWith(')')) yearEnded = 1; 110 } 111 if(titleStarted && !titleEnded) html += '</em>'; 112 return html; 113} 114function formatHTML(html) { 115 html = html.replace(/ /g, ' '); 116 html = html.replace(/\s\s+/g, ' '); 117 html = html.replace(/[\u00A0-\u9999<>&]/gim, function (i) { 118 return '&#' + i.charCodeAt(0) + ';'; 119 }); 120 //html = html.replace(/data-type="(.*?)"/g, ""); 121 html = html.replace(/data-selected="(.*?)"/g, ""); 122 html = html.replace(/>/g, '>[br]'); 123 html = html.replace(/</g, '[br]<'); 124 html = html.replace(/\[br\]/g, '</div><div>'); 125 html = '<div>' + html + '</div>'; 126 //html = html.replace(/>(.*?)</g, '><div>$1</div><'); 127 html = html.replace(/class="(.*?)"/g, 'class="<span class="code-editor-class">$1</span>"'); 128 html = html.replace(/src="(.*?)"/g, 'src="<span class="code-editor-src">$1</span>"'); 129 html = html.replace(/href="(.*?)"/g, 'href="<span class="code-editor-href">$1</span>"'); 130 html = html.replace(/id="(.*?)"/g, 'id="<span class="code-editor-id">$1</span>"'); 131 html = html.replace(/alt="(.*?)"/g, 'alt="<span class="code-editor-alt">$1</span>"'); 132 indent = -1; 133 let obj = $('<div>' + html + '</div>'); 134 $(obj).find('div').each(function () { 135 let css = { 136 'margin-left': ((indent + 1) * 20) + 'px' 137 }; 138 if ($(this).text().substring(0, 2) == '</') { 139 indent--; 140 } else if ($(this).text().substring(0, 1) == '<' && $(this).text().substring(0, 5) !== '<img ' && $(this).text().substring(0, 7) !== '<input ' && $(this).text().substring(0, 3) !== '<br') { 141 indent++; 142 } 143 $(this).css(css); 144 }); 145 return $(obj).html(); 146} 147function UpdateDataTypes(e) { 148 let elements = e.children(); 149 elements.each(function () { 150 UpdateDataType(this); 151 }); 152 /* 153 let elements = $('main [data-field="text"]').children(); 154 elements.each(function () { 155 UpdateDataType(this); 156 }); 157 elements.on('mouseup', function (event) { 158 SelectElement(this); 159 160 if ($(this).is('img,figure,input')) { 161 SelectElement(this); 162 } else { 163 SelectElement(); 164 } 165 166 });*/ 167} 168 169function ExitEditor() { 170 //window.location.href = window.location.href.split('?')[0]; 171} 172function TFToInt(tf) { 173 if (tf) return 1; 174 return 0; 175} 176 177function FormatHTML(html) { 178 html = html.replace(/ /g, ' '); 179 html = html.replace(/[\u00A0-\u9999<>&]/gim, function (i) { 180 return '&#' + i.charCodeAt(0) + ';'; 181 }); 182 html = '<div>' + html + '</div>'; 183 //html = html.replace(/>(.*?)</g, '><div>$1</div><'); 184 html = html.replace(/class="(.*?)"/g, 'class="<span class="highlight">$1</span>"'); 185 html = html.replace(/src="(.*?)"/g, 'src="<span class="highlight">$1</span>"'); 186 html = html.replace(/href="(.*?)"/g, 'href="<span class="highlight">$1</span>"'); 187 html = html.replace(/id="(.*?)"/g, 'id="<span class="highlight">$1</span>"');
188 html = html.replace(/alt="(.*?)"/g, 'alt="<span class="highlight">$1</span>"'); 189 html = html.replace(/>/g, '</span>>[br]'); 190 html = html.replace(/</g, '[br]<<span class="highlight">'); 191 html = html.replace(/\[br\]/g, '</div><div>'); 192 indent = -1; 193 let obj = $('<div>' + html + '</div>'); 194 $(obj).find('div').each(function () { 195 let css = { 196 'margin-left': ((indent + 1) * 20) + 'px' 197 }; 198 if ($(this).text().substring(0, 2) == '</') { 199 indent--; 200 } else if ($(this).text().substring(0, 1) == '<' && $(this).text().substring(0, 5) !== '<img ' && $(this).text().substring(0, 7) !== '<input ' && $(this).text().substring(0, 3) !== '<br') { 201 indent++; 202 } 203 $(this).css(css); 204 }); 205 return $(obj).html(); 206} 207 208 209function WrapLinksInATags(html) { 210 // Create a DOM parser to handle the HTML 211 const parser = new DOMParser(); 212 const doc = parser.parseFromString(html, "text/html"); 213 214 // Regex to identify potential links (e.g., URLs or domain names) 215 const linkRegex = /\b(?:https?:\/\/|www\.)[^\s<>]+(?:\.[^\s<>]+)*(?:\/[^\s<>]*)?/gi; 216 217 // Recursive function to process child nodes 218 function processNode(node) { 219 // Only process text nodes 220 if (node.nodeType === Node.TEXT_NODE) { 221 const matches = [...node.textContent.matchAll(linkRegex)]; 222 if (matches.length > 0) { 223 const fragment = document.createDocumentFragment(); 224 let lastIndex = 0; 225 226 matches.forEach(match => { 227 const start = match.index; 228 const end = start + match[0].length; 229 230 // Add text before the match 231 if (start > lastIndex) { 232 fragment.appendChild(document.createTextNode(node.textContent.slice(lastIndex, start))); 233 } 234 235 // Create the <a> tag for the match 236 const link = document.createElement("a"); 237 link.href = match[0].startsWith("http") ? match[0] : "http://" + match[0]; 238 link.textContent = match[0]; 239 fragment.appendChild(link); 240 241 lastIndex = end; 242 }); 243 244 // Add remaining text
245 if (lastIndex < node.textContent.length) { 246 fragment.appendChild(document.createTextNode(node.textContent.slice(lastIndex))); 247 } 248 249 // Replace the original text node with the fragment 250 node.replaceWith(fragment); 251 } 252 } else if (node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() !== "a") { 253 // Recursively process child nodes of non-<a> elements 254 Array.from(node.childNodes).forEach(processNode); 255 } 256 } 257 258 // Process all child nodes of the body 259 Array.from(doc.body.childNodes).forEach(processNode); 260 261 // Return the modified HTML as a string 262 return doc.body.innerHTML; 263}
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.