[решено] Правильная регулярка для замены тегов в выводе php

Ответить
Аватара пользователя
Mancoffee

[решено] Правильная регулярка для замены тегов в выводе php

Сообщение Mancoffee »

Есть скрипт (знаю, что не профессиональный), уже замучался с регулярками.



Скрытый текст

[spoiler]Код:
[/spoiler]

Код: Выделить всё

document.addEventListener("DOMContentLoaded", function() {
    document.querySelectorAll("td.e").forEach(function (cell) {
        cell.innerHTML = cell.innerHTML.replace(/_/g, "_");
    });
// ---------------------------------
// Замена логотипа
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, 'no');
    });
    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 ..."



Есть несколько ячеек с кодами цветов, нужно каждый под свой цвет/код, пример

#FF8000 -> #FF8000



available, disabled -> available,disabled

active -> active

1 -> 1

enabled -> enabled

Enabled -> Enabled

On -> On



0 -> 0

disabled -> disabled

Disabled -> Disabled

disabled (install ext/bz2) ->disabled (install ext/bz2)

Off -> Off



no -> no

no-ctrl -> no-ctrl

nocache -> nocache

no value -> no value



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



ПС. Если кому интересно
ссылка на проект
Аватара пользователя
Mancoffee

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

Сообщение Mancoffee »

Цитата Mancoffee:



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




Всё, решил проблему через php на пути вывода.



Скрытый текст

[spoiler]

Код: Выделить всё

<?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>
[/spoiler]






Всем спасибо за внимание Изображение
Ответить

Вернуться в «Вебмастеру»