Export Elsevier inspection copy articles to PDF
Size
6.0 KB
Version
1.1.1
Created
Dec 1, 2025
Updated
11 days ago
1// ==UserScript==
2// @name Elsevier Article PDF Exporter
3// @description Export Elsevier inspection copy articles to PDF
4// @version 1.1.1
5// @match https://*.inspectioncopy.elsevier.com/*
6// @icon https://www.inspectioncopy.elsevier.com/favicon.ico
7// @require https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
8// @require https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
9// ==/UserScript==
10(function() {
11 'use strict';
12
13 console.log('Elsevier PDF Exporter loaded');
14
15 // Wait for page to load
16 function init() {
17 console.log('Initializing PDF exporter');
18
19 // Check if we're on a book reading page
20 if (window.location.pathname.includes('/read/')) {
21 createExportButton();
22 }
23 }
24
25 function createExportButton() {
26 console.log('Creating export button');
27
28 // Create a floating export button
29 const exportBtn = document.createElement('button');
30 exportBtn.id = 'elsevier-pdf-export-btn';
31 exportBtn.innerHTML = '📄 Export to PDF';
32 exportBtn.style.cssText = `
33 position: fixed;
34 top: 20px;
35 right: 20px;
36 z-index: 999999;
37 padding: 12px 24px;
38 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
39 color: white;
40 border: none;
41 border-radius: 8px;
42 font-size: 14px;
43 font-weight: 600;
44 cursor: pointer;
45 box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
46 transition: all 0.3s ease;
47 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
48 `;
49
50 // Hover effect
51 exportBtn.onmouseenter = () => {
52 exportBtn.style.transform = 'translateY(-2px)';
53 exportBtn.style.boxShadow = '0 6px 20px rgba(0, 0, 0, 0.3)';
54 };
55 exportBtn.onmouseleave = () => {
56 exportBtn.style.transform = 'translateY(0)';
57 exportBtn.style.boxShadow = '0 4px 15px rgba(0, 0, 0, 0.2)';
58 };
59
60 exportBtn.onclick = handleExportClick;
61
62 document.body.appendChild(exportBtn);
63 console.log('Export button added to page');
64 }
65
66 async function handleExportClick() {
67 console.log('Export button clicked');
68
69 const btn = document.getElementById('elsevier-pdf-export-btn');
70 const originalText = btn.innerHTML;
71
72 try {
73 btn.innerHTML = '⏳ Preparing PDF...';
74 btn.disabled = true;
75 btn.style.opacity = '0.7';
76 btn.style.cursor = 'wait';
77
78 // Get the iframe containing the book content
79 const iframe = document.querySelector('iframe');
80
81 if (!iframe) {
82 throw new Error('Could not find book content iframe');
83 }
84
85 // Get book title from page
86 const pageTitle = document.getElementById('page-title')?.value || 'Elsevier Article';
87 const bookTitle = document.title || pageTitle;
88
89 console.log('Capturing content for:', bookTitle);
90
91 // Since the content is in an iframe from a different domain (Calameo),
92 // we'll capture the visible viewport
93 btn.innerHTML = '📸 Capturing content...';
94
95 const canvas = await html2canvas(document.body, {
96 allowTaint: true,
97 useCORS: true,
98 scale: 2,
99 logging: false,
100 backgroundColor: '#ffffff'
101 });
102
103 btn.innerHTML = '📝 Generating PDF...';
104
105 // Create PDF
106 const { jsPDF } = window.jspdf;
107 const pdf = new jsPDF({
108 orientation: 'portrait',
109 unit: 'mm',
110 format: 'a4'
111 });
112
113 const imgData = canvas.toDataURL('image/png');
114 const pdfWidth = pdf.internal.pageSize.getWidth();
115 const pdfHeight = pdf.internal.pageSize.getHeight();
116
117 // Calculate dimensions to fit the page
118 const imgWidth = pdfWidth;
119 const imgHeight = (canvas.height * pdfWidth) / canvas.width;
120
121 pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight);
122
123 // Generate filename
124 const filename = `${bookTitle.replace(/[^a-z0-9]/gi, '_')}_export.pdf`;
125
126 btn.innerHTML = '💾 Downloading...';
127
128 // Save the PDF
129 pdf.save(filename);
130
131 console.log('PDF exported successfully:', filename);
132
133 // Success feedback
134 btn.innerHTML = '✅ Downloaded!';
135 btn.style.background = 'linear-gradient(135deg, #11998e 0%, #38ef7d 100%)';
136
137 setTimeout(() => {
138 btn.innerHTML = originalText;
139 btn.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
140 btn.disabled = false;
141 btn.style.opacity = '1';
142 btn.style.cursor = 'pointer';
143 }, 2000);
144
145 } catch (error) {
146 console.error('Error exporting PDF:', error);
147
148 btn.innerHTML = '❌ Export Failed';
149 btn.style.background = 'linear-gradient(135deg, #eb3349 0%, #f45c43 100%)';
150
151 setTimeout(() => {
152 btn.innerHTML = originalText;
153 btn.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
154 btn.disabled = false;
155 btn.style.opacity = '1';
156 btn.style.cursor = 'pointer';
157 }, 3000);
158
159 alert('Failed to export PDF. Please try again or check the console for details.');
160 }
161 }
162
163 // Initialize when DOM is ready
164 if (document.readyState === 'loading') {
165 document.addEventListener('DOMContentLoaded', init);
166 } else {
167 init();
168 }
169})();