Better support for loading HTML pages plus some of their referenced content.

This commit is contained in:
Dan 2017-12-16 21:34:40 -08:00
parent d66c456cf1
commit c033769279
2 changed files with 61 additions and 6 deletions

View File

@ -39,3 +39,9 @@ browser.
### Production
TODO
### Compatibility
So far, this is only tested in Firefox 57 on Linux. If you have success or
issues on other browsers, please let me know.

View File

@ -2,25 +2,74 @@
const IPFS = require('ipfs')
function materialize_references_to_ipfs_content(node, element) {
// Given an IPFS node and a DOM element with a relevant attribute referring to content on IPFS,
// load that content and set it into the attribute as a blob.
//
// Return a promise for doing all of that.
// TODO: Support <div style="background-image: url(./styles/img/main/alpha-sunrise.png);"> rewriting.
for (let attribute_name of ['content', 'href', 'src']) {
let attribute_value = element.getAttribute(attribute_name)
if (attribute_value && attribute_value.startsWith('./')) {
let base_hash = window.location.pathname.match(/(^\/ipfs\/\w+)/)[1]
let uri = base_hash + attribute_value.slice(1)
let anchor = document.createElement('a')
anchor.href = uri
console.log('loading IPFS sub-content for ' + anchor.pathname)
return node.files.cat(anchor.pathname).then(function (contents_buffer) {
element.setAttribute(attribute_name, URL.createObjectURL(new Blob([contents_buffer])))
})
}
}
}
function App() {
let node
create()
function create() {
node = new IPFS()
node = new IPFS({
config: {
Addresses: {
Swarm: [
// '/dns4/wrtc-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star'
]
}
}
})
node.on('ready', () => {
console.log('IPFS node is ready')
console.log('loading IPFS content for ' + window.location.pathname)
// Load the page contents for the IPFS hash.
node.files.cat(window.location.pathname, (err, file) => {
if (err) { throw err }
var iframe = document.createElement('iframe')
node.files.cat(window.location.pathname)
.then(function (contents_buffer) {
let iframe = document.createElement('iframe')
iframe.style = 'width: 100%; height: 100%; border: 0; overflow: hidden'
iframe.src = URL.createObjectURL(new Blob([file]))
document.body.appendChild(iframe)
// TODO: Should only do this if it's actually an HTML document. Need to gracefully skip this for other content types.
let contents_document = new DOMParser().parseFromString(contents_buffer.toString(), 'text/html')
let elements = contents_document.querySelectorAll('link,meta,script')
let promises = []
for (let element of elements) {
promises.push(materialize_references_to_ipfs_content(node, element))
}
Promise.all(promises).then(function () {
iframe.src = URL.createObjectURL(
new Blob([
new XMLSerializer().serializeToString(contents_document)
])
)
document.body.appendChild(iframe)
})
})
})
}