bit-twiddler 0.2.0

Cross-platform developer toolbox: bit manipulation, hashing, YAML/JSON/SQL, QR, Markdown, cron, and 40+ more tools — Tauri v2, no Node.js
$(document).ready(function() {
  let algorithm = 'bcrypt';

  // --- Mode tabs (Hash / Verify) ---
  $('.pwhash-mode-btn').on('click', function() {
    const mode = $(this).data('mode');
    $('.pwhash-mode-btn').removeClass('active text-blue-400 border-blue-500').addClass('text-gray-500 border-transparent hover:text-gray-300');
    $(this).addClass('active text-blue-400 border-blue-500').removeClass('text-gray-500 border-transparent hover:text-gray-300');
    $('.pwhash-mode-view').addClass('hidden');
    $('#pwhash-mode-' + mode).removeClass('hidden');
  });

  // --- Algorithm toggle ---
  const updateAlgoUI = () => {
    const isBcrypt = algorithm === 'bcrypt';
    $('#pwhash-algo-bcrypt').toggleClass('bg-blue-600 text-white', isBcrypt).toggleClass('text-gray-500 hover:text-gray-300', !isBcrypt);
    $('#pwhash-algo-argon2').toggleClass('bg-blue-600 text-white', !isBcrypt).toggleClass('text-gray-500 hover:text-gray-300', isBcrypt);
    $('#pwhash-bcrypt-params').toggleClass('hidden', !isBcrypt);
    $('#pwhash-argon2-params-1, #pwhash-argon2-params-2, #pwhash-argon2-params-3').toggleClass('hidden', isBcrypt);
  };

  $('#pwhash-algo-bcrypt').on('click', () => { algorithm = 'bcrypt'; updateAlgoUI(); });
  $('#pwhash-algo-argon2').on('click', () => { algorithm = 'argon2id'; updateAlgoUI(); });
  updateAlgoUI();

  $('#pwhash-advanced-toggle').on('click', () => $('#pwhash-advanced').toggleClass('hidden'));

  // --- Hash panel ---
  $('#pwhash-generate-btn').on('click', async () => {
    const password = $('#pwhash-input').val();
    const $error = $('#pwhash-error');
    const $output = $('#pwhash-output');
    $error.addClass('hidden');

    if (!password) {
      $error.removeClass('hidden').text('Enter a password to hash.');
      return;
    }

    const cost = algorithm === 'bcrypt'
      ? parseInt($('#pwhash-bcrypt-cost').val(), 10)
      : parseInt($('#pwhash-argon2-iterations').val(), 10);
    const memoryKib = parseInt($('#pwhash-argon2-memory').val(), 10) || 65536;
    const parallelism = parseInt($('#pwhash-argon2-parallelism').val(), 10) || 1;

    try {
      const hash = await window.tauriApi.hashPassword(password, algorithm, cost, memoryKib, parallelism);
      $output.val(hash);
    } catch (e) {
      $output.val('');
      $error.removeClass('hidden').text('Error: ' + e);
    }
  });

  $('#pwhash-copy-btn').on('click', function() {
    const text = $('#pwhash-output').val();
    if (text) window.copyToClipboard(text, $(this));
  });

  // --- Verify panel ---
  $('#pwverify-btn').on('click', async () => {
    const password = $('#pwverify-password').val();
    const hash = $('#pwverify-hash').val().trim();
    const $result = $('#pwverify-result');

    if (!password || !hash) {
      $result.removeClass('hidden bg-emerald-500/10 border-emerald-500/40 text-emerald-400 bg-rose-500/10 border-rose-500/40 text-rose-400')
        .addClass('bg-gray-800/50 border-gray-700 text-gray-400')
        .text('Enter both a password and a hash.');
      return;
    }

    try {
      const isMatch = await window.tauriApi.verifyPassword(password, hash);
      $result.removeClass('hidden bg-gray-800/50 border-gray-700 text-gray-400 bg-emerald-500/10 border-emerald-500/40 text-emerald-400 bg-rose-500/10 border-rose-500/40 text-rose-400');
      if (isMatch) {
        $result.addClass('bg-emerald-500/10 border-emerald-500/40 text-emerald-400').text('✅ Match');
      } else {
        $result.addClass('bg-rose-500/10 border-rose-500/40 text-rose-400').text('❌ No match');
      }
    } catch (e) {
      $result.removeClass('hidden bg-emerald-500/10 border-emerald-500/40 text-emerald-400')
        .addClass('bg-rose-500/10 border-rose-500/40 text-rose-400')
        .text('Error: ' + e);
    }
  });
});