MediaWiki:Common.js: Perbedaan antara revisi

Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Tidak ada ringkasan suntingan
Tanda: Pengembalian manual Suntingan perangkat seluler Suntingan peramban seluler
 
(46 revisi perantara oleh pengguna yang sama 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);
});
/* 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 311: 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 414: 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.127: 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.144: 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.162: 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.202: 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.208: 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.232: 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.263: Baris 1.022:


/* ==========================================================
/* ==========================================================
   🚀 MIPPEDIA OMNI-AUTO v5 (Mobile & Desktop Optimized)
   🚀 MIPPEDIA DATA BUTTON ONLY (Otomatis)
   Fix: Auto-Position, Data Button, & Social Media Whitelist
   Hanya memunculkan tombol jika data tersedia di pusat.
   ========================================================== */
   ========================================================== */
$(document).ready(function() {
$(document).ready(function() {
Baris 1.271: Baris 1.030:
     var dataDomain = 'https://data.mippedia.org';
     var dataDomain = 'https://data.mippedia.org';


    // Jalankan hanya di namespace artikel
     if (namespace === 0) {
     if (namespace === 0) {
         // 1. CEK DATA KE PUSAT
         // Cek apakah halaman tersebut ada di Mippedia Data
         $.ajax({
         $.ajax({
             url: dataDomain + '/api.php',
             url: dataDomain + '/api.php',
             data: { action: 'parse', page: pageName, prop: 'text', format: 'json', origin: '*' },
             data: {  
                action: 'query',  
                titles: pageName,  
                format: 'json',  
                origin: '*'  
            },
             dataType: 'jsonp',
             dataType: 'jsonp',
             success: function(data) {
             success: function(res) {
                 if (data.parse && data.parse.text) {
                 var pages = res.query.pages;
                    var $html = $(data.parse.text['*']);
                var isExist = false;
                    var $infobox = $html.find('table.infobox');
               
 
                // Cek apakah ID halaman > 0 (artinya halaman ada)
                    if ($infobox.length) {
                for (var id in pages) {
                        // Jalankan fungsi suntik tombol data
                    if (parseInt(id) > 0) {
                        injectMippediaDataBtn(pageName);
                        isExist = true;
 
                        break;
                        // FIX GAMBAR: Ambil dari jalur lokal wiki
                    }
                        $infobox.find('img, .image').each(function() {
                }
                            var $imgObj = $(this).is('img') ? $(this) : $(this).find('img');
                            var fileName = $imgObj.attr('alt') || $imgObj.data('file-name');
                            if (fileName) {
                                $(this).attr('src', '/thumb.php?f=' + encodeURIComponent(fileName) + '&w=400');
                                $(this).attr('srcset', '');
                            }
                        });


                        // WHITELIST: Lindungi link medsos & URL luar
                // Jika data ditemukan, munculkan tombol melayang
                        $infobox.find('a').each(function() {
                if (isExist) {
                            var href = $(this).attr('href') || '';
                    injectFloatingDataBtn(pageName, dataDomain);
                            var text = $(this).text().trim();
                            if (href.indexOf('http') === 0 || text.length <= 4) {
                                $(this).addClass('is-safe-link');
                            } else {
                                var cleanTitle = text.replace(/\s*\(.*?\)\s*/g, '').trim();
                                $(this).attr('title', cleanTitle).text(cleanTitle);
                            }
                        });
 
                        // 2. PENEMPATAN INFOBOX (KHUSUS MOBILE & DESKTOP)
                        // Gunakan interval singkat untuk memastikan elemen konten sudah siap
                        var placementTimer = setInterval(function() {
                            var $contentBody = $('#mw-content-text .mw-parser-output');
                            if ($contentBody.length) {
                                var $firstP = $contentBody.find('> p').filter(function() {
                                    return $(this).text().trim().length > 15;
                                }).first();
 
                                if ($firstP.length) {
                                    $firstP.after($infobox);
                                    clearInterval(placementTimer);
                                } else if ($contentBody.length) {
                                    $contentBody.prepend($infobox);
                                    clearInterval(placementTimer);
                                }
                                // Jalankan cek link biru/merah
                                checkInternalLinks($infobox);
                            }
                        }, 500);
                       
                        // Stop timer setelah 5 detik jika gagal (mencegah loop)
                        setTimeout(function() { clearInterval(placementTimer); }, 5000);
                    }
                 }
                 }
             }
             }
Baris 1.337: Baris 1.062:
     }
     }


     function injectMippediaDataBtn(name) {
     function injectFloatingDataBtn(name, domain) {
         if ($('#mippedia-data-btn').length === 0) {
         if ($('#mippedia-data-btn').length) return;
            var dataUrl = dataDomain + '/wiki/' + encodeURIComponent(name);
            var $btn = $('<div id="mippedia-data-btn" style="margin: 12px 0;">')
                .append($('<a>', {
                    href: dataUrl,
                    target: '_blank',
                    style: 'background: #36c; color: #fff; padding: 8px 14px; border-radius: 6px; font-weight: bold; text-decoration: none; display: inline-block; font-size: 12px; box-shadow: 0 2px 5px rgba(0,0,0,0.2);',
                    text: 'LIHAT DI MIPPEDIA DATA'
                }));


             // Support untuk Mobile (Minerva) dan Desktop (Vector)
        var $btn = $('<a>', {
            var $header = $('.estimasi-baca-container, .minerva__subtitle, #siteSub, #contentSub').last();
             id: 'mippedia-data-btn',
            if ($header.length) {  
            href: domain + '/wiki/' + encodeURIComponent(name),
                $header.after($btn);  
            target: '_blank',
            } else {  
            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);',
                $('#firstHeading').after($btn);  
            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";


     function checkInternalLinks($container) {
     var conf = mw.config.get(['wgNamespaceNumber', 'wgAction', 'wgPageName', 'wgIsMainPage', 'wgUserName']);
        var titles = [];
    // Filter: Hanya artikel, hanya saat baca, hanya user yang sudah login
        $container.find('a:not(.is-safe-link)').each(function() {
    if (conf.wgNamespaceNumber !== 0 || conf.wgAction !== 'view' || conf.wgIsMainPage || conf.wgUserName === null) return;
            var t = $(this).attr('title');
            if (t) titles.push(t);
        });


         if (titles.length === 0) 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({
         $.ajax({
             url: mw.util.wikiScript('api'),
             url: 'https://data.mippedia.org/api.php',
             data: { action: 'query', titles: titles.join('|'), format: 'json' },
             data: {  
                action: 'query',  
                prop: 'revisions',
                titles: 'MediaWiki:ShortDesc-Data.json',
                rvprop: 'content',  
                format: 'json',
                origin: '*'
            },
            dataType: 'jsonp',
             success: function(res) {
             success: function(res) {
                 var pages = res.query.pages;
                 try {
                var existMap = {};
                    var pages = res.query.pages;
                for (var id in pages) {
                    var pageId = Object.keys(pages)[0];
                     if (parseInt(id) > 0) existMap[pages[id].title] = true;
                    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.");  
                 }
                 }
                $container.find('a:not(.is-safe-link)').each(function() {
                    var myTitle = $(this).attr('title');
                    if (existMap[myTitle]) {
                        $(this).removeClass('new').attr('href', mw.util.getUrl(myTitle));
                    } else {
                        $(this).addClass('new').attr('href', mw.util.getUrl(myTitle, { action: 'edit', redlink: '1' }));
                    }
                });
             }
             }
         });
         });
        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');
        }
    });
});
});