您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
An automatic and free score downloader for musescore
当前为
// ==UserScript== // @name Musescore Free PDF Downloader // @namespace http://tampermonkey.net/ // @version 1.2 // @author malatia // @match https://musescore.com/*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=musescore.com // @grant GM_addStyle // @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.16.0/pdf-lib.min.js // @description An automatic and free score downloader for musescore // @license MIT // ==/UserScript== // Idea from MuseScore Download By flancast90 let DEBUG = true function get_lazy_imgs() { console.log("Début get_lazy_images"); return new Promise((resolve, reject) => { // Fonction récursive pour récupérer les images function fetchImages() { scrollContainer = document.getElementById('jmuse-scroller-component'); scrollHeight = scrollContainer.scrollHeight; if (scrolled < scrollHeight) { // Faire défiler la fenêtre scrollContainer.scrollTop = scrolled; scrolled += height; // Attendre un peu avant de récupérer les images setTimeout(() => { // Récupérer les images const images = document.getElementsByClassName('KfFlO'); if (images.length > 0) { // Ajouter les URLs des images au tableau urls.push(images[images.length - 1].src); } // Rappel récursif jusqu'à ce que le scroll atteigne la fin fetchImages(); }, 1000); } else { // Résoudre la promesse avec les URLs des images resolve(urls); console.log("Fin get_lazy_images"); } } // Début de la récupération des images fetchImages(); }); } async function download_pdf() { console.log("Avant get_lazy_images"); await get_lazy_imgs(); // Attendre la récupération de toutes les URLs d'images console.log("Après get_lazy_images"); console.log("Avant fetchAndAssemble"); await fetchAndAssemblePDF(urls); // Utiliser les URLs pour générer le PDF console.log("Après fetchAndAssemble"); scrolled = 0; // Réinitialiser le défilement } function createFloatingIframeButton() { if (document.getElementById('tm-fab-frame')) return; const iframe = document.createElement('iframe'); iframe.id = 'tm-fab-frame'; Object.assign(iframe.style, { position: 'fixed', bottom: '20px', left: '20px', width: '160px', height: '48px', border: '0', padding: '0', margin: '0', zIndex: '2147483647', background: 'transparent', pointerEvents: 'auto' }); // Contenu interne de l'iframe (même origine → on peut y accéder) iframe.srcdoc = ` <!doctype html><html><head><meta charset="utf-8"> <style> html,body{margin:0;padding:0;background:transparent} #btn{ all:unset; display:inline-block; padding:10px 14px; border-radius:9999px; box-shadow:0 8px 30px rgba(0,0,0,.25); background:#0dbc79; color:#fff; font:14px/1.2 system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif; cursor:pointer; user-select:none; } #btn:hover{filter:brightness(1.06)} #btn:active{transform:translateY(1px)} </style></head><body> <button id="btn" title="Télécharger le PDF">Télécharger PDF</button> </body></html>`.trim(); document.documentElement.appendChild(iframe); // Quand l'iframe est prête, on accroche NOTRE handler (dans le contexte userscript) iframe.addEventListener('load', () => { const doc = iframe.contentDocument; const btn = doc && doc.getElementById('btn'); if (!btn) return; btn.addEventListener('click', download_pdf_wrapper); // ici, le site ne peut pas bloquer console.log('[TM] Bouton flottant (iframe) prêt.'); }); } async function download_pdf_wrapper(e) { if (e) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); } try { // On repart de zéro à chaque run scrolled = 0; urls = []; // Si la page n'a pas encore initialisé height/scrollContainer, on tente ici if (!height) { const firstImg = document.getElementsByClassName('KfFlO')[0]; if (firstImg) height = parseInt(firstImg.height); } if (!scrollContainer) { scrollContainer = document.getElementById('jmuse-scroller-component'); } await download_pdf(); } catch (err) { console.error('[TM] download_pdf_wrapper error:', err); alert('Échec du téléchargement PDF. Regarde la console pour les détails.'); } } async function img_to_canvas_to_bytes(img) { return new Promise((resolve, reject) => { // Création d'un canvas pour dessiner l'image const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // Chargement de l'image dans le canvas img.crossOrigin = 'Anonymous'; // Permet d'accéder à l'image cross-origin img.onload = () => { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); // Conversion du contenu du canvas en données PNG const pngBytes = canvas.toDataURL('image/png').split(',')[1]; resolve(pngBytes); }; img.onerror = () => { reject(new Error('Échec du chargement de l\'image.')); }; img.src = img.src; // Déclenche le chargement de l'image }); } async function fetchAndAssemblePDF(urls) { // Création d'un nouveau document PDF const pdfDoc = await PDFLib.PDFDocument.create(); // Tableau pour stocker les documents PNG générés const pngDocs = []; // Parcours de chaque URL de fichier img console.log("Avant boucle urls") for (const url of urls) { console.log("url = " + url) // Récupération du fichier img à partir de l'URL const response = await fetch(url); console.log(response) const imgText = await response.text(); if (url.includes(".svg")) { const img = new Image(); const imgLoaded = new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; }); // Création d'un blob à partir du texte SVG const svgBlob = new Blob([imgText], { type: 'image/svg+xml' }); // Création d'une image à partir du blob SVG img.src = URL.createObjectURL(svgBlob); // Attente du chargement complet de l'image try { // Attendre le chargement complet de l'image await imgLoaded; console.log("Image SVG chargée avec succès"); } catch (error) { console.error("Erreur lors du chargement de l'image SVG:", error); continue; // Passe à l'itération suivante dans la boucle } // Création d'un canvas pour dessiner l'image SVG const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); // Conversion du canvas en format PNG const pngBytes = canvas.toDataURL('image/png').split(',')[1]; // Incorporation du PNG dans le document PDF const pngDoc = await pdfDoc.embedPng(pngBytes); pngDocs.push(pngDoc); // Ajout du document PNG au tableau } else if (url.includes(".png")) { console.log("Dans la partie PNG"); const img = new Image(); const imgLoaded = new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; }); // Chargement de l'image à partir de l'URL img.src = url; // Promesse basée sur le chargement complet de l'image try { // Attendre le chargement complet de l'image await imgLoaded; console.log("Image PNG chargée avec succès"); } catch (error) { console.error("Erreur lors du chargement de l'image PNG:", error); continue; // Passe à l'itération suivante dans la boucle } const pngBytes = await img_to_canvas_to_bytes(img) // Incorporation de l'image PNG dans le document PDF const pngDoc = await pdfDoc.embedPng(pngBytes); pngDocs.push(pngDoc); } } // Parcours des documents PNG pour les ajouter au document PDF for (const pngDoc of pngDocs) { const page = pdfDoc.addPage([pngDoc.width, pngDoc.height]); page.drawImage(pngDoc, { x: 0, y: 0, width: pngDoc.width, height: pngDoc.height, }); } // Enregistrement du document PDF const pdfBytes = await pdfDoc.save(); // Téléchargement du PDF const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); let title = document.title.replace(" ", "_") + ".pdf" link.download = title; link.click(); } let scrolled = 0; let urls = []; let height; let scrollHeight; let scrollContainer $(document).ready(async function () { console.log("SCRIPT LOADED"); setTimeout(() => { console.log("Set timeout"); // ICI ON PARLE DU CONTENANT AVEC SCROLL scrollContainer = parseInt(document.getElementById('jmuse-scroller-component').scrollHeight); // ICI ON PARLE DES IMAGES height = parseInt(document.getElementsByClassName('KfFlO')[0].height); console.log("height = " + height); scrollHeight = (scrollContainer - (scrollContainer % height)); console.log("scrollHeight = " + scrollHeight); // installe le bouton iframe (à la fin de ton $(document).ready(...)) createFloatingIframeButton(); // (optionnel) réinstalle si le site détruit le nœud const mo = new MutationObserver(() => { if (!document.getElementById('tm-fab-frame')) createFloatingIframeButton(); }); mo.observe(document.documentElement, { childList: true, subtree: true }); // (optionnel) menu Tampermonkey en secours if (typeof GM_registerMenuCommand === 'function') { GM_registerMenuCommand('Télécharger PDF', () => download_pdf_wrapper()); } // (optionnel) raccourci clavier Ctrl+Alt+D window.addEventListener('keydown', (e) => { if ((e.ctrlKey || e.metaKey) && e.altKey && e.key.toLowerCase() === 'd') { e.preventDefault(); download_pdf_wrapper(); } }, true); }, 2000) });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址