首页 > 解决方案 > 基于 javascript 的自定义代码编辑器的缩进

问题描述

我正在为自己创建的语言制作自定义代码编辑器。到目前为止,我已经使用 javascriprt span 类实现了语法高亮。现在我想在 IF ELSE 嵌套循环前面添加适当的间距或制表符空间。我不太擅长 javascript。

以下是我到目前为止编写的代码。

<!DOCTYPE html>
<html>
    <body>

        <style>
            .code-str { color: #008000; }
            .code-elem{ color: #ff0000;}
            .code-comment { color: #0000FF; }
        </style>



<textarea rows="20" cols="100" type="text" id="text2">Code to test

###IFLISTING:7786###

    replaces

###ENDIFLISTING:7786###


Paste this code in the text area below and see the magic </textarea>

        <textarea rows="20" cols="100" type="text" id="text1"></textarea>

        <button onclick="myFunction()">MAGIC</button>

        <script>
            function myFunction() {



                var str = document.getElementById("text1").value;

                str = str.replace(/###IF(.*?)###/g, '<span class="code-elem"></br> </br>###IF$1### </br></span>'); 
                str = str.replace(/###ENDIF(.*?)###/g, '<span class="code-elem"></br> ###ENDIF$1### </br></span>');
                str = str.replace(/###IFLISTING(.*?)###/g, '<span class="code-str">  ###IFLISTING$1### </span>');
                str = str.replace(/###ENDIFLISTING(.*?)###/g, '<span class="code-str">###ENDIFLISTING$1### </span>');
                str = str.replace(/###VAR(.*?)###/g, '<span class="code-comment"> ###VAR$1### </span>');
                 str = str.replace(/###LISTING(.*?)###/g, '<span class="code-comment">  ###LISTING$1### </span>');

                document.getElementById("demo").innerHTML = str;
            }
        </script>


        <p id="demo"></p>
    </body>
</html>

这是代码的输出

现在我想要的是嵌套的 IF ELSE 循环应该通过适当的缩进清楚地看到。我心中有一些粗略的看法。我想我应该使用 FOR 循环,然后使用计数器来增加 IF 和 ELSE 计数。但我不知道该怎么做。谁能给我一个想法?

我会非常感谢最小的帮助或建议。

标签: javascripthtmlregex

解决方案


您将不得不迭代所有行,不仅是那些具有匹配关键字的行,然后保持当前缩进,您为某些关键字增加该缩进,而为其他一些关键字减少该缩进。我会将这种缩进影响存储为每个关键字的属性,在它们的样式属性旁边:

const keywords = {
    IF: { style: "code-elem", indent: 4 },
    ENDIF: { style: "code-elem", indent: -4 },
    IFLISTING: { style: "code-str", indent: 4 },
    ENDIFLISTING: { style: "code-str", indent: -4 },
    VAR: { style: "code-comment", indent: 0 },
    LISTING: { style: "code-comment", indent: 0 } 
};

function myFunction() {
    let indent = 0;
    document.getElementById("demo").innerHTML = document.getElementById("text1").value.split(/[\r\n]+/).map(line => {
        const oldIndent = indent;
        line = line.trim().replace(/###([A-Z]+)(.*?)###/g, (m, keyword, arg) => {
            const param = keywords[keyword];
            if (!param) return m;
            indent += param.indent;
            return `<span class="${param.style}">${m}</span>`;
        });
        return "&nbsp;".repeat(Math.min(indent, oldIndent)) + line;
    }).join("<br>");
}
.code-str     { color: #080; }
.code-elem    { color: #f00;}
.code-comment { color: #00f; }
<textarea rows="15" cols="80" type="text" id="text1">###VAR:837:Single###
###IF:69154!=1###
###IF:69154!=1###
 ###VAR:69154:Single###x
###ENDIF:69154###
    ###VAR:69154:Single###x
###ENDIF:69154###
###VAR:990:Single### battery ###VAR:S301:Single###mAh (###VAR:S302:Single###V) 
###IFLISTING:7785###
       replaces
   ###ENDIFLISTING:7785###
###IFLISTING:7786###
    replaces
###ENDIFLISTING:7786###
</textarea><br>
<button onclick="myFunction()">MAGIC</button>
<p id="demo"></p>


推荐阅读