123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- ( 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 <style>, <script> and <body> parts extracted
- * @param {Object<string, HTMLPart>} htmlParts All the extracted parts
- * @return {string} The modified html template
- */
- function extraHTMLParsing( html /* , htmlParts */ ) {
- return html;
- }
- /**
- * Change JavaScript before uploading code to JSFiddle/Codepen
- *
- * @param {string} js JavaScript source
- * @returns {string} The JavaScript source with any fixes applied.
- */
- let version;
- async function fixJSForCodeSite( js ) {
- const moduleRE = /(import.*?)('|")(.*?)('|")/g;
- // convert https://threejs.org/build/three.module.js -> https://cdn.jsdelivr.net/npm/three@<version>
- // convert https://threejs.org/examples/jsm/.?? -> https://cdn.jsdelivr.net/npm/three@<version>/examples/jsm/.??
- if ( ! version ) {
- try {
- const res = await fetch( 'https://raw.githubusercontent.com/mrdoob/three.js/master/package.json' );
- const json = await res.json();
- version = json.version;
- } catch ( e ) {
- console.error( e );
- }
- }
- function addVersion( href ) {
- if ( href.startsWith( window.location.origin ) ) {
- if ( href.includes( '/build/three.module.js' ) ) {
- return `https://cdn.jsdelivr.net/npm/three@${version}`;
- } else if ( href.includes( '/examples/jsm/' ) ) {
- const url = new URL( href );
- return `https://cdn.jsdelivr.net/npm/three@${version}${url.pathname}${url.search}${url.hash}`;
- }
- }
- return href;
- }
- function addVersionToURL( match, start, q1, url, q2 ) {
- return start + q1 + addVersion( url ) + q2;
- }
- if ( version !== undefined ) {
- js = js.replace( moduleRE, addVersionToURL );
- }
- return js;
- }
- window.lessonEditorSettings = {
- extraHTMLParsing,
- fixSourceLinks,
- fixJSForCodeSite,
- runOnResize: false,
- lessonSettings: {
- glDebug: false,
- },
- tags: [ 'three.js' ],
- name: 'three.js',
- icon: '/files/icon.svg',
- };
- }() );
|