Source: script.js

let inputNum = document.getElementById("inputNmr");
let inputDeBase = document.getElementById("inputBas");
let inputParaBase = document.getElementById("outputBas");
let resultado = document.getElementById("outputNmr");
let converterBtn = document.getElementById("convertBtn");

/**
 * Filtra a entrada com base nas bases de origem e destino. Confere se alguma das bases é 10, se são potências, ou se devem passar por base 10 primeiro.
 * @param {number} baseOrigem A base original a ser convertida.
 * @param {number} baseDestino A base de destino para a qual o número será convertido.
 * @returns {string|boolean} Retorna uma string indicando o tipo de conversão necessária ou false se as bases forem inválidas.
 */
function filtrarEntrada(baseOrigem, baseDestino) {
	if (baseOrigem >= 2 && baseOrigem <= 36) {
		if (baseOrigem === 10) {
			return "origem10";
		} else if (baseDestino === 10) {
			return "destino10";
		} else if (baseDestino === baseOrigem ** Math.log2(baseDestino) / Math.log2(baseOrigem)) {
			return "mesmaPotencia";
		} else {
			return "basesDiferentes";
		}
	}
	return false;
}

/**
 * Converte um número de uma base para a base 10.
 * @param {string} nmr O número a ser convertido.
 * @param {number} baseOrigem A base original do número.
 * @returns {number} O número convertido para a base 10.
 */
function paraBase10(nmr, baseOrigem) {
	const digitos = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	let decimal = 0;
	for (const c of nmr.toUpperCase()) {
		decimal = decimal * baseOrigem + digitos.indexOf(c);
	}
	return decimal;
};

/**
 * Converte um número da base 10 para outra base.
 * @param {number} nmr O número em base 10 a ser convertido.
 * @param {number} baseDestino A base para a qual o número será convertido.
 * @returns {string} O número convertido para a base de destino.
 */
function deBase10(nmr, baseDestino) {
	const digitos = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	let decimal = nmr;
	let resultado = "";
	while (decimal > 0) {
		resultado = digitos[decimal % baseDestino] + resultado;
		decimal = Math.floor(decimal / baseDestino);
	}
	return resultado === "" ? "0" : resultado;
};

/**
 * Valida se um número é válido na base especificada.
 * @param {string} nmr O número a ser validado.
 * @param {number} baseOrigem A base na qual o número deve ser validado.
 * @returns {boolean} Retorna true se o número for válido na base especificada, caso contrário, retorna false.
 */
function validarNmr(nmr, baseOrigem) {
	const digitos = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".slice(0, baseOrigem);
	return nmr.length > 0 && [...nmr.toUpperCase()].every(c => digitos.includes(c));
}

/**
 * Converte um número entre bases que são potências.
 * @param {string} nmr O número a ser convertido.
 * @param {number} baseOrigem A base original do número.
 * @param {number} baseDestino A base de destino para a qual o número será convertido.
 * @returns {string}
 */
function converterPotencia(nmr, baseOrigem, baseDestino) {
	const digitos = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	const bitsOrigem = Math.round(Math.log2(baseOrigem));
	const bitsDestino = Math.round(Math.log2(baseDestino));

	let binario = "";
	for (const c of nmr.toUpperCase()) {
		const bloco = deBase10(paraBase10(c, baseOrigem), 2);
		binario += "0".repeat(bitsOrigem - bloco.length) + bloco;
	}

	const resto = binario.length % bitsDestino;
	if (resto !== 0) {
		binario = "0".repeat(bitsDestino - resto) + binario;
	}

	let resultado = "";
	for (let i = 0; i < binario.length; i += bitsDestino) {
		resultado += digitos[paraBase10(binario.substring(i, i + bitsDestino), 2)];
	}
	return resultado.replace(/^0+(?=.)/, "");
};

convertBtn.addEventListener("click", function () {
	let nmr = inputNum.value;
	let baseOrigem = Number(inputDeBase.value);
	let baseDestino = Number(inputParaBase.value);

	inputNum.setCustomValidity("");
	inputDeBase.setCustomValidity("");
	inputParaBase.setCustomValidity("");

	if (isNaN(baseOrigem) || baseOrigem < 2 || baseOrigem > 36) {
		inputDeBase.setCustomValidity("A base deve ser um número entre 2 e 36.");
	} else if (isNaN(baseDestino) || baseDestino < 2 || baseDestino > 36) {
		inputParaBase.setCustomValidity("A base deve ser um número entre 2 e 36.");
	} else if (!validarNmr(nmr, baseOrigem)) {
		inputNum.setCustomValidity(`"${nmr}" não é um número válido na base ${baseOrigem}.`);
	}

	if (!inputDeBase.reportValidity() || !inputParaBase.reportValidity() || !inputNum.reportValidity()) {
		resultado.value = "";
		return;
	}

	if (filtrarEntrada(baseOrigem, baseDestino)) {
		switch (filtrarEntrada(baseOrigem, baseDestino)) {
			case "origem10":
				resultado.value = deBase10(nmr, baseDestino);
				break;
			case "destino10":
				resultado.value = paraBase10(nmr, baseOrigem);
				break;
			case "mesmaPotencia":
				resultado.value = converterPotencia(nmr, baseOrigem, baseDestino);
				break;
			case "basesDiferentes":
				resultado.value = deBase10(paraBase10(nmr, baseOrigem), baseDestino);
				break;
		}
	}
});