Aymkdn / html-to-pdfmake

This module permits to convert HTML to the PDFMake format
https://aymkdn.github.io/html-to-pdfmake/index.html
MIT License
545 stars 88 forks source link

React native #216

Closed dragospeta closed 2 months ago

dragospeta commented 2 months ago

Hi, i'm using this beautiful library on my frontend app and i want to use it on a react native mobile app too. (Expo 51)

I'm using the same code, i can even try htmlToPdfmake('<div></div>'), but in react native i get: TypeError: Cannot read property 'prototype' of undefined. (it's located at var parser = new this.wndw.DOMParser();).

I suppose DOMParser is also undefined in react native. Is there a workaround to this? I tried to attach some library parsers to window DOMParser without success.

Aymkdn commented 2 months ago

You need to pass DOMParser using the additional parameter as explained here https://github.com/Aymkdn/html-to-pdfmake?tab=readme-ov-file#window

Is it what you did using the library parsers?

Something like htmlToPdfmake(html, {window:{DOMParser:whateverLibraryParser}})

dragospeta commented 2 months ago

Yes, i tried to add different parsers but i get different errors, meaning that those parsers might have a slightly different implementation than default DOMParser. I guess i have to start debugging more and investigate further as soon as i find some free time.

Aymkdn commented 2 months ago

Did you try JSDom as explained in this example?

Sorry, I cannot do more than that… Please, comment it if you find a solution: it could help someone else.

dragospeta commented 2 months ago

The package at "node_modules/jsdom/lib/api.js" attempted to import the Node standard library module "path". It failed because the native React runtime does not include the Node standard library.

Don't worry, i'll see what i can do and return if i find a solution. Thanks for your time!

dragospeta commented 2 months ago

@Aymkdn I managed to make some progress but i'm stuck again and i think i'll opt for another solution.

I tried more parsers, ended up with: import { DOMParser } from "xmldom";

Ex:

const documentPdf = {
      content: [
        htmlToPdfmake(contractHtml, {
          showHidden: true,
          window: {
            DOMParser: () => {
              return {
                parseFromString: (text: string) => ({
                  body: new DOMParser().parseFromString(text).documentElement,
                }),
              };
            },
          },
        }),
      ],
    };
 pdfMake.createPdf(documentPdf).getBase64(async (pdfData) => { console.log(pdfData) }

Also had to comment this line from library temporary because element style is undefined:

   if (!this.showHidden && (element.style.display && element.style.display === 'none') || (element.style.visibility && element.style.visibility === 'hidden')) {
     return;
   }

It created the documentPdf with success but then it freezes at getBase64. (Exception in HostFunction: Malformed calls from JS: field sizes are different.)

It's funny because it works for: <p>test</p> or <div>test</div> but it fails for <div><p>test</p></div>

Update: I discovered that fontSizes were NaN. After replacing them with a random number it worked for this simple example but i have different error for tables.

Update 2 I returned docDef in this.convertHtml instead of return docDef.stack || docDef.text; and it works! It looks like the styling isn't applied right but i'm happy with the progress.

Notes:

I might check later because i gotta go to work :))

c-goettert commented 1 month ago

@dragospeta did you make any progress on this? I am thinking about trying the same path.

dragospeta commented 1 month ago

@c-goettert No, there was too much time to invest... I opted for another solution completely.

When the user requests the document, i generate an encrypted token made by some combinations of data from the document and i return a public url. (with token and document id as params). The user is then redirected from the phone to that web url and the backend checks if he is eligible to see that document. On web all of these pdfmake libraries work fine.

The advantage of this is that the phone build gets smaller and you can centralize your documents in a single codebase. (in my case i had a frontend application in parallel with the mobile application with the same purpose)