Как использовать валидатор редактора Ace без создания экземпляра редактора Ace?

Я использую react-ace для создания текстового редактора CSS в своем приложении React.

Это похоже на что-то...

import Ace from 'react-ace'

...
  <Ace 
    mode="css" 
    value={value} 
    onChange={onValueChange} 
    onValidate={onValidate} 
    ...
  />
...

Это прекрасно работает и прекрасно — выделяет синтаксические ошибки и предупреждения CSS. Кроме того, onValidate возвращает структуру данных "аннотации" ошибок/предупреждений.

Однако в другом месте приложения необходимо запустить тот же валидатор, который используется в этом компоненте React Ace, но вне контекста этого компонента. По сути, мне нужно передать содержимое в value через систему аннотаций ошибок/предупреждений, но я не могу создать экземпляр этого элемента реакции.

Я пробовал следующее:

import { EditSession } from 'brace'; # "brace" is the "module" compatible version of the ace editor that our "react-ace" uses
import 'brace/mode/css';

export const getCssAnnotations = (value)=> {
  const editSession = new EditSession(value);
  editSession.setMode('ace/mode/css');
  const annotations = editSession.getAnnotations();
  return annotations;
};

Однако аннотации, возвращаемые этой функцией, всегда []! Я предполагаю, что это связано с тем, что я просто обращаюсь к интерфейсу установки/получения аннотаций, а не запускаю создателя аннотаций. Но я не могу понять, что на самом деле аннотации работают нормально.

Я просмотрел документы по Создание подсветки синтаксиса для Ace, но не Не понимаю, нужно ли/почему здесь должен быть задействован веб-работник.

Спасибо!


person Chris W.    schedule 26.03.2019    source источник


Ответы (1)


Это не работает, потому что editSession использует веб-воркер для создания аннотаций, которые являются асинхронными:

editSession.on('changeAnnotation', () => {
    let annotations = editSession.getAnnotations();
    callback(null, annotations)
});

документы

Обратите внимание, что в настоящее время каждый editSession создает нового работника, поэтому лучше использовать setValue для существующего экземпляра editSession или вызывать editSession.destroy() перед вызовом обратного вызова.


Таким образом, полное решение может выглядеть так:

const getAnnotationsPromise = (value, mode)=> {
  const editSession = new EditSession(value);
  editSession.setMode(`ace/mode/${mode}`);

  return new Promise((resolve)=> {
    editSession.on('changeAnnotation', () => {
      const annotations = editSession.getAnnotations();
      editSession.removeAllListeners('changeAnnotation');
      editSession.destroy();
      resolve(annotations);
    });
  });
};
person Michael Doye    schedule 26.03.2019
comment
Потрясающий! Это было именно то, что мне было нужно! Большое спасибо! - person Chris W.; 27.03.2019