javascript setValue 后的 Codemirror 自动格式化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25109809/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 03:58:00  来源:igfitidea点击:

Codemirror Auto Format after setValue

javascriptjquerycodemirror

提问by Michael Schwartz

http://liveweave.com/UxEJ0s

http://liveweave.com/UxEJ0s

I'm using Codemirror for my app.

我正在为我的应用程序使用 Codemirror。

I noticed if I select all the text and press SHIFT+Tab it will auto align my code making it easier to read.

我注意到如果我选择所有文本并按 SHIFT+Tab,它会自动对齐我的代码,使其更易于阅读。

Here's an example of what my app currently renders...

这是我的应用程序当前呈现的示例...

<ul>
<li>
<font color="#f90000">
  Apples
</font>
</li>
<li>
<font color="#ff9a3d">
  Oranges
</font>
</li>
</ul>

Here's what I'm trying to get it to render.

这是我试图让它呈现的内容。

<ul>
  <li>
    <font color="#f90000">
      Apples
    </font>
  </li>
  <li>
    <font color="#ff9a3d">
      Oranges
    </font>
  </li>
</ul>

EDIT:

编辑

Does anyone know if there's a way to do this without selecting the whole code manually in Codemirror?

有谁知道是否有办法在不在 Codemirror 中手动选择整个代码的情况下做到这一点?

Why? I have Codemirror running in my background of my app all code that's added is added dynamically, but when I save the final code it looks like above.

为什么?我在我的应用程序的后台运行 Codemirror,所有添加的代码都是动态添加的,但是当我保存最终代码时,它看起来像上面一样。

Any help is greatly appreciated.

任何帮助是极大的赞赏。

回答by shukshin.ivan

autoFormatRangewas removedfrom codemirror, so we should use another way, register our own extension:

autoFormatRange已从codemirror中删除,因此我们应该使用另一种方式,注册我们自己的扩展:

1. generate js

1.生成js

Go to js generator (just an easy way to get minified js with plugins and custom extensions). http://codemirror.net/doc/compress.html

转到 js 生成器(这是使用插件和自定义扩展获取缩小 js 的简单方法)。http://codemirror.net/doc/compress.html

Updated link for version 3: http://codemirror.net/3/doc/compress.html

版本 3 的更新链接:http: //codemirror.net/3/doc/compress.html

2. Select options desired

2. 选择所需的选项

Paste custom extension code and press "Compress" button.

粘贴自定义扩展代码并按“压缩”按钮。

CodeMirror.defineExtension("autoFormatRange", function (from, to) {
    var cm = this;
    var outer = cm.getMode(), text = cm.getRange(from, to).split("\n");
    var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
    var tabSize = cm.getOption("tabSize");

    var out = "", lines = 0, atSol = from.ch == 0;
    function newline() {
        out += "\n";
        atSol = true;
        ++lines;
    }

    for (var i = 0; i < text.length; ++i) {
        var stream = new CodeMirror.StringStream(text[i], tabSize);
        while (!stream.eol()) {
            var inner = CodeMirror.innerMode(outer, state);
            var style = outer.token(stream, state), cur = stream.current();
            stream.start = stream.pos;
            if (!atSol || /\S/.test(cur)) {
                out += cur;
                atSol = false;
            }
            if (!atSol && inner.mode.newlineAfterToken &&
                inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state))
                newline();
        }
        if (!stream.pos && outer.blankLine) outer.blankLine(state);
        if (!atSol) newline();
    }

    cm.operation(function () {
        cm.replaceRange(out, from, to);
        for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
            cm.indentLine(cur, "smart");
    });
});

// Applies automatic mode-aware indentation to the specified range
CodeMirror.defineExtension("autoIndentRange", function (from, to) {
    var cmInstance = this;
    this.operation(function () {
        for (var i = from.line; i <= to.line; i++) {
            cmInstance.indentLine(i, "smart");
        }
    });
});

3. Use generated .js as follows

3.使用生成的.js如下

Html:

网址:

<textarea id=code><?=$value?></textarea>

<link rel="stylesheet" href="/codemirror/codemirror.css">
<script src="/codemirror/codemirror-compressed.js"></script>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
    lineNumbers: true,
    mode: "text/html"
});
var totalLines = editor.lineCount();  
editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
</script>

Code was found here

代码在这里找到

回答by RajV

Ever since Codemirror has removed support for autoFormatRange()it's not worth the trouble to use it for formatting text. I use js-beautifyinstead.

自从 Codemirror 取消autoFormatRange()了对使用它来格式化文本的支持是不值得的。我用js-beautify代替。

var beautify_js = require('js-beautify').js_beautify
var beautify_html = require('js-beautify').html

var formattedJSON = beautify_js(jsonText, { indent_size: 2 });
var formattedXML = beautify_html(xmlText, { indent_size: 2 });

回答by djadmin

You can use the following code to achieve what you want :

您可以使用以下代码来实现您想要的:

function format() {
    var totalLines = editor.lineCount();  
    editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
}

Bind this function with your events, and it will auto-format the code.

将此函数与您的事件绑定,它将自动格式化代码。

回答by vjy

By using codemirrorformatting add-on you can achieve your requirement

通过使用codemirror格式化插件,您可以实现您的要求

JSFiddle Demo

JSFiddle 演示

 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
        lineNumbers: true,
        mode: "htmlmixed",
        extraKeys:{"Shift-Tab":autoFormatSelection}
      });


      function getSelectedRange() {
        return { from: editor.getCursor(true), to: editor.getCursor(false) };
      }

      function autoFormatSelection() {
        var range = getSelectedRange();
        editor.autoFormatRange(range.from, range.to);
      }

Source Link

来源链接

http://codemirror.net/2/demo/formatting.html

http://codemirror.net/2/demo/formatting.html

回答by iole

Here is the original addon including a small update to let it work with CodeMirror V3 :

这是原始插件,包括一个小更新,让它与 CodeMirror V3 一起工作:

CodeMirror.extendMode("css", {
    commentStart: "/*",
    commentEnd: "*/",
    newlineAfterToken: function(type, content) {
        return /^[;{}]$/.test(content);
    }
});

CodeMirror.extendMode("javascript", {
    commentStart: "/*",
    commentEnd: "*/",    
    newlineAfterToken: function(type, content, textAfter, state) {
        if (this.jsonMode) {
            return /^[\[,{]$/.test(content) || /^}/.test(textAfter);
        } else {
            if (content == ";" && state.lexical && state.lexical.type == ")") return false;
        return /^[;{}]$/.test(content) && !/^;/.test(textAfter);
        }
    }
});

CodeMirror.extendMode("xml", {
    commentStart: "<!--",
    commentEnd: "-->",
    newlineAfterToken: function(type, content, textAfter) {    
        return ( type == "tag" && />$/.test(content) || /^</.test(textAfter) ) || (  type == "tag bracket" && />$/.test(content) );
    }
});


CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
    var cm = this, curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode;
    cm.operation(function() {
        if (isComment) { // Comment range
            cm.replaceRange(curMode.commentEnd, to);
            cm.replaceRange(curMode.commentStart, from);
        if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
            cm.setCursor(from.line, from.ch + curMode.commentStart.length);
        } else { // Uncomment range
            var selText = cm.getRange(from, to);
            var startIndex = selText.indexOf(curMode.commentStart);
            var endIndex = selText.lastIndexOf(curMode.commentEnd);
            if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
                // Take string till comment start
                selText = selText.substr(0, startIndex)
                // From comment start till comment end
                + selText.substring(startIndex + curMode.commentStart.length, endIndex)
                // From comment end till string end
                + selText.substr(endIndex + curMode.commentEnd.length);
            }
            cm.replaceRange(selText, from, to);
        }
    });
});


CodeMirror.defineExtension("autoIndentRange", function (from, to) {
    var cmInstance = this;
    this.operation(function () {
        for (var i = from.line; i <= to.line; i++) {
            cmInstance.indentLine(i, "smart");
        }
    });
});


CodeMirror.defineExtension("autoFormatRange", function (from, to) {
    var cm = this;
    var outer = cm.getMode(), text = cm.getRange(from, to).split("\n");        
    var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
    var tabSize = cm.getOption("tabSize");

    var out = "", lines = 0, atSol = from.ch == 0;
    function newline() {
      out += "\n";
      atSol = true;
      ++lines;
    }

    for (var i = 0; i < text.length; ++i) {
      var stream = new CodeMirror.StringStream(text[i], tabSize);      
      while (!stream.eol()) {
        var inner = CodeMirror.innerMode(outer, state);   
        var style = outer.token(stream, state), cur = stream.current();
        stream.start = stream.pos;
        if (!atSol || /\S/.test(cur)) {
          out += cur;
          atSol = false;
        }

        if (!atSol && inner.mode.newlineAfterToken &&
            inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state))
          newline();        
      }
      if (!stream.pos && outer.blankLine) outer.blankLine(state);
      if (!atSol)newline();
    }

    cm.operation(function () {
      cm.replaceRange(out, from, to);
      for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
        cm.indentLine(cur, "smart");
      cm.setSelection(from, cm.getCursor(false));
    });
});