jsreport / jsreport-docx

jsreport recipe rendering word docx
MIT License
10 stars 3 forks source link

Using "{{#if false}}" in headings not always removes the heading from the rendered output #29

Closed pdecat closed 2 years ago

pdecat commented 3 years ago

Sometimes, when using {{#if cond}} tags in paragraphs with a heading style, the heading is not completely removed from the rendered output when the condition is false. This is most visible when heading style is numbered.

Here's an example from the actual template I'm working on:

3.1.5 {{#if false}}THIS SHOULD NEVER SHOW
{{/if}}

The template:

image

The output when the heading is not removed as expected:

image

When it is working, i.e. the empty numbered heading does not show in the output, at the XML level the {{#if false}} tag is not in the same <w:t> tag as the heading's actual text (the selected text in the screenshot above):

    <w:p w14:paraId="5328E42C" w14:textId="77777777" w:rsidR="00BD3E73" w:rsidRDefault="00BD3E73" w:rsidP="00BD3E73">
      <w:pPr>
        <w:pStyle w:val="Titre3"/>
        <w:rPr>
          <w:noProof/>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r w:rsidRPr="00DC2D2E">
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:lastRenderedPageBreak/>
        <w:t xml:space="preserve">{{#if </w:t>
      </w:r>
      <w:r>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>false</w:t>
      </w:r>
      <w:r w:rsidRPr="00DC2D2E">
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>}}</w:t>
      </w:r>
      <w:r>
        <w:rPr>
          <w:noProof/>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>THIS SHOULD NEVER SHOW</w:t>
      </w:r>
    </w:p>
    <w:p w14:paraId="36AAD7E3" w14:textId="1C50F426" w:rsidR="00BD3E73" w:rsidRDefault="00BD3E73" w:rsidP="00EE51CD">
      <w:pPr>
        <w:rPr>
          <w:noProof/>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>{{/if}}</w:t>
      </w:r>
    </w:p>

But when everything is in the heading tag, the empty numbered heading is showing:

    <w:p w14:paraId="711095CE" w14:textId="5C1DC568" w:rsidR="00093A06" w:rsidRDefault="0066354C" w:rsidP="00093A06">
      <w:pPr>
        <w:pStyle w:val="Titre3"/>
        <w:rPr>
          <w:noProof/>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r w:rsidRPr="0066354C">
        <w:rPr>
          <w:noProof/>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:lastRenderedPageBreak/>
        <w:t>{{#if false}}THIS SHOULD NEVER SHOW</w:t>
      </w:r>
    </w:p>
    <w:p w14:paraId="5617FB4D" w14:textId="161D081F" w:rsidR="00093A06" w:rsidRDefault="00093A06" w:rsidP="00944FF9">
      <w:pPr>
        <w:rPr>
          <w:noProof/>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>{{/if}</w:t>
      </w:r>
      <w:r w:rsidR="00664BF7">
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>}</w:t>
      </w:r>
    </w:p>

A work-around is to cut the selected text above then paste it in the same location to split the text across several XML tags.

bjrmatos commented 3 years ago

hi! yes, what you describe is something that I also found in another case, that Word internally represents the XML different from how it looks in real.

in normal circumstances, I would expect your template to always stay with the heading, but with empty text, i.e. just showing the numbered heading but with no text, empty. why? because the {{#if}} is wrapping just the text, or at least that is what MS Word shows, however as you found, internally sometimes Word represents the heading differently and that causes the whole numbered heading to be also removed. so yes, there is an inconsistency here, but only if the intention is to stay with empty numbered headings in the .docx

so what is your intention for your case? do you want to conditionally remove headings completely (which means the whole heading text and the number)? or do you want to conditionally remove just the heading text (which mean that the number will stay with empty text)?

if you want to remove heading completely you can put the {{#if}} one line above, something like this

Captura de pantalla 2021-02-04 a la(s) 3 00 03 p  m
pdecat commented 3 years ago

Hi!

hi! yes, what you describe is something that I also found in another case, that Word internally represents the XML different from how it looks in real.

:+1:

in normal circumstances, I would expect your template to always stay with the heading, but with empty text, i.e. just showing the numbered heading but with no text, empty.

That was what I was expecting too, until I tried to move the {{#if}} in the heading itself.

why? because the {{#if}} is wrapping just the text, or at least that is what MS Word shows,

Well visually, the {{#if}} / {{/if}} pair are also wrapping the paragraph marking character to which the Heading3 style is applied as Word shows:

image

If there is nothing left in the heading text after the condition evaluates to false, I could, perhaps wrongfully, expect the heading to be removed.

however as you found, internally sometimes Word represents the heading differently and that causes the whole numbered heading to be also removed. so yes, there is an inconsistency here, but only if the intention is to stay with empty numbered headings in the .docx

so what is your intention for your case? do you want to conditionally remove headings completely (which means the whole heading text and the number)? or do you want to conditionally remove just the heading text (which mean that the number will stay with empty text)?

The intention is really to conditionally remove headings completely.

if you want to remove heading completely you can put the {{#if}} one line above, something like this

That's what I was doing before, but we found it was really painful to navigate the template to find out which sections were conditional. Especially when conditions apply at different heading levels (i.e. Heading2 > Heading3 > Heading4). With the condition in the heading itself, it feels much easier, e.g.:

image

(nothing really sensitive in here, but redacted the screenshot anyway to avoid leaking too much details about the project I'm working on).

Also, with the conditions in the headings, it is much easier to have the number of closing {{/if}} tags match the number of opening {{#if}} tags.

bjrmatos commented 3 years ago

If there is nothing left in the heading text after the condition evaluates to false, I could, perhaps wrongfully, expect the heading to be removed.

for now, the expected behavior should be that the heading stays with empty text, even if right now we know (because the internal xml is represented different) that in some cases it is not working like that. but the remove the heading if it has empty text was definetly not the intention, and it is just something that happens in the particular case of the xml representation here.

The intention is really to conditionally remove headings completely.

good to know, I was starting to wonder what would be the use case of leaving empty headings, thanks for the confirmation.

That's what I was doing before, but we found it was really painful to navigate the template to find out which sections were conditional. Especially when conditions apply at different heading levels (i.e. Heading2 > Heading3 > Heading4). With the condition in the heading itself, it feels much easier

you are describing something that yes looks useful, however, to come to the conclusion of how to proceed we need to evaluate this more deeply because it works differently from how it was expected to behave. I will leave the issue open and we will come back with a conclusion later.

bjrmatos commented 2 years ago

resolved in https://github.com/jsreport/jsreport/pull/935