When debugging or revamping web pages, we inspect views and partials inside. When complicated page comes in, locating codes can be time consuming, especially when we are not familiar with the page.
The Idea
Chrome extension for finding out partials rendered.
Click the partial name to hit the exact file.
To implement, we need
an automated way to add extra markups
a chrome extension to visualize partials and listen to user action
a background script to launch the text editor
The Markups
The partial info must come from somewhere. Below I take sinatra and erb as an example.
12345678910111213141516
# inside the configure do block (not production)# override the prepare method of tiltTilt::ERBTemplate.class_evaldodefprepare@outvar=options[:outvar]||self.class.default_output_variableoptions[:trim]='<>'if!(options[:trim]==false)&&(options[:trim].nil?||options[:trim]==true)unlessdata.lines.first.start_with?"<!doctype"dataanddata.prepend<<-TAG <i class="erb-locator" style="display:none; visibility:hidden">#{file}</i> TAGend@engine=::ERB.new(data,options[:safe],options[:trim],@outvar)endendunless$production
Now <i> tags should be generated right above any partials rendered.
As you can see, a fixed extension ID and Native Messaging support are required.
12345678910111213141516171819202122
// background.js// Execute the erb locator script when user clicked on a locatorchrome.runtime.onMessage.addListener(function(request,sender,sendResponse){if(request.erb){console.log("Received",request);chrome.runtime.sendNativeMessage('com.loki.erb_locator',{erb:request.erb},function(){console.log("Native Message Sent");});sendResponse({});}});// Extension entry pointchrome.browserAction.onClicked.addListener(function(tab){chrome.tabs.executeScript(null,{file:"jquery-1.10.2.min.js"},function(){chrome.tabs.executeScript(null,{file:"inject.js"});});});
We have done 2 things here.
added a listener to trigger the erb locator ruby script
injected inject.js to the active tab when user activating our extension
Finally, inject.js for visualizing locators and listening to user action.
// inject.js// the backdrop, we will place our locators on itvar$mask=null;// Open partial in text editor thru Native MessagingfunctionopenERB(erb){chrome.runtime.sendMessage({erb:erb},function(){console.log("Message Sent: "+erb);});}// locate and visualize those locatorfunctionbuildLinks(){// keep track on locators with same position for avoid overlappingvarcount={};$('i.erb-locator').each(function(){var$this=$(this);varpath=$this.text();varerbName=path.replace(/.*\/(.*).erb/,"$1");var$a=$('<a class="_erb">'+erbName+'</a>').attr({"href":"javascript:void(0)","data-erb":path}).css({"position":"absolute","border":"1px solid #888","padding":"2px 6px","font-size":"14px","color":"#111","background":"white"});// slightly add offsets to overlapped nodesvaro=$this.next().offset();vark=o.top*1000+o.left;count[k]=count[k]==undefined?0:count[k]+1;$a.offset({top:o.top+count[k]*19,left:o.left});$mask.append($a);});$('body').append($mask);}// select the backdrop out$mask=$('#_mask');// remove it when it is already exist// user triggered the extension again without selecting any oneif(!!$mask.length){$mask.remove();}else{$mask=$('<div id="_mask">');$mask.css({"position":"absolute","top":"0","left":"0","right":"0","bottom":"0","background-color":"rgba(255, 255, 255, 0.5)","z-index":"99999"});buildLinks();$mask.on('click','a._erb',function(){openERB($(this).data('erb'));$mask.remove();returnfalse;});}
The Backend
Mentioned quite a lot the locator ruby script, below is an example and you may roll out your own.
12345678910111213141516171819202122232425262728
#!/usr/bin/env rubyrequire'syslog'require'json'Syslog.open# start hereSyslog.info"Native Message Received, RUBY_VERSION: #{RUBY_VERSION}"# read number of bytes from stdindefreadc(n)n.times.map{STDIN.getc}.joinend# read msg from chrome native messagingdefreadmsglen=readc(4).unpack("i")[0]readclenend# read filenamemsg=readmsgSyslog.info"msg: #{msg}"filename=JSON.load(msg)["erb"]system"vim --servername main --remote-send ':tab drop #{filename}<cr><cr>'"system"wmctrl -a 'GVIM main'"
To let chrome talk to the script, we have to register a Native Messaging Host. For Linux host, place file below under ~/.config/google-chrome/NativeMessagingHosts.