From b44e5a661e6bea2bdb95543acbb2fd6ead39ca8a Mon Sep 17 00:00:00 2001 From: Greggman Date: Mon, 31 Jan 2022 08:43:48 -0800 Subject: [PATCH] Fix Live Editor for r137 (#23373) This is a more generic fix than hardcoding checks for 'three'. Also fixes the export function. --- manual/examples/resources/editor-settings.js | 17 ++--- manual/examples/resources/editor.html | 3 - manual/examples/resources/editor.js | 74 +++++++++++++++++--- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/manual/examples/resources/editor-settings.js b/manual/examples/resources/editor-settings.js index 1f778e535f2d27..6ee47863056f5f 100644 --- a/manual/examples/resources/editor-settings.js +++ b/manual/examples/resources/editor-settings.js @@ -61,7 +61,7 @@ function fixSourceLinks(url, source) { const urlPropRE = /(url:\s*)('|")(.*?)('|")/g; const workerRE = /(new\s+Worker\s*\(\s*)('|")(.*?)('|")/g; const importScriptsRE = /(importScripts\s*\(\s*)('|")(.*?)('|")/g; - const moduleRE = /(import.*?)(?!'three')('|")(.*?)('|")/g; + const moduleRE = /(import.*?)('|")(.*?)('|")/g; const prefix = getPrefix(url); const rootPrefix = getRootPrefix(url); @@ -82,8 +82,9 @@ function fixSourceLinks(url, source) { function makeTaggedFDedQuotes(match, start, q1, url, q2, suffix) { return start + q1 + addPrefix(url) + q2 + suffix; } - function makeFDedQuotes(match, start, q1, url, q2) { - return start + q1 + addPrefix(url) + q2; + 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) => { @@ -105,7 +106,7 @@ function fixSourceLinks(url, source) { source = source.replace(importScriptsRE, makeLinkFDedQuotes); source = source.replace(loaderArrayLoadRE, makeArrayLinksFDed); source = source.replace(threejsUrlRE, makeTaggedFDedQuotes); - source = source.replace(moduleRE, makeFDedQuotes); + source = source.replace(moduleRE, makeFDedQuotesModule); return source; } @@ -130,8 +131,8 @@ let version; async function fixJSForCodeSite(js) { const moduleRE = /(import.*?)('|")(.*?)('|")/g; - // convert https://threejs.org/build/three.module.js -> https://cdn.skypack.dev/three@ - // convert https://threejs.org/examples/jsm/.?? -> https://cdn.skypack.dev/three@/examples/jsm/.?? + // convert https://threejs.org/build/three.module.js -> https://unpkg.com/three@ + // convert https://threejs.org/examples/jsm/.?? -> https://unpkg.com/three@/examples/jsm/.?? if (!version) { try { @@ -146,10 +147,10 @@ async function fixJSForCodeSite(js) { function addVersion(href) { if (href.startsWith(window.location.origin)) { if (href.includes('/build/three.module.js')) { - return `https://cdn.skypack.dev/three@${version}`; + return `https://unpkg.com/three@${version}`; } else if (href.includes('/examples/jsm/')) { const url = new URL(href); - return `https://cdn.skypack.dev/three@${version}${url.pathname}${url.search}${url.hash}`; + return `https://unpkg.com/three@${version}${url.pathname}${url.search}${url.hash}`; } } return href; diff --git a/manual/examples/resources/editor.html b/manual/examples/resources/editor.html index 334a73c9dcf86c..e9f8d3a9e5f833 100644 --- a/manual/examples/resources/editor.html +++ b/manual/examples/resources/editor.html @@ -190,9 +190,6 @@ border-bottom: none !important; border-top: 5px solid #666 !important; } -.button-export { - display: none; /* TODO: Fix export with import maps */ -} .button-result { margin-left: 2em !important; } diff --git a/manual/examples/resources/editor.js b/manual/examples/resources/editor.js index 6e03c2838b087b..4a28c42f8780cb 100644 --- a/manual/examples/resources/editor.js +++ b/manual/examples/resources/editor.js @@ -122,6 +122,26 @@ const htmlParts = { }, }; +function getRootPrefix(url) { + const u = new URL(url, window.location.href); + return u.origin; +} + +function removeDotDotSlash(href) { + // assumes a well formed URL. In other words: 'https://..//foo.html" is a bad URL and this code would fail. + const url = new URL(href, window.location.href); + const parts = url.pathname.split('/'); + for (;;) { + const dotDotNdx = parts.indexOf('..'); + if (dotDotNdx < 0) { + break; + } + parts.splice(dotDotNdx - 1, 2); + } + url.pathname = parts.join('/'); + return url.toString(); +} + function forEachHTMLPart(fn) { Object.keys(htmlParts).forEach(function(name, ndx) { const info = htmlParts[name]; @@ -201,10 +221,17 @@ async function getWorkerScripts(text, baseUrl, scriptInfos = {}) { return `${prefix}${quote}${fqURL}${quote}`; } + function replaceWithUUIDModule(match, prefix, quote, url) { + // modules are either relative, fully qualified, or a module name + // Skip it if it's a module name + return (url.startsWith('.') || url.includes('://')) + ? replaceWithUUID(match, prefix, quote, url) + : match.toString(); + } text = text.replace(workerRE, replaceWithUUID); text = text.replace(importScriptsRE, replaceWithUUID); - text = text.replace(importRE, replaceWithUUID); + text = text.replace(importRE, replaceWithUUIDModule); await Promise.all(newScripts.map((url) => { return getScript(url, scriptInfos); @@ -233,8 +260,8 @@ async function parseHTML(url, html) { const bodyRE = /([^]*?)<\/body>/i; const inlineScriptRE = /\n'); - html = html.replace('../../build/three.module.js', window.location.origin + '/build/three.module.js'); - html = extraHTMLParsing(html, htmlParts); let links = '';