MediaWiki:Common.js: Perbedaan antara revisi

Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Tidak ada ringkasan suntingan
 
(7 revisi perantara oleh pengguna yang sama tidak ditampilkan)
Baris 1: Baris 1:
/**
/**
  * ====================================================================
  * ====================================================================
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.6 SECURE ULTIMATE)
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.7 SECURE ULTIMATE)
  * Fitur: ALL ORIGINAL V7/V8 FEATURES KEPT + Premium Verified Badge,  
  * Fitur: ALL ORIGINAL V8 FEATURES KEPT + Global Social Media Box,  
  * Ultra-Strict OWASP XSS Security, Stricter URL Parsing, Mobile Optimized.
  * Smart Autocomplete/Preview Wikilink, Ultra-Strict Security, Mobile Ready.
  * ====================================================================
  * ====================================================================
  */
  */
Baris 66: Baris 66:
         ];
         ];


         // 3. IKON SISTEM (Centang Biru Diperbarui ke Versi Premium Rosette)
         // 3. IKON SISTEM  
         var svgEdit = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>';
         var svgEdit = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>';
         var svgLock = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>';
         var svgLock = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>';
Baris 74: Baris 74:
         var svgSearch = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';
         var svgSearch = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';
         var svgCode = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>';
         var svgCode = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>';
        // NEW PREMIUM VERIFIED BADGE
         var svgVerified = '<svg width="15" height="15" viewBox="0 0 24 24" fill="#3b82f6" stroke="#ffffff" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>';
         var svgVerified = '<svg width="16" height="16" viewBox="0 0 24 24" fill="#1d9bf0" xmlns="http://www.w3.org/2000/svg"><path d="M22.5 12.5l-1.58 1.95.23 2.5-2.47.53-1.12 2.23-2.43-.88-1.8 1.76-2.33-1.07-2.33 1.07-1.8-1.76-2.43.88-1.12-2.23-2.47-.53.23-2.5L1.5 12.5l1.58-1.95-.23-2.5 2.47-.53 1.12-2.23 2.43.88 1.8-1.76 2.33 1.07 2.33-1.07 1.8 1.76 2.43-.88 1.12 2.23 2.47.53-.23 2.5L22.5 12.5z" stroke="#ffffff" stroke-width="1"></path><path d="M9.5 15.5l-3-3 1.4-1.4 1.6 1.6 4.6-4.6 1.4 1.4-6 6z" fill="#ffffff"></path></svg>';
         var svgHelp = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>';
         var svgHelp = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>';


         // 4. HELPER UTILITY & ADVANCED SECURITY (Tingkat Tinggi OWASP)
         // 4. HELPER UTILITY & ADVANCED SECURITY
         function sanitizeHTML(str) {
         function sanitizeHTML(str) {
             if (typeof str !== 'string') return str;
             if (typeof str !== 'string') return str;
            // Enhanced OWASP-style sanitization to prevent ANY bypasses
             return str.replace(/[&<>"'`=\/]/g, function(s) {
             return str.replace(/[&<>"'`=\/]/g, function(s) {
                 return {
                 return {
Baris 114: Baris 112:
             if (!urlStr) return '';
             if (!urlStr) return '';
             urlStr = urlStr.trim();
             urlStr = urlStr.trim();
            // Ultra-Strict URL Protocol validation to completely neutralize all XSS vectors in hrefs
             var protoMatch = urlStr.match(/^([a-z0-9]+):/i);
             var protoMatch = urlStr.match(/^([a-z0-9]+):/i);
             if (protoMatch) {
             if (protoMatch) {
Baris 130: Baris 127:
         }
         }


         // 5. STYLESHEET  
         // 5. STYLESHEET (TERMASUK LAYOUT MEDIA SOSIAL GLOBAL & AUTOCOMPLETE)
         var css = `
         var css = `
             #mippedia-data-app {
             #mippedia-data-app {
Baris 154: Baris 151:
             .md-search-input:focus { background: #fff; border-color: #4f46e5; outline: none; }
             .md-search-input:focus { background: #fff; border-color: #4f46e5; outline: none; }
             .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #94a3b8; }
             .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #94a3b8; }
            /* Kotak Global Sosial Media Terpisah di Atas */
            .md-global-social-box { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.02); }
            .md-social-box-title { font-size: 0.85rem; font-weight: 800; color: #475569; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 12px; border-bottom: 1px dashed #cbd5e1; padding-bottom: 8px; }
            .md-social-group { display: flex; flex-wrap: wrap; gap: 8px; }
            .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; color: white !important; text-decoration: none !important; transition: transform 0.2s, opacity 0.2s; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
            .md-social-badge:hover { transform: translateY(-2px); opacity: 0.92; }


             .md-row-display { display: flex; justify-content: space-between; align-items: flex-start; padding: 16px 12px; border-bottom: 1px solid #f1f5f9; transition: all 0.2s; border-radius: 12px; gap: 12px; margin-bottom: 8px; background: #fff; }
             .md-row-display { display: flex; justify-content: space-between; align-items: flex-start; padding: 16px 12px; border-bottom: 1px solid #f1f5f9; transition: all 0.2s; border-radius: 12px; gap: 12px; margin-bottom: 8px; background: #fff; }
Baris 165: Baris 169:
             .md-btn-copy { background: none; border: none; color: #94a3b8; cursor: pointer; padding: 2px 4px; border-radius: 4px; transition: 0.2s; display: inline-flex; align-items: center; }
             .md-btn-copy { background: none; border: none; color: #94a3b8; cursor: pointer; padding: 2px 4px; border-radius: 4px; transition: 0.2s; display: inline-flex; align-items: center; }
             .md-btn-copy:hover { color: #4f46e5; background: #e0e7ff; }
             .md-btn-copy:hover { color: #4f46e5; background: #e0e7ff; }
            .md-social-group { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
            .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 18px; font-size: 0.78rem; font-weight: 600; color: white; text-decoration: none; transition: transform 0.2s, opacity 0.2s; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
            .md-social-badge:hover { transform: translateY(-2px); opacity: 0.92; color: white; text-decoration: none; }


             .md-ref-container { margin-top: 10px; width: 100%; box-sizing: border-box; }
             .md-ref-container { margin-top: 10px; width: 100%; box-sizing: border-box; }
Baris 190: Baris 190:
             .md-form-group { margin-bottom: 14px; }
             .md-form-group { margin-bottom: 14px; }
             .md-form-group label { display: flex; align-items:center; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: #334155; }
             .md-form-group label { display: flex; align-items:center; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: #334155; }
           
             .md-input, .md-select, .md-textarea { width: 100%; padding: 9px 12px; border: 1px solid #cbd5e1; border-radius: 8px; box-sizing: border-box; font-family: inherit; font-size: 0.9rem; transition: 0.2s; background: #fff; }
             .md-input, .md-select, .md-textarea { width: 100%; padding: 9px 12px; border: 1px solid #cbd5e1; border-radius: 8px; box-sizing: border-box; font-family: inherit; font-size: 0.9rem; transition: 0.2s; background: #fff; }
             .md-input:focus, .md-select:focus, .md-textarea:focus { border-color: #4f46e5; outline: none; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); }
             .md-input:focus, .md-select:focus, .md-textarea:focus { border-color: #4f46e5; outline: none; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); }
              
              
            /* Autocomplete Styles */
            .md-autocomplete-wrapper { position: relative; width: 100%; }
            .md-autocomplete-list { position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 1px solid #cbd5e1; border-radius: 0 0 8px 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); z-index: 1000; display: none; max-height: 200px; overflow-y: auto; margin-top: -2px; }
            .md-autocomplete-item { padding: 10px 12px; font-size: 0.88rem; color: #0f172a; cursor: pointer; border-bottom: 1px solid #f1f5f9; transition: 0.2s; display: flex; align-items: center; gap: 8px; }
            .md-autocomplete-item:last-child { border-bottom: none; }
            .md-autocomplete-item:hover { background: #f8fafc; color: #4f46e5; padding-left: 16px; }
             .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f8fafc; padding: 12px; border-radius: 8px; border: 1px dashed #cbd5e1; }
             .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f8fafc; padding: 12px; border-radius: 8px; border: 1px dashed #cbd5e1; }
             .md-social-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f1f5f9; padding: 12px; border-radius: 8px; border: 1px solid #cbd5e1; max-height: 280px; overflow-y: auto; }
             .md-social-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f1f5f9; padding: 12px; border-radius: 8px; border: 1px solid #cbd5e1; max-height: 280px; overflow-y: auto; }
Baris 233: Baris 241:
                 .md-row-display { padding: 12px 10px; flex-direction:column; align-items:stretch;}
                 .md-row-display { padding: 12px 10px; flex-direction:column; align-items:stretch;}
                 .edit-btn { align-self:flex-end; margin-top:8px; }
                 .edit-btn { align-self:flex-end; margin-top:8px; }
                /* Memastikan elemen panah menu rujukan tidak tergencet di layar kecil */
                 .md-ref-details summary { align-items: flex-start; }
                 .md-ref-details summary { align-items: flex-start; }
             }
             }
Baris 240: Baris 247:
         $('<style>').text(css).appendTo('head');
         $('<style>').text(css).appendTo('head');


         // 6. POPUP, MODAL & TOOLTIPS (FIXED POSITION & SECURE)
         // 6. POPUP, MODAL & TOOLTIPS  
         function showModal(title, text) {
         function showModal(title, text) {
             $('.md-modal-overlay').remove();
             $('.md-modal-overlay').remove();
Baris 255: Baris 262:
                 e.stopPropagation();
                 e.stopPropagation();
                 var $icon = $(this);
                 var $icon = $(this);
                // Menggunakan sanitize untuk mengamankan atribut sebelum diletakkan di DOM
                 var text = sanitizeHTML($icon.data('help'));  
                 var text = sanitizeHTML($icon.data('help'));  
                 var $tt = $('<div class="md-tooltip-popup">' + text + '</div>');
                 var $tt = $('<div class="md-tooltip-popup">' + text + '</div>');
Baris 265: Baris 271:
                 var leftPos = offset.left - 15;
                 var leftPos = offset.left - 15;
                  
                  
                // Mencegah tooltip terpotong di tepi kanan layar (Smart Shift Position)
                 if (leftPos + ttWidth > winWidth - 15) leftPos = winWidth - ttWidth - 15;
                 if (leftPos + ttWidth > winWidth - 15) {
                 if (leftPos < 10) leftPos = 10;
                    leftPos = winWidth - ttWidth - 15;
                }
                // Mencegah terpotong di tepi kiri
                 if (leftPos < 10) {
                    leftPos = 10;
                }
                  
                  
                 $tt.css({ top: offset.top - $tt.outerHeight() - 10, left: leftPos }).fadeIn(200);
                 $tt.css({ top: offset.top - $tt.outerHeight() - 10, left: leftPos }).fadeIn(200);
Baris 335: Baris 335:
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
              
              
             var summaryTxt = customSummary ? ('Mippedia Data: ' + customSummary) : ('Mippedia Data V8.6: ' + actionType);
             var summaryTxt = customSummary ? ('Mippedia Data: ' + customSummary) : ('Mippedia Data V8.7: ' + actionType);
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n";
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n";
Baris 397: Baris 397:
             $app.append($header);
             $app.append($header);


            // Tampilkan kotak pencarian jika data banyak
             if (dataItems.length > 2) {
             if (dataItems.length > 2) {
                 var $searchBox = $('<div class="md-search-box"><span class="md-search-icon">' + svgSearch + '</span><input type="text" class="md-search-input" placeholder="Cari data terstruktur..."></div>');
                 var $searchBox = $('<div class="md-search-box"><span class="md-search-icon">' + svgSearch + '</span><input type="text" class="md-search-input" placeholder="Cari data terstruktur..."></div>');
Baris 407: Baris 408:
                 });
                 });
                 $app.append($searchBox);
                 $app.append($searchBox);
            }
            // MENGUMPULKAN MEDIA SOSIAL GLOBAL (Memisahkan media sosial ke atas)
            var globalSocials = {};
            dataItems.forEach(function(item) {
                if (item.isPersonOrg && item.socials) {
                    Object.assign(globalSocials, item.socials);
                }
            });
            if (Object.keys(globalSocials).length > 0) {
                var $topSocials = $('<div class="md-global-social-box"></div>');
                $topSocials.append('<div class="md-social-box-title">Media Sosial & Platform Resmi</div>');
                var $socialGroupGlobal = $('<div class="md-social-group"></div>');
               
                Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                    var uname = globalSocials[key];
                    if (uname) {
                        var platform = SOCIAL_PLATFORMS[key];
                        var fullUrl = platform.base + uname.replace(/^@/, '');
                        var $badge = $('<a class="md-social-badge" href="' + sanitizeHTML(fullUrl) + '" target="_blank" rel="noopener noreferrer" style="background:' + platform.color + ';">' + platform.icon + ' ' + sanitizeHTML(platform.name) + '</a>');
                        $socialGroupGlobal.append($badge);
                    }
                });
                $topSocials.append($socialGroupGlobal);
                $app.append($topSocials);
             }
             }


Baris 451: Baris 478:
                     $valWrap.append($copyBtn);
                     $valWrap.append($copyBtn);
                     $info.append($valWrap);
                     $info.append($valWrap);
                    if (item.isPersonOrg && item.socials) {
                        var $socialGroup = $('<div class="md-social-group"></div>');
                        var hasSocial = false;
                        Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                            var uname = item.socials[key];
                            if (uname) {
                                hasSocial = true;
                                var platform = SOCIAL_PLATFORMS[key];
                                var fullUrl = platform.base + uname.replace(/^@/, '');
                                var $badge = $('<a class="md-social-badge" href="' + sanitizeHTML(fullUrl) + '" target="_blank" rel="noopener noreferrer" style="background:' + platform.color + ';">' + platform.icon + ' ' + sanitizeHTML(platform.name) + '</a>');
                                $socialGroup.append($badge);
                            }
                        });
                        if (hasSocial) $info.append($socialGroup);
                    }
                      
                      
                     if (item.ref && (item.ref.url || item.ref.title)) {
                     if (item.ref && (item.ref.url || item.ref.title)) {
Baris 565: Baris 576:
              
              
             var $valBox = $('<div class="md-form-group"></div>');
             var $valBox = $('<div class="md-form-group"></div>');
             $valBox.append('<label>Nilai Data <span class="md-help-icon" data-help="Isi dari data tersebut (contoh: Penyanyi, 15 April 2003). Centang opsi di bawah jika ingin jadikan teks ini sebagai link biru (Wikilink).">' + svgHelp + '</span></label>');
             $valBox.append('<label>Nilai Data <span class="md-help-icon" data-help="Ketik nilai. Jika halaman sudah ada di Wiki, saran akan muncul (pratinjau) dan otomatis mencentang opsi Wikilink.">' + svgHelp + '</span></label>');
             $valBox.append('<input type="text" id="md-inp-val" class="md-input" value="' + sanitizeHTML(currentData.val || '') + '">');
              
            // FITUR AUTOCOMPLETE PRATINJAU DIMULAI DI SINI
            var $autoWrap = $('<div class="md-autocomplete-wrapper"></div>');
            var $valInput = $('<input type="text" id="md-inp-val" class="md-input" autocomplete="off" value="' + sanitizeHTML(currentData.val || '') + '">');
            var $autoList = $('<div class="md-autocomplete-list"></div>');
            $autoWrap.append($valInput).append($autoList);
            $valBox.append($autoWrap);
              
              
             var $wikilinkOpts = $('<div style="margin-top:8px; display:flex; flex-direction:column; gap:8px; background:#f8fafc; padding:10px; border-radius:8px; border:1px solid #e2e8f0;"></div>');
             var $wikilinkOpts = $('<div style="margin-top:8px; display:flex; flex-direction:column; gap:8px; background:#f8fafc; padding:10px; border-radius:8px; border:1px solid #e2e8f0;"></div>');
Baris 572: Baris 589:
             var chkSplit = currentData.linkSplit ? 'checked' : '';
             var chkSplit = currentData.linkSplit ? 'checked' : '';
              
              
             $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"><input type="checkbox" id="md-inp-link" ' + chkLink + '> Jadikan Wikilink Standar</label>');
             var $linkCheck = $('<input type="checkbox" id="md-inp-link" ' + chkLink + '>');
            var $lblLinkCheck = $('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"></label>');
            $lblLinkCheck.append($linkCheck).append(' Jadikan Wikilink Standar');
 
            // Logika pratinjau ketika diketik
            var isAutoChecked = false;
            $valInput.on('input', function() {
                var q = $(this).val();
               
                // Jika input dikosongkan/berubah, kembalikan centang link ke false jika tadinya otomatis centang
                if (isAutoChecked) {
                    $linkCheck.prop('checked', false);
                    isAutoChecked = false;
                }
 
                if(q.length < 1) {
                    $autoList.empty().hide();
                    return;
                }
 
                // Panggil API MediaWiki Prefix Search
                api.get({
                    action: 'query',
                    list: 'prefixsearch',
                    pssearch: q,
                    pslimit: 6,
                    format: 'json'
                }).done(function(data) {
                    $autoList.empty();
                    if(data.query && data.query.prefixsearch && data.query.prefixsearch.length > 0) {
                        data.query.prefixsearch.forEach(function(res) {
                            var $item = $('<div class="md-autocomplete-item">' + svgSearch + ' ' + sanitizeHTML(res.title) + '</div>');
                            $item.on('click', function() {
                                $valInput.val(res.title);
                                $autoList.empty().hide();
                                $linkCheck.prop('checked', true); // OTOMATIS TERCENTANG
                                isAutoChecked = true;
                            });
                            $autoList.append($item);
                        });
                        $autoList.show();
                    } else {
                        $autoList.hide();
                    }
                });
            });
 
            // Sembunyikan pratinjau saat klik di luar
            $(document).on('click.mdauto', function(e) {
                if(!$(e.target).closest('.md-autocomplete-wrapper').length) {
                    $autoList.hide();
                }
            });
 
            $wikilinkOpts.append($lblLinkCheck);
             $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"><input type="checkbox" id="md-inp-split" ' + chkSplit + '> Smart Split Wikilink</label>');
             $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"><input type="checkbox" id="md-inp-split" ' + chkSplit + '> Smart Split Wikilink</label>');
             var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:#475569; margin-bottom:4px;">Target Halaman Khusus (Opsional):</label><input type="text" id="md-inp-target" class="md-input" style="padding:6px 10px; font-size:0.85rem;" placeholder="Contoh: Diskografi Rumi Haitami" value="' + sanitizeHTML(currentData.linkTarget || '') + '"></div>');
             var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:#475569; margin-bottom:4px;">Target Halaman Khusus (Opsional):</label><input type="text" id="md-inp-target" class="md-input" style="padding:6px 10px; font-size:0.85rem;" placeholder="Contoh: Diskografi Rumi Haitami" value="' + sanitizeHTML(currentData.linkTarget || '') + '"></div>');
Baris 581: Baris 652:
             var $socialSec = $('<div class="md-form-group" style="margin-top:16px;"></div>');
             var $socialSec = $('<div class="md-form-group" style="margin-top:16px;"></div>');
             var chkPerson = currentData.isPersonOrg ? 'checked' : '';
             var chkPerson = currentData.isPersonOrg ? 'checked' : '';
             $socialSec.append('<label style="display:flex; align-items:center; gap:8px; cursor:pointer; background:#e0e7ff; padding:10px; border-radius:8px; font-weight:700; color:#3730a3; font-size:0.85rem;"><input type="checkbox" id="md-chk-person" ' + chkPerson + '> Aktifkan Profil Media Sosial & Musik <span class="md-help-icon" data-help="Centang ini untuk memunculkan tombol-tombol sosial media (Spotify, YouTube, IG, dll) di bawah nilai data.">' + svgHelp + '</span></label>');
             $socialSec.append('<label style="display:flex; align-items:center; gap:8px; cursor:pointer; background:#e0e7ff; padding:10px; border-radius:8px; font-weight:700; color:#3730a3; font-size:0.85rem;"><input type="checkbox" id="md-chk-person" ' + chkPerson + '> Simpan Profil Media Sosial (Akan muncul di paling atas) <span class="md-help-icon" data-help="Centang ini untuk mengisi data sosial media. Datanya akan dihimpun dan dimunculkan di kotak teratas data struktur.">' + svgHelp + '</span></label>');
              
              
             var $socialGrid = $('<div class="md-social-grid" id="md-social-box" style="display:' + (currentData.isPersonOrg ? 'grid' : 'none') + '; margin-top:8px;"></div>');
             var $socialGrid = $('<div class="md-social-grid" id="md-social-box" style="display:' + (currentData.isPersonOrg ? 'grid' : 'none') + '; margin-top:8px;"></div>');
Baris 1.286: Baris 1.357:
             '<div style="font-size:11px; color:#718096; font-weight:800; text-transform:uppercase; letter-spacing:1px; margin-bottom:10px;">Lisensi, Atribusi & Penggunaan Data</div>' +
             '<div style="font-size:11px; color:#718096; font-weight:800; text-transform:uppercase; letter-spacing:1px; margin-bottom:10px;">Lisensi, Atribusi & Penggunaan Data</div>' +
             '<p style="margin:0 0 10px; font-size:13px; color:#4a5568; line-height:1.6;">' +
             '<p style="margin:0 0 10px; font-size:13px; color:#4a5568; line-height:1.6;">' +
             'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah lisensi resmi ' +
             'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah ' +
             '<a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" style="color:#6a5acd; text-decoration:none; font-weight:700;">Creative Commons Attribution-ShareAlike 4.0 International</a>.' +
             '<a href="https://creativecommons.org/publicdomain/zero/1.0/"target="_blank" style="color:#6a5acd; text-decoration:none; font-weight:700;">Lisensi Creative Commons CC0</a>.' +
             '</p>' +
             '</p>' +
             '<p style="margin:0; font-size:12px; color:#a0aec0;">Akses API dan penggunaan data secara massal wajib mencantumkan atribusi kepada <strong>Mippedia Community</strong> selaku pengelola proyek.</p></div>';
             '<p style="margin:0; font-size:12px; color:#a0aec0;">Akses API dan penggunaan data secara massal wajib mencantumkan atribusi kepada <strong>Mippedia Community</strong> selaku pengelola proyek.</p></div>';