@@ -174,13 +174,14 @@ document.addEventListener('DOMContentLoaded', () => {
174174 if ( ! files . length ) return ;
175175 fileInput . value = '' ;
176176
177- const invalidFile = files . find ( file => ! file . name . toLowerCase ( ) . endsWith ( '.epub' ) ) ;
178- if ( invalidFile ) {
177+ // Ignore non-EPUB files unless none are valid.
178+ const epubFiles = files . filter ( file => file . name . toLowerCase ( ) . endsWith ( '.epub' ) ) ;
179+ if ( ! epubFiles . length ) {
179180 showError ( T . onlyEpub ) ;
180181 return ;
181182 }
182183
183- const oversizedFile = files . find ( file => file . size > MAX_FILE_SIZE_MB * 1024 * 1024 ) ;
184+ const oversizedFile = epubFiles . find ( file => file . size > MAX_FILE_SIZE_MB * 1024 * 1024 ) ;
184185 if ( oversizedFile ) {
185186 showError ( getErrorText ( 'tooLarge' ) ) ;
186187 return ;
@@ -190,30 +191,53 @@ document.addEventListener('DOMContentLoaded', () => {
190191 showLoading ( ) ;
191192
192193 try {
193- if ( files . length === 1 ) {
194- const text = await extractEPUBText ( files [ 0 ] ) ;
195- const resultFilename = files [ 0 ] . name . replace ( / \. e p u b $ / i, '.txt' ) ;
194+ if ( epubFiles . length === 1 ) {
195+ const text = await extractEPUBText ( epubFiles [ 0 ] ) ;
196+ const resultFilename = epubFiles [ 0 ] . name . replace ( / \. e p u b $ / i, '.txt' ) ;
196197 prepareTextDownload ( text , resultFilename ) ;
197198 return ;
198199 }
199200
200201 const zip = new JSZip ( ) ;
201202 const usedNames = new Set ( ) ;
202-
203- for ( let i = 0 ; i < files . length ; i ++ ) {
204- const file = files [ i ] ;
203+ let successfulCount = 0 ;
204+ let lastError = null ;
205+ let lastErrorFile = null ;
206+ let lastSuccessText = null ;
207+ let lastSuccessFilename = null ;
208+
209+ for ( let i = 0 ; i < epubFiles . length ; i ++ ) {
210+ const file = epubFiles [ i ] ;
205211 let text ;
206212 try {
207- text = await extractEPUBText ( file , { index : i , total : files . length } ) ;
213+ text = await extractEPUBText ( file , { index : i , total : epubFiles . length } ) ;
208214 } catch ( err ) {
209215 console . error ( err ) ;
210- showError ( T . fileError ( file . name , normalizeError ( err ) ) ) ;
211- return ;
216+ lastError = err ;
217+ lastErrorFile = file ;
218+ continue ;
212219 }
213220 const baseName = file . name . replace ( / \. e p u b $ / i, '.txt' ) ;
214221 const entryName = makeUniqueFilename ( baseName , usedNames ) ;
215222 usedNames . add ( entryName ) ;
216223 zip . file ( entryName , text ) ;
224+ successfulCount += 1 ;
225+ lastSuccessText = text ;
226+ lastSuccessFilename = entryName ;
227+ }
228+
229+ // If everything failed, surface the last error; otherwise return TXT or ZIP.
230+ if ( successfulCount === 0 ) {
231+ const errorMessage = lastErrorFile
232+ ? T . fileError ( lastErrorFile . name , normalizeError ( lastError ) )
233+ : T . genericError ;
234+ showError ( errorMessage ) ;
235+ return ;
236+ }
237+
238+ if ( successfulCount === 1 ) {
239+ prepareTextDownload ( lastSuccessText , lastSuccessFilename ) ;
240+ return ;
217241 }
218242
219243 statusText . textContent = T . packaging ;
0 commit comments