Repository navigation
Expand file tree
/
Copy pathBrowserStaticServer.js
More file actions
1 lines (1 loc) · 15.8 KB
/
Copy pathBrowserStaticServer.js
File metadata and controls
1 lines (1 loc) · 15.8 KB
1
define(function(require,exports,module){const BaseServer=require("LiveDevelopment/Servers/BaseServer").BaseServer,LiveDevelopmentUtils=require("LiveDevelopment/LiveDevelopmentUtils"),LiveDevelopment=require("LiveDevelopment/main"),LiveDevProtocol=require("LiveDevelopment/MultiBrowserImpl/protocol/LiveDevProtocol"),marked=require("thirdparty/marked.min"),DocumentManager=require("document/DocumentManager"),Mustache=require("thirdparty/mustache/mustache"),FileSystem=require("filesystem/FileSystem"),EventDispatcher=require("utils/EventDispatcher"),StringUtils=require("utils/StringUtils"),EventManager=require("utils/EventManager"),LivePreviewSettings=require("./LivePreviewSettings"),ProjectManager=require("project/ProjectManager"),Strings=require("strings"),utils=require("./utils"),LivePreviewTabs=require("./LivePreviewTabs"),BootstrapCSSText=require("text!thirdparty/bootstrap/bootstrap.min.css"),GithubCSSText=require("text!thirdparty/highlight.js/styles/github.min.css"),HilightJSText=require("text!thirdparty/highlight.js/highlight.min.js"),GFMCSSText=require("text!thirdparty/gfm.min.css"),markdownHTMLTemplate=require("text!./markdown.html"),redirectionHTMLTemplate=require("text!./redirectPage.html"),EVENT_GET_PHOENIX_INSTANCE_ID="GET_PHOENIX_INSTANCE_ID",EVENT_GET_CONTENT="GET_CONTENT",EVENT_TAB_ONLINE="TAB_ONLINE",EVENT_REPORT_ERROR="REPORT_ERROR",EVENT_UPDATE_TITLE_ICON="UPDATE_TITLE_AND_ICON",EVENT_EMBEDDED_IFRAME_ESCAPE_PRESS="embeddedEscapeKeyPressed",EVENT_SERVER_READY="SERVER_READY";EventDispatcher.makeEventDispatcher(exports);const livePreviewTabs=LivePreviewTabs.livePreviewTabs,PHCODE_LIVE_PREVIEW_QUERY_PARAM="phcodeLivePreview";let navigatorChannel;const NAVIGATOR_CHANNEL_ID=`live-preview-loader-${Phoenix.PHOENIX_INSTANCE_ID}`;let livePreviewChannel;const LIVE_PREVIEW_MESSENGER_CHANNEL=`live-preview-messenger-${Phoenix.PHOENIX_INSTANCE_ID}`,LIVE_PREVIEW_BROADCAST_CHANNEL_ID=`${Phoenix.PHOENIX_INSTANCE_ID}_livePreview`;let _staticServerInstance,$livepreviewServerIframe;const LIVE_PREVIEW_STATIC_SERVER_BASE_URL="https://phcode.live/",PREVIEW_BASE_URL=`${LIVE_PREVIEW_STATIC_SERVER_BASE_URL}vfs/PHOENIX_LIVE_PREVIEW_${Phoenix.PHOENIX_INSTANCE_ID}`,BASE_URL_PATH_PREFIX=`/vfs/PHOENIX_LIVE_PREVIEW_${Phoenix.PHOENIX_INSTANCE_ID}`;function getLivePreviewNotSupportedURL(){return`${window.Phoenix.baseURL}assets/phoenix-splash/live-preview-error.html?mainHeading=`+encodeURIComponent(`${Strings.DESCRIPTION_LIVEDEV_MAIN_HEADING}`)+"&mainSpan="+encodeURIComponent(`${Strings.DESCRIPTION_LIVEDEV_MAIN_SPAN}`)}function getNoPreviewURL(heading=Strings.DESCRIPTION_LIVEDEV_NO_PREVIEW,message=Strings.DESCRIPTION_LIVEDEV_NO_PREVIEW_DETAILS){return`${window.Phoenix.baseURL}assets/phoenix-splash/no-preview.html?jsonInput=`+encodeURIComponent(`{"heading":"${heading}",`+`"details":"${message}"}`)}function getMdviewrURL(){return`${window.Phoenix.baseURL}mdViewer/index.html`}function _isLivePreviewSupported(){return Phoenix.isNativeApp||!(Phoenix.browser.desktop.isSafari||Phoenix.browser.mobile.isIos)}let _lastPreviewedFilePath,currentPopoutURL;async function getPreviewDetails(){return new Promise(async(resolve,reject)=>{try{if(!_isLivePreviewSupported())return void resolve({URL:getLivePreviewNotSupportedURL(),isNoPreview:!0});const projectRoot=ProjectManager.getProjectRoot().fullPath,projectRootUrl=`${PREVIEW_BASE_URL}${projectRoot}`,currentDocument=DocumentManager.getCurrentDocument(),currentFile=currentDocument?currentDocument.file:ProjectManager.getSelectedItem();if(currentFile){let fullPath=currentFile.fullPath,httpFilePath=null;(fullPath.startsWith("http://")||fullPath.startsWith("https://"))&&(httpFilePath=fullPath);const customServeURL=LivePreviewSettings.getCustomServerConfig(fullPath),shouldUseInbuiltPreview=utils.isMarkdownFile(fullPath)||utils.isSVG(fullPath);if(customServeURL){const relativePath=path.relative(projectRoot,fullPath);return void resolve({URL:customServeURL,filePath:relativePath,fullPath:fullPath,isMarkdownFile:utils.isMarkdownFile(fullPath),isHTMLFile:utils.isHTMLFile(fullPath),isCustomServer:!0,serverSupportsHotReload:LivePreviewSettings.serverSupportsHotReload()})}if(LivePreviewSettings.isUsingCustomServer()&&!customServeURL&&!shouldUseInbuiltPreview)return void resolve({URL:getNoPreviewURL(Strings.DESCRIPTION_LIVEDEV_EXCLUDED,StringUtils.format(Strings.DESCRIPTION_LIVEDEV_NO_PREVIEW_EXCLUDED,LivePreviewSettings.getCustomServeRoot())),isNoPreview:!0});utils.isPreviewableFile(fullPath)&&(_lastPreviewedFilePath=fullPath);let fileExists=await FileSystem.existsAsync(_lastPreviewedFilePath);if(_lastPreviewedFilePath&&fileExists){const filePath=httpFilePath||path.relative(projectRoot,_lastPreviewedFilePath);let URL;return void resolve({URL:httpFilePath||`${projectRootUrl}${filePath}`,filePath:filePath,fullPath:_lastPreviewedFilePath,isMarkdownFile:utils.isMarkdownFile(_lastPreviewedFilePath),isHTMLFile:utils.isHTMLFile(_lastPreviewedFilePath)})}}resolve({URL:getNoPreviewURL(),isNoPreview:!0})}catch(e){reject(e)}})}function _initNavigatorChannel(){(navigatorChannel=new BroadcastChannel(NAVIGATOR_CHANNEL_ID)).onmessage=(event=>{window.logger.livePreview.log("Live Preview navigator channel: Phoenix received event from tab: ",event);const type=event.data.type;switch(type){case"GET_INITIAL_URL":return void _sendInitialURL(event.data.pageLoaderID);case"TAB_LOADER_ONLINE":return void LivePreviewTabs.tabOnline(event.data.pageLoaderID,event.data.URL,!0);default:return}})}function _sendToLivePreviewServerTabs(data,pageLoaderID=null){livePreviewChannel.postMessage({pageLoaderID:pageLoaderID,data:data})}function _initLivePreviewChannel(){(livePreviewChannel=new BroadcastChannel(LIVE_PREVIEW_MESSENGER_CHANNEL)).onmessage=(event=>{window.logger.livePreview.log("StaticServer: Live Preview message channel Phoenix recvd:",event);const pageLoaderID=event.data.pageLoaderID,data=event.data.data,eventName=data.eventName,message=data.message;switch(eventName){case EVENT_GET_PHOENIX_INSTANCE_ID:return void _sendToLivePreviewServerTabs({type:"PHOENIX_INSTANCE_ID",PHOENIX_INSTANCE_ID:Phoenix.PHOENIX_INSTANCE_ID},pageLoaderID);case EVENT_GET_CONTENT:return void getContent(message.path,message.url).then(response=>{response.type="REQUEST_RESPONSE",response.requestID=message.requestID,_sendToLivePreviewServerTabs(response,pageLoaderID)}).catch(console.error);case EVENT_TAB_ONLINE:return void LivePreviewTabs.tabOnline(message.clientID,message.URL);case EVENT_REPORT_ERROR:return void logger.reportError(new Error(message));case"BROWSER_CONNECT":return LivePreviewTabs.tabConnected(message.clientID,message.url),void exports.trigger(eventName,{data:data});case"BROWSER_CLOSE":return LivePreviewTabs.dropTab(message.clientID),void exports.trigger(eventName,{data:data});default:exports.trigger(eventName,{data:data})}})}function StaticServer(config){this._baseUrl=PREVIEW_BASE_URL,this._getInstrumentedContent=this._getInstrumentedContent.bind(this),BaseServer.call(this,config)}function _getMarkdown(fullPath){return new Promise((resolve,reject)=>{DocumentManager.getDocumentForPath(fullPath).done(function(doc){let text=doc.getText();text=text.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/,"");let markdownHtml,templateVars={markdownContent:marked.parse(text),BOOTSTRAP_LIB_CSS:BootstrapCSSText,HIGHLIGHT_JS_CSS:GithubCSSText,TRUSTED_ORIGINS_EMBED:`const TRUSTED_ORIGINS_EMBED = ${JSON.stringify(Phoenix.TRUSTED_ORIGINS)};`,HIGHLIGHT_JS:HilightJSText,GFM_CSS:GFMCSSText,PARENT_ORIGIN:location.origin},html=Mustache.render(markdownHTMLTemplate,templateVars);resolve({contents:html,headers:{"Content-Type":"text/html"},path:fullPath})}).fail(function(err){reject(new Error(`Markdown rendering failed for ${fullPath}: `+err))})})}function _getRedirectionPage(redirectURL){let url=new URL(redirectURL);url.searchParams.delete(PHCODE_LIVE_PREVIEW_QUERY_PARAM);let templateVars={redirectURL:url.href};return Mustache.render(redirectionHTMLTemplate,templateVars)}function getContent(path,url){const currentDocument=DocumentManager.getCurrentDocument(),currentFile=currentDocument?currentDocument.file:ProjectManager.getSelectedItem();if(!_staticServerInstance)return Promise.reject("Static serve not started!");if(!url.startsWith(_staticServerInstance.getBaseUrl()))return Promise.reject("Not serving content as url belongs to another phcode instance: "+url);const shouldServeRendered=path===_lastPreviewedFilePath||currentFile&¤tFile.fullPath===path;return utils.isMarkdownFile(path)&&shouldServeRendered?_getMarkdown(path):_staticServerInstance?_staticServerInstance._getInstrumentedContent(path,url):Promise.reject("Cannot get content")}function _startHeartBeatListeners(){LivePreviewTabs.start({close:function(clientID){exports.trigger("BROWSER_CLOSE",{data:{message:{clientID:clientID}}})},reconnect:function(clientID,url){exports.trigger("BROWSER_CONNECT",{data:{message:{clientID:clientID,url:url}}})}})}function messageToLivePreviewTabs(message){if(!message.type)throw new Error("Missing type attribute to send live preview message to tabs");$livepreviewServerIframe&&$livepreviewServerIframe[0].contentWindow.postMessage(message,"*"),_sendToLivePreviewServerTabs(message)}function _sendInitialURL(pageLoaderID){currentPopoutURL&&navigatorChannel.postMessage({type:"INITIAL_URL_NAVIGATE",URL:currentPopoutURL,pageLoaderID:pageLoaderID})}function redirectAllTabs(newURL,force){currentPopoutURL=newURL,navigatorChannel.postMessage({type:"REDIRECT_PAGE",URL:newURL,force:force})}function _projectOpened(_evt,projectRoot){_lastPreviewedFilePath=null,navigatorChannel.postMessage({type:"PROJECT_SWITCH",projectRoot:projectRoot.fullPath})}function getPageLoaderURL(url){return`${Phoenix.baseURL}live-preview-loader.html?`+`virtualServerURL=${encodeURIComponent(LIVE_PREVIEW_STATIC_SERVER_BASE_URL)}`+`&phoenixInstanceID=${Phoenix.PHOENIX_INSTANCE_ID}&initialURL=${encodeURIComponent(url)}`+`&localMessage=${encodeURIComponent(Strings.DESCRIPTION_LIVEDEV_SECURITY_POPOUT_MESSAGE)}`+`&appName=${encodeURIComponent(Strings.APP_NAME)}`+`&initialProjectRoot=${encodeURIComponent(ProjectManager.getProjectRoot().fullPath)}`+`&okMessage=${encodeURIComponent(Strings.TRUST_PROJECT)}`}function getTabPopoutURL(url){let openURL=new URL(url);return openURL.searchParams.set(PHCODE_LIVE_PREVIEW_QUERY_PARAM,"true"),getPageLoaderURL(openURL.href)}function hasActiveLivePreviews(){return livePreviewTabs.size>0}function getRemoteTransportScript(){return`TRANSPORT_CONFIG.LIVE_PREVIEW_BROADCAST_CHANNEL_ID = "${LIVE_PREVIEW_BROADCAST_CHANNEL_ID}";\n`}function init(){LiveDevelopment.setLivePreviewTransportBridge(exports),$livepreviewServerIframe=$("#live-preview-server-iframe");let url=LIVE_PREVIEW_STATIC_SERVER_BASE_URL+`?parentOrigin=${location.origin}`;$livepreviewServerIframe.attr("src",url),_initNavigatorChannel(),_initLivePreviewChannel(),EventManager.registerEventHandler("ph-liveServer",exports),ProjectManager.on(ProjectManager.EVENT_PROJECT_OPEN,_projectOpened),_startHeartBeatListeners()}marked.setOptions({renderer:new marked.Renderer,pedantic:!1,gfm:!0,breaks:!1,sanitize:!1,smartLists:!0,smartypants:!1,xhtml:!1}),StaticServer.prototype=Object.create(BaseServer.prototype),StaticServer.prototype.constructor=StaticServer,StaticServer.prototype.getBaseUrl=function(){return this._baseUrl},StaticServer.prototype.pathToUrl=function(path){const baseUrl=this.getBaseUrl(),relativePath=this._pathResolver(path);return relativePath!==path?`${baseUrl}${encodeURI(path)}`:null},StaticServer.prototype.urlToPath=function(url){let baseUrl=this.getBaseUrl();if(""!==baseUrl&&0===url.indexOf(baseUrl)){const urlObj=new URL(url),filePath=decodeURI(urlObj.pathname).replace(BASE_URL_PATH_PREFIX,"");return decodeURI(filePath)}return null},StaticServer.prototype.canServe=function(localPath){return localPath!==this._pathResolver(localPath)&&(!!localPath.match(/\/$/)||LiveDevelopmentUtils.isStaticHtmlFileExt(localPath))},StaticServer.prototype.readyToServe=function(){return $.Deferred().resolve().promise()},StaticServer.prototype.addVirtualContentAtPath=function(path,docText){BaseServer.prototype.addVirtualContentAtPath.call(this,path,docText)},StaticServer.prototype.add=function(liveDocument){liveDocument.setInstrumentationEnabled&&liveDocument.setInstrumentationEnabled(!0),BaseServer.prototype.add.call(this,liveDocument)},StaticServer.prototype.remove=function(liveDocument){BaseServer.prototype.remove.call(this,liveDocument)},StaticServer.prototype.removeVirtualContentAtPath=function(path){BaseServer.prototype.removeVirtualContentAtPath.call(this,path)},StaticServer.prototype.clear=function(){BaseServer.prototype.clear.call(this)},StaticServer.prototype._getInstrumentedContent=function(requestedPath,url){return new Promise((resolve,reject)=>{let path=this._documentKey(requestedPath),liveDocument=this._liveDocuments[path],virtualDocument=this._virtualServingDocuments[path],contents;if(!ProjectManager.isWithinProject(requestedPath))return console.error("Security issue prevented: Live preview tried to access non project resource!!!",path),void resolve({path:path,contents:null});let isLivePreviewPopoutPage=!1,headers;if((url=new URL(url)).searchParams.get(PHCODE_LIVE_PREVIEW_QUERY_PARAM)&&(isLivePreviewPopoutPage=!0),virtualDocument)contents=virtualDocument;else if(liveDocument&&liveDocument.getResponseData)contents=liveDocument.getResponseData().body,isLivePreviewPopoutPage&&-1===contents.indexOf(LiveDevProtocol.getRemoteScript())&&(console.log("serving stale live preview with navigable url",url),contents=_getRedirectionPage(url));else{const file=FileSystem.getFileForPath(requestedPath);let doc=DocumentManager.getOpenDocumentForPath(file.fullPath);if(!doc)return void fs.readFile(requestedPath,fs.BYTE_ARRAY_ENCODING,function(error,binContent){error&&(binContent=null),resolve({path:path,contents:binContent})});contents=doc.getText()}(path.endsWith(".htm")||path.endsWith(".html")||path.endsWith(".xhtml")||path.endsWith(".php"))&&(headers={"Content-Type":"text/html;charset=UTF-8"}),resolve({path:path,contents:contents,headers:headers})})},StaticServer.prototype.start=async function(){_staticServerInstance=this},StaticServer.prototype.isActive=function(){return _staticServerInstance===this},StaticServer.prototype.stop=function(){_staticServerInstance=void 0},exports.on(EVENT_REPORT_ERROR,function(_ev,event){logger.reportError(new Error(event.data.message))}),exports.on(EVENT_GET_CONTENT,function(_ev,event){if(window.logger.livePreview.log("Static Server GET_CONTENT",event),event.data.message&&event.data.message.phoenixInstanceID===Phoenix.PHOENIX_INSTANCE_ID){const requestPath=event.data.message.path,requestID=event.data.message.requestID,url=event.data.message.url;getContent(requestPath,url).then(response=>{response.type="REQUEST_RESPONSE",response.requestID=requestID,messageToLivePreviewTabs(response)}).catch(console.error)}}),exports.on(EVENT_GET_PHOENIX_INSTANCE_ID,function(_ev){messageToLivePreviewTabs({type:"PHOENIX_INSTANCE_ID",PHOENIX_INSTANCE_ID:Phoenix.PHOENIX_INSTANCE_ID})}),exports.on(EVENT_TAB_ONLINE,function(_ev,event){LivePreviewTabs.tabOnline(event.data.message.clientID,event.data.message.URL)}),exports.on("UPDATE_TITLE_AND_ICON",function(_ev,event){const title=event.data.message.title,faviconBase64=event.data.message.faviconBase64;navigatorChannel.postMessage({type:"UPDATE_TITLE_ICON",title:title,faviconBase64:faviconBase64})}),exports.on("embeddedEscapeKeyPressed",function(){LiveDevelopment.isInPreviewMode()||utils.focusActiveEditorIfFocusInLivePreview()}),exports.init=init,exports.StaticServer=StaticServer,exports.messageToLivePreviewTabs=messageToLivePreviewTabs,exports.getPreviewDetails=getPreviewDetails,exports.livePreviewTabs=livePreviewTabs,exports.dropTab=LivePreviewTabs.dropTab,exports.redirectAllTabs=redirectAllTabs,exports.getTabPopoutURL=getTabPopoutURL,exports.hasActiveLivePreviews=hasActiveLivePreviews,exports.getNoPreviewURL=getNoPreviewURL,exports.getMdviewrURL=getMdviewrURL,exports.getRemoteTransportScript=getRemoteTransportScript,exports.PHCODE_LIVE_PREVIEW_QUERY_PARAM=PHCODE_LIVE_PREVIEW_QUERY_PARAM,exports.EVENT_SERVER_READY="SERVER_READY"});