Function to replace text matching (c/ID) with a link
// ==UserScript==
// @name Trello link replacer
// @namespace http://tampermonkey.net/
// @match https://phabricator.clockwise.info/*
// @description Function to replace text matching (c/ID) with a link
// @version 0.0.1.20241216091059
// ==/UserScript==
// Function to replace text matching (c/ID) with a link
setTimeout(() => {
const replaceTrelloLinks = () => {
// Regex to match (c/ID) pattern
const regex = /\(c\/([a-zA-Z0-9]+)\)/g;
// Recursive function to process text nodes
const processNode = (node) => {
if (node.nodeType === Node.TEXT_NODE) {
const matches = [...node.textContent.matchAll(regex)];
if (matches.length > 0) {
const parent = node.parentNode;
const fragments = [];
let lastIndex = 0;
matches.forEach((match) => {
const [fullMatch, id] = match;
const startIndex = match.index;
// Text before the match
if (startIndex > lastIndex) {
fragments.push(document.createTextNode(node.textContent.slice(lastIndex, startIndex)));
}
// Create the link
const link = document.createElement("a");
link.href = `https://trello.com/c/${id}`;
link.textContent = fullMatch;
fragments.push(link);
lastIndex = startIndex + fullMatch.length;
});
// Text after the last match
if (lastIndex < node.textContent.length) {
fragments.push(document.createTextNode(node.textContent.slice(lastIndex)));
}
// Replace the original text node with the new content
fragments.forEach((fragment) => parent.insertBefore(fragment, node));
parent.removeChild(node);
}
} else if (node.nodeType === Node.ELEMENT_NODE) {
// Avoid replacing text inside <a> tags
if (node.tagName.toLowerCase() !== "a") {
Array.from(node.childNodes).forEach(processNode);
}
}
};
// Start processing the body of the document
Array.from(document.body.childNodes).forEach(processNode);
};
replaceTrelloLinks();
}, 500);