// ==UserScript==
// @name Ozon Product Links
// @namespace http://tampermonkey.net/
// @version 1.01
// @description Заменяет 10-значные номера товаров Ozon на кликабельные ссылки
// @author Gemini
// @match https://mipped.com/f/threads/ozon-ru-obshchaya-tema-2.320473/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Регулярное выражение для поиска ровно 10 цифр
const productRegex = /\b\d{9,10}\b/g;
const ozonBaseUrl = 'https://www.ozon.ru/product/';
function createLink(id) {
const a = document.createElement('a');
a.href = ozonBaseUrl + id + '/';
a.textContent = id;
a.target = '_blank';
a.style.color = '#005bff'; // Фирменный цвет Ozon для наглядности
a.style.textDecoration = 'underline';
return a;
}
function processNode(node) {
// Ищем элементы с нужным классом
const elements = node.querySelectorAll ? node.querySelectorAll('.message-content') : [];
// Если сам переданный узел имеет этот класс, добавляем в список
const targets = node.classList && node.classList.contains('message-content')
? [node, ...elements]
: elements;
targets.forEach(container => {
const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, null, false);
const nodesToReplace = [];
let textNode;
while (textNode = walker.nextNode()) {
// Игнорируем, если текст уже находится внутри ссылки
if (textNode.parentElement.tagName === 'A') continue;
if (productRegex.test(textNode.nodeValue)) {
nodesToReplace.push(textNode);
}
}
// Заменяем найденные текстовые узлы
nodesToReplace.forEach(node => {
const fragment = document.createDocumentFragment();
let lastIndex = 0;
node.nodeValue.replace(productRegex, (match, offset) => {
// Добавляем текст перед числом
fragment.appendChild(document.createTextNode(node.nodeValue.substring(lastIndex, offset)));
// Добавляем саму ссылку
fragment.appendChild(createLink(match));
lastIndex = offset + match.length;
});
// Добавляем оставшийся текст после последнего совпадения
fragment.appendChild(document.createTextNode(node.nodeValue.substring(lastIndex)));
node.parentNode.replaceChild(fragment, node);
});
});
}
// Наблюдаем за изменениями в DOM для поддержки динамического контента
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(newNode => processNode(newNode));
});
});
// Запуск при загрузке
processNode(document.body);
observer.observe(document.body, { childList: true, subtree: true });
})();