I've been working on a syntax highlighter for a slightly modified version of Velocity. In short how can I wrap all the content starting at #inline()
and ending with the corresponding #end
under the condition that there can be 0-infinite if statements that will always have an #end
. Let me know if you have any questions.
Example can be found on this fiddle. See the below for more detailed information.
Sample HTML
The fiddle shows the post javascript modified version of the below html.
<pre><code>
$javascript.push("/path/to/file")
#inline()
$('.lazy.bg2').attr({'data-src':'/img_path2.jpg'}).css('background','red');
#if($myVar == "hi")
$('.someClass).hide()
#elseif($myVar == "there")
$('.lazy.bg1').attr({'data-src':'/img_path.jpg'})
#else
$('.lazy.bg3').attr({'data-src':'/img_path3.jpg'})
#end
$('.lazy.bg2 a').attr({'data-href':'/random-path2.htm'})
$('.lazy.bg1 a').attr({'data-href':'/random-path.htm'})
#end
#if($test.method == "myVal")
#set($foo = "swag")
#elseif($foo == "bar")
#set($foo = "ballin")
#elseif($myObject.randomMethod().contains("myVal"))
#set($foo = "weeee")
#else
#set($foo = "sad days")
#end
#set($testVar = "Test value")
#parse("/path/to/file")</code></pre>
The Problem
Since there are multiple instances of #end
I'm not sure how to get it to match the end to the #inline()
statement. The main problem being is that there could be an infinite number of if statements, but the #inline()
will always have a corresponding end statement. So I'm guessing the best approach would be to match it based on it being the same white-space level. However I'm not sure if there is a better solution. I found the original javascript in Gone Coding's post here. However I've slightly modified it to better match my implementation. Note I'm adding the velocity class to the <pre>
in an earlier jQuery statement. The end result should only apply the <span>
to the jQuery inside the #inline()
.
Javascript
$('pre.velocity code').each(function () {
var open = false;
var result = $();
$(this).contents().each(function () {
var $this = $(this);
if ($this.text() == "#inline()" || $this.text() == "#end") {
if (open) {
result.wrapAll('<span class="velocity-inline-inner"></span>');
open = false;
} else {
result = $();
open = true;
}
} else {
result = result.add($this)
}
});
if (open) {
result.wrapAll('<span class="velocity-inline-inner"></span>');
}
});
Updated Javascript
I have the following that can count the white space and selects the #end
that matches white space level of the #inline()
, however I am having the issue of converting just that substring to html within the if statement.
$('pre.velocity code').each(function(){
var str = $(this).text();
str = str.substring(str.indexOf("#inline()") + 10);
textArray = str.split("\n");
getInlineEnd(str,textArray);
});
function getInlineEnd(str,textArray) {
for(var i = 0; i <= textArray.length; i++) {
if(textArray[i].length === 4 && textArray[i] === "#end") {
//convert textArray[i] to a html node and then wrap with a <span>
break;
}
}
}
End Goal HTML
The end result should look something like the below. I'm adding a span around the #inline()
and #end
already.
#inline()
<span class="velocity-inline-inner">
$('.lazy.bg2').attr({'data-src':'/img_path2.jpg'}).css('background','red');
#if($myVar == "hi")
$('.someClass).hide()
#elseif($myVar == "there")
$('.lazy.bg1').attr({'data-src':'/img_path.jpg'})
#else
$('.lazy.bg3').attr({'data-src':'/img_path3.jpg'})
#end
$('.lazy.bg2 a').attr({'data-href':'/random-path2.htm'})
$('.lazy.bg1 a').attr({'data-href':'/random-path.htm'})
</span>
#end
I believe once I get the above code working correctly then it should syntax highlight appropriately. The end goal though is to get all of the jQuery method values highlighting. I am going to be handling the selector under a different regex.