CodeMirror2: Как отформатировать вставленный контент?

Можно ли отформатировать вставленный контент после такого события, как «onPaste» в CodeMirror2? - Я хочу сделать отступ содержимого буфера обмена после вставки. Я уже знаю, что с помощью JavaScript невозможно получить доступ к буферу обмена.

Так что я думаю, что также нет возможности создать контекстное меню с функциями вырезания/копирования/вставки? - Могу ли я создать свой собственный JS-буфер обмена или существует существующее решение?

Спасибо! Лекс


person agassner    schedule 21.05.2012    source источник


Ответы (4)


Мне потребовалось некоторое время, чтобы решить это, поэтому, если это кому-то поможет, вот как я перехватываю пасты и заменяю каждую вкладку двумя пробелами:

editor.on("beforeChange", (cm, change) => {
  if(change.origin === "paste") {
    const newText = change.text.map(line => line.replace(/\t/g, "  "));
    change.update(null, null, newText);
  }
});
person Community    schedule 17.06.2019

CodeMirror имеет собственное событие inputRead, поэтому вы можете сделать это:

editor.on('inputRead', function(cm, event) {
    /* event -> object{
         origin: string, can be '+input', '+move' or 'paste'
             doc for origins >> http://codemirror.net/doc/manual.html#selection_origin
         from: object {line, ch},
         to: object {line, ch},
         removed: array of removed strings
         text: array of pasted strings
    } */
    if (event.origin == 'paste') {
        console.log(event.text);
        var text = event.text[0]; // pasted string
        var new_text = '['+text+']'; // any operations here
        cm.refresh();
        // my first idea was
        // note: for multiline strings may need more complex calculations
        cm.replaceRange(new_text, event.from, {line: event.from.line, ch: event.from.ch + text.length});
        // first solution did'nt work (before i guess to call refresh) so i tried that way, works too
        /* cm.execCommand('undo');
        cm.setCursor(event.from);
        cm.replaceSelection(new_text); */
    }
});

А также есть другие события "вырезать", "копировать" и "вставить" (http://codemirror.net/doc/manual.html#events), так что это будет работать:

editor.on('paste', function(cm, event) { ... } );

Кроме того, вы можете отменить событие, вызвав event.preventDefault(); но получение вставленного текста является проблемой.

В настоящее время я работаю над похожей вещью - перехватываю события копирования/вставки и делаю некоторые замены. Я нашел решение для программного копирования текста в буфер обмена. Это clipboard.js обсуждается здесь Предоставляет ли codemirror API вырезания, копирования и вставки?. Самое замечательное, что вы можете запускать событие клика программно (это было проблемой, когда я использовал ZeroClipboard с кросс-браузерной прокладкой флэш-памяти), и это будет работать!

new Clipboard('.btn-copy', {
    text: function(trigger) {
        var text = editor.getValue(); // or editor.getSelection();
        return text.replace(/\s+/g,' ');
    }
});

editor.on('copy', function(cm, event) {
    $('.btn-copy').click();
    event.preventDefault();
});
person NesCafe Zos42    schedule 03.04.2016

Единственное решение, которое я нашел, это перехватить даже использование inputRead, а затем вручную изменить вставленное содержимое. Я сделал общую функцию, которую вы могли бы использовать повторно:

class CodeMirrorExt {
    // This function returns a callback to be used with codemirror's inputRead event.
    // The intent is to intercept a pasted text, transform the pasted contents (each line) with the function
    // you provide, and then have that transformed content be what ends up in the editor.
    //
    // Usage example that cuts each pasted line to 10 chars:
    //
    // this.codemirror.on("inputRead", CodeMirrorExt.replaceTextOnPasteFunc((line) => {
    //     return line.slice(0, 10);
    // }));

    static replaceTextOnPasteFunc(transformFunc) {
        return ((doc, event) => {
            if (event.origin !== "paste") {
                return;
            }

            const firstText = event.text[0];
            const lineNum = event.from.line;
            const chNum = event.from.ch;

            const newTexts = event.text.map(transformFunc);

            newTexts.forEach((text, i) => {
                if (i == 0) {
                    doc.replaceRange(text, {line: lineNum, ch: chNum}, {line: lineNum, ch: chNum + firstText.length});
                }
                else {
                    doc.replaceRange(text, {line: lineNum + i, ch: 0}, {line: lineNum + i, ch: event.text[i].length});
                }
            })
        });
    }
}

export default CodeMirrorExt;
person rogercampos    schedule 27.02.2018

Используя js-beautify, вы можете украсить значение редактора во время paste события на .CodeMirror лайке так:

$(document).on('paste', '.CodeMirror', function(e) {
    var content = $(this).closest('.content');
    var editor = content[0].editor;

    // beautify the code
    editor.setValue( js_beautify( editor.getValue(), { indent_size: 2 } ) );
});

Имейте в виду, что при вставке текста в редактор он прослушивает первый отступ, поэтому, если ваша первая строка имеет отступ, все остальные строки будут иметь соответствующий отступ.

пример:

    function something() { // if the start is indented like so,
        var blah = something; // next lines will follow
    }
person Souleste    schedule 15.08.2019