Войти

Показать полную графическую версию : [решено] Правильная регулярка для замены тегов в выводе php


Mancoffee
21-02-2025, 11:43
Есть скрипт (знаю, что не профессиональный), уже замучался с регулярками.


document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll("td.e").forEach(function (cell) {
cell.innerHTML = cell.innerHTML.replace(/_/g, "_<wbr>");
});
// ---------------------------------
// Замена логотипа
const oldLogo = document.querySelector('img[src*="data:image/png;base64,"]');
if (oldLogo) {
const newLogo = document.createElement('img');
newLogo.src = '/res/imgs/phplogo.svg';
newLogo.alt = 'PHP Logo';
newLogo.className = 'custom-logo';
newLogo.style.width = '15vw';
newLogo.style.height = 'auto';

const parent = oldLogo.parentElement;

if (parent.tagName.toLowerCase() === 'a') {
parent.replaceChild(newLogo, oldLogo);

// Проверяем, есть ли уже ссылка, если нет — добавляем
if (!parent.nextElementSibling || !parent.nextElementSibling.classList.contains('logo-text')) {
const textLink = document.createElement('a');
textLink.href = 'https://github.com/BlagoYar/beautiful_phpinfo';
textLink.textContent = 'Designed by BlagoYar';
textLink.className = 'logo-text';
textLink.target = '_blank'; // Открывать в новой вкладке
textLink.rel = 'noopener noreferrer';

parent.parentElement.insertBefore(textLink, parent.nextSibling);
}
}
}



// ---------------------------------
// Замена слова active
function replaceActiveText() {
const elements = document.querySelectorAll('td.v');

elements.forEach(element => {
if (element.textContent.trim() === 'active') {
const span = document.createElement('span');
span.classList.add('enabled-text');
span.textContent = 'active';

// Заменяем текстовый узел внутри td на span
element.innerHTML = ''; // Очищаем содержимое td
element.appendChild(span); // Добавляем span внутрь td
}
});
}

// Запускаем функцию после загрузки DOM
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', replaceActiveText);
} else {
replaceActiveText(); // DOMContentLoaded уже сработал
}

function replaceFontWithClass() {
const fontElements = document.querySelectorAll('font[style*="color: #"]');

fontElements.forEach(element => {
const style = element.getAttribute('style');
const colorCode = style.match(/color: (#[\da-fA-F]{3,6})/)[1];
const colorName = getColorName(colorCode); // Получаем английское название цвета
const className = `${colorName}-${colorCode.replace('#', '')}`; // Формируем имя класса

element.classList.add(className);
element.removeAttribute('style');

// Создаем CSS правило
const styleElement = document.createElement('style');
styleElement.textContent = `.${className} { color: ${colorCode} !important; }`;
document.head.appendChild(styleElement);
});
}

function getColorName(hexColor) {
// Здесь можно добавить более сложную логику для преобразования hex в название цвета.
// Пока что, для простоты, будем возвращать просто "color"
return "color"; // В дальнейшем можно улучшить
}

// Запускаем функцию после загрузки DOM
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', replaceFontWithClass);
} else {
replaceFontWithClass(); // DOMContentLoaded уже сработал
}

// ---------------------------------
// Замена 0 и 1
const numberMappings = {
"0": "disabled-int",
"1": "enabled-int"
};

function replaceNumbersWithSpan(node) {
const text = node.textContent;
const regex = new RegExp(`(?:^|\\s)\\b(${Object.keys(numberMappings).join('|')})\\b(?:$|\\s)`, 'g');
const newContent = text.replace(regex, (match, p1) => {
const span = document.createElement('span');
span.className = numberMappings[p1];
span.textContent = p1;
return span.outerHTML;
});

const parentNode = node.parentNode;
const tempDiv = document.createElement('div');
tempDiv.innerHTML = newContent;
while (tempDiv.firstChild) {
parentNode.insertBefore(tempDiv.firstChild, node);
}
parentNode.removeChild(node);
}

function traverseNodesForNumbers(node) {
node.childNodes.forEach(child => {
if (child.nodeType === Node.ELEMENT_NODE) {
traverseNodesForNumbers(child);
} else if (child.nodeType === Node.TEXT_NODE) {
replaceNumbersWithSpan(child);
}
});
}

traverseNodesForNumbers(document.body);

// ---------------------------------
// Замена слов
const wordMappings = {
"enabled": "enabled-text",
"Enabled": "enabled-text",
"disabled": "disabled-text",
"Disabled": "disabled-text",
"Off": "disabled-text",
"On": "enabled-text",
"no value": "no-text",
"available": "available-text"
};

function replaceWordsWithSpan(node) {
const text = node.textContent;
// Улучшенное регулярное выражение:
const regex = new RegExp(`\\b(?:enabled|Enabled|disabled|Disabled|Off|On|no value|available)\\b`, 'gi');

const newContent = text.replace(regex, match => {
const span = document.createElement('span');
span.className = wordMappings[match];
span.textContent = match;
return span.outerHTML;
});

const parentNode = node.parentNode;
const tempDiv = document.createElement('div');
tempDiv.innerHTML = newContent;
while (tempDiv.firstChild) {
parentNode.insertBefore(tempDiv.firstChild, node);
}
parentNode.removeChild(node);
}

function traverseNodesForWords(node) {
node.childNodes.forEach(child => {
if (child.nodeType === Node.ELEMENT_NODE) {
if (child.tagName !== 'TH') {
traverseNodesForWords(child);
}
} else if (child.nodeType === Node.TEXT_NODE) {
replaceWordsWithSpan(child);
}
});
}

traverseNodesForWords(document.body);

document.querySelectorAll("td.v").forEach(el => {
el.childNodes.forEach(node => {
if (node.nodeType === Node.TEXT_NODE) {
node.textContent = node.textContent.replace(/\bno\b/g, 'no');
}
});
el.innerHTML = el.innerHTML.replace(/\bno\b(?!-)/g, '<span class="no-text">no</span>');
});

const scrollButtonsContainer = document.createElement("div");
scrollButtonsContainer.classList.add("scroll-buttons");
document.body.appendChild(scrollButtonsContainer);

const buttonsData = [
{ symbol: "⬆", action: () => window.scrollTo({ top: 0, behavior: 'smooth' }) },
{ symbol: "⚪", action: () => window.scrollTo({ top: document.body.scrollHeight / 2, behavior: 'smooth' }) },
{ symbol: "⬇", action: () => window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }) }
];

buttonsData.forEach(({ symbol, action }) => {
const btn = document.createElement("button");
btn.classList.add("scroll-btn");
btn.textContent = symbol;
btn.addEventListener("click", action);
scrollButtonsContainer.appendChild(btn);
});

function updateButtonPosition() {
const mainContent = document.querySelector(".center");
if (mainContent) {
const marginBottom = parseFloat(getComputedStyle(mainContent).marginBottom);
scrollButtonsContainer.style.bottom = `${marginBottom + 20}px`;
}
}

let scrollTimeout;
let firstScroll = false;

function updateButtonsVisibility() {
if (!firstScroll && window.scrollY > 50) {
firstScroll = true;
scrollButtonsContainer.classList.add("visible");
}

if (firstScroll) {
scrollButtonsContainer.classList.add("visible");
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
if (!scrollButtonsContainer.matches(":hover")) {
scrollButtonsContainer.classList.remove("visible");
}
}, 2000);
}
}

window.addEventListener("scroll", () => {
updateButtonsVisibility();
updateButtonPosition();
});

window.addEventListener("resize", updateButtonPosition);
scrollButtonsContainer.addEventListener("mouseenter", () => clearTimeout(scrollTimeout));
scrollButtonsContainer.addEventListener("mouseleave", () => {
scrollTimeout = setTimeout(() => scrollButtonsContainer.classList.remove("visible"), 2000);
});

// Убеждаемся, что кнопки скрыты при загрузке
scrollButtonsContainer.style.display = "none";

// Показываем контейнер только после первой прокрутки
window.addEventListener("scroll", function firstScrollCheck() {
if (window.scrollY > 50) {
scrollButtonsContainer.style.display = "flex";
scrollButtonsContainer.classList.add("visible");
window.removeEventListener("scroll", firstScrollCheck);
}
});

updateButtonPosition();


});



Всё нужно заменить с учётом, чтобы последующее оформление стилями не затронуло, если эти значения есть где-то в контексте с другими, например "0" встречается в "1.0.25" или "active" в "Previously active authors, editors ..."

Есть несколько ячеек с кодами цветов, нужно каждый под свой цвет/код, пример
<font style="color: [здесь код цвета в формате #FF8000]">#FF8000</font> -> <font class="color-[тот же код цвета в формате #FF8000]">#FF8000</font>

<td class="v">available, disabled </td> -> <td class="v"><span class="v available-text">available</span>,<span class="v disabled-text">disabled </span></td>
<td class="v">active </td> -> <td class="v enabled-text">active </td>
<td class="v">1</td> -> <td class="v enabled-text">1</td>
<td class="v">enabled </td> -> <td class="v enabled-text">enabled </td>
<td class="v">Enabled </td> -> <td class="v enabled-text">Enabled </td>
<td class="v">On</td> -> <td class="v enabled-text">On</td>

<td class="v">0</td> -> <td class="v disabled-text">0</td>
<td class="v">disabled </td> -> <td class="v disabled-text">disabled </td>
<td class="v">Disabled </td> -> <td class="v disabled-text">Disabled </td>
<td class="v">disabled (install ext/bz2) </td> -><td class="v"><span class="disabled-text">disabled </span> (install ext/bz2)</td>
<td class="v">Off</td> -> <td class="v disabled-text">Off</td>

<td class="v">no </td> -> <td class="v no-text">no </td>
<td class="v">no-ctrl</td> -> <td class="v no-text">no-ctrl</td>
<td class="v">nocache</td> -> <td class="v no-text">nocache</td>
<td class="v">no value </td> -> <td class="v no-text">no value </td>

Сейчас работает, но кривовато, где-то enabled в неположенном месте (session_on_enabled), в консоли браузера "[Violation]Forced reflow while executing JavaScript took 46ms"

ПС. Если кому интересно ссылка на проект (https://github.com/BlagoYar/beautiful_phpinfo)

Mancoffee
21-02-2025, 14:09
Сейчас работает, но кривовато, где-то enabled в неположенном месте (session_on_enabled), в консоли браузера "[Violation]Forced reflow while executing JavaScript took 46ms" »
Всё, решил проблему через php на пути вывода.


<?php
define('VALID_TOKEN', getenv('VALID_TOKEN_PHPINFO'));

function unauthorizedResponse() {
header('HTTP/1.1 401 Unauthorized');
readfile("/usr/share/nginx/html/401.html");
exit;
}

if ($_GET['token'] !== VALID_TOKEN) {
unauthorizedResponse();
}


// Функция для вывода User-Agent
function getUserAgent() {
return $_SERVER['HTTP_USER_AGENT'];
}

// Функция для определения мобильного устройства
function isMobile() {
$userAgent = $_SERVER['HTTP_USER_AGENT'];

// Мобильные устройства: проверка на iPhone, iPad, Android (Mobile), Windows Phone, BlackBerry, IEMobile и Opera Mini
if (preg_match('/(iPhone|iPad|iPod|Android.*Mobile|Windows Phone|BlackBerry|IEMobile|Opera Mini)/i', $userAgent)) {
return true; // Это мобильное устройство
}

// ПК устройства: если не мобильное, то по умолчанию считаем это ПК
return false;
}

// Выбор стилей в зависимости от устройства
$cssFile = isMobile() ? '/res/css/php_smart.css' : '/res/css/php_pc.css';

ob_start();
phpinfo(); // Выводим phpinfo()
$phpinfo = ob_get_clean();

?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Custom PHP Info</title>
<link rel="stylesheet" href="/res/css/php_out.css" type="text/css">
<link rel="stylesheet" href="<?php echo $cssFile; ?>" type="text/css">
<link rel="shortcut icon" href="/res/imgs/php_out_favicon.png" type="image/png">
<script defer src="/res/js/php_out.js"></script>
</head>
<body>
<?php

ob_start();
phpinfo();
$phpinfo = ob_get_clean();

$phpinfo = preg_replace('#<style.*?>.*?</style>#is', '', $phpinfo);

$phpinfo = preg_replace_callback(
'/<font style="color: (#?[A-Fa-f0-9]{6})">(.*?)<\/font>/',
function ($matches) {
$color = ltrim($matches[1], '#');
return '<span class="color-' . $color . '">' . $matches[2] . '</span>';
},
$phpinfo
);

$replacements = [
'/<td class="v">available, disabled <\/td>/' => '<td class="v"><span class="v available-text">available</span>, <span class="v disabled-text">disabled</span></td>',
'/<td class="v">available <\/td>/' => '<td class="v"><span class="v available-text">available</span></td>',
'/<td class="v">disabled <\/td>/' => '<td class="v"><span class="v disabled-text">disabled</span></td>',
'/<td class="v">active <\/td>/' => '<td class="v"><span class="v enabled-text">active</span></td>',
'/<td class="v">1<\/td>/' => '<td class="v"><span class="v enabled-text">1</span></td>',
'/<td class="v">enabled <\/td>/' => '<td class="v"><span class="v enabled-text">enabled</span></td>',
'/<td class="v">Enabled <\/td>/' => '<td class="v"><span class="v enabled-text">Enabled</span></td>',
'/<td class="v">On<\/td>/' => '<td class="v enabled-text">On</td>',
'/<td class="v">Off<\/td>/' => '<td class="v disabled-text">Off</td>',
'/<td class="v">0<\/td>/' => '<td class="v"><span class="v disabled-text">0</span></td>',
'/<td class="v">disabled <\/td>/' => '<td class="v"><span class="v disabled-text">disabled</span></td>',
'/<td class="v">Disabled <\/td>/' => '<td class="v"><span class="v disabled-text">Disabled</span></td>',
'/<td class="v">disabled \(install ext\/bz2\) <\/td>/' => '<td class="v"><span class="v disabled-text">disabled</span> (install ext/bz2)</td>',
'/<td class="v">no <\/td>/' => '<td class="v"><span class="v no-text">no</span></td>',
'/<td class="v">no-ctrl<\/td>/' => '<td class="v"><span class="v no-text">no-ctrl</span></td>',
'/<td class="v">nocache<\/td>/' => '<td class="v"><span class="v no-text">nocache</span></td>',
'/<td class="v">none<\/td>/' => '<td class="v"><span class="v no-text">none</span></td>',
'/<td class="v"><i>no value<\/i><\/td>/' => '<td class="v"><i class="no-text">no value</i></td>',
'/<tr class="h"><th>(.*?)<\/th><th>enabled<\/th><\/tr>/' => '<tr class="h"><th>$1</th><th class="enabled-text">enabled</th></tr>',
'/<td class="v">on<\/td>/' => '<td class="v enabled-text">on</td>',
'/<td class="v">off<\/td>/' => '<td class="v disabled-text">off</td>',
'/<tr class="h"><th>(.*?)<\/th><th>disabled<\/th><\/tr>/' => '<tr class="h"><th>$1</th><th class="disabled-text">disabled</th></tr>',
'/<td class="v">OK <\/td>/' => '<td class="v enabled-text">OK </td>',
'/<td class="v">no-cache<\/td>/' => '<td class="v"><span class="v no-text">no-cache</span></td>',
'/<td class="v">0 <\/td>/' => '<td class="v"><span class="v disabled-text">0 </span></td>',
'/<td class="v"><i>no value<\/i> <\/td>/' => '<td class="v"><i class="no-text">no value</i> </td>',
];

$phpinfo = preg_replace(array_keys($replacements), array_values($replacements), $phpinfo);

echo $phpinfo;
?>
</body>
</html>


Всем спасибо за внимание :)




© OSzone.net 2001-2012