Lompat ke isi

MediaWiki:Common.js: Perbedaan antara revisi

Dari Mippedia Data
Tidak ada ringkasan suntingan
Tanda: Dikembalikan Suntingan perangkat seluler Suntingan peramban seluler
Tidak ada ringkasan suntingan
Tanda: Dikembalikan Suntingan perangkat seluler Suntingan peramban seluler
Baris 1: Baris 1:
/* ==========================================================
/* ==========================================================
   🧠 MIPPEDIA DATA - ULTRA-FAST ISOLATION & DETAILED LAYOUT (V11.3)
   🧠 MIPPEDIA DATA - FIX ISOLATION & FAILSAFE RENDERING (V11.4)
   Features: Priority Check (ID > EN > CONCISE), Auto-Age,  
   Features: Priority Check (ID > EN > CONCISE), Auto-Age, Auto-Bold.
            Auto-Bold, Smart Links, Dynamic Context, Dynamic Noindex.
   Fixes:
   Fixes:  
             - Fixed crash where script stops completely if #descBox doesn't exist.
             - Super Instant isolation hiding for Infobox/Wikidata elements (Pre-DOM execution).
             - Fixed condition where data is not hidden on first-load empty pages.
             - Removed Live Data Integrator Scanner box completely.
             - Guaranteed instant hide execution for infobox, mapbox, and site links.
            - Removed emoji icons inside the detailed narrative texts.
             - Expanded system explanation text to be highly detailed and comprehensive.
   ========================================================= */
   ========================================================= */


// --- ⚡ LANGKAH 1: ISOLASI ULTRA-CEPAT (DIJALANKAN INSTAN SEBELUM DOM READY) ---
// --- ⚡ LANGKAH 1: ENGINE ISOLASI SINKRONUS (ANTI-FLICKER GLOBAL CSS) ---
(function() {
(function() {
     var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' ');
     var style = document.createElement('style');
    var cacheKey = 'mip_smart_context_thumb_' + pageTitle;
    style.id = 'mip-core-isolate-style';
    var cached = JSON.parse(localStorage.getItem(cacheKey) || "{}");
    style.innerHTML =  
   
        'body.mip-lock-active #mw-content-text > *:not(#mip-empty-state-notice):not(#mip-desc-section):not(script):not(style), ' +
    // Jika cache mendeteksi halaman ini kosong, kunci visualnya sekarang juga!
        'body.mip-lock-active .vertical-navbox, body.mip-lock-active .infobox, ' +
    if (cached.isEmpty) {
        'body.mip-lock-active #catlinks, body.mip-lock-active .data-box, ' +
        var preStyle = document.createElement('style');
        'body.mip-lock-active .wikibase-statementlistview, body.mip-lock-active .wikibase-sitelinks { display: none !important; }';
        preStyle.id = 'mip-instant-isolate-style';
    document.head.appendChild(style);
        preStyle.innerHTML =  
            'body.mip-isolated-active #mw-content-text > *:not(#mip-empty-state-notice):not(#mip-desc-section):not(script):not(style), ' +
            'body.mip-isolated-active .vertical-navbox, body.mip-isolated-active .infobox, ' +
            'body.mip-isolated-active #catlinks, body.mip-isolated-active .data-box { display: none !important; }';
        document.head.appendChild(preStyle);
        document.body.classList.add('mip-isolated-active');
    }
})();
})();


// --- 🛠️ LANGKAH 2: OPERASI UTAMA UTK RENDER DAN VALIDASI DATA ---
// --- 🛠️ LANGKAH 2: CORE OPERATIONS & LOGIC ---
(function() {
(function() {
     $(document).ready(function() {
     $(document).ready(function() {
        var $descSection = $('#mip-desc-section'), $descBox = $('#mip-auto-description'),
            $sourceInfo = $('#mip-source-info'), $portalLinks = $('#mip-portal-links'),
            $projectPortal = $('#mip-project-portal'), $mainContent = $('#mw-content-text');
       
        if (!$descBox.length) return;
         var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' '),
         var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' '),
             cacheKey = 'mip_smart_context_thumb_' + pageTitle,  
             cacheKey = 'mip_smart_context_thumb_' + pageTitle,
             currentYear = 2026;
             currentYear = 2026;
        // Inisialisasi DOM - Buat dinamis jika elemen penampung belum ada di skin wiki
        if (!$('#mip-desc-section').length) {
            $('#mw-content-text').prepend('<div id="mip-desc-section" style="display:none;"><div id="mip-auto-description"></div><div id="mip-source-info" style="margin-top:8px;"></div></div>');
        }
        if (!$('#mip-project-portal').length) {
            $('#mw-content-text').append('<div id="mip-project-portal" style="display:none; margin-top:20px; text-align:center; font-size:0.9em; color:#666;">Halaman ini juga tersedia di: <span id="mip-portal-links"></span></div>');
        }
        var $descSection = $('#mip-desc-section'),
            $descBox = $('#mip-auto-description'),
            $sourceInfo = $('#mip-source-info'),
            $portalLinks = $('#mip-portal-links'),
            $projectPortal = $('#mip-project-portal'),
            $mainContent = $('#mw-content-text');


         var projects = [
         var projects = [
Baris 48: Baris 48:
         ];
         ];


         // --- 🎨 STYLE INJECTION FOR ANIMATION & HUB ---
         // --- 🎨 CSS ANIMATION & BUTTON HUB ---
         if (!$('#mip-clean-style').length) {
         if (!$('#mip-clean-style').length) {
             $('head').append(
             $('head').append(
                 '<style id="mip-clean-style">' +
                 '<style id="mip-clean-style">' +
                     '@keyframes mipFadeInUp {' +
                     '@keyframes mipFadeInUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }' +
                        'from { opacity: 0; transform: translateY(12px); }' +
                     '@keyframes mipPulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.06); opacity: 0.85; } 100% { transform: scale(1); opacity: 1; } }' +
                        'to { opacity: 1; transform: translateY(0); }' +
                     '#mip-empty-state-notice { display: block !important; animation: mipFadeInUp 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards; }' +
                    '}' +
                     '.mip-pulse-icon { animation: mipPulse 2s infinite ease-in-out; transform-origin: center; }' +
                     '@keyframes mipPulse {' +
                     '.mip-btn-container { display: flex; flex-wrap: wrap; justify-content: center; margin: 30px 0 25px 0; padding-top: 5px; }' +
                        '0% { transform: scale(1); opacity: 1; }' +
                     '.mip-action-btn { display: inline-flex; align-items: center; justify-content: center; padding: 11px 22px; margin: 6px; font-size: 0.9em; font-weight: 600; color: #6a5acd !important; background: #ffffff; border: 1.5px solid #6a5acd; border-radius: 30px; text-decoration: none !important; cursor: pointer; transition: all 0.25s ease-in-out; box-shadow: 0 2px 5px rgba(106,92,205,0.08); flex-grow: 1; max-width: 220px; min-width: 160px; }' +
                        '50% { transform: scale(1.06); opacity: 0.85; filter: drop-shadow(0 0 6px rgba(217,83,79,0.4)); }' +
                     '.mip-action-btn:hover { color: #ffffff !important; background: #6a5acd; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(106,92,205,0.2); }' +
                        '100% { transform: scale(1); opacity: 1; }' +
                    '}' +
                     '#mip-empty-state-notice {' +
                        'display: block !important;' +
                        'animation: mipFadeInUp 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards;' +
                    '}' +
                     '.mip-pulse-icon {' +
                        'animation: mipPulse 2s infinite ease-in-out;' +
                        'transform-origin: center;' +
                    '}' +
                     '.mip-btn-container {' +
                        'display: flex; flex-wrap: wrap; justify-content: center; margin: 30px 0 25px 0; padding-top: 5px;' +
                    '}' +
                     '.mip-action-btn {' +
                        'display: inline-flex; align-items: center; justify-content: center;' +
                        'padding: 11px 22px; margin: 6px; font-size: 0.9em; font-weight: 600;' +
                        'color: #6a5acd !important; background: #ffffff; border: 1.5px solid #6a5acd;' +
                        'border-radius: 30px; text-decoration: none !important; cursor: pointer;' +
                        'transition: all 0.25s ease-in-out; box-shadow: 0 2px 5px rgba(106,92,205,0.08);' +
                        'flex-grow: 1; max-width: 220px; min-width: 160px;' +
                    '}' +
                     '.mip-action-btn:hover {' +
                        'color: #ffffff !important; background: #6a5acd;' +
                        'transform: translateY(-2px); box-shadow: 0 4px 12px rgba(106,92,205,0.2);' +
                    '}' +
                 '</style>'
                 '</style>'
             );
             );
         }
         }
        var cached = JSON.parse(localStorage.getItem(cacheKey) || "{}");


         function applyAutoBold(text) { return text.replace(new RegExp('(' + pageTitle + ')', 'gi'), '<strong>$1</strong>'); }
         function applyAutoBold(text) { return text.replace(new RegExp('(' + pageTitle + ')', 'gi'), '<strong>$1</strong>'); }
Baris 133: Baris 110:
         }
         }


         // --- 🧠 RENDER LAYOUT DETAILED NOTICE (NO ICONS, HIGHLY DETAILED) ---
         // --- 🧠 LAYOUT MANAGER (KUNCI/BUKA HALAMAN) ---
         function toggleMippediaLayout(isEmpty) {
         function toggleMippediaLayout(isEmpty) {
             var $existingNotice = $('#mip-empty-state-notice');
             var $existingNotice = $('#mip-empty-state-notice');
Baris 142: Baris 119:


             if (isEmpty) {
             if (isEmpty) {
                 if (!$('#mip-instant-isolate-style').length) {
                 $('body').addClass('mip-lock-active'); // Eksekusi penyembunyian total
                    $('head').append('<style id="mip-instant-isolate-style">body.mip-isolated-active #mw-content-text > *:not(#mip-empty-state-notice):not(#mip-desc-section):not(script):not(style), body.mip-isolated-active .vertical-navbox, body.mip-isolated-active .infobox, body.mip-isolated-active #catlinks, body.mip-isolated-active .data-box { display: none !important; }</style>');
                 $descSection.hide();
                }
                 $('body').addClass('mip-isolated-active');


                 if (!$existingNotice.length) {
                 if (!$existingNotice.length) {
Baris 154: Baris 129:
                     var noticeHtml =  
                     var noticeHtml =  
                         '<div id="mip-empty-state-notice" style="max-width: 720px; margin: 25px auto; padding: 10px 15px; font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;">' +
                         '<div id="mip-empty-state-notice" style="max-width: 720px; margin: 25px auto; padding: 10px 15px; font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;">' +
                           
                            '<!-- Ikon Peringatan Segitiga Tetap Dipertahankan (Animasi Aktif) -->' +
                             '<div style="text-align: center; margin-bottom: 22px;">' +
                             '<div style="text-align: center; margin-bottom: 22px;">' +
                                 '<div class="mip-pulse-icon" style="display: inline-block;">' +
                                 '<div class="mip-pulse-icon" style="display: inline-block;">' +
Baris 162: Baris 135:
                                         '<line x1="12" y1="9" x2="12" y2="13"></line>' +
                                         '<line x1="12" y1="9" x2="12" y2="13"></line>' +
                                         '<line x1="12" y1="17" x2="12.01" y2="17"></line>' +
                                         '<line x1="12" y1="17" x2="12.01" y2="17"></line>' +
                                     '</' + 'svg>' +
                                     '</svg>' +
                                 '</div>' +
                                 '</div>' +
                                 '<h4 style="color: #2c3e50; margin: 12px 0 0 0; font-size: 1.35em; font-weight: 700; letter-spacing: -0.3px;">Item Data Terisolasi: Rujukan Artikel Tidak Ditemukan</h4>' +
                                 '<h4 style="color: #2c3e50; margin: 12px 0 0 0; font-size: 1.35em; font-weight: 700; letter-spacing: -0.3px;">Item Data Terisolasi: Rujukan Artikel Tidak Ditemukan</h4>' +
                             '</div>' +
                             '</div>' +
                              
                              
                            '<!-- 📄 INFORMASI DETAIL & FORMAL (Symmetry Left-Aligned, Tanpa Emoji Internal) -->' +
                             '<div style="text-align: left; color: #4a5568; font-size: 0.93em; line-height: 1.65;">' +
                             '<div style="text-align: left; color: #4a5568; font-size: 0.93em; line-height: 1.65;">' +
                               
                                 '<p style="margin-bottom: 16px;">' +
                                 '<p style="margin-bottom: 16px; text-align: left; letter-spacing: normal; word-spacing: normal;">' +
                                     '<strong>PENGANTAR SISTEM OTOMATIS:</strong> ' +
                                     '<strong>PENGANTAR SISTEM OTOMATIS:</strong> ' +
                                     'Halaman ini ditampilkan karena sistem deteksi siklus internal mendeteksi bahwa entitas data terstruktur ini berada dalam status terisolasi total atau Yatim (Orphaned Data Item). Berdasarkan arsitektur basis data terintegrasi, sebuah item data wajib terikat dengan minimal satu artikel ensiklopedia aktif sebagai validasi literatur atas eksistensi subjek tersebut. Karena item data ini sama sekali tidak memiliki dokumen rujukan yang valid pada Mippedia bahasa Indonesia (ID), Mippedia bahasa Inggris (EN), maupun Mippedia Indonesia Ringkas (Concise), maka sistem secara otomatis menghentikan visualisasi data bawaan untuk mencegah penyebaran informasi tanpa referensi.' +
                                     'Halaman ini ditampilkan karena sistem deteksi siklus internal mendeteksi bahwa entitas data terstruktur ini berada dalam status terisolasi total atau Yatim (Orphaned Data Item). Berdasarkan arsitektur basis data terintegrasi, sebuah item data wajib terikat dengan minimal satu artikel ensiklopedia aktif sebagai validasi literatur atas eksistensi subjek tersebut. Karena item data ini sama sekali tidak memiliki dokumen rujukan yang valid pada Mippedia bahasa Indonesia (ID), Mippedia bahasa Inggris (EN), maupun Mippedia Indonesia Ringkas (Concise), maka sistem secara otomatis menghentikan visualisasi data bawaan untuk mencegah penyebaran informasi tanpa referensi.' +
                                 '</p>' +
                                 '</p>' +
                               
                                 '<p style="margin-bottom: 16px;">' +
                                 '<p style="margin-bottom: 16px; text-align: left; letter-spacing: normal; word-spacing: normal;">' +
                                     '<strong>KEBIJAKAN PENGUNCIAN DAN PROTEKSI HALAMAN:</strong> ' +
                                     '<strong>KEBIJAKAN PENGUNCIAN DAN PROTEKSI HALAMAN:</strong> ' +
                                     'Sebagai langkah preventif demi menjaga integritas data dan mematuhi standar privasi serta validitas ekosistem Mippedia Foundation, halaman data yang terisolasi ini telah dialihkan ke dalam mode proteksi penuh dan dikunci secara otomatis oleh sistem keamanan. Pengguna umum, kontributor non-pengurus, maupun mesin pembaca otomatis tidak diizinkan melakukan penyuntingan langsung (*read-only mode*) pada elemen data terstruktur di halaman ini. Kebijakan penguncian ini diterapkan secara ketat untuk menghindari manipulasi data mentah sepihak, meminimalkan risiko vandalisme tak terlihat, serta mencegah terjadinya anomali skrip (*visual script error*) yang berpotensi merusak struktur database repositori secara global.' +
                                     'Sebagai langkah preventif demi menjaga integritas data dan mematuhi standar privasi serta validitas ekosistem Mippedia Foundation, halaman data yang terisolasi ini telah dialihkan ke dalam mode proteksi penuh dan dikunci secara otomatis oleh sistem keamanan. Pengguna umum, kontributor non-pengurus, maupun mesin pembaca otomatis tidak diizinkan melakukan penyuntingan langsung (*read-only mode*) pada elemen data terstruktur di halaman ini. Kebijakan penguncian ini diterapkan secara ketat untuk menghindari manipulasi data mentah sepihak, meminimalkan risiko vandalisme tak terlihat, serta mencegah terjadinya anomali skrip (*visual script error*) yang berpotensi merusak struktur database repositori secara global.' +
                                 '</p>' +
                                 '</p>' +
                               
                                 '<p style="margin-bottom: 16px;">' +
                                 '<p style="margin-bottom: 16px; text-align: left; letter-spacing: normal; word-spacing: normal;">' +
                                     '<strong>KONSEKUENSI DAN REGULASI PENGAPUSAN PERMANEN:</strong> ' +
                                     '<strong>KONSEKUENSI DAN REGULASI PENGAPUSAN PERMANEN:</strong> ' +
                                     'Sesuai dengan regulasi pemeliharaan ruang penyimpanan server, entitas data tanpa rujukan hanya diklasifikasikan sebagai data konsumsi sementara (*temporary cache entry*). Jika dalam batas waktu evaluasi berkala yang ditentukan item ini tetap dibiarkan kosong tanpa adanya tindakan penyelamatan berupa pembuatan artikel baru, maka skrip pembersihan otomatis (*cron-job cleaner*) bersama Dewan Moderator Mippedia Community akan melakukan tindakan penghapusan permanen secara menyeluruh (*Hard Purge / Delete*). Setelah proses penghapusan dilakukan, seluruh data terkait entitas ini akan dihapus dari server untuk mengoptimalkan ruang alokasi database dan menjaga stabilitas performa jaringan.' +
                                     'Sesuai dengan regulasi pemeliharaan ruang penyimpanan server, entitas data tanpa rujukan hanya diklasifikasikan sebagai data konsumsi sementara (*temporary cache entry*). Jika dalam batas waktu evaluasi berkala yang ditentukan item ini tetap dibiarkan kosong tanpa adanya tindakan penyelamatan berupa pembuatan artikel baru, maka skrip pembersihan otomatis (*cron-job cleaner*) bersama Dewan Moderator Mippedia Community akan melakukan tindakan penghapusan permanen secara menyeluruh (*Hard Purge / Delete*). Setelah proses penghapusan dilakukan, seluruh data terkait entitas ini akan dihapus dari server untuk mengoptimalkan ruang alokasi database dan menjaga stabilitas performa jaringan.' +
                                 '</p>' +
                                 '</p>' +
                               
                                 '<p style="margin-bottom: 0;">' +
                                 '<p style="margin-bottom: 0; text-align: left; letter-spacing: normal; word-spacing: normal;">' +
                                     '<strong>PANDUAN PEMULIHAN BAGI KONTRIBUTOR:</strong> ' +
                                     '<strong>PANDUAN PEMULIHAN BAGI KONTRIBUTOR:</strong> ' +
                                     'Satu-satunya cara untuk memulihkan status entitas data ini dan membuka kembali akses penyuntingannya adalah dengan membuat dokumen artikel rujukan yang sah pada salah satu pilar ekosistem Mippedia. Anda sangat disarankan untuk segera memulai pembuatan draf artikel baru melalui salah satu tombol akselerasi instan di bawah ini. Pastikan artikel yang Anda buat memuat informasi yang valid, ditulis dengan sudut pandang netral, serta dilengkapi dengan referensi literatur yang kredibel agar sistem sinkronisasi dapat memetakan kembali dan menormalkan halaman data ini secara otomatis.' +
                                     'Satu-satunya cara untuk memulihkan status entitas data ini dan membuka kembali akses penyuntingannya adalah dengan membuat dokumen artikel rujukan yang sah pada salah satu pilar ekosistem Mippedia. Anda sangat disarankan untuk segera memulai pembuatan draf artikel baru melalui salah satu tombol akselerasi instan di bawah ini. Pastikan artikel yang Anda buat memuat informasi yang valid, ditulis dengan sudut pandang netral, serta dilengkapi dengan referensi literatur yang kredibel agar sistem sinkronisasi dapat memetakan kembali dan menormalkan halaman data ini secara otomatis.' +
Baris 191: Baris 159:
                             '</div>' +
                             '</div>' +
                              
                              
                            '<!-- 🚀 INSTANT ACTION HUB (3 TOMBOL AKSES) -->' +
                             '<div class="mip-btn-container">' +
                             '<div class="mip-btn-container">' +
                                 '<a href="' + createUrlID + '" target="_blank" class="mip-action-btn">Buat Artikel ID</a>' +
                                 '<a href="' + createUrlID + '" target="_blank" class="mip-action-btn">Buat Artikel ID</a>' +
Baris 198: Baris 165:
                             '</div>' +
                             '</div>' +


                            '<!-- Catatan Kaki -->' +
                             '<div style="font-size: 0.82em; color: #a0a0a0; line-height: 1.4; font-style: italic; border-top: 1px solid #f0f0f0; padding-top: 15px; text-align: center;">' +
                             '<div style="font-size: 0.82em; color: #a0a0a0; line-height: 1.4; font-style: italic; border-top: 1px solid #f0f0f0; padding-top: 15px; text-align: center;">' +
                                 'Informasi Sistem: Item data yang tidak terikat dengan artikel ensiklopedia apa pun dalam ekosistem Mippedia akan dihapus secara otomatis oleh pengurus dalam waktu dekat.' +
                                 'Informasi Sistem: Item data yang tidak terikat dengan artikel ensiklopedia apa pun dalam ekosistem Mippedia akan dihapus secara otomatis oleh pengurus dalam waktu dekat.' +
Baris 205: Baris 171:
                     $mainContent.prepend(noticeHtml);
                     $mainContent.prepend(noticeHtml);
                 }
                 }
                $descSection.hide();


                 if (!isSysop) {
                 if (!isSysop) {
Baris 212: Baris 176:
                     $(document).on('keydown.miplock', function(e) {
                     $(document).on('keydown.miplock', function(e) {
                         if (e.key.toLowerCase() === 'e' && !$(e.target).is('input, textarea')) {
                         if (e.key.toLowerCase() === 'e' && !$(e.target).is('input, textarea')) {
                             e.preventDefault();
                             e.preventDefault(); return false;
                            return false;
                         }
                         }
                     });
                     });
Baris 219: Baris 182:


                 mw.config.set('wgRobotsPolicies', { 'index': 'noindex', 'follow': 'nofollow' });
                 mw.config.set('wgRobotsPolicies', { 'index': 'noindex', 'follow': 'nofollow' });
                 if ($metaRobots.length) {
                 if ($metaRobots.length) { $metaRobots.attr('content', 'noindex, nofollow'); }
                    $metaRobots.attr('content', 'noindex, nofollow');
                 else { $('head').append('<meta name="robots" content="noindex, nofollow">'); }
                 } else {
                    $('head').append('<meta name="robots" content="noindex, nofollow">');
                }


             } else {
             } else {
                 $('body').removeClass('mip-isolated-active');
                // JIKA ADA DATA: Buka proteksi visual skrip
                 $('body').removeClass('mip-lock-active');
                 if ($existingNotice.length) $existingNotice.remove();
                 if ($existingNotice.length) $existingNotice.remove();
                 $descSection.show();
                 $descSection.show();


                 if (!isSysop) {
                 if (!isSysop) { $(document).off('keydown.miplock'); }
                    $(document).off('keydown.miplock');
                }
 
                 mw.config.set('wgRobotsPolicies', { 'index': 'index', 'follow': 'follow' });
                 mw.config.set('wgRobotsPolicies', { 'index': 'index', 'follow': 'follow' });
                 if ($metaRobots.length) $metaRobots.attr('content', 'index, follow');
                 if ($metaRobots.length) $metaRobots.attr('content', 'index, follow');
Baris 239: Baris 197:
         }
         }


         // --- SISTEM PRIORITAS ---
         // --- PRIORITIZED DISPATCHER RUNNER ---
         var globalEnTitle = cached.enTitle || "";  
         var globalEnTitle = cached.enTitle || "";  


Baris 265: Baris 223:
                 },
                 },
                 error: function() {  
                 error: function() {  
                     if (cached.content) {
                     if (cached.content && !cached.isEmpty) {
                         toggleMippediaLayout(cached.isEmpty || false);
                         toggleMippediaLayout(false);
                         if (!cached.isEmpty) renderAll(cached.p, cached.content, cached.isTrans, cached.orig, cached.img, cached.customUrl, cached.enTitle);
                         renderAll(cached.p, cached.content, cached.isTrans, cached.orig, cached.img, cached.customUrl, cached.enTitle);
                     }  
                    } else {
                        fetchPriorityData(0, "0", "");
                     }
                 }
                 }
             });
             });
Baris 345: Baris 305:
             var processedText = applyAutoBold(applyDynamicContext(currentText));
             var processedText = applyAutoBold(applyDynamicContext(currentText));
             var thumbHtml = img ? '<div style="float: right; margin-left: 15px; margin-bottom: 10px; border: 1px solid #ddd; padding: 3px; background: #fff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"><img src="'+img+'" style="max-width: 100px; display: block; height: auto;"></div>' : '';
             var thumbHtml = img ? '<div style="float: right; margin-left: 15px; margin-bottom: 10px; border: 1px solid #ddd; padding: 3px; background: #fff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"><img src="'+img+'" style="max-width: 100px; display: block; height: auto;"></div>' : '';
            if (!$mainContent.find('#mip-desc-section').length) {
                $mainContent.prepend($descSection);
            }


             $descSection.show();
             $descSection.show();

Revisi per 1 Juni 2026 17.08

/* ==========================================================
   🧠 MIPPEDIA DATA - FIX ISOLATION & FAILSAFE RENDERING (V11.4)
   Features: Priority Check (ID > EN > CONCISE), Auto-Age, Auto-Bold.
   Fixes:
             - Fixed crash where script stops completely if #descBox doesn't exist.
             - Fixed condition where data is not hidden on first-load empty pages.
             - Guaranteed instant hide execution for infobox, mapbox, and site links.
   ========================================================= */

// --- ⚡ LANGKAH 1: ENGINE ISOLASI SINKRONUS (ANTI-FLICKER GLOBAL CSS) ---
(function() {
    var style = document.createElement('style');
    style.id = 'mip-core-isolate-style';
    style.innerHTML = 
        'body.mip-lock-active #mw-content-text > *:not(#mip-empty-state-notice):not(#mip-desc-section):not(script):not(style), ' +
        'body.mip-lock-active .vertical-navbox, body.mip-lock-active .infobox, ' +
        'body.mip-lock-active #catlinks, body.mip-lock-active .data-box, ' +
        'body.mip-lock-active .wikibase-statementlistview, body.mip-lock-active .wikibase-sitelinks { display: none !important; }';
    document.head.appendChild(style);
})();

// --- 🛠️ LANGKAH 2: CORE OPERATIONS & LOGIC ---
(function() {
    $(document).ready(function() {
        var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' '),
            cacheKey = 'mip_smart_context_thumb_' + pageTitle,
            currentYear = 2026;

        // Inisialisasi DOM - Buat dinamis jika elemen penampung belum ada di skin wiki
        if (!$('#mip-desc-section').length) {
            $('#mw-content-text').prepend('<div id="mip-desc-section" style="display:none;"><div id="mip-auto-description"></div><div id="mip-source-info" style="margin-top:8px;"></div></div>');
        }
        if (!$('#mip-project-portal').length) {
            $('#mw-content-text').append('<div id="mip-project-portal" style="display:none; margin-top:20px; text-align:center; font-size:0.9em; color:#666;">Halaman ini juga tersedia di: <span id="mip-portal-links"></span></div>');
        }

        var $descSection = $('#mip-desc-section'), 
            $descBox = $('#mip-auto-description'),
            $sourceInfo = $('#mip-source-info'), 
            $portalLinks = $('#mip-portal-links'),
            $projectPortal = $('#mip-project-portal'), 
            $mainContent = $('#mw-content-text');

        var projects = [
            { id: 'id', name: 'Mippedia bahasa Indonesia', url: 'https://id.mippedia.org/api.php', base: 'https://id.mippedia.org/wiki/', label: 'Mippedia Indonesia' },
            { id: 'en', name: 'Mippedia bahasa Inggris', url: 'https://en.mippedia.org/api.php', base: 'https://en.mippedia.org/wiki/', label: 'Mippedia Inggris' },
            { id: 'concise', name: 'Mippedia bahasa Indonesia ringkas', url: 'https://concise.mippedia.org/api.php', base: 'https://concise.mippedia.org/wiki/', label: 'Mippedia Ringkas' }
        ];

        // --- 🎨 CSS ANIMATION & BUTTON HUB ---
        if (!$('#mip-clean-style').length) {
            $('head').append(
                '<style id="mip-clean-style">' +
                    '@keyframes mipFadeInUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }' +
                    '@keyframes mipPulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.06); opacity: 0.85; } 100% { transform: scale(1); opacity: 1; } }' +
                    '#mip-empty-state-notice { display: block !important; animation: mipFadeInUp 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards; }' +
                    '.mip-pulse-icon { animation: mipPulse 2s infinite ease-in-out; transform-origin: center; }' +
                    '.mip-btn-container { display: flex; flex-wrap: wrap; justify-content: center; margin: 30px 0 25px 0; padding-top: 5px; }' +
                    '.mip-action-btn { display: inline-flex; align-items: center; justify-content: center; padding: 11px 22px; margin: 6px; font-size: 0.9em; font-weight: 600; color: #6a5acd !important; background: #ffffff; border: 1.5px solid #6a5acd; border-radius: 30px; text-decoration: none !important; cursor: pointer; transition: all 0.25s ease-in-out; box-shadow: 0 2px 5px rgba(106,92,205,0.08); flex-grow: 1; max-width: 220px; min-width: 160px; }' +
                    '.mip-action-btn:hover { color: #ffffff !important; background: #6a5acd; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(106,92,205,0.2); }' +
                '</style>'
            );
        }

        var cached = JSON.parse(localStorage.getItem(cacheKey) || "{}");

        function applyAutoBold(text) { return text.replace(new RegExp('(' + pageTitle + ')', 'gi'), '<strong>$1</strong>'); }
        function cleanExtract(text) { return text.replace(/\[\d+\]/g, '').replace(/\{\{[^}]+\}\}/g, '').replace(/\(\s*\)/g, '').replace(/\s\s+/g, ' ').trim(); }
        
        function applyDynamicContext(text) {
            var date = new Date();
            var hari = ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"];
            var bulan = ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"];
            var tglSkrg = hari[date.getDay()] + ", " + date.getDate() + " " + bulan[date.getMonth()] + " " + date.getFullYear();
            return text.replace(/(hari ini|saat ini|sekarang)/gi, '$1 (' + tglSkrg + ')')
                .replace(/(\d{1,2}\s(?:Januari|Februari|Maret|April|Mei|Juni|Juli|Agustus|September|Oktober|November|Desember)\s(\d{4}))/gi, function(m, f, y) { 
                    return f + " <span style='color: #444; font-weight: bold;'>– usia " + (currentYear - parseInt(y)) + " tahun</span>"; 
                })
                .replace(/(sejak|tahun)\s(\d{4})/gi, function(m, k, y) {
                    var gap = currentYear - parseInt(y);
                    if (gap > 0 && gap < 100) return k + " " + y + " <small style='color: #888;'>(" + gap + " thn lalu)</small>";
                    return m;
                });
        }

        function applySummary(text) {
            var limit = 250;
            if (text.length <= limit) return '<span>' + text + '</span>';
            return '<span>' + text.substring(0, limit) + '</span><span class="mip-dots">... </span><span class="mip-more" style="display:none;">' + text.substring(limit) + '</span><span class="mip-read-btn" style="color: #6a5acd; cursor: pointer; font-weight: bold; margin-left: 5px;">Baca selengkapnya</span>';
        }

        function buildSmartLinks(currentId, validatedEnTitle) {
            $portalLinks.empty();
            var validLinks = [];
            var checkRequests = projects.filter(p => p.id !== currentId).map(function(p) {
                var targetTitle = (p.id === 'en' && validatedEnTitle) ? validatedEnTitle : pageTitle;
                if (p.id === 'en' && !validatedEnTitle) return $.Deferred().resolve();

                return $.ajax({ url: p.url, data: { action: 'query', titles: targetTitle, format: 'json', origin: '*' }, dataType: 'json' })
                    .then(function(data) { 
                        if (data.query.pages["-1"] === undefined) { 
                            validLinks.push('<a href="' + p.base + encodeURIComponent(targetTitle) + '" target="_blank" style="color: #6a5acd; text-decoration: underline; font-weight: bold;">' + p.label + '</a>'); 
                        } 
                    });
            });

            $.when.apply($, checkRequests).done(function() {
                if (validLinks.length > 0) { $portalLinks.html(validLinks.join(' <span style="color:#ccc; margin: 0 5px;">•</span> ')); $projectPortal.fadeIn(); }
            });
        }

        // --- 🧠 LAYOUT MANAGER (KUNCI/BUKA HALAMAN) ---
        function toggleMippediaLayout(isEmpty) {
            var $existingNotice = $('#mip-empty-state-notice');
            var userGroups = mw.config.get('wgUserGroups') || [];
            var isSysop = userGroups.indexOf('sysop') !== -1;
            var $editElements = $('#ca-edit, .mw-editsection, .wb-editsection, .mip-edit-trigger, [id*="edit"], [class*="edit-pencil"]');
            var $metaRobots = $('meta[name="robots"]');

            if (isEmpty) {
                $('body').addClass('mip-lock-active'); // Eksekusi penyembunyian total
                $descSection.hide();

                if (!$existingNotice.length) {
                    var createUrlID = 'https://id.mippedia.org/index.php?title=' + encodeURIComponent(pageTitle) + '&action=edit';
                    var createUrlEN = 'https://en.mippedia.org/index.php?title=' + encodeURIComponent(pageTitle) + '&action=edit';
                    var createUrlConcise = 'https://concise.mippedia.org/index.php?title=' + encodeURIComponent(pageTitle) + '&action=edit';

                    var noticeHtml = 
                        '<div id="mip-empty-state-notice" style="max-width: 720px; margin: 25px auto; padding: 10px 15px; font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;">' +
                            '<div style="text-align: center; margin-bottom: 22px;">' +
                                '<div class="mip-pulse-icon" style="display: inline-block;">' +
                                    '<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="#d9534f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
                                        '<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>' +
                                        '<line x1="12" y1="9" x2="12" y2="13"></line>' +
                                        '<line x1="12" y1="17" x2="12.01" y2="17"></line>' +
                                    '</svg>' +
                                '</div>' +
                                '<h4 style="color: #2c3e50; margin: 12px 0 0 0; font-size: 1.35em; font-weight: 700; letter-spacing: -0.3px;">Item Data Terisolasi: Rujukan Artikel Tidak Ditemukan</h4>' +
                            '</div>' +
                            
                            '<div style="text-align: left; color: #4a5568; font-size: 0.93em; line-height: 1.65;">' +
                                '<p style="margin-bottom: 16px;">' +
                                    '<strong>PENGANTAR SISTEM OTOMATIS:</strong> ' +
                                    'Halaman ini ditampilkan karena sistem deteksi siklus internal mendeteksi bahwa entitas data terstruktur ini berada dalam status terisolasi total atau Yatim (Orphaned Data Item). Berdasarkan arsitektur basis data terintegrasi, sebuah item data wajib terikat dengan minimal satu artikel ensiklopedia aktif sebagai validasi literatur atas eksistensi subjek tersebut. Karena item data ini sama sekali tidak memiliki dokumen rujukan yang valid pada Mippedia bahasa Indonesia (ID), Mippedia bahasa Inggris (EN), maupun Mippedia Indonesia Ringkas (Concise), maka sistem secara otomatis menghentikan visualisasi data bawaan untuk mencegah penyebaran informasi tanpa referensi.' +
                                '</p>' +
                                '<p style="margin-bottom: 16px;">' +
                                    '<strong>KEBIJAKAN PENGUNCIAN DAN PROTEKSI HALAMAN:</strong> ' +
                                    'Sebagai langkah preventif demi menjaga integritas data dan mematuhi standar privasi serta validitas ekosistem Mippedia Foundation, halaman data yang terisolasi ini telah dialihkan ke dalam mode proteksi penuh dan dikunci secara otomatis oleh sistem keamanan. Pengguna umum, kontributor non-pengurus, maupun mesin pembaca otomatis tidak diizinkan melakukan penyuntingan langsung (*read-only mode*) pada elemen data terstruktur di halaman ini. Kebijakan penguncian ini diterapkan secara ketat untuk menghindari manipulasi data mentah sepihak, meminimalkan risiko vandalisme tak terlihat, serta mencegah terjadinya anomali skrip (*visual script error*) yang berpotensi merusak struktur database repositori secara global.' +
                                '</p>' +
                                '<p style="margin-bottom: 16px;">' +
                                    '<strong>KONSEKUENSI DAN REGULASI PENGAPUSAN PERMANEN:</strong> ' +
                                    'Sesuai dengan regulasi pemeliharaan ruang penyimpanan server, entitas data tanpa rujukan hanya diklasifikasikan sebagai data konsumsi sementara (*temporary cache entry*). Jika dalam batas waktu evaluasi berkala yang ditentukan item ini tetap dibiarkan kosong tanpa adanya tindakan penyelamatan berupa pembuatan artikel baru, maka skrip pembersihan otomatis (*cron-job cleaner*) bersama Dewan Moderator Mippedia Community akan melakukan tindakan penghapusan permanen secara menyeluruh (*Hard Purge / Delete*). Setelah proses penghapusan dilakukan, seluruh data terkait entitas ini akan dihapus dari server untuk mengoptimalkan ruang alokasi database dan menjaga stabilitas performa jaringan.' +
                                '</p>' +
                                '<p style="margin-bottom: 0;">' +
                                    '<strong>PANDUAN PEMULIHAN BAGI KONTRIBUTOR:</strong> ' +
                                    'Satu-satunya cara untuk memulihkan status entitas data ini dan membuka kembali akses penyuntingannya adalah dengan membuat dokumen artikel rujukan yang sah pada salah satu pilar ekosistem Mippedia. Anda sangat disarankan untuk segera memulai pembuatan draf artikel baru melalui salah satu tombol akselerasi instan di bawah ini. Pastikan artikel yang Anda buat memuat informasi yang valid, ditulis dengan sudut pandang netral, serta dilengkapi dengan referensi literatur yang kredibel agar sistem sinkronisasi dapat memetakan kembali dan menormalkan halaman data ini secara otomatis.' +
                                '</p>' +
                            '</div>' +
                            
                            '<div class="mip-btn-container">' +
                                '<a href="' + createUrlID + '" target="_blank" class="mip-action-btn">Buat Artikel ID</a>' +
                                '<a href="' + createUrlEN + '" target="_blank" class="mip-action-btn">Buat Artikel EN</a>' +
                                '<a href="' + createUrlConcise + '" target="_blank" class="mip-action-btn">Buat Artikel Ringkas</a>' +
                            '</div>' +

                            '<div style="font-size: 0.82em; color: #a0a0a0; line-height: 1.4; font-style: italic; border-top: 1px solid #f0f0f0; padding-top: 15px; text-align: center;">' +
                                'Informasi Sistem: Item data yang tidak terikat dengan artikel ensiklopedia apa pun dalam ekosistem Mippedia akan dihapus secara otomatis oleh pengurus dalam waktu dekat.' +
                            '</div>' +
                        '</div>';
                    $mainContent.prepend(noticeHtml);
                }

                if (!isSysop) {
                    $editElements.css({ 'pointer-events': 'none', 'opacity': '0.3', 'cursor': 'not-allowed' }).hide();
                    $(document).on('keydown.miplock', function(e) {
                        if (e.key.toLowerCase() === 'e' && !$(e.target).is('input, textarea')) {
                            e.preventDefault(); return false;
                        }
                    });
                }

                mw.config.set('wgRobotsPolicies', { 'index': 'noindex', 'follow': 'nofollow' });
                if ($metaRobots.length) { $metaRobots.attr('content', 'noindex, nofollow'); } 
                else { $('head').append('<meta name="robots" content="noindex, nofollow">'); }

            } else {
                // JIKA ADA DATA: Buka proteksi visual skrip
                $('body').removeClass('mip-lock-active');
                if ($existingNotice.length) $existingNotice.remove();
                $descSection.show();

                if (!isSysop) { $(document).off('keydown.miplock'); }
                mw.config.set('wgRobotsPolicies', { 'index': 'index', 'follow': 'follow' });
                if ($metaRobots.length) $metaRobots.attr('content', 'index, follow');
            }
        }

        // --- PRIORITIZED DISPATCHER RUNNER ---
        var globalEnTitle = cached.enTitle || ""; 

        function init() {
            var pPrimary = projects[0]; 
            $.ajax({
                url: pPrimary.url,
                data: { action: 'query', prop: 'revisions|pageimages|langlinks', lllang: 'en', rvprop: 'timestamp', piprop: 'thumbnail', pithumbsize: 150, titles: pageTitle, format: 'json', origin: '*' },
                dataType: 'json',
                success: function(res) {
                    var pg = res.query.pages, id = Object.keys(pg)[0];
                    var latestTS = (id != "-1") ? pg[id].revisions[0].timestamp : "0";
                    var thumbUrl = (id != "-1" && pg[id].thumbnail) ? pg[id].thumbnail.source : "";
                    
                    if (id != "-1" && pg[id].langlinks && pg[id].langlinks[0]) {
                        globalEnTitle = pg[id].langlinks[0]['*'];
                    }

                    if (cached.content && cached.ts === latestTS && latestTS !== "0" && !cached.isEmpty) {
                        toggleMippediaLayout(false);
                        renderAll(cached.p, cached.content, cached.isTrans, cached.orig, cached.img, cached.customUrl, cached.enTitle);
                    } else { 
                        fetchPriorityData(0, latestTS, thumbUrl); 
                    }
                },
                error: function() { 
                    if (cached.content && !cached.isEmpty) {
                        toggleMippediaLayout(false);
                        renderAll(cached.p, cached.content, cached.isTrans, cached.orig, cached.img, cached.customUrl, cached.enTitle);
                    } else {
                        fetchPriorityData(0, "0", "");
                    }
                }
            });
        }

        function fetchPriorityData(index, newTS, img) {
            if (index >= projects.length) {
                localStorage.setItem(cacheKey, JSON.stringify({isEmpty: true, ts: newTS, content: ""}));
                toggleMippediaLayout(true);
                return;
            }

            var p = projects[index];

            if (p.id === 'en') {
                if (!globalEnTitle) {
                    $.ajax({
                        url: 'https://concise.mippedia.org/api.php',
                        data: { action: 'query', prop: 'langlinks', lllang: 'en', titles: pageTitle, format: 'json', origin: '*' },
                        dataType: 'json',
                        async: false, 
                        success: function(cRes) {
                            var cPg = cRes.query.pages, cId = Object.keys(cPg)[0];
                            if (cId != "-1" && cPg[cId].langlinks && cPg[cId].langlinks[0]) {
                                globalEnTitle = cPg[cId].langlinks[0]['*'];
                            }
                        }
                    });
                }

                if (globalEnTitle) {
                    $.ajax({
                        url: p.url,
                        data: { action: 'query', prop: 'extracts', exintro: 1, explaintext: 1, titles: globalEnTitle, format: 'json', origin: '*' },
                        dataType: 'json',
                        success: function(data) {
                            var pages = data.query.pages, pageId = Object.keys(pages)[0];
                            if (pageId != "-1" && pages[pageId].extract) {
                                var extract = cleanExtract(pages[pageId].extract);
                                finalize(p, extract, false, "", newTS, img, p.base + encodeURIComponent(globalEnTitle), globalEnTitle);
                            } else {
                                fetchPriorityData(index + 1, newTS, img);
                            }
                        },
                        error: function() { fetchPriorityData(index + 1, newTS, img); }
                    });
                } else {
                    fetchPriorityData(index + 1, newTS, img);
                }
            } else {
                $.ajax({
                    url: p.url,
                    data: { action: 'query', prop: 'extracts', exintro: 1, explaintext: 1, titles: pageTitle, format: 'json', origin: '*' },
                    dataType: 'json',
                    success: function(data) {
                        var pages = data.query.pages, pageId = Object.keys(pages)[0];
                        if (pageId != "-1" && pages[pageId].extract) {
                            var extract = cleanExtract(pages[pageId].extract);
                            finalize(p, extract, false, "", newTS, img, p.base + encodeURIComponent(pageTitle), globalEnTitle); 
                        } else {
                            fetchPriorityData(index + 1, newTS, img);
                        }
                    },
                    error: function() { fetchPriorityData(index + 1, newTS, img); }
                });
            }
        }

        function finalize(p, c, t, o, ts, img, customUrl, enTitle) {
            localStorage.setItem(cacheKey, JSON.stringify({isEmpty: false, p:p, content:c, isTrans:t, orig:o, ts:ts, img:img, customUrl: customUrl, enTitle: enTitle}));
            toggleMippediaLayout(false); 
            renderAll(p, c, t, o, img, customUrl, enTitle);
        }

        function renderAll(p, currentText, isTranslated, originalText, img, customUrl, enTitle) {
            var processedText = applyAutoBold(applyDynamicContext(currentText));
            var thumbHtml = img ? '<div style="float: right; margin-left: 15px; margin-bottom: 10px; border: 1px solid #ddd; padding: 3px; background: #fff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"><img src="'+img+'" style="max-width: 100px; display: block; height: auto;"></div>' : '';

            $descSection.show();
            $descBox.show().html(thumbHtml + applySummary(processedText) + '<div style="clear:both;"></div>');
            
            var targetLink = customUrl ? customUrl : p.base + encodeURIComponent(pageTitle);
            var footer = '<div style="font-size: 0.9em; color: #777;">Sumber : <a href="' + targetLink + '" target="_blank" style="color: #6a5acd; font-weight: bold; text-decoration: none;">' + p.name + '.</a>';
            if (isTranslated) { footer += '<br><span style="font-size: 0.85em; font-style: italic;">(Diterjemahkan secara otomatis)</span> <span id="mip-toggle-orig" style="color: #6a5acd; cursor: pointer; text-decoration: underline; margin-left: 5px;">Tampilkan versi asli</span>'; }
            $sourceInfo.show().html(footer);
            
            buildSmartLinks(p.id, enTitle);
            
            $(document).off('click', '.mip-read-btn').on('click', '.mip-read-btn', function() { $(this).hide(); $('.mip-dots').hide(); $('.mip-more').fadeIn(); });
            $(document).off('click', '#mip-toggle-orig').on('click', '#mip-toggle-orig', function() {
                var isOrig = ($(this).text() === 'Tampilkan versi asli');
                var textToDisplay = applyAutoBold(applyDynamicContext(isOrig ? originalText : currentText));
                $descBox.html(thumbHtml + applySummary(textToDisplay) + '<div style="clear:both;"></div>');
                $(this).text(isOrig ? 'Tampilkan terjemahan' : 'Tampilkan versi asli');
            });
        }

        init();
    });
})();

/* ==========================================================
   🚀 MIPPEDIA DATA - CORE SYSTEM (ULTIMATE BUNDLE)
   Status: FINAL & REVISED (Visual Fix + Permission Logic)
   Fix: Mobile Responsive Notification Position
   ========================================================== */

(function() {
    $(document).ready(function() {
        // --- 1. FILTER GLOBAL (Namespace 0 & Bukan Halaman Utama) ---
        if (mw.config.get('wgNamespaceNumber') !== 0 || 
            mw.config.get('wgIsMainPage') || 
            mw.config.get('wgAction') !== 'view') return;

        var pageTitle = mw.config.get('wgPageName');
        var dataPage = 'MediaWiki:Sitelinks-Data.json';
        var userGroups = mw.config.get('wgUserGroups');
        var isAdmin = userGroups.includes('sysop') || userGroups.includes('interface-admin');

        var projects = {
            'id': { name: 'ID', url: 'https://id.mippedia.org/api.php', base: 'https://id.mippedia.org/wiki/', color: '#6a5acd' },
            'en': { name: 'EN', url: 'https://en.mippedia.org/api.php', base: 'https://en.mippedia.org/wiki/', color: '#4169e1' },
            'concise': { name: 'Concise', url: 'https://concise.mippedia.org/api.php', base: 'https://concise.mippedia.org/wiki/', color: '#20b2aa' }
        };

        // --- 2. KOTAK NOTIFIKASI INFORMASI MODERN (FIXED MOBILE POSITION) ---
        function showBoxNotif(title, msg, type) {
            $('.mip-box-notif').remove();
            var theme = type === 'success' ? {bg:'#e6fffa', border:'#38b2ac', text:'#234e52', icon:''} : 
                        {bg:'#fff5f5', border:'#f56565', text:'#742a2a', icon:''};
            
            // Logika CSS Responsif untuk posisi
            var isMobile = window.innerWidth <= 768;
            var desktopStyle = "top:25px; right:25px; width:350px;";
            var mobileStyle = "top:15px; left:50%; transform:translateX(-50%); width:90%; max-width:400px;";
            var finalPos = isMobile ? mobileStyle : desktopStyle;

            var $notif = $('<div class="mip-box-notif" style="position:fixed; ' + finalPos + ' background:'+theme.bg+'; border-left:6px solid '+theme.border+'; padding:18px; z-index:10001; border-radius:12px; box-shadow:0 15px 35px rgba(0,0,0,0.2); font-family:sans-serif; animation:mipSlideIn 0.4s ease-out;">' +
                '<div style="display:flex; align-items:center; gap:12px; margin-bottom:8px;">' +
                    '<span style="font-size:20px;">'+theme.icon+'</span>' +
                    '<strong style="color:'+theme.text+'; font-size:15px; letter-spacing:-0.3px;">'+title+'</strong>' +
                '</div>' +
                '<p style="margin:0; font-size:13px; color:'+theme.text+'; line-height:1.6; opacity:0.9;">'+msg+'</p>' +
            '</div>').appendTo('body');

            setTimeout(function() { $notif.fadeOut(function(){ $(this).remove(); }); }, 5500);
        }

        // --- 3. UI GENERATOR (DIPERTEBAL) ---

      // A. Header Pro
        var headerHtml = '<div id="mip-header" style="background:#f8f9fa; border:1px solid #ddd; border-left:6px solid #6a5acd; padding:18px; margin-bottom:25px; border-radius:6px; box-shadow:inset 0 0 10px rgba(0,0,0,0.02);">' +
            '<div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">' +
            '<span style="background:#6a5acd; color:white; padding:3px 10px; border-radius:4px; font-size:11px; font-weight:bold; text-transform:uppercase; letter-spacing:0.5px;">Basis Data Terstruktur</span>' +
            '<strong style="color:#111; font-size:16px;"></strong></div>' +
            '<p style="margin:0; font-size:13px; color:#444; line-height:1.6;">' +
            'Halaman ini adalah metadata entitas repositori pusat yang disinkronisasi secara otomatis lintas ekosistem. ' +
            'Informasi di bawah ini bersifat teknis dan bebas digunakan sebagai referensi data terbuka bagi semua orang di seluruh dunia berdasarkan lisensi atribusi yang sesuai.' +
            '</p></div>';

        // B. Connector Box
        var editBtn = '<span id="mip-open-editor" style="cursor:pointer; font-size:20px; color:#6a5acd; opacity:0.8; transition:0.3s;" onmouseover="this.style.opacity=1" onmouseout="this.style.opacity=0.8">✎</span>';
        var connectorHtml = '<div id="mip-connector" style="background:#fff; border:1px solid #e2e8f0; border-radius:16px; padding:22px; margin-top:30px; box-shadow:0 10px 25px rgba(0,0,0,0.04);">' +
            '<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">' +
            '<strong style="font-size:15px; color:#1a202c; display:flex; align-items:center; gap:8px;">ID situs</strong>'+editBtn+'</div>' +
            '<div id="mip-display" style="display:flex; gap:12px; flex-wrap:wrap;"><small style="color:#a0aec0;">Mensinkronisasi basis data...</small></div>' +
            '<div id="mip-editor" style="display:none; margin-top:20px; border-top:2px solid #f7fafc; padding-top:20px;">' +
                Object.keys(projects).map(p => '<div style="margin-bottom:12px; display:flex; gap:10px;"><span style="width:75px; font-size:11px; font-weight:bold; background:#edf2f7; display:flex; align-items:center; justify-content:center; border-radius:8px; color:#4a5568;">'+projects[p].name+'</span><input type="text" id="in-'+p+'" placeholder="Judul artikel di '+projects[p].name+'..." style="flex:1; padding:10px; font-size:13px; border:1.5px solid #e2e8f0; border-radius:10px; outline:none; transition:0.2s;" onfocus="this.style.borderColor=\'#6a5acd\'"></div>').join('') +
                '<button id="mip-save" style="width:100%; padding:14px; background:#6a5acd; color:white; border:none; border-radius:12px; font-size:14px; font-weight:bold; cursor:pointer; box-shadow:0 4px 12px rgba(106,90,205,0.3); transition:0.3s;">Terbitkan</button>' +
            '</div></div>';

        // C. Footer Lisensi Lengkap
        var footerHtml = '<div id="mip-footer" style="background:#fafafa; border:1px solid #eee; border-radius:10px; padding:20px; margin-top:30px; text-align:center;">' +
            '<div style="font-size:11px; color:#718096; font-weight:800; text-transform:uppercase; letter-spacing:1px; margin-bottom:10px;">Lisensi, Atribusi & Penggunaan Data</div>' +
            '<p style="margin:0 0 10px; font-size:13px; color:#4a5568; line-height:1.6;">' +
            'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah lisensi resmi ' +
            '<a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" style="color:#6a5acd; text-decoration:none; font-weight:700;">Creative Commons Attribution-ShareAlike 4.0 International</a>.' +
            '</p>' +
            '<p style="margin:0; font-size:12px; color:#a0aec0;">Akses API dan penggunaan data secara massal wajib mencantumkan atribusi kepada <strong>Mippedia Community</strong> selaku pengelola proyek.</p></div>';

        // Injeksi
        $('#mw-content-text').prepend(headerHtml);
        $('#mw-content-text').append(connectorHtml).append(footerHtml);

        // --- 4. LOGIC ENGINE ---
        function loadLinks() {
            new mw.Api().get({ action: 'query', prop: 'revisions', titles: dataPage, rvprop: 'content', formatversion: 2 }).done(function(d) {
                var json = d.query.pages[0].revisions ? JSON.parse(d.query.pages[0].revisions[0].content) : {};
                var data = json[pageTitle] || {};
                var $box = $('#mip-display').empty();
                var found = false;
                Object.keys(projects).forEach(p => {
                    if (data[p]) {
                        found = true;
                        $box.append('<a style="background:'+projects[p].color+'; color:white; padding:8px 16px; border-radius:10px; font-size:12px; font-weight:bold; text-decoration:none; border-bottom:3px solid rgba(0,0,0,0.15);" href="'+projects[p].base+encodeURIComponent(data[p])+'" target="_blank">Mippedia '+projects[p].name+': '+data[p]+'</a>');
                        $('#in-' + p).val(data[p]);
                    }
                });
                if (!found) $box.html('<em style="color:#cbd5e0; font-size:13px;">Entitas ini belum terhubung ke cabang Mippedia manapun.</em>');
            });
        }

        $(document).on('click', '#mip-save', function() {
            // CEK IZIN: Tolak user biasa
            if (!isAdmin) {
                showBoxNotif('Suntingan anda tidak di terbitkan', 'Halaman ini dilindungi. Hanya <b>Pengurus</b> yang memiliki otoritas untuk memodifikasi metadata ekosistem secara langsung.', 'error');
                return;
            }

            var $btn = $(this).text('Sedang Memvalidasi...').prop('disabled', true);
            var api = new mw.Api();
            var newData = {}, promises = [], invalid = [], isDel = true;

            Object.keys(projects).forEach(p => {
                var v = $('#in-' + p).val().trim();
                if (v) {
                    isDel = false;
                    promises.push($.ajax({ url: projects[p].url, data: { action: 'query', titles: v, format: 'json', origin: '*' }, dataType: 'json' }).done(function(res){
                        if (res.query.pages["-1"]) invalid.push(projects[p].name); else newData[p] = v;
                    }));
                }
            });

            $.when.apply($, promises).then(function() {
                if (invalid.length > 0) {
                    showBoxNotif('Suntingan anda tidak di terbitkan', 'Artikel dengan judul tersebut tidak ditemukan di basis data Mippedia cabang: ' + invalid.join(', ') + '. Periksa kembali ejaan dan kapitalisasi.', 'error');
                    $btn.text('Terbitkan').prop('disabled', false); return;
                }
                
                api.get({ action: 'query', prop: 'revisions', titles: dataPage, rvprop: 'content', formatversion: 2 }).done(function(r) {
                    var full = r.query.pages[0].revisions ? JSON.parse(r.query.pages[0].revisions[0].content) : {};
                    if (isDel) delete full[pageTitle]; else full[pageTitle] = newData;
                    
                    api.postWithEditToken({ action: 'edit', title: dataPage, text: JSON.stringify(full, null, 2), summary: 'Sync Metadata: ' + pageTitle })
                    .done(function() {
                        showBoxNotif('Suntingan anda berhasil di terbitkan!', 'Metadata entitas berhasil disinkronisasi ke seluruh jaringan ekosistem Mippedia.', 'success');
                        setTimeout(function(){ location.reload(); }, 1500);
                    }).fail(function(c) {
                        showBoxNotif('Gagal Menyimpan', 'Terjadi kesalahan pada token API atau koneksi server. Kode: ' + c, 'error');
                        $btn.text('Simpan & Sinkronkan Data').prop('disabled', false);
                    });
                });
            });
        });

        $(document).on('click', '#mip-open-editor', function() { $('#mip-editor').slideToggle(); });
        loadLinks();
    });
})();

(function() {
    // Fungsi utama suntik teks
    function forcePreload() {
        var ns = mw.config.get('wgNamespaceNumber');
        var pageExists = mw.config.get('wgArticleId') > 0;
        
        // Cek Namespace Utama & Halaman Baru
        if (ns === 0 && !pageExists) {
            // Cari textarea secara spesifik (Desktop & Mobile punya selector beda)
            var $textbox = $('#wpTextbox1, textarea.mw-ui-input, .editor-container textarea');
            
            if ($textbox.length && $textbox.val().trim() === "") {
                var pageName = mw.config.get('wgTitle');
                $textbox.val('{{Infobox umum\n|nama = ' + pageName + '\n}}');
                console.log("Mippedia: Infobox injected!");
            }
        }
    }

    // 1. Jalankan pas halaman beres load
    $(document).ready(forcePreload);

    // 2. Jalankan tiap ada klik (karena mobile buka editor pake klik tanpa refresh)
    $(document).on('click', function() {
        setTimeout(forcePreload, 800); // Kasih delay dikit nunggu overlay muncul
    });

    // 3. Pake MutationObserver buat mantau elemen yang baru muncul secara gaib
    var observer = new MutationObserver(function() {
        forcePreload();
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();

/* ==========================================================
   🚀 MIPPEDIA DATA - CONTENT GUARD (MODIFIED FOR RELATED)
   ========================================================== */
(function() {
    function handleBlock(e) {
        var ns = mw.config.get('wgNamespaceNumber');
        if (ns !== 0 || mw.config.get('wgIsMainPage')) return;

        var $el = $(e.currentTarget);
        
        if ($el.closest('.mw-parser-output').length && $el.text().toLowerCase().includes('buat item')) {
            return; 
        }

        var $textbox = $('#wpTextbox1, .editor-container textarea, textarea.mw-ui-input');
        
        if ($textbox.length) {
            var content = $textbox.val() || "";
            
            // Pengecekan: Harus ada {{Infobox ATAU setidaknya ada kode #related
            var hasInfobox = content.includes('{{Infobox');
            var hasRelated = content.includes('#related:');

            if (!hasInfobox && !hasRelated) {
                e.preventDefault();
                e.stopPropagation();
                e.stopImmediatePropagation();

                window.alert("SUNTINGAN ANDA TIDAK BISA DI TERBITKAN!\n\nMippedia Data bukan tempat untuk menulis artikel ensiklopedia, Jika anda ingin membuat artikel ensiklopedia bukan di sini tempat nya.\n");
                return false;
            }
        }
    }

    $(document).on('click mousedown touchstart', 
        '#wpSave, .editor-save, .mw-ui-button.primary, button[type="submit"], .save-button, .header-action button', 
        function(e) {
            handleBlock(e);
        }
    );

    window.addEventListener('submit', function(e) {
        handleBlock(e);
    }, true);
})();

/* ==========================================================
   🛡️ MIPPEDIA CORE SYSTEM - NEURAL ENGINE V12
   Update: Brain Upgrade - Semantic Search & Anti-Duplicate
   Semua fitur asli (Patroli, Promo, Kategori) tetap UTUH.
   ========================================================== */
mw.hook('postEdit').add(function() {
    var rawUser = mw.config.get('wgUserName');
    var userName = rawUser ? rawUser.replace(/_/g, ' ') : 'Anonim';
    var isPatroli = (userName === 'Admin');
    
    if (mw.config.get('wgNamespaceNumber') !== 0) return;

    var api = new mw.Api();
    var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' ');

    api.get({
        action: 'query',
        titles: pageTitle,
        prop: 'revisions|categories|links',
        rvprop: 'content',
        clshow: '!hidden',
        pllimit: 'max'
    }).done(function(resData) {
        var page = resData.query.pages[Object.keys(resData.query.pages)[0]];
        if (!page || !page.revisions) return;

        var rawContent = page.revisions[0]['*'];
        var content = rawContent;
        var summaryParts = [];

        // --- 2. SUPER INTELLIGENCE RELATED (UPGRADE OTAK V12) ---
        // Cek jumlah related saat ini
        var currentRelatedMatch = content.match(/\{\{#related:.*?\}\}/g) || [];
        
        // Jika kurang dari 3, kita jalankan otak pencarian canggih
        if (currentRelatedMatch.length < 3) {
            // Hapus yang lama dulu agar tidak ada duplikat atau "pake yang bekas"
            content = content.replace(/\n*\{\{#related:.*?\}\}/g, '');

            // Langkah A: Ambil kandidat dari Search Engine (Ranking Skor)
            api.get({
                action: 'query',
                list: 'search',
                srsearch: pageTitle, // Gunakan judul sebagai basis pencarian semantic
                srlimit: 15,
                srprop: ''
            }).done(function(searchRes) {
                var candidates = {};

                // Masukkan hasil pencarian ke pool skor
                if (searchRes.query && searchRes.query.search) {
                    searchRes.query.search.forEach(function(item, index) {
                        if (item.title === pageTitle) return;
                        candidates[item.title] = (15 - index); // Skor berdasarkan urutan relevansi
                    });
                }

                // Langkah B: Tambah skor jika artikel ada di daftar Link Internal
                if (page.links) {
                    page.links.forEach(function(link) {
                        if (link.title === pageTitle) return;
                        candidates[link.title] = (candidates[link.title] || 0) + 5; // Bonus skor link
                    });
                }

                // Langkah C: Urutkan berdasarkan skor tertinggi (yang paling nyambung)
                var sortedTitles = Object.keys(candidates).sort(function(a, b) {
                    return candidates[b] - candidates[a];
                });

                // Ambil TOP 3
                var finalRelated = sortedTitles.filter(t => t.indexOf(':') === -1).slice(0, 3);

                if (finalRelated.length > 0) {
                    var relatedTags = '\n\n' + finalRelated.map(t => '{{#related: ' + t + '}}').join('\n');
                    content += relatedTags;
                    summaryParts.push('NeuralRelated');
                }
                
                runPatroliAndSave();
            });
        } else {
            runPatroliAndSave();
        }

        function runPatroliAndSave() {
            // --- 3. PATROLI ENGINE (FITUR ASLI - TETAP BERFUNGSI) ---
            if (isPatroli) {
                var placeholders = [];
                // Lindungi Brankas: Template, Header, Kategori, Ref, dan Kalimat Pembuka
                content = content.replace(/(\{\{[\s\S]*?\}\}|==+.*?==+|\[\[Kategori:.*?\]\]|<ref[\s\S]*?<\/ref>|^.*?adalah)/gi, function(match) {
                    placeholders.push(match);
                    return '___MIP_SKIP_' + (placeholders.length - 1) + '___';
                });

                // Proses Auto-Link (Wajib ambil daftar AllPages dulu)
                api.get({ action: 'query', list: 'allpages', apnamespace: 0, aplimit: 'max' }).done(function(apData) {
                    var allTitles = apData.query.allpages.map(p => p.title);
                    var lowerTitles = allTitles.map(t => t.toLowerCase());

                    var tokens = content.split(/(\s+|\[\[|\]\])/);
                    var inLink = false;
                    for (var i = 0; i < tokens.length; i++) {
                        if (tokens[i] === '[[' ) { inLink = true; continue; }
                        if (tokens[i] === ']]' ) { inLink = false; continue; }
                        if (inLink || tokens[i].trim().length < 3 || tokens[i].includes('___MIP_SKIP_')) continue;

                        var wordsInToken = tokens[i].match(/\b\w+\b/g);
                        if (wordsInToken) {
                            wordsInToken.forEach(function(word) {
                                var idx = lowerTitles.indexOf(word.toLowerCase());
                                if (idx !== -1 && allTitles[idx] !== pageTitle) {
                                    tokens[i] = tokens[i].replace(new RegExp('\\b' + word + '\\b', 'g'), '[[' + allTitles[idx] + '|' + word + ']]');
                                }
                            });
                        }
                    }
                    content = tokens.join('');
                    
                    // Kembalikan dari Brankas
                    content = content.replace(/___MIP_SKIP_(\d+)___/g, function(match, id) { return placeholders[id]; });

                    // Bersihkan Link Merah
                    content = content.replace(/\[\[([^|\]:]+)\]\]/g, function(match, p1) {
                        return lowerTitles.includes(p1.toLowerCase()) ? match : p1;
                    });

                    saveAction();
                });
            } else {
                saveAction();
            }
        }

        function saveAction() {
            // --- 4. EKSEKUSI ---
            if (content.trim() !== rawContent.trim()) {
                api.postWithToken('edit', {
                    action: 'edit',
                    title: pageTitle,
                    text: content,
                    summary: 'Mippedia Neural Engine V12: ' + summaryParts.join(', '),
                    bot: true, markasbot: true
                }).done(function() { location.reload(); });
            }
        }
    });
});

/* ==========================================================
   🌐 MIPPEDIA SHORTDESC - DATA CENTER (PREMIUM UI)
   Status: INDEPENDENT & REFINED VISUAL
   Storage: MediaWiki:ShortDesc-Data.json
   ========================================================== */
(function($, mw) {
    "use strict";
    $(document).ready(function() {
        if (mw.config.get('wgNamespaceNumber') !== 0 || mw.config.get('wgIsMainPage')) return;

        var pageTitle = mw.config.get('wgPageName');
        var storagePage = 'MediaWiki:ShortDesc-Data.json';
        var isAdmin = mw.config.get('wgUserGroups').some(g => ['sysop', 'interface-admin'].includes(g));

        var langs = {
            id: { label: 'Mippedia bahasa Indonesia', short: 'ID', color: '#6366f1' },
            en: { label: 'Mippedia bahasa Inggris', short: 'EN', color: '#3b82f6' },
            concise: { label: 'Mippedia bahasa Indonesia ringkas', short: 'CON', color: '#14b8a6' }
        };

        // UI Box dengan Spasi dan Desain Baru
        var html = `
            <div id="desc-manager" style="background:#ffffff; border:1px solid #f1f5f9; border-left:4px solid #6366f1; border-radius:12px; padding:20px; margin: 20px 0 25px 0; box-shadow:0 4px 12px rgba(0,0,0,0.03); font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
                    <span style="font-size:13px; font-weight:700; color:#475569; text-transform:uppercase; letter-spacing:0.5px; display:flex; align-items:center; gap:6px;">
                        Label Deskripsi
                    </span>
                    <span id="desc-open-editor" style="cursor:pointer; padding:5px; transition:0.2s;" title="Edit Deskripsi">
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>
                    </span>
                </div>
                
                <div id="desc-status-display" style="display:flex; flex-direction:column; gap:8px;">
                    <small style="color:#94a3b8; font-style:italic;">Sinkronisasi data...</small>
                </div>

                <div id="desc-editor" style="display:none; margin-top:18px; border-top:1px dashed #e2e8f0; padding-top:18px;">
                    ${Object.keys(langs).map(k => `
                        <div style="margin-bottom:12px;">
                            <label style="display:block; font-size:11px; font-weight:bold; color:#64748b; margin-bottom:4px;">${langs[k].label}</label>
                            <input type="text" id="desc-in-${k}" placeholder="Tulis deskripsi..." style="width:100%; padding:10px; font-size:13px; border:1px solid #e2e8f0; border-radius:8px; box-sizing:border-box; outline:none; focus:border-color:#6366f1;">
                        </div>
                    `).join('')}
                    <button id="desc-save" style="width:100%; padding:12px; background:#6366f1; color:white; border:none; border-radius:8px; font-size:13px; font-weight:600; cursor:pointer; margin-top:5px;">Terbitkan</button>
                </div>
            </div>`;

        $('.mw-parser-output').prepend(html);

        function loadDescStatus() {
            new mw.Api().get({ action: 'query', prop: 'revisions', titles: storagePage, rvprop: 'content', formatversion: 2 }).done(function(res) {
                var content = res.query.pages[0].revisions ? res.query.pages[0].revisions[0].content : "{}";
                var fullData = JSON.parse(content);
                var myData = fullData[pageTitle] || {};
                var $statusBox = $('#desc-status-display').empty();
                var foundAny = false;

                Object.keys(langs).forEach(k => {
                    var val = myData[k];
                    if (val && val.trim() !== "") {
                        foundAny = true;
                        $statusBox.append(`
                            <div style="display:flex; align-items:center; gap:10px;">
                                <span style="background:${langs[k].color}15; color:${langs[k].color}; padding:3px 10px; border-radius:20px; font-size:10px; font-weight:800; border:1px solid ${langs[k].color}30; min-width:35px; text-align:center;">${langs[k].short}</span>
                                <span style="font-size:13px; color:#334155; line-height:1.4;">${val}</span>
                            </div>
                        `);
                        $('#desc-in-' + k).val(val);
                    }
                });

                if (!foundAny) {
                    $statusBox.html('<div style="color:#cbd5e0; font-size:13px; background:#f8fafc; padding:10px; border-radius:8px; border:1px dashed #e2e8f0;">Belum ada metadata deskripsi yang dikaitkan dengan entitas ini.</div>');
                }
            });
        }

        $(document).on('click', '#desc-open-editor', function() { $('#desc-editor').slideToggle(); });

        $(document).on('click', '#desc-save', function() {
            if (!isAdmin) { alert('Akses ditolak. Anda memerlukan izin pengurus.'); return; }
            var $btn = $(this).text('Proses Sinkronisasi...').css('opacity','0.7');
            var api = new mw.Api();
            var newData = { id: $('#desc-in-id').val().trim(), en: $('#desc-in-en').val().trim(), concise: $('#desc-in-concise').val().trim() };

            api.get({ action: 'query', prop: 'revisions', titles: storagePage, rvprop: 'content', formatversion: 2 }).done(function(r) {
                var json = r.query.pages[0].revisions ? JSON.parse(r.query.pages[0].revisions[0].content) : {};
                if (!newData.id && !newData.en && !newData.concise) { delete json[pageTitle]; } else { json[pageTitle] = newData; }

                api.postWithEditToken({
                    action: 'edit',
                    title: storagePage,
                    text: JSON.stringify(json, null, 2),
                    summary: 'Update Entity Description: ' + pageTitle
                }).done(function() { location.reload(); });
            });
        });

        loadDescStatus();
    });
})(jQuery, mediaWiki);

/* ==========================================================
   📍 MIPPEDIA DATA - ULTIMATE TEXT-TO-MAP LOCATOR
   Fitur: Deteksi lokasi dari teks dengan database label lengkap
   ========================================================== */
(function() {
    $(document).ready(function() {
        var locationText = "";
        
        // --- DAFTAR LABEL SUPER LENGKAP & MASUK AKAL ---
        var locationLabels = [
            // Umum & Geografis
            'lokasi', 'tempat', 'wilayah', 'daerah', 'koordinat', 'alamat',
            // Orang (Biografi)
            'tempat lahir', 'asal', 'kediaman', 'domisili', 'negara asal',
            // Organisasi & Perusahaan
            'kantor pusat', 'markas', 'cabang utama', 'titik operasi',
            // Makanan & Budaya
            'asal wilayah', 'daerah asal', 'negara sumber', 'kawasan',
            // Sejarah & Bangunan
            'letak', 'posisi', 'titik temu', 'orbit'
        ];

        // Jalankan pencarian di tabel data (infobox atau wikitable)
        $('.wikitable tr, .infobox tr, .mip-data-table tr').each(function() {
            var label = $(this).find('th').text().toLowerCase().trim();
            // Hilangkan karakter spesial kayak titik dua biar matching-nya akurat
            label = label.replace(/[:]/g, '');

            var isMatch = locationLabels.some(function(target) {
                return label === target || label.includes(target);
            });

            if (isMatch) {
                var rawValue = $(this).find('td').text().trim();
                // Ambil bagian utama sebelum tanda koma, kurung, atau titik koma
                // Misal: "Bandung, Jawa Barat" -> ambil "Bandung"
                locationText = rawValue.split(/[,(\[;]/)[0].trim(); 
                
                if (locationText.length > 2) return false; // Stop jika sudah ketemu yang valid
            }
        });

        // Eksekusi Render Peta
        if (locationText && locationText.length > 2) {
            var $mapWrapper = $('<div>').css({
                'margin': '15px 0',
                'padding': '12px',
                'border': '1px solid #ddd',
                'background': '#ffffff',
                'border-radius': '10px',
                'box-shadow': '0 4px 12px rgba(0,0,0,0.08)'
            });

            $mapWrapper.append('<div style="font-weight:bold; font-size:0.9em; margin-bottom:10px; color:#444; display:flex; align-items:center;">' +
                               '<span style="margin-right:8px;">🗺️</span>Pratinjau Lokasi : ' + locationText + '</div>');

            // Embed URL dengan pencarian teks (Nominatim)
            var embedUrl = "https://www.openstreetmap.org/export/embed.html?layer=mapnik&q=" + encodeURIComponent(locationText);

            var $iframe = $('<iframe>').attr({
                'src': embedUrl,
                'width': '100%',
                'height': '280',
                'frameborder': '0',
                'style': 'border-radius: 8px; border: 1px solid #eee;'
            });

            $mapWrapper.append($iframe);
            
            // Link eksternal yang lebih rapi
            var gMapsUrl = "https://www.google.com/maps/search/" + encodeURIComponent(locationText);
            $mapWrapper.append('<div style="text-align:right; margin-top:8px;">' +
                               '<a href="' + gMapsUrl + '" target="_blank" style="font-size:0.75em; color:#6a5acd; font-weight:bold; text-decoration:none; text-transform:uppercase; letter-spacing:0.5px;">Buka di Google Maps →</a></div>');

            // Masukkan ke bawah section deskripsi otomatis
            if ($('#mip-desc-section').length) {
                $('#mip-desc-section').after($mapWrapper);
            }
        }
    });
})();