thinreports 0.12.1 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +3 -3
  3. data/.github/workflows/test.yml +28 -36
  4. data/.gitignore +1 -1
  5. data/CHANGELOG.md +25 -1
  6. data/Gemfile +11 -0
  7. data/README.md +12 -17
  8. data/Rakefile +17 -11
  9. data/lib/thinreports/basic_report/core/errors.rb +62 -0
  10. data/lib/thinreports/basic_report/core/format/base.rb +91 -0
  11. data/lib/thinreports/basic_report/core/shape/base/interface.rb +42 -0
  12. data/lib/thinreports/basic_report/core/shape/base/internal.rb +53 -0
  13. data/lib/thinreports/basic_report/core/shape/basic/block_format.rb +15 -0
  14. data/lib/thinreports/basic_report/core/shape/basic/block_interface.rb +34 -0
  15. data/lib/thinreports/basic_report/core/shape/basic/block_internal.rb +36 -0
  16. data/lib/thinreports/basic_report/core/shape/basic/format.rb +24 -0
  17. data/lib/thinreports/basic_report/core/shape/basic/interface.rb +87 -0
  18. data/lib/thinreports/basic_report/core/shape/basic/internal.rb +28 -0
  19. data/lib/thinreports/{core → basic_report/core}/shape/basic.rb +6 -4
  20. data/lib/thinreports/basic_report/core/shape/image_block/format.rb +14 -0
  21. data/lib/thinreports/basic_report/core/shape/image_block/interface.rb +25 -0
  22. data/lib/thinreports/basic_report/core/shape/image_block/internal.rb +19 -0
  23. data/lib/thinreports/{core → basic_report/core}/shape/image_block.rb +6 -4
  24. data/lib/thinreports/basic_report/core/shape/list/format.rb +92 -0
  25. data/lib/thinreports/basic_report/core/shape/list/manager.rb +231 -0
  26. data/lib/thinreports/basic_report/core/shape/list/page.rb +112 -0
  27. data/lib/thinreports/basic_report/core/shape/list/page_state.rb +50 -0
  28. data/lib/thinreports/basic_report/core/shape/list/section_format.rb +37 -0
  29. data/lib/thinreports/basic_report/core/shape/list/section_interface.rb +51 -0
  30. data/lib/thinreports/basic_report/core/shape/list/section_internal.rb +33 -0
  31. data/lib/thinreports/{core → basic_report/core}/shape/list.rb +6 -4
  32. data/lib/thinreports/basic_report/core/shape/manager/format.rb +33 -0
  33. data/lib/thinreports/basic_report/core/shape/manager/internal.rb +109 -0
  34. data/lib/thinreports/basic_report/core/shape/manager/target.rb +114 -0
  35. data/lib/thinreports/basic_report/core/shape/page_number/format.rb +32 -0
  36. data/lib/thinreports/basic_report/core/shape/page_number/interface.rb +31 -0
  37. data/lib/thinreports/basic_report/core/shape/page_number/internal.rb +57 -0
  38. data/lib/thinreports/{core → basic_report/core}/shape/page_number.rb +6 -4
  39. data/lib/thinreports/basic_report/core/shape/stack_view/format.rb +29 -0
  40. data/lib/thinreports/basic_report/core/shape/stack_view/interface.rb +19 -0
  41. data/lib/thinreports/basic_report/core/shape/stack_view/internal.rb +24 -0
  42. data/lib/thinreports/basic_report/core/shape/stack_view/row_format.rb +41 -0
  43. data/lib/thinreports/{core → basic_report/core}/shape/stack_view.rb +6 -4
  44. data/lib/thinreports/basic_report/core/shape/style/base.rb +149 -0
  45. data/lib/thinreports/basic_report/core/shape/style/basic.rb +24 -0
  46. data/lib/thinreports/basic_report/core/shape/style/graphic.rb +43 -0
  47. data/lib/thinreports/basic_report/core/shape/style/text.rb +122 -0
  48. data/lib/thinreports/basic_report/core/shape/text/format.rb +17 -0
  49. data/lib/thinreports/basic_report/core/shape/text/interface.rb +20 -0
  50. data/lib/thinreports/basic_report/core/shape/text/internal.rb +24 -0
  51. data/lib/thinreports/{core → basic_report/core}/shape/text.rb +6 -4
  52. data/lib/thinreports/basic_report/core/shape/text_block/format.rb +43 -0
  53. data/lib/thinreports/basic_report/core/shape/text_block/formatter/basic.rb +41 -0
  54. data/lib/thinreports/basic_report/core/shape/text_block/formatter/datetime.rb +25 -0
  55. data/lib/thinreports/basic_report/core/shape/text_block/formatter/number.rb +69 -0
  56. data/lib/thinreports/basic_report/core/shape/text_block/formatter/padding.rb +27 -0
  57. data/lib/thinreports/basic_report/core/shape/text_block/formatter.rb +38 -0
  58. data/lib/thinreports/basic_report/core/shape/text_block/interface.rb +37 -0
  59. data/lib/thinreports/basic_report/core/shape/text_block/internal.rb +75 -0
  60. data/lib/thinreports/{core → basic_report/core}/shape/text_block.rb +6 -4
  61. data/lib/thinreports/basic_report/core/shape.rb +44 -0
  62. data/lib/thinreports/basic_report/core/utils.rb +47 -0
  63. data/lib/thinreports/basic_report/generator/pdf/document/draw_shape.rb +108 -0
  64. data/lib/thinreports/basic_report/generator/pdf/document/draw_template_items.rb +71 -0
  65. data/lib/thinreports/basic_report/generator/pdf/document/font.rb +90 -0
  66. data/lib/thinreports/basic_report/generator/pdf/document/graphics/attributes.rb +149 -0
  67. data/lib/thinreports/basic_report/generator/pdf/document/graphics/basic.rb +137 -0
  68. data/lib/thinreports/basic_report/generator/pdf/document/graphics/image.rb +99 -0
  69. data/lib/thinreports/basic_report/generator/pdf/document/graphics/text.rb +180 -0
  70. data/lib/thinreports/basic_report/generator/pdf/document/graphics.rb +42 -0
  71. data/lib/thinreports/basic_report/generator/pdf/document/page.rb +96 -0
  72. data/lib/thinreports/basic_report/generator/pdf/document/parse_color.rb +51 -0
  73. data/lib/thinreports/basic_report/generator/pdf/document.rb +132 -0
  74. data/lib/thinreports/basic_report/generator/pdf/drawer/base.rb +50 -0
  75. data/lib/thinreports/basic_report/generator/pdf/drawer/list.rb +65 -0
  76. data/lib/thinreports/basic_report/generator/pdf/drawer/list_section.rb +51 -0
  77. data/lib/thinreports/basic_report/generator/pdf/drawer/page.rb +127 -0
  78. data/lib/thinreports/basic_report/generator/pdf/prawn_ext/calc_image_dimensions.rb +34 -0
  79. data/lib/thinreports/basic_report/generator/pdf/prawn_ext/width_of.rb +31 -0
  80. data/lib/thinreports/basic_report/generator/pdf.rb +66 -0
  81. data/lib/thinreports/basic_report/layout/base.rb +48 -0
  82. data/lib/thinreports/basic_report/layout/format.rb +67 -0
  83. data/lib/thinreports/basic_report/layout/legacy_schema.rb +383 -0
  84. data/lib/thinreports/basic_report/layout/version.rb +41 -0
  85. data/lib/thinreports/{layout.rb → basic_report/layout.rb} +6 -4
  86. data/lib/thinreports/basic_report/report/base.rb +174 -0
  87. data/lib/thinreports/basic_report/report/internal.rb +107 -0
  88. data/lib/thinreports/basic_report/report/page.rb +97 -0
  89. data/lib/thinreports/basic_report/report.rb +26 -0
  90. data/lib/thinreports/basic_report.rb +15 -0
  91. data/lib/thinreports/config.rb +1 -1
  92. data/lib/thinreports/section_report.rb +12 -0
  93. data/lib/thinreports/version.rb +1 -1
  94. data/lib/thinreports.rb +2 -13
  95. data/thinreports.gemspec +3 -7
  96. metadata +97 -154
  97. data/gemfiles/prawn-2.2.gemfile +0 -5
  98. data/gemfiles/prawn-2.3.gemfile +0 -5
  99. data/gemfiles/prawn-2.4.gemfile +0 -5
  100. data/lib/thinreports/core/errors.rb +0 -60
  101. data/lib/thinreports/core/format/base.rb +0 -89
  102. data/lib/thinreports/core/shape/base/interface.rb +0 -40
  103. data/lib/thinreports/core/shape/base/internal.rb +0 -51
  104. data/lib/thinreports/core/shape/basic/block_format.rb +0 -13
  105. data/lib/thinreports/core/shape/basic/block_interface.rb +0 -32
  106. data/lib/thinreports/core/shape/basic/block_internal.rb +0 -34
  107. data/lib/thinreports/core/shape/basic/format.rb +0 -22
  108. data/lib/thinreports/core/shape/basic/interface.rb +0 -85
  109. data/lib/thinreports/core/shape/basic/internal.rb +0 -26
  110. data/lib/thinreports/core/shape/image_block/format.rb +0 -12
  111. data/lib/thinreports/core/shape/image_block/interface.rb +0 -23
  112. data/lib/thinreports/core/shape/image_block/internal.rb +0 -17
  113. data/lib/thinreports/core/shape/list/format.rb +0 -90
  114. data/lib/thinreports/core/shape/list/manager.rb +0 -229
  115. data/lib/thinreports/core/shape/list/page.rb +0 -110
  116. data/lib/thinreports/core/shape/list/page_state.rb +0 -48
  117. data/lib/thinreports/core/shape/list/section_format.rb +0 -35
  118. data/lib/thinreports/core/shape/list/section_interface.rb +0 -49
  119. data/lib/thinreports/core/shape/list/section_internal.rb +0 -31
  120. data/lib/thinreports/core/shape/manager/format.rb +0 -31
  121. data/lib/thinreports/core/shape/manager/internal.rb +0 -107
  122. data/lib/thinreports/core/shape/manager/target.rb +0 -112
  123. data/lib/thinreports/core/shape/page_number/format.rb +0 -30
  124. data/lib/thinreports/core/shape/page_number/interface.rb +0 -29
  125. data/lib/thinreports/core/shape/page_number/internal.rb +0 -55
  126. data/lib/thinreports/core/shape/stack_view/format.rb +0 -27
  127. data/lib/thinreports/core/shape/stack_view/interface.rb +0 -17
  128. data/lib/thinreports/core/shape/stack_view/internal.rb +0 -22
  129. data/lib/thinreports/core/shape/stack_view/row_format.rb +0 -39
  130. data/lib/thinreports/core/shape/style/base.rb +0 -146
  131. data/lib/thinreports/core/shape/style/basic.rb +0 -22
  132. data/lib/thinreports/core/shape/style/graphic.rb +0 -41
  133. data/lib/thinreports/core/shape/style/text.rb +0 -120
  134. data/lib/thinreports/core/shape/text/format.rb +0 -15
  135. data/lib/thinreports/core/shape/text/interface.rb +0 -18
  136. data/lib/thinreports/core/shape/text/internal.rb +0 -22
  137. data/lib/thinreports/core/shape/text_block/format.rb +0 -41
  138. data/lib/thinreports/core/shape/text_block/formatter/basic.rb +0 -39
  139. data/lib/thinreports/core/shape/text_block/formatter/datetime.rb +0 -23
  140. data/lib/thinreports/core/shape/text_block/formatter/number.rb +0 -67
  141. data/lib/thinreports/core/shape/text_block/formatter/padding.rb +0 -25
  142. data/lib/thinreports/core/shape/text_block/formatter.rb +0 -34
  143. data/lib/thinreports/core/shape/text_block/interface.rb +0 -35
  144. data/lib/thinreports/core/shape/text_block/internal.rb +0 -73
  145. data/lib/thinreports/core/shape.rb +0 -42
  146. data/lib/thinreports/core/utils.rb +0 -45
  147. data/lib/thinreports/generate.rb +0 -11
  148. data/lib/thinreports/generator/pdf/document/draw_shape.rb +0 -106
  149. data/lib/thinreports/generator/pdf/document/draw_template_items.rb +0 -69
  150. data/lib/thinreports/generator/pdf/document/font.rb +0 -88
  151. data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +0 -147
  152. data/lib/thinreports/generator/pdf/document/graphics/basic.rb +0 -135
  153. data/lib/thinreports/generator/pdf/document/graphics/image.rb +0 -98
  154. data/lib/thinreports/generator/pdf/document/graphics/text.rb +0 -178
  155. data/lib/thinreports/generator/pdf/document/graphics.rb +0 -40
  156. data/lib/thinreports/generator/pdf/document/page.rb +0 -94
  157. data/lib/thinreports/generator/pdf/document/parse_color.rb +0 -49
  158. data/lib/thinreports/generator/pdf/document.rb +0 -130
  159. data/lib/thinreports/generator/pdf/drawer/base.rb +0 -48
  160. data/lib/thinreports/generator/pdf/drawer/list.rb +0 -63
  161. data/lib/thinreports/generator/pdf/drawer/list_section.rb +0 -49
  162. data/lib/thinreports/generator/pdf/drawer/page.rb +0 -125
  163. data/lib/thinreports/generator/pdf/prawn_ext/calc_image_dimensions.rb +0 -32
  164. data/lib/thinreports/generator/pdf/prawn_ext/width_of.rb +0 -29
  165. data/lib/thinreports/generator/pdf.rb +0 -63
  166. data/lib/thinreports/layout/base.rb +0 -46
  167. data/lib/thinreports/layout/format.rb +0 -65
  168. data/lib/thinreports/layout/legacy_schema.rb +0 -381
  169. data/lib/thinreports/layout/version.rb +0 -39
  170. data/lib/thinreports/report/base.rb +0 -169
  171. data/lib/thinreports/report/internal.rb +0 -105
  172. data/lib/thinreports/report/page.rb +0 -95
  173. data/lib/thinreports/report.rb +0 -24
  174. /data/lib/thinreports/{core → basic_report/core}/shape/base.rb +0 -0
  175. /data/lib/thinreports/{core → basic_report/core}/shape/manager.rb +0 -0
  176. /data/lib/thinreports/{core → basic_report/core}/shape/style.rb +0 -0
  177. /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