将javascript生成的html结构包装在具有多个端点实例的span中



我一直在为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。

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>');
    }
});

更新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>

最新更新