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