Lompat ke isi

MediaWiki:Common.js: Perbedaan antara revisi

Dari Mippedia bahasa Indonesia, ensiklopedia umum
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Tidak ada ringkasan suntingan
Tanda: Pengembalian manual Suntingan perangkat seluler Suntingan peramban seluler
 
(90 revisi perantara oleh 2 pengguna tidak ditampilkan)
Baris 1: Baris 1:
/* Script Estimasi Waktu Baca - Spesialis Mobile (Minerva) & Desktop */
/* Script Estimasi Waktu Baca - Spesialis Mobile (Minerva) & Desktop */
$(document).ready(function() {
$(document).ready(function() {
     // Hanya jalan di halaman artikel asli
     // Hanya jalan di halaman artikel asli dan BUKAN di Halaman Utama
     if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view' && mw.config.get('wgNamespaceNumber') === 0) {
     if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view' && mw.config.get('wgNamespaceNumber') === 0 && !mw.config.get('wgIsMainPage')) {
          
          
         function hitungWaktuBaca() {
         function hitungWaktuBaca() {
Baris 15: Baris 15:
             // Bikin elemen tampilannya
             // Bikin elemen tampilannya
             var icon = '🕒'; // Emoji jam biar simpel dan ringan
             var icon = '🕒'; // Emoji jam biar simpel dan ringan
             var label = (readingTime <= 1) ? 'Kurang dari 1 menit' : readingTime + ' menit';
             var label = (readingTime <= 1) ? '- 1 menit' : readingTime + ' menit';
              
              
             var html = '<div id="reading-time-auto" style="font-size: 0.9em; color: #54595d; margin-bottom: 15px; display: flex; align-items: center; font-family: sans-serif;">';
             var html = '<div id="reading-time-auto" style="font-size: 0.9em; color: #54595d; margin-bottom: 15px; display: flex; align-items: center; font-family: sans-serif;">';
             html += '<span style="margin-right: 5px;">' + icon + '</span>';
             html += '<span style="margin-right: 5px;">' + icon + '</span>';
             html += '<span>Estimasi waktu baca: <b>' + label + '</b></span>';
             html += '<span>Estimasi waktu baca : <b>' + label + '</b></span>';
             html += '</div>';
             html += '</div>';


Baris 36: Baris 36:
     }
     }
});
});


/* Script Tombol Back to Top (Spesial Mobile) */
/* Script Tombol Back to Top (Spesial Mobile) */
Baris 59: Baris 58:
     });
     });
});
});
/* Smart Glossary Pop-up (Pratinjau Link Ringan) */
$(document).ready(function() {
    if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view') {
       
        var timer;
        // Targetkan link di dalam konten artikel saja
        $('#mw-content-text a').on('mouseenter touchstart', function(e) {
            var $link = $(this);
            var title = $link.attr('title');
           
            // Jangan jalan kalau link-nya bukan artikel (misal link luar atau redlink)
            if (!title || $link.hasClass('new') || $link.hasClass('external')) return;
            timer = setTimeout(function() {
                $.getJSON(mw.util.wikiScript('api'), {
                    action: 'query',
                    prop: 'extracts',
                    exintro: true,
                    exsentences: 2, // Ambil 2 kalimat aja biar singkat
                    titles: title,
                    explaintext: true,
                    format: 'json'
                }, function(data) {
                    var pages = data.query.pages;
                    var pageId = Object.keys(pages)[0];
                    var extract = pages[pageId].extract;
                    if (extract) {
                        // Hapus pop-up lama kalau ada
                        $('.wiki-preview').remove();
                        var preview = $('<div class="wiki-preview" style="position:absolute; background:#fff; color:#202122; border:1px solid #a2a9b1; padding:12px; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.2); z-index:10001; font-size:13px; max-width:250px; line-height:1.4; opacity:0; transition:opacity 0.3s ease;"></div>');
                        preview.text(extract);
                       
                        $('body').append(preview);
                        // Atur posisi pop-up di deket link
                        var offset = $link.offset();
                        preview.css({
                            top: offset.top + 25,
                            left: Math.min(offset.left, $(window).width() - 270),
                            opacity: 1
                        });
                        // Hilang kalau klik di mana aja atau setelah 5 detik
                        setTimeout(function() { $('.wiki-preview').fadeOut(function() { $(this).remove(); }); }, 5000);
                    }
                });
            }, 600); // Delay 0.6 detik biar gak ganggu kalau cuma scrolling lewat
        }).on('mouseleave', function() {
            clearTimeout(timer);
        });
        $(document).on('mousedown touchstart', function() {
            $('.wiki-preview').remove();
        });
    }
});
/* 3. Notifikasi Link Luar */
$(document).ready(function() {
    $('a.external').click(function(e) {
        var url = $(this).attr('href');
        if (!confirm('Anda akan meninggalkan Mippedia menuju situs luar:\n' + url + '\n\nLanjutkan?')) {
            e.preventDefault();
        }
    });
});


/* 3. Anti-Ghosting pada Link Kosong (Redlinks) */
/* 3. Anti-Ghosting pada Link Kosong (Redlinks) */
Baris 139: Baris 67:
         }
         }
     });
     });
});
/* 1. Navigasi Bab Melayang (Vertical Stack Edition) */
$(document).ready(function() {
    if (mw.config.get('wgIsArticle') && $('#toc').length) {
       
        // CSS untuk posisi menumpuk secara vertikal
        var $quickNav = $('<div id="quick-nav" style="position:fixed; bottom:20px; right:20px; width:45px; height:45px; background:#36c; color:#fff; border-radius:50%; display:flex; align-items:center; justify-content:center; z-index:9996; box-shadow:0 4px 12px rgba(0,0,0,0.2); cursor:pointer; font-size:20px; transition: all 0.3s ease;">≡</div>');
       
        // Tombol Back to Top lo biasanya di bottom: 80px atau 90px kan?
        // Kita paksa Back to Top naik sedikit, dan navigasi bab ada di bawahnya.
        // Script ini bakal otomatis menyesuaikan posisi tombol panah atas lo.
       
        $('body').append($quickNav);
        // Menyesuaikan posisi tombol Back to Top bawaan (jika ada) biar gak tabrakan
        // Kita set navigasi di bottom 20px, dan Back to Top di bottom 80px
        $('.back-to-top, #mw-mf-back-to-top').css('bottom', '85px');
        $quickNav.click(function() {
            var $toc = $('#toc ul').first().clone();
            var $modal = $('<div id="nav-modal" style="position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:20001; display:flex; align-items:flex-end; justify-content:center; backdrop-filter:blur(5px); opacity:0; transition:opacity 0.3s ease;">' +
                '<div id="nav-card" style="background:#fff; width:100%; max-height:75%; overflow-y:auto; border-top-left-radius:30px; border-top-right-radius:30px; padding:25px; transform:translateY(100%); transition:transform 0.4s cubic-bezier(0.23, 1, 0.32, 1);">' +
                '<div style="width:50px; height:5px; background:#eee; border-radius:10px; margin:0 auto 20px;"></div>' +
                '<h3 style="margin-top:0; color:#36c; font-size:1.3em; text-align:center;">Daftar Isi</h3>' +
                '<div id="nav-list" style="margin-top:10px;"></div>' +
                '</div></div>');
           
            $('body').append($modal);
            $modal.find('#nav-list').append($toc);
           
            setTimeout(function() {
                $modal.css('opacity', '1');
                $modal.find('#nav-card').css('transform', 'translateY(0)');
            }, 10);
            // Styling link agar terasa seperti menu aplikasi
            $modal.find('a').css({
                'display':'block',
                'padding':'15px 10px',
                'color':'#333',
                'text-decoration':'none',
                'border-bottom':'1px solid #f9f9f9',
                'font-size':'1.1em'
            });
            function closeModal() {
                $modal.find('#nav-card').css('transform', 'translateY(100%)');
                $modal.css('opacity', '0');
                setTimeout(function() { $modal.remove(); }, 400);
            }
            $modal.on('click', function(e) { if(e.target === this) closeModal(); });
        });
    }
});
/* 2. Auto-Night Shift (Berdasarkan Jam Lokal) */
$(document).ready(function() {
    var hour = new Date().getHours();
    if (hour >= 21 || hour < 6) { // Jam 9 malem sampe 6 pagi
        $("<style id='night-shift'>").prop("type", "text/css").html(`
            body::after {
                content: "";
                position: fixed;
                top: 0; left: 0;
                width: 100vw; height: 100vh;
                background: rgba(255, 165, 0, 0.05); /* Filter orange tipis */
                pointer-events: none;
                z-index: 99999;
            }
        `).appendTo("head");
    }
});
/* 3. Smooth Fade-In saat Ganti Halaman */
$(document).ready(function() {
    $('body').css({'opacity': '0', 'transition': 'opacity 0.5s ease'});
    setTimeout(function() { $('body').css('opacity', '1'); }, 100);
});
/* 2. Auto-Source on Copy (Kredit Otomatis) */
document.addEventListener('copy', function(e) {
    var selection = window.getSelection();
    if (selection.toString().length > 1) { // Hanya aktif kalau copy lebih dari 50 karakter
        var body_element = document.getElementsByTagName('body')[0];
        var newdiv = document.createElement('div');
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';
        body_element.appendChild(newdiv);
        newdiv.innerHTML = selection + '<br /><br />Sumber: ' + document.title + '<br />Link: ' + window.location.href;
        selection.selectAllChildren(newdiv);
        window.setTimeout(function() {
            body_element.removeChild(newdiv);
        }, 0);
    }
});
/* ==========================================================
  🚀 MIPPEDIA DATA INTEGRATION (Global Version)
  Berfungsi untuk: User Login & Anonim
  Posisi: Di bawah Estimasi Waktu Baca (Header)
  ========================================================== */
$(document).ready(function() {
    function injectMippediaData() {
        // 1. Cari template asli
        var $dataTemplate = $('.mw-parser-output div:contains("Mippedia Data")').first();
        var dataUrl = $dataTemplate.find('a').attr('href');
        // 2. Jika ketemu dan belum pernah di-inject sebelumnya
        if ($dataTemplate.length && dataUrl && $('#mippedia-data-btn').length === 0) {
           
            // Buat tombol bergaya metadata yang premium
            var $newBtn = $(`
                <div id="mippedia-data-btn" style="margin: 10px 0; display: inline-block;">
                    <a href="${dataUrl}" target="_blank" style="text-decoration: none !important;">
                        <div style="display: flex; align-items: center; background: #36c; color: #fff; padding: 6px 12px; border-radius: 8px; font-family: sans-serif; box-shadow: 0 4px 10px rgba(54,102,204,0.25);">
                            <span style="font-size: 14px; margin-right: 8px;"></span>
                            <span style="font-size: 11px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase;">Lihat di Mippedia Data</span>
                        </div>
                    </a>
                </div>
            `);
            // 3. PENEMPATAN POSISI (Target: Di bawah estimasi waktu baca)
            var $targetHeader = $('.tagline, .minerva__subtitle, .estimasi-baca-container');
           
            if ($targetHeader.length) {
                // Taruh tepat di bawah estimasi waktu baca atau subtitle
                $targetHeader.last().after($newBtn);
                // Hapus template lama dari dalam artikel agar tidak dobel
                $dataTemplate.hide();
            } else {
                // Fallback: Jika header tidak ketemu, taruh di bawah judul utama
                $('#firstHeading').after($newBtn);
                $dataTemplate.hide();
            }
        }
    }
    // Jalankan segera dan ulangi sekali lagi untuk memastikan render mobile selesai
    injectMippediaData();
    setTimeout(injectMippediaData, 1500);
});
/* Smart Random Toaster Mippedia (Fixed: Article & Main Page Only) */
$(document).ready(function() {
    var ns = mw.config.get('wgNamespaceNumber');
    var action = mw.config.get('wgAction');
    var isMainPage = mw.config.get('wgIsMainPage');
    var isDiff = mw.config.get('wgDiffOldId') !== null;
    // VALIDASI: Cuma di Artikel (NS 0), Halaman Utama, dan saat 'View' saja
    if ((ns === 0 || isMainPage) && action === 'view' && !isDiff) {
       
        var mippediaDatabase = [
            // KATEGORI: FAKTA UNIK (💡)
            { type: "💡 FAKTA UNIK", text: "Mippedia adalah proyek ensiklopedia mandiri yang berfokus pada sejarah, musik, dan teknologi." },
            { type: "💡 FAKTA UNIK", text: "Rumi Haitami, pendiri Mippedia, adalah musisi dan pengusaha muda asal Indonesia." },
            { type: "💡 FAKTA UNIK", text: "Nama 'Mippedia' merepresentasikan identitas kolektif dari Mippedia Community." },
            { type: "💡 FAKTA UNIK", text: "Mippedia tidak berafiliasi dengan Wikimedia Foundation dan mengelola server secara mandiri." },
            { type: "💡 FAKTA UNIK", text: "Sugar Store Id merupakan bagian dari ekosistem bisnis yang dikembangkan pendiri Mippedia." },
            { type: "💡 FAKTA UNIK", text: "Mippedia memiliki ribuan item data yang terhubung melalui sistem Mippedia Data." },
            { type: "💡 FAKTA UNIK", text: "Proyek ini dimulai dengan visi untuk mendokumentasikan pengetahuan secara profesional dan bebas." },
            { type: "💡 FAKTA UNIK", text: "Logo Mippedia melambangkan integrasi ilmu pengetahuan global dan lokal." },
            { type: "💡 FAKTA UNIK", text: "Mippedia Community terdiri dari kontributor yang ahli di bidang teknologi dan dokumentasi digital." },
            { type: "💡 FAKTA UNIK", text: "Selain ensiklopedia, ekosistem Mippedia juga mencakup label rekaman musik." },
            { type: "💡 FAKTA UNIK", text: "Mippedia mendukung standarisasi Wikidata untuk sinkronisasi informasi tokoh." },
            { type: "💡 FAKTA UNIK", text: "Setiap artikel di sini melewati proses kurasi oleh tim administrator Mippedia." },
            { type: "💡 FAKTA UNIK", text: "Sistem pencarian Mippedia dirancang untuk menemukan artikel dalam hitungan milidetik." },
            { type: "💡 FAKTA UNIK", text: "Mippedia menggunakan platform MediaWiki yang telah dimodifikasi secara ekstrim untuk kenyamanan pengguna." },
            { type: "💡 FAKTA UNIK", text: "Warna biru pada tema Mippedia melambangkan kepercayaan, profesionalisme, dan teknologi." },
            { type: "💡 FAKTA UNIK", text: "Mippedia adalah salah satu proyek wiki independen terbesar yang dikelola oleh komunitas lokal." },
            { type: "💡 FAKTA UNIK", text: "Konten musik di Mippedia mencakup diskografi lengkap dari artis-artis di bawah label Mippedia." },
            { type: "💡 FAKTA UNIK", text: "Mippedia menyediakan portal khusus bagi administrator untuk mengelola sistem secara real-time." },
            { type: "💡 FAKTA UNIK", text: "Data kelahiran dan riwayat tokoh di Mippedia diambil dari sumber primer yang tervalidasi." },
            { type: "💡 FAKTA UNIK", text: "Mippedia sering melakukan pembaruan sistem pesan sistem untuk menjaga keamanan komunitas." },
            { type: "💡 FAKTA UNIK", text: "User interface Mippedia dioptimasi agar ramah bagi pengguna perangkat mobile." },
            { type: "💡 FAKTA UNIK", text: "Mippedia memiliki kebijakan privasi yang ketat untuk melindungi data setiap pembacanya." },
            { type: "💡 FAKTA UNIK", text: "Sistem 'Dengarkan Artikel' di Mippedia menggunakan teknologi sintesis suara yang jernih." },
            { type: "💡 FAKTA UNIK", text: "Mippedia secara aktif mengarsipkan dokumen sejarah yang jarang ditemukan di tempat lain." },
            { type: "💡 FAKTA UNIK", text: "Setiap gambar yang diunggah ke Mippedia disimpan dalam repositori lokal yang aman." },
            // KATEGORI: INFORMASI (ℹ️)
            { type: "ℹ️ INFORMASI", text: "Anda dapat mendengarkan isi artikel ini dengan mengklik ikon 🔊 di bagian atas halaman." },
            { type: "ℹ️ INFORMASI", text: "Klik ikon ≡ di pojok kanan bawah untuk melihat daftar isi dan melompat antar bagian." },
            { type: "ℹ️ INFORMASI", text: "Gunakan fitur 'Back to Top' (ikon panah) untuk kembali ke atas halaman dengan cepat." },
            { type: "ℹ️ INFORMASI", text: "Artikel ini terakhir diperbarui sesuai dengan log aktivitas Mippedia Community." },
            { type: "ℹ️ INFORMASI", text: "Anda bisa membagikan artikel ini melalui tombol share yang tersedia di akhir tulisan." },
            { type: "ℹ️ INFORMASI", text: "Mippedia Data menyediakan basis data teknis yang terhubung dengan artikel ini." },
            { type: "ℹ️ INFORMASI", text: "Aktifkan Mode Malam pada browser Anda untuk pengalaman membaca yang lebih nyaman di Mippedia." },
            { type: "ℹ️ INFORMASI", text: "Seluruh konten di sini dilindungi oleh lisensi Creative Commons BY-SA 4.0." },
            { type: "ℹ️ INFORMASI", text: "Untuk bantuan teknis atau laporan bug, silakan hubungi tim administrator Mippedia." },
            { type: "ℹ️ INFORMASI", text: "Anda bisa melihat estimasi waktu baca artikel tepat di bawah judul halaman." },
            { type: "ℹ️ INFORMASI", text: "Mippedia menyediakan fitur pencarian pintar di header untuk menemukan topik terkait." },
            { type: "ℹ️ INFORMASI", text: "Pastikan Anda melihat bagian 'Referensi' untuk memverifikasi keaslian data artikel." },
            { type: "ℹ️ INFORMASI", text: "Pendaftaran kontributor Mippedia Community dibuka secara berkala melalui pengumuman resmi." },
            { type: "ℹ️ INFORMASI", text: "Sistem Mippedia secara otomatis mendeteksi perangkat Anda untuk memberikan tampilan terbaik." },
            { type: "ℹ️ INFORMASI", text: "Ikon DATA di sebelah tab Pembicaraan akan mengarahkan Anda ke metadata lengkap tokoh tersebut." },
            { type: "ℹ️ INFORMASI", text: "Mippedia menjaga integritas data dengan sistem proteksi halaman dari suntingan anonim berbahaya." },
            { type: "ℹ️ INFORMASI", text: "Anda bisa mengunduh artikel Mippedia dalam format PDF melalui menu aksi di pojok kanan." },
            { type: "ℹ️ INFORMASI", text: "Jaringan Mippedia mencakup berbagai subdomain untuk proyek bahasa yang berbeda." },
            { type: "ℹ️ INFORMASI", text: "Gunakan fitur seleksi teks untuk mencari istilah yang tidak Anda mengerti di dalam Mippedia." },
            { type: "ℹ️ INFORMASI", text: "Pesan toast ini hanya muncul sekali per sesi halaman untuk kenyamanan membaca Anda." },
            { type: "ℹ️ INFORMASI", text: "Mippedia Community berkomitmen menjaga netralitas informasi di setiap artikel sejarah." },
            { type: "ℹ️ INFORMASI", text: "Pembaruan basis data Mippedia dilakukan setiap hari untuk memastikan akurasi informasi." },
            { type: "ℹ️ INFORMASI", text: "Anda dapat melihat riwayat penyuntingan artikel melalui tab 'History' di menu navigasi." },
            { type: "ℹ️ INFORMASI", text: "Mippedia mendukung integrasi media kaya seperti audio dan video berkualitas tinggi." },
            { type: "ℹ️ INFORMASI", text: "Terima kasih telah menjadi bagian dari pembaca setia Mippedia Community!" }
        ];
        var randomItem = mippediaDatabase[Math.floor(Math.random() * mippediaDatabase.length)];
       
        setTimeout(function() {
            if ($('input:focus, textarea:focus').length > 0) return;
            var $toaster = $('<div id="smart-toaster" style="position:fixed; top:25px; left:20px; right:20px; background:rgba(255,255,255,0.98); border-left:5px solid #36c; color:#333; padding:15px; border-radius:12px; z-index:11000; box-shadow:0 10px 30px rgba(0,0,0,0.15); backdrop-filter:blur(10px); display:none; font-family:sans-serif;">' +
                '<div style="color:#36c; font-weight:bold; font-size:11px; margin-bottom:5px; text-transform:uppercase; letter-spacing:1px;">' + randomItem.type + '</div>' +
                '<div style="font-size:13px; line-height:1.4; color:#444;">' + randomItem.text + '</div>' +
                '</div>');
           
            $('body').append($toaster);
            $toaster.slideDown(500).delay(7000).slideUp(500, function() { $(this).remove(); });
        }, 5000);
    }
});
});


Baris 375: Baris 78:
     // Tambah atau hapus di dalam kurung siku ini. Gunakan koma sebagai pemisah.
     // Tambah atau hapus di dalam kurung siku ini. Gunakan koma sebagai pemisah.
     var protectedPages = [
     var protectedPages = [
         "MediaWiki:",
         "MediaWiki:Common.js",
         "Istimewa:Versi"
         "Istimewa:Versi"
     ];
     ];
Baris 478: Baris 181:
         // Ubah judul tab browser
         // Ubah judul tab browser
         document.title = "Akses Dilindungi - Mippedia bahasa Indonesia, ensiklopedia umum";
         document.title = "Akses Dilindungi - Mippedia bahasa Indonesia, ensiklopedia umum";
    }
});
/* ==========================================================
  🛡️ MIPPEDIA FILE VERIFICATION SYSTEM v3.1 (PRECISION)
  Fix: Kotak lebih ramping & Ikon lebih proporsional
  ========================================================== */
$(document).ready(function() {
    if (mw.config.get('wgNamespaceNumber') === 6) {
       
        var $content = $('#mw-content-text');
        var pageText = $content.text();
        var badgeTitle = "";
        var badgeStyle = "";
        if (pageText.includes("Aset Resmi")) {
            badgeTitle = "ASET RESMI";
            badgeStyle = "border: 1px solid #36c; background: #f0f7ff;";
        } else if (pageText.includes("Terverifikasi")) {
            badgeTitle = "TERVERIFIKASI";
            badgeStyle = "border: 1px solid #00af89; background: #e6fffb;";
        }
        if (badgeTitle !== "") {
            // Ukuran gambar dinaikin ke 24px biar lebih jelas centangnya
            var fileName = "Verified_Badge.png";
           
            new mw.Api().parse('[[Berkas:' + fileName + '|24px|link=]]')
                .done(function(renderedImage) {
                    var badgeHTML = `
                        <div id="mippedia-sleek-badge" style="display: inline-flex; align-items: center; border-radius: 8px; padding: 2px 8px; margin: 5px 0 12px 0; height: 32px; box-sizing: border-box; font-family: sans-serif; vertical-align: middle; ${badgeStyle}">
                            <div style="margin-right: 6px; display: flex; align-items: center; justify-content: center; width: 24px;">${renderedImage}</div>
                            <span style="font-weight: 800; font-size: 11px; letter-spacing: 0.5px; color: #1a1a1a; text-transform: uppercase; white-space: nowrap; line-height: 1;">${badgeTitle}</span>
                        </div>
                    `;
                    $('#firstHeading').after(badgeHTML);
                    $('.mippedia-hidden-key').hide();
                });
            $content.find(':contains("Aset Resmi"), :contains("Terverifikasi")').each(function() {
                var $this = $(this);
                if ($this.children().length === 0 && ($this.text().trim() === "Aset Resmi" || $this.text().trim() === "Terverifikasi")) {
                    $this.addClass('mippedia-hidden-key').css('display', 'none');
                }
            });
        }
     }
     }
});
});
Baris 1.191: Baris 847:
         var summaryParts = [];
         var summaryParts = [];


         // --- 1. GLOBAL ENGINE: MAINTENANCE (FITUR ASLI - JANGAN DIHAPUS) ---
         // --- 1. GLOBAL ENGINE: MAINTENANCE (FITUR ASLI) ---
         if ((!page.categories || page.categories.length === 0) && !/\{\{Butuh Kategori/i.test(content) && !/\[\[Kategori:/i.test(content)) {
         if ((!page.categories || page.categories.length === 0) && !/\{\{Butuh Kategori/i.test(content) && !/\[\[Kategori:/i.test(content)) {
             content = '{{Butuh Kategori|date=April 2026}}\n' + content;
             content = '{{Butuh Kategori|date=April 2026}}\n' + content;
             summaryParts.push('+Cat');
             summaryParts.push('+Cat');
         }
         }
       
        // --- UPGRADE ENGINE: DETEKSI SMART STUB PARAMETER & POSISI BAWAH ---
         var wordCount = rawContent.trim().split(/\s+/).length;
         var wordCount = rawContent.trim().split(/\s+/).length;
         if (wordCount < 200 && !/\{\{Artikel Rintisan/i.test(content)) {
         if (wordCount < 200 && !/\{\{Stub/i.test(content) && !/\{\{Artikel Rintisan/i.test(content)) {
             content = '{{Artikel Rintisan}}\n' + content;
             var lowerContent = rawContent.toLowerCase();
             summaryParts.push('+Stub');
            var stubParam = '';
 
            // Mapping Otak Pintar berdasarkan Kata Kunci Semantik (19 Parameter)
            if (/\b(lahir|wafat|tokoh|pria|wanita|biografi|sosok|pahlawan|presiden|menteri)\b/i.test(lowerContent)) {
                stubParam = 'biografi tokoh';
            } else if (/\b(musik|lagu|album|konser|penyanyi|band|vokal|gitar|single|nada)\b/i.test(lowerContent)) {
                stubParam = 'musik';
            } else if (/\b(geografi|negara|kota|desa|kecamatan|kabupaten|provinsi|pulau|gunung|sungai)\b/i.test(lowerContent)) {
                stubParam = 'geografi';
            } else if (/\b(teknologi|komputer|aplikasi|software|hardware|internet|digital|android|sistem|gawai)\b/i.test(lowerContent)) {
                stubParam = 'teknologi';
            } else if (/\b(sejarah|kerajaan|perang|prasasti|arkeo|masa lalu|kuno|dinasti|peristiwa|abad)\b/i.test(lowerContent)) {
                stubParam = 'sejarah';
            } else if (/\b(olahraga|atlet|sepak|bola|stadion|juara|klub|tanding|liga|olimpiade)\b/i.test(lowerContent)) {
                stubParam = 'olahraga';
            } else if (/\b(film|bioskop|aktor|aktris|sutradara|drama|sinema|serial|movie|tayang)\b/i.test(lowerContent)) {
                stubParam = 'film';
            } else if (/\b(perusahaan|pt|perbangkan|bisnis|saham|industri|korporasi|merek|ceo|didirikan)\b/i.test(lowerContent)) {
                stubParam = 'perusahaan';
            } else if (/\b(ilmu pengetahuan|sains|kimia|fisika|matematika|biologi|riset|laboratorium|teori|molekul)\b/i.test(lowerContent)) {
                stubParam = 'ilmu pengetahuan';
            } else if (/\b(seni|lukisan|patung|pameran|budaya|teater|rupa|desain|kriya|estetika)\b/i.test(lowerContent)) {
                stubParam = 'seni';
            } else if (/\b(politik|partai|pemilu|dpr|pemerintah|kebijakan|demokrasi|suara|kampanye|negara)\b/i.test(lowerContent)) {
                stubParam = 'politik';
            } else if (/\b(militer|tni|tentara|perang|senjata|pasukan|jenderal|alutsista|batalyon|operasi)\b/i.test(lowerContent)) {
                stubParam = 'militer';
            } else if (/\b(transportasi|kereta|pesawat|mobil|kapal|bandara|stasiun|pelabuhan|rute|kendaraan)\b/i.test(lowerContent)) {
                stubParam = 'transportasi';
            } else if (/\b(literatur|buku|novel|puisi|sastra|penulis|penerbit|komik|cerpen|fiksi)\b/i.test(lowerContent)) {
                stubParam = 'literatur';
            } else if (/\b(makanan|kuliner|resep|masakan|minuman|rasa|koki|restoran|hidangan|bahan)\b/i.test(lowerContent)) {
                stubParam = 'makanan';
            } else if (/\b(kesehatan|medis|dokter|penyakit|obat|rumah sakit|klinik|terapi|virus|gejala)\b/i.test(lowerContent)) {
                stubParam = 'kesehatan';
            } else if (/\b(astronomi|bintang|planet|galaksi|teleskop|antariksa|nasa|komet|orbit|luar angkasa)\b/i.test(lowerContent)) {
                stubParam = 'astronomi';
            } else if (/\b(agama|ibadah|kitab|tuhan|nabi|gereja|masjid|pura|vihara|iman)\b/i.test(lowerContent)) {
                stubParam = 'agama';
            } else if (/\b(bahasa|dialek|aksara|kamus|linguistik|kata|kalimat|suku|ucapan|fonem)\b/i.test(lowerContent)) {
                stubParam = 'bahasa';
            } else if (/\b(hukum|undang|pasal|pengadilan|hakim|jaksa|pengacara|pidana|perdata|legal)\b/i.test(lowerContent)) {
                stubParam = 'hukum';
            }
 
            // Gabungkan teks template Stub pilihan di baris paling bawah artikel
            var stubTag = stubParam ? '{{Stub|' + stubParam + '}}' : '{{Stub}}';
            content = content.trim() + '\n\n' + stubTag;
             summaryParts.push('+SmartStub(' + (stubParam || 'umum') + ')');
         }
         }
         var promoList = ['memang hebat', 'terpercaya sekali', 'terbaik di dunia', 'hubungi nomor kami', 'harga murah', 'kualitas terjamin'];
         var promoList = ['memang hebat', 'terpercaya sekali', 'terbaik di dunia', 'hubungi nomor kami', 'harga murah', 'kualitas terjamin'];
         if (promoList.some(p => rawContent.toLowerCase().indexOf(p) !== -1) && !/\{\{Hapus/i.test(content)) {
         if (promoList.some(p => rawContent.toLowerCase().indexOf(p) !== -1) && !/\{\{Hapus/i.test(content)) {
Baris 1.208: Baris 915:


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


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


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


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


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


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


Baris 1.266: Baris 965:
             if (isPatroli) {
             if (isPatroli) {
                 var placeholders = [];
                 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) {
                 content = content.replace(/(\{\{[\s\S]*?\}\}|==+.*?==+|\[\[Kategori:.*?\]\]|<ref[\s\S]*?<\/ref>|^.*?adalah)/gi, function(match) {
                     placeholders.push(match);
                     placeholders.push(match);
Baris 1.272: Baris 970:
                 });
                 });


                // Proses Auto-Link (Wajib ambil daftar AllPages dulu)
                 api.get({ action: 'query', list: 'allpages', apnamespace: 0, aplimit: 'max' }).done(function(apData) {
                 api.get({ action: 'query', list: 'allpages', apnamespace: 0, aplimit: 'max' }).done(function(apData) {
                     var allTitles = apData.query.allpages.map(p => p.title);
                     var allTitles = apData.query.allpages.map(p => p.title);
Baris 1.296: Baris 993:
                     content = tokens.join('');
                     content = tokens.join('');
                      
                      
                    // Kembalikan dari Brankas
                     content = content.replace(/___MIP_SKIP_(\d+)___/g, function(match, id) { return placeholders[id]; });
                     content = content.replace(/___MIP_SKIP_(\d+)___/g, function(match, id) { return placeholders[id]; });


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


/* ==========================================================
/* ==========================================================
   🛡️ MIPPEDIA AUTO-FORMATTER ENGINE
   🚀 MIPPEDIA DATA BUTTON ONLY (Otomatis)
   Fitur: Perbaikan Spasi, Tanda Baca, & Tipografi Otomatis
  Hanya memunculkan tombol jika data tersedia di pusat.
  ========================================================== */
$(document).ready(function() {
    var pageName = mw.config.get('wgPageName');
    var namespace = mw.config.get('wgNamespaceNumber');
    var dataDomain = 'https://data.mippedia.org';
 
    // Jalankan hanya di namespace artikel
    if (namespace === 0) {
        // Cek apakah halaman tersebut ada di Mippedia Data
        $.ajax({
            url: dataDomain + '/api.php',
            data: {
                action: 'query',
                titles: pageName,
                format: 'json',
                origin: '*'
            },
            dataType: 'jsonp',
            success: function(res) {
                var pages = res.query.pages;
                var isExist = false;
               
                // Cek apakah ID halaman > 0 (artinya halaman ada)
                for (var id in pages) {
                    if (parseInt(id) > 0) {
                        isExist = true;
                        break;
                    }
                }
 
                // Jika data ditemukan, munculkan tombol melayang
                if (isExist) {
                    injectFloatingDataBtn(pageName, dataDomain);
                }
            }
        });
    }
 
    function injectFloatingDataBtn(name, domain) {
        if ($('#mippedia-data-btn').length) return;
 
        var $btn = $('<a>', {
            id: 'mippedia-data-btn',
            href: domain + '/wiki/' + encodeURIComponent(name),
            target: '_blank',
            style: 'position: absolute; right: 10px; top: -32px; background: #36c; color: #fff; padding: 4px 10px; border-radius: 4px; font-weight: bold; font-size: 10px; text-decoration: none; z-index: 1000; box-shadow: 0 2px 4px rgba(0,0,0,0.1);',
            text: 'DATA'
        });
 
        // Target: Area menu aksi (dekat ikon pensil)
        // Mendukung skin Mobile (Minerva) dan Desktop
        var $target = $('.page-actions-menu, .mw-editsection-visualeditor, #ca-edit, .minerva__tab-container').first();
       
        if ($target.length) {
            $target.css('position', 'relative').append($btn);
        } else {
            // Fallback jika header tidak standar
            $('#firstHeading').css('position', 'relative').append($btn);
        }
    }
});
 
/* ==========================================================
  🚀 MIPPEDIA COMMAND CENTER: AUTO-SYNC ENGINE (V4)
   Status: Global Login User | Auto-Purge | High Reliability
  ========================================================== */
(function($, mw) {
    "use strict";
 
    var conf = mw.config.get(['wgNamespaceNumber', 'wgAction', 'wgPageName', 'wgIsMainPage', 'wgUserName']);
    // Filter: Hanya artikel, hanya saat baca, hanya user yang sudah login
    if (conf.wgNamespaceNumber !== 0 || conf.wgAction !== 'view' || conf.wgIsMainPage || conf.wgUserName === null) return;
 
    $(document).ready(function() {
        var currentTitle = conf.wgPageName;
        // Penentuan subdomain (id, en, concise)
        var hostParts = window.location.hostname.split('.');
        var langKey = hostParts[0] === 'mippedia' || hostParts[0] === 'www' ? 'id' : hostParts[0];
 
        $.ajax({
            url: 'https://data.mippedia.org/api.php',
            data: {
                action: 'query',
                prop: 'revisions',
                titles: 'MediaWiki:ShortDesc-Data.json',
                rvprop: 'content',
                format: 'json',
                origin: '*'
            },
            dataType: 'jsonp',
            success: function(res) {
                try {
                    var pages = res.query.pages;
                    var pageId = Object.keys(pages)[0];
                    if (pageId === "-1") return;
 
                    var fullData = JSON.parse(pages[pageId].revisions[0]['*']);
                    var targetDesc = (fullData[currentTitle] && fullData[currentTitle][langKey]) ? fullData[currentTitle][langKey].trim() : "";
 
                    syncMetadata(currentTitle, targetDesc);
                } catch (e) {
                    console.log("Mippedia System: Data sync not required or entry missing.");
                }
            }
        });
 
        function syncMetadata(title, dataCenterDesc) {
            var api = new mw.Api();
            api.get({
                action: 'query',
                prop: 'revisions',
                titles: title,
                rvprop: 'content',
                formatversion: 2
            }).done(function(data) {
                var content = data.query.pages[0].revisions[0].content;
                var shortDescPattern = /\{\{SHORTDESC:.*?\}\}\n?/gi;
                var hasLocalDesc = shortDescPattern.test(content);
               
                var localMatch = content.match(/\{\{SHORTDESC:(.*?)\}\}/i);
                var currentLocalDesc = localMatch ? localMatch[1].trim() : "";
 
                // AKSI 1: HAPUS (Jika di pusat kosong/dihapus, tapi di artikel lokal masih ada)
                if (dataCenterDesc === "" && hasLocalDesc) {
                    console.log("Mippedia: Purging metadata...");
                    saveEdit(title, content.replace(shortDescPattern, ""), "Purge out-of-sync metadata");
                }
                // AKSI 2: UPDATE/TAMBAH (Jika data di pusat ada dan beda dengan lokal)
                else if (dataCenterDesc !== "" && dataCenterDesc !== currentLocalDesc) {
                    console.log("Mippedia: Syncing with Data Center...");
                    var cleanedContent = content.replace(shortDescPattern, "");
                    // Menaruh di paling atas agar terbaca Extension ShortDescription
                    var newContent = '{{SHORTDESC:' + dataCenterDesc + '}}\n' + cleanedContent;
                    saveEdit(title, newContent, "Sync metadata: " + dataCenterDesc);
                }
            });
        }
 
        function saveEdit(title, text, summary) {
            // Menggunakan token user yang sedang login saat ini
            new mw.Api().postWithEditToken({
                action: 'edit',
                title: title,
                text: text,
                summary: '🤖 ' + summary,
                minor: true // Menandai sebagai suntingan kecil
                // Parameter 'bot: true' DIHAPUS agar bisa dijalankan semua pengguna login
            }).done(function() {
                console.log("Mippedia: " + title + " synced successfully.");
            });
        }
    });
})(jQuery, mediaWiki);
 
/* ==========================================================
  🚀 MIPPEDIA METADATA GUARD - RADAR SYSTEM (V5)
  Status: Professional Messaging | Hybrid Mobile/Desktop
   ========================================================== */
   ========================================================== */
(function() {
(function($, mw) {
     function cleanTypography(text) {
     "use strict";
        var clean = text;


        // 1. Spasi Ganda: Ubah spasi yang lebih dari satu menjadi satu spasi saja
    var ns = mw.config.get('wgNamespaceNumber');
        clean = clean.replace(/[ \t]+/g, ' ');
    if (ns !== 0 || mw.config.get('wgIsMainPage')) return;


        // 2. Tanda Baca (Koma & Titik):
    var shortDescRegex = /\{\{SHORTDESC:.*?\}\}/gi;
        // Hapus spasi SEBELUM tanda baca, dan pastikan ada satu spasi SESUDAHnya
    var originalShortDesc = null;
        // Contoh: "Halo ,apa kabar ." -> "Halo, apa kabar."
        clean = clean.replace(/\s+([,.!?;:])/g, '$1');  
        clean = clean.replace(/([,.!?;:])(?=[^\s\d,.!?;:])/g, '$1 ');


        // 3. Spasi di dalam kurung: "( teks )" -> "(teks)"
    function validateAndBlock(e) {
         clean = clean.replace(/\(\s+/g, '(');
         var $textbox = $('#wpTextbox1, textarea.previewable-render, .editor-container textarea, textarea[name="wpTextbox1"]');
         clean = clean.replace(/\s+\)/g, ')');
         if (!$textbox.length) return true;


         // 4. Perbaikan Baris Baru: Maksimal dua kali enter (biar gak ada ruang kosong raksasa)
         var currentContent = $textbox.val() || "";
         clean = clean.replace(/\n{3,}/g, '\n\n');
         var currentMatch = currentContent.match(shortDescRegex);
        var currentShortDesc = currentMatch ? currentMatch[0] : "";


         // 5. Simbol Khusus: Ubah (c) jadi ©, (r) jadi ®, atau -- jadi — (em-dash) agar pro
         if (originalShortDesc === null) {
        clean = clean.replace(/\(c\)/gi, '©');
            originalShortDesc = currentShortDesc;
        clean = clean.replace(/\(r\)/gi, '®');
            return true;
         clean = clean.replace(/ -- /g, ' — ');
         }


         return clean;
         if (originalShortDesc !== currentShortDesc) {
            // --- PESAN PROFESIONAL BARU ---
            window.alert(
                "MIPPEDIA SYSTEM NOTIFICATION\n" +
                "────────────────────────────\n\n" +
                "Suntingan anda tidak bisa di lanjutkan untuk di terbitkan, Karena sinkronisasi otomatis terdeteksi tidak valid.\n\n" +
                "Untuk menjaga integritas metadata, deskripsi singkat (ShortDescription) wajib dikelola melalui repositori Mippedia Data.\n\n" +
                "Harap urungkan perubahan manual pada kode {{SHORTDESC}} untuk melanjutkan proses penyimpanan."
            );
           
            e.preventDefault();
            e.stopPropagation();
            e.stopImmediatePropagation();
            return false;
        }
        return true;
     }
     }


     // Jalankan pas user klik tombol Simpan
     // Radar untuk menangkap elemen editor saat muncul (terutama di Mobile)
     $(document).on('click', '#wpSave, #wpSaveWidget, .editCheck-save, button[type="submit"]', function() {
    var observer = new MutationObserver(function() {
         var $textbox = $('#wpTextbox1');
        var $textbox = $('#wpTextbox1, .editor-container textarea, textarea[name="wpTextbox1"]');
         if ($textbox.length) {
        if ($textbox.length && originalShortDesc === null) {
            var originalText = $textbox.val();
            var content = $textbox.val() || "";
            var formattedText = cleanTypography(originalText);
            var match = content.match(shortDescRegex);
           
            originalShortDesc = match ? match[0] : "";
            // Update isi kotak teks sebelum terkirim ke server
        }
            if (originalText !== formattedText) {
    });
                $textbox.val(formattedText);
 
                console.log("Mippedia System: Typography cleaned automatically.");
    observer.observe(document.body, { childList: true, subtree: true });
            }
 
    // Event listener untuk tombol simpan di berbagai platform
     $(document).on('click mousedown touchstart',  
        '#wpSave, .mw-ui-button.primary, button.submit, .editor-save, .save-button, button[type="submit"]',  
        function(e) {
            return validateAndBlock(e);
         }
    );
 
    window.addEventListener('submit', function(e) {
         if (!validateAndBlock(e)) e.preventDefault();
    }, true);
 
})(jQuery, mediaWiki);
 
$(function() {
    $('.ambox-learn-more').on('click', function(e) {
        e.preventDefault();
        var $parentBox = $(this).closest('.ambox');
       
        $parentBox.toggleClass('ambox-active');
        $parentBox.find('.ambox-text-long').slideToggle('fast');
       
        // Ubah teks tombol pas dibuka
        if ($parentBox.hasClass('ambox-active')) {
            $(this).text('Sembunyikan');
        } else {
            $(this).text('Pelajari selengkapnya');
         }
         }
     });
     });
})();
});

Revisi terkini sejak 30 Mei 2026 12.26

/* Script Estimasi Waktu Baca - Spesialis Mobile (Minerva) & Desktop */
$(document).ready(function() {
    // Hanya jalan di halaman artikel asli dan BUKAN di Halaman Utama
    if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view' && mw.config.get('wgNamespaceNumber') === 0 && !mw.config.get('wgIsMainPage')) {
        
        function hitungWaktuBaca() {
            // Ambil teks dari konten utama
            var content = $('#mw-content-text').text();
            
            // Hitung jumlah kata (asumsi rata-rata orang baca 200 kata per menit)
            var wordsPerMinute = 200;
            var textLength = content.split(/\s+/).length; // Pecah berdasarkan spasi
            var readingTime = Math.ceil(textLength / wordsPerMinute);
            
            // Bikin elemen tampilannya
            var icon = '🕒'; // Emoji jam biar simpel dan ringan
            var label = (readingTime <= 1) ? '- 1 menit' : readingTime + ' menit';
            
            var html = '<div id="reading-time-auto" style="font-size: 0.9em; color: #54595d; margin-bottom: 15px; display: flex; align-items: center; font-family: sans-serif;">';
            html += '<span style="margin-right: 5px;">' + icon + '</span>';
            html += '<span>Estimasi waktu baca : <b>' + label + '</b></span>';
            html += '</div>';

            // PENEMPELAN TARGET:
            // Di Minerva (HP), judul biasanya ada di .page-heading
            // Di Vector (Desktop), judul ada di #firstHeading
            if ($('.page-heading').length) {
                $('.page-heading').after(html); // Target Mobile
            } else if ($('#firstHeading').length) {
                $('#firstHeading').after(html); // Target Desktop
            }
        }

        // Jalankan fungsi
        hitungWaktuBaca();
    }
});

/* Script Tombol Back to Top (Spesial Mobile) */
$(document).ready(function() {
    // Bikin tombolnya lewat JS biar gak ribet edit CSS/HTML
    var btnHtml = '<div id="backToTop" style="display:none; position:fixed; bottom:80px; right:20px; z-index:9999; background:#36c; color:#fff; width:45px; height:45px; border-radius:50%; text-align:center; line-height:45px; font-size:24px; cursor:pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.3); opacity: 0.8;">↑</div>';
    $('body').append(btnHtml);

    // Fungsi munculin tombol pas di-scroll
    $(window).scroll(function() {
        if ($(this).scrollTop() > 300) {
            $('#backToTop').fadeIn();
        } else {
            $('#backToTop').fadeOut();
        }
    });

    // Fungsi pas tombol diklik
    $('#backToTop').click(function() {
        $('html, body').animate({scrollTop: 0}, 600);
        return false;
    });
});

/* 3. Anti-Ghosting pada Link Kosong (Redlinks) */
$(document).ready(function() {
    $('a.new').click(function(e) {
        var confirmCreate = confirm("Halaman ini belum tersedia di Mippedia.\n\nApakah Anda ingin berkontribusi membuatnya?");
        if (!confirmCreate) {
            e.preventDefault();
        }
    });
});

/* ==========================================================
   🛡️ MIPPEDIA SHIELD: PROTEKSI HALAMAN SENSITIF (FULL CODE)
   Hanya untuk Pengurus, Birokrat, dan Pengawas.
   ========================================================== */
$(document).ready(function() {
    
    // 1. DAFTAR HALAMAN YANG MAU DIKUNCI
    // Tambah atau hapus di dalam kurung siku ini. Gunakan koma sebagai pemisah.
    var protectedPages = [
        "MediaWiki:Common.js",
        "Istimewa:Versi"
    ];

    // 2. CEK STATUS USER & HALAMAN
    var userGroups = mw.config.get('wgUserGroups') || [];
    // Daftar grup yang KEBAL proteksi (bisa akses halaman)
    var isStaff = userGroups.some(r => ["sysop", "bureaucrat", "steward", "interface-admin"].includes(r));
    
    var currentPage = mw.config.get('wgPageName');
    // Cek apakah halaman saat ini masuk dalam daftar proteksi
    var shouldProtect = protectedPages.some(prefix => currentPage.startsWith(prefix.replace(/ /g, '_')));

    // 3. EKSEKUSI PROTEKSI (Hanya jika user BUKAN staff)
    if (shouldProtect && !isStaff) {
        
        // Hapus total konten asli agar tidak bisa diintip/disunting
        $('body').addClass('mippedia-locked').html('');

        // Inject CSS khusus untuk tampilan Mobile-Friendly & Auto-Center
        $('<style>').prop('type', 'text/css').html(`
            html, body { 
                margin: 0 !important; 
                padding: 0 !important; 
                height: 100% !important; 
                width: 100% !important; 
                overflow: hidden !important; 
                background: #f8f9fa !important;
            }
            #protection-wrapper {
                display: flex;
                align-items: center;
                justify-content: center;
                min-height: 100vh;
                width: 100vw;
                padding: 20px;
                box-sizing: border-box;
                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            }
            .protection-card {
                width: 100%;
                max-width: 400px;
                background: #ffffff;
                padding: 40px 25px;
                border-radius: 30px;
                box-shadow: 0 15px 50px rgba(54, 102, 204, 0.15);
                border: 1px solid #eef0f2;
                text-align: center;
            }
            .shield-icon { font-size: 70px; display: block; margin-bottom: 20px; }
            .lock-title { color: #1a1a1a; font-size: 24px; font-weight: 800; margin: 0 0 15px 0; }
            .lock-desc { color: #5f6368; font-size: 15px; line-height: 1.6; margin-bottom: 25px; }
            .admin-notice { 
                background: #fff5f5; 
                color: #d93025; 
                padding: 12px; 
                border-radius: 12px; 
                font-size: 13px; 
                font-weight: 700; 
                margin-bottom: 30px; 
                border: 1px solid #fadbd8;
            }
            .btn-back { 
                background: #36c; 
                color: #fff; 
                border: none; 
                padding: 16px; 
                border-radius: 18px; 
                font-weight: 700; 
                font-size: 16px;
                width: 100%; 
                cursor: pointer; 
                box-shadow: 0 4px 12px rgba(51, 102, 204, 0.3);
            }
            .link-home { display: block; margin-top: 20px; color: #70757a; font-size: 14px; text-decoration: none; }
            .footer-ver { margin-top: 40px; font-size: 10px; color: #bdc1c6; font-weight: bold; letter-spacing: 2px; }
        `).appendTo('head');

        // Tampilkan layar kunci
        var shieldHTML = `
            <div id="protection-wrapper">
                <div class="protection-card">
                    <span class="shield-icon">🛡️</span>
                    <h2 class="lock-title">Akses Dibatasi</h2>
                    <p class="lock-desc">
                        Halaman ini telah dilindungi oleh <b>Mippedia Community</b> untuk menjaga stabilitas sistem.
                    </p>
                    <div class="admin-notice">
                        Hanya Administrator & Birokrat yang dapat mengakses halaman ini.
                    </div>
                    <button class="btn-back" onclick="window.history.back()">
                        Kembali ke Halaman Sebelumnya
                    </button>
                    <a href="/" class="link-home">Kembali ke Beranda</a>
                    <div class="footer-ver">MIPPEDIA COMMUNITY SECURE v2.0</div>
                </div>
            </div>
        `;

        $('body').append(shieldHTML);
        
        // Ubah judul tab browser
        document.title = "Akses Dilindungi - Mippedia bahasa Indonesia, ensiklopedia umum";
    }
});

/* ==========================================================
   🛡️ MIPPEDIA VERIFICATION SYSTEM v8.0 (ANTI-GAGAL)
   ========================================================== */
$(document).ready(function() {
    var user = mw.config.get('wgUserName');
    var pageName = mw.config.get('wgPageName');
    var ns = mw.config.get('wgNamespaceNumber');
    var isAdmin = mw.config.get('wgUserGroups').includes('sysop');
    var $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS (PENGGUNA) ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_req_text')) {
        var savedText = sessionStorage.getItem('mippedia_req_text');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan saya:** \n(Tulis alasan lo di sini, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_req_text');
    }

    // --- 2. TOMBOL MINTA (HALAMAN BERKAS) ---
    if (ns === 6) {
        if (!$content.text().includes("Aset Resmi")) {
            var $reqBtn = $('<button>').html('<span>📩</span> Minta Verifikasi').css({
                'background': '#36c', 'color': '#fff', 'border': 'none', 'padding': '5px 15px', 
                'border-radius': '20px', 'font-size': '11px', 'font-weight': '800', 'cursor': 'pointer', 'margin': '10px 0'
            });
            $reqBtn.click(function() {
                if (!user) { window.location.href = mw.util.getUrl('Istimewa:Masuk_log', { returnto: pageName }); return; }
                var talkPage = "Pembicaraan_Berkas:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_req_text', "Halo Pengurus Mippedia,\n\nSaya memohon verifikasi untuk berkas [[:" + pageName + "]].");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Verifikasi Berkas' });
            });
            setTimeout(function() { $('#firstHeading').after($reqBtn); }, 600);
        }
    }

    // --- 3. PANEL ADMIN & AUTOMATION (HALAMAN PEMBICARAAN) ---
    if (ns === 7) {
        var api = new mw.Api();
        var filePage = pageName.replace('Pembicaraan_Berkas:', 'Berkas:');
        var fullContent = $content.text();
        var isPending = fullContent.includes("Status: 🕒 Sedang diajukan");

        // Ambil User Pengaju
        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user', rvlimit: 1, rvdir: 'newer' }).done(function(data) {
            var pages = data.query.pages;
            var requester = "";
            for (var id in pages) { requester = pages[id].revisions[0].user; }

            // Tombol Coba Lagi buat Pengaju
            if (fullContent.includes("Status: ❌ Ditolak") && user === requester) {
                var $retryBtn = $('<button>').text('🔄 Coba Lagi').css({'background':'#36c','color':'#fff','border':'none','padding':'4px 10px','border-radius':'4px','cursor':'pointer','display':'block','margin-top':'10px'});
                $retryBtn.click(function() { window.location.href = mw.util.getUrl(filePage); });
                $('.mippedia-status').append($retryBtn);
            }

            // PANEL ADMIN
            if (isAdmin && isPending) {
                var $panel = $('<div id="admin-panel" style="background:#f0f5ff; border:2px solid #36c; padding:15px; border-radius:10px; margin:15px 0;">' +
                    '<div style="font-weight:bold; color:#36c; margin-bottom:10px;">🛡️ ADMIN CONTROL</div></div>');
                
                var $btnApprove = $('<button>').text('✅ SETUJUI').css({'background':'#00af89','color':'#fff','border':'none','padding':'8px 15px','margin-right':'10px','cursor':'pointer'});
                var $btnReject = $('<button>').text('❌ TOLAK').css({'background':'#d33','color':'#fff','border':'none','padding':'8px 15px','cursor':'pointer'});

                $btnApprove.click(function() {
                    $btnApprove.prop('disabled', true).text('Processing...');
                    
                    // STEP 1: Nulis "Aset Resmi" di Berkas
                    api.postWithToken('edit', { action: 'edit', title: filePage, appendtext: '\nAset Resmi', summary: 'Verifikasi Disetujui' }).done(function() {
                        // STEP 2: Ganti teks status di halaman diskusi
                        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                            var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                            var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Disetujui'''");
                            api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Update Status: Disetujui' }).done(function() {
                                // STEP 3: Kirim notif ke User
                                var msg = "\n== Notifikasi Verifikasi ==\nHalo [[" + requester + "]], permohonan Anda untuk [[:" + filePage + "]] telah '''DISETUJUI'''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 16.37 (UTC)";
                                api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                    location.reload();
                                });
                            });
                        });
                    });
                });

                $btnReject.click(function() {
                    var alasan = prompt("Alasan penolakan:");
                    if (!alasan) return;
                    $btnReject.prop('disabled', true).text('Processing...');

                    api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                        var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                        var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\n''Alasan: " + alasan + "''");
                        api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Update Status: Ditolak' }).done(function() {
                            var msg = "\n== Notifikasi Verifikasi ==\nHalo [[" + requester + "]], permohonan Anda untuk [[:" + filePage + "]] '''DITOLAK''' karena: ''" + alasan + "''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 16.37 (UTC)";
                            api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                location.reload();
                            });
                        });
                    });
                });

                $panel.append($btnApprove, $btnReject);
                $('#mw-content-text').prepend($panel);
            }
        });
    }
});

/* ==========================================================
   🛡️ MIPPEDIA AUTO-PROTECTION SYSTEM (ADAPTIVE & AUTO-NOTIF)
   Fitur: Request Protect, Auto-Lock, & Pesan Otomatis ke User
   ========================================================== */
$(document).ready(function() {
    var user = mw.config.get('wgUserName');
    var pageName = mw.config.get('wgPageName');
    var ns = mw.config.get('wgNamespaceNumber');
    var isAdmin = mw.config.get('wgUserGroups').includes('sysop');
    var $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS PERLINDUNGAN ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_protect_text')) {
        var savedText = sessionStorage.getItem('mippedia_protect_text');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan Perlindungan:** \n(Tulis alasan kenapa berkas ini perlu dikunci, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_protect_text');
    }

    // --- 2. TOMBOL DINAMIS (DI HALAMAN BERKAS) ---
    if (ns === 6 && user) { // Khusus user login
        var api = new mw.Api();
        api.get({ action: 'query', prop: 'info', titles: pageName, inprop: 'protection' }).done(function(data) {
            var page = data.query.pages[Object.keys(data.query.pages)[0]];
            var protections = page.protection;
            
            var isFull = false;
            var isSemi = false;

            protections.forEach(function(p) {
                if (p.type === 'edit') {
                    if (p.level === 'sysop') isFull = true;
                    if (p.level === 'autoconfirmed') isSemi = true;
                }
            });

            // Jika Full, tombol hilang. Jika Semi, tombol minta Penuh.
            if (isFull) return;
            var btnLabel = isSemi ? '🔒 Minta Perlindungan Penuh' : '🔒 Minta Perlindungan';
            var reqType = isSemi ? 'Perlindungan Penuh' : 'Perlindungan';

            var $protBtn = $('<button>').html('<span></span> ' + btnLabel).css({
                'background': '#d33', 'color': '#fff', 'border': 'none', 'padding': '5px 15px', 
                'border-radius': '20px', 'font-size': '11px', 'font-weight': '800', 'cursor': 'pointer', 'margin': '10px 5px'
            });

            $protBtn.click(function() {
                var talkPage = "Pembicaraan_Berkas:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_protect_text', "Halo Pengurus Mippedia,\n\nSaya memohon " + reqType + " untuk berkas [[:" + pageName + "]] guna menghindari penyalahgunaan.");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Perlindungan Berkas' });
            });

            setTimeout(function() { $('#firstHeading').after($protBtn); }, 650);
        });
    }

    // --- 3. PANEL ADMIN PERLINDUNGAN (DI HALAMAN PEMBICARAAN) ---
    if (ns === 7) {
        var api = new mw.Api();
        var filePage = pageName.replace('Pembicaraan_Berkas:', 'Berkas:');
        var isPending = $content.text().includes("Status: 🕒 Sedang diajukan");

        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user', rvlimit: 1, rvdir: 'newer' }).done(function(data) {
            var pages = data.query.pages;
            var requester = "";
            for (var id in pages) { requester = pages[id].revisions[0].user; }

            if (isAdmin && isPending && $content.text().includes("Permintaan Perlindungan")) {
                var $panel = $('<div style="background:#fff0f0; border:2px solid #d33; padding:15px; border-radius:10px; margin:15px 0;">' +
                    '<div style="font-weight:bold; color:#d33; margin-bottom:10px;">🛡️ ADMIN PROTECTION CONTROL</div>' +
                    '<p style="font-size:11px;">Pilih tingkat perlindungan untuk berkas ini:</p></div>');
                
                var $btnSemi = $('<button>').text('SEMI-PROT').attr('title', 'Hanya user terdaftar').css({'background':'#faad14','color':'#fff','border':'none','padding':'8px 12px','margin-right':'8px','cursor':'pointer','font-weight':'bold'});
                var $btnFull = $('<button>').text('FULL-PROT').attr('title', 'Hanya pengurus').css({'background':'#d33','color':'#fff','border':'none','padding':'8px 12px','margin-right':'8px','cursor':'pointer','font-weight':'bold'});
                var $btnReject = $('<button>').text('TOLAK').css({'background':'#555','color':'#fff','border':'none','padding':'8px 12px','cursor':'pointer'});

                // FUNGSI EKSEKUSI PROTEKSI (Tetap menjaga sistem kirim pesan otomatis ke user)
                function executeProtect(level, levelName) {
                    var editRight = (level === 'sysop') ? 'sysop' : 'autoconfirmed';

                    api.postWithToken('csrf', {
                        action: 'protect',
                        title: filePage,
                        protections: 'edit=' + editRight + '|move=' + editRight,
                        expiry: 'infinite',
                        reason: 'Permintaan disetujui: ' + levelName
                    }).done(function() {
                        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                            var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                            var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Dilindungi (" + levelName + ")'''");
                            
                            api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Status: Protection Granted' }).done(function() {
                                // FITUR OTOMATIS KIRIM PESAN (TIDAK DIBUANG)
                                var msg = "\n== Notifikasi Perlindungan ==\nHalo [[" + requester + "]], permohonan perlindungan untuk [[:" + filePage + "]] telah '''DISETUJUI''' dengan tingkat '''" + levelName + "'''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 17.37 (UTC)";
                                api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                    location.reload();
                                });
                            });
                        });
                    });
                }

                $btnSemi.click(function() { executeProtect('autoconfirmed', 'Semi Perlindungan'); });
                $btnFull.click(function() { executeProtect('sysop', 'Perlindungan Penuh'); });
                $btnReject.click(function() {
                    var alasan = prompt("Alasan penolakan:");
                    if (!alasan) return;
                    api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                        var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                        var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\n''Alasan: " + alasan + "''");
                        api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Status: Protection Rejected' }).done(function() {
                            // FITUR OTOMATIS KIRIM PESAN PENOLAKAN
                            var msg = "\n== Notifikasi Perlindungan ==\nHalo [[" + requester + "]], permohonan perlindungan untuk [[:" + filePage + "]] '''DITOLAK''' karena: ''" + alasan + "''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 17.37 (UTC)";
                            api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                location.reload();
                            });
                        });
                    });
                });

                $panel.append($btnSemi, $btnFull, $btnReject);
                $('#mw-content-text').prepend($panel);
            }
        });
    }
});

/* ==========================================================
   🛡️ MIPPEDIA ARTICLE PROTECTION SYSTEM (PERFECT ALIGNMENT)
   Fokus: Posisi Sejajar, Teks Tebal, & Warna Standar
   ========================================================== */
$(document).ready(function() {
    var user = mw.config.get('wgUserName');
    var pageName = mw.config.get('wgPageName');
    var ns = mw.config.get('wgNamespaceNumber');
    var isAdmin = mw.config.get('wgUserGroups').includes('sysop');
    var $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS PERLINDUNGAN ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_art_protect')) {
        var savedText = sessionStorage.getItem('mippedia_art_protect');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan Perlindungan:** \n(Tulis alasan lo, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_art_protect');
    }

    // --- 2. TOMBOL DINAMIS (POSISI PRESISI & TEKS TEBAL) ---
    if (ns === 0 && user) {
        var api = new mw.Api();
        api.get({ action: 'query', prop: 'info', titles: pageName, inprop: 'protection' }).done(function(data) {
            var page = data.query.pages[Object.keys(data.query.pages)[0]];
            var protections = page.protection;
            var isFull = protections.some(p => p.type === 'edit' && p.level === 'sysop');
            var isSemi = protections.some(p => p.type === 'edit' && p.level === 'autoconfirmed');

            if (isFull) return;

            var btnLabel = isSemi ? 'Proteksi Penuh' : 'Proteksi';
            var reqType = isSemi ? 'Perlindungan Penuh' : 'Perlindungan';

            // Membuat item list dengan padding supaya tidak terlalu ke kiri
            var $protLink = $('<li>').attr({
                'id': 'ca-protect-request',
                'class': 'mw-list-item'
            }).append(
                $('<a>').attr({'href': '#', 'title': 'Minta perlindungan'}).css({
                    'display': 'flex',
                    'align-items': 'center',
                    'padding': '6px 12px' // Memberi ruang agar tidak mepet ke kiri
                }).append(
                    $('<span>').html('🔒 ' + btnLabel).css({
                        'color': '#202122', 
                        'font-weight': 'bold', // Tulisan jadi tebal
                        'margin-left': '2px'  // Jarak halus setelah ikon
                    })
                )
            );

            $protLink.click(function(e) {
                e.preventDefault();
                var talkPage = "Pembicaraan:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_art_protect', "Halo Pengurus,\n\nSaya memohon " + reqType + " untuk [[" + pageName + "]].");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Perlindungan Artikel' });
            });

            // Menyisipkan ke menu
            $('#p-cactions ul, #p-views ul').append($protLink);
        });
    }

    // --- 3. PANEL ADMIN (LOGIKA BERANTAI ANTI-MACET) ---
    if (ns === 1 && isAdmin && $content.text().includes("Sedang diajukan")) {
        var api = new mw.Api();
        var articlePage = pageName.replace('Pembicaraan:', '');
        
        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user|content', rvlimit: 1 }).done(function(res) {
            var pg = res.query.pages[Object.keys(res.query.pages)[0]];
            var requester = pg.revisions[0].user;
            var oldContent = pg.revisions[0]['*'];

            var $panel = $('<div style="background:#fff0f0; border:2px solid #d33; padding:15px; border-radius:10px; margin-bottom:15px;">' +
                '<b>🛡️ ADMIN CONTROL</b><br><small>Request by: '+requester+'</small></div>');
            
            var $btnOk = $('<button>').text('✅ SETUJUI').css({'background':'#d33','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','font-weight':'bold'});
            var $btnNo = $('<button>').text('❌ TOLAK').css({'background':'#555','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','margin-left':'10px'});

            $btnOk.click(function() {
                var level = oldContent.includes("Penuh") ? "sysop" : "autoconfirmed";
                $(this).prop('disabled', true).text('Processing Step 1/3...');

                api.postWithToken('csrf', {
                    action: 'protect', title: articlePage, protections: 'edit='+level+'|move='+level, expiry: 'infinite', reason: 'Approved'
                }).then(function() {
                    $btnOk.text('Processing Step 2/3...');
                    var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Dilindungi ("+level+")'''");
                    return api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Status Updated' });
                }).then(function() {
                    $btnOk.text('Processing Step 3/3...');
                    var msg = "\n== Notifikasi ==\nHalo [["+requester+"]], permohonan perlindungan [["+articlePage+"]] udah disetujui, boys! --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.40 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $btnNo.click(function() {
                var alasan = prompt("Alasan:");
                if (!alasan) return;
                $(this).prop('disabled', true).text('Rejecting...');
                var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\nAlasan: " + alasan);
                api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Rejected' }).then(function() {
                    var msg = "\n== Notifikasi ==\nSori [["+requester+"]], permintaan lo ditolak: " + alasan + " --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.40 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $panel.append($btnOk, $btnNo);
            $('#mw-content-text').prepend($panel);
        });
    }
});

/* ==========================================================
   🛡️ MIPPEDIA USER PAGE PROTECTION SYSTEM
   Khusus Namespace Pengguna - Versi Stabil, Rapi & Otomatis
   ========================================================== */
$(document).ready(function() {
    var user = mw.config.get('wgUserName');
    var pageName = mw.config.get('wgPageName');
    var ns = mw.config.get('wgNamespaceNumber');
    var isAdmin = mw.config.get('wgUserGroups').includes('sysop');
    var $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS PERLINDUNGAN ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_user_protect')) {
        var savedText = sessionStorage.getItem('mippedia_user_protect');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan Perlindungan:** \n(Tulis alasan kenapa halaman pengguna ini perlu dikunci, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_user_protect');
    }

    // --- 2. TOMBOL DINAMIS (KHUSUS NAMESPACE PENGGUNA / NS 2) ---
    if (ns === 2 && user) { 
        var api = new mw.Api();
        api.get({ action: 'query', prop: 'info', titles: pageName, inprop: 'protection' }).done(function(data) {
            var page = data.query.pages[Object.keys(data.query.pages)[0]];
            var protections = page.protection;
            var isFull = protections.some(p => p.type === 'edit' && p.level === 'sysop');
            var isSemi = protections.some(p => p.type === 'edit' && p.level === 'autoconfirmed');

            if (isFull) return;

            var btnLabel = isSemi ? 'Proteksi Penuh' : 'Proteksi Profil';
            var reqType = isSemi ? 'Perlindungan Penuh' : 'Perlindungan';

            var $protLink = $('<li>').attr({
                'id': 'ca-protect-user-request',
                'class': 'mw-list-item'
            }).append(
                $('<a>').attr({'href': '#', 'title': 'Minta perlindungan halaman pengguna'}).css({
                    'display': 'flex',
                    'align-items': 'center',
                    'padding': '6px 12px'
                }).append(
                    $('<span>').html('🔒 ' + btnLabel).css({
                        'color': '#202122', 
                        'font-weight': 'bold',
                        'margin-left': '2px'
                    })
                )
            );

            $protLink.click(function(e) {
                e.preventDefault();
                // Halaman Pengguna pake Pembicaraan Pengguna: (Namespace 3)
                var talkPage = "Pembicaraan_Pengguna:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_user_protect', "Halo Pengurus,\n\nSaya memohon " + reqType + " untuk halaman pengguna [[" + pageName + "]] guna menghindari vandalisme profil.");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Perlindungan Halaman Pengguna' });
            });

            $('#p-cactions ul, #p-views ul').append($protLink);
        });
    }

    // --- 3. PANEL ADMIN (HALAMAN PEMBICARAAN PENGGUNA / NS 3) ---
    if (ns === 3 && isAdmin && $content.text().includes("Sedang diajukan")) {
        var api = new mw.Api();
        // Target perlindungan adalah halaman pengguna utamanya
        var targetUserPage = "Pengguna:" + mw.config.get('wgTitle');
        
        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user|content', rvlimit: 1 }).done(function(res) {
            var pg = res.query.pages[Object.keys(res.query.pages)[0]];
            var requester = pg.revisions[0].user;
            var oldContent = pg.revisions[0]['*'];

            if (!$content.text().includes("Permintaan Perlindungan Halaman Pengguna")) return;

            var $panel = $('<div style="background:#fff0f0; border:2px solid #d33; padding:15px; border-radius:10px; margin-bottom:15px;">' +
                '<b>🛡️ ADMIN USER-PAGE CONTROL</b><br><small>Request by: '+requester+'</small></div>');
            
            var $btnOk = $('<button>').text('✅ SETUJUI').css({'background':'#d33','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','font-weight':'bold'});
            var $btnNo = $('<button>').text('❌ TOLAK').css({'background':'#555','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','margin-left':'10px'});

            $btnOk.click(function() {
                var level = oldContent.includes("Penuh") ? "sysop" : "autoconfirmed";
                $(this).prop('disabled', true).text('Step 1/3...');

                // STEP 1: PROTEKSI
                api.postWithToken('csrf', {
                    action: 'protect', title: targetUserPage, protections: 'edit='+level+'|move='+level, expiry: 'infinite', reason: 'User Page Protection: Approved'
                }).then(function() {
                    // STEP 2: UPDATE STATUS
                    $btnOk.text('Step 2/3...');
                    var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Dilindungi ("+level+")'''");
                    return api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Protection Status Updated' });
                }).then(function() {
                    // STEP 3: NOTIFIKASI OTOMATIS (KE USER)
                    $btnOk.text('Step 3/3...');
                    var msg = "\n== Notifikasi Perlindungan Profil ==\nHalo [["+requester+"]], permohonan perlindungan untuk halaman pengguna lo [["+targetUserPage+"]] udah disetujui dan aktif, boys! --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.48 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $btnNo.click(function() {
                var alasan = prompt("Alasan penolakan:");
                if (!alasan) return;
                $(this).prop('disabled', true).text('Rejecting...');
                var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\nAlasan: " + alasan);
                api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Protection Rejected' }).then(function() {
                    var msg = "\n== Notifikasi ==\nHalo [["+requester+"]], permintaan perlindungan profil lo belum bisa disetujui karena: " + alasan + " --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.48 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $panel.append($btnOk, $btnNo);
            $('#mw-content-text').prepend($panel);
        });
    }
});

/* ==========================================================
   🔵 MIPPEDIA ULTIMATE VERIFICATION SYSTEM (V3 - HIGH SECURITY)
   Fitur: Identitas Rahasia, Tombol Tolak, & Auto-Purge Data
   ========================================================== */
$(document).ready(function() {
    var user = mw.config.get('wgUserName');
    var pageName = mw.config.get('wgPageName');
    var ns = mw.config.get('wgNamespaceNumber');
    var isAdmin = mw.config.get('wgUserGroups').includes('sysop');
    var api = new mw.Api();
    var vFile = 'Verified_Badge.png';

    // --- 1. POP-UP TERVERIFIKASI ---
    function showVerifiedPopup() {
        api.parse('[[Berkas:' + vFile + '|60px|link=|middle]]').done(function(renderedImage) {
            var modalHtml = '<div id="mippedia-v-modal" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.75);z-index:99999;display:flex;align-items:center;justify-content:center;">' +
                '<div style="background:#fff;padding:30px;border-radius:20px;width:85%;max-width:320px;text-align:center;box-shadow:0 15px 35px rgba(0,0,0,0.5);position:relative;">' +
                '<div style="margin-bottom:15px;">' + renderedImage + '</div>' +
                '<h2 style="margin:0 0 10px 0;color:#1a1a1a;font-family:sans-serif;font-size:20px;font-weight:bold;">Akun Terverifikasi</h2>' +
                '<p style="color:#555;line-height:1.5;font-size:13px;margin-bottom:20px;font-family:sans-serif;">Mippedia telah mengonfirmasi bahwa identitas pemilik akun ini adalah asli. Lencana ini menandakan kredibilitas tinggi di dalam komunitas kami.</p>' +
                '<button id="close-v-modal" style="background:#0095f6;color:#fff;border:none;padding:12px 0;width:100%;border-radius:10px;cursor:pointer;font-weight:bold;font-size:14px;">Mengerti</button>' +
                '</div></div>';
            $('body').append(modalHtml);
            $('#close-v-modal').click(function() { $('#mippedia-v-modal').remove(); });
        });
    }

    // --- 2. LOGIKA CENTANG BIRU GLOBAL ---
    function applyGlobalBadge($element) {
        if ($element.data('has-badge') || $element.next('.mippedia-badge-global').length) return; 
        api.parse('[[Berkas:' + vFile + '|13px|link=|middle]]').done(function(renderedImage) {
            if ($element.next('.mippedia-badge-global').length) return;
            var cleanImage = $(renderedImage).find('img').first();
            var $badge = $('<span class="mippedia-badge-global" style="margin-left: 4px; display: inline-flex; align-items: center; vertical-align: middle; position: relative; top: -1px; cursor: pointer;"></span>').append(cleanImage);
            $badge.click(function(e) { e.preventDefault(); showVerifiedPopup(); });
            $element.after($badge);
            $element.data('has-badge', true);
        });
    }

    api.get({ action: 'query', list: 'categorymembers', cmtitle: 'Category:Pengguna_Terverifikasi', cmlimit: 'max' }).done(function(data) {
        var verifiedUsers = data.query.categorymembers.map(function(member) { return member.title.replace('Pengguna:', ''); });
        function scanLinks() {
            $('a.mw-userlink').each(function() {
                var username = $(this).text().trim();
                if (verifiedUsers.includes(username)) { applyGlobalBadge($(this)); }
            });
        }
        scanLinks();
        mw.hook('wikipage.content').add(scanLinks);
        var currentTitle = mw.config.get('wgTitle');
        if ((ns === 2 || ns === 3) && verifiedUsers.includes(currentTitle)) {
            if (!$('#firstHeading').find('.mippedia-profile-badge').length) {
                api.parse('[[Berkas:' + vFile + '|22px|link=|middle]]').done(function(renderedImage) {
                    var cleanImage = $(renderedImage).find('img').first();
                    var $pBadge = $('<span class="mippedia-profile-badge" style="margin-left: 6px; display: inline-flex; align-items: center; vertical-align: middle; cursor: pointer;"></span>').append(cleanImage);
                    $pBadge.click(showVerifiedPopup);
                    $('#firstHeading').append($pBadge);
                });
            }
        }
    });

    // --- 3. AUTO-FILL TEKS PERMINTAAN (DENGAN FORM IDENTITAS RAHASIA) ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_verify_req')) {
        var identityTemplate = 
            "\n\n\n" +
            "<div class='sysop-show' style='background:#fff5f5; border:1px solid #ff0000; padding:10px;'>\n" +
            "=== Data Identitas Pemohon ===\n" +
            "* '''Foto KTP/ID:''' [[Berkas:Isi_Nama_File_Di_Sini.jpg|thumb|150px]]\n" +
            "* '''Foto Selfie dengan KTP:''' [[Berkas:Isi_Nama_File_Di_Sini.jpg|thumb|150px]]\n" +
            "* '''Nama Lengkap:''' \n" +
            "* '''Tautan Media Sosial:''' \n" +
            "</div>\n" +
            "";

        var savedText = sessionStorage.getItem('mippedia_verify_req');
        $('#wpTextbox1').val(savedText + "\n\n**Persyaratan Verifikasi:** \n(Tulis alasan mengapa akun lo layak dapet centang biru, boys!) " + identityTemplate + "\n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diverifikasi'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_verify_req');
    }

    // --- 4. SEMBUNYIKAN DATA PRIVASI DARI NON-ADMIN ---
    if (!isAdmin) {
        $('.sysop-show').hide();
    }

    // --- 5. TOMBOL MINTA VERIFIKASI ---
    if (ns === 2 && user && mw.config.get('wgTitle') === user) { 
        if (!$('#ca-verify-request').length) {
            var $verifyLink = $('<li>').attr({'id': 'ca-verify-request', 'class': 'mw-list-item'}).append(
                $('<a>').attr({'href': '#', 'title': 'Minta Verifikasi'}).css({
                    'display': 'flex', 'align-items': 'center', 'padding': '6px 12px'
                }).append(
                    $('<span>').html('🔵 Verifikasi').css({'color': '#0095f6', 'font-weight': 'bold', 'margin-left': '2px'})
                )
            );
            $verifyLink.click(function(e) {
                e.preventDefault();
                sessionStorage.setItem('mippedia_verify_req', "Halo Pengurus Mippedia,\n\nSaya mengajukan permohonan verifikasi identitas akun untuk profil [[" + pageName + "]] sesuai dengan kebijakan komunitas.");
                window.location.href = mw.util.getUrl("Pembicaraan_Pengguna:" + user, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Verifikasi Profil Pengguna' });
            });
            $('#p-cactions ul, #p-views ul').append($verifyLink);
        }
    }

    // --- 6. PANEL ADMIN VERIFIKASI (APPROVE & REJECT) ---
    if (ns === 3 && isAdmin && $('#mw-content-text').text().includes("Sedang diverifikasi")) {
        var targetUserPage = "Pengguna:" + mw.config.get('wgTitle');
        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user|content', rvlimit: 1 }).done(function(res) {
            var pg = res.query.pages[Object.keys(res.query.pages)[0]];
            if (!pg || !pg.revisions) return;
            var requester = pg.revisions[0].user;
            var oldContent = pg.revisions[0]['*'];
            if (!$('#mw-content-text').text().includes("Permintaan Verifikasi Profil Pengguna")) return;

            var $panel = $('<div style="background:#f0f7ff; border:2px solid #0095f6; padding:15px; border-radius:12px; margin-bottom:15px; display:flex; flex-direction:column; gap:10px;">' +
                '<div><b style="color:#0095f6;">🔵 ADMIN VERIFICATION PANEL</b><br><small>Memproses permohonan: <b>'+requester+'</b></small></div></div>');
            
            var $btnGroup = $('<div style="display:flex; gap:10px;"></div>');
            var $btnApprove = $('<button>').text('✅ SETUJUI').css({'background':'#0095f6','color':'#fff','padding':'8px 15px','border':'none','border-radius':'6px','cursor':'pointer','font-weight':'bold'});
            var $btnReject = $('<button>').text('❌ TOLAK').css({'background':'#ff4d4d','color':'#fff','padding':'8px 15px','border':'none','border-radius':'6px','cursor':'pointer','font-weight':'bold'});

            // LOGIKA SETUJUI
            $btnApprove.click(function() {
                $(this).prop('disabled', true).text('Approving...');
                sessionStorage.setItem('is_system_verify', 'true');
                api.postWithToken('edit', { action: 'edit', title: targetUserPage, appendtext: '\n[[Category:Pengguna_Terverifikasi]]', summary: 'Akun Terverifikasi'
                }).then(function() {
                    // HAPUS DATA PRIVASI OTOMATIS SAAT DISETUJUI
                    var cleanText = oldContent.replace(/<div class='sysop-show'[\s\S]*?<\/div>/g, "''(Data identitas telah dihapus otomatis demi keamanan tingkat tinggi)''");
                    var newText = cleanText.replace("Status: 🕒 Sedang diverifikasi", "Status: ✅ '''Akun Terverifikasi''' 🔵");
                    return api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Approved & Purged Identity Data' });
                }).then(function() {
                    var msg = "\n== Selamat! Profil Anda Terverifikasi ==\nHalo [["+requester+"]],\n\nKabar gembira! Tim Pengurus Mippedia telah meninjau data identitas Anda dan memutuskan untuk **MENYETUJUI** permohonan verifikasi Anda. Akun Anda kini memiliki lencana centang biru 🔵 sebagai tanda kredibilitas asli.\n\nData identitas yang Anda kirimkan telah kami hapus secara otomatis dari sistem kami demi menjaga keamanan privasi Anda. Terima kasih telah berkontribusi di Mippedia! --[[Pengguna:Admin|Admin]]";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() { 
                    sessionStorage.removeItem('is_system_verify');
                    location.reload(); 
                });
            });

            // LOGIKA TOLAK
            $btnReject.click(function() {
                $(this).prop('disabled', true).text('Rejecting...');
                // HAPUS DATA PRIVASI OTOMATIS SAAT DITOLAK
                var cleanText = oldContent.replace(/<div class='sysop-show'[\s\S]*?<\/div>/g, "''(Data identitas telah dihapus otomatis demi keamanan tingkat tinggi)''");
                var newText = cleanText.replace("Status: 🕒 Sedang diverifikasi", "Status: ❌ '''Permintaan Ditolak'''");
                
                api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Rejected & Purged Identity Data'
                }).then(function() {
                    var msg = "\n== Informasi: Permintaan Verifikasi Belum Disetujui ==\nHalo [["+requester+"]],\n\nMohon maaf, setelah melakukan peninjauan terhadap data yang Anda kirimkan, Tim Pengurus Mippedia memutuskan untuk **BELUM DAPAT MENYETUJUI** permohonan verifikasi Anda saat ini. Hal ini bisa disebabkan oleh data yang kurang jelas atau tidak memenuhi kriteria verifikasi kami.\n\nJangan khawatir, data identitas sensitif yang Anda kirimkan sudah kami hapus secara otomatis demi keamanan Anda. Anda dapat mengajukan permohonan kembali di masa mendatang dengan data yang lebih lengkap. --[[Pengguna:Admin|Admin]]";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() { 
                    location.reload(); 
                });
            });

            $btnGroup.append($btnApprove, $btnReject);
            $panel.append($btnGroup);
            $('#mw-content-text').prepend($panel);
        });
    }
});

/* ==========================================================
   🛡️ 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 === 'Mippedia Patroli');
    
    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 = [];

        // --- 1. GLOBAL ENGINE: MAINTENANCE (FITUR ASLI) ---
        if ((!page.categories || page.categories.length === 0) && !/\{\{Butuh Kategori/i.test(content) && !/\[\[Kategori:/i.test(content)) {
            content = '{{Butuh Kategori|date=April 2026}}\n' + content;
            summaryParts.push('+Cat');
        }
        
        // --- UPGRADE ENGINE: DETEKSI SMART STUB PARAMETER & POSISI BAWAH ---
        var wordCount = rawContent.trim().split(/\s+/).length;
        if (wordCount < 200 && !/\{\{Stub/i.test(content) && !/\{\{Artikel Rintisan/i.test(content)) {
            var lowerContent = rawContent.toLowerCase();
            var stubParam = '';

            // Mapping Otak Pintar berdasarkan Kata Kunci Semantik (19 Parameter)
            if (/\b(lahir|wafat|tokoh|pria|wanita|biografi|sosok|pahlawan|presiden|menteri)\b/i.test(lowerContent)) {
                stubParam = 'biografi tokoh';
            } else if (/\b(musik|lagu|album|konser|penyanyi|band|vokal|gitar|single|nada)\b/i.test(lowerContent)) {
                stubParam = 'musik';
            } else if (/\b(geografi|negara|kota|desa|kecamatan|kabupaten|provinsi|pulau|gunung|sungai)\b/i.test(lowerContent)) {
                stubParam = 'geografi';
            } else if (/\b(teknologi|komputer|aplikasi|software|hardware|internet|digital|android|sistem|gawai)\b/i.test(lowerContent)) {
                stubParam = 'teknologi';
            } else if (/\b(sejarah|kerajaan|perang|prasasti|arkeo|masa lalu|kuno|dinasti|peristiwa|abad)\b/i.test(lowerContent)) {
                stubParam = 'sejarah';
            } else if (/\b(olahraga|atlet|sepak|bola|stadion|juara|klub|tanding|liga|olimpiade)\b/i.test(lowerContent)) {
                stubParam = 'olahraga';
            } else if (/\b(film|bioskop|aktor|aktris|sutradara|drama|sinema|serial|movie|tayang)\b/i.test(lowerContent)) {
                stubParam = 'film';
            } else if (/\b(perusahaan|pt|perbangkan|bisnis|saham|industri|korporasi|merek|ceo|didirikan)\b/i.test(lowerContent)) {
                stubParam = 'perusahaan';
            } else if (/\b(ilmu pengetahuan|sains|kimia|fisika|matematika|biologi|riset|laboratorium|teori|molekul)\b/i.test(lowerContent)) {
                stubParam = 'ilmu pengetahuan';
            } else if (/\b(seni|lukisan|patung|pameran|budaya|teater|rupa|desain|kriya|estetika)\b/i.test(lowerContent)) {
                stubParam = 'seni';
            } else if (/\b(politik|partai|pemilu|dpr|pemerintah|kebijakan|demokrasi|suara|kampanye|negara)\b/i.test(lowerContent)) {
                stubParam = 'politik';
            } else if (/\b(militer|tni|tentara|perang|senjata|pasukan|jenderal|alutsista|batalyon|operasi)\b/i.test(lowerContent)) {
                stubParam = 'militer';
            } else if (/\b(transportasi|kereta|pesawat|mobil|kapal|bandara|stasiun|pelabuhan|rute|kendaraan)\b/i.test(lowerContent)) {
                stubParam = 'transportasi';
            } else if (/\b(literatur|buku|novel|puisi|sastra|penulis|penerbit|komik|cerpen|fiksi)\b/i.test(lowerContent)) {
                stubParam = 'literatur';
            } else if (/\b(makanan|kuliner|resep|masakan|minuman|rasa|koki|restoran|hidangan|bahan)\b/i.test(lowerContent)) {
                stubParam = 'makanan';
            } else if (/\b(kesehatan|medis|dokter|penyakit|obat|rumah sakit|klinik|terapi|virus|gejala)\b/i.test(lowerContent)) {
                stubParam = 'kesehatan';
            } else if (/\b(astronomi|bintang|planet|galaksi|teleskop|antariksa|nasa|komet|orbit|luar angkasa)\b/i.test(lowerContent)) {
                stubParam = 'astronomi';
            } else if (/\b(agama|ibadah|kitab|tuhan|nabi|gereja|masjid|pura|vihara|iman)\b/i.test(lowerContent)) {
                stubParam = 'agama';
            } else if (/\b(bahasa|dialek|aksara|kamus|linguistik|kata|kalimat|suku|ucapan|fonem)\b/i.test(lowerContent)) {
                stubParam = 'bahasa';
            } else if (/\b(hukum|undang|pasal|pengadilan|hakim|jaksa|pengacara|pidana|perdata|legal)\b/i.test(lowerContent)) {
                stubParam = 'hukum';
            }

            // Gabungkan teks template Stub pilihan di baris paling bawah artikel
            var stubTag = stubParam ? '{{Stub|' + stubParam + '}}' : '{{Stub}}';
            content = content.trim() + '\n\n' + stubTag;
            summaryParts.push('+SmartStub(' + (stubParam || 'umum') + ')');
        }

        var promoList = ['memang hebat', 'terpercaya sekali', 'terbaik di dunia', 'hubungi nomor kami', 'harga murah', 'kualitas terjamin'];
        if (promoList.some(p => rawContent.toLowerCase().indexOf(p) !== -1) && !/\{\{Hapus/i.test(content)) {
            content = '{{Hapus|Deteksi kalimat promosi otomatis}}\n' + content;
            summaryParts.push('+Promo');
        }

        // --- 2. SUPER INTELLIGENCE RELATED (UPGRADE OTAK V12) ---
        var currentRelatedMatch = content.match(/\{\{#related:.*?\}\}/g) || [];
        
        if (currentRelatedMatch.length < 3) {
            content = content.replace(/\n*\{\{#related:.*?\}\}/g, '');

            api.get({
                action: 'query',
                list: 'search',
                srsearch: pageTitle,
                srlimit: 15,
                srprop: ''
            }).done(function(searchRes) {
                var candidates = {};

                if (searchRes.query && searchRes.query.search) {
                    searchRes.query.search.forEach(function(item, index) {
                        if (item.title === pageTitle) return;
                        candidates[item.title] = (15 - index);
                    });
                }

                if (page.links) {
                    page.links.forEach(function(link) {
                        if (link.title === pageTitle) return;
                        candidates[link.title] = (candidates[link.title] || 0) + 5;
                    });
                }

                var sortedTitles = Object.keys(candidates).sort(function(a, b) {
                    return candidates[b] - candidates[a];
                });

                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 = [];
                content = content.replace(/(\{\{[\s\S]*?\}\}|==+.*?==+|\[\[Kategori:.*?\]\]|<ref[\s\S]*?<\/ref>|^.*?adalah)/gi, function(match) {
                    placeholders.push(match);
                    return '___MIP_SKIP_' + (placeholders.length - 1) + '___';
                });

                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('');
                    
                    content = content.replace(/___MIP_SKIP_(\d+)___/g, function(match, id) { return placeholders[id]; });

                    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 DATA BUTTON ONLY (Otomatis)
   Hanya memunculkan tombol jika data tersedia di pusat.
   ========================================================== */
$(document).ready(function() {
    var pageName = mw.config.get('wgPageName');
    var namespace = mw.config.get('wgNamespaceNumber');
    var dataDomain = 'https://data.mippedia.org';

    // Jalankan hanya di namespace artikel
    if (namespace === 0) {
        // Cek apakah halaman tersebut ada di Mippedia Data
        $.ajax({
            url: dataDomain + '/api.php',
            data: { 
                action: 'query', 
                titles: pageName, 
                format: 'json', 
                origin: '*' 
            },
            dataType: 'jsonp',
            success: function(res) {
                var pages = res.query.pages;
                var isExist = false;
                
                // Cek apakah ID halaman > 0 (artinya halaman ada)
                for (var id in pages) {
                    if (parseInt(id) > 0) {
                        isExist = true;
                        break;
                    }
                }

                // Jika data ditemukan, munculkan tombol melayang
                if (isExist) {
                    injectFloatingDataBtn(pageName, dataDomain);
                }
            }
        });
    }

    function injectFloatingDataBtn(name, domain) {
        if ($('#mippedia-data-btn').length) return;

        var $btn = $('<a>', {
            id: 'mippedia-data-btn',
            href: domain + '/wiki/' + encodeURIComponent(name),
            target: '_blank',
            style: 'position: absolute; right: 10px; top: -32px; background: #36c; color: #fff; padding: 4px 10px; border-radius: 4px; font-weight: bold; font-size: 10px; text-decoration: none; z-index: 1000; box-shadow: 0 2px 4px rgba(0,0,0,0.1);',
            text: 'DATA'
        });

        // Target: Area menu aksi (dekat ikon pensil)
        // Mendukung skin Mobile (Minerva) dan Desktop
        var $target = $('.page-actions-menu, .mw-editsection-visualeditor, #ca-edit, .minerva__tab-container').first();
        
        if ($target.length) {
            $target.css('position', 'relative').append($btn);
        } else {
            // Fallback jika header tidak standar
            $('#firstHeading').css('position', 'relative').append($btn);
        }
    }
});

/* ==========================================================
   🚀 MIPPEDIA COMMAND CENTER: AUTO-SYNC ENGINE (V4)
   Status: Global Login User | Auto-Purge | High Reliability
   ========================================================== */
(function($, mw) {
    "use strict";

    var conf = mw.config.get(['wgNamespaceNumber', 'wgAction', 'wgPageName', 'wgIsMainPage', 'wgUserName']);
    // Filter: Hanya artikel, hanya saat baca, hanya user yang sudah login
    if (conf.wgNamespaceNumber !== 0 || conf.wgAction !== 'view' || conf.wgIsMainPage || conf.wgUserName === null) return;

    $(document).ready(function() {
        var currentTitle = conf.wgPageName;
        // Penentuan subdomain (id, en, concise)
        var hostParts = window.location.hostname.split('.');
        var langKey = hostParts[0] === 'mippedia' || hostParts[0] === 'www' ? 'id' : hostParts[0];

        $.ajax({
            url: 'https://data.mippedia.org/api.php',
            data: { 
                action: 'query', 
                prop: 'revisions', 
                titles: 'MediaWiki:ShortDesc-Data.json', 
                rvprop: 'content', 
                format: 'json', 
                origin: '*' 
            },
            dataType: 'jsonp',
            success: function(res) {
                try {
                    var pages = res.query.pages;
                    var pageId = Object.keys(pages)[0];
                    if (pageId === "-1") return;

                    var fullData = JSON.parse(pages[pageId].revisions[0]['*']);
                    var targetDesc = (fullData[currentTitle] && fullData[currentTitle][langKey]) ? fullData[currentTitle][langKey].trim() : "";

                    syncMetadata(currentTitle, targetDesc);
                } catch (e) { 
                    console.log("Mippedia System: Data sync not required or entry missing."); 
                }
            }
        });

        function syncMetadata(title, dataCenterDesc) {
            var api = new mw.Api();
            api.get({ 
                action: 'query', 
                prop: 'revisions', 
                titles: title, 
                rvprop: 'content', 
                formatversion: 2 
            }).done(function(data) {
                var content = data.query.pages[0].revisions[0].content;
                var shortDescPattern = /\{\{SHORTDESC:.*?\}\}\n?/gi;
                var hasLocalDesc = shortDescPattern.test(content);
                
                var localMatch = content.match(/\{\{SHORTDESC:(.*?)\}\}/i);
                var currentLocalDesc = localMatch ? localMatch[1].trim() : "";

                // AKSI 1: HAPUS (Jika di pusat kosong/dihapus, tapi di artikel lokal masih ada)
                if (dataCenterDesc === "" && hasLocalDesc) {
                    console.log("Mippedia: Purging metadata...");
                    saveEdit(title, content.replace(shortDescPattern, ""), "Purge out-of-sync metadata");
                } 
                // AKSI 2: UPDATE/TAMBAH (Jika data di pusat ada dan beda dengan lokal)
                else if (dataCenterDesc !== "" && dataCenterDesc !== currentLocalDesc) {
                    console.log("Mippedia: Syncing with Data Center...");
                    var cleanedContent = content.replace(shortDescPattern, "");
                    // Menaruh di paling atas agar terbaca Extension ShortDescription
                    var newContent = '{{SHORTDESC:' + dataCenterDesc + '}}\n' + cleanedContent;
                    saveEdit(title, newContent, "Sync metadata: " + dataCenterDesc);
                }
            });
        }

        function saveEdit(title, text, summary) {
            // Menggunakan token user yang sedang login saat ini
            new mw.Api().postWithEditToken({
                action: 'edit',
                title: title,
                text: text,
                summary: '🤖 ' + summary,
                minor: true // Menandai sebagai suntingan kecil
                // Parameter 'bot: true' DIHAPUS agar bisa dijalankan semua pengguna login
            }).done(function() {
                console.log("Mippedia: " + title + " synced successfully.");
            });
        }
    });
})(jQuery, mediaWiki);

/* ==========================================================
   🚀 MIPPEDIA METADATA GUARD - RADAR SYSTEM (V5)
   Status: Professional Messaging | Hybrid Mobile/Desktop
   ========================================================== */
(function($, mw) {
    "use strict";

    var ns = mw.config.get('wgNamespaceNumber');
    if (ns !== 0 || mw.config.get('wgIsMainPage')) return;

    var shortDescRegex = /\{\{SHORTDESC:.*?\}\}/gi;
    var originalShortDesc = null;

    function validateAndBlock(e) {
        var $textbox = $('#wpTextbox1, textarea.previewable-render, .editor-container textarea, textarea[name="wpTextbox1"]');
        if (!$textbox.length) return true;

        var currentContent = $textbox.val() || "";
        var currentMatch = currentContent.match(shortDescRegex);
        var currentShortDesc = currentMatch ? currentMatch[0] : "";

        if (originalShortDesc === null) {
            originalShortDesc = currentShortDesc;
            return true;
        }

        if (originalShortDesc !== currentShortDesc) {
            // --- PESAN PROFESIONAL BARU ---
            window.alert(
                "MIPPEDIA SYSTEM NOTIFICATION\n" +
                "────────────────────────────\n\n" +
                "Suntingan anda tidak bisa di lanjutkan untuk di terbitkan, Karena sinkronisasi otomatis terdeteksi tidak valid.\n\n" +
                "Untuk menjaga integritas metadata, deskripsi singkat (ShortDescription) wajib dikelola melalui repositori Mippedia Data.\n\n" +
                "Harap urungkan perubahan manual pada kode {{SHORTDESC}} untuk melanjutkan proses penyimpanan."
            );
            
            e.preventDefault();
            e.stopPropagation();
            e.stopImmediatePropagation();
            return false;
        }
        return true;
    }

    // Radar untuk menangkap elemen editor saat muncul (terutama di Mobile)
    var observer = new MutationObserver(function() {
        var $textbox = $('#wpTextbox1, .editor-container textarea, textarea[name="wpTextbox1"]');
        if ($textbox.length && originalShortDesc === null) {
            var content = $textbox.val() || "";
            var match = content.match(shortDescRegex);
            originalShortDesc = match ? match[0] : "";
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });

    // Event listener untuk tombol simpan di berbagai platform
    $(document).on('click mousedown touchstart', 
        '#wpSave, .mw-ui-button.primary, button.submit, .editor-save, .save-button, button[type="submit"]', 
        function(e) {
            return validateAndBlock(e);
        }
    );

    window.addEventListener('submit', function(e) {
        if (!validateAndBlock(e)) e.preventDefault();
    }, true);

})(jQuery, mediaWiki);

$(function() {
    $('.ambox-learn-more').on('click', function(e) {
        e.preventDefault();
        var $parentBox = $(this).closest('.ambox');
        
        $parentBox.toggleClass('ambox-active');
        $parentBox.find('.ambox-text-long').slideToggle('fast');
        
        // Ubah teks tombol pas dibuka
        if ($parentBox.hasClass('ambox-active')) {
            $(this).text('Sembunyikan');
        } else {
            $(this).text('Pelajari selengkapnya');
        }
    });
});