1(async () => { 2 const URL = "https://www.data.jma.go.jp/vois/data/report/activity_info/314.html"; 3 4 const levelEl = document.getElementById("volcano-level"); 5 const noteEl = document.getElementById("volcano-note"); 6 const updatedEl = document.getElementById("volcano-updated"); 7 const boxEl = document.getElementById("volcano-box"); 8 if (!levelEl || !boxEl) return; 9 10 function detectLang() { 11 const urlLang = new URLSearchParams(window.location.search).get('gtlang'); 12 const htmlLang = document.documentElement.getAttribute('lang') || ''; 13 const raw = (urlLang || htmlLang || 'ja').toLowerCase(); 14 15 if (raw.startsWith('ja')) return 'ja'; 16 return 'en'; 17 } 18 19 const LANG = detectLang(); 20 21 const I18N = { 22 ja: { 23 levelLabel: 'å´ç«è¦æã¬ãã«', 24 noteLabel: 'è¦æäºé ', 25 failed: 'åå¾å¤±æ', 26 notAvailable: 'åå¾ã§ãã¾ããã§ãã', 27 noNote: '', 28 updatedFormat: (d) => { 29 const y = d.getFullYear(); 30 const mo = String(d.getMonth() + 1).padStart(2, "0"); 31 const da = String(d.getDate()).padStart(2, "0"); 32 const hh = String(d.getHours()).padStart(2, "0"); 33 const mm = String(d.getMinutes()).padStart(2, "0"); 34 return `${y}/${mo}/${da} ${hh}:${mm}`; 35 }, 36 noteMap: { 37 'ç¹ã«ãªãã': 'ç¹ã«ãªãã' 38 } 39 }, 40 en: { 41 levelLabel: 'Volcanic Alert Level', 42 noteLabel: 'Advisory', 43 failed: 'Failed to load', 44 notAvailable: 'Unavailable', 45 noNote: '', 46 updatedFormat: (d) => { 47 const y = d.getFullYear(); 48 const mo = String(d.getMonth() + 1).padStart(2, "0"); 49 const da = String(d.getDate()).padStart(2, "0"); 50 const hh = String(d.getHours()).padStart(2, "0"); 51 const mm = String(d.getMinutes()).padStart(2, "0"); 52 return `${y}-${mo}-${da} ${hh}:${mm}`; 53 }, 54 noteMap: { 55 'ç¹ã«ãªãã': 'None.' 56 } 57 } 58 }; 59 60 const t = I18N[LANG] || I18N.ja; 61 62 function translateNote(note) { 63 const value = String(note || '').trim(); 64 if (!value) return ''; 65 return t.noteMap[value] || value; 66 } 67 68 try { 69 const html = await fetch(URL, { cache: "no-store" }).then(r => r.text()); 70 71 const m = html.match(/å´ç«è¦æã¬ãã«[ ã]*([0-9ï¼-ï¼])/); 72 73 const toHalf = (s) => 74 String(s).replace(/[ï¼-ï¼]/g, d => 75 String.fromCharCode(d.charCodeAt(0) - 0xFEE0) 76 ); 77 78 const lv = m ? Number(toHalf(m[1])) : null; 79 80 const text = html 81 .replace(/<script[\s\S]*?<\/script>/gi, "") 82 .replace(/<style[\s\S]*?<\/style>/gi, "") 83 .replace(/<[^>]+>/g, "\n") 84 .replace(/\n{2,}/g, "\n") 85 .trim(); 86 87 let note = ""; 88 const idx = text.indexOf("ç¾å¨ã®è¦æäºé ç"); 89 if (idx !== -1) { 90 const chunk = text.slice(idx, idx + 200); 91 const lines = chunk.split("\n").map(s => s.trim()).filter(Boolean); 92 note = lines[1] && lines[1] !== "ç¾å¨ã®è¦æäºé ç" ? lines[1] : (lines[2] || ""); 93 } 94 95 const translatedNote = translateNote(note); 96 97 if (!lv) { 98 levelEl.textContent = `${t.levelLabel}: ${t.notAvailable}`; 99 boxEl.dataset.level = "0"; 100 } else { 101 levelEl.textContent = `${t.levelLabel}: ${lv}`; 102 boxEl.dataset.level = String(lv); 103 } 104 105 if (noteEl) { 106 noteEl.textContent = translatedNote ? `${t.noteLabel}: ${translatedNote}` : t.noNote; 107 } 108 109 if (updatedEl) { 110 updatedEl.textContent = t.updatedFormat(new Date()); 111 } 112 } catch (e) { 113 console.error(e); 114 levelEl.textContent = t.failed; 115 boxEl.dataset.level = "0"; 116 if (noteEl) noteEl.textContent = ""; 117 if (updatedEl) updatedEl.textContent = t.failed; 118 } 119})();
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.