twigg-app 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/data/quips.yml +45 -0
  3. data/lib/twigg-app/app/quips.rb +13 -0
  4. data/lib/twigg-app/app/routes.rb +43 -0
  5. data/lib/twigg-app/app/server.rb +146 -0
  6. data/lib/twigg-app/app/version.rb +5 -0
  7. data/lib/twigg-app/app.rb +14 -0
  8. data/lib/twigg-app.rb +5 -0
  9. data/public/application.js +106 -0
  10. data/public/favicon.ico +0 -0
  11. data/public/favicon.png +0 -0
  12. data/public/vendor/bootstrap/CNAME +1 -0
  13. data/public/vendor/bootstrap/CONTRIBUTING.md +66 -0
  14. data/public/vendor/bootstrap/Gruntfile.js +195 -0
  15. data/public/vendor/bootstrap/LICENSE +176 -0
  16. data/public/vendor/bootstrap/README.md +139 -0
  17. data/public/vendor/bootstrap/_config.yml +28 -0
  18. data/public/vendor/bootstrap/_includes/ads.html +1 -0
  19. data/public/vendor/bootstrap/_includes/footer.html +33 -0
  20. data/public/vendor/bootstrap/_includes/header.html +43 -0
  21. data/public/vendor/bootstrap/_includes/nav-components.html +135 -0
  22. data/public/vendor/bootstrap/_includes/nav-css.html +77 -0
  23. data/public/vendor/bootstrap/_includes/nav-customize.html +40 -0
  24. data/public/vendor/bootstrap/_includes/nav-getting-started.html +28 -0
  25. data/public/vendor/bootstrap/_includes/nav-javascript.html +88 -0
  26. data/public/vendor/bootstrap/_includes/nav-main.html +32 -0
  27. data/public/vendor/bootstrap/_includes/old-bs-docs.html +8 -0
  28. data/public/vendor/bootstrap/_includes/social-buttons.html +16 -0
  29. data/public/vendor/bootstrap/_layouts/customize.html +52 -0
  30. data/public/vendor/bootstrap/_layouts/default.html +72 -0
  31. data/public/vendor/bootstrap/_layouts/home.html +43 -0
  32. data/public/vendor/bootstrap/assets/css/docs.css +896 -0
  33. data/public/vendor/bootstrap/assets/css/pygments-manni.css +66 -0
  34. data/public/vendor/bootstrap/assets/ico/apple-touch-icon-114-precomposed.png +0 -0
  35. data/public/vendor/bootstrap/assets/ico/apple-touch-icon-144-precomposed.png +0 -0
  36. data/public/vendor/bootstrap/assets/ico/apple-touch-icon-57-precomposed.png +0 -0
  37. data/public/vendor/bootstrap/assets/ico/apple-touch-icon-72-precomposed.png +0 -0
  38. data/public/vendor/bootstrap/assets/ico/favicon.png +0 -0
  39. data/public/vendor/bootstrap/assets/js/application.js +82 -0
  40. data/public/vendor/bootstrap/assets/js/customizer.js +175 -0
  41. data/public/vendor/bootstrap/assets/js/holder.js +419 -0
  42. data/public/vendor/bootstrap/assets/js/html5shiv.js +8 -0
  43. data/public/vendor/bootstrap/assets/js/jquery.bbq.min.js +1287 -0
  44. data/public/vendor/bootstrap/assets/js/jquery.js +5 -0
  45. data/public/vendor/bootstrap/assets/js/jszip.js +1425 -0
  46. data/public/vendor/bootstrap/assets/js/less.js +9 -0
  47. data/public/vendor/bootstrap/assets/js/respond.min.js +6 -0
  48. data/public/vendor/bootstrap/assets/js/uglify.js +14 -0
  49. data/public/vendor/bootstrap/bower.json +11 -0
  50. data/public/vendor/bootstrap/browserstack.json +37 -0
  51. data/public/vendor/bootstrap/components.html +2555 -0
  52. data/public/vendor/bootstrap/composer.json +20 -0
  53. data/public/vendor/bootstrap/css.html +2276 -0
  54. data/public/vendor/bootstrap/customize.html +1480 -0
  55. data/public/vendor/bootstrap/dist/css/bootstrap.css +5579 -0
  56. data/public/vendor/bootstrap/dist/css/bootstrap.min.css +9 -0
  57. data/public/vendor/bootstrap/dist/js/bootstrap.js +1993 -0
  58. data/public/vendor/bootstrap/dist/js/bootstrap.min.js +6 -0
  59. data/public/vendor/bootstrap/getting-started.html +375 -0
  60. data/public/vendor/bootstrap/index.html +16 -0
  61. data/public/vendor/bootstrap/javascript.html +1904 -0
  62. data/public/vendor/bootstrap/js/affix.js +126 -0
  63. data/public/vendor/bootstrap/js/alert.js +98 -0
  64. data/public/vendor/bootstrap/js/button.js +109 -0
  65. data/public/vendor/bootstrap/js/carousel.js +217 -0
  66. data/public/vendor/bootstrap/js/collapse.js +179 -0
  67. data/public/vendor/bootstrap/js/dropdown.js +154 -0
  68. data/public/vendor/bootstrap/js/modal.js +244 -0
  69. data/public/vendor/bootstrap/js/popover.js +117 -0
  70. data/public/vendor/bootstrap/js/scrollspy.js +158 -0
  71. data/public/vendor/bootstrap/js/tab.js +135 -0
  72. data/public/vendor/bootstrap/js/tests/index.html +52 -0
  73. data/public/vendor/bootstrap/js/tests/phantom.js +63 -0
  74. data/public/vendor/bootstrap/js/tests/server.js +14 -0
  75. data/public/vendor/bootstrap/js/tests/unit/affix.js +25 -0
  76. data/public/vendor/bootstrap/js/tests/unit/alert.js +62 -0
  77. data/public/vendor/bootstrap/js/tests/unit/button.js +116 -0
  78. data/public/vendor/bootstrap/js/tests/unit/carousel.js +87 -0
  79. data/public/vendor/bootstrap/js/tests/unit/collapse.js +164 -0
  80. data/public/vendor/bootstrap/js/tests/unit/dropdown.js +219 -0
  81. data/public/vendor/bootstrap/js/tests/unit/modal.js +177 -0
  82. data/public/vendor/bootstrap/js/tests/unit/phantom.js +69 -0
  83. data/public/vendor/bootstrap/js/tests/unit/popover.js +133 -0
  84. data/public/vendor/bootstrap/js/tests/unit/scrollspy.js +37 -0
  85. data/public/vendor/bootstrap/js/tests/unit/tab.js +86 -0
  86. data/public/vendor/bootstrap/js/tests/unit/tooltip.js +437 -0
  87. data/public/vendor/bootstrap/js/tests/unit/transition.js +13 -0
  88. data/public/vendor/bootstrap/js/tests/vendor/jquery.js +5 -0
  89. data/public/vendor/bootstrap/js/tests/vendor/qunit.css +232 -0
  90. data/public/vendor/bootstrap/js/tests/vendor/qunit.js +1510 -0
  91. data/public/vendor/bootstrap/js/tooltip.js +382 -0
  92. data/public/vendor/bootstrap/js/transition.js +56 -0
  93. data/public/vendor/bootstrap/less/alerts.less +71 -0
  94. data/public/vendor/bootstrap/less/badges.less +51 -0
  95. data/public/vendor/bootstrap/less/bootstrap.less +63 -0
  96. data/public/vendor/bootstrap/less/breadcrumbs.less +23 -0
  97. data/public/vendor/bootstrap/less/button-groups.less +244 -0
  98. data/public/vendor/bootstrap/less/buttons.less +159 -0
  99. data/public/vendor/bootstrap/less/carousel.less +204 -0
  100. data/public/vendor/bootstrap/less/close.less +33 -0
  101. data/public/vendor/bootstrap/less/code.less +56 -0
  102. data/public/vendor/bootstrap/less/component-animations.less +29 -0
  103. data/public/vendor/bootstrap/less/dropdowns.less +176 -0
  104. data/public/vendor/bootstrap/less/forms.less +332 -0
  105. data/public/vendor/bootstrap/less/grid.less +340 -0
  106. data/public/vendor/bootstrap/less/input-groups.less +127 -0
  107. data/public/vendor/bootstrap/less/jumbotron.less +29 -0
  108. data/public/vendor/bootstrap/less/labels.less +54 -0
  109. data/public/vendor/bootstrap/less/list-group.less +88 -0
  110. data/public/vendor/bootstrap/less/media.less +56 -0
  111. data/public/vendor/bootstrap/less/mixins.less +693 -0
  112. data/public/vendor/bootstrap/less/modals.less +133 -0
  113. data/public/vendor/bootstrap/less/navbar.less +559 -0
  114. data/public/vendor/bootstrap/less/navs.less +228 -0
  115. data/public/vendor/bootstrap/less/normalize.less +396 -0
  116. data/public/vendor/bootstrap/less/pager.less +55 -0
  117. data/public/vendor/bootstrap/less/pagination.less +72 -0
  118. data/public/vendor/bootstrap/less/panels.less +128 -0
  119. data/public/vendor/bootstrap/less/popovers.less +133 -0
  120. data/public/vendor/bootstrap/less/print.less +100 -0
  121. data/public/vendor/bootstrap/less/progress-bars.less +99 -0
  122. data/public/vendor/bootstrap/less/responsive-utilities.less +149 -0
  123. data/public/vendor/bootstrap/less/scaffolding.less +111 -0
  124. data/public/vendor/bootstrap/less/tables.less +211 -0
  125. data/public/vendor/bootstrap/less/thumbnails.less +42 -0
  126. data/public/vendor/bootstrap/less/tooltip.less +95 -0
  127. data/public/vendor/bootstrap/less/type.less +238 -0
  128. data/public/vendor/bootstrap/less/utilities.less +42 -0
  129. data/public/vendor/bootstrap/less/variables.less +607 -0
  130. data/public/vendor/bootstrap/less/wells.less +29 -0
  131. data/public/vendor/bootstrap/package.json +33 -0
  132. data/public/vendor/bootstrap-glyphicons/CHANGELOG.md +3 -0
  133. data/public/vendor/bootstrap-glyphicons/CNAME +1 -0
  134. data/public/vendor/bootstrap-glyphicons/CONTRIBUTING.md +54 -0
  135. data/public/vendor/bootstrap-glyphicons/LICENSE +19 -0
  136. data/public/vendor/bootstrap-glyphicons/README.md +61 -0
  137. data/public/vendor/bootstrap-glyphicons/_config.yml +12 -0
  138. data/public/vendor/bootstrap-glyphicons/composer.json +9 -0
  139. data/public/vendor/bootstrap-glyphicons/css/bootstrap-glyphicons.css +2 -0
  140. data/public/vendor/bootstrap-glyphicons/css/bootstrap.css +9 -0
  141. data/public/vendor/bootstrap-glyphicons/css/docs.css +160 -0
  142. data/public/vendor/bootstrap-glyphicons/fonts/glyphiconshalflings-regular.eot +0 -0
  143. data/public/vendor/bootstrap-glyphicons/fonts/glyphiconshalflings-regular.otf +0 -0
  144. data/public/vendor/bootstrap-glyphicons/fonts/glyphiconshalflings-regular.svg +175 -0
  145. data/public/vendor/bootstrap-glyphicons/fonts/glyphiconshalflings-regular.ttf +0 -0
  146. data/public/vendor/bootstrap-glyphicons/fonts/glyphiconshalflings-regular.woff +0 -0
  147. data/public/vendor/bootstrap-glyphicons/index.html +255 -0
  148. data/public/vendor/bootstrap-glyphicons/less/bootstrap-glyphicons.less +201 -0
  149. data/public/vendor/bootstrap-glyphicons/package.json +18 -0
  150. data/public/vendor/d3/LICENSE +26 -0
  151. data/public/vendor/d3/README.md +7 -0
  152. data/public/vendor/d3/bower.json +25 -0
  153. data/public/vendor/d3/d3.js +8810 -0
  154. data/public/vendor/d3/d3.min.js +5 -0
  155. data/public/vendor/jquery/README.md +11 -0
  156. data/public/vendor/jquery/bower.json +11 -0
  157. data/public/vendor/jquery/component.json +15 -0
  158. data/public/vendor/jquery/composer.json +35 -0
  159. data/public/vendor/jquery/jquery-migrate.js +511 -0
  160. data/public/vendor/jquery/jquery-migrate.min.js +3 -0
  161. data/public/vendor/jquery/jquery.js +8829 -0
  162. data/public/vendor/jquery/jquery.min.js +6 -0
  163. data/public/vendor/jquery/jquery.min.map +1 -0
  164. data/public/vendor/jquery/package.json +7 -0
  165. data/public/vendor/replacejs/CHANGELOG.md +3 -0
  166. data/public/vendor/replacejs/MIT-LICENSE.txt +20 -0
  167. data/public/vendor/replacejs/README.md +123 -0
  168. data/public/vendor/replacejs/bower.json +24 -0
  169. data/public/vendor/replacejs/primer.js +17 -0
  170. data/public/vendor/replacejs/primer.min.js +1 -0
  171. data/public/vendor/replacejs/replace.js +182 -0
  172. data/public/vendor/stupidtable.js +158 -0
  173. data/views/dashboard.haml +17 -0
  174. data/views/layout.haml +60 -0
  175. metadata +330 -0
@@ -0,0 +1,1425 @@
1
+ /**
2
+
3
+ JSZip - A Javascript class for generating and reading zip files
4
+ <http://stuartk.com/jszip>
5
+
6
+ (c) 2009-2012 Stuart Knightley <stuart [at] stuartk.com>
7
+ Dual licenced under the MIT license or GPLv3. See LICENSE.markdown.
8
+
9
+ Usage:
10
+ zip = new JSZip();
11
+ zip.file("hello.txt", "Hello, World!").file("tempfile", "nothing");
12
+ zip.folder("images").file("smile.gif", base64Data, {base64: true});
13
+ zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")});
14
+ zip.remove("tempfile");
15
+
16
+ base64zip = zip.generate();
17
+
18
+ **/
19
+ "use strict";
20
+
21
+ /**
22
+ * Representation a of zip file in js
23
+ * @constructor
24
+ * @param {String=|ArrayBuffer=|Uint8Array=|Buffer=} data the data to load, if any (optional).
25
+ * @param {Object=} options the options for creating this objects (optional).
26
+ */
27
+ var JSZip = function(data, options) {
28
+ // object containing the files :
29
+ // {
30
+ // "folder/" : {...},
31
+ // "folder/data.txt" : {...}
32
+ // }
33
+ this.files = {};
34
+
35
+ // Where we are in the hierarchy
36
+ this.root = "";
37
+
38
+ if (data) {
39
+ this.load(data, options);
40
+ }
41
+ };
42
+
43
+ JSZip.signature = {
44
+ LOCAL_FILE_HEADER : "\x50\x4b\x03\x04",
45
+ CENTRAL_FILE_HEADER : "\x50\x4b\x01\x02",
46
+ CENTRAL_DIRECTORY_END : "\x50\x4b\x05\x06",
47
+ ZIP64_CENTRAL_DIRECTORY_LOCATOR : "\x50\x4b\x06\x07",
48
+ ZIP64_CENTRAL_DIRECTORY_END : "\x50\x4b\x06\x06",
49
+ DATA_DESCRIPTOR : "\x50\x4b\x07\x08"
50
+ };
51
+
52
+ // Default properties for a new file
53
+ JSZip.defaults = {
54
+ base64: false,
55
+ binary: false,
56
+ dir: false,
57
+ date: null,
58
+ compression: null
59
+ };
60
+
61
+
62
+ JSZip.prototype = (function () {
63
+
64
+ /**
65
+ * Returns the raw data of a ZipObject, decompress the content if necessary.
66
+ * @param {ZipObject} file the file to use.
67
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
68
+ */
69
+ var getRawData = function (file) {
70
+ if (file._data instanceof JSZip.CompressedObject) {
71
+ file._data = file._data.getContent();
72
+ file.options.binary = true;
73
+ file.options.base64 = false;
74
+
75
+ if (JSZip.utils.getTypeOf(file._data) === "uint8array") {
76
+ var copy = file._data;
77
+ // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.
78
+ // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).
79
+ file._data = new Uint8Array(copy.length);
80
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
81
+ if (copy.length !== 0) {
82
+ file._data.set(copy, 0);
83
+ }
84
+ }
85
+ }
86
+ return file._data;
87
+ };
88
+
89
+ /**
90
+ * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it.
91
+ * @param {ZipObject} file the file to use.
92
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
93
+ */
94
+ var getBinaryData = function (file) {
95
+ var result = getRawData(file), type = JSZip.utils.getTypeOf(result);
96
+ if (type === "string") {
97
+ if (!file.options.binary) {
98
+ // unicode text !
99
+ // unicode string => binary string is a painful process, check if we can avoid it.
100
+ if (JSZip.support.uint8array && typeof TextEncoder === "function") {
101
+ return TextEncoder("utf-8").encode(result);
102
+ }
103
+ if (JSZip.support.nodebuffer) {
104
+ return new Buffer(result, "utf-8");
105
+ }
106
+ }
107
+ return file.asBinary();
108
+ }
109
+ return result;
110
+ }
111
+
112
+ /**
113
+ * Transform this._data into a string.
114
+ * @param {function} filter a function String -> String, applied if not null on the result.
115
+ * @return {String} the string representing this._data.
116
+ */
117
+ var dataToString = function (asUTF8) {
118
+ var result = getRawData(this);
119
+ if (result === null || typeof result === "undefined") {
120
+ return "";
121
+ }
122
+ // if the data is a base64 string, we decode it before checking the encoding !
123
+ if (this.options.base64) {
124
+ result = JSZip.base64.decode(result);
125
+ }
126
+ if (asUTF8 && this.options.binary) {
127
+ // JSZip.prototype.utf8decode supports arrays as input
128
+ // skip to array => string step, utf8decode will do it.
129
+ result = JSZip.prototype.utf8decode(result);
130
+ } else {
131
+ // no utf8 transformation, do the array => string step.
132
+ result = JSZip.utils.transformTo("string", result);
133
+ }
134
+
135
+ if (!asUTF8 && !this.options.binary) {
136
+ result = JSZip.prototype.utf8encode(result);
137
+ }
138
+ return result;
139
+ };
140
+ /**
141
+ * A simple object representing a file in the zip file.
142
+ * @constructor
143
+ * @param {string} name the name of the file
144
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data
145
+ * @param {Object} options the options of the file
146
+ */
147
+ var ZipObject = function (name, data, options) {
148
+ this.name = name;
149
+ this._data = data;
150
+ this.options = options;
151
+ };
152
+
153
+ ZipObject.prototype = {
154
+ /**
155
+ * Return the content as UTF8 string.
156
+ * @return {string} the UTF8 string.
157
+ */
158
+ asText : function () {
159
+ return dataToString.call(this, true);
160
+ },
161
+ /**
162
+ * Returns the binary content.
163
+ * @return {string} the content as binary.
164
+ */
165
+ asBinary : function () {
166
+ return dataToString.call(this, false);
167
+ },
168
+ /**
169
+ * Returns the content as a nodejs Buffer.
170
+ * @return {Buffer} the content as a Buffer.
171
+ */
172
+ asNodeBuffer : function () {
173
+ var result = getBinaryData(this);
174
+ return JSZip.utils.transformTo("nodebuffer", result);
175
+ },
176
+ /**
177
+ * Returns the content as an Uint8Array.
178
+ * @return {Uint8Array} the content as an Uint8Array.
179
+ */
180
+ asUint8Array : function () {
181
+ var result = getBinaryData(this);
182
+ return JSZip.utils.transformTo("uint8array", result);
183
+ },
184
+ /**
185
+ * Returns the content as an ArrayBuffer.
186
+ * @return {ArrayBuffer} the content as an ArrayBufer.
187
+ */
188
+ asArrayBuffer : function () {
189
+ return this.asUint8Array().buffer;
190
+ }
191
+ };
192
+
193
+ /**
194
+ * Transform an integer into a string in hexadecimal.
195
+ * @private
196
+ * @param {number} dec the number to convert.
197
+ * @param {number} bytes the number of bytes to generate.
198
+ * @returns {string} the result.
199
+ */
200
+ var decToHex = function(dec, bytes) {
201
+ var hex = "", i;
202
+ for(i = 0; i < bytes; i++) {
203
+ hex += String.fromCharCode(dec&0xff);
204
+ dec=dec>>>8;
205
+ }
206
+ return hex;
207
+ };
208
+
209
+ /**
210
+ * Merge the objects passed as parameters into a new one.
211
+ * @private
212
+ * @param {...Object} var_args All objects to merge.
213
+ * @return {Object} a new object with the data of the others.
214
+ */
215
+ var extend = function () {
216
+ var result = {}, i, attr;
217
+ for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers
218
+ for (attr in arguments[i]) {
219
+ if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") {
220
+ result[attr] = arguments[i][attr];
221
+ }
222
+ }
223
+ }
224
+ return result;
225
+ };
226
+
227
+ /**
228
+ * Transforms the (incomplete) options from the user into the complete
229
+ * set of options to create a file.
230
+ * @private
231
+ * @param {Object} o the options from the user.
232
+ * @return {Object} the complete set of options.
233
+ */
234
+ var prepareFileAttrs = function (o) {
235
+ o = o || {};
236
+ if (o.base64 === true && o.binary == null) {
237
+ o.binary = true;
238
+ }
239
+ o = extend(o, JSZip.defaults);
240
+ o.date = o.date || new Date();
241
+ if (o.compression !== null) o.compression = o.compression.toUpperCase();
242
+
243
+ return o;
244
+ };
245
+
246
+ /**
247
+ * Add a file in the current folder.
248
+ * @private
249
+ * @param {string} name the name of the file
250
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file
251
+ * @param {Object} o the options of the file
252
+ * @return {Object} the new file.
253
+ */
254
+ var fileAdd = function (name, data, o) {
255
+ // be sure sub folders exist
256
+ var parent = parentFolder(name), dataType = JSZip.utils.getTypeOf(data);
257
+ if (parent) {
258
+ folderAdd.call(this, parent);
259
+ }
260
+
261
+ o = prepareFileAttrs(o);
262
+
263
+ if (o.dir || data === null || typeof data === "undefined") {
264
+ o.base64 = false;
265
+ o.binary = false;
266
+ data = null;
267
+ } else if (dataType === "string") {
268
+ if (o.binary && !o.base64) {
269
+ // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask
270
+ if (o.optimizedBinaryString !== true) {
271
+ // this is a string, not in a base64 format.
272
+ // Be sure that this is a correct "binary string"
273
+ data = JSZip.utils.string2binary(data);
274
+ }
275
+ }
276
+ } else { // arraybuffer, uint8array, ...
277
+ o.base64 = false;
278
+ o.binary = true;
279
+
280
+ if (!dataType && !(data instanceof JSZip.CompressedObject)) {
281
+ throw new Error("The data of '" + name + "' is in an unsupported format !");
282
+ }
283
+
284
+ // special case : it's way easier to work with Uint8Array than with ArrayBuffer
285
+ if (dataType === "arraybuffer") {
286
+ data = JSZip.utils.transformTo("uint8array", data);
287
+ }
288
+ }
289
+
290
+ return this.files[name] = new ZipObject(name, data, o);
291
+ };
292
+
293
+
294
+ /**
295
+ * Find the parent folder of the path.
296
+ * @private
297
+ * @param {string} path the path to use
298
+ * @return {string} the parent folder, or ""
299
+ */
300
+ var parentFolder = function (path) {
301
+ if (path.slice(-1) == '/') {
302
+ path = path.substring(0, path.length - 1);
303
+ }
304
+ var lastSlash = path.lastIndexOf('/');
305
+ return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
306
+ };
307
+
308
+ /**
309
+ * Add a (sub) folder in the current folder.
310
+ * @private
311
+ * @param {string} name the folder's name
312
+ * @return {Object} the new folder.
313
+ */
314
+ var folderAdd = function (name) {
315
+ // Check the name ends with a /
316
+ if (name.slice(-1) != "/") {
317
+ name += "/"; // IE doesn't like substr(-1)
318
+ }
319
+
320
+ // Does this folder already exist?
321
+ if (!this.files[name]) {
322
+ fileAdd.call(this, name, null, {dir:true});
323
+ }
324
+ return this.files[name];
325
+ };
326
+
327
+ /**
328
+ * Generate a JSZip.CompressedObject for a given zipOject.
329
+ * @param {ZipObject} file the object to read.
330
+ * @param {JSZip.compression} compression the compression to use.
331
+ * @return {JSZip.CompressedObject} the compressed result.
332
+ */
333
+ var generateCompressedObjectFrom = function (file, compression) {
334
+ var result = new JSZip.CompressedObject(), content;
335
+
336
+ // the data has not been decompressed, we might reuse things !
337
+ if (file._data instanceof JSZip.CompressedObject) {
338
+ result.uncompressedSize = file._data.uncompressedSize;
339
+ result.crc32 = file._data.crc32;
340
+
341
+ if (result.uncompressedSize === 0 || file.options.dir) {
342
+ compression = JSZip.compressions['STORE'];
343
+ result.compressedContent = "";
344
+ result.crc32 = 0;
345
+ } else if (file._data.compressionMethod === compression.magic) {
346
+ result.compressedContent = file._data.getCompressedContent();
347
+ } else {
348
+ content = file._data.getContent()
349
+ // need to decompress / recompress
350
+ result.compressedContent = compression.compress(JSZip.utils.transformTo(compression.compressInputType, content));
351
+ }
352
+ } else {
353
+ // have uncompressed data
354
+ content = getBinaryData(file);
355
+ if (!content || content.length === 0 || file.options.dir) {
356
+ compression = JSZip.compressions['STORE'];
357
+ content = "";
358
+ }
359
+ result.uncompressedSize = content.length;
360
+ result.crc32 = this.crc32(content);
361
+ result.compressedContent = compression.compress(JSZip.utils.transformTo(compression.compressInputType, content));
362
+ }
363
+
364
+ result.compressedSize = result.compressedContent.length;
365
+ result.compressionMethod = compression.magic;
366
+
367
+ return result;
368
+ };
369
+
370
+ /**
371
+ * Generate the various parts used in the construction of the final zip file.
372
+ * @param {string} name the file name.
373
+ * @param {ZipObject} file the file content.
374
+ * @param {JSZip.CompressedObject} compressedObject the compressed object.
375
+ * @param {number} offset the current offset from the start of the zip file.
376
+ * @return {object} the zip parts.
377
+ */
378
+ var generateZipParts = function(name, file, compressedObject, offset) {
379
+ var data = compressedObject.compressedContent,
380
+ utfEncodedFileName = this.utf8encode(file.name),
381
+ useUTF8 = utfEncodedFileName !== file.name,
382
+ o = file.options,
383
+ dosTime,
384
+ dosDate;
385
+
386
+ // date
387
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html
388
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html
389
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html
390
+
391
+ dosTime = o.date.getHours();
392
+ dosTime = dosTime << 6;
393
+ dosTime = dosTime | o.date.getMinutes();
394
+ dosTime = dosTime << 5;
395
+ dosTime = dosTime | o.date.getSeconds() / 2;
396
+
397
+ dosDate = o.date.getFullYear() - 1980;
398
+ dosDate = dosDate << 4;
399
+ dosDate = dosDate | (o.date.getMonth() + 1);
400
+ dosDate = dosDate << 5;
401
+ dosDate = dosDate | o.date.getDate();
402
+
403
+
404
+ var header = "";
405
+
406
+ // version needed to extract
407
+ header += "\x0A\x00";
408
+ // general purpose bit flag
409
+ // set bit 11 if utf8
410
+ header += useUTF8 ? "\x00\x08" : "\x00\x00";
411
+ // compression method
412
+ header += compressedObject.compressionMethod;
413
+ // last mod file time
414
+ header += decToHex(dosTime, 2);
415
+ // last mod file date
416
+ header += decToHex(dosDate, 2);
417
+ // crc-32
418
+ header += decToHex(compressedObject.crc32, 4);
419
+ // compressed size
420
+ header += decToHex(compressedObject.compressedSize, 4);
421
+ // uncompressed size
422
+ header += decToHex(compressedObject.uncompressedSize, 4);
423
+ // file name length
424
+ header += decToHex(utfEncodedFileName.length, 2);
425
+ // extra field length
426
+ header += "\x00\x00";
427
+
428
+
429
+ var fileRecord = JSZip.signature.LOCAL_FILE_HEADER + header + utfEncodedFileName;
430
+
431
+ var dirRecord = JSZip.signature.CENTRAL_FILE_HEADER +
432
+ // version made by (00: DOS)
433
+ "\x14\x00" +
434
+ // file header (common to file and central directory)
435
+ header +
436
+ // file comment length
437
+ "\x00\x00" +
438
+ // disk number start
439
+ "\x00\x00" +
440
+ // internal file attributes TODO
441
+ "\x00\x00" +
442
+ // external file attributes
443
+ (file.options.dir===true?"\x10\x00\x00\x00":"\x00\x00\x00\x00")+
444
+ // relative offset of local header
445
+ decToHex(offset, 4) +
446
+ // file name
447
+ utfEncodedFileName;
448
+
449
+
450
+ return {
451
+ fileRecord : fileRecord,
452
+ dirRecord : dirRecord,
453
+ compressedObject : compressedObject
454
+ };
455
+ };
456
+
457
+ /**
458
+ * An object to write any content to a string.
459
+ * @constructor
460
+ */
461
+ var StringWriter = function () {
462
+ this.data = [];
463
+ };
464
+ StringWriter.prototype = {
465
+ /**
466
+ * Append any content to the current string.
467
+ * @param {Object} input the content to add.
468
+ */
469
+ append : function (input) {
470
+ input = JSZip.utils.transformTo("string", input);
471
+ this.data.push(input);
472
+ },
473
+ /**
474
+ * Finalize the construction an return the result.
475
+ * @return {string} the generated string.
476
+ */
477
+ finalize : function () {
478
+ return this.data.join("");
479
+ }
480
+ };
481
+ /**
482
+ * An object to write any content to an Uint8Array.
483
+ * @constructor
484
+ * @param {number} length The length of the array.
485
+ */
486
+ var Uint8ArrayWriter = function (length) {
487
+ this.data = new Uint8Array(length);
488
+ this.index = 0;
489
+ };
490
+ Uint8ArrayWriter.prototype = {
491
+ /**
492
+ * Append any content to the current array.
493
+ * @param {Object} input the content to add.
494
+ */
495
+ append : function (input) {
496
+ if (input.length !== 0) {
497
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
498
+ input = JSZip.utils.transformTo("uint8array", input);
499
+ this.data.set(input, this.index);
500
+ this.index += input.length;
501
+ }
502
+ },
503
+ /**
504
+ * Finalize the construction an return the result.
505
+ * @return {Uint8Array} the generated array.
506
+ */
507
+ finalize : function () {
508
+ return this.data;
509
+ }
510
+ };
511
+
512
+ // return the actual prototype of JSZip
513
+ return {
514
+ /**
515
+ * Read an existing zip and merge the data in the current JSZip object.
516
+ * The implementation is in jszip-load.js, don't forget to include it.
517
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} stream The stream to load
518
+ * @param {Object} options Options for loading the stream.
519
+ * options.base64 : is the stream in base64 ? default : false
520
+ * @return {JSZip} the current JSZip object
521
+ */
522
+ load : function (stream, options) {
523
+ throw new Error("Load method is not defined. Is the file jszip-load.js included ?");
524
+ },
525
+
526
+ /**
527
+ * Filter nested files/folders with the specified function.
528
+ * @param {Function} search the predicate to use :
529
+ * function (relativePath, file) {...}
530
+ * It takes 2 arguments : the relative path and the file.
531
+ * @return {Array} An array of matching elements.
532
+ */
533
+ filter : function (search) {
534
+ var result = [], filename, relativePath, file, fileClone;
535
+ for (filename in this.files) {
536
+ if ( !this.files.hasOwnProperty(filename) ) { continue; }
537
+ file = this.files[filename];
538
+ // return a new object, don't let the user mess with our internal objects :)
539
+ fileClone = new ZipObject(file.name, file._data, extend(file.options));
540
+ relativePath = filename.slice(this.root.length, filename.length);
541
+ if (filename.slice(0, this.root.length) === this.root && // the file is in the current root
542
+ search(relativePath, fileClone)) { // and the file matches the function
543
+ result.push(fileClone);
544
+ }
545
+ }
546
+ return result;
547
+ },
548
+
549
+ /**
550
+ * Add a file to the zip file, or search a file.
551
+ * @param {string|RegExp} name The name of the file to add (if data is defined),
552
+ * the name of the file to find (if no data) or a regex to match files.
553
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded
554
+ * @param {Object} o File options
555
+ * @return {JSZip|Object|Array} this JSZip object (when adding a file),
556
+ * a file (when searching by string) or an array of files (when searching by regex).
557
+ */
558
+ file : function(name, data, o) {
559
+ if (arguments.length === 1) {
560
+ if (name instanceof RegExp) {
561
+ var regexp = name;
562
+ return this.filter(function(relativePath, file) {
563
+ return !file.options.dir && regexp.test(relativePath);
564
+ });
565
+ } else { // text
566
+ return this.filter(function (relativePath, file) {
567
+ return !file.options.dir && relativePath === name;
568
+ })[0]||null;
569
+ }
570
+ } else { // more than one argument : we have data !
571
+ name = this.root+name;
572
+ fileAdd.call(this, name, data, o);
573
+ }
574
+ return this;
575
+ },
576
+
577
+ /**
578
+ * Add a directory to the zip file, or search.
579
+ * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders.
580
+ * @return {JSZip} an object with the new directory as the root, or an array containing matching folders.
581
+ */
582
+ folder : function(arg) {
583
+ if (!arg) {
584
+ return this;
585
+ }
586
+
587
+ if (arg instanceof RegExp) {
588
+ return this.filter(function(relativePath, file) {
589
+ return file.options.dir && arg.test(relativePath);
590
+ });
591
+ }
592
+
593
+ // else, name is a new folder
594
+ var name = this.root + arg;
595
+ var newFolder = folderAdd.call(this, name);
596
+
597
+ // Allow chaining by returning a new object with this folder as the root
598
+ var ret = this.clone();
599
+ ret.root = newFolder.name;
600
+ return ret;
601
+ },
602
+
603
+ /**
604
+ * Delete a file, or a directory and all sub-files, from the zip
605
+ * @param {string} name the name of the file to delete
606
+ * @return {JSZip} this JSZip object
607
+ */
608
+ remove : function(name) {
609
+ name = this.root + name;
610
+ var file = this.files[name];
611
+ if (!file) {
612
+ // Look for any folders
613
+ if (name.slice(-1) != "/") {
614
+ name += "/";
615
+ }
616
+ file = this.files[name];
617
+ }
618
+
619
+ if (file) {
620
+ if (!file.options.dir) {
621
+ // file
622
+ delete this.files[name];
623
+ } else {
624
+ // folder
625
+ var kids = this.filter(function (relativePath, file) {
626
+ return file.name.slice(0, name.length) === name;
627
+ });
628
+ for (var i = 0; i < kids.length; i++) {
629
+ delete this.files[kids[i].name];
630
+ }
631
+ }
632
+ }
633
+
634
+ return this;
635
+ },
636
+
637
+ /**
638
+ * Generate the complete zip file
639
+ * @param {Object} options the options to generate the zip file :
640
+ * - base64, (deprecated, use type instead) true to generate base64.
641
+ * - compression, "STORE" by default.
642
+ * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob.
643
+ * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file
644
+ */
645
+ generate : function(options) {
646
+ options = extend(options || {}, {
647
+ base64 : true,
648
+ compression : "STORE",
649
+ type : "base64"
650
+ });
651
+
652
+ JSZip.utils.checkSupport(options.type);
653
+
654
+ var zipData = [], localDirLength = 0, centralDirLength = 0, writer, i;
655
+
656
+
657
+ // first, generate all the zip parts.
658
+ for (var name in this.files) {
659
+ if ( !this.files.hasOwnProperty(name) ) { continue; }
660
+ var file = this.files[name];
661
+
662
+ var compressionName = file.compression || options.compression.toUpperCase();
663
+ var compression = JSZip.compressions[compressionName];
664
+ if (!compression) {
665
+ throw new Error(compressionName + " is not a valid compression method !");
666
+ }
667
+
668
+ var compressedObject = generateCompressedObjectFrom.call(this, file, compression);
669
+
670
+ var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength);
671
+ localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize;
672
+ centralDirLength += zipPart.dirRecord.length;
673
+ zipData.push(zipPart);
674
+ }
675
+
676
+ var dirEnd = "";
677
+
678
+ // end of central dir signature
679
+ dirEnd = JSZip.signature.CENTRAL_DIRECTORY_END +
680
+ // number of this disk
681
+ "\x00\x00" +
682
+ // number of the disk with the start of the central directory
683
+ "\x00\x00" +
684
+ // total number of entries in the central directory on this disk
685
+ decToHex(zipData.length, 2) +
686
+ // total number of entries in the central directory
687
+ decToHex(zipData.length, 2) +
688
+ // size of the central directory 4 bytes
689
+ decToHex(centralDirLength, 4) +
690
+ // offset of start of central directory with respect to the starting disk number
691
+ decToHex(localDirLength, 4) +
692
+ // .ZIP file comment length
693
+ "\x00\x00";
694
+
695
+
696
+ // we have all the parts (and the total length)
697
+ // time to create a writer !
698
+ switch(options.type.toLowerCase()) {
699
+ case "uint8array" :
700
+ case "arraybuffer" :
701
+ case "blob" :
702
+ case "nodebuffer" :
703
+ writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length);
704
+ break;
705
+ case "base64" :
706
+ default : // case "string" :
707
+ writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length);
708
+ break;
709
+ }
710
+
711
+ for (i = 0; i < zipData.length; i++) {
712
+ writer.append(zipData[i].fileRecord);
713
+ writer.append(zipData[i].compressedObject.compressedContent);
714
+ }
715
+ for (i = 0; i < zipData.length; i++) {
716
+ writer.append(zipData[i].dirRecord);
717
+ }
718
+
719
+ writer.append(dirEnd);
720
+
721
+ var zip = writer.finalize();
722
+
723
+
724
+
725
+ switch(options.type.toLowerCase()) {
726
+ // case "zip is an Uint8Array"
727
+ case "uint8array" :
728
+ case "arraybuffer" :
729
+ case "nodebuffer" :
730
+ return JSZip.utils.transformTo(options.type.toLowerCase(), zip);
731
+ case "blob" :
732
+ return JSZip.utils.arrayBuffer2Blob(JSZip.utils.transformTo("arraybuffer", zip));
733
+
734
+ // case "zip is a string"
735
+ case "base64" :
736
+ return (options.base64) ? JSZip.base64.encode(zip) : zip;
737
+ default : // case "string" :
738
+ return zip;
739
+ }
740
+ },
741
+
742
+ /**
743
+ *
744
+ * Javascript crc32
745
+ * http://www.webtoolkit.info/
746
+ *
747
+ */
748
+ crc32 : function crc32(input, crc) {
749
+ if (typeof input === "undefined" || !input.length) {
750
+ return 0;
751
+ }
752
+
753
+ var isArray = JSZip.utils.getTypeOf(input) !== "string";
754
+
755
+ var table = [
756
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
757
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
758
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
759
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
760
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
761
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
762
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
763
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
764
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
765
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
766
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
767
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
768
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
769
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
770
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
771
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
772
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
773
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
774
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
775
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
776
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
777
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
778
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
779
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
780
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
781
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
782
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
783
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
784
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
785
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
786
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
787
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
788
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
789
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
790
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
791
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
792
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
793
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
794
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
795
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
796
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
797
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
798
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
799
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
800
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
801
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
802
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
803
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
804
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
805
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
806
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
807
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
808
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
809
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
810
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
811
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
812
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
813
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
814
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
815
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
816
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
817
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
818
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
819
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
820
+ ];
821
+
822
+ if (typeof(crc) == "undefined") { crc = 0; }
823
+ var x = 0;
824
+ var y = 0;
825
+ var byte = 0;
826
+
827
+ crc = crc ^ (-1);
828
+ for( var i = 0, iTop = input.length; i < iTop; i++ ) {
829
+ byte = isArray ? input[i] : input.charCodeAt(i);
830
+ y = ( crc ^ byte ) & 0xFF;
831
+ x = table[y];
832
+ crc = ( crc >>> 8 ) ^ x;
833
+ }
834
+
835
+ return crc ^ (-1);
836
+ },
837
+
838
+ // Inspired by http://my.opera.com/GreyWyvern/blog/show.dml/1725165
839
+ clone : function() {
840
+ var newObj = new JSZip();
841
+ for (var i in this) {
842
+ if (typeof this[i] !== "function") {
843
+ newObj[i] = this[i];
844
+ }
845
+ }
846
+ return newObj;
847
+ },
848
+
849
+
850
+ /**
851
+ * http://www.webtoolkit.info/javascript-utf8.html
852
+ */
853
+ utf8encode : function (string) {
854
+ // TextEncoder + Uint8Array to binary string is faster than checking every bytes on long strings.
855
+ // http://jsperf.com/utf8encode-vs-textencoder
856
+ // On short strings (file names for example), the TextEncoder API is (currently) slower.
857
+ if (JSZip.support.uint8array && typeof TextEncoder === "function") {
858
+ var u8 = TextEncoder("utf-8").encode(string);
859
+ return JSZip.utils.transformTo("string", u8);
860
+ }
861
+ if (JSZip.support.nodebuffer) {
862
+ return JSZip.utils.transformTo("string", new Buffer(string, "utf-8"));
863
+ }
864
+
865
+ // array.join may be slower than string concatenation but generates less objects (less time spent garbage collecting).
866
+ // See also http://jsperf.com/array-direct-assignment-vs-push/31
867
+ var result = [], resIndex = 0;
868
+
869
+ for (var n = 0; n < string.length; n++) {
870
+
871
+ var c = string.charCodeAt(n);
872
+
873
+ if (c < 128) {
874
+ result[resIndex++] = String.fromCharCode(c);
875
+ } else if ((c > 127) && (c < 2048)) {
876
+ result[resIndex++] = String.fromCharCode((c >> 6) | 192);
877
+ result[resIndex++] = String.fromCharCode((c & 63) | 128);
878
+ } else {
879
+ result[resIndex++] = String.fromCharCode((c >> 12) | 224);
880
+ result[resIndex++] = String.fromCharCode(((c >> 6) & 63) | 128);
881
+ result[resIndex++] = String.fromCharCode((c & 63) | 128);
882
+ }
883
+
884
+ }
885
+
886
+ return result.join("");
887
+ },
888
+
889
+ /**
890
+ * http://www.webtoolkit.info/javascript-utf8.html
891
+ */
892
+ utf8decode : function (input) {
893
+ var result = [], resIndex = 0;
894
+ var type = JSZip.utils.getTypeOf(input);
895
+ var isArray = type !== "string";
896
+ var i = 0;
897
+ var c = 0, c1 = 0, c2 = 0, c3 = 0;
898
+
899
+ // check if we can use the TextDecoder API
900
+ // see http://encoding.spec.whatwg.org/#api
901
+ if (JSZip.support.uint8array && typeof TextDecoder === "function") {
902
+ return TextDecoder("utf-8").decode(
903
+ JSZip.utils.transformTo("uint8array", input)
904
+ );
905
+ }
906
+ if (JSZip.support.nodebuffer) {
907
+ return JSZip.utils.transformTo("nodebuffer", input).toString("utf-8");
908
+ }
909
+
910
+ while ( i < input.length ) {
911
+
912
+ c = isArray ? input[i] : input.charCodeAt(i);
913
+
914
+ if (c < 128) {
915
+ result[resIndex++] = String.fromCharCode(c);
916
+ i++;
917
+ } else if ((c > 191) && (c < 224)) {
918
+ c2 = isArray ? input[i+1] : input.charCodeAt(i+1);
919
+ result[resIndex++] = String.fromCharCode(((c & 31) << 6) | (c2 & 63));
920
+ i += 2;
921
+ } else {
922
+ c2 = isArray ? input[i+1] : input.charCodeAt(i+1);
923
+ c3 = isArray ? input[i+2] : input.charCodeAt(i+2);
924
+ result[resIndex++] = String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
925
+ i += 3;
926
+ }
927
+
928
+ }
929
+
930
+ return result.join("");
931
+ }
932
+ };
933
+ }());
934
+
935
+ /*
936
+ * Compression methods
937
+ * This object is filled in as follow :
938
+ * name : {
939
+ * magic // the 2 bytes indentifying the compression method
940
+ * compress // function, take the uncompressed content and return it compressed.
941
+ * uncompress // function, take the compressed content and return it uncompressed.
942
+ * compressInputType // string, the type accepted by the compress method. null to accept everything.
943
+ * uncompressInputType // string, the type accepted by the uncompress method. null to accept everything.
944
+ * }
945
+ *
946
+ * STORE is the default compression method, so it's included in this file.
947
+ * Other methods should go to separated files : the user wants modularity.
948
+ */
949
+ JSZip.compressions = {
950
+ "STORE" : {
951
+ magic : "\x00\x00",
952
+ compress : function (content) {
953
+ return content; // no compression
954
+ },
955
+ uncompress : function (content) {
956
+ return content; // no compression
957
+ },
958
+ compressInputType : null,
959
+ uncompressInputType : null
960
+ }
961
+ };
962
+
963
+ /*
964
+ * List features that require a modern browser, and if the current browser support them.
965
+ */
966
+ JSZip.support = {
967
+ // contains true if JSZip can read/generate ArrayBuffer, false otherwise.
968
+ arraybuffer : (function(){
969
+ return typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
970
+ })(),
971
+ // contains true if JSZip can read/generate nodejs Buffer, false otherwise.
972
+ nodebuffer : (function(){
973
+ return typeof Buffer !== "undefined";
974
+ })(),
975
+ // contains true if JSZip can read/generate Uint8Array, false otherwise.
976
+ uint8array : (function(){
977
+ return typeof Uint8Array !== "undefined";
978
+ })(),
979
+ // contains true if JSZip can read/generate Blob, false otherwise.
980
+ blob : (function(){
981
+ // the spec started with BlobBuilder then replaced it with a construtor for Blob.
982
+ // Result : we have browsers that :
983
+ // * know the BlobBuilder (but with prefix)
984
+ // * know the Blob constructor
985
+ // * know about Blob but not about how to build them
986
+ // About the "=== 0" test : if given the wrong type, it may be converted to a string.
987
+ // Instead of an empty content, we will get "[object Uint8Array]" for example.
988
+ if (typeof ArrayBuffer === "undefined") {
989
+ return false;
990
+ }
991
+ var buffer = new ArrayBuffer(0);
992
+ try {
993
+ return new Blob([buffer], { type: "application/zip" }).size === 0;
994
+ }
995
+ catch(e) {}
996
+
997
+ try {
998
+ var builder = new (window.BlobBuilder || window.WebKitBlobBuilder ||
999
+ window.MozBlobBuilder || window.MSBlobBuilder)();
1000
+ builder.append(buffer);
1001
+ return builder.getBlob('application/zip').size === 0;
1002
+ }
1003
+ catch(e) {}
1004
+
1005
+ return false;
1006
+ })()
1007
+ };
1008
+
1009
+ (function () {
1010
+ JSZip.utils = {
1011
+ /**
1012
+ * Convert a string to a "binary string" : a string containing only char codes between 0 and 255.
1013
+ * @param {string} str the string to transform.
1014
+ * @return {String} the binary string.
1015
+ */
1016
+ string2binary : function (str) {
1017
+ var result = "";
1018
+ for (var i = 0; i < str.length; i++) {
1019
+ result += String.fromCharCode(str.charCodeAt(i) & 0xff);
1020
+ }
1021
+ return result;
1022
+ },
1023
+ /**
1024
+ * Create a Uint8Array from the string.
1025
+ * @param {string} str the string to transform.
1026
+ * @return {Uint8Array} the typed array.
1027
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1028
+ * @deprecated : use JSZip.utils.transformTo instead.
1029
+ */
1030
+ string2Uint8Array : function (str) {
1031
+ return JSZip.utils.transformTo("uint8array", str);
1032
+ },
1033
+
1034
+ /**
1035
+ * Create a string from the Uint8Array.
1036
+ * @param {Uint8Array} array the array to transform.
1037
+ * @return {string} the string.
1038
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1039
+ * @deprecated : use JSZip.utils.transformTo instead.
1040
+ */
1041
+ uint8Array2String : function (array) {
1042
+ return JSZip.utils.transformTo("string", array);
1043
+ },
1044
+ /**
1045
+ * Create a blob from the given ArrayBuffer.
1046
+ * @param {ArrayBuffer} buffer the buffer to transform.
1047
+ * @return {Blob} the result.
1048
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1049
+ */
1050
+ arrayBuffer2Blob : function (buffer) {
1051
+ JSZip.utils.checkSupport("blob");
1052
+
1053
+ try {
1054
+ // Blob constructor
1055
+ return new Blob([buffer], { type: "application/zip" });
1056
+ }
1057
+ catch(e) {}
1058
+
1059
+ try {
1060
+ // deprecated, browser only, old way
1061
+ var builder = new (window.BlobBuilder || window.WebKitBlobBuilder ||
1062
+ window.MozBlobBuilder || window.MSBlobBuilder)();
1063
+ builder.append(buffer);
1064
+ return builder.getBlob('application/zip');
1065
+ }
1066
+ catch(e) {}
1067
+
1068
+ // well, fuck ?!
1069
+ throw new Error("Bug : can't construct the Blob.");
1070
+ },
1071
+ /**
1072
+ * Create a blob from the given string.
1073
+ * @param {string} str the string to transform.
1074
+ * @return {Blob} the result.
1075
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1076
+ */
1077
+ string2Blob : function (str) {
1078
+ var buffer = JSZip.utils.transformTo("arraybuffer", str);
1079
+ return JSZip.utils.arrayBuffer2Blob(buffer);
1080
+ }
1081
+ };
1082
+
1083
+ /**
1084
+ * The identity function.
1085
+ * @param {Object} input the input.
1086
+ * @return {Object} the same input.
1087
+ */
1088
+ function identity(input) {
1089
+ return input;
1090
+ };
1091
+
1092
+ /**
1093
+ * Fill in an array with a string.
1094
+ * @param {String} str the string to use.
1095
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).
1096
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.
1097
+ */
1098
+ function stringToArrayLike(str, array) {
1099
+ for (var i = 0; i < str.length; ++i) {
1100
+ array[i] = str.charCodeAt(i) & 0xFF;
1101
+ }
1102
+ return array;
1103
+ };
1104
+
1105
+ /**
1106
+ * Transform an array-like object to a string.
1107
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.
1108
+ * @return {String} the result.
1109
+ */
1110
+ function arrayLikeToString(array) {
1111
+ // Performances notes :
1112
+ // --------------------
1113
+ // String.fromCharCode.apply(null, array) is the fastest, see
1114
+ // see http://jsperf.com/converting-a-uint8array-to-a-string/2
1115
+ // but the stack is limited (and we can get huge arrays !).
1116
+ //
1117
+ // result += String.fromCharCode(array[i]); generate too many strings !
1118
+ //
1119
+ // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2
1120
+ var chunk = 65536;
1121
+ var result = [], len = array.length, type = JSZip.utils.getTypeOf(array), k = 0;
1122
+
1123
+ while (k < len && chunk > 1) {
1124
+ try {
1125
+ if (type === "array" || type === "nodebuffer") {
1126
+ result.push(String.fromCharCode.apply(null, array.slice(k, Math.max(k + chunk, len))));
1127
+ } else {
1128
+ result.push(String.fromCharCode.apply(null, array.subarray(k, k + chunk)));
1129
+ }
1130
+ k += chunk;
1131
+ } catch (e) {
1132
+ chunk = Math.floor(chunk / 2);
1133
+ }
1134
+ }
1135
+ return result.join("");
1136
+ };
1137
+
1138
+ /**
1139
+ * Copy the data from an array-like to an other array-like.
1140
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.
1141
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.
1142
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.
1143
+ */
1144
+ function arrayLikeToArrayLike(arrayFrom, arrayTo) {
1145
+ for(var i = 0; i < arrayFrom.length; i++) {
1146
+ arrayTo[i] = arrayFrom[i];
1147
+ }
1148
+ return arrayTo;
1149
+ };
1150
+
1151
+ // a matrix containing functions to transform everything into everything.
1152
+ var transform = {};
1153
+
1154
+ // string to ?
1155
+ transform["string"] = {
1156
+ "string" : identity,
1157
+ "array" : function (input) {
1158
+ return stringToArrayLike(input, new Array(input.length));
1159
+ },
1160
+ "arraybuffer" : function (input) {
1161
+ return transform["string"]["uint8array"](input).buffer;
1162
+ },
1163
+ "uint8array" : function (input) {
1164
+ return stringToArrayLike(input, new Uint8Array(input.length));
1165
+ },
1166
+ "nodebuffer" : function (input) {
1167
+ return stringToArrayLike(input, new Buffer(input.length));
1168
+ }
1169
+ };
1170
+
1171
+ // array to ?
1172
+ transform["array"] = {
1173
+ "string" : arrayLikeToString,
1174
+ "array" : identity,
1175
+ "arraybuffer" : function (input) {
1176
+ return (new Uint8Array(input)).buffer;
1177
+ },
1178
+ "uint8array" : function (input) {
1179
+ return new Uint8Array(input);
1180
+ },
1181
+ "nodebuffer" : function (input) {
1182
+ return new Buffer(input);
1183
+ }
1184
+ };
1185
+
1186
+ // arraybuffer to ?
1187
+ transform["arraybuffer"] = {
1188
+ "string" : function (input) {
1189
+ return arrayLikeToString(new Uint8Array(input));
1190
+ },
1191
+ "array" : function (input) {
1192
+ return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
1193
+ },
1194
+ "arraybuffer" : identity,
1195
+ "uint8array" : function (input) {
1196
+ return new Uint8Array(input);
1197
+ },
1198
+ "nodebuffer" : function (input) {
1199
+ return new Buffer(new Uint8Array(input));
1200
+ }
1201
+ };
1202
+
1203
+ // uint8array to ?
1204
+ transform["uint8array"] = {
1205
+ "string" : arrayLikeToString,
1206
+ "array" : function (input) {
1207
+ return arrayLikeToArrayLike(input, new Array(input.length));
1208
+ },
1209
+ "arraybuffer" : function (input) {
1210
+ return input.buffer;
1211
+ },
1212
+ "uint8array" : identity,
1213
+ "nodebuffer" : function(input) {
1214
+ return new Buffer(input);
1215
+ }
1216
+ };
1217
+
1218
+ // nodebuffer to ?
1219
+ transform["nodebuffer"] = {
1220
+ "string" : arrayLikeToString,
1221
+ "array" : function (input) {
1222
+ return arrayLikeToArrayLike(input, new Array(input.length));
1223
+ },
1224
+ "arraybuffer" : function (input) {
1225
+ return transform["nodebuffer"]["uint8array"](input).buffer;
1226
+ },
1227
+ "uint8array" : function (input) {
1228
+ return arrayLikeToArrayLike(input, new Uint8Array(input.length));
1229
+ },
1230
+ "nodebuffer" : identity
1231
+ };
1232
+
1233
+ /**
1234
+ * Transform an input into any type.
1235
+ * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer.
1236
+ * If no output type is specified, the unmodified input will be returned.
1237
+ * @param {String} outputType the output type.
1238
+ * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.
1239
+ * @throws {Error} an Error if the browser doesn't support the requested output type.
1240
+ */
1241
+ JSZip.utils.transformTo = function (outputType, input) {
1242
+ if (!input) {
1243
+ // undefined, null, etc
1244
+ // an empty string won't harm.
1245
+ input = "";
1246
+ }
1247
+ if (!outputType) {
1248
+ return input;
1249
+ }
1250
+ JSZip.utils.checkSupport(outputType);
1251
+ var inputType = JSZip.utils.getTypeOf(input);
1252
+ var result = transform[inputType][outputType](input);
1253
+ return result;
1254
+ };
1255
+
1256
+ /**
1257
+ * Return the type of the input.
1258
+ * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
1259
+ * @param {Object} input the input to identify.
1260
+ * @return {String} the (lowercase) type of the input.
1261
+ */
1262
+ JSZip.utils.getTypeOf = function (input) {
1263
+ if (typeof input === "string") {
1264
+ return "string";
1265
+ }
1266
+ if (input instanceof Array) {
1267
+ return "array";
1268
+ }
1269
+ if (JSZip.support.nodebuffer && Buffer.isBuffer(input)) {
1270
+ return "nodebuffer";
1271
+ }
1272
+ if (JSZip.support.uint8array && input instanceof Uint8Array) {
1273
+ return "uint8array";
1274
+ }
1275
+ if (JSZip.support.arraybuffer && input instanceof ArrayBuffer) {
1276
+ return "arraybuffer";
1277
+ }
1278
+ };
1279
+
1280
+ /**
1281
+ * Throw an exception if the type is not supported.
1282
+ * @param {String} type the type to check.
1283
+ * @throws {Error} an Error if the browser doesn't support the requested type.
1284
+ */
1285
+ JSZip.utils.checkSupport = function (type) {
1286
+ var supported = true;
1287
+ switch (type.toLowerCase()) {
1288
+ case "uint8array":
1289
+ supported = JSZip.support.uint8array;
1290
+ break;
1291
+ case "arraybuffer":
1292
+ supported = JSZip.support.arraybuffer;
1293
+ break;
1294
+ case "nodebuffer":
1295
+ supported = JSZip.support.nodebuffer;
1296
+ break;
1297
+ case "blob":
1298
+ supported = JSZip.support.blob;
1299
+ break;
1300
+ }
1301
+ if (!supported) {
1302
+ throw new Error(type + " is not supported by this browser");
1303
+ }
1304
+ };
1305
+
1306
+
1307
+ })();
1308
+
1309
+ (function (){
1310
+ /**
1311
+ * Represents an entry in the zip.
1312
+ * The content may or may not be compressed.
1313
+ * @constructor
1314
+ */
1315
+ JSZip.CompressedObject = function () {
1316
+ this.compressedSize = 0;
1317
+ this.uncompressedSize = 0;
1318
+ this.crc32 = 0;
1319
+ this.compressionMethod = null;
1320
+ this.compressedContent = null;
1321
+ };
1322
+
1323
+ JSZip.CompressedObject.prototype = {
1324
+ /**
1325
+ * Return the decompressed content in an unspecified format.
1326
+ * The format will depend on the decompressor.
1327
+ * @return {Object} the decompressed content.
1328
+ */
1329
+ getContent : function () {
1330
+ return null; // see implementation
1331
+ },
1332
+ /**
1333
+ * Return the compressed content in an unspecified format.
1334
+ * The format will depend on the compressed conten source.
1335
+ * @return {Object} the compressed content.
1336
+ */
1337
+ getCompressedContent : function () {
1338
+ return null; // see implementation
1339
+ }
1340
+ };
1341
+ })();
1342
+
1343
+ /**
1344
+ *
1345
+ * Base64 encode / decode
1346
+ * http://www.webtoolkit.info/
1347
+ *
1348
+ * Hacked so that it doesn't utf8 en/decode everything
1349
+ **/
1350
+ JSZip.base64 = (function() {
1351
+ // private property
1352
+ var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
1353
+
1354
+ return {
1355
+ // public method for encoding
1356
+ encode : function(input, utf8) {
1357
+ var output = "";
1358
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
1359
+ var i = 0;
1360
+
1361
+ while (i < input.length) {
1362
+
1363
+ chr1 = input.charCodeAt(i++);
1364
+ chr2 = input.charCodeAt(i++);
1365
+ chr3 = input.charCodeAt(i++);
1366
+
1367
+ enc1 = chr1 >> 2;
1368
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
1369
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
1370
+ enc4 = chr3 & 63;
1371
+
1372
+ if (isNaN(chr2)) {
1373
+ enc3 = enc4 = 64;
1374
+ } else if (isNaN(chr3)) {
1375
+ enc4 = 64;
1376
+ }
1377
+
1378
+ output = output +
1379
+ _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
1380
+ _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
1381
+
1382
+ }
1383
+
1384
+ return output;
1385
+ },
1386
+
1387
+ // public method for decoding
1388
+ decode : function(input, utf8) {
1389
+ var output = "";
1390
+ var chr1, chr2, chr3;
1391
+ var enc1, enc2, enc3, enc4;
1392
+ var i = 0;
1393
+
1394
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
1395
+
1396
+ while (i < input.length) {
1397
+
1398
+ enc1 = _keyStr.indexOf(input.charAt(i++));
1399
+ enc2 = _keyStr.indexOf(input.charAt(i++));
1400
+ enc3 = _keyStr.indexOf(input.charAt(i++));
1401
+ enc4 = _keyStr.indexOf(input.charAt(i++));
1402
+
1403
+ chr1 = (enc1 << 2) | (enc2 >> 4);
1404
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
1405
+ chr3 = ((enc3 & 3) << 6) | enc4;
1406
+
1407
+ output = output + String.fromCharCode(chr1);
1408
+
1409
+ if (enc3 != 64) {
1410
+ output = output + String.fromCharCode(chr2);
1411
+ }
1412
+ if (enc4 != 64) {
1413
+ output = output + String.fromCharCode(chr3);
1414
+ }
1415
+
1416
+ }
1417
+
1418
+ return output;
1419
+
1420
+ }
1421
+ };
1422
+ }());
1423
+
1424
+ // enforcing Stuk's coding style
1425
+ // vim: set shiftwidth=3 softtabstop=3: