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

Line break issue for chinese font (Noto Serif Simplified Chinese) #2917

Open
meinjam opened this issue Oct 28, 2024 · 1 comment
Open

Line break issue for chinese font (Noto Serif Simplified Chinese) #2917

meinjam opened this issue Oct 28, 2024 · 1 comment

Comments

@meinjam
Copy link

meinjam commented Oct 28, 2024

Describe the bug
I’m experiencing an issue with line breaks in Chinese text when using @react-pdf/renderer. While text in other languages (e.g., English, French) automatically wraps within the set container width, Chinese characters are rendered in a single line, even when the text overflows the container width. This issue significantly impacts readability and layout in documents with Chinese text. I am using Noto Serif Simplified Chinese font.

Expected behavior
The Chinese text should wrap in next line when it exceeds the defined container width or page boundary.

Screenshots

react-pdf-code
react-pdf-renderer

Desktop (please complete the following information):

  • OS: Ubuntu, Windows
  • Browser: Chrome, Firefox
  • React-pdf version: v3.4.4
@jonnny013
Copy link

This is my ugly work around for the same issue.

import React from 'react'
import {Text, View, StyleSheet } from '@react-pdf/renderer'
import { pdfStyles } from '../../../styles/mainStyles'

const isChinese = char => {
  const code = char.charCodeAt(0)
  return code >= 0x4e00 && code <= 0x9fff
}

// Helper function to check if a character is punctuation
const isPunctuation = char => {
  return /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/.test(char)
}

// Helper function to split text into words and characters
const splitText = text => {
  if (typeof text !== 'string') {
    console.warn('splitText received non-string input:', text)
    return [String(text)]
  }

  let result = []
  let currentWord = ''

  for (let i = 0; i < text.length; i++) {
    const char = text[i]
    if (isChinese(char)) {
      if (currentWord) {
        result.push(currentWord)
        currentWord = ''
      }
      result.push(char)
    } else if (isPunctuation(char)) {
      if (currentWord) {
        result.push(currentWord)
        currentWord = ''
      }
      // Append punctuation to the previous segment if it exists
      if (result.length > 0 && !isChinese(result[result.length - 1])) {
        result[result.length - 1] += char
      } else {
        result.push(char)
      }
    } else {
      currentWord += char
    }
  }

  if (currentWord) {
    result.push(currentWord)
  }

  return result
}


const styles = StyleSheet.create({
  container: {
    display: 'flex',
    flexDirection: 'row',
    flexWrap: 'wrap',
  },
  text: {
    fontSize: pdfStyles.text.textFontSize,
    width: '100%'
  },
})

const ChineseText = ({ text, padding }) => {
   const segments = splitText(text)
  return (
    <View style={{ ...styles.container, paddingTop: padding ? 10 : undefined }}>
      <Text style={styles.text}>
        {segments.map((segment, index) => (
          <React.Fragment key={index}>{segment}</React.Fragment>
        ))}
      </Text>
    </View>
  )
}

export default ChineseText

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