@@ -247,6 +247,19 @@ class X2TConverter {
247247
248248 const result = this . x2tModule . ccall ( 'main1' , 'number' , [ 'string' ] , [ paramsPath ] ) ;
249249 if ( result !== 0 ) {
250+ // Read the params XML for debugging
251+ try {
252+ const paramsContent = this . x2tModule . FS . readFile ( paramsPath , { encoding : 'binary' } ) ;
253+ // Convert binary to string for logging
254+ if ( paramsContent instanceof Uint8Array ) {
255+ const paramsText = new TextDecoder ( 'utf-8' ) . decode ( paramsContent ) ;
256+ console . error ( 'Conversion failed. Parameters XML:' , paramsText ) ;
257+ } else {
258+ console . error ( 'Conversion failed. Parameters XML:' , paramsContent ) ;
259+ }
260+ } catch ( _e ) {
261+ // Ignore if we can't read the params file
262+ }
250263 throw new Error ( `Conversion failed with code: ${ result } ` ) ;
251264 }
252265 }
@@ -298,6 +311,73 @@ class X2TConverter {
298311 return media ;
299312 }
300313
314+ /**
315+ * Load xlsx library dynamically from CDN
316+ */
317+ private async loadXlsxLibrary ( ) : Promise < any > {
318+ // Check if xlsx is already loaded
319+ if ( typeof window !== 'undefined' && ( window as any ) . XLSX ) {
320+ return ( window as any ) . XLSX ;
321+ }
322+
323+ return new Promise ( ( resolve , reject ) => {
324+ const script = document . createElement ( 'script' ) ;
325+ script . src = 'https://cdn.sheetjs.com/xlsx-0.20.1/package/dist/xlsx.full.min.js' ;
326+ script . onload = ( ) => {
327+ if ( typeof window !== 'undefined' && ( window as any ) . XLSX ) {
328+ resolve ( ( window as any ) . XLSX ) ;
329+ } else {
330+ reject ( new Error ( 'Failed to load xlsx library' ) ) ;
331+ }
332+ } ;
333+ script . onerror = ( ) => {
334+ reject ( new Error ( 'Failed to load xlsx library from CDN' ) ) ;
335+ } ;
336+ document . head . appendChild ( script ) ;
337+ } ) ;
338+ }
339+
340+ /**
341+ * Convert CSV to XLSX format using SheetJS library
342+ * This is a workaround since x2t may not support CSV directly
343+ */
344+ private async convertCsvToXlsx ( csvData : Uint8Array , fileName : string ) : Promise < File > {
345+ try {
346+ // Load xlsx library
347+ const XLSX = await this . loadXlsxLibrary ( ) ;
348+
349+ // Remove UTF-8 BOM if present
350+ let csvText : string ;
351+ if ( csvData . length >= 3 && csvData [ 0 ] === 0xEF && csvData [ 1 ] === 0xBB && csvData [ 2 ] === 0xBF ) {
352+ csvText = new TextDecoder ( 'utf-8' ) . decode ( csvData . slice ( 3 ) ) ;
353+ } else {
354+ // Try UTF-8 first, fallback to other encodings if needed
355+ try {
356+ csvText = new TextDecoder ( 'utf-8' ) . decode ( csvData ) ;
357+ } catch {
358+ csvText = new TextDecoder ( 'latin1' ) . decode ( csvData ) ;
359+ }
360+ }
361+
362+ // Parse CSV using SheetJS
363+ const workbook = XLSX . read ( csvText , { type : 'string' , raw : false } ) ;
364+
365+ // Convert to XLSX binary format
366+ const xlsxBuffer = XLSX . write ( workbook , { type : 'array' , bookType : 'xlsx' } ) ;
367+
368+ // Create File object
369+ const xlsxFileName = fileName . replace ( / \. c s v $ / i, '.xlsx' ) ;
370+ return new File ( [ xlsxBuffer ] , xlsxFileName , {
371+ type : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ,
372+ } ) ;
373+ } catch ( error ) {
374+ throw new Error (
375+ `Failed to convert CSV to XLSX: ${ error instanceof Error ? error . message : 'Unknown error' } . ` +
376+ 'Please convert your CSV file to XLSX format manually and try again.'
377+ ) ;
378+ }
379+ }
380+
301381 /**
302382 * Convert document to bin format
303383 */
@@ -313,16 +393,67 @@ class X2TConverter {
313393 const arrayBuffer = await file . arrayBuffer ( ) ;
314394 const data = new Uint8Array ( arrayBuffer ) ;
315395
316- // Generate safe file name
396+ // Handle CSV files - x2t may not support them directly, so convert to XLSX first
397+ if ( fileExt . toLowerCase ( ) === 'csv' ) {
398+ if ( data . length === 0 ) {
399+ throw new Error ( 'CSV file is empty' ) ;
400+ }
401+ console . log ( 'CSV file detected. Converting to XLSX format...' ) ;
402+ console . log ( 'CSV file size:' , data . length , 'bytes' ) ;
403+
404+ // Convert CSV to XLSX first
405+ try {
406+ const xlsxFile = await this . convertCsvToXlsx ( data , fileName ) ;
407+ console . log ( 'CSV converted to XLSX, now converting with x2t...' ) ;
408+
409+ // Now convert the XLSX file using x2t
410+ const xlsxArrayBuffer = await xlsxFile . arrayBuffer ( ) ;
411+ const xlsxData = new Uint8Array ( xlsxArrayBuffer ) ;
412+
413+ // Use the XLSX file for conversion
414+ const sanitizedName = this . sanitizeFileName ( xlsxFile . name ) ;
415+ const inputPath = `/working/${ sanitizedName } ` ;
416+ const outputPath = `${ inputPath } .bin` ;
417+
418+ // Write XLSX file to virtual file system
419+ this . x2tModule ! . FS . writeFile ( inputPath , xlsxData ) ;
420+
421+ // Create conversion parameters - no special params needed for XLSX
422+ const params = this . createConversionParams ( inputPath , outputPath , '' ) ;
423+ this . x2tModule ! . FS . writeFile ( '/working/params.xml' , params ) ;
424+
425+ // Execute conversion
426+ this . executeConversion ( '/working/params.xml' ) ;
427+
428+ // Read conversion result
429+ const result = this . x2tModule ! . FS . readFile ( outputPath ) ;
430+ const media = this . readMediaFiles ( ) ;
431+
432+ return {
433+ fileName : sanitizedName ,
434+ type : documentType ,
435+ bin : result ,
436+ media,
437+ } ;
438+ } catch ( conversionError : any ) {
439+ // If conversion fails, provide helpful error message
440+ throw new Error (
441+ `Failed to convert CSV file: ${ conversionError ?. message || 'Unknown error' } . ` +
442+ 'Please ensure your CSV file is properly formatted and try again.'
443+ ) ;
444+ }
445+ }
446+
447+ // For all other file types, use standard conversion
317448 const sanitizedName = this . sanitizeFileName ( fileName ) ;
318449 const inputPath = `/working/${ sanitizedName } ` ;
319450 const outputPath = `${ inputPath } .bin` ;
320451
321452 // Write file to virtual file system
322453 this . x2tModule ! . FS . writeFile ( inputPath , data ) ;
323454
324- // Create conversion parameters
325- const params = this . createConversionParams ( inputPath , outputPath ) ;
455+ // Create conversion parameters - no special params needed for non-CSV files
456+ const params = this . createConversionParams ( inputPath , outputPath , '' ) ;
326457 this . x2tModule ! . FS . writeFile ( '/working/params.xml' , params ) ;
327458
328459 // Execute conversion
@@ -343,6 +474,52 @@ class X2TConverter {
343474 }
344475 }
345476
477+ /**
478+ * Attempt to convert CSV directly using x2t (may fail)
479+ */
480+ private async convertCsvDirectly (
481+ _file : File ,
482+ data : Uint8Array ,
483+ fileName : string ,
484+ documentType : DocumentType ,
485+ ) : Promise < ConversionResult > {
486+ // Handle UTF-8 BOM
487+ let fileData = data ;
488+ const hasBOM = data . length >= 3 && data [ 0 ] === 0xEF && data [ 1 ] === 0xBB && data [ 2 ] === 0xBF ;
489+ if ( ! hasBOM ) {
490+ const bom = new Uint8Array ( [ 0xEF , 0xBB , 0xBF ] ) ;
491+ fileData = new Uint8Array ( bom . length + data . length ) ;
492+ fileData . set ( bom , 0 ) ;
493+ fileData . set ( data , bom . length ) ;
494+ }
495+
496+ const sanitizedName = this . sanitizeFileName ( fileName ) ;
497+ const inputPath = `/working/${ sanitizedName } ` ;
498+ const outputPath = `${ inputPath } .bin` ;
499+
500+ // Write file to virtual file system
501+ this . x2tModule ! . FS . writeFile ( inputPath , fileData ) ;
502+
503+ // Try with format specification
504+ const additionalParams = '<m_nFormatFrom>260</m_nFormatFrom>' ;
505+ const params = this . createConversionParams ( inputPath , outputPath , additionalParams ) ;
506+ this . x2tModule ! . FS . writeFile ( '/working/params.xml' , params ) ;
507+
508+ // Execute conversion - this will likely fail with error 89
509+ this . executeConversion ( '/working/params.xml' ) ;
510+
511+ // If we get here, conversion succeeded (unlikely for CSV)
512+ const result = this . x2tModule ! . FS . readFile ( outputPath ) ;
513+ const media = this . readMediaFiles ( ) ;
514+
515+ return {
516+ fileName : sanitizedName ,
517+ type : documentType ,
518+ bin : result ,
519+ media,
520+ } ;
521+ }
522+
346523 /**
347524 * Convert bin format to specified format and download
348525 */
0 commit comments