Enterprise Command Center PDF Extractor

Extract OCR searchable PDF from Enterprise Command Center documentation pages

Size

10.7 KB

Version

1.1.1

Created

Dec 17, 2025

Updated

about 2 months ago

1// ==UserScript==
2// @name		Enterprise Command Center PDF Extractor
3// @description		Extract OCR searchable PDF from Enterprise Command Center documentation pages
4// @version		1.1.1
5// @match		https://*.eservice.addigital.gov.ae/*
6// @require		https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('Enterprise Command Center PDF Extractor loaded');
12
13    // Add styles for the PDF button
14    TM_addStyle(`
15        #ecc-pdf-button {
16            position: fixed;
17            top: 20px;
18            right: 20px;
19            z-index: 10000;
20            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
21            color: white;
22            border: none;
23            padding: 12px 24px;
24            border-radius: 8px;
25            font-size: 14px;
26            font-weight: 600;
27            cursor: pointer;
28            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
29            transition: all 0.3s ease;
30            display: flex;
31            align-items: center;
32            gap: 8px;
33        }
34        
35        #ecc-pdf-button:hover {
36            transform: translateY(-2px);
37            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
38        }
39        
40        #ecc-pdf-button:active {
41            transform: translateY(0);
42        }
43        
44        #ecc-pdf-button.processing {
45            background: #95a5a6;
46            cursor: wait;
47        }
48        
49        #ecc-pdf-button .spinner {
50            display: none;
51            width: 16px;
52            height: 16px;
53            border: 2px solid #ffffff;
54            border-top-color: transparent;
55            border-radius: 50%;
56            animation: spin 0.8s linear infinite;
57        }
58        
59        #ecc-pdf-button.processing .spinner {
60            display: block;
61        }
62        
63        @keyframes spin {
64            to { transform: rotate(360deg); }
65        }
66    `);
67
68    function extractPageContent() {
69        console.log('Extracting page content...');
70        
71        // Get the main content area
72        const mainContent = document.body;
73        
74        if (!mainContent) {
75            console.error('Could not find main content');
76            return null;
77        }
78
79        // Extract title
80        const title = document.title || 'Enterprise Command Center Documentation';
81        
82        // Extract all text content with structure
83        const content = [];
84        
85        // Get all headings, paragraphs, and images
86        const elements = mainContent.querySelectorAll('h1, h2, h3, h4, h5, h6, p, li, td, th, div, img');
87        
88        elements.forEach(el => {
89            // Handle images
90            if (el.tagName.toLowerCase() === 'img') {
91                const src = el.src;
92                const alt = el.alt || 'Image';
93                if (src && !src.startsWith('data:image/svg')) {
94                    content.push({
95                        type: 'img',
96                        src: src,
97                        alt: alt,
98                        width: el.naturalWidth || el.width,
99                        height: el.naturalHeight || el.height
100                    });
101                }
102                return;
103            }
104            
105            const text = el.textContent.trim();
106            if (text && text.length > 0) {
107                const tagName = el.tagName.toLowerCase();
108                
109                // Skip if this element's text is already included in a parent
110                let isNested = false;
111                let parent = el.parentElement;
112                while (parent && parent !== mainContent) {
113                    if (parent.matches('h1, h2, h3, h4, h5, h6, p, li, td, th')) {
114                        isNested = true;
115                        break;
116                    }
117                    parent = parent.parentElement;
118                }
119                
120                if (!isNested) {
121                    content.push({
122                        type: tagName,
123                        text: text
124                    });
125                }
126            }
127        });
128        
129        console.log(`Extracted ${content.length} content elements`);
130        return { title, content };
131    }
132
133    async function generatePDF() {
134        console.log('Starting PDF generation...');
135        
136        const button = document.getElementById('ecc-pdf-button');
137        button.classList.add('processing');
138        button.innerHTML = '<span class="spinner"></span> Generating PDF...';
139        
140        try {
141            const pageData = extractPageContent();
142            
143            if (!pageData || !pageData.content || pageData.content.length === 0) {
144                alert('No content found to extract');
145                return;
146            }
147            
148            // Initialize jsPDF
149            const { jsPDF } = window.jspdf;
150            const doc = new jsPDF({
151                orientation: 'portrait',
152                unit: 'mm',
153                format: 'a4'
154            });
155            
156            // Page settings
157            const pageWidth = doc.internal.pageSize.getWidth();
158            const pageHeight = doc.internal.pageSize.getHeight();
159            const margin = 20;
160            const maxWidth = pageWidth - (margin * 2);
161            let yPosition = margin;
162            
163            // Add title
164            doc.setFontSize(18);
165            doc.setFont(undefined, 'bold');
166            const titleLines = doc.splitTextToSize(pageData.title, maxWidth);
167            doc.text(titleLines, margin, yPosition);
168            yPosition += titleLines.length * 8 + 10;
169            
170            // Add URL and date
171            doc.setFontSize(10);
172            doc.setFont(undefined, 'normal');
173            doc.setTextColor(100, 100, 100);
174            doc.text(`Source: ${window.location.href}`, margin, yPosition);
175            yPosition += 6;
176            doc.text(`Generated: ${new Date().toLocaleString()}`, margin, yPosition);
177            yPosition += 15;
178            
179            doc.setTextColor(0, 0, 0);
180            
181            // Add content
182            for (const item of pageData.content) {
183                // Handle images
184                if (item.type === 'img') {
185                    try {
186                        // Calculate image dimensions to fit page
187                        const maxImgWidth = maxWidth;
188                        const maxImgHeight = pageHeight - margin - yPosition - 20;
189                        
190                        let imgWidth = item.width;
191                        let imgHeight = item.height;
192                        
193                        // Scale image to fit width
194                        if (imgWidth > maxImgWidth) {
195                            const ratio = maxImgWidth / imgWidth;
196                            imgWidth = maxImgWidth;
197                            imgHeight = imgHeight * ratio;
198                        }
199                        
200                        // Check if image fits on current page
201                        if (yPosition + imgHeight > pageHeight - margin) {
202                            doc.addPage();
203                            yPosition = margin;
204                        }
205                        
206                        // Add image to PDF
207                        doc.addImage(item.src, 'JPEG', margin, yPosition, imgWidth, imgHeight);
208                        yPosition += imgHeight + 5;
209                        
210                        // Add image caption if available
211                        if (item.alt && item.alt !== 'Image') {
212                            doc.setFontSize(9);
213                            doc.setTextColor(100, 100, 100);
214                            const captionLines = doc.splitTextToSize(item.alt, maxWidth);
215                            doc.text(captionLines, margin, yPosition);
216                            yPosition += captionLines.length * 4 + 5;
217                            doc.setTextColor(0, 0, 0);
218                        }
219                        
220                        console.log('Added image to PDF:', item.alt);
221                    } catch (imgError) {
222                        console.error('Error adding image to PDF:', imgError);
223                        // Continue with next item if image fails
224                    }
225                    continue;
226                }
227                
228                // Check if we need a new page
229                if (yPosition > pageHeight - margin - 20) {
230                    doc.addPage();
231                    yPosition = margin;
232                }
233                
234                // Set font based on element type
235                if (item.type.startsWith('h')) {
236                    const level = parseInt(item.type.charAt(1));
237                    doc.setFontSize(18 - (level * 2));
238                    doc.setFont(undefined, 'bold');
239                    yPosition += 5;
240                } else {
241                    doc.setFontSize(11);
242                    doc.setFont(undefined, 'normal');
243                }
244                
245                // Split text to fit width
246                const lines = doc.splitTextToSize(item.text, maxWidth);
247                
248                // Check if lines fit on current page
249                const lineHeight = item.type.startsWith('h') ? 7 : 6;
250                const blockHeight = lines.length * lineHeight;
251                
252                if (yPosition + blockHeight > pageHeight - margin) {
253                    doc.addPage();
254                    yPosition = margin;
255                }
256                
257                // Add text
258                doc.text(lines, margin, yPosition);
259                yPosition += blockHeight + (item.type.startsWith('h') ? 5 : 3);
260            }
261            
262            // Save the PDF
263            const fileName = `${pageData.title.replace(/[^a-z0-9]/gi, '_')}_${Date.now()}.pdf`;
264            doc.save(fileName);
265            
266            console.log('PDF generated successfully:', fileName);
267            
268        } catch (error) {
269            console.error('Error generating PDF:', error);
270            alert('Error generating PDF: ' + error.message);
271        } finally {
272            button.classList.remove('processing');
273            button.innerHTML = '📄 Download as PDF';
274        }
275    }
276
277    function init() {
278        console.log('Initializing PDF extractor...');
279        
280        // Wait for page to be fully loaded
281        if (document.readyState === 'loading') {
282            document.addEventListener('DOMContentLoaded', init);
283            return;
284        }
285        
286        // Create download button
287        const button = document.createElement('button');
288        button.id = 'ecc-pdf-button';
289        button.innerHTML = '📄 Download as PDF';
290        button.addEventListener('click', generatePDF);
291        
292        document.body.appendChild(button);
293        console.log('PDF download button added');
294    }
295
296    // Start the extension
297    init();
298})();
Enterprise Command Center PDF Extractor | Robomonkey