@@ -75,6 +75,8 @@ define(function LiveDevelopment(require, exports, module) {
7575 var STATUS_SYNC_ERROR = exports . STATUS_SYNC_ERROR = 5 ;
7676
7777 var Async = require ( "utils/Async" ) ,
78+ CollectionUtils = require ( "utils/CollectionUtils" ) ,
79+ FileIndexManager = require ( "project/FileIndexManager" ) ,
7880 Dialogs = require ( "widgets/Dialogs" ) ,
7981 DefaultDialogs = require ( "widgets/DefaultDialogs" ) ,
8082 DocumentManager = require ( "document/DocumentManager" ) ,
@@ -566,7 +568,7 @@ define(function LiveDevelopment(require, exports, module) {
566568 // After (1) the interstitial page loads, (2) then browser navigation
567569 // to the base URL is completed, and (3) the agents finish loading
568570 // gather related documents and finally set status to STATUS_ACTIVE.
569- var doc = _getCurrentDocument ( ) ;
571+ var doc = _getCurrentDocument ( ) ; // TODO: probably wrong...
570572
571573 if ( doc ) {
572574 var status = STATUS_ACTIVE ,
@@ -611,6 +613,115 @@ define(function LiveDevelopment(require, exports, module) {
611613 return result . promise ( ) ;
612614 }
613615
616+ /**
617+ * @private
618+ * Determine an index file that can be used to start Live Development.
619+ * This function will inspect all files in a project to find the closest index file
620+ * available for currently opened document. We are searching for these files:
621+ * - index.html
622+ * - index.htm
623+ *
624+ * If the project is configured with a custom base url for live developmment, then
625+ * the list of possible index files is extended to contain these index files too:
626+ * - index.php
627+ * - index.php3
628+ * - index.php4
629+ * - index.php5
630+ * - index.phtm
631+ * - index.phtml
632+ * - index.cfm
633+ * - index.cfml
634+ * - index.asp
635+ * - index.aspx
636+ * - index.jsp
637+ * - index.jspx
638+ * - index.shm
639+ * - index.shml
640+ *
641+ * If a file was found, the promise will be resolved with the full path to this file. If no file
642+ * was found in the whole project tree, the promise will be resolved with null.
643+ *
644+ * @return {jQuery.Promise } A promise that is resolved with a full path
645+ * to a file if one could been determined, or null if there was no suitable index
646+ * file.
647+ */
648+ function _getInitialDocFromCurrent ( ) {
649+ var doc = _getCurrentDocument ( ) ,
650+ refPath ,
651+ i ;
652+
653+ // TODO: FileUtils.getParentFolder()
654+ function getParentFolder ( path ) {
655+ return path . substring ( 0 , path . lastIndexOf ( '/' , path . length - 2 ) + 1 ) ;
656+ }
657+
658+ // Is the currently opened document already a file we can use for Live Development?
659+ if ( doc ) {
660+ refPath = doc . file . fullPath ;
661+ if ( FileUtils . isStaticHtmlFileExt ( refPath ) || FileUtils . isServerHtmlFileExt ( refPath ) ) {
662+ return new $ . Deferred ( ) . resolve ( doc ) ;
663+ }
664+ }
665+
666+ var result = new $ . Deferred ( ) ;
667+
668+ var baseUrl = ProjectManager . getBaseUrl ( ) ,
669+ hasOwnServerForLiveDevelopment = ( baseUrl && baseUrl . length ) ;
670+
671+ // TODO: It would be better to reuse the list of file extensions from FileUtils
672+ var staticIndexFiles = [ "html" , "htm" ] . map ( function ( extension ) { return "index." + extension ; } ) ;
673+ var dynamicIndexFiles = [ "php" , "php3" , "php4" , "php5" , "phtm" , "phtml" , "cfm" , "cfml" , "asp" , "aspx" , "jsp" , "jspx" , "shtm" , "shtml" ] . map ( function ( extension ) { return "index." + extension ; } ) ;
674+
675+ FileIndexManager . getFileInfoList ( "all" ) . done ( function ( allFiles ) {
676+ if ( refPath ) {
677+ var projectRoot = ProjectManager . getProjectRoot ( ) . fullPath ,
678+ containingFolder = FileUtils . getDirectoryPath ( refPath ) ,
679+ indexFileFound = false ,
680+ stillInProjectTree = true ;
681+
682+ var filterIndexFile = function ( fileInfo ) {
683+ if ( fileInfo . fullPath . indexOf ( containingFolder ) === 0 ) {
684+ if ( hasOwnServerForLiveDevelopment ) {
685+ if ( ( dynamicIndexFiles . indexOf ( fileInfo . name ) !== - 1 ) ||
686+ ( staticIndexFiles . indexOf ( fileInfo . name ) !== - 1 ) ) {
687+ return true ;
688+ }
689+ } else if ( staticIndexFiles . indexOf ( fileInfo . name ) !== - 1 ) {
690+ return true ;
691+ }
692+ } else {
693+ return false ;
694+ }
695+ } ;
696+
697+ while ( ! indexFileFound && stillInProjectTree ) {
698+ i = CollectionUtils . indexOf ( allFiles , filterIndexFile ) ;
699+
700+ // We found no good match
701+ if ( i === - 1 ) {
702+ // traverse the directory tree up one level
703+ containingFolder = getParentFolder ( containingFolder ) ;
704+ // Are we still inside the project?
705+ if ( containingFolder . indexOf ( projectRoot ) === - 1 ) {
706+ stillInProjectTree = false ;
707+ }
708+ } else {
709+ indexFileFound = true ;
710+ }
711+ }
712+
713+ if ( i !== - 1 ) {
714+ DocumentManager . getDocumentForPath ( allFiles [ i ] . fullPath ) . then ( result . resolve , result . resolve ) ;
715+ return ;
716+ }
717+ }
718+
719+ result . resolve ( null ) ;
720+ } ) ;
721+
722+ return result . promise ( ) ;
723+ }
724+
614725 /**
615726 * @private
616727 * While still connected to the Inspector, do cleanup for agents,
@@ -819,17 +930,18 @@ define(function LiveDevelopment(require, exports, module) {
819930 // parallel.
820931 loadAgents ( ) ;
821932
822- var doc = _getCurrentDocument ( ) ;
823- if ( doc ) {
824- // Navigate from interstitial to the document
825- // Fires a frameNavigated event
826- Inspector . Page . navigate ( doc . url ) ;
827- } else {
828- // Unlikely that we would get to this state where
829- // a connection is in process but there is no current
830- // document
831- close ( ) ;
832- }
933+ _getInitialDocFromCurrent ( ) . done ( function ( doc ) {
934+ if ( doc ) {
935+ // Navigate from interstitial to the document
936+ // Fires a frameNavigated event
937+ Inspector . Page . navigate ( doc . url ) ;
938+ } else {
939+ // Unlikely that we would get to this state where
940+ // a connection is in process but there is no current
941+ // document
942+ close ( ) ;
943+ }
944+ } ) ;
833945 } ) ;
834946 }
835947
@@ -974,12 +1086,13 @@ define(function LiveDevelopment(require, exports, module) {
9741086
9751087 // helper function that actually does the launch once we are sure we have
9761088 // a doc and the server for that doc is up and running.
977- function _doLaunchAfterServerReady ( doc ) {
1089+ function _doLaunchAfterServerReady ( initialDoc ) {
9781090 // update status
9791091 _setStatus ( STATUS_CONNECTING ) ;
9801092
9811093 // create live document
982- _liveDocument = _createDocument ( doc , EditorManager . getCurrentFullEditor ( ) ) ;
1094+ initialDoc . _ensureMasterEditor ( ) ;
1095+ _liveDocument = _createDocument ( initialDoc , initialDoc . _masterEditor ) ;
9831096
9841097 // start listening for requests
9851098 _server . add ( _liveDocument ) ;
@@ -1037,18 +1150,23 @@ define(function LiveDevelopment(require, exports, module) {
10371150 /** Open the Connection and go live */
10381151 function open ( ) {
10391152 _openDeferred = new $ . Deferred ( ) ;
1040-
1041- var doc = _getCurrentDocument ( ) ,
1042- prepareServerPromise = ( doc && _prepareServer ( doc ) ) || new $ . Deferred ( ) . reject ( ) ;
10431153
1044- // wait for server (StaticServer, Base URL or file:)
1045- prepareServerPromise . done ( function ( result ) {
1046- _doLaunchAfterServerReady ( doc ) ;
1047- } ) ;
1048-
1049- prepareServerPromise . fail ( function ( ) {
1050- _showWrongDocError ( ) ;
1051- _openDeferred . reject ( ) ;
1154+ // TODO: need to run _onDocumentChange() after load if doc != currentDocument here? Maybe not, since activeEditorChange
1155+ // doesn't trigger it, while inline editors can still cause edits in doc other than currentDoc...
1156+ _getInitialDocFromCurrent ( ) . done ( function ( doc ) {
1157+ var prepareServerPromise = ( doc && _prepareServer ( doc ) ) || new $ . Deferred ( ) . reject ( ) ;
1158+
1159+ DocumentManager . addToWorkingSet ( doc . file ) ;
1160+
1161+ // wait for server (StaticServer, Base URL or file:)
1162+ prepareServerPromise
1163+ . done ( function ( ) {
1164+ _doLaunchAfterServerReady ( doc ) ;
1165+ } )
1166+ . fail ( function ( ) {
1167+ _showWrongDocError ( ) ;
1168+ _openDeferred . reject ( ) ;
1169+ } ) ;
10521170 } ) ;
10531171
10541172 return _openDeferred . promise ( ) ;
@@ -1181,8 +1299,9 @@ define(function LiveDevelopment(require, exports, module) {
11811299 }
11821300
11831301 // For unit testing
1184- exports . launcherUrl = launcherUrl ;
1185- exports . _getServer = _getServer ;
1302+ exports . launcherUrl = launcherUrl ;
1303+ exports . _getServer = _getServer ;
1304+ exports . _getInitialDocFromCurrent = _getInitialDocFromCurrent ;
11861305
11871306 // Export public functions
11881307 exports . agents = agents ;
0 commit comments