admin管理员组

文章数量:1403468

Trying to auto format some HTML in CodeMirror V4. Found the docs on how to do it but it looks like the call editor.autoFormatRange(range.from, range.to) was removed in V3...

Code for V2 is below.

Anyone know how to do it with V4 today?

From: .html

<script>
  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
    lineNumbers: true,
    mode: "htmlmixed"
  });
  CodeMirrormands["selectAll"](editor);

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

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

  function mentSelection(isComment) {
    var range = getSelectedRange();
    editormentRange(isComment, range.from, range.to);
  }      
</script>

Trying to auto format some HTML in CodeMirror V4. Found the docs on how to do it but it looks like the call editor.autoFormatRange(range.from, range.to) was removed in V3...

Code for V2 is below.

Anyone know how to do it with V4 today?

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

<script>
  var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
    lineNumbers: true,
    mode: "htmlmixed"
  });
  CodeMirror.mands["selectAll"](editor);

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

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

  function mentSelection(isComment) {
    var range = getSelectedRange();
    editor.mentRange(isComment, range.from, range.to);
  }      
</script>
Share Improve this question asked Aug 29, 2014 at 4:55 PrecisionPetePrecisionPete 3,4116 gold badges37 silver badges57 bronze badges 4
  • We have also faced this problem, auto formatting add on is removed in the newer version. But the old formatting add on will still work with the new version of the codemirror. We have used codemirror.js version 3_21, with formatting.js version 3_01. – vjy Commented Sep 2, 2014 at 5:52
  • Have you tried it with the V4 codebase? – PrecisionPete Commented Sep 3, 2014 at 14:02
  • No I haven't give a try with V4. I hope it will work – vjy Commented Sep 4, 2014 at 6:08
  • 1 It was removed in CodeMirror 4 because the developer said it was too difficult to maintain. I haven't been able to find a replacement yet. – jnoreiga Commented Dec 2, 2015 at 16:14
Add a ment  | 

2 Answers 2

Reset to default 6

If you put the formatting.js file in the addons folder of codemirror 4 and reference it, the functions will work.

  1. Location: addon/format/formatting.js
  2. include the script file in your html
  3. Call the formatting code (example at http://codemirror/2/demo/formatting.html)

formatting.js

(function() {

  CodeMirror.extendMode("css", {
    mentStart: "/*",
    mentEnd: "*/",
    newlineAfterToken: function(_type, content) {
      return /^[;{}]$/.test(content);
    }
  });

  CodeMirror.extendMode("javascript", {
    mentStart: "/*",
    mentEnd: "*/",
    // FIXME semicolons inside of for
    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);
      }
    }
  });

  var inlineElements = /^(a|abbr|acronym|area|base|bdo|big|br|button|caption|cite|code|col|colgroup|dd|del|dfn|em|frame|hr|iframe|img|input|ins|kbd|label|legend|link|map|object|optgroup|option|param|q|samp|script|select|small|span|strong|sub|sup|textarea|tt|var)$/;

  CodeMirror.extendMode("xml", {
    mentStart: "<!--",
    mentEnd: "-->",
    newlineAfterToken: function(type, content, textAfter, state) {
      var inline = false;
      if (this.configuration == "html")
        inline = state.context ? inlineElements.test(state.context.tagName) : false;
      return !inline && ((type == "tag" && />$/.test(content) && state.context) ||
                         /^</.test(textAfter));
    }
  });

  // Comment/unment the specified range
  CodeMirror.defineExtension("mentRange", 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.mentEnd, to);
        cm.replaceRange(curMode.mentStart, from);
        if (from.line == to.line && from.ch == to.ch) // An empty ment inserted - put cursor inside
          cm.setCursor(from.line, from.ch + curMode.mentStart.length);
      } else { // Unment range
        var selText = cm.getRange(from, to);
        var startIndex = selText.indexOf(curMode.mentStart);
        var endIndex = selText.lastIndexOf(curMode.mentEnd);
        if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
          // Take string till ment start
          selText = selText.substr(0, startIndex)
          // From ment start till ment end
            + selText.substring(startIndex + curMode.mentStart.length, endIndex)
          // From ment end till string end
            + selText.substr(endIndex + curMode.mentEnd.length);
        }
        cm.replaceRange(selText, from, to);
      }
    });
  });

  // 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");
      }
    });
  });

  // Applies automatic formatting to the specified range
  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 && i < text.length - 1) 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));
    });
  });
})();

You can use any 3rd party formatting tools, like JS Beautifier (it supports CSS, HTML and JS)

  1. Add custom button
  2. Add onclick handler for it
  3. Use editor.getValue() and editor.setValue(string) from API

jQuery(function($) {
  var editor = CodeMirror.fromTextArea($('#code')[0], {
    lineNumbers: true,
    mode: 'text/javascript',
    theme: 'oceanic-next'
  });

  $('#format').on('click', function() {
    editorContent = editor.getValue();
    editorContent = js_beautify(editorContent, {indent_with_tabs: true});
    editor.setValue(editorContent);
    editor.refresh();
  });
});
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/codemirror/5.60.0/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/codemirror/5.60.0/mode/javascript/javascript.min.js" rel="stylesheet"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/js-beautify/1.13.5/beautify.min.js"></script>
<link href="https://cdnjs.cloudflare./ajax/libs/codemirror/5.60.0/codemirror.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare./ajax/libs/codemirror/5.60.0/theme/oceanic-next.min.css" rel="stylesheet"/>
<button id="format">Format</button>
<textarea id="code">var APP_ID = "APP_ID";
(function(){var w=window;var ic=w.Inter;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.interSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Inter=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.inter.io/widget/' + APP_ID;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);};if(document.readyState==='plete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
</textarea>

本文标签: javascriptAnyone know what happened to the AutoFormat feature in CodeMirrorStack Overflow