Skip to content

Instantly share code, notes, and snippets.

@ka2n
Created December 24, 2021 01:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ka2n/156b5c74a31e98053edc1d1729b79f97 to your computer and use it in GitHub Desktop.
Save ka2n/156b5c74a31e98053edc1d1729b79f97 to your computer and use it in GitHub Desktop.
Rails: alt-clickでクリックしたpartialをVSCodeで開きます
module TempleRailsAnnotate
def call(template, source = nil)
opts = {}.update(self.class.options).update(file: template.identifier)
result = ''
if ActionView::Base.annotate_rendered_view_with_filenames && template.format == :html
whatpartial = "(file://#{template.identifier})"
result << "@output_buffer.safe_concat('<!-- BEGIN #{template.short_identifier}#{whatpartial} -->');"
end
result << self.class.compile((source || template.source), opts)
if ActionView::Base.annotate_rendered_view_with_filenames && template.format == :html
result << ";@output_buffer.safe_concat('<!-- END #{template.short_identifier} -->');@output_buffer"
end
result
end
end
Temple::Templates::Rails.prepend(TempleRailsAnnotate)
/** クリックするとVSCodeで該当のpartialを開きます
*
* - ネストした場合は一番近いpartialを開きます
* - 将来的に簡単なコンテキストメニューを表示して選べても便利そう
*/
type Option = { mod: ("alt" | "shift" | "ctrl" | "meta")[] }
export const setup = (option: Option = { mod: ["alt"] }) => {
const h = handler(option)
document.addEventListener("click", h)
return () => document.removeEventListener("click", h)
}
const handler = (option: Option) => {
const mod = new Set(option.mod)
return (e: MouseEvent) => {
if (!e.target) return
// Prevent a collisioning with babel-plugin-open-source
const target = e.target as HTMLElement
if (target.dataset.source) return
if (mod.has("alt") && !e.altKey) return
if (mod.has("shift") && !e.shiftKey) return
if (mod.has("ctrl") && !e.ctrlKey) return
if (mod.has("meta") && !e.metaKey) return
// Find comment node
let element = e.target as Node | null
let comment: Comment | null = null
while (element) {
comment = document
.evaluate("./preceding-sibling::comment()", element)
.iterateNext() as any
if (comment) {
break
}
element = element.parentNode
}
// Open with editor using URI scheme
const path = comment?.textContent?.match(
/BEGIN [^\(]+\(file:\/\/([^)]+)\)/
)?.[1]
if (!path) return
try {
window.open(`vscode://file${path}`)
} catch (e) {
console.error(e)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment