From c09f3e9cda1ff230c5248fca5fbdc60b1c466f04 Mon Sep 17 00:00:00 2001 From: ZechyW Date: Tue, 11 Aug 2020 17:23:36 +0800 Subject: [PATCH] Use `wcswidth` instead of `len` to measure cell text width - Fixes problems with cell alignment for CJK text within RST tables --- dashtable/dashutils/center_line.py | 6 ++++-- dashtable/dashutils/get_longest_line_length.py | 7 +++++-- dashtable/data2md/get_column_width.py | 5 ++++- dashtable/data2rst/cell/center_cell_text.py | 7 +++++-- .../data2rst/cell/get_longest_line_length.py | 7 +++++-- dashtable/data2rst/cell/v_center_cell_text.py | 4 +++- dashtable/data2rst/make_cell.py | 4 +++- .../restructify/converters/convert_h1.py | 5 ++++- .../restructify/converters/convert_h2.py | 5 ++++- .../restructify/converters/convert_h3.py | 5 ++++- .../restructify/converters/convert_li.py | 5 ++++- setup.py | 1 + tests/static/cjk.html | 18 ++++++++++++++++++ tests/static/cjk.md | 4 ++++ tests/static/cjk.rst | 7 +++++++ 15 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 tests/static/cjk.html create mode 100644 tests/static/cjk.md create mode 100644 tests/static/cjk.rst diff --git a/dashtable/dashutils/center_line.py b/dashtable/dashutils/center_line.py index 7a1bad2..8e35e25 100755 --- a/dashtable/dashutils/center_line.py +++ b/dashtable/dashutils/center_line.py @@ -1,5 +1,7 @@ import math +from wcwidth import wcswidth + def center_line(space, line): """ @@ -21,8 +23,8 @@ def center_line(space, line): """ line = line.strip() - left_length = math.floor((space - len(line)) / 2) - right_length = math.ceil((space - len(line)) / 2) + left_length = math.floor((space - wcswidth(line)) / 2) + right_length = math.ceil((space - wcswidth(line)) / 2) left_space = " " * int(left_length) right_space = " " * int(right_length) diff --git a/dashtable/dashutils/get_longest_line_length.py b/dashtable/dashutils/get_longest_line_length.py index 52dd3ec..16a16d9 100755 --- a/dashtable/dashutils/get_longest_line_length.py +++ b/dashtable/dashutils/get_longest_line_length.py @@ -1,10 +1,13 @@ +from wcwidth import wcswidth + + def get_longest_line_length(text): """Get the length longest line in a paragraph""" lines = text.split("\n") length = 0 for i in range(len(lines)): - if len(lines[i]) > length: - length = len(lines[i]) + if wcswidth(lines[i]) > length: + length = wcswidth(lines[i]) return length diff --git a/dashtable/data2md/get_column_width.py b/dashtable/data2md/get_column_width.py index e150360..10678ca 100755 --- a/dashtable/data2md/get_column_width.py +++ b/dashtable/data2md/get_column_width.py @@ -1,3 +1,6 @@ +from wcwidth import wcswidth + + def get_column_width(column, table): """ Get the character width of a column in a table @@ -17,7 +20,7 @@ def get_column_width(column, table): width = 3 for row in range(len(table)): - cell_width = len(table[row][column]) + cell_width = wcswidth(table[row][column]) if cell_width > width: width = cell_width diff --git a/dashtable/data2rst/cell/center_cell_text.py b/dashtable/data2rst/cell/center_cell_text.py index 7670f2c..caa947f 100755 --- a/dashtable/data2rst/cell/center_cell_text.py +++ b/dashtable/data2rst/cell/center_cell_text.py @@ -1,4 +1,7 @@ import math + +from wcwidth import wcswidth + from .get_longest_line_length import get_longest_line_length def center_cell_text(cell): @@ -20,7 +23,7 @@ def center_cell_text(cell): cell : dashtable.data2rst.Cell """ lines = cell.text.split('\n') - cell_width = len(lines[0]) - 2 + cell_width = wcswidth(lines[0]) - 2 truncated_lines = [''] for i in range(1, len(lines) - 1): @@ -37,7 +40,7 @@ def center_cell_text(cell): for i in range(len(truncated_lines)): truncated_lines[i] = left_space + truncated_lines[i] - right_width = cell_width - len(truncated_lines[i]) + right_width = cell_width - wcswidth(truncated_lines[i]) truncated_lines[i] += right_width * ' ' for i in range(1, len(lines) - 1): diff --git a/dashtable/data2rst/cell/get_longest_line_length.py b/dashtable/data2rst/cell/get_longest_line_length.py index 52dd3ec..16a16d9 100755 --- a/dashtable/data2rst/cell/get_longest_line_length.py +++ b/dashtable/data2rst/cell/get_longest_line_length.py @@ -1,10 +1,13 @@ +from wcwidth import wcswidth + + def get_longest_line_length(text): """Get the length longest line in a paragraph""" lines = text.split("\n") length = 0 for i in range(len(lines)): - if len(lines[i]) > length: - length = len(lines[i]) + if wcswidth(lines[i]) > length: + length = wcswidth(lines[i]) return length diff --git a/dashtable/data2rst/cell/v_center_cell_text.py b/dashtable/data2rst/cell/v_center_cell_text.py index b0d35e7..67f4932 100755 --- a/dashtable/data2rst/cell/v_center_cell_text.py +++ b/dashtable/data2rst/cell/v_center_cell_text.py @@ -1,5 +1,7 @@ import math +from wcwidth import wcswidth + def v_center_cell_text(cell): """ @@ -24,7 +26,7 @@ def v_center_cell_text(cell): cell : dashtable.data2rst.Cell """ lines = cell.text.split('\n') - cell_width = len(lines[0]) - 2 + cell_width = wcswidth(lines[0]) - 2 truncated_lines = [] for i in range(1, len(lines) - 1): diff --git a/dashtable/data2rst/make_cell.py b/dashtable/data2rst/make_cell.py index c595190..ebcc5b8 100755 --- a/dashtable/data2rst/make_cell.py +++ b/dashtable/data2rst/make_cell.py @@ -1,3 +1,5 @@ +from wcwidth import wcswidth + from ..dashutils import get_span_char_width from ..dashutils import get_span_char_height from ..dashutils import get_span_row_count @@ -35,7 +37,7 @@ def make_cell(table, span, widths, heights, use_headers): lines = text.split("\n") for i in range(len(lines)): - width_difference = width - len(lines[i]) + width_difference = width - wcswidth(lines[i]) lines[i] = ''.join([lines[i], " " * width_difference]) height_difference = height - len(lines) diff --git a/dashtable/html2data/restructify/converters/convert_h1.py b/dashtable/html2data/restructify/converters/convert_h1.py index f780119..a72612c 100755 --- a/dashtable/html2data/restructify/converters/convert_h1.py +++ b/dashtable/html2data/restructify/converters/convert_h1.py @@ -1,7 +1,10 @@ +from wcwidth import wcswidth + + def convert_h1(element, text): """ Add '=' to the bottom of text """ if text: - text = text + '\n' + '=' * len(text) + text = text + '\n' + '=' * wcswidth(text) return text diff --git a/dashtable/html2data/restructify/converters/convert_h2.py b/dashtable/html2data/restructify/converters/convert_h2.py index fbf796d..fdd04d7 100755 --- a/dashtable/html2data/restructify/converters/convert_h2.py +++ b/dashtable/html2data/restructify/converters/convert_h2.py @@ -1,7 +1,10 @@ +from wcwidth import wcswidth + + def convert_h2(element, text): """ Adds '-' to the bottom of the text """ if text: - text = text + '\n' + '-' * len(text) + text = text + '\n' + '-' * wcswidth(text) return text diff --git a/dashtable/html2data/restructify/converters/convert_h3.py b/dashtable/html2data/restructify/converters/convert_h3.py index 2b3e5db..371f4c0 100755 --- a/dashtable/html2data/restructify/converters/convert_h3.py +++ b/dashtable/html2data/restructify/converters/convert_h3.py @@ -1,7 +1,10 @@ +from wcwidth import wcswidth + + def convert_h3(element, text): """ Adds '~' to the bottom of the text """ if text: - text = text + '\n' + '~' * len(text) + '\n' + text = text + '\n' + '~' * wcswidth(text) + '\n' return text diff --git a/dashtable/html2data/restructify/converters/convert_li.py b/dashtable/html2data/restructify/converters/convert_li.py index 758e18e..0dbee30 100755 --- a/dashtable/html2data/restructify/converters/convert_li.py +++ b/dashtable/html2data/restructify/converters/convert_li.py @@ -1,3 +1,6 @@ +from wcwidth import wcswidth + + def get_bullet_depth(element): depth = -1 while element: @@ -21,7 +24,7 @@ def convert_li(element, text): for i in range(len(children)): if parent.index(children[i]) == index: number = str(i + 1) - interspace = (space - len(number)) * ' ' + interspace = (space - wcswidth(number)) * ' ' text = number + '.' + interspace + text depth = get_bullet_depth(element) diff --git a/setup.py b/setup.py index cd1fcdd..2e47e1a 100755 --- a/setup.py +++ b/setup.py @@ -23,4 +23,5 @@ url='https://github.com/doakey3/DashTable', download_url='https://github.com/doakey3/DashTable/tarball/1.4.5', license='MIT', + install_requires=['wcwidth'], ) diff --git a/tests/static/cjk.html b/tests/static/cjk.html new file mode 100644 index 0000000..f042c63 --- /dev/null +++ b/tests/static/cjk.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +
Testing tables with CJK text
This issome textin English.
This text是用中文写的instead.
This issome more textin English.
diff --git a/tests/static/cjk.md b/tests/static/cjk.md new file mode 100644 index 0000000..6263a7d --- /dev/null +++ b/tests/static/cjk.md @@ -0,0 +1,4 @@ +| This is | some text | in English. | +|-----------|----------------|-------------| +| This text | 是用中文写的 | instead. | +| This is | some more text | in English. | \ No newline at end of file diff --git a/tests/static/cjk.rst b/tests/static/cjk.rst new file mode 100644 index 0000000..8cc1f1d --- /dev/null +++ b/tests/static/cjk.rst @@ -0,0 +1,7 @@ ++-----------+----------------+-------------+ +| This is | some text | in English. | ++-----------+----------------+-------------+ +| This text | 是用中文写的 | instead. | ++-----------+----------------+-------------+ +| This is | some more text | in English. | ++-----------+----------------+-------------+ \ No newline at end of file