( function () { // eslint-disable-line strict 'use strict'; // eslint-disable-line strict function dirname( path ) { const ndx = path.lastIndexOf( '/' ); return path.substring( 0, ndx + 1 ); } function getPrefix( url ) { const u = new URL( url, window.location.href ); const prefix = u.origin + dirname( u.pathname ); return prefix; } function getRootPrefix( url ) { const u = new URL( url, window.location.href ); return u.origin; } function removeDotDotSlash( url ) { // assumes a well formed URL. In other words: 'https://..//foo.html" is a bad URL and this code would fail. const parts = url.split( '/' ); for ( ;; ) { const dotDotNdx = parts.indexOf( '..' ); if ( dotDotNdx < 0 ) { break; } parts.splice( dotDotNdx - 1, 2 ); } const newUrl = parts.join( '/' ); return newUrl; } /** * Fix any local URLs into fully qualified urls. * * Examples: * resources/image.jpg -> https://domain.org/webgl/resouces/image.jpg * /3rdparty/lib.js -> https://domain.org/3rdparty/lib.js * * The reason is (a) we're running the code as via blobUrl and nothing is relative to a blob. * (b) we can upload to jsfiddle/codepen and so need to link back to the files. * * This is all kind of hacky in that it's just a bunch of regular expressions looking * for matches. * * @param {string} url The URL of the file source. * @param {string} source An HTML file or JavaScript file * @returns {string} the source after having urls fixed. */ function fixSourceLinks( url, source ) { const srcRE = /(src=)(")(.*?)(")()/g; const linkRE = /(href=)(")(.*?)(")()/g; const imageSrcRE = /((?:image|img)\.src = )(")(.*?)(")()/g; const loaderLoadRE = /(loader\.load[a-z]*\s*\(\s*)('|")(.*?)('|")/ig; const loaderArrayLoadRE = /(loader\.load[a-z]*\(\[)([\s\S]*?)(\])/ig; const loadFileRE = /(loadFile\s*\(\s*)('|")(.*?)('|")/ig; const threejsUrlRE = /(.*?)('|")([^"']*?)('|")([^'"]*?)(\/\*\s+threejs.org:\s+url\s+\*\/)/ig; const arrayLineRE = /^(\s*["|'])([\s\S]*?)(["|']*$)/; const urlPropRE = /(url:\s*)('|")(.*?)('|")/g; const workerRE = /(new\s+Worker\s*\(\s*)('|")(.*?)('|")/g; const importScriptsRE = /(importScripts\s*\(\s*)('|")(.*?)('|")/g; const moduleRE = /(import.*?)('|")(.*?)('|")/g; const prefix = getPrefix( url ); const rootPrefix = getRootPrefix( url ); function addCorrectPrefix( url ) { return ( url.startsWith( '/' ) ) ? `${rootPrefix}${url}` : removeDotDotSlash( ( prefix + url ).replace( /\/.\//g, '/' ) ); } function addPrefix( url ) { return url.indexOf( '://' ) < 0 && ! url.startsWith( 'data:' ) && url[ 0 ] !== '?' ? removeDotDotSlash( addCorrectPrefix( url ) ) : url; } function makeLinkFDedQuotes( match, fn, q1, url, q2 ) { return fn + q1 + addPrefix( url ) + q2; } function makeTaggedFDedQuotes( match, start, q1, url, q2, suffix ) { return start + q1 + addPrefix( url ) + q2 + suffix; } function makeFDedQuotesModule( match, start, q1, url, q2 ) { // modules require relative paths or fully qualified, otherwise they are module names return `${start}${q1}${url.startsWith( '.' ) ? addPrefix( url ) : url}${q2}`; } function makeArrayLinksFDed( match, prefix, arrayStr, suffix ) { const lines = arrayStr.split( ',' ).map( ( line ) => { const m = arrayLineRE.exec( line ); return m ? `${m[ 1 ]}${addPrefix( m[ 2 ] )}${m[ 3 ]}` : line; } ); return `${prefix}${lines.join( ',' )}${suffix}`; } source = source.replace( srcRE, makeTaggedFDedQuotes ); source = source.replace( linkRE, makeTaggedFDedQuotes ); source = source.replace( imageSrcRE, makeTaggedFDedQuotes ); source = source.replace( urlPropRE, makeLinkFDedQuotes ); source = source.replace( loadFileRE, makeLinkFDedQuotes ); source = source.replace( loaderLoadRE, makeLinkFDedQuotes ); source = source.replace( workerRE, makeLinkFDedQuotes ); source = source.replace( importScriptsRE, makeLinkFDedQuotes ); source = source.replace( loaderArrayLoadRE, makeArrayLinksFDed ); source = source.replace( threejsUrlRE, makeTaggedFDedQuotes ); source = source.replace( moduleRE, makeFDedQuotesModule ); return source; } /** * Called after parsing to give a change to update htmlParts * @param {string} html The main page html turned into a template with the