thinreports 0.12.0 → 0.13.0

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