MÀJ_Citation_(réparé_V3)

Réparation du bouton de citation avec pseudo (nouvelle DOM de merde de JVC...) : ajout d'un espace après un smiley.
 avatar
unknown
javascript
8 days ago
7.0 kB
19
No Index
// ==UserScript==
// @name         BOUTON CITATION QUI MET LES PSEUDOS
// @namespace    http://tampermonkey.net/
// @version      2026-04-16(3.0)
// @description  --- Mise à jour (pour Charlotte) du bouton citer pour qu'il précise le pseudo de l'auteur du message
// @author       captain_cid31/CinedineCidane - Gemini
// @match        https://www.jeuxvideo.com/forums/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=jeuxvideo.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict' ;

    // FONCTION DE PARSING COMPLÈTE
    function reverseMessage(node, isInit, isUl) {
        let quote = "" ;
        let startsWithSpoil = false ;

        for (let child of node.childNodes) {
            let name = child.nodeName ;
            switch (name) {
                case "P"   :
                case "UL"  :
                case "OL"  :
                case "PRE" : {
                    let content = reverseMessage(child, false, (name === "UL")).trim() ;
                    if (content) quote += content + "\n\n" ;
                    break ;
                }

                case "LI" :
                    quote += (isUl === true ? "* " : "# ") + reverseMessage(child).trim() + "\n" ;
                    break ;

                case "STRONG" : quote += "'''" + reverseMessage(child) + "'''"  ; break ;
                case "U"      : quote += "<u>" + reverseMessage(child) + "</u>" ; break ;
                case "S"      : quote += "<s>" + reverseMessage(child) + "</s>" ; break ;
                case "EM"     : quote += "''"  + reverseMessage(child) + "''"   ; break ;
                case "BR"     : quote += "\n" ; break ;

                case "DIV"  :
                case "SPAN" : {
                    let classList = child.classList ;
                    if (classList.contains("message__spoil")) {

                        if (quote === "") startsWithSpoil = true ;
                        let isInline = classList.contains("message__spoil--inline") ;
                        let separator = isInline ? "" : "\n\n" ;
                        quote += "<spoil>" + reverseMessage(child).trim() + "</spoil>" + separator ;

                    } else if (classList.contains("message__spoilContent")) {
                        quote += reverseMessage(child) ;
                    } else if (classList.contains("message__noBlankline")) { /* <==================== IL ÉTAIT LÀ LE SOUCI : IL FALLAIT AJOUTER LE CAS DU message__noBlankline !!! */
                        quote += reverseMessage(child) + "\n" ;
                    }
                    break ;
                }
                case "LABEL" : break ;
                case "INPUT" : break ;
                //case "BUTTON" : break ; // On ignore les boutons "Voir la citation" dans le texte

                case "IMG"  : {
                    let smiley = child.title || child.alt || "" ;
                    quote += smiley + " " ; /* <======================== Ajout d'un espace après le smiley : sinon tout est collé... */
                    break ;
                }
                case "A"    : {
                    let link = child.href || reverseMessage(child) ;
                    quote += link + " " ; /* <======================== ON AJOUTE L'ESPACE APRÈS LE LIEN : SINON PROBLÈME DE LIENS COLLÉS !!! */
                    break ;
                }
                case "CODE" : quote += "<code>" + child.textContent + "</code>" ; break ;

                case "BLOCKQUOTE" : {
                    quote = quote.trimEnd() + "\n" + reverseMessage(child).trim().replace(/^/gm, '> ') + "\n\n" ;
                    break ;
                }
                case "#text" : {
                    let txt = child.textContent ;
                    // On ne garde le texte brut que s'il n'est pas juste un saut de ligne vide du HTML
                    if (txt.replace(/\s/g, '').length > 0) {
                        quote += txt ;
                    }
                    break ;
                }
            }
        }

        quote = quote.trim() ;
        if (isInit) {
            // On ajoute le chevron au début de chaque ligne
            quote = quote.replace(/^/gm, '> ') ;
            // On nettoie les lignes qui n'auraient qu'un chevron et des espaces
            quote = quote.replace(/^> \s+$/gm, '>') ;
            if (startsWithSpoil) quote = ">\n" + quote ;
        }
        return quote ;
    }

    // LOGIQUE D'INTERCEPTION ET D'INJECTION
    async function intercepterCitation(e) {
        const btn = e.target.closest('.icon-quotes') || (e.target.classList && e.target.classList.contains('messageUser__action') && e.target.title === "Citer le message") ;
        if (!btn) return ;

        e.preventDefault() ;
        e.stopPropagation() ;

        const card = btn.closest('.messageUser__card') ;
        const pseudo = card.querySelector('.messageUser__label').textContent.trim() ;
        const date = card.querySelector('.messageUser__date').textContent.trim() ;
        const msgContent = card.querySelector('.messageUser__msg') ;
        // Appel de la fonction de parsing
        let quotedText = reverseMessage(msgContent, true) ;
        let finalQuote = `> Le ${date} ${pseudo} a écrit :\n${quotedText}\n\n` ;
        let textarea = document.querySelector('#message_reponse') ;
        if (!textarea) {
            const btnOuvrir = document.querySelector(".js-post-message, .btn-post-message") ;
            if (btnOuvrir) {
                btnOuvrir.click() ;
                for (let i = 0 ; i < 20 ; i++) {
                    await new Promise(r => setTimeout(r, 50)) ;
                    textarea = document.querySelector('#message_reponse') ;
                    if (textarea) break ;
                }
            }
        }

        if (textarea) {
            const start = textarea.selectionStart ;
            const end = textarea.selectionEnd ;
            const fullText = textarea.value.substring(0, start) + finalQuote + textarea.value.substring(end) ;
            // Injection via le setter natif pour bypasser les verrous de l'éditeur
            const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set ;
            nativeInputValueSetter.call(textarea, fullText) ;
            // On déclenche les events pour que l'interface JVC réagisse
            textarea.dispatchEvent(new Event('input', { bubbles: true })) ;
            textarea.dispatchEvent(new Event('change', { bubbles: true })) ;
            textarea.focus() ;
            textarea.setSelectionRange(start + finalQuote.length, start + finalQuote.length) ;
            textarea.scrollIntoView({ behavior: 'smooth', block: 'center' }) ;
        }
    }
    // Priorité absolue sur le clic
    document.addEventListener('click', intercepterCitation, true) ;

})() ;
Editor is loading...
Leave a Comment