Auto tag replacer chrome script for Contributor+ users

Posted under General

Recently, I’ve been working on replacing incorrect tags, so I asked Claude to help me create a script. This script runs in Chrome’s console: after pasting the code into the console and pressing Enter, an interface appears where the user can input the tag to be replaced and the new tag to use as a replacement.

After clicking “start_replacing,” the script will begin replacing tags automatically.

In this state, while in edit mode, clicking post will resulted in automatically replace the specified old tag with the new one, so there’s no need to manually select the old tag and paste the new one. However, it is still necessary to click “submit” to complete the edit, which also serves as a safeguard in case a post is clicked by mistake (i.e., when the tag should not be replaced).

I’m not sure whether a tool with similar functionality already exists. If there is one that works better, recommendations would be greatly appreciated. Thank you!

The script:

Show
(function() {
  if (document.getElementById('tag-replacer-ui')) {
    console.log('UI already exists');
    return;
  }

  const ui = document.createElement('div');
  ui.id = 'tag-replacer-ui';
  ui.style.cssText = `
    position: fixed;
    top: 20px;
    right: 20px;
    z-index: 999999;
    background: #1e1e2e;
    border: 1px solid #444;
    border-radius: 10px;
    padding: 16px;
    width: 300px;
    font-family: sans-serif;
    box-shadow: 0 4px 20px rgba(0,0,0,0.5);
    color: #cdd6f4;
    transition: all 0.2s ease;
  `;

  ui.innerHTML = `
    <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
      <strong id="tag-replacer-title" style="font-size:14px;">🏷️ Tag Replacer</strong>
      <div style="display:flex; gap:6px; align-items:center;">
        <button id="tag-replacer-minimize" title="Minimize" style="background:none;border:none;color:#a6adc8;font-size:16px;cursor:pointer;line-height:1;">—</button>
        <button id="tag-replacer-close" title="Close" style="background:none;border:none;color:#f38ba8;font-size:18px;cursor:pointer;line-height:1;">✕</button>
      </div>
    </div>
    <div id="tag-replacer-body">
      <div style="margin-bottom:8px;">
        <label style="font-size:12px; color:#a6adc8;">Find</label>
        <input id="tag-replacer-from" type="text" placeholder="e.g. old_tag" style="width:100%;box-sizing:border-box;margin-top:4px;padding:6px 8px;border-radius:6px;border:1px solid #555;background:#313244;color:#cdd6f4;font-size:13px;" />
      </div>
      <div style="margin-bottom:12px;">
        <label style="font-size:12px; color:#a6adc8;">Replace with</label>
        <input id="tag-replacer-to" type="text" placeholder="e.g. new_tag" style="width:100%;box-sizing:border-box;margin-top:4px;padding:6px 8px;border-radius:6px;border:1px solid #555;background:#313244;color:#cdd6f4;font-size:13px;" />
      </div>
      <button id="tag-replacer-toggle" style="width:100%;padding:8px;border-radius:6px;border:none;background:#a6e3a1;color:#1e1e2e;font-weight:bold;font-size:13px;cursor:pointer;">▶ Start Replacing</button>
      <div id="tag-replacer-status" style="margin-top:8px;font-size:11px;color:#a6adc8;text-align:center;"></div>
    </div>
  `;

  document.body.appendChild(ui);

  let intervalId = null;
  let isRunning = false;
  let isMinimized = false;
  let totalCount = 0;

  const toggleBtn = document.getElementById('tag-replacer-toggle');
  const statusDiv = document.getElementById('tag-replacer-status');
  const minimizeBtn = document.getElementById('tag-replacer-minimize');
  const body = document.getElementById('tag-replacer-body');
  const title = document.getElementById('tag-replacer-title');

  const SELECTOR = 'textarea.text.required.text-sm.ui-autocomplete-input[name="post[tag_string]"]';

  function poll() {
    const from = document.getElementById('tag-replacer-from').value;
    const to = document.getElementById('tag-replacer-to').value;
    if (!from) return;

    const elements = document.querySelectorAll(SELECTOR);
    elements.forEach(el => {
      const original = el.value;
      if (!original.includes(from)) return;

      const replaced = original.split(from).join(to);
      el.value = replaced;

      el.dispatchEvent(new Event('input', { bubbles: true }));
      el.dispatchEvent(new Event('change', { bubbles: true }));
      el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText' }));

      const count = original.split(from).length - 1;
      totalCount += count;
      statusDiv.textContent = `✅ Replaced ${totalCount} occurrence(s) total (${new Date().toLocaleTimeString()})`;
      // 縮小狀態下也更新 title 顯示狀態
      if (isMinimized) {
        title.textContent = `🏷️ Tag Replacer · ✅ ${totalCount}`;
      }
      console.log(`[Tag Replacer] "${from}" → "${to}" | This round: ${count} | Total: ${totalCount}`);
    });
  }

  minimizeBtn.addEventListener('click', () => {
    isMinimized = !isMinimized;
    if (isMinimized) {
      body.style.display = 'none';
      ui.style.width = 'auto';
      ui.style.padding = '10px 14px';
      minimizeBtn.textContent = '▢';
      minimizeBtn.title = 'Restore';
      // 縮小時在標題顯示運作狀態
      title.textContent = isRunning
        ? `🏷️ Tag Replacer · 🔍 ${totalCount}`
        : `🏷️ Tag Replacer · ⏸`;
    } else {
      body.style.display = 'block';
      ui.style.width = '300px';
      ui.style.padding = '16px';
      minimizeBtn.textContent = '—';
      minimizeBtn.title = 'Minimize';
      title.textContent = '🏷️ Tag Replacer';
    }
  });

  toggleBtn.addEventListener('click', () => {
    if (!isRunning) {
      const from = document.getElementById('tag-replacer-from').value;
      if (!from) {
        statusDiv.textContent = '⚠️ Please enter a search string first.';
        return;
      }
      isRunning = true;
      totalCount = 0;
      toggleBtn.textContent = '⏹ Stop';
      toggleBtn.style.background = '#f38ba8';
      statusDiv.textContent = '🔍 Listening...';
      if (isMinimized) title.textContent = `🏷️ Tag Replacer · 🔍 0`;

      poll();
      intervalId = setInterval(poll, 500);
    } else {
      isRunning = false;
      clearInterval(intervalId);
      intervalId = null;
      toggleBtn.textContent = '▶ Start Replacing';
      toggleBtn.style.background = '#a6e3a1';
      statusDiv.textContent = `⏸ Stopped. Total replacements: ${totalCount}`;
      if (isMinimized) title.textContent = `🏷️ Tag Replacer · ⏸`;
    }
  });

  document.getElementById('tag-replacer-close').addEventListener('click', () => {
    if (intervalId) clearInterval(intervalId);
    ui.remove();
  });

  console.log('✅ Tag Replacer loaded');
})();

Updated by Amurita

1