Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Codemirror Auto Format after setValue

http://liveweave.com/UxEJ0s

I'm using Codemirror for my app.

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

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?

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.

Any help is greatly appreciated.

like image 741
Michael Schwartz Avatar asked Aug 03 '14 22:08

Michael Schwartz


People also ask

How do I use CodeMirror in textarea?

This could be used to, for example, replace a textarea with a real editor: var myCodeMirror = CodeMirror(function(elt) { myTextArea. parentNode. replaceChild(elt, myTextArea); }, {value: myTextArea.

How do I set up CodeMirror?

Download CodeMirror files. Download jQuery file. Inside the codemirror project folder create subfolders and name them js, css and plugin. The js folder will hold all the javascript files.


2 Answers

autoFormatRange was removed from codemirror, so we should use another way, register our own extension:

1. generate js

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

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

2. Select options desired

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

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

like image 143
shukshin.ivan Avatar answered Nov 01 '22 02:11

shukshin.ivan


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

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 });
like image 28
RajV Avatar answered Nov 01 '22 01:11

RajV