我一直在为Velocity稍微修改的版本编写语法高亮笔。简而言之,我如何包装所有的内容,从#inline()
开始,以相应的#end
结束,在可以有0-无限if语句的条件下,总是有一个#end
。如果你有任何问题,请告诉我。
示例可以在此提琴上找到。详细信息见下文
示例HTML
显示了下面html的javascript修改后的版本。
<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>
由于有#end
的多个实例,我不确定如何使它与#inline()
语句的结尾相匹配。主要的问题是可能有无限个if语句,但是#inline()
总是有一个相应的结束语句。所以我猜最好的方法是基于相同的空白级别来匹配它。然而,我不确定是否有更好的解决方案。我在Gone Coding的帖子中找到了原始的javascript。然而,我稍微修改了它,以更好地匹配我的实现。注意,我在之前的jQuery语句中将velocity类添加到<pre>
中。最终结果应该只将<span>
应用于#inline()
内的jQuery。
$('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>');
}
});
更新Javascript
我有以下可以计算空白并选择与#inline()
的空白级别匹配的#end
,但是我有在if语句中将该子字符串转换为html的问题。
$('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;
}
}
}
最终目标HTML
最终结果应该如下所示。我已经在#inline()
和#end
周围添加了一个跨度。
#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
我相信一旦我得到上面的代码工作正确,那么它应该语法高亮适当。最终的目标是突出显示所有的jQuery方法值。我将在不同的正则表达式下处理选择器
我快速浏览了一下您的代码,但它有点像野兽。所以我会给出一个更一般的概述。首先,您需要能够(在一定程度上)解析输入的某些部分(为此,使用#inline、#if和#end)。然后,您需要计算以#end结束的开口的数量。然后,当每个#end出现时,你检查列表上最新的开放。当你到达#end时,它会关闭开头的#inline,这就是你关闭</span>
的地方。
注意:我还没有测试代码。我不知道代码最初是如何工作的等等。我只是用它作为伪代码来展示你需要做的事情。
$('pre.velocity code').each(function () {
var open = [];
var result = $();
$(this).contents().each(function () {
var $this = $(this);
if ($this.text() == "#inline()" || $this.text().substr("#if(") === 0) {
open.push($this);
}
else if ($this.text() == "#end") {
var toClose = open.pop();
if (toClose.text() === "#inline()") {
// wrap from after #inline() to before #end
}
}
});
});
我最终做了下面的js和html来包装#inline()
和相应的#end
基于空白。这是小提琴呈现的html。
// Loop thorugh each of the velocity and see if there is an inline to syntax highlight.
$('pre.velocity code').each(function(){
var html = $(this).html();
var str = html.toString(html); // convert html object to a string
str = str.substring(str.indexOf("#inline()") + 17); // split the string so only take half of it.
var textArray = str.split("n"); // split the array on a new line
var newHtml = getInlineEnd(textArray);
regExVelocity($(this),str,newHtml); // replace the string
});
/**
* Loops through the inline and finds the #end based on white-space
* @param textArray
* @type Array
* @returns {string|*}
*/
function getInlineEnd(textArray) {
// loop through each line of the string.
for(var i = 0; i <= textArray.length; i++) {
if(i == 0) {
// first line in #inline()
textArray[i] = "<span class="velocity-inline-inner">"+textArray[i]
}
if(undefined !== textArray[i] && textArray[i].length === 38 && textArray[i] === "<span class="velocity-end">#end</span>") {
// Found the end of the #inline() based on white-space. Update the text.
textArray[i] = textArray[i].replace(textArray[i],'</span><span class="velocity-end">#end</span>');
// break out of the for loop since we got the value
break;
}
}
// return the string and reformat it.
return textArray.join('n');
}
/**
* Runs regex for velocity syntax highlighting uses .html() if you want to use the text then use regExText
* @param selector
* @param regex
* @param output
*/
function regExVelocity(selector, regex, output) {
selector.html(function(i, html) {
return( html.replace(regex, output));
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre class="velocity"><code>
<span class="velocity-object">$javascript</span>.push(<span class="velocity-string">"/path/to/file"</span>)
<span class="velocity-inline">#inline()</span>
$('.lazy.bg2').attr({'data-src':'/img_path2.jpg'}).css('background','red');
<span class="velocity-if">#if(</span><span class="velocity-if-inner">$myVar == "hi"</span><span class="velocity-if">)</span>
#elseif($myVar == "there")
$('.lazy.bg1').attr({'data-src':'/img_path.jpg'})
#else
$('.lazy.bg3').attr({'data-src':'/img_path3.jpg'})
<span class="velocity-end">#end</span>
$('.lazy.bg1 a').attr({'data-href':'/random-path.htm'})
<span class="velocity-end">#end</span>
<span class="velocity-if">#if(</span><span class="velocity-if-inner"><span class="velocity-object">$test</span>.method == "myVal"</span><span class="velocity-if">)</span>
<span class="velocity-set">#set(</span><span class="velocity-inner"><span class="velocity-variable">$foo </span><span class="equalSign">=</span> "swag"</span><span class="velocity-set">)</span>
#elseif($foo == "bar")
<span class="velocity-set">#set(</span><span class="velocity-inner"><span class="velocity-variable">$foo </span><span class="equalSign">=</span> "ballin"</span><span class="velocity-set">)</span>
#elseif(<span class="velocity-object">$myObject</span>.randomMethod().contains(<span class="velocity-string">"myVal"</span>))
<span class="velocity-set">#set(</span><span class="velocity-inner"><span class="velocity-variable">$foo </span><span class="equalSign">=</span> "weeee"</span><span class="velocity-set">)</span>
#else
<span class="velocity-set">#set(</span><span class="velocity-inner"><span class="velocity-variable">$foo </span><span class="equalSign">=</span> "sad days"</span><span class="velocity-set">)</span>
<span class="velocity-end">#end</span>
<span class="velocity-set">#set(</span><span class="velocity-inner"><span class="velocity-variable">$testVar </span><span class="equalSign">=</span> "Test value"</span><span class="velocity-set">)</span>
<span class="velocity-parse">#parse(</span><span class="velocity-parse-path">"/path/to/file"</span><span class="velocity-parse">)</span></code></pre>