Skip to content
This repository was archived by the owner on May 7, 2025. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions plugins/ResourceFetcherPlugin/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

// This is a sample implementation of a resource fetcher plugin. It is intended to show how a resource fetcher plugin might be written.
// This plugin uses an ajax call to call to a service to get the contents of a resource.
//
// It's based on a plugin used at Bibliotheca to get the contents of an epub from a server. I've edited this file to remove
// some functionality specific to Bibliotheca. The result may or may not be suitiable for your needs.

define(['readium_js_plugins', 'readium_shared_js/globals', '../../../js/epub-fetch/discover_content_type' ],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

../../../js/epub-fetch/discover_content_type
https://github.com/readium/readium-js/blob/develop/js/epub-fetch/discover_content_type.js

This reference is problematic, because code in readium-shared-js cannot make assumptions about its integration context. This dependency injection assumes that readium-js is the parent repository (that readium-shared-js is a submodule). ReadiumSDK-based native apps also make use of readium-shared-js, but have absolutely zero-awareness of readium-js.

Now, this issue is mitigated by the fact that in practice, the ResourceFetcherPlugin would only ever be used in the context of an app that relies on readium-js. But generally-speaking, there is definitely a problem in readium-shared-js plugins having dependencies from external RequireJS namespaces (../../../js/epub-fetch/discover_content_type is of course equivalent to readium_js/epub-fetch/discover_content_type, but this syntax would only work when building from readium-js or readium-js-viewer, not from within readium-shared-js).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS: the point I am making here is that Readium "plugins" were originally designed (minimally) for usage within the readium-shared-js scope. So some architectural hacks are required to implement plugins for readium-js, etc.
@jccr

function (Plugins, Globals,ContentTypeDiscovery) {
var config = {};
Plugins.register("ResourceFetcherPlugin", function (api) {

api.plugin.CustomResourceFetcher = function(parentFetcher){
var ebookURL = parentFetcher.getEbookURL();
var ebookURL_filepath = parentFetcher.getEbookURL_FilePath();

var self = this;

// INTERNAL FUNCTIONS
// PUBLIC API
this.shouldConstructDomProgrammatically = function() { return true; }
this.resolveURI = function (pathRelativeToPackageRoot) {
var pathRelativeToPackageRootUri = undefined;
try {
pathRelativeToPackageRootUri = new URI(pathRelativeToPackageRoot);
} catch(err) {
console.error(err);
console.log(pathRelativeToPackageRoot);
}
if (pathRelativeToPackageRootUri && pathRelativeToPackageRootUri.is("absolute")) return pathRelativeToPackageRoot; //pathRelativeToPackageRootUri.scheme() == "http://", "https://", "data:", etc.


var url = ebookURL_filepath;
try {
//url = new URI(relativeUrl).absoluteTo(url).search('').hash('').toString();
url = new URI(url).search('').hash('').toString();
} catch(err) {
console.error(err);
console.log(url);
}

return url + (url.charAt(url.length-1) == '/' ? "" : "/") + pathRelativeToPackageRoot;
};

this.fetchFileContents = function(pathRelativeToPackageRoot, isText, fetchCallback, onerror) {
var body={};
var config={ };

var success = function(data, textStatus, jqXHR) {
ReadiumSDK.emit('ResourceFetcher-Success', data, pathRelativeToPackageRoot, body, config);
fetchCallback(data);
};

var error = function (xhr, status, errorThrown, self) {
onerror(new Error(errorThrown));
}

// Hook; someone can listen for this event and modify the config object before the ajax call.
ReadiumSDK.emit('ResourceFetcher-BeforeFetchFileContents', pathRelativeToPackageRoot, isText, config, success,error);
config.isText=isText;

var ajaxArguments ={
retryCount: 0,
isText: isText,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
url: config.url,
type: 'POST',
dataType: 'json',
data: JSON.stringify(body),
success: success,
error: error
}

$.ajax(ajaxArguments);
};

this.fetchFileContentsText = function(pathRelativeToPackageRoot, fetchCallback, onerror) {
this.fetchFileContents(pathRelativeToPackageRoot, true, function (result) {
fetchCallback(result);
}, onerror);
};

this.fetchFileContentsBlob = function(pathRelativeToPackageRoot, fetchCallback, onerror) {
this.fetchFileContents(pathRelativeToPackageRoot, false, function(result) {
var contentType = ContentTypeDiscovery.identifyContentTypeFromFileName(pathRelativeToPackageRoot);
var bytes = new Uint8Array(result.length); for (var i=0; i<result.length; i++) bytes[i] = result.charCodeAt(i);
var blob = new Blob([bytes],{type: contentType});
fetchCallback(blob);
},onerror);
};

};
api.plugin.CustomResourceFetcher.openPackageDocument = function(ebookURL, callback, openPageRequest, openPackageDocument_) {
openPackageDocument_(ebookURL, callback, openPageRequest, '');
}
});

return config;
});