repolho 0.1.0 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2950c91544adda9db0b125b7b73717f20ac7d6535a9f378789c6aa3dadacd59c
4
- data.tar.gz: dc205200e80ddee22718e5964ce121001da131b7c7545d62cdb4505344b71620
3
+ metadata.gz: 3e44c3e92b2bf34c0785294e65149968cc4f8ce0c5dd1eabd4eebdb9f200340e
4
+ data.tar.gz: 4ec8fc094c8da9d07d1cac32ef07ab41908c47cb95419db424c4d8a1c9dc611a
5
5
  SHA512:
6
- metadata.gz: d63f3ef00ee5d6ccf72ed10331c09445672150ea41a977ba24cb90e12a321022a10e372aece79db3ac2c23e648fffd3fc77534062067c74ccbb019c3428adc25
7
- data.tar.gz: 18dc8cc1965a0a5d020f294a6ff47e581a7dbf0008a9eff2d7fb413d410dcea4ef635d806a32fb74207318788782db32a86b676d92689077793b6d7b416b0229
6
+ metadata.gz: b422a100451181e9b6bf1f96cf1fa4255be8c854677e6cb214f1149a175f464990d3b3064e3512c682cad13a8d63f191d347cac92850c5ad62bed1e458584bd9
7
+ data.tar.gz: f73bc63146708f0ec37c71f5e402c39c0eadec437d6a70f784e23e1bd5b36d46f98b3b011a01f09f995ed8eca3f06ce3cd8aebfa927fe9925c16ac9ce1532fd5
checksums.yaml.gz.sig CHANGED
@@ -1,3 +1 @@
1
- ��0��x�o�PM�'���Q4:jp{�Y�V3]������Gj��k�B�]f�/$P�a'r�>ۧ��u�L.W_!
2
- �����%GD�A2�кT��"�`e����C� Fc�5��/����g���@���J7[�c=4�!V�Y�ֻ� ���@�0]�o�|+b�����_�� ����V���(����©�\
3
- 8���]8���إ��)fݨ�Y�����,���反ˮ섮�z���7
1
+ ��è��ÿ��Zmj>����*O%Ɲ��X��SK�<�4X���:U H!8{;�4�)�A@�!iR3T���<c
data/README.md CHANGED
@@ -58,7 +58,7 @@ sections). Everything inside the custom elements is processed as ERB.
58
58
 
59
59
  | Element | Purpose | Attributes |
60
60
  |---------|---------|------------|
61
- | `<report>` | Root container of the report | — |
61
+ | `<report>` | Root container of the report | `pagination` (optional, `"true"`): enables client-side page navigation. Also accepts `pagination-first`, `pagination-prev`, `pagination-next`, `pagination-last` for custom labels. |
62
62
  | `<report-page>` | Defines a page (required, only one) | `rows` (required): max data rows per page |
63
63
  | `<report-group>` | Nested grouping | `id` (required), `attr` (required), `reprint-header-on-page-break` (optional, `"true"`) |
64
64
  | `<report-header>` | Header of the current container | — |
@@ -95,6 +95,56 @@ Repolho automatically wraps each page like this:
95
95
  The `data-page` attribute and the `break-after` style are injected for you.
96
96
  You do not need to write the `<tbody>` yourself.
97
97
 
98
+ ### Client-side pagination
99
+
100
+ If you set `pagination="true"` on the root `<report>` element, Repolho
101
+ appends a navigation bar just before the `after` section (still inside
102
+ the table) and a small pure-ES6 script at the end of the document
103
+ (inserted before `</body>` when present, otherwise appended). The bar
104
+ is omitted when the report has only one page.
105
+
106
+ Optional attributes let you customize the labels:
107
+
108
+ | Attribute | Default | Description |
109
+ |-----------|---------|-------------|
110
+ | `pagination-first` | `First` | First page link text |
111
+ | `pagination-prev` | `<` | Previous page link text |
112
+ | `pagination-next` | `>` | Next page link text |
113
+ | `pagination-last` | `Last` | Last page link text |
114
+
115
+ ```html
116
+ <report pagination="true"
117
+ pagination-first="Primeira"
118
+ pagination-prev="«"
119
+ pagination-next="»"
120
+ pagination-last="Última">
121
+ ...
122
+ </report>
123
+ ```
124
+
125
+ The generated controls look like:
126
+
127
+ ```html
128
+ <tbody id="report-pagination" data-max="N">
129
+ <tr>
130
+ <td colspan="200" id="report-pagination-links">
131
+ <a href="#" id="report-first-page">First</a>
132
+ <a href="#" id="report-prev-page"><</a>
133
+ <input type="number" id="report-current-page" min="1" max="N" value="1"/>
134
+ <a href="#" id="report-next-page">></a>
135
+ <a href="#" id="report-last-page">Last</a>
136
+ </td>
137
+ </tr>
138
+ </tbody>
139
+ ```
140
+
141
+ You can restyle the links and the input with normal CSS. The script is
142
+ wrapped in try/catch so a failure does not break the rest of the page.
143
+
144
+ When pagination is enabled, `page_number` (available in ERB) holds the
145
+ total number of pages after the report has been fully generated.
146
+
147
+
98
148
  ### Template example
99
149
 
100
150
  ```erb
data/lib/repolho/main.rb CHANGED
@@ -5,19 +5,84 @@ require_relative "page"
5
5
  require_relative "report"
6
6
  require_relative "stats"
7
7
  require "nokogiri"
8
+ require "erb"
9
+ require "cgi"
8
10
 
9
11
  module Repolho
10
12
  class Main
13
+ PAGINATION_TBODY = <<~HTML
14
+ <tbody id="report-pagination" data-max="<%= page_number %>">
15
+ <tr>
16
+ <td colspan="200" id="report-pagination-links">
17
+ <a href="#" id="report-first-page"><%= @pagination_first %></a>
18
+ <a href="#" id="report-prev-page"><%= @pagination_prev %></a>
19
+ <input type="number" id="report-current-page" min="1" max="<%= page_number %>" value="1"/>
20
+ <a href="#" id="report-next-page"><%= @pagination_next %></a>
21
+ <a href="#" id="report-last-page"><%= @pagination_last %></a>
22
+ </td>
23
+ </tr>
24
+ </tbody>
25
+ HTML
26
+
27
+ PAGINATION_SCRIPT = <<~HTML
28
+ <script>
29
+ function change_report_page(page) {
30
+ try {
31
+ const pages = document.querySelectorAll(".repolho-page");
32
+ page = parseInt(page, 10);
33
+ if (isNaN(page) || page < 1) page = 1;
34
+ if (page > pages.length) page = pages.length;
35
+
36
+ pages.forEach(function(p) { p.style.display = "none"; });
37
+ var target = document.querySelector('[data-page="' + page + '"]');
38
+ if (target) target.style.display = "";
39
+
40
+ var input = document.getElementById("report-current-page");
41
+ if (input) input.value = page;
42
+ } catch (e) {
43
+ console.error("Repolho pagination error:", e);
44
+ }
45
+ }
46
+
47
+ document.addEventListener("DOMContentLoaded", function() {
48
+ try {
49
+ var first = document.getElementById("report-first-page");
50
+ var prev = document.getElementById("report-prev-page");
51
+ var next = document.getElementById("report-next-page");
52
+ var last = document.getElementById("report-last-page");
53
+ var input = document.getElementById("report-current-page");
54
+
55
+ if (first) first.addEventListener("click", function(e) { e.preventDefault(); change_report_page(1); });
56
+ if (prev) prev.addEventListener("click", function(e) { e.preventDefault(); change_report_page(parseInt(input && input.value || 1, 10) - 1); });
57
+ if (next) next.addEventListener("click", function(e) { e.preventDefault(); change_report_page(parseInt(input && input.value || 1, 10) + 1); });
58
+ if (last) last.addEventListener("click", function(e) { e.preventDefault(); change_report_page(9999); });
59
+ if (input) input.addEventListener("change", function(e) { change_report_page(e.target.value); });
60
+
61
+ change_report_page(1);
62
+ } catch (e) {
63
+ console.error("Repolho pagination init error:", e);
64
+ }
65
+ });
66
+ </script>
67
+ HTML
68
+
11
69
  def initialize(path, data, locals = {})
12
- @path = path
13
- @data = normalize_data(data)
14
- @locals = locals
15
- @columns = make_columns
16
- @page = Page.new("page", locals, make_stats)
17
- @report = Report.new("report", locals, make_stats)
18
- @previous = ""
19
- @after = ""
20
- @body = ""
70
+ @path = path
71
+ @data = normalize_data(data)
72
+ @locals = locals
73
+ @columns = make_columns
74
+ @page = Page.new("page", locals, make_stats)
75
+ @report = Report.new("report", locals, make_stats)
76
+ @previous = ""
77
+ @after = ""
78
+ @body = ""
79
+ @pagination = false
80
+ @pagination_labels = {
81
+ first: "First",
82
+ prev: "<",
83
+ next: ">",
84
+ last: "Last"
85
+ }
21
86
 
22
87
  @report.containers << @page
23
88
  @report.page = @page
@@ -30,7 +95,7 @@ module Repolho
30
95
  def run
31
96
  parse
32
97
 
33
- @page.append_raw(@previous)
98
+ @page.append_raw(render_erb(@previous))
34
99
  @page.append_raw(@body)
35
100
 
36
101
  @data.each do |row|
@@ -38,12 +103,39 @@ module Repolho
38
103
  end
39
104
 
40
105
  @report.call(:finish, nil)
41
- @page.append_raw(@after)
42
106
  @page.finalize
107
+
108
+ # After finalize, page_number is one past the last page.
109
+ # Set it to the real total so ERB (pagination + @after) sees the correct value.
110
+ total_pages = [@page.page_number - 1, 1].max
111
+ @page.instance_variable_set(:@page_number, total_pages)
112
+
113
+ after_content = render_erb(@after)
114
+
115
+ if @pagination && total_pages > 1
116
+ inject_pagination_labels
117
+ @page.append_raw(render_erb(PAGINATION_TBODY))
118
+
119
+ script = PAGINATION_SCRIPT
120
+ if after_content =~ /<\/body>/i
121
+ after_content = after_content.sub(/<\/body>/i, "#{script}</body>")
122
+ else
123
+ after_content += script
124
+ end
125
+ end
126
+
127
+ @page.append_raw(after_content)
43
128
  end
44
129
 
45
130
  private
46
131
 
132
+ def inject_pagination_labels
133
+ @page.instance_variable_set(:@pagination_first, @pagination_labels[:first])
134
+ @page.instance_variable_set(:@pagination_prev, @pagination_labels[:prev])
135
+ @page.instance_variable_set(:@pagination_next, @pagination_labels[:next])
136
+ @page.instance_variable_set(:@pagination_last, @pagination_labels[:last])
137
+ end
138
+
47
139
  def make_columns
48
140
  return [] if @data.empty?
49
141
 
@@ -93,11 +185,11 @@ module Repolho
93
185
  end
94
186
 
95
187
  def extract_sections(content)
96
- matches = content.gsub(/\n/, "").match(/(?<previous>\A.*?)(?<body><body[^>]*>.*?)(?<report><report>.*?<\/report>)(?<after>.*)\z/m)
188
+ matches = content.gsub(/\n/, "").match(/(?<previous>\A.*?)(?<body><body[^>]*>.*?)(?<report><report[^>]*>.*?<\/report>)(?<after>.*)\z/m)
97
189
 
98
- @body = matches[:body]
99
- @previous = matches[:previous]
100
- @after = matches[:after]
190
+ @body = matches[:body]
191
+ @previous = matches[:previous]
192
+ @after = matches[:after]
101
193
  @report_xml = matches[:report]
102
194
  end
103
195
 
@@ -105,6 +197,19 @@ module Repolho
105
197
  parsed = Nokogiri::HTML.parse(@report_xml)
106
198
  report = parsed.search("report")
107
199
 
200
+ report_node = report.first
201
+ @pagination = report_node["pagination"] == "true"
202
+
203
+ if @pagination
204
+ @pagination_labels[:first] = report_node["pagination-first"] if report_node["pagination-first"]
205
+ @pagination_labels[:prev] = report_node["pagination-prev"] if report_node["pagination-prev"]
206
+ @pagination_labels[:next] = report_node["pagination-next"] if report_node["pagination-next"]
207
+ @pagination_labels[:last] = report_node["pagination-last"] if report_node["pagination-last"]
208
+
209
+ # Escape for safe HTML output
210
+ @pagination_labels.transform_values! { |v| CGI.escapeHTML(v.to_s) }
211
+ end
212
+
108
213
  @report.header = info(report.search("> report-header").first)
109
214
  @report.footer = info(report.search("> report-footer").first)
110
215
 
@@ -154,5 +259,11 @@ module Repolho
154
259
 
155
260
  { content: element.inner_html }
156
261
  end
262
+
263
+ def render_erb(content)
264
+ return "" if content.nil? || content.empty?
265
+
266
+ ERB.new(content).result(@page.instance_eval { binding })
267
+ end
157
268
  end
158
269
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Repolho
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: repolho
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eustáquio Rangel
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
@@ -36,7 +35,7 @@ cert_chain:
36
35
  L0XcRn7yJijWxXFMBrnwp/4PHjPT0l6Qci+zxGly0D7LCTHa5WSyWujq4BZw55Yp
37
36
  G13dwkTphaMB
38
37
  -----END CERTIFICATE-----
39
- date: 2026-10-21 00:00:00.000000000 Z
38
+ date: 1980-01-02 00:00:00.000000000 Z
40
39
  dependencies:
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: nokogiri
@@ -77,7 +76,6 @@ licenses:
77
76
  metadata:
78
77
  homepage_uri: https://github.com/taq/repolho
79
78
  source_code_uri: https://github.com/taq/repolho
80
- post_install_message:
81
79
  rdoc_options: []
82
80
  require_paths:
83
81
  - lib
@@ -92,8 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
90
  - !ruby/object:Gem::Version
93
91
  version: '0'
94
92
  requirements: []
95
- rubygems_version: 3.5.3
96
- signing_key:
93
+ rubygems_version: 4.0.20
97
94
  specification_version: 4
98
95
  summary: Report generator for Ruby and Rails from .rep.erb templates
99
96
  test_files: []
metadata.gz.sig CHANGED
Binary file