Skip to content

Commit

Permalink
openEditorAtCaller and openEditorAtDef
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismccord committed Feb 27, 2024
1 parent 8ef154b commit 45c0f03
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 16 deletions.
31 changes: 22 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,38 @@ window.addEventListener("phx:live_reload:connected", ({detail: reloader}) => {

## Jumping to HEEx function definitions

Many times it's useful to inspect the HTML DOM tree to find where markup is being rendered from within your application. HEEx supports annotating rendered HTML with HTML comments that give you the file/line of a HEEx function component. `:phoenix_live_reload` will look for the `PLUG_EDITOR` environment export to launch a configured URL of your choice to open your code editor to the file-line of the HTML annotation. For example, the following export on your system would open vscode at the correct file/line:
Many times it's useful to inspect the HTML DOM tree to find where markup is being rendered from within your application. HEEx supports annotating rendered HTML with HTML comments that give you the file/line of a HEEx function component and caller. `:phoenix_live_reload` will look for the `PLUG_EDITOR` environment export (used by the plug debugger page to link to source code) to launch a configured URL of your choice to open your code editor to the file-line of the HTML annotation. For example, the following export on your system would open vscode at the correct file/line:

```
export PLUG_EDITOR="vscode://file/__FILE__:__LINE__"
```

The `vscode://` protocol URL will open vscode with placeholders of `__FILE__:__LINE__` substited at runtime. Check your editor's documentation on protocol URL support. To open your configured editor URL when an element is clicked, say with alt-click, you can wire up an event listener within your `"phx:live_reload:connected"` callback and make use of the reloader's `openEditor` function, passing the event target as the DOM node to reference for HEEx file:line annotation information. For example:
The `vscode://` protocol URL will open vscode with placeholders of `__FILE__:__LINE__` substited at runtime. Check your editor's documentation on protocol URL support. To open your configured editor URL when an element is clicked, say with alt-click, you can wire up an event listener within your `"phx:live_reload:connected"` callback and make use of the reloader's `openEditorAtCaller` and `openEditorAtDef` functions, passing the event target as the DOM node to reference for HEEx file:line annotation information. For example:

```javascript
window.addEventListener("phx:live_reload:connected", ({detail: reloader}) => {
// enable server log streaming to client.
reloader.enableServerLogs() // disable with reloader.disableServerLogs()
// open configured PLUG_EDITOR at file:line of the alt-clicked element's HEEx component
// Enable server log streaming to client. Disable with reloader.disableServerLogs()
reloader.enableServerLogs()

// Open configured PLUG_EDITOR at file:line of the clicked element's HEEx component
//
// * click with "c" key pressed to open at caller location
// * click with "d" key pressed to open at function component definition location
let keyDown
window.addEventListener("keydown", e => keyDown = e.key)
window.addEventListener("keyup", e => keyDown = null)
window.addEventListener("click", e => {
if(!e.altKey){ return }
e.preventDefault()
e.stopImmediatePropagation()
reloader.openEditor(e.target)
if(keyDown === "c"){
e.preventDefault()
e.stopImmediatePropagation()
reloader.openEditorAtCaller(e.target)
} else if(keyDown === "d"){
e.preventDefault()
e.stopImmediatePropagation()
reloader.openEditorAtDef(e.target)
}
}, true)
window.liveReloader = reloader
})
```

Expand Down
44 changes: 37 additions & 7 deletions priv/static/phoenix_live_reload.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ class LiveReloader {
enableServerLogs(){ this.logsEnabled = true }
disableServerLogs(){ this.logsEnabled = false }

openEditor(targetNode){
openEditorAtCaller(targetNode){
if(!this.editorURL){
return console.error("phoenix_live_reload cannot openEditor without configured PLUG_EDITOR")
return console.error("phoenix_live_reload cannot openEditorAtCaller without configured PLUG_EDITOR")
}

let fileLine = this.closestDebugFileLine(targetNode)
let fileLine = this.closestCallerFileLine(targetNode)
if(fileLine){
let [file, line] = fileLine.split(":")
let fullPath = [this.relativePath, file].join("/")
Expand All @@ -101,6 +101,19 @@ class LiveReloader {
}
}

openEditorAtDef(targetNode){
if(!this.editorURL){
return console.error("phoenix_live_reload cannot openEditorAtDef without configured PLUG_EDITOR")
}

let fileLine = this.closestDefFileLine(targetNode)
if(fileLine){
let [file, line] = fileLine.split(":")
let fullPath = [this.relativePath, file].join("/")
let url = this.editorURL.replace("__FILE__", fullPath).replace("__LINE__", line)
window.open(url, "_self")
}
}
// private

dispatchConnected(){
Expand All @@ -113,15 +126,32 @@ class LiveReloader {
console[consoleFunc](`%c📡 [${level}] ${str}`, `color: ${levelColor};`)
}

closestDebugFileLine(node){
closestCallerFileLine(node){
while(node.previousSibling){
node = node.previousSibling
if(node.nodeType === Node.COMMENT_NODE){
let callerComment = node.previousSibling
let callerMatch = callerComment &&
callerComment.nodeType === Node.COMMENT_NODE &&
callerComment.nodeValue.match(/\s@caller\s+(.+):(\d+)\s/i)

if(callerMatch){
return `${callerMatch[1]}:${callerMatch[2]}`
}
}
}
if(node.parentNode){ return this.closestCallerFileLine(node.parentNode) }
}

closestDefFileLine(node){
while(node.previousSibling){
node = node.previousSibling
if(node.nodeType === Node.COMMENT_NODE){
let match = node.nodeValue.match(/.*>\s([\w\/]+.*ex:\d+)/i)
if(match){ return match[1] }
let fcMatch = node.nodeValue.match(/.*>\s([\w\/]+.*ex:\d+)/i)
if(fcMatch){ return fcMatch[1] }
}
}
if(node.parentNode){ return this.closestDebugFileLine(node.parentNode) }
if(node.parentNode){ return this.closestDefFileLine(node.parentNode) }
}
}

Expand Down

0 comments on commit 45c0f03

Please sign in to comment.