MediaWiki:Common.js: Difference between revisions
Aparência da Noite
Restaurado botao Inserir no VisualEditor com try/catch |
JS completo reescrito: VE + toolbar + botoes + animacao (chaves validadas) |
||
| Line 6: | Line 6: | ||
'use strict'; | 'use strict'; | ||
/* | /* 1. CENSURA & REVELAÇÃO DINÂMICA */ | ||
function initVtmSecrets() { | function initVtmSecrets() { | ||
var els = document.querySelectorAll('[data-vtm-secret="true"]'); | var els = document.querySelectorAll('[data-vtm-secret="true"]'); | ||
if (!els || !els.length) return; | if (!els || !els.length) return; | ||
var now = new Date(); | var now = new Date(); | ||
els.forEach(function (el) { | els.forEach(function (el) { | ||
var lib = (el.getAttribute('data-liberado') || '').toLowerCase().trim(); | var lib = (el.getAttribute('data-liberado') || '').toLowerCase().trim(); | ||
var ds | var ds = (el.getAttribute('data-reveal-date') || '').trim(); | ||
var dica = (el.getAttribute('data-dica') || '').trim(); | var dica = (el.getAttribute('data-dica') || '').trim(); | ||
var revealed = false; | var revealed = false; | ||
| Line 25: | Line 22: | ||
revealed = true; | revealed = true; | ||
} else if (lib === 'nao' || lib === 'false' || lib === '0') { | } else if (lib === 'nao' || lib === 'false' || lib === '0') { | ||
tip = '[CLASSIFICADO' + (dica ? ' // ' + dica : '') + ']'; | tip = '[CLASSIFICADO' + (dica ? ' // ' + dica : '') + ']'; | ||
} else if (ds) { | } else if (ds) { | ||
| Line 39: | Line 35: | ||
revealed = true; | revealed = true; | ||
} else { | } else { | ||
var f = ('0' + td.getDate()).slice(-2) + '/' + | var f = ('0' + td.getDate()).slice(-2) + '/' + ('0' + (td.getMonth() + 1)).slice(-2) + '/' + td.getFullYear(); | ||
tip = '[CLASSIFICADO' + (dica ? ' // ' + dica : '') + ' - ' + f + ']'; | tip = '[CLASSIFICADO' + (dica ? ' // ' + dica : '') + ' - ' + f + ']'; | ||
} | } | ||
| Line 59: | Line 53: | ||
} | } | ||
/* | /* 2. BOTÕES CENSURADO/LIBERADO NO MODAL */ | ||
function transformLiberadoInputs() { | function transformLiberadoInputs() { | ||
var inputs = document.querySelectorAll( | var inputs = document.querySelectorAll( | ||
| Line 67: | Line 59: | ||
'.oo-ui-fieldLayout input, .oo-ui-fieldLayout textarea' | '.oo-ui-fieldLayout input, .oo-ui-fieldLayout textarea' | ||
); | ); | ||
inputs.forEach(function (input) { | inputs.forEach(function (input) { | ||
var container = input.closest('.oo-ui-fieldLayout') || | var container = input.closest('.oo-ui-fieldLayout') || | ||
| Line 74: | Line 65: | ||
input.parentElement; | input.parentElement; | ||
if (!container) return; | if (!container) return; | ||
var txt = (container.textContent || '').toLowerCase(); | var txt = (container.textContent || '').toLowerCase(); | ||
if (txt.indexOf('liberado') === -1) return; | if (txt.indexOf('liberado') === -1) return; | ||
| Line 83: | Line 73: | ||
box.style.cssText = 'display:flex;gap:12px;margin:10px 0 16px;width:100%;max-width:460px;'; | box.style.cssText = 'display:flex;gap:12px;margin:10px 0 16px;width:100%;max-width:460px;'; | ||
var btnC = | var btnC = mkToggle('CENSURADO'); | ||
var btnL = | var btnL = mkToggle('LIBERADO'); | ||
function paint(v) { | function paint(v) { | ||
var isLib = (v === 'sim' || v === '1' || v === 'true'); | var isLib = (v === 'sim' || v === '1' || v === 'true'); | ||
btnC.style.background = isLib ? '#121218' : 'linear-gradient(180deg,#5c0f18,#2b060a)'; | btnC.style.background = isLib ? '#121218' : 'linear-gradient(180deg,#5c0f18,#2b060a)'; | ||
btnC.style.color | btnC.style.color = isLib ? '#7a7a88' : '#fff'; | ||
btnC.style.border | btnC.style.border = isLib ? '1px solid #2d2d38' : '2px solid #ff2a3f'; | ||
btnC.style.boxShadow | btnC.style.boxShadow = isLib ? 'none' : '0 0 12px rgba(255,42,63,.7)'; | ||
btnL.style.background = isLib ? 'linear-gradient(180deg,#1b5e20,#0d3814)' : '#121218'; | btnL.style.background = isLib ? 'linear-gradient(180deg,#1b5e20,#0d3814)' : '#121218'; | ||
btnL.style.color | btnL.style.color = isLib ? '#fff' : '#7a7a88'; | ||
btnL.style.border | btnL.style.border = isLib ? '2px solid #4caf50' : '1px solid #2d2d38'; | ||
btnL.style.boxShadow | btnL.style.boxShadow = isLib ? '0 0 12px rgba(76,175,80,.7)' : 'none'; | ||
} | } | ||
btnC.onclick = function (e) { | btnC.onclick = function (e) { e.preventDefault(); e.stopPropagation(); setVal(input, 'nao'); paint('nao'); }; | ||
btnL.onclick = function (e) { e.preventDefault(); e.stopPropagation(); setVal(input, 'sim'); paint('sim'); }; | |||
input.addEventListener('input', function () { paint((input.value || '').toLowerCase().trim()); }); | |||
paint((input.value || 'nao').toLowerCase().trim()); | |||
btnL.onclick = function (e) { | |||
input.addEventListener('input', function () { paint(input.value); }); | |||
paint(input.value || 'nao'); | |||
box.appendChild(btnC); | box.appendChild(btnC); | ||
box.appendChild(btnL); | box.appendChild(btnL); | ||
var wrap = input.closest('.oo-ui-textInputWidget') || input.closest('.oo-ui-inputWidget') || input; | |||
var wrap = input.closest('.oo-ui-textInputWidget') || | |||
wrap.parentNode.insertBefore(box, wrap); | wrap.parentNode.insertBefore(box, wrap); | ||
wrap.style.display = 'none'; | wrap.style.display = 'none'; | ||
| Line 123: | Line 101: | ||
} | } | ||
function | function mkToggle(label) { | ||
var b = document.createElement('button'); | var b = document.createElement('button'); | ||
b.type = 'button'; | b.type = 'button'; | ||
b.textContent = (label === 'CENSURADO' ? ' | b.textContent = (label === 'CENSURADO' ? '\u2B1B ' : '\uD83D\uDD13 ') + label; | ||
b.style.cssText = 'flex:1;padding:10px 16px;border-radius:4px;font-weight:800; | b.style.cssText = 'flex:1;padding:10px 16px;border-radius:4px;font-weight:800;font-size:.9em;cursor:pointer;font-family:"Cinzel",Georgia,serif;letter-spacing:1px;transition:all .25s ease;outline:none;'; | ||
return b; | return b; | ||
} | } | ||
| Line 142: | Line 118: | ||
setInterval(transformLiberadoInputs, 300); | setInterval(transformLiberadoInputs, 300); | ||
/* | /* 3. BOTÃO NO MENU INSERIR DO VISUALEDITOR */ | ||
function registerVeTool() { | |||
try { | |||
if (!window.ve || !ve.ui || !ve.ui.toolFactory) return; | |||
if (ve.ui.toolFactory.lookup('vtmSecret')) return; | |||
var tplData = { | |||
type: 'mwTransclusionInline', | |||
attributes: { | |||
mw: { | |||
parts: [ | |||
{ | |||
template: { | |||
target: { href: 'Template:Segredo', wt: 'Segredo' }, | |||
params: { | |||
'1': { wt: 'Texto confidencial' }, | |||
'liberado': { wt: 'nao' } | |||
} | |||
} | |||
} | |||
] | |||
} | |||
} | |||
}; | |||
ve.ui.commandRegistry.register( | |||
new ve.ui.Command('insertVtmSecret', 'content', 'insert', { | |||
args: [[tplData, { type: '/mwTransclusionInline' }]], | |||
supportedSelections: ['linear'] | |||
}) | |||
); | |||
function VtmTool() { VtmTool.super.apply(this, arguments); } | |||
OO.inheritClass(VtmTool, ve.ui.Tool); | |||
VtmTool.static.name = 'vtmSecret'; | |||
VtmTool.static.group = 'insert'; | |||
VtmTool.static.icon = 'lock'; | |||
VtmTool.static.title = 'Censura / Segredo (Confidencial)'; | |||
VtmTool.static.commandName = 'insertVtmSecret'; | |||
VtmTool.static.autoAddToCatchall = true; | |||
ve.ui.toolFactory.register(VtmTool); | |||
} catch (e) { | |||
if (window.console) console.warn('[VtM] Erro VE:', e); | |||
} | |||
} | |||
/* 4. BARRA DE FERRAMENTAS NO EDITOR DE CÓDIGO-FONTE */ | |||
function initVtmQuickToolbar() { | function initVtmQuickToolbar() { | ||
var tb = document.getElementById('wpTextbox1'); | var tb = document.getElementById('wpTextbox1'); | ||
| Line 151: | Line 171: | ||
var bar = document.createElement('div'); | var bar = document.createElement('div'); | ||
bar.id = 'vtm-editor-quickbar'; | bar.id = 'vtm-editor-quickbar'; | ||
bar.style.cssText = | bar.style.cssText = 'display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:10px 14px;margin:10px 0;background:linear-gradient(90deg,#181014,#0d0d12);border:1px solid #3d0a12;border-left:4px solid #8b0000;border-radius:4px;font-family:"Cinzel",Georgia,serif;box-shadow:0 4px 14px rgba(0,0,0,.6);z-index:99;'; | ||
var lbl = document.createElement('span'); | var lbl = document.createElement('span'); | ||
| Line 162: | Line 178: | ||
bar.appendChild(lbl); | bar.appendChild(lbl); | ||
bar.appendChild( | bar.appendChild(mkBtn('\u2B1B Censurar Trecho', '#240c12', '#ff2a3f', function () { | ||
wrapSel(tb, '{{Segredo|', '|liberado=nao}}', 'Texto censurado'); | |||
})); | })); | ||
bar.appendChild( | bar.appendChild(mkBtn('\uD83D\uDD13 Inserir Liberado', '#0d2915', '#2e7d32', function () { | ||
wrapSel(tb, '{{Segredo|', '|liberado=sim}}', 'Texto revelado'); | |||
})); | })); | ||
bar.appendChild( | bar.appendChild(mkBtn('\uD83D\uDCC1 Dossie Bloco', '#181822', '#3d0a12', function () { | ||
wrapSel(tb, '\n{{Segredo|tipo=bloco|nivel=CONFIDENCIAL|data=AAAA-MM-DD|dica=Operacao|\n', '\n}}\n', 'Relatorio confidencial...'); | |||
})); | })); | ||
bar.appendChild( | bar.appendChild(mkBtn('\uD83D\uDDD1 Remover Censura', '#1a1a22', '#4a4a58', function () { | ||
removeSecret(tb); | removeSecret(tb); | ||
})); | })); | ||
| Line 181: | Line 194: | ||
} | } | ||
function | function mkBtn(text, bg, border, fn) { | ||
var b = document.createElement('button'); | var b = document.createElement('button'); | ||
b.type = 'button'; | b.type = 'button'; b.textContent = text; | ||
b.style.cssText = 'background:' + bg + ';color:#fff;border:1px solid ' + border + ';border-radius:3px;padding:6px 12px;font-size:.82em;font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:4px;transition:all .2s ease;'; | |||
b.style.cssText = | |||
b.onmouseover = function () { b.style.opacity = '.85'; }; | b.onmouseover = function () { b.style.opacity = '.85'; }; | ||
b.onmouseout | b.onmouseout = function () { b.style.opacity = '1'; }; | ||
b.onclick = function (e) { e.preventDefault(); fn(); }; | b.onclick = function (e) { e.preventDefault(); fn(); }; | ||
return b; | return b; | ||
} | } | ||
function | function wrapSel(tb, pre, post, ph) { | ||
var s = tb.selectionStart, e = tb.selectionEnd; | var s = tb.selectionStart, e = tb.selectionEnd; | ||
var | var t = tb.value, sel = t.substring(s, e) || ph; | ||
tb.value = | tb.value = t.substring(0, s) + pre + sel + post + t.substring(e); | ||
tb.focus(); | tb.focus(); tb.setSelectionRange(s + pre.length, s + pre.length + sel.length); | ||
if (window.$) { $(tb).trigger('input').trigger('change'); } | if (window.$) { $(tb).trigger('input').trigger('change'); } | ||
} | } | ||
| Line 208: | Line 216: | ||
var i = text.lastIndexOf('{{Segredo|', s); | var i = text.lastIndexOf('{{Segredo|', s); | ||
if (i === -1) { alert('Nenhum {{Segredo|...}} encontrado.\nPosicione o cursor dentro do trecho.'); return; } | if (i === -1) { alert('Nenhum {{Segredo|...}} encontrado.\nPosicione o cursor dentro do trecho.'); return; } | ||
var depth = 0, j, end = -1; | var depth = 0, j, end = -1; | ||
for (j = i; j < text.length - 1; j++) { | for (j = i; j < text.length - 1; j++) { | ||
if (text[j] === '{' && text[j+1] === '{') { depth++; j++; } | if (text[j] === '{' && text[j + 1] === '{') { depth++; j++; } | ||
else if (text[j] === '}' && text[j+1] === '}') { depth--; if (depth === 0) { end = j + 2; break; } j++; } | else if (text[j] === '}' && text[j + 1] === '}') { depth--; if (depth === 0) { end = j + 2; break; } j++; } | ||
} | } | ||
if (end === -1) { alert('Fechamento }} | if (end === -1) { alert('Fechamento }} nao encontrado.'); return; } | ||
var inner = text.substring(i + '{{Segredo|'.length, end - 2); | var inner = text.substring(i + '{{Segredo|'.length, end - 2); | ||
var parts = [], cur = '', d = 0; | var parts = [], cur = '', d = 0; | ||
for (j = 0; j < inner.length; j++) { | for (j = 0; j < inner.length; j++) { | ||
if (inner[j] === '{' && j+1 < inner.length && inner[j+1] === '{') { d++; cur += '{{'; j++; } | if (inner[j] === '{' && j + 1 < inner.length && inner[j + 1] === '{') { d++; cur += '{{'; j++; } | ||
else if (inner[j] === '}' && j+1 < inner.length && inner[j+1] === '}') { d--; cur += '}}'; j++; } | else if (inner[j] === '}' && j + 1 < inner.length && inner[j + 1] === '}') { d--; cur += '}}'; j++; } | ||
else if (inner[j] === '|' && d === 0) { parts.push(cur); cur = ''; } | else if (inner[j] === '|' && d === 0) { parts.push(cur); cur = ''; } | ||
else { cur += inner[j]; } | else { cur += inner[j]; } | ||
} | } | ||
parts.push(cur); | parts.push(cur); | ||
var content = ''; | var content = ''; | ||
for (var k = 0; k < parts.length; k++) { | for (var k = 0; k < parts.length; k++) { | ||
if (parts[k].trim().indexOf('=') === -1) { content = parts[k].trim(); break; } | if (parts[k].trim().indexOf('=') === -1) { content = parts[k].trim(); break; } | ||
} | } | ||
tb.value = text.substring(0, i) + content + text.substring(end); | tb.value = text.substring(0, i) + content + text.substring(end); | ||
tb.focus(); | tb.focus(); tb.setSelectionRange(i, i + content.length); | ||
if (window.$) { $(tb).trigger('input').trigger('change'); } | if (window.$) { $(tb).trigger('input').trigger('change'); } | ||
} | } | ||
/* | /* 5. ANIMAÇÃO DE CASCATA DAS SEÇÕES */ | ||
function initSectionAnimation() { | function initSectionAnimation() { | ||
var c = document.querySelector('.mw-parser-output'); | var c = document.querySelector('.mw-parser-output'); | ||
if (!c || c.dataset.vtmAnimated === 'true') return; | if (!c || c.dataset.vtmAnimated === 'true') return; | ||
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; | if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; | ||
c.dataset.vtmAnimated = 'true'; | c.dataset.vtmAnimated = 'true'; | ||
var kids = Array.from(c.children), secs = [], cur = []; | var kids = Array.from(c.children), secs = [], cur = []; | ||
kids.forEach(function (ch) { | kids.forEach(function (ch) { | ||
if (ch.classList.contains('catlinks') || ch.classList.contains('mw-category-generated') || | if (ch.classList.contains('catlinks') || ch.classList.contains('mw-category-generated') || | ||
| Line 254: | Line 253: | ||
return; | return; | ||
} | } | ||
if ((ch.tagName === 'H2' || ch.classList.contains('mw-heading2')) && cur.length) { | if ((ch.tagName === 'H2' || ch.classList.contains('mw-heading2')) && cur.length) { secs.push(cur); cur = []; } | ||
cur.push(ch); | cur.push(ch); | ||
}); | }); | ||
if (cur.length) secs.push(cur); | if (cur.length) secs.push(cur); | ||
secs.forEach(function (items, idx) { | secs.forEach(function (items, idx) { | ||
var w = document.createElement('div'); | var w = document.createElement('div'); | ||
| Line 266: | Line 262: | ||
w.style.animationDelay = (0.12 + idx * 0.42).toFixed(2) + 's'; | w.style.animationDelay = (0.12 + idx * 0.42).toFixed(2) + 's'; | ||
var f = items[0]; | var f = items[0]; | ||
if (f && f.parentNode) { | if (f && f.parentNode) { f.parentNode.insertBefore(w, f); items.forEach(function (el) { w.appendChild(el); }); } | ||
}); | }); | ||
} | } | ||
/* | /* INICIALIZAÇÃO */ | ||
function initAll() { | function initAll() { | ||
initVtmSecrets(); | initVtmSecrets(); | ||
initSectionAnimation(); | initSectionAnimation(); | ||
initVtmQuickToolbar(); | initVtmQuickToolbar(); | ||
registerVeTool(); | |||
} | } | ||
| Line 293: | Line 285: | ||
initSectionAnimation(); | initSectionAnimation(); | ||
}); | }); | ||
window.mw.hook('ve.activationComplete').add(registerVeTool); | |||
} | } | ||
})(); | |||
Revision as of 20:03, 1 September 2026
/* ==========================================================================
VAMPIRO: A MÁSCARA — SCRIPTS GLOBAIS & SEGREDO DINÂMICO
========================================================================== */
(function () {
'use strict';
/* 1. CENSURA & REVELAÇÃO DINÂMICA */
function initVtmSecrets() {
var els = document.querySelectorAll('[data-vtm-secret="true"]');
if (!els || !els.length) return;
var now = new Date();
els.forEach(function (el) {
var lib = (el.getAttribute('data-liberado') || '').toLowerCase().trim();
var ds = (el.getAttribute('data-reveal-date') || '').trim();
var dica = (el.getAttribute('data-dica') || '').trim();
var revealed = false;
var tip = '[ARQUIVO CONFIDENCIAL]';
if (lib === 'sim' || lib === 'true' || lib === '1') {
revealed = true;
} else if (lib === 'nao' || lib === 'false' || lib === '0') {
tip = '[CLASSIFICADO' + (dica ? ' // ' + dica : '') + ']';
} else if (ds) {
var td = null;
if (ds.indexOf('/') !== -1) {
var p = ds.split('/');
if (p.length === 3) td = new Date(p[2], parseInt(p[1], 10) - 1, p[0]);
} else {
td = new Date(ds);
}
if (td && !isNaN(td.getTime())) {
if (now >= td) {
revealed = true;
} else {
var f = ('0' + td.getDate()).slice(-2) + '/' + ('0' + (td.getMonth() + 1)).slice(-2) + '/' + td.getFullYear();
tip = '[CLASSIFICADO' + (dica ? ' // ' + dica : '') + ' - ' + f + ']';
}
}
}
if (revealed) {
el.classList.add('is-revealed');
el.classList.remove('is-redacted');
el.title = '[DESCLASSIFICADO' + (dica ? ' // ' + dica : '') + ']';
} else {
el.classList.add('is-redacted');
el.classList.remove('is-revealed');
el.title = tip;
}
});
}
/* 2. BOTÕES CENSURADO/LIBERADO NO MODAL */
function transformLiberadoInputs() {
var inputs = document.querySelectorAll(
'.oo-ui-windowManager input, .oo-ui-windowManager textarea, ' +
'.oo-ui-fieldLayout input, .oo-ui-fieldLayout textarea'
);
inputs.forEach(function (input) {
var container = input.closest('.oo-ui-fieldLayout') ||
input.closest('.ve-ui-mwParameterPage') ||
input.closest('.oo-ui-pageLayout') ||
input.parentElement;
if (!container) return;
var txt = (container.textContent || '').toLowerCase();
if (txt.indexOf('liberado') === -1) return;
if (container.querySelector('.vtm-toggle-box')) return;
var box = document.createElement('div');
box.className = 'vtm-toggle-box';
box.style.cssText = 'display:flex;gap:12px;margin:10px 0 16px;width:100%;max-width:460px;';
var btnC = mkToggle('CENSURADO');
var btnL = mkToggle('LIBERADO');
function paint(v) {
var isLib = (v === 'sim' || v === '1' || v === 'true');
btnC.style.background = isLib ? '#121218' : 'linear-gradient(180deg,#5c0f18,#2b060a)';
btnC.style.color = isLib ? '#7a7a88' : '#fff';
btnC.style.border = isLib ? '1px solid #2d2d38' : '2px solid #ff2a3f';
btnC.style.boxShadow = isLib ? 'none' : '0 0 12px rgba(255,42,63,.7)';
btnL.style.background = isLib ? 'linear-gradient(180deg,#1b5e20,#0d3814)' : '#121218';
btnL.style.color = isLib ? '#fff' : '#7a7a88';
btnL.style.border = isLib ? '2px solid #4caf50' : '1px solid #2d2d38';
btnL.style.boxShadow = isLib ? '0 0 12px rgba(76,175,80,.7)' : 'none';
}
btnC.onclick = function (e) { e.preventDefault(); e.stopPropagation(); setVal(input, 'nao'); paint('nao'); };
btnL.onclick = function (e) { e.preventDefault(); e.stopPropagation(); setVal(input, 'sim'); paint('sim'); };
input.addEventListener('input', function () { paint((input.value || '').toLowerCase().trim()); });
paint((input.value || 'nao').toLowerCase().trim());
box.appendChild(btnC);
box.appendChild(btnL);
var wrap = input.closest('.oo-ui-textInputWidget') || input.closest('.oo-ui-inputWidget') || input;
wrap.parentNode.insertBefore(box, wrap);
wrap.style.display = 'none';
});
}
function mkToggle(label) {
var b = document.createElement('button');
b.type = 'button';
b.textContent = (label === 'CENSURADO' ? '\u2B1B ' : '\uD83D\uDD13 ') + label;
b.style.cssText = 'flex:1;padding:10px 16px;border-radius:4px;font-weight:800;font-size:.9em;cursor:pointer;font-family:"Cinzel",Georgia,serif;letter-spacing:1px;transition:all .25s ease;outline:none;';
return b;
}
function setVal(input, v) {
input.value = v;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
if (window.$) { $(input).trigger('input').trigger('change'); }
}
setInterval(transformLiberadoInputs, 300);
/* 3. BOTÃO NO MENU INSERIR DO VISUALEDITOR */
function registerVeTool() {
try {
if (!window.ve || !ve.ui || !ve.ui.toolFactory) return;
if (ve.ui.toolFactory.lookup('vtmSecret')) return;
var tplData = {
type: 'mwTransclusionInline',
attributes: {
mw: {
parts: [
{
template: {
target: { href: 'Template:Segredo', wt: 'Segredo' },
params: {
'1': { wt: 'Texto confidencial' },
'liberado': { wt: 'nao' }
}
}
}
]
}
}
};
ve.ui.commandRegistry.register(
new ve.ui.Command('insertVtmSecret', 'content', 'insert', {
args: [[tplData, { type: '/mwTransclusionInline' }]],
supportedSelections: ['linear']
})
);
function VtmTool() { VtmTool.super.apply(this, arguments); }
OO.inheritClass(VtmTool, ve.ui.Tool);
VtmTool.static.name = 'vtmSecret';
VtmTool.static.group = 'insert';
VtmTool.static.icon = 'lock';
VtmTool.static.title = 'Censura / Segredo (Confidencial)';
VtmTool.static.commandName = 'insertVtmSecret';
VtmTool.static.autoAddToCatchall = true;
ve.ui.toolFactory.register(VtmTool);
} catch (e) {
if (window.console) console.warn('[VtM] Erro VE:', e);
}
}
/* 4. BARRA DE FERRAMENTAS NO EDITOR DE CÓDIGO-FONTE */
function initVtmQuickToolbar() {
var tb = document.getElementById('wpTextbox1');
if (!tb || document.getElementById('vtm-editor-quickbar')) return;
var bar = document.createElement('div');
bar.id = 'vtm-editor-quickbar';
bar.style.cssText = 'display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:10px 14px;margin:10px 0;background:linear-gradient(90deg,#181014,#0d0d12);border:1px solid #3d0a12;border-left:4px solid #8b0000;border-radius:4px;font-family:"Cinzel",Georgia,serif;box-shadow:0 4px 14px rgba(0,0,0,.6);z-index:99;';
var lbl = document.createElement('span');
lbl.style.cssText = 'color:#c5a059;font-size:.85em;font-weight:700;text-transform:uppercase;letter-spacing:1px;margin-right:6px;';
lbl.textContent = 'Ferramentas:';
bar.appendChild(lbl);
bar.appendChild(mkBtn('\u2B1B Censurar Trecho', '#240c12', '#ff2a3f', function () {
wrapSel(tb, '{{Segredo|', '|liberado=nao}}', 'Texto censurado');
}));
bar.appendChild(mkBtn('\uD83D\uDD13 Inserir Liberado', '#0d2915', '#2e7d32', function () {
wrapSel(tb, '{{Segredo|', '|liberado=sim}}', 'Texto revelado');
}));
bar.appendChild(mkBtn('\uD83D\uDCC1 Dossie Bloco', '#181822', '#3d0a12', function () {
wrapSel(tb, '\n{{Segredo|tipo=bloco|nivel=CONFIDENCIAL|data=AAAA-MM-DD|dica=Operacao|\n', '\n}}\n', 'Relatorio confidencial...');
}));
bar.appendChild(mkBtn('\uD83D\uDDD1 Remover Censura', '#1a1a22', '#4a4a58', function () {
removeSecret(tb);
}));
tb.parentNode.insertBefore(bar, tb);
}
function mkBtn(text, bg, border, fn) {
var b = document.createElement('button');
b.type = 'button'; b.textContent = text;
b.style.cssText = 'background:' + bg + ';color:#fff;border:1px solid ' + border + ';border-radius:3px;padding:6px 12px;font-size:.82em;font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:4px;transition:all .2s ease;';
b.onmouseover = function () { b.style.opacity = '.85'; };
b.onmouseout = function () { b.style.opacity = '1'; };
b.onclick = function (e) { e.preventDefault(); fn(); };
return b;
}
function wrapSel(tb, pre, post, ph) {
var s = tb.selectionStart, e = tb.selectionEnd;
var t = tb.value, sel = t.substring(s, e) || ph;
tb.value = t.substring(0, s) + pre + sel + post + t.substring(e);
tb.focus(); tb.setSelectionRange(s + pre.length, s + pre.length + sel.length);
if (window.$) { $(tb).trigger('input').trigger('change'); }
}
function removeSecret(tb) {
var s = tb.selectionStart, text = tb.value;
var i = text.lastIndexOf('{{Segredo|', s);
if (i === -1) { alert('Nenhum {{Segredo|...}} encontrado.\nPosicione o cursor dentro do trecho.'); return; }
var depth = 0, j, end = -1;
for (j = i; j < text.length - 1; j++) {
if (text[j] === '{' && text[j + 1] === '{') { depth++; j++; }
else if (text[j] === '}' && text[j + 1] === '}') { depth--; if (depth === 0) { end = j + 2; break; } j++; }
}
if (end === -1) { alert('Fechamento }} nao encontrado.'); return; }
var inner = text.substring(i + '{{Segredo|'.length, end - 2);
var parts = [], cur = '', d = 0;
for (j = 0; j < inner.length; j++) {
if (inner[j] === '{' && j + 1 < inner.length && inner[j + 1] === '{') { d++; cur += '{{'; j++; }
else if (inner[j] === '}' && j + 1 < inner.length && inner[j + 1] === '}') { d--; cur += '}}'; j++; }
else if (inner[j] === '|' && d === 0) { parts.push(cur); cur = ''; }
else { cur += inner[j]; }
}
parts.push(cur);
var content = '';
for (var k = 0; k < parts.length; k++) {
if (parts[k].trim().indexOf('=') === -1) { content = parts[k].trim(); break; }
}
tb.value = text.substring(0, i) + content + text.substring(end);
tb.focus(); tb.setSelectionRange(i, i + content.length);
if (window.$) { $(tb).trigger('input').trigger('change'); }
}
/* 5. ANIMAÇÃO DE CASCATA DAS SEÇÕES */
function initSectionAnimation() {
var c = document.querySelector('.mw-parser-output');
if (!c || c.dataset.vtmAnimated === 'true') return;
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
c.dataset.vtmAnimated = 'true';
var kids = Array.from(c.children), secs = [], cur = [];
kids.forEach(function (ch) {
if (ch.classList.contains('catlinks') || ch.classList.contains('mw-category-generated') ||
ch.tagName === 'SCRIPT' || ch.tagName === 'STYLE' || ch.id === 'vtm-editor-quickbar') {
if (cur.length) { secs.push(cur); cur = []; }
return;
}
if ((ch.tagName === 'H2' || ch.classList.contains('mw-heading2')) && cur.length) { secs.push(cur); cur = []; }
cur.push(ch);
});
if (cur.length) secs.push(cur);
secs.forEach(function (items, idx) {
var w = document.createElement('div');
w.className = 'vtm-section-block';
w.style.animationDelay = (0.12 + idx * 0.42).toFixed(2) + 's';
var f = items[0];
if (f && f.parentNode) { f.parentNode.insertBefore(w, f); items.forEach(function (el) { w.appendChild(el); }); }
});
}
/* INICIALIZAÇÃO */
function initAll() {
initVtmSecrets();
initSectionAnimation();
initVtmQuickToolbar();
registerVeTool();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initAll);
} else {
initAll();
}
if (window.mw && window.mw.hook) {
window.mw.hook('wikipage.content').add(function () {
initVtmSecrets();
initSectionAnimation();
});
window.mw.hook('ve.activationComplete').add(registerVeTool);
}
})();