I have the following two files:
index.html
Web Page
For chrome you still need --allow-file-access-from-files
(and I recommend installing a separate chrome and using it solely for these projects to stay secure), but just shim fetch()
for XMLHttpRequest
for file://
requests:
if (/^file:\/\/\//.test(location.href)) {
let path = './';
let orig = fetch;
window.fetch = (resource) => ((/^[^/:]*:/.test(resource)) ?
orig(resource) :
new Promise(function(resolve, reject) {
let request = new XMLHttpRequest();
let fail = (error) => {reject(error)};
['error', 'abort'].forEach((event) => { request.addEventListener(event, fail); });
let pull = (expected) => (new Promise((resolve, reject) => {
if (
request.responseType == expected ||
(expected == 'text' && !request.responseType)
)
resolve(request.response);
else
reject(request.responseType);
}));
request.addEventListener('load', () => (resolve({
arrayBuffer : () => (pull('arraybuffer')),
blob : () => (pull('blob')),
text : () => (pull('text')),
json : () => (pull('json'))
})));
request.open('GET', resource.replace(/^\//, path));
request.send();
})
);
}
This shim will;
if
statement),fetch()
for any url that doesn't specify protocol (and thus non-file://
requests), and/root/bob.html
) with ones relative to the current path (since that would dangerously evaluate to C:\
or equivalent)Set path
to something else if your index.html
isn't actually at the root for the project.
If you need support for init, or anything other than text()
, you'll need to add it.
Explicit file://
requests wont be fulfilled, that's on purpose, but if you really do know what you're doing, you'll know how to make this work for you, and if you don't you shouldn't.
The following is useful if you're going to be doing this for multiple files. Swap out './'
for document.currentScript.getAttribute('data-root')
. Now you can put that snippet into its own file, say filesystemHelper.js
, and call like so in the various files:
<script src="../filesystemHelper.js" data-root="../"></script>
Pretty snazzy.