1function toast(message, code = 200) { 2 3 classToast = "toast-success"; 4 if (code != 200) classToast = "toast-error"; 5 6 7 const toastInstance = Toastify({ 8 text: message, 9 duration: 5000, 10 close: false, 11 gravity: "top", // `top` or `bottom` 12 position: "left", // `left`, `center` or `right` 13 stopOnFocus: true, // Prevents dismissing of toast on hover 14 className: classToast, 15 onClick: function () { toastInstance.hideToast() } // Callback after click 16 }); 17 18 toastInstance.showToast(); 19} 20 21function reinitMasonry() { 22 const masonryContainer = document.querySelector('[data-masonry]'); 23 if (masonryContainer && typeof Masonry !== 'undefined') { 24 new Masonry(masonryContainer, { 25 itemSelector: '[data-masonry] > div', 26 percentPosition: true 27 }); 28 } 29} 30 31function deleteMetaTags() { 32 33 const head = document.head; 34 const nodes = Array.from(head.childNodes); 35 let inside = false; 36 37 // Remove existing meta tags between comments 38 for (let i = nodes.length - 1; i >= 0; i--) { 39 const node = nodes[i]; 40 if (node.nodeType === Node.COMMENT_NODE) { 41 if (node.data.trim() === 'Meta-End') { 42 inside = true; 43 continue; 44 } 45 if (node.data.trim() === 'Meta-Start') { 46 inside = false;
47 continue; 48 } 49 } 50 51 if (inside 52 && node.nodeType === Node.ELEMENT_NODE 53 // && node.tagName === 'META' 54 ) { 55 head.removeChild(node); 56 } 57 } 58 59 // Check if Meta-Start comment exists 60 const metaStartComment = Array.from(head.childNodes).find(node => 61 node.nodeType === Node.COMMENT_NODE && node.data.trim() === 'Meta-Start' 62 ); 63 64 return !!metaStartComment; 65} 66 67function updateMetaTags2(decodedHtml) { 68 69 // Create temporary div to parse escaped HTML 70 const tempDiv = document.createElement('div'); 71 tempDiv.innerHTML = decodedHtml; 72 73 // Extract meta tags from parsed HTML 74 const newMetaTags = Array.from(tempDiv.children); 75 76 // Delete existing meta tags 77 const metaStartExists = deleteMetaTags(); 78 79 if (decodedHtml != "") { 80 if (!metaStartExists) { 81 console.error('Meta-Start comment not found'); 82 tempDiv.remove(); 83 return; 84 } 85 86 // Find Meta-Start comment to insert after 87 const head = document.head; 88 const metaStartComment = Array.from(head.childNodes).find(node => 89 node.nodeType === Node.COMMENT_NODE && node.data.trim() === 'Meta-Start' 90 ); 91 92 // Insert new meta tags 93 newMetaTags.slice().reverse().forEach(meta => { 94 if (meta.tagName.toLowerCase() === "script") { 95 // re-create script so it executes 96 const script = document.createElement("script"); 97 if (meta.src) { 98 script.src = meta.src; 99 } else { 100 script.textContent = meta.textContent; 101 } 102 metaStartComment.after(script); 103 } else { 104 // for <meta> or others, clone normally 105 metaStartComment.after(meta.cloneNode(true)); 106 } 107 }); 108 109 } 110 111 112 // Clean up 113 tempDiv.remove(); 114} 115 116 117function updateMetaTags(base64Encoded) { 118 119 var decodedHtml = atob(base64Encoded); 120 121 // Create temporary div to parse escaped HTML 122 const tempDiv = document.createElement('div'); 123 tempDiv.innerHTML = decodedHtml; 124 125 // Extract meta tags from parsed HTML 126 const newMetaTags = Array.from(tempDiv.children); 127 128 // Delete existing meta tags 129 const metaStartExists = deleteMetaTags(); 130 131 if (!metaStartExists) { 132 console.error('Meta-Start comment not found'); 133 tempDiv.remove(); 134 return; 135 } 136 137 // Find Meta-Start comment to insert after 138 const head = document.head; 139 const metaStartComment = Array.from(head.childNodes).find(node => 140 node.nodeType === Node.COMMENT_NODE && node.data.trim() === 'Meta-Start' 141 ); 142 143 // Insert new meta tags 144 newMetaTags.slice().reverse().forEach(meta => { 145 if (meta.tagName.toLowerCase() === "script") { 146 // re-create script so it executes 147 const script = document.createElement("script"); 148 if (meta.src) { 149 script.src = meta.src; 150 } else { 151 script.textContent = meta.textContent; 152 } 153 metaStartComment.after(script); 154 } else { 155 // for <meta> or others, clone normally 156 metaStartComment.after(meta.cloneNode(true)); 157 } 158 }); 159 160 // Clean up 161 tempDiv.remove(); 162} 163 164function isOtpMobileApp() { 165 return navigator.userAgent.includes("OTP"); 166} 167 168// Core content loader 169function content(uri, target = 'content', callback = null) { 170 loading(target); 171 closeAllSlidePages(); 172 173 // if (target == 'content') { 174 // window.history.pushState({}, '', uri); 175 // console.log(window.location.href); 176 // getMeta(window.location.href); 177 // } 178 if(!navigator.userAgent.includes('OTP')) { 179 window.history.pushState({}, '', uri); 180 } 181 console.log(window.location.href); 182 getMeta(window.location.href); 183 184 window.api.get(uri, {}, { 185 onSuccess: (response) => { 186 $(`#${target}`).html(response); 187 188 if (typeof callback === "function") { 189 callback(); // call after success 190 } 191 }, 192 onError: (response) => { 193 if (typeof callback === "function") { 194 callback(); // also call after error if needed 195 } 196 } 197 }); 198} 199 200 201function getMeta(url) { 202 203 var form = new FormData(); 204 form.append("url", url); 205 206 var settings = { 207 "url": "/api/meta", 208 "method": "POST", 209 "timeout": 0, 210 "processData": false, 211 "mimeType": "multipart/form-data", 212 "contentType": false, 213 "data": form 214 }; 215 216 $.ajax(settings).done(function (response) { 217 response = JSON.parse(response); 218 219 if (response['error']['code'] == 200) { 220 221 meta = response['data']['meta']; 222 223 title = response['data']['title']; 224 225 226 document.title = title; 227 updateMetaTags2(meta); 228 } 229 }); 230 231} 232 233 234function loading(content = 'content') { 235 $(`#${content}`).html( 236 '<div class="h-100 w-100 d-flex justify-content-center align-items-center py-5"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>' 237 ); 238} 239 240// Close all slide pages and re-enable scroll 241function closeAllSlidePages() { 242 $('.slide-page').removeClass('show'); 243 $('body').css('overflow', ''); 244} 245 246 247function salin(text) { 248 navigator.clipboard.writeText(text).then(function () { 249 toast(`${text} berhasil di salin`, 200); 250 }, function (err) { 251 toast(`${text} gagal di salin`, 400); 252 }); 253} 254 255 256 257// // Example usage: 258// const metaTags = getMetaBetweenComments();
259// metaTags.forEach(tag => console.log(tag.outerHTML))
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.