22 PDFArray ,
33 PDFDict ,
44 PDFDocument ,
5- PDFHexString ,
65 PDFName ,
76 PDFNumber ,
87 PDFString ,
@@ -42,7 +41,7 @@ function escapeHtml(value: unknown): string {
4241 . replace ( / ' / g, "'" ) ;
4342}
4443
45- function escapeHtmlWithBreaks ( value : unknown ) : string {
44+ function _escapeHtmlWithBreaks ( value : unknown ) : string {
4645 return escapeHtml ( value ) . replace ( / \r ? \n / g, "<br />" ) ;
4746}
4847
@@ -342,8 +341,9 @@ export async function generateInvoicePDF(
342341 `${ profile . name } export embedded by Invio` ,
343342 opts ?. locale || invoiceData . locale || inlined ?. locale || "en-US" ,
344343 ) ;
345- } catch ( _e ) {
346- // Silently ignore embedding failures to avoid breaking download
344+ } catch ( error ) {
345+ console . warn ( "Failed to embed XML attachment:" , error ) ;
346+ // Continue without attachment to avoid breaking download
347347 }
348348 }
349349 return pdfBytes as Uint8Array ;
@@ -514,13 +514,6 @@ async function convertPdfToPdfA3(pdfBytes: Uint8Array): Promise<Uint8Array | nul
514514 }
515515}
516516
517- function toHexUpper ( bytes : Uint8Array ) : string {
518- return Array . from ( bytes )
519- . map ( ( b ) => b . toString ( 16 ) . padStart ( 2 , "0" ) )
520- . join ( "" )
521- . toUpperCase ( ) ;
522- }
523-
524517async function embedXmlAttachment (
525518 pdfBytes : Uint8Array ,
526519 xmlBytes : Uint8Array ,
@@ -532,23 +525,19 @@ async function embedXmlAttachment(
532525 const pdfDoc = await PDFDocument . load ( pdfBytes , { updateMetadata : false } ) ;
533526 const context = pdfDoc . context ;
534527 const now = new Date ( ) ;
535- const xmlBuffer = xmlBytes . buffer . slice (
536- xmlBytes . byteOffset ,
537- xmlBytes . byteOffset + xmlBytes . byteLength ,
538- ) ;
539- const checksumBuffer = await crypto . subtle . digest ( "MD5" , xmlBuffer as ArrayBuffer ) ;
540- const checksum = toHexUpper ( new Uint8Array ( checksumBuffer ) ) ;
541-
542528 const paramsDict = context . obj ( {
543529 Size : PDFNumber . of ( xmlBytes . length ) ,
544- CheckSum : PDFHexString . of ( checksum ) ,
545530 CreationDate : PDFString . fromDate ( now ) ,
546531 ModDate : PDFString . fromDate ( now ) ,
547532 } ) ;
548533
534+ const subtypeName = mediaType . includes ( "/" )
535+ ? mediaType . replace ( "/" , "#2F" )
536+ : mediaType ;
537+
549538 const embeddedFileStream = context . stream ( xmlBytes , {
550539 Type : PDFName . of ( "EmbeddedFile" ) ,
551- Subtype : PDFName . of ( mediaType . replace ( "/" , "#2F" ) ) ,
540+ Subtype : PDFName . of ( subtypeName ) ,
552541 Params : paramsDict ,
553542 } ) ;
554543 const embeddedFileRef = context . register ( embeddedFileStream ) ;
@@ -568,34 +557,40 @@ async function embedXmlAttachment(
568557 } ) ;
569558 const fileSpecRef = context . register ( fileSpecDict ) ;
570559
571- let namesDict = pdfDoc . catalog . lookup ( PDFName . of ( "Names" ) , PDFDict ) ;
572- if ( ! namesDict ) {
573- namesDict = context . obj ( { } ) ;
574- pdfDoc . catalog . set ( PDFName . of ( "Names" ) , namesDict ) ;
560+ let namesDict = pdfDoc . catalog . get ( PDFName . of ( "Names" ) ) ;
561+ if ( ! ( namesDict instanceof PDFDict ) ) {
562+ const created = context . obj ( { } ) ;
563+ pdfDoc . catalog . set ( PDFName . of ( "Names" ) , created ) ;
564+ namesDict = created ;
575565 }
566+ const namesDictObj = namesDict as PDFDict ;
576567
577- let embeddedFilesDict = namesDict . lookup ( PDFName . of ( "EmbeddedFiles" ) , PDFDict ) ;
578- if ( ! embeddedFilesDict ) {
579- embeddedFilesDict = context . obj ( {
580- Names : context . obj ( [ ] ) ,
581- } ) ;
582- namesDict . set ( PDFName . of ( "EmbeddedFiles" ) , embeddedFilesDict ) ;
568+ let embeddedFilesDict = namesDictObj . get ( PDFName . of ( "EmbeddedFiles" ) ) ;
569+ if ( ! ( embeddedFilesDict instanceof PDFDict ) ) {
570+ const created = context . obj ( { } ) ;
571+ namesDictObj . set ( PDFName . of ( "EmbeddedFiles" ) , created ) ;
572+ embeddedFilesDict = created ;
583573 }
574+ const embeddedFilesDictObj = embeddedFilesDict as PDFDict ;
584575
585- let namesArray = embeddedFilesDict . lookup ( PDFName . of ( "Names" ) , PDFArray ) ;
586- if ( ! namesArray ) {
587- namesArray = context . obj ( [ ] ) ;
588- embeddedFilesDict . set ( PDFName . of ( "Names" ) , namesArray ) ;
576+ let namesArray = embeddedFilesDictObj . get ( PDFName . of ( "Names" ) ) ;
577+ if ( ! ( namesArray instanceof PDFArray ) ) {
578+ const created = context . obj ( [ ] ) ;
579+ embeddedFilesDictObj . set ( PDFName . of ( "Names" ) , created ) ;
580+ namesArray = created ;
589581 }
590- namesArray . push ( PDFString . of ( fileName ) ) ;
591- namesArray . push ( fileSpecRef ) ;
592-
593- let afArray = pdfDoc . catalog . lookup ( PDFName . of ( "AF" ) , PDFArray ) ;
594- if ( ! afArray ) {
595- afArray = context . obj ( [ ] ) ;
596- pdfDoc . catalog . set ( PDFName . of ( "AF" ) , afArray ) ;
582+ const namesArrayObj = namesArray as PDFArray ;
583+ namesArrayObj . push ( PDFString . of ( fileName ) ) ;
584+ namesArrayObj . push ( fileSpecRef ) ;
585+
586+ let afArray = pdfDoc . catalog . get ( PDFName . of ( "AF" ) ) ;
587+ if ( ! ( afArray instanceof PDFArray ) ) {
588+ const created = context . obj ( [ ] ) ;
589+ pdfDoc . catalog . set ( PDFName . of ( "AF" ) , created ) ;
590+ afArray = created ;
597591 }
598- afArray . push ( fileSpecRef ) ;
592+ const afArrayObj = afArray as PDFArray ;
593+ afArrayObj . push ( fileSpecRef ) ;
599594
600595 pdfDoc . setSubject ( `Embedded XML: ${ fileName } ` ) ;
601596 pdfDoc . setKeywords ( [ "Invoice" , "Embedded XML" , fileName ] ) ;
0 commit comments