@@ -31,6 +31,14 @@ const EXTERNAL_DECK_ID = '__external__';
3131 */
3232const isUrl = value => / ^ h t t p s ? : \/ \/ / . test ( value ) || value . startsWith ( '/' ) || value . startsWith ( './' ) ;
3333
34+ // Resolve a relative URL against document.referrer (iframe) or window.location.href
35+ const resolveUrl = url => {
36+ if ( ! url ) return url ;
37+ if ( / ^ h t t p s ? : \/ \/ / . test ( url ) ) return url ;
38+ const base = document . referrer || window . location . href ;
39+ return new URL ( url , base ) . href ;
40+ } ;
41+
3442const ProjectFileHOC = function ( WrappedComponent ) {
3543 class ProjectFileComponent extends React . Component {
3644 constructor ( props ) {
@@ -46,16 +54,17 @@ const ProjectFileHOC = function (WrappedComponent) {
4654 if ( queryParams . project ) {
4755 const value = queryParams . project ;
4856 if ( isUrl ( value ) ) {
49- this . setState ( { projectFileUrl : value } ) ;
50- if ( value . endsWith ( '.sb3' ) ) {
57+ const resolvedValue = resolveUrl ( value ) ;
58+ this . setState ( { projectFileUrl : resolvedValue } ) ;
59+ if ( resolvedValue . endsWith ( '.sb3' ) ) {
5160 // Claim the loading state to prevent the default project from loading
5261 this . props . onRequestProjectUpload ( this . props . loadingState ) ;
53- this . props . onSetProjectFile ( { sb3 : value , title : '' } ) ;
62+ this . props . onSetProjectFile ( { sb3 : resolvedValue , title : '' } ) ;
5463 if ( this . props . vm ) {
55- this . loadSb3 ( value ) ;
64+ this . loadSb3 ( resolvedValue ) ;
5665 }
5766 } else {
58- this . loadProjectFile ( value ) ;
67+ this . loadProjectFile ( resolvedValue ) ;
5968 }
6069 } else {
6170 // Treat as base64-encoded JSON
@@ -65,6 +74,22 @@ const ProjectFileHOC = function (WrappedComponent) {
6574 if ( ! projectFile . title || typeof projectFile . title !== 'string' ) {
6675 throw new Error ( 'Project file must have a "title" string field' ) ;
6776 }
77+ // Resolve relative URLs against referrer when in an iframe
78+ if ( projectFile . sb3 ) {
79+ projectFile . sb3 = resolveUrl ( projectFile . sb3 ) ;
80+ }
81+ if ( Array . isArray ( projectFile . steps ) ) {
82+ projectFile . steps = projectFile . steps . map ( step => {
83+ const resolved = Object . assign ( { } , step ) ;
84+ if ( resolved . image ) {
85+ resolved . image = resolveUrl ( resolved . image ) ;
86+ }
87+ if ( resolved . video ) {
88+ resolved . video = resolveUrl ( resolved . video ) ;
89+ }
90+ return resolved ;
91+ } ) ;
92+ }
6893 this . props . onSetProjectFile ( projectFile ) ;
6994 if ( projectFile . sb3 && this . props . vm ) {
7095 this . loadSb3 ( projectFile . sb3 ) ;
0 commit comments