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

issue with rendering mixed text of RTL and LTR #1349

Open
Khazam opened this issue Aug 18, 2024 · 1 comment
Open

issue with rendering mixed text of RTL and LTR #1349

Khazam opened this issue Aug 18, 2024 · 1 comment

Comments

@Khazam
Copy link

Khazam commented Aug 18, 2024

We appreciate your feedback - to help the team understand your needs please complete the following template to ensure we have the details to help.

Submission Guidelines

  • If you are not using the latest release, please update and see if the issue is resolved before submitting an issue
  • General questions or high-level topics should be posted in Discussions
  • Please browse the online Documentation to see if your question is already addressed there

Issue Category

  • [0] Enhancement
  • [1] Bug
  • [0] Question
  • [0] Documentation gap/issue

Product Versions

  • Please specify what version of the library you are using......: [3.12.0]
  • Please specify what version(s) of PowerPoint you are targeting: [Home and Student 2016 and 365]
  • Please specify what web browser you are using.................: [Chrome]

Desired Behavior

The mixed text containing RTL and LTR words (Arabic and English words in the same paragraph), is not rendered properly.
I ran the following code:

//version 3.12.0
let pptx = new PptxGenJS();

// Simple Slide 
let pptx = new PptxGenJS();
let slide = pptx.addSlide();
let opts_ar = {
  align: 'right',
  fontSize: 12,
  color: '000000',
  rtlMode: true,
  lang: 'AR'
};

let opts_en = {
  align: 'right',
  fontSize: 12,
  color: '000000',
  rtlMode: true,
  lang: 'EN'
};

slide.addText(
  'نص تجريبي\nهذا text تجريبي يخلط نص عربي و english text\nهذا النَّص يحتوي على ثلاثة سطور number of newlines is 3', {
    align: 'right',
    fontSize: 12,
    color: '000000',
    rtlMode: true,
    lang: 'AR',
    x: 0.0,
    y: 1,
    w: 5,
    h: 2,
    fill: 'ffaaaa',
  }

);

slide.addText([{
    text: 'نص تجريبي\nهذا ',
    options: opts_ar
  }, {
    text: 'text',
    options: opts_en
  }, {
    text: ' تجريبي يخلط نص عربي و ',
    options: opts_ar
  },
  {
    text: 'english text',
    options: opts_en
  }, {
    text: '\nهذا النَّص يحتوي على ثلاثة سطور ',
    options: opts_ar
  },
  {
    text: 'number of newlines is',
    options: opts_en
  }, {
    text: ' 3',
    options: opts_ar
  },

], {
  x: 0.0,
  y: 3,
  w: 5,
  h: 2,
  fill: 'aaaaff',
});

pptx.writeFile();

output:
pptxgenjs github issues example

Observed Behavior

in the output box in the top left (the red box), the text "number of lines is 3" should rendered as expected in the right box (the yellow box). but it is not.
in the output box in the bottom left (the blue box), the text was segmented into RTL and LTR parts, and made an array to store the text object of each part, if it is an english text then the lang='EN' else lang='AR'.
The library is adding breaklines before each english segment.
The expected output is shown in the bottom right box (the green box).

Steps to Reproduce

Code is shown above.

@Khazam
Copy link
Author

Khazam commented Aug 25, 2024

Found the issue in:
https://github.com/gitbrent/PptxGenJS/blob/master/dist/pptxgen.es.js
line 6123

/* STEP 3: Modify slideObj.text to array
        CASES:
        addText( 'string' ) // string
        addText( 'line1\n line2' ) // string with lineBreak
        addText( {text:'word1'} ) // TextProps object
        addText( ['barry','allen'] ) // array of strings
        addText( [{text:'word1'}, {text:'word2'}] ) // TextProps object array
        addText( [{text:'line1\n line2'}, {text:'end word'}] ) // TextProps object array with lineBreak
    */

The last case of having new line was not handled properly, there was an underlineing assumption.

 else if (Array.isArray(slideObj.text)) {
        // Handle cases 4,5,6
        // NOTE: use cast as text is TextProps[]|TableCell[] and their `options` dont overlap (they share the same TextBaseProps though)
        tmpTextObjects = slideObj.text.map(function (item) { return ({ text: item.text, options: item.options }); });
    }

I did a work around to solve the issue:
1- segment the input text into RTL and LTR and newline segments.
2- create an object for each segment.
3- make sure all the object have the algin property being the same (the library assumed change in alignment means starting a new paragraph, which will break the text).
4- make sure newline segment does not have "breakLine: true" it must be "breakLine: false".
this way you will dodge the case of having multiple breakLine and unintended breaklines.

  let pptx = new PptxGenJS();
  let slide = pptx.addSlide();
  let opts_ar = {
    align: 'right',
    fontSize: 12,
    color: '000000',
    rtlMode: true,
    breakLine: false,
    lang: 'AR'
  };

  let opts_en = {
    align: 'right',
    fontSize: 12,
    color: '000000',
    rtlMode: true,
    breakLine: false,
    lang: 'EN'
  };

  let opts_new_line = {
    align: 'arbitrary'
  }; 
  
  slide.addText([{
      text: 'نص تجريبي',
      options: opts_ar
    },
    {
      text: '\n',
      options: opts_ar
    },{
      text: 'هذا ',
      options: opts_ar
    },
    {
      text: 'text',
      options: opts_en
    },
    {
      text: ' تجريبي يخلط نص عربي و ',
      options: opts_ar
    },
    {
      text: 'english text',
      options: opts_en
    },
    {
      text: '\n',
      options: opts_ar
    },
    {
      text: ' هذا النَّص يحتوي على ثلاثة سطور ',
      options: opts_ar
    },
    {
      text: 'number of newlines is 3',
      options: opts_en
    },

  ], {
    x: 5,
    y: 3,
    w: 5,
    h: 2,
    fill: 'aaaaff',
  });

  pptx.writeFile();

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

1 participant