thinreports 0.10.2 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CONTRIBUTING.md +2 -2
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/test.yml +50 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +43 -0
- data/Gemfile +2 -1
- data/{MIT-LICENSE → LICENSE.txt} +2 -0
- data/README.md +70 -56
- data/Rakefile +12 -25
- data/gemfiles/prawn-2.2.gemfile +5 -0
- data/gemfiles/prawn-2.3.gemfile +5 -0
- data/gemfiles/prawn-2.4.gemfile +5 -0
- data/lib/thinreports/core/shape/basic/format.rb +5 -0
- data/lib/thinreports/core/shape/image_block.rb +1 -1
- data/lib/thinreports/core/shape/list.rb +1 -1
- data/lib/thinreports/core/shape/page_number.rb +1 -1
- data/lib/thinreports/core/shape/stack_view/format.rb +27 -0
- data/lib/thinreports/core/shape/stack_view/interface.rb +17 -0
- data/lib/thinreports/core/shape/stack_view/internal.rb +22 -0
- data/lib/thinreports/core/shape/stack_view/row_format.rb +39 -0
- data/lib/thinreports/core/shape/stack_view.rb +17 -0
- data/lib/thinreports/core/shape/style/basic.rb +4 -1
- data/lib/thinreports/core/shape/text.rb +1 -1
- data/lib/thinreports/core/shape/text_block/formatter/number.rb +6 -1
- data/lib/thinreports/core/shape/text_block/internal.rb +0 -2
- data/lib/thinreports/core/shape/text_block.rb +1 -1
- data/lib/thinreports/core/shape.rb +2 -0
- data/lib/thinreports/generate.rb +11 -0
- data/lib/thinreports/generator/pdf/document/draw_shape.rb +31 -10
- data/lib/thinreports/generator/pdf/document/draw_template_items.rb +1 -1
- data/lib/thinreports/generator/pdf/document/graphics/image.rb +19 -1
- data/lib/thinreports/generator/pdf/document/graphics/text.rb +10 -5
- data/lib/thinreports/generator/pdf/document/page.rb +12 -0
- data/lib/thinreports/generator/pdf/prawn_ext/width_of.rb +7 -7
- data/lib/thinreports/layout/base.rb +1 -1
- data/lib/thinreports/layout/legacy_schema.rb +1 -0
- data/lib/thinreports/layout/version.rb +1 -1
- data/lib/thinreports/report/internal.rb +2 -0
- data/lib/thinreports/report.rb +2 -2
- data/lib/thinreports/section_report/build.rb +32 -0
- data/lib/thinreports/section_report/builder/item_builder.rb +49 -0
- data/lib/thinreports/section_report/builder/report_builder.rb +82 -0
- data/lib/thinreports/section_report/builder/report_data.rb +13 -0
- data/lib/thinreports/section_report/builder/stack_view_builder.rb +53 -0
- data/lib/thinreports/section_report/builder/stack_view_data.rb +11 -0
- data/lib/thinreports/section_report/generate.rb +26 -0
- data/lib/thinreports/section_report/pdf/render.rb +23 -0
- data/lib/thinreports/section_report/pdf/renderer/draw_item.rb +68 -0
- data/lib/thinreports/section_report/pdf/renderer/group_renderer.rb +57 -0
- data/lib/thinreports/section_report/pdf/renderer/section_height.rb +100 -0
- data/lib/thinreports/section_report/pdf/renderer/section_renderer.rb +39 -0
- data/lib/thinreports/section_report/pdf/renderer/stack_view_renderer.rb +55 -0
- data/lib/thinreports/section_report/pdf/renderer/stack_view_row_renderer.rb +38 -0
- data/lib/thinreports/section_report/schema/loader.rb +28 -0
- data/lib/thinreports/section_report/schema/parser.rb +52 -0
- data/lib/thinreports/section_report/schema/report.rb +30 -0
- data/lib/thinreports/section_report/schema/section.rb +47 -0
- data/lib/thinreports/version.rb +1 -1
- data/lib/thinreports.rb +5 -0
- data/thinreports.gemspec +11 -10
- metadata +48 -150
- data/.travis.yml +0 -16
- data/examples/character_spacing/character_spacing.rb +0 -8
- data/examples/character_spacing/character_spacing.tlf +0 -293
- data/examples/dynamic_image/dynamic_image.rb +0 -31
- data/examples/dynamic_image/dynamic_image.tlf +0 -661
- data/examples/dynamic_image/img200x100.png +0 -0
- data/examples/dynamic_image/img50x50.png +0 -0
- data/examples/dynamic_style/dynamic_style.rb +0 -150
- data/examples/dynamic_style/dynamic_style.tlf +0 -1835
- data/examples/dynamic_style/dynamic_style_in_list.tlf +0 -344
- data/examples/dynamic_style/image.png +0 -0
- data/examples/eudc/eudc.rb +0 -20
- data/examples/eudc/eudc.tlf +0 -180
- data/examples/eudc/eudc.ttf +0 -0
- data/examples/helper.rb +0 -50
- data/examples/hidden_shapes/hidden_shapes.rb +0 -9
- data/examples/hidden_shapes/hidden_shapes.tlf +0 -449
- data/examples/list_events/list_events.rb +0 -32
- data/examples/list_events/list_events.tlf +0 -361
- data/examples/list_manual_generation/list_manual_generation.rb +0 -22
- data/examples/list_manual_generation/list_manual_generation.tlf +0 -132
- data/examples/list_page_number/list_page_number.rb +0 -17
- data/examples/list_page_number/list_page_number.tlf +0 -254
- data/examples/page_number/page_number.rb +0 -33
- data/examples/page_number/page_number.tlf +0 -215
- data/examples/palleted_png/palleted_png.png +0 -0
- data/examples/palleted_png/palleted_png.rb +0 -9
- data/examples/palleted_png/palleted_png.tlf +0 -47
- data/examples/password_setting/password_setting.rb +0 -10
- data/examples/password_setting/password_setting.tlf +0 -45
- data/examples/report_callbacks/report_callbacks.rb +0 -14
- data/examples/report_callbacks/report_callbacks.tlf +0 -147
- data/examples/single_line_tblock/single_line_tblock.rb +0 -13
- data/examples/single_line_tblock/single_line_tblock.tlf +0 -170
- data/examples/tblock_overflow/tblock_overflow.rb +0 -20
- data/examples/tblock_overflow/tblock_overflow.tlf +0 -538
- data/examples/tblock_styles/font_size.tlf +0 -383
- data/examples/tblock_styles/tblock_styles.rb +0 -43
- data/examples/tblock_styles/tblock_styles.tlf +0 -889
- data/examples/text_align/text_align.rb +0 -8
- data/examples/text_align/text_align.tlf +0 -241
- data/examples/typeB_page_size/B4_ISO.tlf +0 -45
- data/examples/typeB_page_size/B4_JIS.tlf +0 -45
- data/examples/typeB_page_size/typeB_page_size.rb +0 -17
- data/examples/word_wrap/word_wrap.rb +0 -26
- data/examples/word_wrap/word_wrap.tlf +0 -297
- data/test/data/font.ttf +0 -0
- data/test/data/image_normal.jpg +0 -0
- data/test/data/image_normal.png +0 -0
- data/test/data/image_normal_jpg_noext +0 -0
- data/test/data/image_normal_png_noext +0 -0
- data/test/data/image_pallete_based.png +0 -0
- data/test/data/legacy_layout/all-items.tlf +0 -1
- data/test/schema_helper.rb +0 -122
- data/test/test_helper.rb +0 -48
- data/test/tmp/.gitkeep +0 -0
- data/test/unit/core/format/test_base.rb +0 -152
- data/test/unit/core/shape/base/test_internal.rb +0 -87
- data/test/unit/core/shape/basic/test_block_format.rb +0 -23
- data/test/unit/core/shape/basic/test_block_interface.rb +0 -29
- data/test/unit/core/shape/basic/test_block_internal.rb +0 -55
- data/test/unit/core/shape/basic/test_format.rb +0 -37
- data/test/unit/core/shape/basic/test_interface.rb +0 -108
- data/test/unit/core/shape/basic/test_internal.rb +0 -55
- data/test/unit/core/shape/image_block/test_interface.rb +0 -24
- data/test/unit/core/shape/image_block/test_internal.rb +0 -31
- data/test/unit/core/shape/list/test_format.rb +0 -111
- data/test/unit/core/shape/list/test_manager.rb +0 -67
- data/test/unit/core/shape/list/test_page.rb +0 -156
- data/test/unit/core/shape/list/test_page_state.rb +0 -31
- data/test/unit/core/shape/list/test_section_format.rb +0 -36
- data/test/unit/core/shape/list/test_section_interface.rb +0 -75
- data/test/unit/core/shape/list/test_section_internal.rb +0 -50
- data/test/unit/core/shape/manager/test_format.rb +0 -38
- data/test/unit/core/shape/manager/test_internal.rb +0 -132
- data/test/unit/core/shape/manager/test_target.rb +0 -140
- data/test/unit/core/shape/page_number/test_format.rb +0 -55
- data/test/unit/core/shape/page_number/test_interface.rb +0 -33
- data/test/unit/core/shape/page_number/test_internal.rb +0 -81
- data/test/unit/core/shape/styles/test_base.rb +0 -191
- data/test/unit/core/shape/styles/test_basic.rb +0 -24
- data/test/unit/core/shape/styles/test_graphic.rb +0 -50
- data/test/unit/core/shape/styles/test_text.rb +0 -97
- data/test/unit/core/shape/text/test_format.rb +0 -44
- data/test/unit/core/shape/text/test_internal.rb +0 -20
- data/test/unit/core/shape/text_block/formatter/test_basic.rb +0 -24
- data/test/unit/core/shape/text_block/formatter/test_datetime.rb +0 -49
- data/test/unit/core/shape/text_block/formatter/test_number.rb +0 -76
- data/test/unit/core/shape/text_block/formatter/test_padding.rb +0 -77
- data/test/unit/core/shape/text_block/test_format.rb +0 -169
- data/test/unit/core/shape/text_block/test_formatter.rb +0 -28
- data/test/unit/core/shape/text_block/test_interface.rb +0 -63
- data/test/unit/core/shape/text_block/test_internal.rb +0 -128
- data/test/unit/core/test_shape.rb +0 -52
- data/test/unit/core/test_utils.rb +0 -68
- data/test/unit/generator/pdf/document/graphics/test_attributes.rb +0 -135
- data/test/unit/generator/pdf/document/graphics/test_basic.rb +0 -46
- data/test/unit/generator/pdf/document/graphics/test_image.rb +0 -46
- data/test/unit/generator/pdf/document/graphics/test_text.rb +0 -171
- data/test/unit/generator/pdf/document/test_font.rb +0 -110
- data/test/unit/generator/pdf/document/test_graphics.rb +0 -42
- data/test/unit/generator/pdf/document/test_page.rb +0 -122
- data/test/unit/generator/pdf/document/test_parse_color.rb +0 -30
- data/test/unit/generator/pdf/prawn_ext/test_calc_image_dimensions.rb +0 -41
- data/test/unit/generator/pdf/prawn_ext/test_width_of.rb +0 -22
- data/test/unit/generator/pdf/test_document.rb +0 -22
- data/test/unit/generator/test_pdf.rb +0 -26
- data/test/unit/layout/test_base.rb +0 -41
- data/test/unit/layout/test_format.rb +0 -100
- data/test/unit/layout/test_legacy_schema.rb +0 -574
- data/test/unit/layout/test_version.rb +0 -26
- data/test/unit/report/test_base.rb +0 -248
- data/test/unit/report/test_internal.rb +0 -206
- data/test/unit/test_config.rb +0 -36
- data/test/unit/test_layout.rb +0 -12
- data/test/unit/test_report.rb +0 -18
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'section_renderer'
|
4
|
+
|
5
|
+
module Thinreports
|
6
|
+
module SectionReport
|
7
|
+
module Renderer
|
8
|
+
class GroupRenderer
|
9
|
+
def initialize(pdf)
|
10
|
+
@pdf = pdf
|
11
|
+
@section_renderer = Renderer::SectionRenderer.new(pdf)
|
12
|
+
end
|
13
|
+
|
14
|
+
def render(report, group)
|
15
|
+
pdf.start_new_page_for_section_report report.schema
|
16
|
+
current_page_height = 0
|
17
|
+
|
18
|
+
max_page_height = pdf.max_content_height
|
19
|
+
|
20
|
+
group.headers.each do |header|
|
21
|
+
section_renderer.render(header)
|
22
|
+
current_page_height += section_renderer.section_height(header)
|
23
|
+
end
|
24
|
+
|
25
|
+
group.details.each do |detail|
|
26
|
+
if current_page_height + section_renderer.section_height(detail) > max_page_height
|
27
|
+
pdf.start_new_page_for_section_report report.schema
|
28
|
+
current_page_height = 0
|
29
|
+
|
30
|
+
group.headers.each do |header|
|
31
|
+
if header.schema.every_page?
|
32
|
+
section_renderer.render(header)
|
33
|
+
current_page_height += section_renderer.section_height(header)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
section_renderer.render(detail)
|
38
|
+
current_page_height += section_renderer.section_height(detail)
|
39
|
+
end
|
40
|
+
|
41
|
+
group.footers.each do |footer|
|
42
|
+
if current_page_height + section_renderer.section_height(footer) > max_page_height
|
43
|
+
pdf.start_new_page_for_section_report report.schema
|
44
|
+
current_page_height = 0
|
45
|
+
end
|
46
|
+
section_renderer.render(footer)
|
47
|
+
current_page_height += section_renderer.section_height(footer)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
attr_reader :pdf, :section_renderer
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thinreports
|
4
|
+
module SectionReport
|
5
|
+
module Renderer
|
6
|
+
module SectionHeight
|
7
|
+
LayoutInfo = Struct.new(:shape, :content_height, :top_margin, :bottom_margin)
|
8
|
+
|
9
|
+
def section_height(section)
|
10
|
+
return [section.min_height || 0, section.schema.height].max if !section.schema.auto_stretch? || section.items.empty?
|
11
|
+
|
12
|
+
item_layouts = section.items.map { |item| item_layout(section, item.internal) }.compact
|
13
|
+
|
14
|
+
min_bottom_margin = item_layouts.each_with_object([]) do |l, margins|
|
15
|
+
margins << l.bottom_margin if l.shape.format.affect_bottom_margin?
|
16
|
+
end.min.to_f
|
17
|
+
|
18
|
+
max_content_bottom = item_layouts.each_with_object([]) do |l, bottoms|
|
19
|
+
bottoms << l.top_margin + l.content_height if l.shape.format.affect_bottom_margin?
|
20
|
+
end.max.to_f
|
21
|
+
|
22
|
+
[section.min_height || 0, max_content_bottom + min_bottom_margin].max
|
23
|
+
end
|
24
|
+
|
25
|
+
def calc_float_content_bottom(section)
|
26
|
+
item_layouts = section.items.map { |item| item_layout(section, item.internal) }.compact
|
27
|
+
item_layouts
|
28
|
+
.map { |l| l.top_margin + l.content_height }
|
29
|
+
.max.to_f
|
30
|
+
end
|
31
|
+
|
32
|
+
def item_layout(section, shape)
|
33
|
+
if shape.type_of?(Core::Shape::TextBlock::TYPE_NAME)
|
34
|
+
text_layout(section, shape)
|
35
|
+
elsif shape.type_of?(Core::Shape::StackView::TYPE_NAME)
|
36
|
+
stack_view_layout(section, shape)
|
37
|
+
elsif shape.type_of?(Core::Shape::ImageBlock::TYPE_NAME)
|
38
|
+
image_block_layout(section, shape)
|
39
|
+
elsif shape.type_of?('ellipse')
|
40
|
+
cy, ry = shape.format.attributes.values_at('cy', 'ry')
|
41
|
+
static_layout(section, shape, cy - ry, ry * 2)
|
42
|
+
elsif shape.type_of?('line')
|
43
|
+
y1, y2 = shape.format.attributes.values_at('y1', 'y2')
|
44
|
+
static_layout(section, shape, [y1, y2].min, (y2 - y1).abs)
|
45
|
+
else
|
46
|
+
y, height = shape.format.attributes.values_at('y', 'height')
|
47
|
+
raise ArgumentError.new("Unknown layout for #{shape}") if height == nil || y == nil
|
48
|
+
static_layout(section, shape, y, height)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def static_layout(section, shape, y, height)
|
53
|
+
LayoutInfo.new(shape, height, y, section.schema.height - height - y)
|
54
|
+
end
|
55
|
+
|
56
|
+
def image_block_layout(section, shape)
|
57
|
+
y, height = shape.format.attributes.values_at('y', 'height')
|
58
|
+
if shape.style.finalized_styles['position-y'] == 'top'
|
59
|
+
dimensions = pdf.shape_iblock_dimenions(shape)
|
60
|
+
content_height = dimensions ? dimensions[1] : 0
|
61
|
+
|
62
|
+
LayoutInfo.new(shape, content_height, y, section.schema.height - height - y)
|
63
|
+
else
|
64
|
+
static_layout(section, shape, y, height)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def calc_text_block_height(shape)
|
69
|
+
height = 0
|
70
|
+
|
71
|
+
pdf.draw_shape_tblock(shape) do |array, options|
|
72
|
+
modified_options = options.merge(at: [0, 10_000], height: 10_000)
|
73
|
+
height = pdf.pdf.height_of_formatted(array, modified_options)
|
74
|
+
end
|
75
|
+
height
|
76
|
+
end
|
77
|
+
|
78
|
+
def text_layout(section, shape)
|
79
|
+
y, schema_height = shape.format.attributes.values_at('y', 'height')
|
80
|
+
|
81
|
+
content_height = if shape.style.finalized_styles['overflow'] == 'expand'
|
82
|
+
[schema_height, calc_text_block_height(shape)].max
|
83
|
+
else
|
84
|
+
schema_height
|
85
|
+
end
|
86
|
+
|
87
|
+
LayoutInfo.new(shape, content_height, y, section.schema.height - schema_height - y)
|
88
|
+
end
|
89
|
+
|
90
|
+
def stack_view_layout(section, shape)
|
91
|
+
schema_height = 0
|
92
|
+
shape.format.rows.each {|row| schema_height += row.attributes['height']}
|
93
|
+
|
94
|
+
y = shape.format.attributes['y']
|
95
|
+
LayoutInfo.new(shape, stack_view_renderer.section_height(shape), y, section.schema.height - schema_height - y)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'stack_view_renderer'
|
4
|
+
require_relative 'section_height'
|
5
|
+
require_relative 'draw_item'
|
6
|
+
|
7
|
+
module Thinreports
|
8
|
+
module SectionReport
|
9
|
+
module Renderer
|
10
|
+
class SectionRenderer
|
11
|
+
include SectionHeight
|
12
|
+
include DrawItem
|
13
|
+
|
14
|
+
def initialize(pdf)
|
15
|
+
@pdf = pdf
|
16
|
+
end
|
17
|
+
|
18
|
+
def render(section)
|
19
|
+
doc = pdf.pdf
|
20
|
+
|
21
|
+
actual_height = section_height(section)
|
22
|
+
doc.bounding_box([0, doc.cursor], width: doc.bounds.width, height: actual_height) do
|
23
|
+
section.items.each do |item|
|
24
|
+
draw_item(item, (actual_height - section.schema.height))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :pdf
|
32
|
+
|
33
|
+
def stack_view_renderer
|
34
|
+
@stack_view_renderer ||= Renderer::StackViewRenderer.new(pdf)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'stack_view_row_renderer'
|
4
|
+
|
5
|
+
module Thinreports
|
6
|
+
module SectionReport
|
7
|
+
module Renderer
|
8
|
+
class StackViewRenderer
|
9
|
+
def initialize(pdf)
|
10
|
+
@pdf = pdf
|
11
|
+
@row_renderer = Renderer::StackViewRowRenderer.new(pdf)
|
12
|
+
end
|
13
|
+
|
14
|
+
RowLayout = Struct.new(:row, :height, :top)
|
15
|
+
|
16
|
+
def section_height(shape)
|
17
|
+
row_layouts = build_row_layouts(shape.rows)
|
18
|
+
|
19
|
+
total_row_height = row_layouts.sum(0, &:height)
|
20
|
+
float_content_bottom = row_layouts
|
21
|
+
.map { |l| row_renderer.calc_float_content_bottom(l.row) + l.top }
|
22
|
+
.max.to_f
|
23
|
+
|
24
|
+
[total_row_height, float_content_bottom].max
|
25
|
+
end
|
26
|
+
|
27
|
+
def render(shape)
|
28
|
+
doc = pdf.pdf
|
29
|
+
|
30
|
+
x, y, w = shape.format.attributes.values_at('x', 'y', 'width')
|
31
|
+
doc.bounding_box([x, doc.bounds.height - y], width: w, height: section_height(shape)) do
|
32
|
+
shape.rows.each do |row|
|
33
|
+
row_renderer.render(row)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :pdf, :row_renderer
|
41
|
+
|
42
|
+
def build_row_layouts(rows)
|
43
|
+
row_layouts = rows.map { |row| RowLayout.new(row, row_renderer.section_height(row)) }
|
44
|
+
|
45
|
+
row_layouts.inject(0) do |top, row_layout|
|
46
|
+
row_layout.top = top
|
47
|
+
top + row_layout.height
|
48
|
+
end
|
49
|
+
|
50
|
+
row_layouts
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'section_height'
|
4
|
+
require_relative 'draw_item'
|
5
|
+
|
6
|
+
module Thinreports
|
7
|
+
module SectionReport
|
8
|
+
module Renderer
|
9
|
+
class StackViewRowRenderer
|
10
|
+
include SectionHeight
|
11
|
+
include DrawItem
|
12
|
+
|
13
|
+
def initialize(pdf)
|
14
|
+
@pdf = pdf
|
15
|
+
end
|
16
|
+
|
17
|
+
def render(row)
|
18
|
+
doc = pdf.pdf
|
19
|
+
|
20
|
+
actual_height = section_height(row)
|
21
|
+
doc.bounding_box([0, doc.cursor], width: doc.bounds.width, height: actual_height) do
|
22
|
+
row.items.each do |item|
|
23
|
+
draw_item(item, (actual_height - row.schema.height))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :pdf
|
31
|
+
|
32
|
+
def stack_view_renderer
|
33
|
+
raise Thinreports::Errors::InvalidLayoutFormat, 'nested StackView does not supported'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'parser'
|
4
|
+
|
5
|
+
module Thinreports
|
6
|
+
module SectionReport
|
7
|
+
module Schema
|
8
|
+
class Loader
|
9
|
+
def initialize
|
10
|
+
@parser = Schema::Parser.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_from_file(filename)
|
14
|
+
data = File.read(filename, encoding: 'UTF-8')
|
15
|
+
load_from_data(data)
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_from_data(data)
|
19
|
+
parser.parse(data)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :parser
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require_relative 'report'
|
6
|
+
require_relative 'section'
|
7
|
+
|
8
|
+
module Thinreports
|
9
|
+
module SectionReport
|
10
|
+
module Schema
|
11
|
+
class Parser
|
12
|
+
def parse(schema_json_data)
|
13
|
+
schema_data = JSON.parse(schema_json_data)
|
14
|
+
|
15
|
+
section_schema_datas = schema_data['sections'].group_by { |section| section['type'] }
|
16
|
+
|
17
|
+
Schema::Report.new(
|
18
|
+
schema_data,
|
19
|
+
headers: parse_sections(:header, section_schema_datas['header']),
|
20
|
+
details: parse_sections(:detail, section_schema_datas['detail']),
|
21
|
+
footers: parse_sections(:footer, section_schema_datas['footer'])
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :schema_data
|
28
|
+
|
29
|
+
def parse_sections(section_type, section_schema_datas = nil)
|
30
|
+
return {} if section_schema_datas.nil?
|
31
|
+
|
32
|
+
section_schema_datas.each_with_object({}) do |section_schema_data, section_schemas|
|
33
|
+
id = section_schema_data['id']
|
34
|
+
section_schemas[id.to_sym] = parse_section(section_type, section_schema_data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_section(type, section_schema_data)
|
39
|
+
items = section_schema_data['items'].map do |item_schema_data|
|
40
|
+
item_type = item_schema_data['type']
|
41
|
+
Core::Shape::Format(item_type).new(item_schema_data)
|
42
|
+
end
|
43
|
+
section_schema_class_for(type).new(section_schema_data, items: items)
|
44
|
+
end
|
45
|
+
|
46
|
+
def section_schema_class_for(section_type)
|
47
|
+
Schema::Section.const_get(section_type.capitalize)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thinreports
|
4
|
+
module SectionReport
|
5
|
+
module Schema
|
6
|
+
class Report < Core::Shape::Manager::Format
|
7
|
+
config_reader last_version: %w( version )
|
8
|
+
config_reader report_title: %w( title )
|
9
|
+
config_reader page_paper_type: %w( report paper-type ),
|
10
|
+
page_orientation: %w( report orientation ),
|
11
|
+
page_margin: %w( report margin ),
|
12
|
+
page_width: %w[report width],
|
13
|
+
page_height: %w[report height]
|
14
|
+
|
15
|
+
attr_reader :headers, :details, :footers
|
16
|
+
|
17
|
+
def user_paper_type?
|
18
|
+
page_paper_type == 'user'
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(schema_data, headers:, details:, footers:)
|
22
|
+
super(schema_data)
|
23
|
+
@headers = headers
|
24
|
+
@details = details
|
25
|
+
@footers = footers
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thinreports
|
4
|
+
module SectionReport
|
5
|
+
module Schema
|
6
|
+
module Section
|
7
|
+
class Base < Core::Shape::Manager::Format
|
8
|
+
config_reader :id, :type
|
9
|
+
config_reader :height
|
10
|
+
config_checker true, :display
|
11
|
+
config_checker true, auto_stretch: 'auto-stretch'
|
12
|
+
|
13
|
+
attr_reader :items
|
14
|
+
|
15
|
+
def initialize(schema_data, items:)
|
16
|
+
super(schema_data)
|
17
|
+
initialize_items(items)
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_item(id)
|
21
|
+
@item_with_ids[id.to_sym]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def initialize_items(items)
|
27
|
+
@items = items
|
28
|
+
@item_with_ids = items.each_with_object({}) do |item, item_with_ids|
|
29
|
+
next if item.id.empty?
|
30
|
+
item_with_ids[item.id.to_sym] = item
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Header < Base
|
36
|
+
config_checker true, every_page: 'every-page'
|
37
|
+
end
|
38
|
+
|
39
|
+
class Footer < Base
|
40
|
+
end
|
41
|
+
|
42
|
+
class Detail < Base
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/thinreports/version.rb
CHANGED
data/lib/thinreports.rb
CHANGED
@@ -6,6 +6,10 @@ module Thinreports
|
|
6
6
|
def self.root
|
7
7
|
@root ||= Pathname.new(__FILE__).join('..', '..')
|
8
8
|
end
|
9
|
+
|
10
|
+
def self.generate(report_params, filename: nil)
|
11
|
+
Generate.new.call(report_params, filename: filename)
|
12
|
+
end
|
9
13
|
end
|
10
14
|
|
11
15
|
require_relative 'thinreports/version'
|
@@ -18,3 +22,4 @@ require_relative 'thinreports/core/utils'
|
|
18
22
|
require_relative 'thinreports/report'
|
19
23
|
require_relative 'thinreports/layout'
|
20
24
|
require_relative 'thinreports/generator/pdf'
|
25
|
+
require_relative 'thinreports/generate'
|
data/thinreports.gemspec
CHANGED
@@ -14,17 +14,18 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.homepage = 'http://www.thinreports.org'
|
15
15
|
s.license = 'MIT'
|
16
16
|
|
17
|
-
s.required_ruby_version = '>= 2.
|
17
|
+
s.required_ruby_version = '>= 2.5.0'
|
18
18
|
|
19
|
-
s.files =
|
20
|
-
|
19
|
+
s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^test/}) }
|
21
|
+
end
|
22
|
+
s.require_paths = ['lib']
|
21
23
|
|
22
|
-
s.add_dependency 'prawn', '~> 2.2
|
24
|
+
s.add_dependency 'prawn', '~> 2.2'
|
25
|
+
s.add_dependency 'rexml'
|
23
26
|
|
24
|
-
s.add_development_dependency '
|
25
|
-
s.add_development_dependency '
|
26
|
-
s.add_development_dependency '
|
27
|
-
s.add_development_dependency '
|
28
|
-
s.add_development_dependency 'rake', '>= 0'
|
29
|
-
s.add_development_dependency 'yard', '>= 0'
|
27
|
+
s.add_development_dependency 'minitest', '>= 5.14.1'
|
28
|
+
s.add_development_dependency 'mocha', '>= 1.11.2'
|
29
|
+
s.add_development_dependency 'pdf-inspector', '>= 1.3.0'
|
30
|
+
s.add_development_dependency 'rake', '>= 13.0.1'
|
30
31
|
end
|