Amazon Product Copier

Copies Amazon product information to the clipboard with the press of a button.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

You will need to install an extension such as Tampermonkey to install this script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Amazon Product Copier
// @description  Copies Amazon product information to the clipboard with the press of a button.
// @author       Tim Macy
// @license      AGPL-3.0-or-later
// @version      1.1
// @namespace    TimMacy.AmazonProductCopier
// @include      /^https:\/\/www\.amazon\..+?\/.*/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=amazon.com
// @run-at       document-end
// @noframes
// @homepageURL  https://github.com/TimMacy/AmazonProductCopier
// @supportURL   https://github.com/TimMacy/AmazonProductCopier/issues
// ==/UserScript==

/************************************************************************
*                                                                       *
*                    Copyright © 2025 Tim Macy                          *
*                    GNU Affero General Public License v3.0             *
*                    Version: 1.1 - Amazon Product Copier               *
*                                                                       *
*             Visit: https://github.com/TimMacy                         *
*                                                                       *
************************************************************************/

(async function () {
    'use strict';
    // CSS
    const styleSheet = document.createElement('style');
    styleSheet.textContent = `
        #amazonCopierBtn {
            position: fixed;
            left: 20px;
            bottom: 20px;
            z-index: 9999;
            padding: 4px 8px;
            margin-left: 8px;
            font-size: 12px;
            font-weight: 500;
            cursor: pointer;
            border-radius: 2px;
            border: 1px solid #a88734;
            background: var(--__dChw-LmGoMXsPxT,#ffd814);
            color: var(--__dChw-LmGoMXsw4B,#0f1111);
        }

        #amazonCopierBtn:hover {
            background: var(--__dChw-LmGofIsPxT,#ffce12);
        }

        .CentAnni-force-visibility #productDetails_feature_div div.a-expander-content,
        .CentAnni-force-visibility #productDetailsWithModules_feature_div div.a-expander-content,
        .CentAnni-force-visibility #centerCol #nutritionalInfoAndIngredients_feature_div div.a-expander-content.a-expander-section-content,
        .CentAnni-force-visibility div#productDescription_feature_div div[data-a-expander-name="toggle_description"] div.a-expander-content.a-expander-extend-content {
            display: block !important;
        }

        .CentAnni-force-visibility div#productOverview_feature_div span.a-expander-prompt,
        .CentAnni-force-visibility div#productDescription_feature_div span.a-expander-prompt {
            display: none;
        }

        .CentAnni-overlay {
            position: fixed;
            display: flex;
            z-index: 2053;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            align-items: center;
            justify-content: center;
            background-color: rgba(0, 0, 0, .5);
            backdrop-filter: blur(5px);
        }

        .CentAnni-notification {
            background: hsl(0, 0%, 7%);
            padding: 20px 30px;
            border-radius: 8px;
            border: 1px solid hsl(0, 0%, 18.82%);
            max-width: 80%;
            text-align: center;
            font-family: -apple-system, "Roboto", "Arial", sans-serif;
            font-size: 16px;
            color: white;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }
    `;

    // append css
    (document.head
        ? Promise.resolve(document.head)
        : new Promise(resolve => {
            document.readyState === 'loading'
                ? document.addEventListener('DOMContentLoaded', () => resolve(document.head), { once: true })
                : resolve(document.head);
        })
    ).then(head => {
        if (head)
            head.appendChild(styleSheet);
        else {
            document.documentElement.appendChild(styleSheet);
            console.error("AmazonProductCopier: Failed to find head element. Using backup to append stylesheet.");
        }
    });

    // elements to copy
    const productTitleSelector = "#productTitle";
    const infoSelectors = [
        '#social-proofing-faceout-title-tk_bought',
        'div[id^="corePriceDisplay_"] > div.aok-relative > span:first-child',
        'div[id^="corePriceDisplay_"] > div.a-spacing-small span.aok-offscreen',
        'div#productOverview_feature_div',
        'div#featurebullets_feature_div',
        'div.a-expander-collapsed-height.a-row.a-expander-container.a-spacing-medium.a-expander-partial-collapse-container',
        '#centerCol #nutritionalInfoAndIngredients_feature_div',
        '.a-cardui.brand-snapshot-card-container',
        'div#productDetails_feature_div',
        'div#productDetailsWithModules_feature_div',
        'div#importantInformation_feature_div',
        'div#productDescription_feature_div:first-child',
        'div#detailBulletsWithExceptions_feature_div',
        'div#detailBulletsReverseInterleaveContainer_feature_v2',
        '#detailBullets2_feature_div',
        '#reviewsMedley #averageCustomerReviewsAnchor',
        'span[data-hook="rating-out-of-text"]',
        'span[data-hook="total-review-count"]',
        '#histogramTable',
        '#reviewsMedley .cm_cr_grid_center_right div[data-csa-c-item-id="cr-product-insights-cards"] h3',
        '#reviewsMedley .cm_cr_grid_center_right div[data-csa-c-item-id="cr-product-insights-cards"] div[data-testid="overall-summary"]',
        '#reviewsMedley .cm_cr_grid_center_right div[data-csa-c-item-id="cr-product-insights-cards"] div[data-testid="ai-disclaimer"] > span:first-child',
        '#reviewsMedley .cm_cr_grid_center_right div[data-csa-c-item-id="cr-product-insights-cards"] div[data-csa-c-item-id="cr-product-insights-cards-popover"] div[id^="rh_controls_aspect_"]'
    ];

    // build content
    const buildContent = () => {
        const titleNode = document.querySelector(productTitleSelector);
        const rawTitle = titleNode?.textContent?.trim();
        const title = rawTitle ? rawTitle.replace(/\s+/g, " ") : "";
        if (!title) return "";

        const rawBlocks = infoSelectors.flatMap(selector => Array.from(document.querySelectorAll(selector))).map(node => node?.innerText?.trim()).filter(text => text && text.length > 0);
        const fixedBlocks = rawBlocks.map(block => {
            if (!block.includes('5 star') || !block.includes('3 star')) return block;

            const lines = block.split('\n').map(line => line.trim()).filter(line => line.length > 0);
            if (lines.length % 2 !== 0) return block;

            const merged = [];
            for (let i = 0; i < lines.length; i += 2) merged.push(lines[i] + ' ' + lines[i + 1]);
            return merged.join('\n');
        });

        const infoText = fixedBlocks.join('\n\n');
        if (!infoText) return "";

        const header = `<product: ${title}>\n`;
        const footer = `\n</product: ${title}>`;
        return header + infoText + footer;
    };

    // copy to clipboard
    const copyToClipboard = async () => {
        document.body.classList.add("CentAnni-force-visibility");
        const payload = buildContent();
        if (payload) {
            await navigator.clipboard.writeText(payload);
            showNotification('Content Copied to Clipboard.');
        }
        document.body.classList.remove("CentAnni-force-visibility");
    };

    // function to display the notification
    function showNotification(message) {
        const overlay = document.createElement('div');
        overlay.classList.add('CentAnni-overlay');

        const modal = document.createElement('div');
        modal.classList.add('CentAnni-notification');
        modal.textContent = message;

        overlay.appendChild(modal);
        document.body.appendChild(overlay);

        setTimeout(() => { overlay.remove(); }, 600);
    }

    // add the button
    const addButton = () => {
        const titleSection = document.querySelector("#titleSection") || document.querySelector("#buybox");
        if (!titleSection || document.querySelector("#amazonCopierBtn")) return;

        const btn = document.createElement("button");
        btn.id = "amazonCopierBtn";
        btn.type = "button";
        btn.textContent = "Copy Content";
        btn.addEventListener("click", () => { copyToClipboard(); });

        document.body.appendChild(btn);
    };

    document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", addButton, { once: true }) : addButton();
})();