@@ -44,13 +44,15 @@ define(function (require, exports, module) {
4444 // Text of the script we'll inject into the browser that handles protocol requests.
4545 const LiveDevProtocolRemote = require ( "text!LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js" ) ,
4646 DocumentObserver = require ( "text!LiveDevelopment/BrowserScripts/DocumentObserver.js" ) ,
47+ LanguageManager = require ( "language/LanguageManager" ) ,
4748 RemoteFunctions = require ( "text!LiveDevelopment/BrowserScripts/RemoteFunctions.js" ) ,
4849 EditorManager = require ( "editor/EditorManager" ) ,
4950 LiveDevMultiBrowser = require ( "LiveDevelopment/LiveDevMultiBrowser" ) ,
5051 PreferencesManager = require ( "preferences/PreferencesManager" ) ,
5152 HTMLInstrumentation = require ( "LiveDevelopment/MultiBrowserImpl/language/HTMLInstrumentation" ) ,
5253 StringUtils = require ( "utils/StringUtils" ) ,
53- FileViewController = require ( "project/FileViewController" ) ;
54+ FileViewController = require ( "project/FileViewController" ) ,
55+ MainViewManager = require ( "view/MainViewManager" ) ;
5456
5557 const LIVE_DEV_REMOTE_SCRIPTS_FILE_NAME = `phoenix_live_preview_scripts_instrumented_${ StringUtils . randomString ( 8 ) } .js` ;
5658 const LIVE_DEV_REMOTE_WORKER_SCRIPTS_FILE_NAME = `pageLoaderWorker_${ StringUtils . randomString ( 8 ) } .js` ;
@@ -107,38 +109,96 @@ define(function (require, exports, module) {
107109 editor . focus ( ) ;
108110 }
109111
110- function _tagSelectedInLivePreview ( tagId , nodeName , contentEditable ) {
112+ const cssLangIDS = [ "css" , "scss" , "sass" , "less" ] ;
113+ const lessLangIDS = [ "scss" , "sass" , "less" ] ;
114+ function _isLessOrSCSS ( editor ) {
115+ if ( ! editor ) {
116+ return false ;
117+ }
118+ const language = LanguageManager . getLanguageForPath ( editor . document . file . fullPath ) ;
119+ return language && lessLangIDS . includes ( language . getId ( ) ) ;
120+ }
121+
122+ function _searchAndCursorIfCSS ( editor , allSelectors , nodeName ) {
123+ const codeMirror = editor . _codeMirror ;
124+ const language = LanguageManager . getLanguageForPath ( editor . document . file . fullPath ) ;
125+ if ( ! language || ! cssLangIDS . includes ( language . getId ( ) ) ) {
126+ return ;
127+ }
128+
129+ // this is a css file
130+ if ( allSelectors && allSelectors . length ) {
131+ // check if we can find a class selector
132+ for ( let selector of allSelectors ) {
133+ const cursor = codeMirror . getSearchCursor ( selector ) ;
134+ const found = cursor . findNext ( ) ;
135+ if ( found ) {
136+ editor . setCursorPos ( cursor . from ( ) . line , cursor . from ( ) . ch , true ) ;
137+ return ;
138+ }
139+ }
140+ }
141+ // check if we can do tag matching, html tag selectors are not case-sensitive
142+ const htmlTagSearch = new RegExp ( nodeName , "i" ) ;
143+ const cursor = codeMirror . getSearchCursor ( htmlTagSearch ) ;
144+ const found = cursor . findNext ( ) ;
145+ if ( found ) {
146+ editor . setCursorPos ( cursor . from ( ) . line , cursor . from ( ) . ch , true ) ;
147+ }
148+ }
149+
150+ function _tagSelectedInLivePreview ( tagId , nodeName , contentEditable , allSelectors ) {
111151 const highlightPref = PreferencesManager . getViewState ( "livedevHighlight" ) ;
112152 if ( ! highlightPref ) {
113153 // live preview highlight and reverse highlight feature is disabled
114154 return ;
115155 }
116156 const liveDoc = LiveDevMultiBrowser . getCurrentLiveDoc ( ) ,
117- editor = EditorManager . getActiveEditor ( ) ;
157+ activeEditor = EditorManager . getActiveEditor ( ) , // this can be an inline editor
158+ activeFullEditor = EditorManager . getCurrentFullEditor ( ) ;
118159 const liveDocPath = liveDoc ? liveDoc . doc . file . fullPath : null ,
119- activeEditorDocPath = editor ? editor . document . file . fullPath : null ;
120- function selectInActiveDocument ( ) {
121- // activeEditor can be either a full or inline(Eg. css inline within html) editor
122- const activeEditor = EditorManager . getActiveEditor ( ) ;
123- const activeFullEditor = EditorManager . getCurrentFullEditor ( ) ; // always full editor
124- const position = HTMLInstrumentation . getPositionFromTagId ( activeFullEditor , parseInt ( tagId , 10 ) ) ;
125- // should we scan all editors for the file path and update selections on every editor?
126- // currently we do it only for active / full editor.
127- if ( position &&
128- activeEditor && activeEditor . document . file . fullPath === activeFullEditor . document . file . fullPath ) {
129- activeEditor . setCursorPos ( position . line , position . ch , true ) ;
130- _focusEditorIfNeeded ( activeEditor , nodeName , contentEditable ) ;
131- }
132- if ( position && activeFullEditor ) {
133- activeFullEditor . setCursorPos ( position . line , position . ch , true ) ;
134- _focusEditorIfNeeded ( activeFullEditor , nodeName , contentEditable ) ;
160+ activeEditorPath = activeEditor ? activeEditor . document . file . fullPath : null ,
161+ activeFullEditorPath = activeFullEditor ? activeFullEditor . document . file . fullPath : null ;
162+ if ( ! liveDocPath ) {
163+ activeEditor && activeEditor . focus ( ) ; // restore focus from live preview
164+ return ;
165+ }
166+ const openFullEditors = MainViewManager . findInOpenPane ( liveDocPath ) ;
167+ const openLiveDocEditor = openFullEditors . length ? openFullEditors [ 0 ] . editor : null ;
168+ function selectInHTMLEditor ( fullHtmlEditor ) {
169+ const position = HTMLInstrumentation . getPositionFromTagId ( fullHtmlEditor , parseInt ( tagId , 10 ) ) ;
170+ if ( position && fullHtmlEditor ) {
171+ const masterEditor = fullHtmlEditor . document . _masterEditor || fullHtmlEditor ;
172+ masterEditor . setCursorPos ( position . line , position . ch , true ) ;
173+ _focusEditorIfNeeded ( masterEditor , nodeName , contentEditable ) ;
135174 }
136175 }
137- if ( liveDocPath && liveDocPath !== activeEditorDocPath ) {
138- FileViewController . openAndSelectDocument ( liveDocPath , FileViewController . PROJECT_MANAGER )
139- . done ( selectInActiveDocument ) ;
176+ if ( liveDocPath === activeFullEditorPath ) {
177+ // if the active pane is the html being live previewed, select that.
178+ selectInHTMLEditor ( activeFullEditor ) ;
179+ } else if ( liveDoc . isRelated ( activeEditorPath ) || _isLessOrSCSS ( activeEditor ) ) {
180+ // the active editor takes the priority in the workflow. If a css related file is active,
181+ // then we dont need to open the html live doc. For less files, we dont check if its related as
182+ // its not directly linked usually and needs a compile step. so we just do a fuzzy search.
183+ activeEditor . focus ( ) ;
184+ _searchAndCursorIfCSS ( activeEditor , allSelectors , nodeName ) ;
185+ // in this case, see if we need to do any css reverse highlight magic here
186+ } else if ( openLiveDocEditor ) {
187+ // If we are on multi pane mode, the html doc was open in an inactive unfocused editor.
188+ selectInHTMLEditor ( openLiveDocEditor ) ;
140189 } else {
141- selectInActiveDocument ( ) ;
190+ // no open editor for the live doc in panes, check if there is one in the working set.
191+ const foundInWorkingSetPane = MainViewManager . findInAllWorkingSets ( liveDocPath ) ;
192+ const paneToUse = foundInWorkingSetPane . length ?
193+ foundInWorkingSetPane [ 0 ] . paneId :
194+ MainViewManager . ACTIVE_PANE ; // if pane id is active pane, then the file is not open in working set
195+ const viewToUse = ( paneToUse === MainViewManager . ACTIVE_PANE ) ?
196+ FileViewController . PROJECT_MANAGER :
197+ FileViewController . WORKING_SET_VIEW ;
198+ FileViewController . openAndSelectDocument ( liveDocPath , viewToUse , paneToUse )
199+ . done ( ( ) => {
200+ selectInHTMLEditor ( EditorManager . getActiveEditor ( ) ) ;
201+ } ) ;
142202 }
143203 }
144204
@@ -168,7 +228,7 @@ define(function (require, exports, module) {
168228 }
169229 }
170230 } else if ( msg . clicked && msg . tagId ) {
171- _tagSelectedInLivePreview ( msg . tagId , msg . nodeName , msg . contentEditable ) ;
231+ _tagSelectedInLivePreview ( msg . tagId , msg . nodeName , msg . contentEditable , msg . allSelectors ) ;
172232 exports . trigger ( EVENT_LIVE_PREVIEW_CLICKED , msg ) ;
173233 } else {
174234 // enrich received message with clientId
0 commit comments