mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-10-31 19:10:08 +00:00 
			
		
		
		
	
		
			
	
	
		
			248 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			248 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /*! FileSaver.js | ||
|  |  *  A saveAs() FileSaver implementation. | ||
|  |  *  2014-01-24 | ||
|  |  * | ||
|  |  *  By Eli Grey, http://eligrey.com
 | ||
|  |  *  License: X11/MIT | ||
|  |  *    See LICENSE.md | ||
|  |  */ | ||
|  | 
 | ||
|  | /*global self */ | ||
|  | /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ | ||
|  | 
 | ||
|  | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ | ||
|  | 
 | ||
|  | var saveAs = saveAs | ||
|  |   // IE 10+ (native saveAs)
 | ||
|  |   || (typeof navigator !== "undefined" && | ||
|  |       navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator)) | ||
|  |   // Everyone else
 | ||
|  |   || (function(view) { | ||
|  | 	"use strict"; | ||
|  | 	// IE <10 is explicitly unsupported
 | ||
|  | 	if (typeof navigator !== "undefined" && | ||
|  | 	    /MSIE [1-9]\./.test(navigator.userAgent)) { | ||
|  | 		return; | ||
|  | 	} | ||
|  | 	var | ||
|  | 		  doc = view.document | ||
|  | 		  // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
 | ||
|  | 		, get_URL = function() { | ||
|  | 			return view.URL || view.webkitURL || view; | ||
|  | 		} | ||
|  | 		, URL = view.URL || view.webkitURL || view | ||
|  | 		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") | ||
|  | 		, can_use_save_link = !view.externalHost && "download" in save_link | ||
|  | 		, click = function(node) { | ||
|  | 			var event = doc.createEvent("MouseEvents"); | ||
|  | 			event.initMouseEvent( | ||
|  | 				"click", true, false, view, 0, 0, 0, 0, 0 | ||
|  | 				, false, false, false, false, 0, null | ||
|  | 			); | ||
|  | 			node.dispatchEvent(event); | ||
|  | 		} | ||
|  | 		, webkit_req_fs = view.webkitRequestFileSystem | ||
|  | 		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem | ||
|  | 		, throw_outside = function(ex) { | ||
|  | 			(view.setImmediate || view.setTimeout)(function() { | ||
|  | 				throw ex; | ||
|  | 			}, 0); | ||
|  | 		} | ||
|  | 		, force_saveable_type = "application/octet-stream" | ||
|  | 		, fs_min_size = 0 | ||
|  | 		, deletion_queue = [] | ||
|  | 		, process_deletion_queue = function() { | ||
|  | 			var i = deletion_queue.length; | ||
|  | 			while (i--) { | ||
|  | 				var file = deletion_queue[i]; | ||
|  | 				if (typeof file === "string") { // file is an object URL
 | ||
|  | 					URL.revokeObjectURL(file); | ||
|  | 				} else { // file is a File
 | ||
|  | 					file.remove(); | ||
|  | 				} | ||
|  | 			} | ||
|  | 			deletion_queue.length = 0; // clear queue
 | ||
|  | 		} | ||
|  | 		, dispatch = function(filesaver, event_types, event) { | ||
|  | 			event_types = [].concat(event_types); | ||
|  | 			var i = event_types.length; | ||
|  | 			while (i--) { | ||
|  | 				var listener = filesaver["on" + event_types[i]]; | ||
|  | 				if (typeof listener === "function") { | ||
|  | 					try { | ||
|  | 						listener.call(filesaver, event || filesaver); | ||
|  | 					} catch (ex) { | ||
|  | 						throw_outside(ex); | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 		, FileSaver = function(blob, name) { | ||
|  | 			// First try a.download, then web filesystem, then object URLs
 | ||
|  | 			var | ||
|  | 				  filesaver = this | ||
|  | 				, type = blob.type | ||
|  | 				, blob_changed = false | ||
|  | 				, object_url | ||
|  | 				, target_view | ||
|  | 				, get_object_url = function() { | ||
|  | 					var object_url = get_URL().createObjectURL(blob); | ||
|  | 					deletion_queue.push(object_url); | ||
|  | 					return object_url; | ||
|  | 				} | ||
|  | 				, dispatch_all = function() { | ||
|  | 					dispatch(filesaver, "writestart progress write writeend".split(" ")); | ||
|  | 				} | ||
|  | 				// on any filesys errors revert to saving with object URLs
 | ||
|  | 				, fs_error = function() { | ||
|  | 					// don't create more object URLs than needed
 | ||
|  | 					if (blob_changed || !object_url) { | ||
|  | 						object_url = get_object_url(blob); | ||
|  | 					} | ||
|  | 					if (target_view) { | ||
|  | 						target_view.location.href = object_url; | ||
|  | 					} else { | ||
|  | 						window.open(object_url, "_blank"); | ||
|  | 					} | ||
|  | 					filesaver.readyState = filesaver.DONE; | ||
|  | 					dispatch_all(); | ||
|  | 				} | ||
|  | 				, abortable = function(func) { | ||
|  | 					return function() { | ||
|  | 						if (filesaver.readyState !== filesaver.DONE) { | ||
|  | 							return func.apply(this, arguments); | ||
|  | 						} | ||
|  | 					}; | ||
|  | 				} | ||
|  | 				, create_if_not_found = {create: true, exclusive: false} | ||
|  | 				, slice | ||
|  | 			; | ||
|  | 			filesaver.readyState = filesaver.INIT; | ||
|  | 			if (!name) { | ||
|  | 				name = "download"; | ||
|  | 			} | ||
|  | 			if (can_use_save_link) { | ||
|  | 				object_url = get_object_url(blob); | ||
|  | 				// FF for Android has a nasty garbage collection mechanism
 | ||
|  | 				// that turns all objects that are not pure javascript into 'deadObject'
 | ||
|  | 				// this means `doc` and `save_link` are unusable and need to be recreated
 | ||
|  | 				// `view` is usable though:
 | ||
|  | 				doc = view.document; | ||
|  | 				save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"); | ||
|  | 				save_link.href = object_url; | ||
|  | 				save_link.download = name; | ||
|  | 				var event = doc.createEvent("MouseEvents"); | ||
|  | 				event.initMouseEvent( | ||
|  | 					"click", true, false, view, 0, 0, 0, 0, 0 | ||
|  | 					, false, false, false, false, 0, null | ||
|  | 				); | ||
|  | 				save_link.dispatchEvent(event); | ||
|  | 				filesaver.readyState = filesaver.DONE; | ||
|  | 				dispatch_all(); | ||
|  | 				return; | ||
|  | 			} | ||
|  | 			// Object and web filesystem URLs have a problem saving in Google Chrome when
 | ||
|  | 			// viewed in a tab, so I force save with application/octet-stream
 | ||
|  | 			// http://code.google.com/p/chromium/issues/detail?id=91158
 | ||
|  | 			if (view.chrome && type && type !== force_saveable_type) { | ||
|  | 				slice = blob.slice || blob.webkitSlice; | ||
|  | 				blob = slice.call(blob, 0, blob.size, force_saveable_type); | ||
|  | 				blob_changed = true; | ||
|  | 			} | ||
|  | 			// Since I can't be sure that the guessed media type will trigger a download
 | ||
|  | 			// in WebKit, I append .download to the filename.
 | ||
|  | 			// https://bugs.webkit.org/show_bug.cgi?id=65440
 | ||
|  | 			if (webkit_req_fs && name !== "download") { | ||
|  | 				name += ".download"; | ||
|  | 			} | ||
|  | 			if (type === force_saveable_type || webkit_req_fs) { | ||
|  | 				target_view = view; | ||
|  | 			} | ||
|  | 			if (!req_fs) { | ||
|  | 				fs_error(); | ||
|  | 				return; | ||
|  | 			} | ||
|  | 			fs_min_size += blob.size; | ||
|  | 			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { | ||
|  | 				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { | ||
|  | 					var save = function() { | ||
|  | 						dir.getFile(name, create_if_not_found, abortable(function(file) { | ||
|  | 							file.createWriter(abortable(function(writer) { | ||
|  | 								writer.onwriteend = function(event) { | ||
|  | 									target_view.location.href = file.toURL(); | ||
|  | 									deletion_queue.push(file); | ||
|  | 									filesaver.readyState = filesaver.DONE; | ||
|  | 									dispatch(filesaver, "writeend", event); | ||
|  | 								}; | ||
|  | 								writer.onerror = function() { | ||
|  | 									var error = writer.error; | ||
|  | 									if (error.code !== error.ABORT_ERR) { | ||
|  | 										fs_error(); | ||
|  | 									} | ||
|  | 								}; | ||
|  | 								"writestart progress write abort".split(" ").forEach(function(event) { | ||
|  | 									writer["on" + event] = filesaver["on" + event]; | ||
|  | 								}); | ||
|  | 								writer.write(blob); | ||
|  | 								filesaver.abort = function() { | ||
|  | 									writer.abort(); | ||
|  | 									filesaver.readyState = filesaver.DONE; | ||
|  | 								}; | ||
|  | 								filesaver.readyState = filesaver.WRITING; | ||
|  | 							}), fs_error); | ||
|  | 						}), fs_error); | ||
|  | 					}; | ||
|  | 					dir.getFile(name, {create: false}, abortable(function(file) { | ||
|  | 						// delete file if it already exists
 | ||
|  | 						file.remove(); | ||
|  | 						save(); | ||
|  | 					}), abortable(function(ex) { | ||
|  | 						if (ex.code === ex.NOT_FOUND_ERR) { | ||
|  | 							save(); | ||
|  | 						} else { | ||
|  | 							fs_error(); | ||
|  | 						} | ||
|  | 					})); | ||
|  | 				}), fs_error); | ||
|  | 			}), fs_error); | ||
|  | 		} | ||
|  | 		, FS_proto = FileSaver.prototype | ||
|  | 		, saveAs = function(blob, name) { | ||
|  | 			return new FileSaver(blob, name); | ||
|  | 		} | ||
|  | 	; | ||
|  | 	FS_proto.abort = function() { | ||
|  | 		var filesaver = this; | ||
|  | 		filesaver.readyState = filesaver.DONE; | ||
|  | 		dispatch(filesaver, "abort"); | ||
|  | 	}; | ||
|  | 	FS_proto.readyState = FS_proto.INIT = 0; | ||
|  | 	FS_proto.WRITING = 1; | ||
|  | 	FS_proto.DONE = 2; | ||
|  | 
 | ||
|  | 	FS_proto.error = | ||
|  | 	FS_proto.onwritestart = | ||
|  | 	FS_proto.onprogress = | ||
|  | 	FS_proto.onwrite = | ||
|  | 	FS_proto.onabort = | ||
|  | 	FS_proto.onerror = | ||
|  | 	FS_proto.onwriteend = | ||
|  | 		null; | ||
|  | 
 | ||
|  | 	view.addEventListener("unload", process_deletion_queue, false); | ||
|  | 	saveAs.unload = function() { | ||
|  | 		process_deletion_queue(); | ||
|  | 		view.removeEventListener("unload", process_deletion_queue, false); | ||
|  | 	}; | ||
|  | 	return saveAs; | ||
|  | }( | ||
|  | 	   typeof self !== "undefined" && self | ||
|  | 	|| typeof window !== "undefined" && window | ||
|  | 	|| this.content | ||
|  | )); | ||
|  | // `self` is undefined in Firefox for Android content script context
 | ||
|  | // while `this` is nsIContentFrameMessageManager
 | ||
|  | // with an attribute `content` that corresponds to the window
 | ||
|  | 
 | ||
|  | if (typeof module !== "undefined") module.exports = saveAs; |