Queria só mencionar uma ferramenta (site) que ajuda bastante quem tem dificuldades com código ou só está com pressa para criar uma tabelinha sem se stressar com o bbcode...
dá uma olhada nisso, se achar interessante já deixa favoritado:
https://tableconvert.com/pt/bbcode-generatorTrabalhar com o BBCode em tópicos extensos é complicado, mesmo com tarefas mais simples, e traduzir é pior ainda.

Eu já conhecia essa ferramenta. Ela agiliza bastante a tarefa de criar tabelas básicas; para quem não tem muita familiaridade com o código dos fóruns, é uma ótima opção.
Dei uma fuçada aqui, achei um script meia boca e com a ajuda da IA consegui algo até que interessante para usar com o tampermonkey, ele adiciona um "botão" do lado dos que já existem quando tu vai criar uma nova postagem, abrindo uma interface gráfica onde tu escolhe a uqantidade de linhas e colunas, aí é só reservar algumas para colocar o __ e |
// ==UserScript==
// @name Bitcointalk BBCode Table Editor
// @namespace https://example.com/
// @version 1.0
// @description Small visual editor for BBCode tables
// @match https://bitcointalk.org/*
// @grant none
// @author alegotardo + IA
// ==/UserScript==
(function () {
'use strict';
function getTextarea() {
return document.forms.postmodify?.message || document.querySelector('textarea');
}
function insertAtCursor(textarea, text) {
textarea.focus();
const start = textarea.selectionStart ?? textarea.value.length;
const end = textarea.selectionEnd ?? textarea.value.length;
textarea.setRangeText(text, start, end, 'end');
textarea.dispatchEvent(new Event('input', { bubbles: true }));
textarea.dispatchEvent(new Event('change', { bubbles: true }));
}
function esc(text) {
return String(text || '')
.replace(/\[/g, '[')
.replace(/\]/g, ']');
}
function buildTable(rows, cols, values, header) {
let out = '[table]\n';
let i = 0;
for (let r = 0; r < rows; r++) {
out += '[tr]\n';
for (let c = 0; c < cols; c++) {
const value = esc(values[i++] || '');
out += header && r === 0
? `[td][b]${value}[/b][/td]\n`
: `[td]${value}[/td]\n`;
}
out += '[/tr]\n';
}
out += '[/table]';
return out;
}
function createInput(value = '', isHeader = false) {
const input = document.createElement('input');
input.type = 'text';
input.value = value;
input.style.cssText = [
'width:100%',
'padding:4px 6px',
'border:1px solid #999',
'border-radius:3px',
'font:12px Verdana,sans-serif',
'box-sizing:border-box',
isHeader ? 'font-weight:bold' : ''
].join(';');
return input;
}
function openEditor(textarea) {
const overlay = document.createElement('div');
overlay.style.cssText = [
'position:fixed',
'inset:0',
'background:rgba(0,0,0,.35)',
'display:flex',
'align-items:center',
'justify-content:center',
'z-index:999999'
].join(';');
const box = document.createElement('div');
box.style.cssText = [
'background:#fff',
'color:#222',
'width:min(920px,95vw)',
'max-height:90vh',
'overflow:auto',
'padding:12px',
'border:1px solid #999',
'border-radius:6px',
'font:12px Verdana,sans-serif',
'box-shadow:0 10px 30px rgba(0,0,0,.2)'
].join(';');
box.innerHTML = `
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
<strong>BBCode Table Editor</strong>
<button type="button" id="bbte-close">Close</button>
</div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:10px;">
<label>Rows <input id="bbte-rows" type="number" min="1" value="3" style="width:60px;"></label>
<label>Cols <input id="bbte-cols" type="number" min="1" value="3" style="width:60px;"></label>
<label><input id="bbte-header" type="checkbox"> Header row</label>
<button type="button" id="bbte-build">Build</button>
<button type="button" id="bbte-insert">Insert</button>
</div>
<div id="bbte-grid-wrap" style="overflow:auto;"></div>
`;
overlay.appendChild(box);
document.body.appendChild(overlay);
const rowsInput = box.querySelector('#bbte-rows');
const colsInput = box.querySelector('#bbte-cols');
const headerInput = box.querySelector('#bbte-header');
const gridWrap = box.querySelector('#bbte-grid-wrap');
function getCurrentValues() {
return [...gridWrap.querySelectorAll('input')].map(i => i.value);
}
function rebuildGrid() {
const oldValues = getCurrentValues();
const rows = Math.max(1, parseInt(rowsInput.value || '1', 10));
const cols = Math.max(1, parseInt(colsInput.value || '1', 10));
const header = headerInput.checked;
gridWrap.innerHTML = '';
const grid = document.createElement('div');
grid.style.cssText = [
'display:grid',
`grid-template-columns:repeat(${cols}, minmax(120px, 1fr))`,
'gap:6px'
].join(';');
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
const index = r * cols + c;
grid.appendChild(createInput(oldValues[index] || '', header && r === 0));
}
}
gridWrap.appendChild(grid);
}
box.querySelector('#bbte-build').onclick = rebuildGrid;
headerInput.onchange = rebuildGrid;
box.querySelector('#bbte-insert').onclick = function () {
const rows = Math.max(1, parseInt(rowsInput.value || '1', 10));
const cols = Math.max(1, parseInt(colsInput.value || '1', 10));
const header = headerInput.checked;
const values = getCurrentValues();
const table = buildTable(rows, cols, values, header);
insertAtCursor(textarea, '\n' + table + '\n');
overlay.remove();
};
box.querySelector('#bbte-close').onclick = function () {
overlay.remove();
};
overlay.addEventListener('click', function (e) {
if (e.target === overlay) overlay.remove();
});
rebuildGrid();
}
function findTdButton() {
return [...document.querySelectorAll('a[onclick]')].find(a =>
a.getAttribute('onclick')?.includes("surroundText('[td]', '[/td]'")
);
}
function addButton() {
if (document.getElementById('bbcode-table-editor-btn')) return;
const textarea = getTextarea();
if (!textarea) return;
const anchor = document.createElement('a');
anchor.href = 'javascript:void(0);';
anchor.id = 'bbcode-table-editor-btn';
anchor.title = 'Open BBCode Table Editor';
anchor.textContent = '[[TB]]';
anchor.style.cssText = [
'margin-left:4px',
'font:12px Verdana,sans-serif',
'text-decoration:none',
'vertical-align:middle'
].join(';');
anchor.onclick = function (e) {
e.preventDefault();
openEditor(textarea);
return false;
};
const tdButton = findTdButton();
if (tdButton) {
tdButton.after(anchor);
} else {
textarea.parentNode.insertBefore(anchor, textarea);
}
}
function init() {
addButton();
new MutationObserver(addButton).observe(document.body, {
childList: true,
subtree: true
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();