// ==UserScript== // @name NetBox DNS Name → SSH links // @version 1.0 // @description Trasforma la colonna "DNS Name" in link ssh:// nella lista IP addresses di NetBox // @match *://netbox.example.com/* // @grant none // @run-at document-idle // ==/UserScript== (function () { 'use strict'; const TAG = '[ssh-links]'; const HEADER = 'dns name'; // confronto case-insensitive const DEBUG = false; const log = (...a) => DEBUG && console.log(TAG, ...a); if (!location.pathname.includes('/ipam/ip-addresses')) return; function findColumnIndex(table) { const ths = table.querySelectorAll('thead th'); for (let i = 0; i < ths.length; i++) { if (ths[i].textContent.trim().toLowerCase() === HEADER) return i; } console.warn(TAG, 'colonna DNS name non trovata'); return -1; } function processTable(table) { const idx = findColumnIndex(table); if (idx === -1) return; let done = 0; table.querySelectorAll('tbody > tr').forEach(tr => { const cell = tr.children[idx]; if (!cell) return; if (cell.querySelector('a[href^="ssh://"]')) return; const name = cell.textContent.trim(); if (!name || name === '—' || name === '-') return; const a = document.createElement('a'); a.href = 'ssh://' + name; a.textContent = name; cell.replaceChildren(a); done++; }); log('link creati:', done); } function run() { document.querySelectorAll('table.table.table-hover.object-list').forEach(processTable); } run(); // NetBox usa htmx: la tabella viene rimpiazzata su sort/paginazione/filtri let pending = false; const mo = new MutationObserver(() => { if (pending) return; pending = true; setTimeout(() => { pending = false; run(); }, 100); }); mo.observe(document.body, { childList: true, subtree: true }); })();