mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-26 14:19:24 +00:00
Integration with new changes - fix problems with icons
This commit is contained in:
parent
9cdeb013e6
commit
5025e06289
@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { icons } = require('@iconify-json/material-symbols');
|
||||
const { getIcons } = require('@iconify/utils');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
@ -89,68 +88,73 @@ function scanForUsedIcons() {
|
||||
return iconArray;
|
||||
}
|
||||
|
||||
// Auto-detect used icons
|
||||
const usedIcons = scanForUsedIcons();
|
||||
// Main async function
|
||||
async function main() {
|
||||
// Auto-detect used icons
|
||||
const usedIcons = scanForUsedIcons();
|
||||
|
||||
// Check if we need to regenerate (compare with existing)
|
||||
const outputPath = path.join(__dirname, '..', 'src', 'assets', 'material-symbols-icons.json');
|
||||
let needsRegeneration = true;
|
||||
// Check if we need to regenerate (compare with existing)
|
||||
const outputPath = path.join(__dirname, '..', 'src', 'assets', 'material-symbols-icons.json');
|
||||
let needsRegeneration = true;
|
||||
|
||||
if (fs.existsSync(outputPath)) {
|
||||
try {
|
||||
const existingSet = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
||||
const existingIcons = Object.keys(existingSet.icons || {}).sort();
|
||||
const currentIcons = [...usedIcons].sort();
|
||||
if (fs.existsSync(outputPath)) {
|
||||
try {
|
||||
const existingSet = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
||||
const existingIcons = Object.keys(existingSet.icons || {}).sort();
|
||||
const currentIcons = [...usedIcons].sort();
|
||||
|
||||
if (JSON.stringify(existingIcons) === JSON.stringify(currentIcons)) {
|
||||
needsRegeneration = false;
|
||||
info(`✅ Icon set already up-to-date (${usedIcons.length} icons, ${Math.round(fs.statSync(outputPath).size / 1024)}KB)`);
|
||||
if (JSON.stringify(existingIcons) === JSON.stringify(currentIcons)) {
|
||||
needsRegeneration = false;
|
||||
info(`✅ Icon set already up-to-date (${usedIcons.length} icons, ${Math.round(fs.statSync(outputPath).size / 1024)}KB)`);
|
||||
}
|
||||
} catch (error) {
|
||||
// If we can't parse existing file, regenerate
|
||||
needsRegeneration = true;
|
||||
}
|
||||
} catch (error) {
|
||||
// If we can't parse existing file, regenerate
|
||||
needsRegeneration = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needsRegeneration) {
|
||||
info('🎉 No regeneration needed!');
|
||||
process.exit(0);
|
||||
}
|
||||
if (!needsRegeneration) {
|
||||
info('🎉 No regeneration needed!');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
info(`🔍 Extracting ${usedIcons.length} icons from Material Symbols...`);
|
||||
info(`🔍 Extracting ${usedIcons.length} icons from Material Symbols...`);
|
||||
|
||||
// Extract only our used icons from the full set
|
||||
const extractedIcons = getIcons(icons, usedIcons);
|
||||
// Dynamic import of ES module
|
||||
const { getIcons } = await import('@iconify/utils');
|
||||
|
||||
if (!extractedIcons) {
|
||||
console.error('❌ Failed to extract icons');
|
||||
process.exit(1);
|
||||
}
|
||||
// Extract only our used icons from the full set
|
||||
const extractedIcons = getIcons(icons, usedIcons);
|
||||
|
||||
// Check for missing icons
|
||||
const extractedIconNames = Object.keys(extractedIcons.icons || {});
|
||||
const missingIcons = usedIcons.filter(icon => !extractedIconNames.includes(icon));
|
||||
if (!extractedIcons) {
|
||||
console.error('❌ Failed to extract icons');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (missingIcons.length > 0) {
|
||||
info(`⚠️ Missing icons (${missingIcons.length}): ${missingIcons.join(', ')}`);
|
||||
info('💡 These icons don\'t exist in Material Symbols. Please use available alternatives.');
|
||||
}
|
||||
// Check for missing icons
|
||||
const extractedIconNames = Object.keys(extractedIcons.icons || {});
|
||||
const missingIcons = usedIcons.filter(icon => !extractedIconNames.includes(icon));
|
||||
|
||||
// Create output directory
|
||||
const outputDir = path.join(__dirname, '..', 'src', 'assets');
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
if (missingIcons.length > 0) {
|
||||
info(`⚠️ Missing icons (${missingIcons.length}): ${missingIcons.join(', ')}`);
|
||||
info('💡 These icons don\'t exist in Material Symbols. Please use available alternatives.');
|
||||
}
|
||||
|
||||
// Write the extracted icon set to a file (outputPath already defined above)
|
||||
fs.writeFileSync(outputPath, JSON.stringify(extractedIcons, null, 2));
|
||||
// Create output directory
|
||||
const outputDir = path.join(__dirname, '..', 'src', 'assets');
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
info(`✅ Successfully extracted ${Object.keys(extractedIcons.icons || {}).length} icons`);
|
||||
info(`📦 Bundle size: ${Math.round(JSON.stringify(extractedIcons).length / 1024)}KB`);
|
||||
info(`💾 Saved to: ${outputPath}`);
|
||||
// Write the extracted icon set to a file (outputPath already defined above)
|
||||
fs.writeFileSync(outputPath, JSON.stringify(extractedIcons, null, 2));
|
||||
|
||||
// Generate TypeScript types
|
||||
const typesContent = `// Auto-generated icon types
|
||||
info(`✅ Successfully extracted ${Object.keys(extractedIcons.icons || {}).length} icons`);
|
||||
info(`📦 Bundle size: ${Math.round(JSON.stringify(extractedIcons).length / 1024)}KB`);
|
||||
info(`💾 Saved to: ${outputPath}`);
|
||||
|
||||
// Generate TypeScript types
|
||||
const typesContent = `// Auto-generated icon types
|
||||
// This file is automatically generated by scripts/generate-icons.js
|
||||
// Do not edit manually - changes will be overwritten
|
||||
|
||||
@ -168,8 +172,15 @@ declare const iconSet: IconSet;
|
||||
export default iconSet;
|
||||
`;
|
||||
|
||||
const typesPath = path.join(outputDir, 'material-symbols-icons.d.ts');
|
||||
fs.writeFileSync(typesPath, typesContent);
|
||||
const typesPath = path.join(outputDir, 'material-symbols-icons.d.ts');
|
||||
fs.writeFileSync(typesPath, typesContent);
|
||||
|
||||
info(`📝 Generated types: ${typesPath}`);
|
||||
info(`🎉 Icon extraction complete!`);
|
||||
info(`📝 Generated types: ${typesPath}`);
|
||||
info(`🎉 Icon extraction complete!`);
|
||||
}
|
||||
|
||||
// Run the main function
|
||||
main().catch(error => {
|
||||
console.error('❌ Script failed:', error);
|
||||
process.exit(1);
|
||||
});
|
@ -327,7 +327,22 @@ const PageEditor = ({
|
||||
return sourceFiles.size > 0 ? sourceFiles : null;
|
||||
}, [activeFileIds, selectors]);
|
||||
|
||||
// Helper function to generate proper filename for exports
|
||||
const getExportFilename = useCallback((): string => {
|
||||
if (activeFileIds.length <= 1) {
|
||||
// Single file - use original name
|
||||
return displayDocument?.name || 'document.pdf';
|
||||
}
|
||||
|
||||
// Multiple files - use first file name with " (merged)" suffix
|
||||
const firstFile = selectors.getFile(activeFileIds[0]);
|
||||
if (firstFile) {
|
||||
const baseName = firstFile.name.replace(/\.pdf$/i, '');
|
||||
return `${baseName} (merged).pdf`;
|
||||
}
|
||||
|
||||
return 'merged-document.pdf';
|
||||
}, [activeFileIds, selectors, displayDocument]);
|
||||
|
||||
const onExportSelected = useCallback(async () => {
|
||||
if (!displayDocument || selectedPageNumbers.length === 0) return;
|
||||
@ -355,17 +370,18 @@ const PageEditor = ({
|
||||
console.log('Exporting selected pages:', selectedPageNumbers, 'with DOM rotations applied');
|
||||
|
||||
const sourceFiles = getSourceFiles();
|
||||
const exportFilename = getExportFilename();
|
||||
const result = sourceFiles
|
||||
? await pdfExportService.exportPDFMultiFile(
|
||||
documentWithDOMState,
|
||||
sourceFiles,
|
||||
selectedPageIds,
|
||||
{ selectedOnly: true, filename: documentWithDOMState.name }
|
||||
{ selectedOnly: true, filename: exportFilename }
|
||||
)
|
||||
: await pdfExportService.exportPDF(
|
||||
documentWithDOMState,
|
||||
selectedPageIds,
|
||||
{ selectedOnly: true, filename: documentWithDOMState.name }
|
||||
{ selectedOnly: true, filename: exportFilename }
|
||||
);
|
||||
|
||||
// Step 4: Download the result
|
||||
@ -376,7 +392,7 @@ const PageEditor = ({
|
||||
console.error('Export failed:', error);
|
||||
setExportLoading(false);
|
||||
}
|
||||
}, [displayDocument, selectedPageNumbers, mergedPdfDocument, splitPositions, getSourceFiles]);
|
||||
}, [displayDocument, selectedPageNumbers, mergedPdfDocument, splitPositions, getSourceFiles, getExportFilename]);
|
||||
|
||||
const onExportAll = useCallback(async () => {
|
||||
if (!displayDocument) return;
|
||||
@ -399,10 +415,11 @@ const PageEditor = ({
|
||||
const filenames: string[] = [];
|
||||
|
||||
const sourceFiles = getSourceFiles();
|
||||
const exportFilename = getExportFilename();
|
||||
for (const doc of processedDocuments) {
|
||||
const result = sourceFiles
|
||||
? await pdfExportService.exportPDFMultiFile(doc, sourceFiles, [], { filename: doc.name })
|
||||
: await pdfExportService.exportPDF(doc, [], { filename: doc.name });
|
||||
? await pdfExportService.exportPDFMultiFile(doc, sourceFiles, [], { filename: exportFilename })
|
||||
: await pdfExportService.exportPDF(doc, [], { filename: exportFilename });
|
||||
blobs.push(result.blob);
|
||||
filenames.push(result.filename);
|
||||
}
|
||||
@ -416,24 +433,25 @@ const PageEditor = ({
|
||||
});
|
||||
|
||||
const zipBlob = await zip.generateAsync({ type: 'blob' });
|
||||
const zipFilename = displayDocument.name.replace(/\.pdf$/i, '.zip');
|
||||
const zipFilename = exportFilename.replace(/\.pdf$/i, '.zip');
|
||||
|
||||
pdfExportService.downloadFile(zipBlob, zipFilename);
|
||||
} else {
|
||||
// Single document - regular export
|
||||
console.log('Exporting as single PDF');
|
||||
const sourceFiles = getSourceFiles();
|
||||
const exportFilename = getExportFilename();
|
||||
const result = sourceFiles
|
||||
? await pdfExportService.exportPDFMultiFile(
|
||||
processedDocuments,
|
||||
sourceFiles,
|
||||
[],
|
||||
{ selectedOnly: false, filename: processedDocuments.name }
|
||||
{ selectedOnly: false, filename: exportFilename }
|
||||
)
|
||||
: await pdfExportService.exportPDF(
|
||||
processedDocuments,
|
||||
[],
|
||||
{ selectedOnly: false, filename: processedDocuments.name }
|
||||
{ selectedOnly: false, filename: exportFilename }
|
||||
);
|
||||
|
||||
pdfExportService.downloadFile(result.blob, result.filename);
|
||||
@ -444,7 +462,7 @@ const PageEditor = ({
|
||||
console.error('Export failed:', error);
|
||||
setExportLoading(false);
|
||||
}
|
||||
}, [displayDocument, mergedPdfDocument, splitPositions, getSourceFiles]);
|
||||
}, [displayDocument, mergedPdfDocument, splitPositions, getSourceFiles, getExportFilename]);
|
||||
|
||||
// Apply DOM changes to document state using dedicated service
|
||||
const applyChanges = useCallback(() => {
|
||||
@ -543,32 +561,6 @@ const PageEditor = ({
|
||||
|
||||
{displayDocument && (
|
||||
<Box ref={gridContainerRef} p={0} style={{ position: 'relative' }}>
|
||||
{/* File name and basic controls */}
|
||||
<Group mb="md" p="md" justify="space-between">
|
||||
<TextInput
|
||||
placeholder="Enter filename"
|
||||
defaultValue={displayDocument.name.replace(/\.pdf$/i, '')}
|
||||
style={{ minWidth: 300 }}
|
||||
/>
|
||||
<Group>
|
||||
<Button
|
||||
variant={selectionMode ? "filled" : "outline"}
|
||||
onClick={() => setSelectionMode(!selectionMode)}
|
||||
>
|
||||
{selectionMode ? "Exit Selection" : "Select Pages"}
|
||||
</Button>
|
||||
{selectionMode && (
|
||||
<>
|
||||
<Button variant="outline" onClick={() => toggleSelectAll(displayDocument?.pages.length || 0)}>
|
||||
{selectedPageNumbers.length === displayDocument.pages.length ? "Deselect All" : "Select All"}
|
||||
</Button>
|
||||
<Text size="sm" c="dimmed">
|
||||
{selectedPageNumbers.length} selected
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
|
||||
{/* Split Lines Overlay */}
|
||||
|
@ -31,7 +31,7 @@ export class PDFExportService {
|
||||
const originalPDFBytes = await pdfDocument.file.arrayBuffer();
|
||||
const sourceDoc = await PDFLibDocument.load(originalPDFBytes);
|
||||
const blob = await this.createSingleDocument(sourceDoc, pagesToExport);
|
||||
const exportFilename = this.generateFilename(filename || pdfDocument.name, selectedOnly);
|
||||
const exportFilename = this.generateFilename(filename || pdfDocument.name, selectedOnly, false);
|
||||
|
||||
return { blob, filename: exportFilename };
|
||||
} catch (error) {
|
||||
@ -62,7 +62,7 @@ export class PDFExportService {
|
||||
}
|
||||
|
||||
const blob = await this.createMultiSourceDocument(sourceFiles, pagesToExport);
|
||||
const exportFilename = this.generateFilename(filename || pdfDocument.name, selectedOnly);
|
||||
const exportFilename = this.generateFilename(filename || pdfDocument.name, selectedOnly, false);
|
||||
|
||||
return { blob, filename: exportFilename };
|
||||
} catch (error) {
|
||||
|
@ -51,6 +51,8 @@ export interface PageEditorFunctions {
|
||||
handleDelete: () => void;
|
||||
handleSplit: () => void;
|
||||
handleSplitAll: () => void;
|
||||
handlePageBreak: () => void;
|
||||
handlePageBreakAll: () => void;
|
||||
onExportSelected: () => void;
|
||||
onExportAll: () => void;
|
||||
exportLoading: boolean;
|
||||
|
Loading…
x
Reference in New Issue
Block a user