1globalThis.siteUrl = (globalThis.isLocal &&false ? "http://localhost:3000/" : "https://api.aidark.net/"); 2 3async function IsUrlExists(url) { 4 try{ 5 return (await fetch(url)).ok; 6 }catch(e){ 7 return false; 8 } 9 /* 10 return new Promise(resolve => { 11 const obj = Object.assign(document.createElement('object'), { 12 data: url, 13 onload: () => { 14 document.body.removeChild(obj); 15 resolve(true); 16 }, 17 onerror: () => { 18 document.body.removeChild(obj); 19 resolve(false); 20 } 21 }); 22 document.body.appendChild(obj); 23 }); 24 */ 25} 26function promiseRace(promises, timeout = 5000) { 27 return new Promise((resolve, reject) => { 28 let failedCount = 0; 29 const forceTimeout = setTimeout(() => { 30 reject(new Error('Promise race timed out')); 31 }, timeout); 32 33 promises.forEach((promise) => { 34 promise 35 .then((result) => { 36 clearTimeout(forceTimeout); 37 resolve(result); // Resolve with the first successful result 38 }) 39 .catch(() => { 40 failedCount++; 41 if (failedCount === promises.length) { 42 clearTimeout(forceTimeout); 43 reject(new Error('All promises failed')); // Reject with an error if all promises fail 44 } 45 }); 46 }); 47 }); 48} 49 50if (!navigator.serviceWorker && !window.location.hostname.startsWith('192')) { 51 alert("Error: Service worker is not supported"); 52 } else { 53 (async () => { 54 try { 55 const registration = await navigator.serviceWorker.getRegistration(); 56 if (registration) { 57 await registration.unregister(); 58 } 59 await navigator.serviceWorker.register('service-worker.mjs'); 60 } catch (error) { 61 console.error("Service worker registration failed:", error); 62 } 63 })(); 64 } 65 66/** 67 * Parses files from a message. 68 * @param {string} message - The message to parse. 69 * @returns {Promise<{messageWithoutCodeBlocks: string, files: EditorFile[]}>} - The parsed message and files. 70 */ 71async function parseFilesFromMessage(message) { 72 /** @type {EditorFile[]} */ 73 let files = []; 74 let regexHtml = /(?:^|\n)(?:(?:[#*][^\r\n]*?([\w\-_]+\.\w+)[^\r\n]*?\n)?\n?```(\w+)\n?(.*?)(?:\n```|$(?!\n)))|(?:<
74html.*?>.*?(?:<\/html>|$(?!\n)))/gs; 75 let match; 76 let messageWithoutCodeBlocks = message; 77 let correctFormat = false; 78 function getFileName(lang2) { 79 var lang = lang2.trim().toLowerCase(); 80 return lang === 'css' ? "styles.css" : 81 lang === 'javascript' ? "script.js" : 82 lang === 'html' || lang === '' ? "index.html" : 83 lang === 'python' ? "script.py" : lang2; 84 } 85 while ((match = regexHtml.exec(message)) !== null) { 86 let fileName; 87 let content = ''; 88 if (match[0].startsWith('<html') && !correctFormat) { 89 fileName = "index.html"; 90 content = match[0]; 91 } 92 else if (match[1]) { 93 fileName = getFileName(match[1].trim()); 94 content = match[3]; 95 //if(!correctFormat) files = []; 96 correctFormat=true; 97 } 98 else if(!correctFormat) { 99 fileName = getFileName(match[2]); 100 content = match[3]; 101 } 102 else 103 continue; 104 messageWithoutCodeBlocks = messageWithoutCodeBlocks.replace(match[0],'\n');// "# "+fileName 105 if (files.find(a => a.name == fileName)?.content.length > content.length) 106 continue; 107 files = files.filter(a => a.name != fileName); 108 files.push({ name: fileName, content,langauge:match[2]||"html" ,hidden:false}); 109 110 111 112 } 113 114 return { messageWithoutCodeBlocks, files }; 115} 116function extractMeaningfulText(file, minLength = 4, maxLength = 1000, encoding = 'utf-8') { 117 return new Promise((resolve, reject) => { 118 const reader = new FileReader(); 119 reader.onload = (event) => { 120 const uint8Array = new Uint8Array(event.target.result.slice(0, maxLength)); 121 let meaningfulText = ''; 122 let currentText = ''; 123 let consecutiveTextChars = 0; 124 125 for (const byte of uint8Array) { 126 if (byte >= 32 && byte <= 126) { 127 currentText += String.fromCharCode(byte); 128 consecutiveTextChars++; 129 } else { 130 if (consecutiveTextChars >= minLength) { 131 meaningfulText += currentText.trim() + ' '; 132 if (meaningfulText.length >= maxLength) { 133 break; 134 } 135 } 136 currentText = ''; 137 consecutiveTextChars = 0; 138 } 139 } 140 141 if (consecutiveTextChars >= minLength && meaningfulText.length < maxLength) { 142 meaningfulText += currentText.trim(); 143 } 144 145 resolve(meaningfulText.slice(0, maxLength).trim()); 146 }; 147 148 reader.onerror = reject; 149 reader.readAsArrayBuffer(file); 150 }); 151} 152 153 154 155function InitVue(obj, args = {}) { 156 157 let defaultParams = structuredClone(obj.params); 158 let updating = false; 159 const updateParamsFromHash = (event) => { 160 161 const hashParams = new URLSearchParams(window.location.hash.slice(1)); 162 for (let key in obj.params) { 163 if (!key.startsWith("_")) 164 if (hashParams.has(key)) 165 try { obj.params[key] = JSON.parse(hashParams.get(key)); } catch (e) { obj.params[key] = hashParams.get(key); } 166 else 167 obj.params[key] = defaultParams[key]; 168 } 169 }; 170 updateParamsFromHash(); 171 window.addEventListener('hashchange', () => { 172 //if (!updating)location.reload(); 173 updating = false; 174 }); 175 return { 176 data: () => { 177 //obj = shallowClone(obj) 178 for (let key in obj) { 179 if (typeof obj[key] === 'function') { 180 delete obj[key]; 181 } 182 } 183 obj.data = obj; 184 return obj; 185 }, 186 ...args 187 , 188 mounted() { 189 Object.assign(obj, this); 190 args.mounted?.call(obj); 191 }, 192 methods: Object.keys(obj).reduce((methods, key) => { 193 if (typeof obj[key] === 'function') { 194 methods[key] = obj[key]; 195 } 196 return methods; 197 }, {}), 198 watch: Object.keys(obj.params || {}).reduce((watchers, key) => { 199 if (!key.startsWith("_")) 200 watchers["params." + key] = function (newValue) { 201 updating = true; 202 const hashParams = new URLSearchParams(window.location.hash.slice(1)); 203 hashParams.set(key, JSON.stringify(newValue)); 204 window.location.hash = hashParams.toString(); 205 }; 206 return watchers; 207 }, args.watch || {}) 208 }; 209} 210 211document.querySelectorAll('[data-template]').forEach(dropdown => { 212 const template = document.getElementById(dropdown.getAttribute('data-template')); 213 if (template) dropdown.appendChild(template.content.cloneNode(true)); 214}); 215 216Array.prototype=Array.prototype 217Array.prototype.last = function() { 218 return this[this.length - 1]; 219}; 220async function resolveSettingsPromises(obj) { 221 if (typeof obj === 'function' && obj.constructor.name === 'AsyncFunction') { 222 return await obj(); 223 } 224 if (obj && typeof obj.then === 'function') return await obj; 225 if (Array.isArray(obj)) return await Promise.all(obj.map(resolveSettingsPromises)); 226 if (typeof obj === 'object' && obj !== null) { 227 const entries = await Promise.all( 228 Object.entries(obj).map(async ([k, v]) => [k, await resolveSettingsPromises(v)]) 229 ); 230 return Object.fromEntries(entries); 231 } 232 return obj; 233 } 234 235async function getDatabase() { 236 237 let db = await Promise.all(["./examples/database.js", "./examples2/database.js","./examples/3d/database.js", "./examples2/3d/database.js"].map(async dbPath => (await import(dbPath)).database)); 238 return chat.contact.db = Object.assign({}, ...db); 239} 240 241async function getMostUsedKeywords() { 242 const data = await getDatabase(); 243 244 const groupedKeywords = {}; 245
246 Object.values(data).forEach(item => { 247 const category = item.category; 248 if (!groupedKeywords[category]) { 249 groupedKeywords[category] = {}; 250 } 251 item.keywords.forEach(keyword => { 252 groupedKeywords[category][keyword] = (groupedKeywords[category][keyword] || 0) + 1; 253 }); 254 }); 255 for (const category in groupedKeywords) { 256 groupedKeywords[category] = Object.keys(groupedKeywords[category]).sort((a, b) => groupedKeywords[category][b] - groupedKeywords[category][a]); 257 } 258 return groupedKeywords; 259} 260 261 262 263function jaccardSimilarity(a, b) { 264 const setA = new Set(a.toLowerCase().split(/\s+/)); 265 const setB = new Set(b.toLowerCase().split(/\s+/)); 266 const intersection = [...setA].filter(x => setB.has(x)).length; 267 const union = new Set([...setA, ...setB]).size; 268 return intersection / union; 269}; 270function deepMerge(target, source) { 271 function isObject(item) { 272 return (item && typeof item === 'object' && !Array.isArray(item)); 273 } 274 let output = target; 275 for (let key in source) { 276 if (isObject(source[key])) { 277 if (!(key in target)) 278 Object.assign(output, { [key]: source[key] }); 279 else 280 output[key] = deepMerge(target[key], source[key]); 281 } else { 282 try { 283 Object.assign(output, { [key]: source[key] }); 284 } catch (e) { console.log(e) } 285 } 286 } 287 return output; 288} 289const languageMap = { 290 'js': 'javascript', 291 'html': 'html', 292 'css': 'css', 293 'py': 'python', 294}; 295function shuffleArray(array) { 296 for (let i = array.length - 1; i > 0; i--) { 297 const j = Math.floor(Math.random() * (i + 1)); 298 [array[i], array[j]] = [array[j], array[i]]; 299 } 300 return array; 301} 302 303function extractJSONStructures(str) { 304 const jsonStructures = []; 305 let braceCount = 0; 306 let bracketCount = 0; 307 let jsonStart = -1; 308 309 for (let i = 0; i < str.length; i++) { 310 if (str[i] === '{') { 311 if (braceCount === 0 && bracketCount === 0) jsonStart = i; // Start of a new JSON object 312 braceCount++; 313 } else if (str[i] === '}') { 314 braceCount--; 315 if (braceCount === 0 && jsonStart !== -1 && bracketCount === 0) { 316 // Extract the JSON object 317 const jsonObject = str.slice(jsonStart, i + 1);
318 jsonStructures.push(jsonObject); 319 jsonStart = -1; // Reset the start index 320 } 321 } else if (str[i] === '[') { 322 if (braceCount === 0 && bracketCount === 0) jsonStart = i; // Start of a new JSON array 323 bracketCount++; 324 } else if (str[i] === ']') { 325 bracketCount--; 326 if (bracketCount === 0 && jsonStart !== -1 && braceCount === 0) { 327 // Extract the JSON array 328 const jsonArray = str.slice(jsonStart, i + 1); 329 jsonStructures.push(jsonArray); 330 jsonStart = -1; // Reset the start index 331 } 332 } 333 } 334 335 return jsonStructures; 336} 337async function fetchP(url, sets ) { 338 console.log("fetching", url, sets); 339 return fetch(siteUrl + "/proxy?url=" + encodeURIComponent(url) + "&sets=" + encodeURIComponent(JSON.stringify(sets || { method: "GET", headers: { 'Content-Type': 'text/html' } }))); 340} 341 342function logEvent(name, extra = {}) { 343 let query = { 344 add: 1, unique: localStorage.getItem(name) ? 0 : 1, name: 'aidark/' + name, url: location.href, extra 345 }; 346 localStorage.setItem(name, '1'); 347 fetch(`${siteUrl}/count?query=${encodeURIComponent(JSON.stringify(query))}`); 348} 349 350 351logEvent('start');
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.