monocle-rails 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -18,7 +18,12 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- TODO: Write usage instructions here
21
+ <div id="reader">
22
+ <h1>Hello world.</h1>
23
+ </div>
24
+
25
+ <!-- Instantiate the reader when the containing element has loaded -->
26
+ <script>Monocle.Reader('reader');</script>
22
27
 
23
28
  ## Contributing
24
29
 
@@ -1,5 +1,5 @@
1
1
  module Monocle
2
2
  module Rails
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -0,0 +1,280 @@
1
+ /*
2
+ * EFM - Epub for Monocle
3
+ *
4
+ * A pure-javascript implementation of the book data object for Monocle.
5
+ *
6
+ * Copyright (c) 2013 Robert Schroll
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining
9
+ * a copy of this software and associated documentation files (the
10
+ * "Software"), to deal in the Software without restriction, including
11
+ * without limitation the rights to use, copy, modify, merge, publish,
12
+ * distribute, sublicense, and/or sell copies of the Software, and to
13
+ * permit persons to whom the Software is furnished to do so, subject to
14
+ * the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ MIMETYPES = {
29
+ png: "image/png",
30
+ gif: "image/gif",
31
+ jpg: "image/jpeg",
32
+ jpeg: "image/jpeg",
33
+ js: "text/javascript",
34
+ css: "text/css",
35
+ svg: "image/svg+xml",
36
+ };
37
+ URL_TAGS = {
38
+ img: "src",
39
+ link: "href",
40
+ image: "xlink:href", // Image in in-line SVG. (Calibre uses these for covers.)
41
+ };
42
+
43
+ // Get the directory portion of path. The path separator is '/', for
44
+ // use with zip files.
45
+ function getDir(path) {
46
+ return path.split('/').slice(0,-1).join('/');
47
+ }
48
+
49
+ // Join and normalize the two paths. The path separator is '/', for use
50
+ // with zip files.
51
+ function joinPaths(path1, path2) {
52
+ var path = path1.split('/').concat(path2.split('/')),
53
+ normpath = [];
54
+ for (var i in path) {
55
+ var dir = path[i];
56
+ if (dir == "..")
57
+ normpath.pop();
58
+ else if (dir != "." && dir != "")
59
+ normpath.push(dir);
60
+ }
61
+ return normpath.join('/');
62
+ }
63
+
64
+ // A book data object for the Epub file 'epubfile', a HTML5 File object.
65
+ // The callback will be called when this object is fully initialized,
66
+ // with this object as an argument.
67
+ function Epub(epubfile, callback) {
68
+ var files = {}; // Maps filename to zip.Entry
69
+ var spine = []; // List of filenames in spine
70
+ var contents = []; // Table of contents
71
+ var metadata = {}; // Maps keys to metadata
72
+ var data_urls = {}; // Maps filename to data URL of file contents
73
+ var num_data_urls = 0;
74
+ zip.createReader(new zip.BlobReader(epubfile), function (zipReader) {
75
+ zipReader.getEntries(function (entries) {
76
+ for (i in entries) {
77
+ e = entries[i];
78
+ files[e.filename] = e;
79
+ }
80
+ zipReader.close();
81
+ getComponent("META-INF/container.xml", findOPF);
82
+ // This starts a chain of callbacks, which will eventually
83
+ // end with onLoaded().
84
+ });
85
+ }, console.error);
86
+
87
+ // Find the location of the OPF file from container.xml
88
+ findOPF = function (xml) {
89
+ var doc = new DOMParser().parseFromString(xml, "text/xml");
90
+ var opffn = doc.getElementsByTagName("rootfile")[0].getAttribute("full-path");
91
+ getComponent(opffn, parseOPF(getDir(opffn)));
92
+ };
93
+
94
+ // Parse the OPF file to get the spine, the table of contents, and
95
+ // the metadata.
96
+ parseOPF = function (reldir) {
97
+ return function (xml) {
98
+ var doc = new DOMParser().parseFromString(xml, "text/xml");
99
+ var idmap = {};
100
+ var nav_href = null;
101
+
102
+ // Parse manifest
103
+ var manifest = doc.getElementsByTagName("manifest")[0];
104
+ var items = manifest.getElementsByTagName("item");
105
+ for (var i=0; i<items.length; i++) {
106
+ item = items[i];
107
+ var id = item.getAttribute("id");
108
+ var href = item.getAttribute("href");
109
+ idmap[id] = joinPaths(reldir, href);
110
+ var props = item.getAttribute("properties")
111
+ if (props != null && props.split(" ").indexOf("nav") > -1)
112
+ nav_href = idmap[id];
113
+ }
114
+
115
+ // Parse spine
116
+ var spineel = doc.getElementsByTagName("spine")[0];
117
+ var sitems = spineel.getElementsByTagName("itemref");
118
+ for (var i=0; i<sitems.length; i++) {
119
+ id = sitems[i].getAttribute("idref");
120
+ spine.push(idmap[id]);
121
+ }
122
+
123
+ // Parse table of contents
124
+ if (nav_href != null) { // Epub3 navigation
125
+ getComponent(nav_href, parseNav(getDir(nav_href)));
126
+ } else { // Epub2 navigation
127
+ var ncxfile = idmap[spineel.getAttribute("toc")];
128
+ if (ncxfile != undefined)
129
+ getComponent(ncxfile, parseNCX(getDir(ncxfile)));
130
+ }
131
+
132
+ // Parse metadata
133
+ var metadatael = doc.getElementsByTagName("metadata")[0];
134
+ for (var i=0; i<metadatael.childNodes.length; i++) {
135
+ var node = metadatael.childNodes[i];
136
+ if (node.nodeType == 1 && node.firstChild != null)
137
+ metadata[node.localName] = node.firstChild.nodeValue;
138
+ }
139
+
140
+ // Make data URLs for auxillary files, for future use
141
+ for (var fn in files) {
142
+ if (spine.indexOf(fn) == -1 && ["mimetype", "META-INF/container.xml"].indexOf(fn) == -1) {
143
+ num_data_urls += 1;
144
+ getEncodedComponent(fn, function (f) {
145
+ return function (data) {
146
+ data_urls[f] = data;
147
+ num_data_urls -= 1;
148
+ if (num_data_urls == 0)
149
+ onLoaded();
150
+ };
151
+ }(fn));
152
+ }
153
+ }
154
+ if (num_data_urls == 0) {
155
+ onLoaded();
156
+ }
157
+ };
158
+ };
159
+
160
+ // Parse the Epub3 table of contents.
161
+ parseNav = function (reldir) {
162
+ return function (navdata) {
163
+ var navdoc = new DOMParser().parseFromString(navdata, "text/xml");
164
+ var navs = navdoc.getElementsByTagName("nav");
165
+ for (var i=0; i<navs.length; i++) {
166
+ var nav = navs[i];
167
+ if (nav.getAttribute("epub:type") == "toc")
168
+ contents = self.parseNavList(nav.getElementsByTagName("ol")[0], reldir);
169
+ }
170
+ };
171
+ };
172
+
173
+ parseNavList = function (element, reldir) {
174
+ var children = [];
175
+ for (var i=0; i<element.childNodes.length; i++) {
176
+ var node = element.childNodes[i];
177
+ if (node.nodeType == 1 && node.nodeName == "li") {
178
+ var link = node.getElementsByTagName("a")[0];
179
+ if (link != undefined) {
180
+ var child = { title: link.firstChild.nodeValue,
181
+ src: joinPaths(reldir, link.getAttribute("href")) };
182
+ var olist = node.getElementsByTagName("ol")[0];
183
+ if (olist != undefined)
184
+ child["children"] = parseNavList(olist, reldir);
185
+ children.push(child);
186
+ }
187
+ }
188
+ }
189
+ return children;
190
+ };
191
+
192
+ // Parse the Epub2 table of contents.
193
+ parseNCX = function (reldir) {
194
+ return function (ncxdata) {
195
+ var ncx = new DOMParser().parseFromString(ncxdata, "text/xml");
196
+ var navmap = ncx.getElementsByTagName("navMap")[0];
197
+ contents = self.parseNCXChildren(navmap, reldir);
198
+ };
199
+ };
200
+
201
+ parseNCXChildren = function(element, reldir) {
202
+ var children = [];
203
+ for (var i=0; i<element.childNodes.length; i++) {
204
+ var node = element.childNodes[i];
205
+ if (node.nodeType == 1 && node.nodeName == "navPoint") {
206
+ var child = {};
207
+ var nav_label = node.getElementsByTagName("text")[0];
208
+ child["title"] = nav_label.firstChild.nodeValue;
209
+ var content = node.getElementsByTagName("content")[0];
210
+ child["src"] = joinPaths(reldir, content.getAttribute("src"));
211
+ var child_nav = parseNCXChildren(node, reldir);
212
+ if (child_nav.length > 0)
213
+ child["children"] = child_nav;
214
+ children.push(child);
215
+ }
216
+ }
217
+ return children;
218
+ };
219
+
220
+ // Part of Monocle's book data object interface.
221
+ getComponents = function () {
222
+ return spine;
223
+ };
224
+
225
+ // Part of Monocle's book data object interface.
226
+ getContents = function () {
227
+ return contents;
228
+ };
229
+
230
+ // Part of Monocle's book data object interface.
231
+ // Note that (X|HT)ML files are parsed and URLs in <img> and <link>
232
+ // to resouces in the Epub are replaced with data URLs.
233
+ getComponent = function (id, callback) {
234
+ var reldir = getDir(id);
235
+ var ext = id.split('.').slice(-1)[0];
236
+ if (["html", "htm", "xhtml", "xml"].indexOf(ext) != -1) {
237
+ files[id].getData(new zip.TextWriter(), function (data) {
238
+ var doc = new DOMParser().parseFromString(data, "text/xml");
239
+
240
+ for (var tag in URL_TAGS) {
241
+ var attribute = URL_TAGS[tag];
242
+ var elements = doc.getElementsByTagName(tag);
243
+ for (var i=0; i<elements.length; i++) {
244
+ var element = elements[i];
245
+ var path = joinPaths(reldir, element.getAttribute(attribute));
246
+ var data_url = data_urls[path];
247
+ if (data_url != undefined)
248
+ element.setAttribute(attribute, data_url);
249
+ }
250
+ }
251
+
252
+ callback(new XMLSerializer().serializeToString(doc));
253
+ });
254
+ } else {
255
+ files[id].getData(new zip.TextWriter(), function (data) {
256
+ callback(data);
257
+ });
258
+ }
259
+ };
260
+
261
+ // Return the content, via the callback, as a data URL.
262
+ getEncodedComponent = function (id, callback) {
263
+ var mime = MIMETYPES[id.split('.').slice(-1)[0]];
264
+ files[id].getData(new zip.Data64URIWriter(mime), function (data) {
265
+ callback(data);
266
+ });
267
+ };
268
+
269
+ // Part of Monocle's book data object interface.
270
+ getMetaData = function (key) {
271
+ return metadata[key];
272
+ }
273
+
274
+ // Called at the end of the initialization process. At this point,
275
+ // the object is ready to be passed to a Monocle.Reader.
276
+ onLoaded = function () {
277
+ callback(this);
278
+ };
279
+ }
280
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monocle-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -89,6 +89,7 @@ files:
89
89
  - vendor/assets/javascripts/core/selection.js
90
90
  - vendor/assets/javascripts/core/styles.js
91
91
  - vendor/assets/javascripts/dimensions/columns.js
92
+ - vendor/assets/javascripts/efm.js
92
93
  - vendor/assets/javascripts/flippers/instant.js
93
94
  - vendor/assets/javascripts/flippers/scroller.js
94
95
  - vendor/assets/javascripts/flippers/slider.js