im_reader 1.0.1 → 1.0.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
- data/app/assets/javascripts/im_reader/reader.js +42 -60
- data/app/controllers/im_reader/epub_reader_controller.rb +23 -3
- data/app/views/im_reader/epub_reader/show.html.erb +1 -0
- data/config/locales/de.yml +2 -0
- data/config/locales/en.yml +2 -0
- data/config/locales/es.yml +2 -0
- data/config/locales/fr.yml +2 -0
- data/config/locales/pt.yml +2 -0
- data/lib/im_reader/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9df80b54a543f446c9a12e0f09d296813cb861cd44f1ed283d5b30e3df57797c
|
|
4
|
+
data.tar.gz: 48e211b702f2dd7e3261db75d8be8d48c7c759e0dd7c23b85fdaa63148f0ad08
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: df2f8086643d74000d8fed67ad0f0068b56966757c4de95fe72ed38f4f8a113486294f0240a16c95d353b6cd3b0784b3313de5188e18a7ce4b10d02cd9959788
|
|
7
|
+
data.tar.gz: 066ed3cb0d3ead6971f51589aa722c872b77f9394d107246e89b1b9cb02d74aacbb5446d5247d4e53e3fafab02ce7103914db1ea8e8e3010b020a9dac875db64
|
|
@@ -19,17 +19,43 @@
|
|
|
19
19
|
$("#reader-root").append(overlay);
|
|
20
20
|
|
|
21
21
|
var bookUrl = $root.data("book-url");
|
|
22
|
+
if (!bookUrl) {
|
|
23
|
+
$("#cover-content").html(`<p class="ui red text">${i18n.missing_url || "URL manquante."}</p>`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
22
26
|
var theme = "light";
|
|
23
27
|
var fontSize = 100;
|
|
28
|
+
fetch(bookUrl, { method: "HEAD" })
|
|
29
|
+
.then((res) => {
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
// Si HEAD échoue, on tente GET pour récupérer le message texte
|
|
32
|
+
return fetch(bookUrl).then(async (resp) => {
|
|
33
|
+
const msg = await resp.text();
|
|
34
|
+
throw new Error(msg || i18n.reading_error || "Erreur de lecture.");
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
.then(() => startReader(bookUrl, i18n, overlay))
|
|
39
|
+
.catch((err) => {
|
|
40
|
+
console.error("[im_reader] load error:", err);
|
|
41
|
+
$("#cover-content").html(`<p class="ui red text">${err.message}</p>`);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
24
44
|
|
|
45
|
+
function startReader(bookUrl, i18n, overlay) {
|
|
25
46
|
var $viewer = $("#viewer"), $toc = $("#toc");
|
|
26
|
-
var $prev_button = $("#prev_button"), $next_button = $("#next_button")
|
|
47
|
+
var $prev_button = $("#prev_button"), $next_button = $("#next_button");
|
|
27
48
|
|
|
28
|
-
if (!window.ePub) {
|
|
49
|
+
if (!window.ePub) {
|
|
50
|
+
$("#cover-content").html(`<p class="ui red text">ePub introuvable</p>`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
29
53
|
|
|
30
|
-
window.book = window.ePub(bookUrl, {
|
|
54
|
+
window.book = window.ePub(bookUrl, {
|
|
55
|
+
openAs: "epub",
|
|
31
56
|
replacements: "blob",
|
|
32
|
-
restore: false
|
|
57
|
+
restore: false
|
|
58
|
+
});
|
|
33
59
|
|
|
34
60
|
var rendition = book.renderTo("viewer", {
|
|
35
61
|
width: "100%",
|
|
@@ -53,34 +79,17 @@
|
|
|
53
79
|
if (iframe) iframe.setAttribute("sandbox", "allow-same-origin allow-scripts");
|
|
54
80
|
});
|
|
55
81
|
|
|
56
|
-
$prev_button.on("click", () =>
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
$next_button.on("click", () => {
|
|
61
|
-
rendition.next();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
rendition.on("relocated", (location) => {
|
|
65
|
-
if (book.locations.total > 0) {
|
|
66
|
-
const current = book.locations.locationFromCfi(location.start.cfi);
|
|
67
|
-
const total = book.locations.total;
|
|
68
|
-
let percentage = current / total;
|
|
69
|
-
if (location.atEnd) percentage = 1.0;
|
|
70
|
-
|
|
71
|
-
$('#progressBar').progress('set percent', Math.round(percentage * 100));
|
|
72
|
-
}
|
|
73
|
-
});
|
|
82
|
+
$prev_button.on("click", () => rendition.prev());
|
|
83
|
+
$next_button.on("click", () => rendition.next());
|
|
74
84
|
|
|
75
85
|
book.ready.then(() => Promise.all([book.loaded.navigation, book.loaded.manifest]))
|
|
76
86
|
.then(([toc, manifest]) => {
|
|
77
|
-
|
|
78
87
|
book.coverUrl().then((url) => {
|
|
79
88
|
if (url) {
|
|
80
89
|
$("#cover-content").html(`
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
<img src="${url}" alt="${i18n.book_cover}">
|
|
91
|
+
<button id="start_button" class="ui primary button">${i18n.start}</button>
|
|
92
|
+
`);
|
|
84
93
|
|
|
85
94
|
overlay.on("click", "#start_button", () => {
|
|
86
95
|
overlay.remove();
|
|
@@ -93,51 +102,24 @@
|
|
|
93
102
|
});
|
|
94
103
|
|
|
95
104
|
const $toc = $("#toc");
|
|
96
|
-
|
|
97
|
-
function normalizeHref(href) {
|
|
98
|
-
for (const key in manifest) {
|
|
99
|
-
const entry = manifest[key];
|
|
100
|
-
if (
|
|
101
|
-
entry.href.endsWith(href) ||
|
|
102
|
-
entry.href.endsWith("x" + href) ||
|
|
103
|
-
entry.href.endsWith("/" + href)
|
|
104
|
-
) {
|
|
105
|
-
return entry.href;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Par défaut
|
|
110
|
-
return href;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
105
|
toc.toc.forEach((chapter) => {
|
|
114
|
-
const resolvedHref = normalizeHref(chapter.href);
|
|
115
|
-
|
|
116
106
|
$("<a>")
|
|
117
107
|
.addClass("item")
|
|
118
108
|
.attr("href", "#")
|
|
119
109
|
.text(chapter.label)
|
|
120
110
|
.on("click", (e) => {
|
|
121
111
|
e.preventDefault();
|
|
122
|
-
rendition
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
-
console.error("[im_reader] Display error:", err.message, resolvedHref);
|
|
126
|
-
});
|
|
112
|
+
rendition.display(chapter.href).catch((err) => {
|
|
113
|
+
console.error("[im_reader] Display error:", err.message);
|
|
114
|
+
});
|
|
127
115
|
})
|
|
128
116
|
.appendTo($toc);
|
|
129
117
|
});
|
|
130
118
|
})
|
|
131
|
-
.catch((err) =>
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}).then(() => {
|
|
136
|
-
}).catch(e => console.error("Error, book not ready", e));
|
|
137
|
-
|
|
138
|
-
rendition.on("displayError", (e)=> console.error("Error on display", e));
|
|
139
|
-
|
|
140
|
-
rendition.display().catch(e=>console.error("Error while rendering book", e));
|
|
119
|
+
.catch((err) => {
|
|
120
|
+
console.error("[im_reader] TOC load error:", err);
|
|
121
|
+
$("#cover-content").html(`<p class="ui red text">${i18n.reading_error || "Erreur de lecture du livre."}</p>`);
|
|
122
|
+
});
|
|
141
123
|
}
|
|
142
124
|
|
|
143
125
|
$(function(){ var $root = $("#reader-root"); if ($root.length) initReader($root); });
|
|
@@ -8,12 +8,14 @@ module ImReader
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def remote
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
raw_url = params[:url].to_s.strip
|
|
12
|
+
return render plain: I18n.t('im_reader.messages.missing_url'), status: 400 if raw_url.empty?
|
|
13
|
+
uri = parse_uri(raw_url)
|
|
14
|
+
return render plain: I18n.t('im_reader.messages.invalid_url'), status: 400 unless uri
|
|
15
|
+
|
|
13
16
|
response = fetch_with_redirect(uri)
|
|
14
17
|
|
|
15
18
|
if response.is_a?(Net::HTTPSuccess)
|
|
16
|
-
|
|
17
19
|
send_data response.body,
|
|
18
20
|
filename: File.basename(uri.path.presence || "remote.epub"),
|
|
19
21
|
type: "application/epub+zip",
|
|
@@ -25,6 +27,24 @@ module ImReader
|
|
|
25
27
|
|
|
26
28
|
private
|
|
27
29
|
|
|
30
|
+
def parse_uri(value)
|
|
31
|
+
raw = value.to_s.strip
|
|
32
|
+
return nil if raw.empty?
|
|
33
|
+
|
|
34
|
+
candidates = [raw, CGI.unescape(raw)].uniq
|
|
35
|
+
|
|
36
|
+
candidates.each do |c|
|
|
37
|
+
begin
|
|
38
|
+
uri = URI.parse(c)
|
|
39
|
+
return uri if uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS)
|
|
40
|
+
rescue URI::InvalidURIError, URI::InvalidComponentError
|
|
41
|
+
next
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
|
|
28
48
|
def fetch_with_redirect(uri, limit = 5)
|
|
29
49
|
raise "Too many redirects" if limit == 0
|
|
30
50
|
|
data/config/locales/de.yml
CHANGED
data/config/locales/en.yml
CHANGED
data/config/locales/es.yml
CHANGED
data/config/locales/fr.yml
CHANGED
data/config/locales/pt.yml
CHANGED
data/lib/im_reader/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: im_reader
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Elodie Ailleaume
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-11-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: sass
|