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 +4 -4
- checksums.yaml.gz.sig +1 -3
- data/README.md +51 -1
- data/lib/repolho/main.rb +126 -15
- data/lib/repolho/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +3 -6
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3e44c3e92b2bf34c0785294e65149968cc4f8ce0c5dd1eabd4eebdb9f200340e
|
|
4
|
+
data.tar.gz: 4ec8fc094c8da9d07d1cac32ef07ab41908c47cb95419db424c4d8a1c9dc611a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b422a100451181e9b6bf1f96cf1fa4255be8c854677e6cb214f1149a175f464990d3b3064e3512c682cad13a8d63f191d347cac92850c5ad62bed1e458584bd9
|
|
7
|
+
data.tar.gz: f73bc63146708f0ec37c71f5e402c39c0eadec437d6a70f784e23e1bd5b36d46f98b3b011a01f09f995ed8eca3f06ce3cd8aebfa927fe9925c16ac9ce1532fd5
|
checksums.yaml.gz.sig
CHANGED
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
|
|
13
|
-
@data
|
|
14
|
-
@locals
|
|
15
|
-
@columns
|
|
16
|
-
@page
|
|
17
|
-
@report
|
|
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
|
|
188
|
+
matches = content.gsub(/\n/, "").match(/(?<previous>\A.*?)(?<body><body[^>]*>.*?)(?<report><report[^>]*>.*?<\/report>)(?<after>.*)\z/m)
|
|
97
189
|
|
|
98
|
-
@body
|
|
99
|
-
@previous
|
|
100
|
-
@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
|
data/lib/repolho/version.rb
CHANGED
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.
|
|
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:
|
|
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:
|
|
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
|