Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem when centering images in bullet list with HtmlModule #655

Closed
vdechef opened this issue May 30, 2022 · 8 comments
Closed

Problem when centering images in bullet list with HtmlModule #655

vdechef opened this issue May 30, 2022 · 8 comments

Comments

@vdechef
Copy link

vdechef commented May 30, 2022

Using:

  • docxtemplater 3.29.0
  • docxtemplater-html-module 3.29.3
  • docxtemplater-image-module 3.13.4

I use the suggestion from #611 and it works well : the images included in my html page are rendered centered.

The problem arises when the image is included in a bullet list: the resulting docx file is corrupted and Word cannot open it.

Below is a minimal script to reproduce this behavior. The resulting docx file will display 2 images : one in a bullet list (wrapped in a text line), and one outside of the bullet list (centered). Notice that removing the display: block; line prevents the file to be corrupted, but then no image is centered.

The template contains only {~~html}.
I tried to reproduce this using the demo page, but it seems like stylesheet does not work in this demo for centering image ...

const Docxtemplater = require("docxtemplater")
const HTMLModule = require("docxtemplater-html-module")
const ImageModule = require("docxtemplater-image-module")
const PizZip = require("pizzip")
const fs = require("fs")

function toDocx(data, template) {
        const htmlModule = new HTMLModule({
            styleSheet: `
                img {
                    display: block;
                    margin:auto;
                }
            `,
            img: {
                Module: ImageModule
            }
        })
        const zip = new PizZip(template)
        const doc = new Docxtemplater(zip, {
            modules: [
                htmlModule
            ]
        })

        doc.setData(data)
        doc.render()

        const out = doc.getZip().generate({
            type: "nodebuffer",
            compression: "DEFLATE",
        })
        return out
}

const data = toDocx({
    html: `
        <ul>
            <li>toto</li>
            <li>
                text before
                <img src='data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='/>
                text after
            </li>
            <li>tata</li>
        </ul>
        <img src='data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='/>
    `
}, fs.readFileSync("./html-stylesheet.docx"))

fs.writeFileSync("./test.docx", data)
@edi9999
Copy link
Member

edi9999 commented Jun 3, 2022

Interesting, I see having an "img" inside a "li" tag that has a block property is causing this behavior.

It will work if you use the following styleSheet :

img {
    display: block;
    margin:auto;
}
li img, p img {
    display: inline-block;
}

@edi9999
Copy link
Member

edi9999 commented Jun 3, 2022

Using this stylesheet will work, however, I'm not sure whether to do changes here.

The possible behaviors would be the following :

  1. Use the display:block and follow exactly what the stylesheet says (this is the current behavior, and produces a corrupt document).
  2. Ignore the display:block when inside an li
  3. Throw an error saying : <img> with display block was found inside a <li> tag, which is not allowed"

@vdechef
Copy link
Author

vdechef commented Jun 3, 2022

If display: block inside an <li> corrupts the document, I think you should apply solution 2. You already have some cases in your library where you ignore some formatting directives.

  • Solution 1 produces corrupted document, so it does not seem a valid solution from my perspective
  • Solution 3 will at least warn the user, but it will not be helpfull if he cannot modify the stylesheet or the data (from final user perspective, not library user)

@edi9999
Copy link
Member

edi9999 commented Jun 3, 2022

Helo @vdechef , I totally agree with you, the point of HTML in general is to be permissive and avoid errors as much as possible, and that also is the direction that we should use for the docxtemplater-html-module specifically.

I have just implemented solution 2 and released it in the docxtemplater-html-module version 3.30.2 which I have just released.

@edi9999 edi9999 closed this as completed Jun 3, 2022
@vdechef
Copy link
Author

vdechef commented Jun 5, 2022

Thanks for the fix, but when I try to use docxtemplater-html-module version >3.30.0 I get the following error :

image

No problem with version 3.30.0 though.

@edi9999 edi9999 reopened this Jun 6, 2022
@edi9999
Copy link
Member

edi9999 commented Jun 6, 2022

Hello @vdechef , it has something to do with the update from htmlparser2 version 7.x to htmlparser2 version 8.x

@edi9999
Copy link
Member

edi9999 commented Jun 6, 2022

Since htmlparser2 version 8.x, the package.json defines multiple exports fields :

Webpack will by default use the "module" entry of the package.json :

https://github.com/fb55/htmlparser2/blob/master/package.json#L34

This means that it will load the file from "lib/esm/index.js".

I think that in your webpack configuration, you need to have the appropriate loader to be able to parse the "export" statement (and other ESM specific syntax)

You most probably currently have something like this :

loaders: [{
  test: /\.js$/,
  loader: 'babel',
  exclude: /node_modules/,
  query: {
    presets: ['es2015', 'stage-0']
  }
},

You should rather use include like this :

loaders: [{
  test: /\.js$/,
  loader: 'babel',
  include: [
    /node_modules\/(htmlparser2)/,
    path.join(__dirname, "./app") // assuming that your config and app are in the same folder.
  ],
  query: {
    presets: ['es2015', 'stage-0']
  }
},

I've inspired this answer from here : webpack/webpack#2017

@edi9999 edi9999 closed this as completed Jun 6, 2022
@vdechef
Copy link
Author

vdechef commented Jun 14, 2022

Thanks @edi9999.
In the end I migrated to webpack 5 and everything was OK, without defining custom loader.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants