Skip to content

Commit b0aceac

Browse files
authored
Merge pull request #129 from thinreports/add-overflow-wrap-option
Add overflow-wrap option
2 parents 069777b + c24bbee commit b0aceac

10 files changed

Lines changed: 355 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## main (Unreleased)
22

3+
* Add overflow-wrap option #129
4+
35
## 0.14.0
46

57
Breaking Changes:

lib/thinreports/basic_report/generator/pdf.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# frozen_string_literal: true
22

33
require 'prawn'
4+
require 'prawn/disable_word_break'
5+
6+
Prawn::DisableWordBreak.config.default = false
47

58
module Thinreports
69
module BasicReport

lib/thinreports/basic_report/generator/pdf/document/graphics/attributes.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ def build_graphic_attributes(style, &block)
2525
# @yieldparam [Hash] attrs
2626
# @return [Hash]
2727
def build_text_attributes(style, &block)
28+
word_wrap = word_wrap(style['word-wrap'])
29+
2830
text_attributes = {
2931
font: font_family(style['font-family']),
3032
size: style['font-size'],
@@ -35,12 +37,32 @@ def build_text_attributes(style, &block)
3537
letter_spacing: letter_spacing(style['letter-spacing']),
3638
line_height: line_height(style['line-height']),
3739
overflow: text_overflow(style['overflow']),
38-
word_wrap: word_wrap(style['word-wrap'])
40+
word_wrap: word_wrap,
41+
# Deprecated: Use overflow_wrap instead of word_wrap
42+
overflow_wrap: overflow_wrap(style['overflow-wrap'], word_wrap)
3943
}
4044
block.call(text_attributes) if block_given?
4145
text_attributes
4246
end
4347

48+
def overflow_wrap(style, computed_word_wrap)
49+
case style || migrate_overflow_wrap_from_word_wrap(computed_word_wrap)
50+
when 'normal', nil then :normal
51+
when 'anywhere' then :anywhere
52+
# Deprecated: This is a temporary value for migrating from word_wrap.
53+
when 'disable-break-word-by-space' then :disable_break_word_by_space
54+
else :normal
55+
end
56+
end
57+
58+
def migrate_overflow_wrap_from_word_wrap(computed_word_wrap)
59+
case computed_word_wrap
60+
when :none then 'disable-break-word-by-space'
61+
when :break_word then 'normal'
62+
else raise ArgumentError, 'Invalid computed word_wrap value'
63+
end
64+
end
65+
4466
# @param [Array<String>] font_names
4567
# @return [String]
4668
def font_family(font_names)

lib/thinreports/basic_report/generator/pdf/document/graphics/text.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Graphics
2323
# @option attrs [Boolean] :single (false)
2424
# @option attrs [:trancate, :shrink_to_fit, :expand] :overflow (:trancate)
2525
# @option attrs [:none, :break_word] :word_wrap (:none)
26+
# @option attrs [:normal, :anywhere, :disable_break_word_by_space] :overflow_wrap (:normal)
2627
def text_box(content, x, y, w, h, attrs = {}, &block)
2728
w, h = s2f(w, h)
2829

@@ -32,8 +33,7 @@ def text_box(content, x, y, w, h, attrs = {}, &block)
3233
overflow: attrs[:overflow]
3334
)
3435

35-
# Do not break by word unless :word_wrap is :break_word
36-
content = text_without_line_wrap(content) if attrs[:word_wrap] == :none
36+
content = replace_space_to_nbsp(content) if attrs[:overflow_wrap] == :disable_break_word_by_space
3737

3838
with_text_styles(attrs) do |built_attrs, font_styles|
3939
if block
@@ -112,6 +112,12 @@ def with_text_styles(attrs, &block)
112112
spacing = attrs.delete(:letter_spacing)
113113
attrs[:character_spacing] = s2f(spacing) if spacing
114114

115+
# Disable line breaking on chars such as spaces and hyphens
116+
attrs[:disable_word_break] = true if attrs.delete(:overflow_wrap) == :anywhere
117+
118+
# Delete unnecessary attributes
119+
attrs.delete(:word_wrap)
120+
115121
# Or... with_font_styles(attrs, fontinfo, &block)
116122
with_font_styles(attrs, fontinfo) do |modified_attrs, styles|
117123
block.call(modified_attrs, styles)
@@ -131,7 +137,7 @@ def text_line_leading(line_height, font)
131137

132138
# @param [String] content
133139
# @return [String]
134-
def text_without_line_wrap(content)
140+
def replace_space_to_nbsp(content)
135141
content.gsub(/ /, Prawn::Text::NBSP)
136142
end
137143

17.5 KB
Binary file not shown.
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
{
2+
"version": "0.12.0",
3+
"items": [
4+
{
5+
"id": "",
6+
"type": "text",
7+
"display": true,
8+
"description": "",
9+
"x": 20,
10+
"y": 20,
11+
"width": 191,
12+
"height": 20,
13+
"style": {
14+
"font-family": [
15+
"Helvetica"
16+
],
17+
"font-size": 18,
18+
"color": "#000000",
19+
"text-align": "left",
20+
"vertical-align": "top",
21+
"line-height": "",
22+
"line-height-ratio": "",
23+
"letter-spacing": "",
24+
"font-style": []
25+
},
26+
"texts": [
27+
"overflow-wrap: normal"
28+
]
29+
},
30+
{
31+
"id": "",
32+
"type": "text",
33+
"display": true,
34+
"description": "",
35+
"x": 20,
36+
"y": 230,
37+
"width": 199.9,
38+
"height": 20,
39+
"style": {
40+
"font-family": [
41+
"Helvetica"
42+
],
43+
"font-size": 18,
44+
"color": "#000000",
45+
"text-align": "left",
46+
"vertical-align": "top",
47+
"line-height": "",
48+
"line-height-ratio": "",
49+
"letter-spacing": "",
50+
"font-style": []
51+
},
52+
"texts": [
53+
"overflow-wrap: anywhere"
54+
]
55+
},
56+
{
57+
"id": "",
58+
"type": "text",
59+
"display": true,
60+
"description": "",
61+
"x": 20,
62+
"y": 445,
63+
"width": 353.8,
64+
"height": 20,
65+
"style": {
66+
"font-family": [
67+
"Helvetica"
68+
],
69+
"font-size": 18,
70+
"color": "#000000",
71+
"text-align": "left",
72+
"vertical-align": "top",
73+
"line-height": "",
74+
"line-height-ratio": "",
75+
"letter-spacing": "",
76+
"font-style": []
77+
},
78+
"texts": [
79+
"overflow-wrap: disable-break-word-by-space"
80+
]
81+
},
82+
{
83+
"id": "normal",
84+
"type": "text-block",
85+
"display": true,
86+
"description": "",
87+
"x": 20,
88+
"y": 49,
89+
"width": 243.6,
90+
"height": 162,
91+
"style": {
92+
"font-family": [
93+
"IPAPGothic"
94+
],
95+
"font-size": 16,
96+
"color": "#000000",
97+
"text-align": "left",
98+
"vertical-align": "top",
99+
"line-height": "",
100+
"line-height-ratio": "",
101+
"letter-spacing": "",
102+
"font-style": [],
103+
"overflow": "truncate",
104+
"word-wrap": "none",
105+
"overflow-wrap": "normal"
106+
},
107+
"reference-id": "",
108+
"value": "",
109+
"multiple-line": true,
110+
"format": {
111+
"base": "",
112+
"type": ""
113+
}
114+
},
115+
{
116+
"id": "anywhere",
117+
"type": "text-block",
118+
"display": true,
119+
"description": "",
120+
"x": 20,
121+
"y": 261,
122+
"width": 243.6,
123+
"height": 162,
124+
"style": {
125+
"font-family": [
126+
"IPAPGothic"
127+
],
128+
"font-size": 16,
129+
"color": "#000000",
130+
"text-align": "left",
131+
"vertical-align": "top",
132+
"line-height": "",
133+
"line-height-ratio": "",
134+
"letter-spacing": "",
135+
"font-style": [],
136+
"overflow": "truncate",
137+
"word-wrap": "none",
138+
"overflow-wrap": "anywhere"
139+
},
140+
"reference-id": "",
141+
"value": "",
142+
"multiple-line": true,
143+
"format": {
144+
"base": "",
145+
"type": ""
146+
}
147+
},
148+
{
149+
"id": "disable_break_word_by_space",
150+
"type": "text-block",
151+
"display": true,
152+
"description": "",
153+
"x": 20,
154+
"y": 481,
155+
"width": 243.6,
156+
"height": 162,
157+
"style": {
158+
"font-family": [
159+
"IPAPGothic"
160+
],
161+
"font-size": 16,
162+
"color": "#000000",
163+
"text-align": "left",
164+
"vertical-align": "top",
165+
"line-height": "",
166+
"line-height-ratio": "",
167+
"letter-spacing": "",
168+
"font-style": [],
169+
"overflow": "truncate",
170+
"word-wrap": "none",
171+
"overflow-wrap": "disable-break-word-by-space"
172+
},
173+
"reference-id": "",
174+
"value": "",
175+
"multiple-line": true,
176+
"format": {
177+
"base": "",
178+
"type": ""
179+
}
180+
},
181+
{
182+
"id": "",
183+
"type": "line",
184+
"display": true,
185+
"description": "",
186+
"style": {
187+
"border-color": "#000000",
188+
"border-width": 1,
189+
"border-style": "solid"
190+
},
191+
"x1": 20,
192+
"y1": 41,
193+
"x2": 263.6,
194+
"y2": 41
195+
},
196+
{
197+
"id": "",
198+
"type": "line",
199+
"display": true,
200+
"description": "",
201+
"style": {
202+
"border-color": "#000000",
203+
"border-width": 1,
204+
"border-style": "solid"
205+
},
206+
"x1": 20,
207+
"y1": 253,
208+
"x2": 263.6,
209+
"y2": 253
210+
},
211+
{
212+
"id": "",
213+
"type": "line",
214+
"display": true,
215+
"description": "",
216+
"style": {
217+
"border-color": "#000000",
218+
"border-width": 1,
219+
"border-style": "solid"
220+
},
221+
"x1": 20,
222+
"y1": 470,
223+
"x2": 263.6,
224+
"y2": 470
225+
}
226+
],
227+
"state": {
228+
"layout-guides": [
229+
{
230+
"type": "x",
231+
"position": 263.6
232+
}
233+
]
234+
},
235+
"title": "",
236+
"report": {
237+
"paper-type": "A4",
238+
"orientation": "portrait",
239+
"margin": [
240+
20,
241+
20,
242+
20,
243+
20
244+
]
245+
}
246+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
class Thinreports::BasicReport::TestTextOverflowWrapFeature < Thinreports::FeatureTest[__dir__]
6+
feature do
7+
report = Thinreports::BasicReport::Report.new layout: template_path
8+
report.start_new_page
9+
10+
text = 'Thinreports is a PDF generation tool ' +
11+
'that provides thinreports-editor and thinreports-generator. ' +
12+
'Thinreports は thinreports-editor と thinreports-generator を提供するPDF 生成ツールです。'
13+
14+
report.page.values(
15+
normal: text,
16+
anywhere: text,
17+
disable_break_word_by_space: text
18+
)
19+
20+
assert_pdf report.generate
21+
end
22+
end

0 commit comments

Comments
 (0)