thinreports 0.12.1 → 0.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +3 -3
- data/.github/workflows/test.yml +28 -36
- data/.gitignore +1 -1
- data/CHANGELOG.md +25 -1
- data/Gemfile +11 -0
- data/README.md +12 -17
- data/Rakefile +17 -11
- data/lib/thinreports/basic_report/core/errors.rb +62 -0
- data/lib/thinreports/basic_report/core/format/base.rb +91 -0
- data/lib/thinreports/basic_report/core/shape/base/interface.rb +42 -0
- data/lib/thinreports/basic_report/core/shape/base/internal.rb +53 -0
- data/lib/thinreports/basic_report/core/shape/basic/block_format.rb +15 -0
- data/lib/thinreports/basic_report/core/shape/basic/block_interface.rb +34 -0
- data/lib/thinreports/basic_report/core/shape/basic/block_internal.rb +36 -0
- data/lib/thinreports/basic_report/core/shape/basic/format.rb +24 -0
- data/lib/thinreports/basic_report/core/shape/basic/interface.rb +87 -0
- data/lib/thinreports/basic_report/core/shape/basic/internal.rb +28 -0
- data/lib/thinreports/{core → basic_report/core}/shape/basic.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/image_block/format.rb +14 -0
- data/lib/thinreports/basic_report/core/shape/image_block/interface.rb +25 -0
- data/lib/thinreports/basic_report/core/shape/image_block/internal.rb +19 -0
- data/lib/thinreports/{core → basic_report/core}/shape/image_block.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/list/format.rb +92 -0
- data/lib/thinreports/basic_report/core/shape/list/manager.rb +231 -0
- data/lib/thinreports/basic_report/core/shape/list/page.rb +112 -0
- data/lib/thinreports/basic_report/core/shape/list/page_state.rb +50 -0
- data/lib/thinreports/basic_report/core/shape/list/section_format.rb +37 -0
- data/lib/thinreports/basic_report/core/shape/list/section_interface.rb +51 -0
- data/lib/thinreports/basic_report/core/shape/list/section_internal.rb +33 -0
- data/lib/thinreports/{core → basic_report/core}/shape/list.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/manager/format.rb +33 -0
- data/lib/thinreports/basic_report/core/shape/manager/internal.rb +109 -0
- data/lib/thinreports/basic_report/core/shape/manager/target.rb +114 -0
- data/lib/thinreports/basic_report/core/shape/page_number/format.rb +32 -0
- data/lib/thinreports/basic_report/core/shape/page_number/interface.rb +31 -0
- data/lib/thinreports/basic_report/core/shape/page_number/internal.rb +57 -0
- data/lib/thinreports/{core → basic_report/core}/shape/page_number.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/stack_view/format.rb +29 -0
- data/lib/thinreports/basic_report/core/shape/stack_view/interface.rb +19 -0
- data/lib/thinreports/basic_report/core/shape/stack_view/internal.rb +24 -0
- data/lib/thinreports/basic_report/core/shape/stack_view/row_format.rb +41 -0
- data/lib/thinreports/{core → basic_report/core}/shape/stack_view.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/style/base.rb +149 -0
- data/lib/thinreports/basic_report/core/shape/style/basic.rb +24 -0
- data/lib/thinreports/basic_report/core/shape/style/graphic.rb +43 -0
- data/lib/thinreports/basic_report/core/shape/style/text.rb +122 -0
- data/lib/thinreports/basic_report/core/shape/text/format.rb +17 -0
- data/lib/thinreports/basic_report/core/shape/text/interface.rb +20 -0
- data/lib/thinreports/basic_report/core/shape/text/internal.rb +24 -0
- data/lib/thinreports/{core → basic_report/core}/shape/text.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/text_block/format.rb +43 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/basic.rb +41 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/datetime.rb +25 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/number.rb +69 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/padding.rb +27 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter.rb +38 -0
- data/lib/thinreports/basic_report/core/shape/text_block/interface.rb +37 -0
- data/lib/thinreports/basic_report/core/shape/text_block/internal.rb +75 -0
- data/lib/thinreports/{core → basic_report/core}/shape/text_block.rb +6 -4
- data/lib/thinreports/basic_report/core/shape.rb +44 -0
- data/lib/thinreports/basic_report/core/utils.rb +47 -0
- data/lib/thinreports/basic_report/generator/pdf/document/draw_shape.rb +108 -0
- data/lib/thinreports/basic_report/generator/pdf/document/draw_template_items.rb +71 -0
- data/lib/thinreports/basic_report/generator/pdf/document/font.rb +90 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/attributes.rb +149 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/basic.rb +137 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/image.rb +99 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/text.rb +180 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics.rb +42 -0
- data/lib/thinreports/basic_report/generator/pdf/document/page.rb +96 -0
- data/lib/thinreports/basic_report/generator/pdf/document/parse_color.rb +51 -0
- data/lib/thinreports/basic_report/generator/pdf/document.rb +132 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/base.rb +50 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/list.rb +65 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/list_section.rb +51 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/page.rb +127 -0
- data/lib/thinreports/basic_report/generator/pdf/prawn_ext/calc_image_dimensions.rb +34 -0
- data/lib/thinreports/basic_report/generator/pdf/prawn_ext/width_of.rb +31 -0
- data/lib/thinreports/basic_report/generator/pdf.rb +66 -0
- data/lib/thinreports/basic_report/layout/base.rb +48 -0
- data/lib/thinreports/basic_report/layout/format.rb +67 -0
- data/lib/thinreports/basic_report/layout/legacy_schema.rb +383 -0
- data/lib/thinreports/basic_report/layout/version.rb +41 -0
- data/lib/thinreports/{layout.rb → basic_report/layout.rb} +6 -4
- data/lib/thinreports/basic_report/report/base.rb +174 -0
- data/lib/thinreports/basic_report/report/internal.rb +107 -0
- data/lib/thinreports/basic_report/report/page.rb +97 -0
- data/lib/thinreports/basic_report/report.rb +26 -0
- data/lib/thinreports/basic_report.rb +15 -0
- data/lib/thinreports/config.rb +1 -1
- data/lib/thinreports/section_report.rb +12 -0
- data/lib/thinreports/version.rb +1 -1
- data/lib/thinreports.rb +2 -13
- data/thinreports.gemspec +3 -7
- metadata +97 -154
- data/gemfiles/prawn-2.2.gemfile +0 -5
- data/gemfiles/prawn-2.3.gemfile +0 -5
- data/gemfiles/prawn-2.4.gemfile +0 -5
- data/lib/thinreports/core/errors.rb +0 -60
- data/lib/thinreports/core/format/base.rb +0 -89
- data/lib/thinreports/core/shape/base/interface.rb +0 -40
- data/lib/thinreports/core/shape/base/internal.rb +0 -51
- data/lib/thinreports/core/shape/basic/block_format.rb +0 -13
- data/lib/thinreports/core/shape/basic/block_interface.rb +0 -32
- data/lib/thinreports/core/shape/basic/block_internal.rb +0 -34
- data/lib/thinreports/core/shape/basic/format.rb +0 -22
- data/lib/thinreports/core/shape/basic/interface.rb +0 -85
- data/lib/thinreports/core/shape/basic/internal.rb +0 -26
- data/lib/thinreports/core/shape/image_block/format.rb +0 -12
- data/lib/thinreports/core/shape/image_block/interface.rb +0 -23
- data/lib/thinreports/core/shape/image_block/internal.rb +0 -17
- data/lib/thinreports/core/shape/list/format.rb +0 -90
- data/lib/thinreports/core/shape/list/manager.rb +0 -229
- data/lib/thinreports/core/shape/list/page.rb +0 -110
- data/lib/thinreports/core/shape/list/page_state.rb +0 -48
- data/lib/thinreports/core/shape/list/section_format.rb +0 -35
- data/lib/thinreports/core/shape/list/section_interface.rb +0 -49
- data/lib/thinreports/core/shape/list/section_internal.rb +0 -31
- data/lib/thinreports/core/shape/manager/format.rb +0 -31
- data/lib/thinreports/core/shape/manager/internal.rb +0 -107
- data/lib/thinreports/core/shape/manager/target.rb +0 -112
- data/lib/thinreports/core/shape/page_number/format.rb +0 -30
- data/lib/thinreports/core/shape/page_number/interface.rb +0 -29
- data/lib/thinreports/core/shape/page_number/internal.rb +0 -55
- data/lib/thinreports/core/shape/stack_view/format.rb +0 -27
- data/lib/thinreports/core/shape/stack_view/interface.rb +0 -17
- data/lib/thinreports/core/shape/stack_view/internal.rb +0 -22
- data/lib/thinreports/core/shape/stack_view/row_format.rb +0 -39
- data/lib/thinreports/core/shape/style/base.rb +0 -146
- data/lib/thinreports/core/shape/style/basic.rb +0 -22
- data/lib/thinreports/core/shape/style/graphic.rb +0 -41
- data/lib/thinreports/core/shape/style/text.rb +0 -120
- data/lib/thinreports/core/shape/text/format.rb +0 -15
- data/lib/thinreports/core/shape/text/interface.rb +0 -18
- data/lib/thinreports/core/shape/text/internal.rb +0 -22
- data/lib/thinreports/core/shape/text_block/format.rb +0 -41
- data/lib/thinreports/core/shape/text_block/formatter/basic.rb +0 -39
- data/lib/thinreports/core/shape/text_block/formatter/datetime.rb +0 -23
- data/lib/thinreports/core/shape/text_block/formatter/number.rb +0 -67
- data/lib/thinreports/core/shape/text_block/formatter/padding.rb +0 -25
- data/lib/thinreports/core/shape/text_block/formatter.rb +0 -34
- data/lib/thinreports/core/shape/text_block/interface.rb +0 -35
- data/lib/thinreports/core/shape/text_block/internal.rb +0 -73
- data/lib/thinreports/core/shape.rb +0 -42
- data/lib/thinreports/core/utils.rb +0 -45
- data/lib/thinreports/generate.rb +0 -11
- data/lib/thinreports/generator/pdf/document/draw_shape.rb +0 -106
- data/lib/thinreports/generator/pdf/document/draw_template_items.rb +0 -69
- data/lib/thinreports/generator/pdf/document/font.rb +0 -88
- data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +0 -147
- data/lib/thinreports/generator/pdf/document/graphics/basic.rb +0 -135
- data/lib/thinreports/generator/pdf/document/graphics/image.rb +0 -98
- data/lib/thinreports/generator/pdf/document/graphics/text.rb +0 -178
- data/lib/thinreports/generator/pdf/document/graphics.rb +0 -40
- data/lib/thinreports/generator/pdf/document/page.rb +0 -94
- data/lib/thinreports/generator/pdf/document/parse_color.rb +0 -49
- data/lib/thinreports/generator/pdf/document.rb +0 -130
- data/lib/thinreports/generator/pdf/drawer/base.rb +0 -48
- data/lib/thinreports/generator/pdf/drawer/list.rb +0 -63
- data/lib/thinreports/generator/pdf/drawer/list_section.rb +0 -49
- data/lib/thinreports/generator/pdf/drawer/page.rb +0 -125
- data/lib/thinreports/generator/pdf/prawn_ext/calc_image_dimensions.rb +0 -32
- data/lib/thinreports/generator/pdf/prawn_ext/width_of.rb +0 -29
- data/lib/thinreports/generator/pdf.rb +0 -63
- data/lib/thinreports/layout/base.rb +0 -46
- data/lib/thinreports/layout/format.rb +0 -65
- data/lib/thinreports/layout/legacy_schema.rb +0 -381
- data/lib/thinreports/layout/version.rb +0 -39
- data/lib/thinreports/report/base.rb +0 -169
- data/lib/thinreports/report/internal.rb +0 -105
- data/lib/thinreports/report/page.rb +0 -95
- data/lib/thinreports/report.rb +0 -24
- /data/lib/thinreports/{core → basic_report/core}/shape/base.rb +0 -0
- /data/lib/thinreports/{core → basic_report/core}/shape/manager.rb +0 -0
- /data/lib/thinreports/{core → basic_report/core}/shape/style.rb +0 -0
- /data/lib/thinreports/{generator → basic_report/generator}/pdf/prawn_ext.rb +0 -0
@@ -0,0 +1,383 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
module Thinreports
|
7
|
+
module BasicReport
|
8
|
+
module Layout
|
9
|
+
class LegacySchema
|
10
|
+
include Utils
|
11
|
+
|
12
|
+
def initialize(legacy_schema)
|
13
|
+
@legacy_schema = legacy_schema
|
14
|
+
@legacy_svg = legacy_schema['svg'].dup
|
15
|
+
@legacy_item_schemas = extract_legacy_item_schemas(legacy_svg)
|
16
|
+
|
17
|
+
@legacy_svg = cleanup_svg(@legacy_svg)
|
18
|
+
end
|
19
|
+
|
20
|
+
def upgrade
|
21
|
+
config = legacy_schema['config']
|
22
|
+
page_config = config['page']
|
23
|
+
|
24
|
+
{
|
25
|
+
'version' => legacy_schema['version'],
|
26
|
+
'title' => legacy_schema['config']['title'],
|
27
|
+
'report' => {
|
28
|
+
'paper-type' => page_config['paper-type'],
|
29
|
+
'width' => page_config['width'].to_f,
|
30
|
+
'height' => page_config['height'].to_f,
|
31
|
+
'orientation' => page_config['orientation'],
|
32
|
+
'margin' => page_config.values_at(
|
33
|
+
'margin-top',
|
34
|
+
'margin-right',
|
35
|
+
'margin-bottom',
|
36
|
+
'margin-left'
|
37
|
+
).map(&:to_f)
|
38
|
+
},
|
39
|
+
'items' => item_schemas
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :legacy_schema, :legacy_svg, :legacy_item_schemas
|
44
|
+
|
45
|
+
def item_schemas
|
46
|
+
svg = REXML::Document.new(legacy_svg)
|
47
|
+
build_item_schemas_from_svg(svg.elements['/svg/g'])
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_item_schemas_from_svg(svg_elements)
|
51
|
+
return [] unless svg_elements
|
52
|
+
|
53
|
+
items = []
|
54
|
+
|
55
|
+
svg_elements.each do |item_element|
|
56
|
+
item_attributes = item_element.attributes
|
57
|
+
|
58
|
+
items <<
|
59
|
+
case item_element.attributes['class']
|
60
|
+
when 's-text' then text_item_schema(item_attributes, extract_texts_from(item_element))
|
61
|
+
when 's-image' then image_item_schema(item_attributes)
|
62
|
+
when 's-rect' then rect_item_schema(item_attributes)
|
63
|
+
when 's-ellipse' then ellipse_item_schema(item_attributes)
|
64
|
+
when 's-line' then line_item_schema(item_attributes)
|
65
|
+
when 's-tblock' then text_block_item_schema(item_attributes)
|
66
|
+
when 's-iblock' then image_block_item_schema(item_attributes)
|
67
|
+
when 's-pageno' then page_number_item_schema(item_attributes)
|
68
|
+
when 's-list' then list_item_schema(item_element)
|
69
|
+
else raise 'Unknown item type'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
items
|
74
|
+
end
|
75
|
+
|
76
|
+
def text_item_schema(attributes, texts)
|
77
|
+
{
|
78
|
+
'id' => attributes['x-id'],
|
79
|
+
'type' => Core::Shape::Text::TYPE_NAME,
|
80
|
+
'x' => attributes['x-left'].to_f,
|
81
|
+
'y' => attributes['x-top'].to_f,
|
82
|
+
'width' => attributes['x-width'].to_f,
|
83
|
+
'height' => attributes['x-height'].to_f,
|
84
|
+
'display' => display(attributes['x-display']),
|
85
|
+
'texts' => texts,
|
86
|
+
'style' => {
|
87
|
+
'font-family' => [attributes['font-family']],
|
88
|
+
'font-size' => attributes['font-size'].to_f,
|
89
|
+
'color' => attributes['fill'],
|
90
|
+
'font-style' => font_style(attributes),
|
91
|
+
'text-align' => text_align(attributes['text-anchor']),
|
92
|
+
'vertical-align' => vertical_align(attributes['x-valign']),
|
93
|
+
'line-height' => line_height(attributes['x-line-height']),
|
94
|
+
'letter-spacing' => letter_spacing(attributes['kerning'])
|
95
|
+
}
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def rect_item_schema(attributes)
|
100
|
+
{
|
101
|
+
'id' => attributes['x-id'],
|
102
|
+
'type' => 'rect',
|
103
|
+
'x' => attributes['x'].to_f,
|
104
|
+
'y' => attributes['y'].to_f,
|
105
|
+
'width' => attributes['width'].to_f,
|
106
|
+
'height' => attributes['height'].to_f,
|
107
|
+
'display' => display(attributes['x-display']),
|
108
|
+
'border-radius' => attributes['rx'].to_i,
|
109
|
+
'style' => {
|
110
|
+
'border-width' => attributes['stroke-width'].to_f,
|
111
|
+
'border-color' => attributes['stroke'],
|
112
|
+
'border-style' => attributes['x-stroke-type'],
|
113
|
+
'fill-color' => attributes['fill']
|
114
|
+
}
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def line_item_schema(attributes)
|
119
|
+
{
|
120
|
+
'id' => attributes['x-id'],
|
121
|
+
'type' => 'line',
|
122
|
+
'x1' => attributes['x1'].to_f,
|
123
|
+
'y1' => attributes['y1'].to_f,
|
124
|
+
'x2' => attributes['x2'].to_f,
|
125
|
+
'y2' => attributes['y2'].to_f,
|
126
|
+
'display' => display(attributes['x-display']),
|
127
|
+
'style' => {
|
128
|
+
'border-width' => attributes['stroke-width'].to_f,
|
129
|
+
'border-color' => attributes['stroke'],
|
130
|
+
'border-style' => attributes['x-stroke-type']
|
131
|
+
}
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
def ellipse_item_schema(attributes)
|
136
|
+
{
|
137
|
+
'id' => attributes['x-id'],
|
138
|
+
'type' => 'ellipse',
|
139
|
+
'cx' => attributes['cx'].to_f,
|
140
|
+
'cy' => attributes['cy'].to_f,
|
141
|
+
'rx' => attributes['rx'].to_f,
|
142
|
+
'ry' => attributes['ry'].to_f,
|
143
|
+
'display' => display(attributes['x-display']),
|
144
|
+
'style' => {
|
145
|
+
'border-width' => attributes['stroke-width'].to_f,
|
146
|
+
'border-color' => attributes['stroke'],
|
147
|
+
'border-style' => attributes['x-stroke-type'],
|
148
|
+
'fill-color' => attributes['fill']
|
149
|
+
}
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
def image_item_schema(attributes)
|
154
|
+
_, image_type, image_data = attributes['xlink:href'].match(%r{^data:(image/[a-z]+?);base64,(.+)}).to_a
|
155
|
+
|
156
|
+
{
|
157
|
+
'id' => attributes['x-id'],
|
158
|
+
'type' => 'image',
|
159
|
+
'x' => attributes['x'].to_f,
|
160
|
+
'y' => attributes['y'].to_f,
|
161
|
+
'width' => attributes['width'].to_f,
|
162
|
+
'height' => attributes['height'].to_f,
|
163
|
+
'display' => display(attributes['x-display']),
|
164
|
+
'data' => {
|
165
|
+
'mime-type' => image_type,
|
166
|
+
'base64' => image_data
|
167
|
+
}
|
168
|
+
}
|
169
|
+
end
|
170
|
+
|
171
|
+
def page_number_item_schema(attributes)
|
172
|
+
{
|
173
|
+
'id' => attributes['x-id'],
|
174
|
+
'type' => Core::Shape::PageNumber::TYPE_NAME,
|
175
|
+
'x' => attributes['x-left'].to_f,
|
176
|
+
'y' => attributes['x-top'].to_f,
|
177
|
+
'width' => attributes['x-width'].to_f,
|
178
|
+
'height' => attributes['x-height'].to_f,
|
179
|
+
'format' => attributes['x-format'],
|
180
|
+
'target' => attributes['x-target'],
|
181
|
+
'display' => display(attributes['x-display']),
|
182
|
+
'style' => {
|
183
|
+
'font-family' => [attributes['font-family']],
|
184
|
+
'font-size' => attributes['font-size'].to_f,
|
185
|
+
'color' => attributes['fill'],
|
186
|
+
'font-style' => font_style(attributes),
|
187
|
+
'text-align' => text_align(attributes['text-anchor']),
|
188
|
+
'overflow' => attributes['x-overflow']
|
189
|
+
}
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
def image_block_item_schema(attributes)
|
194
|
+
{
|
195
|
+
'id' => attributes['x-id'],
|
196
|
+
'type' => Core::Shape::ImageBlock::TYPE_NAME,
|
197
|
+
'x' => attributes['x-left'].to_f,
|
198
|
+
'y' => attributes['x-top'].to_f,
|
199
|
+
'width' => attributes['x-width'].to_f,
|
200
|
+
'height' => attributes['x-height'].to_f,
|
201
|
+
'display' => display(attributes['x-display']),
|
202
|
+
'style' => {
|
203
|
+
'position-x' => attributes['x-position-x'],
|
204
|
+
'position-y' => image_position_y(attributes['x-position-y'])
|
205
|
+
}
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
def text_block_item_schema(attributes)
|
210
|
+
text_format = {
|
211
|
+
'base' => attributes['x-format-base'],
|
212
|
+
'type' => attributes['x-format-type']
|
213
|
+
}
|
214
|
+
case text_format['type']
|
215
|
+
when 'datetime'
|
216
|
+
text_format['datetime'] = {
|
217
|
+
'format' => attributes['x-format-datetime-format']
|
218
|
+
}
|
219
|
+
when 'number'
|
220
|
+
text_format['number'] = {
|
221
|
+
'delimiter' => attributes['x-format-number-delimiter'],
|
222
|
+
'precision' => attributes['x-format-number-precision'].to_i
|
223
|
+
}
|
224
|
+
when 'padding'
|
225
|
+
text_format['padding'] = {
|
226
|
+
'length' => attributes['x-format-padding-length'].to_i,
|
227
|
+
'char' => attributes['x-format-padding-char'],
|
228
|
+
'direction' => attributes['x-format-padding-direction']
|
229
|
+
}
|
230
|
+
end
|
231
|
+
|
232
|
+
{
|
233
|
+
'id' => attributes['x-id'],
|
234
|
+
'type' => Core::Shape::TextBlock::TYPE_NAME,
|
235
|
+
'x' => attributes['x-left'].to_f,
|
236
|
+
'y' => attributes['x-top'].to_f,
|
237
|
+
'width' => attributes['x-width'].to_f,
|
238
|
+
'height' => attributes['x-height'].to_f,
|
239
|
+
'display' => display(attributes['x-display']),
|
240
|
+
'value' => attributes['x-value'],
|
241
|
+
'multiple-line' => attributes['x-multiple'] == 'true',
|
242
|
+
'format' => text_format,
|
243
|
+
'reference-id' => attributes['x-ref-id'],
|
244
|
+
'style' => {
|
245
|
+
'font-family' => [attributes['font-family']],
|
246
|
+
'font-size' => attributes['font-size'].to_f,
|
247
|
+
'color' => attributes['fill'],
|
248
|
+
'font-style' => font_style(attributes),
|
249
|
+
'text-align' => text_align(attributes['text-anchor']),
|
250
|
+
'vertical-align' => vertical_align(attributes['x-valign']),
|
251
|
+
'line-height' => line_height(attributes['x-line-height']),
|
252
|
+
'letter-spacing' => letter_spacing(attributes['kerning']),
|
253
|
+
'overflow' => attributes['x-overflow'],
|
254
|
+
'word-wrap' => attributes['x-word-wrap'] || ''
|
255
|
+
}
|
256
|
+
}
|
257
|
+
end
|
258
|
+
|
259
|
+
def list_item_schema(legacy_element)
|
260
|
+
legacy_schema = legacy_item_schemas[legacy_element.attributes['x-id']]
|
261
|
+
|
262
|
+
header = list_section_schema('header', legacy_element, legacy_schema)
|
263
|
+
detail = list_section_schema('detail', legacy_element, legacy_schema)
|
264
|
+
page_footer = list_section_schema('page-footer', legacy_element, legacy_schema)
|
265
|
+
footer = list_section_schema('footer', legacy_element, legacy_schema)
|
266
|
+
|
267
|
+
schema = {
|
268
|
+
'id' => legacy_schema['id'],
|
269
|
+
'type' => Core::Shape::List::TYPE_NAME,
|
270
|
+
'content-height' => legacy_schema['content-height'].to_f,
|
271
|
+
'auto-page-break' => legacy_schema['page-break'] == 'true',
|
272
|
+
'display' => display(legacy_schema['display']),
|
273
|
+
'header' => header,
|
274
|
+
'detail' => detail,
|
275
|
+
'page-footer' => page_footer,
|
276
|
+
'footer' => footer
|
277
|
+
}
|
278
|
+
|
279
|
+
page_footer['translate']['y'] += detail['height'] if page_footer['enabled']
|
280
|
+
|
281
|
+
if footer['enabled']
|
282
|
+
footer['translate']['y'] += detail['height']
|
283
|
+
footer['translate']['y'] += page_footer['height'] if page_footer['enabled']
|
284
|
+
end
|
285
|
+
schema
|
286
|
+
end
|
287
|
+
|
288
|
+
def list_section_schema(section_name, legacy_list_element, legacy_list_schema)
|
289
|
+
legacy_section_schema = legacy_list_schema[section_name]
|
290
|
+
return {} if legacy_section_schema.empty?
|
291
|
+
|
292
|
+
section_item_elements = legacy_list_element.elements["g[@class='s-list-#{section_name}']"]
|
293
|
+
|
294
|
+
section_schema = {
|
295
|
+
'height' => legacy_section_schema['height'].to_f,
|
296
|
+
'translate' => {
|
297
|
+
'x' => legacy_section_schema['translate']['x'].to_f,
|
298
|
+
'y' => legacy_section_schema['translate']['y'].to_f
|
299
|
+
},
|
300
|
+
'items' => build_item_schemas_from_svg(section_item_elements)
|
301
|
+
}
|
302
|
+
|
303
|
+
unless section_name == 'detail'
|
304
|
+
section_schema['enabled'] = legacy_list_schema["#{section_name}-enabled"] == 'true'
|
305
|
+
end
|
306
|
+
section_schema
|
307
|
+
end
|
308
|
+
|
309
|
+
def extract_texts_from(text_item_element)
|
310
|
+
[].tap do |texts|
|
311
|
+
text_item_element.each_element('text') { |e| texts << e.text }
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def image_position_y(legacy_position_y)
|
316
|
+
case legacy_position_y
|
317
|
+
when 'top' then 'top'
|
318
|
+
when 'center' then 'middle'
|
319
|
+
when 'bottom' then 'bottom'
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def display(legacy_display)
|
324
|
+
legacy_display == 'true'
|
325
|
+
end
|
326
|
+
|
327
|
+
def font_style(attributes)
|
328
|
+
style = []
|
329
|
+
style << 'bold' if attributes['font-weight'] == 'bold'
|
330
|
+
style << 'italic' if attributes['font-style'] == 'italic'
|
331
|
+
style << 'underline' if attributes['text-decoration'].include?('underline')
|
332
|
+
style << 'linethrough' if attributes['text-decoration'].include?('line-through')
|
333
|
+
style
|
334
|
+
end
|
335
|
+
|
336
|
+
def text_align(legacy_text_align)
|
337
|
+
case legacy_text_align
|
338
|
+
when 'start' then 'left'
|
339
|
+
when 'middle' then 'center'
|
340
|
+
when 'end' then 'right'
|
341
|
+
else 'left'
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def vertical_align(legacy_vertical_align)
|
346
|
+
return '' unless legacy_vertical_align
|
347
|
+
|
348
|
+
case legacy_vertical_align
|
349
|
+
when 'top' then 'top'
|
350
|
+
when 'center' then 'middle'
|
351
|
+
when 'bottom' then 'bottom'
|
352
|
+
else 'top'
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def line_height(legacy_line_height)
|
357
|
+
blank_value?(legacy_line_height) ? '' : legacy_line_height.to_f
|
358
|
+
end
|
359
|
+
|
360
|
+
def letter_spacing(legacy_letter_spacing)
|
361
|
+
case legacy_letter_spacing
|
362
|
+
when 'auto', '' then ''
|
363
|
+
else legacy_letter_spacing.to_f
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def extract_legacy_item_schemas(svg)
|
368
|
+
items = {}
|
369
|
+
svg.scan(/<!--SHAPE(.*?)SHAPE-->/) do |(item_schema_json)|
|
370
|
+
item_schema = JSON.parse(item_schema_json)
|
371
|
+
items[item_schema['id']] = item_schema
|
372
|
+
end
|
373
|
+
items
|
374
|
+
end
|
375
|
+
|
376
|
+
def cleanup_svg(svg)
|
377
|
+
cleaned_svg = svg.gsub(/<!--SHAPE.*?SHAPE-->/, '')
|
378
|
+
cleaned_svg.gsub(/<!--LAYOUT(.*?)LAYOUT-->/) { $1 }
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thinreports
|
4
|
+
module BasicReport
|
5
|
+
module Layout
|
6
|
+
class Version
|
7
|
+
COMPATIBLE_RULES = ['>= 0.8.0', '< 1.0.0'].freeze
|
8
|
+
NEW_SCHEMA_FROM = '0.9.0'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def compatible_rules
|
12
|
+
COMPATIBLE_RULES
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(schema_version)
|
17
|
+
@schema_version = normalize_version(schema_version)
|
18
|
+
end
|
19
|
+
|
20
|
+
def compatible?
|
21
|
+
self.class.compatible_rules.all? do |rule|
|
22
|
+
op, ver = rule.split(' ')
|
23
|
+
schema_version.send(op.to_sym, normalize_version(ver))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def legacy?
|
28
|
+
@schema_version < normalize_version(NEW_SCHEMA_FROM)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :schema_version
|
34
|
+
|
35
|
+
def normalize_version(version)
|
36
|
+
Gem::Version.create(version)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thinreports
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module BasicReport
|
5
|
+
module Layout
|
6
|
+
# @see Thinreports::BasicReport::Layout::Base#initialize
|
7
|
+
def self.new(filename, options = {})
|
8
|
+
Base.new(filename, options)
|
9
|
+
end
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thinreports
|
4
|
+
module BasicReport
|
5
|
+
module Report
|
6
|
+
class Base
|
7
|
+
extend Forwardable
|
8
|
+
include Utils
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# @param options (see #initialize)
|
12
|
+
# @option options (see #initialize)
|
13
|
+
# @yield [report]
|
14
|
+
# @yieldparam [Thinreports::BasicReport::Report::Base] report
|
15
|
+
# @return [Thinreports::BasicReport::Report::Base]
|
16
|
+
def create(options = {}, &block)
|
17
|
+
raise ArgumentError, '#create requires a block' unless block_given?
|
18
|
+
|
19
|
+
report = new(options)
|
20
|
+
call_block_in(report, &block)
|
21
|
+
report.finalize
|
22
|
+
|
23
|
+
report
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param layout (see #initialize)
|
27
|
+
# @param filename (see #generate)
|
28
|
+
# @param security (see #generate)
|
29
|
+
# @param title (see #generate)
|
30
|
+
# @param [Hash] report ({}) DEPRECATED. Options for Report.
|
31
|
+
# @param [Hash] generator ({}) DEPRECATED. Options for Generator.
|
32
|
+
# @yield (see .create)
|
33
|
+
# @yieldparam (see .create)
|
34
|
+
# @return [String]
|
35
|
+
def generate(layout: nil, filename: nil, security: nil, title: nil, report: {}, generator: {}, &block)
|
36
|
+
raise ArgumentError, '#generate requires a block' unless block_given?
|
37
|
+
|
38
|
+
if report.any? || generator.any?
|
39
|
+
warn '[DEPRECATION] :report and :generator argument has been deprecated. ' \
|
40
|
+
'Use :layout and :filename, :security argument instead.'
|
41
|
+
end
|
42
|
+
|
43
|
+
layout ||= report[:layout]
|
44
|
+
filename ||= generator[:filename]
|
45
|
+
security ||= generator[:security]
|
46
|
+
|
47
|
+
report = create(layout: layout, &block)
|
48
|
+
report.generate(filename: filename, security: security, title: title)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Thinreports::BasicReport::Report::Internal]
|
53
|
+
attr_reader :internal
|
54
|
+
|
55
|
+
# @return [Integer]
|
56
|
+
attr_reader :start_page_number
|
57
|
+
|
58
|
+
# @return [Thinreports::BasicReport::Report::Page]
|
59
|
+
def_delegator :internal, :page
|
60
|
+
|
61
|
+
# @return [Integer]
|
62
|
+
def_delegator :internal, :page_count
|
63
|
+
|
64
|
+
# @return [Array<Thinreports::BasicReport::Report::Page>]
|
65
|
+
def_delegator :internal, :pages
|
66
|
+
|
67
|
+
# @return [Thinreports::BasicReport::Layout::Base]
|
68
|
+
def_delegator :internal, :default_layout
|
69
|
+
|
70
|
+
# @param [Hash] options
|
71
|
+
# @option options [String, nil] :layout (nil)
|
72
|
+
def initialize(options = {})
|
73
|
+
@internal = Report::Internal.new(self, options)
|
74
|
+
@start_page_number = 1
|
75
|
+
end
|
76
|
+
|
77
|
+
# @yield [page]
|
78
|
+
# @yieldparam [Thinreports::BasicReport::Report::Page] page
|
79
|
+
# @example
|
80
|
+
# report.on_page_create do |page|
|
81
|
+
# page.item(:header_title).value = 'Title'
|
82
|
+
# end
|
83
|
+
def on_page_create(&block)
|
84
|
+
internal.page_create_handler = block
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param [Integer] page_number
|
88
|
+
def start_page_number_from(page_number)
|
89
|
+
@start_page_number = page_number
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param [String] layout filename of layout file
|
93
|
+
# @param [Hash] options
|
94
|
+
# @option options [Boolean] :default (true)
|
95
|
+
# @option options [Symbol] :id (nil)
|
96
|
+
# @example
|
97
|
+
# report.use_layout '/path/to/default_layout.tlf' # Default layout
|
98
|
+
# report.use_layout '/path/to/default_layout.tlf', default: true
|
99
|
+
# report.use_layout '/path/to/other_layout', id: :other_layout
|
100
|
+
def use_layout(layout, options = {})
|
101
|
+
internal.register_layout(layout, options)
|
102
|
+
end
|
103
|
+
|
104
|
+
# @example
|
105
|
+
# page = report.start_new_page
|
106
|
+
#
|
107
|
+
# report.start_new_page do |page|
|
108
|
+
# page.item(:text).value = 'value'
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# report.use_layout 'foo.tlf', default: true
|
112
|
+
# report.use_layout 'bar.tlf', id: :bar
|
113
|
+
#
|
114
|
+
# report.start_new_page # Use 'foo.tlf'
|
115
|
+
# report.start_new_page layout: :bar # Use 'bar.tlf'
|
116
|
+
# report.start_new_page layout: 'boo.tlf' # Use 'boo.tlf'
|
117
|
+
# @param [Hash] options
|
118
|
+
# @option options [String, Symbol] :layout (nil)
|
119
|
+
# @option options [Boolean] :count (true)
|
120
|
+
# @yield [page]
|
121
|
+
# @yieldparam [Thinreports::BasicReport::Report::Page] page
|
122
|
+
# @return [Thinreports::BasicReport::Report::Page]
|
123
|
+
def start_new_page(options = {}, &block)
|
124
|
+
layout = internal.load_layout(options.delete(:layout))
|
125
|
+
|
126
|
+
raise Thinreports::BasicReport::Errors::NoRegisteredLayoutFound unless layout
|
127
|
+
|
128
|
+
page = internal.add_page(Report::Page.new(self, layout, options))
|
129
|
+
call_block_in(page, &block)
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param [Hash] options
|
133
|
+
# @option options [Boolean] :count (true)
|
134
|
+
# @return [Thinreports::BasicReport::Report::BlankPage]
|
135
|
+
def add_blank_page(options = {})
|
136
|
+
internal.add_page(Report::BlankPage.new(options[:count]))
|
137
|
+
end
|
138
|
+
alias blank_page add_blank_page
|
139
|
+
|
140
|
+
# @param [Symbol, nil] id
|
141
|
+
# @return [Thinreports::BasicReport::Layout::Base]
|
142
|
+
def layout(id = nil)
|
143
|
+
if id
|
144
|
+
internal.layout_registry[id] ||
|
145
|
+
raise(Thinreports::BasicReport::Errors::UnknownLayoutId)
|
146
|
+
else
|
147
|
+
internal.default_layout
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# @param [String] filename
|
152
|
+
# @param [Hash] security (see http://prawnpdf.org/api-docs/2.0/Prawn/Document/Security.html#encrypt_document-instance_method)
|
153
|
+
# @param [String] title Value of the title attribute of the PDF document metadata.
|
154
|
+
# if nil, the title of the default layout file is set.
|
155
|
+
# @return [String]
|
156
|
+
# @example Generate PDF data
|
157
|
+
# report.generate # => "%PDF-1.4...."
|
158
|
+
# @example Create a PDF file
|
159
|
+
# report.generate(filename: 'foo.pdf')
|
160
|
+
def generate(filename: nil, security: nil, title: nil)
|
161
|
+
Thinreports::BasicReport::Generator::PDF.new(self, security: security, title: title).generate(filename)
|
162
|
+
end
|
163
|
+
|
164
|
+
# @see Thinreports::BasicReport::Core::Shape::Manager::Target#list
|
165
|
+
def list(id = nil, &block)
|
166
|
+
start_new_page if page.nil? || page.finalized?
|
167
|
+
page.list(id, &block)
|
168
|
+
end
|
169
|
+
|
170
|
+
def_delegators :internal, :finalize, :finalized?
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|