1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/aomao-am-editor

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Здесь представлен новый редактор с богатым текстовым форматированием, названный Editable, который не использует встроенное свойство contenteditable, а вместо этого применяет кастомный рендерер. Такой подход позволяет нам лучше контролировать поведение редактора.

am-editor

Разработанный редактор с богатым текстовым форматированием, поддерживающий совместное редактирование, вы можете свободно использовать React, Vue и другие популярные библиотеки фронтенд-разработки для расширения и определения плагинов.

Просмотреть · Документация · Плагины

[**`Vue 2`**](https://github.com/zb201307/am-editor-vue2)

Vue 3

React

Vue 2 Demo

Vue 2 Nuxt Demo## Возможности

  • 🎁 Готовое решение с десятками богатых плагинов для удовлетворения большинства потребностей
  • 🚀 Высоко расширяемо; помимо базовых плагинов для маркировки, встроенной и блочной типизации, мы также предоставляем компоненты карточек, объединённые с библиотеками фронтенда, такими как React и Vue для отображения пользовательского интерфейса плагинов
  • 🎨 Поддержка многоформатного мультимедийного контента, поддерживающего не только изображения и аудио/видео, но и встраиваемого мультимедийного контента
  • 📝 Поддерживает синтаксис Markdown
  • 🌍 Поддерживает международализацию
  • 💻 Двигатель, написанный полностью на JavaScript, без использования любых библиотек фронтенда; плагины могут быть отображены с использованием библиотек фронтенда, таких как React и Vue. Легко управляет сложной архитектурой
  • 👥 Встроенное решение совместной работы над редактированием, простая конфигурация для использования
  • 📱 Совместимо со большинством последних мобильных браузеров

Плагины

Пакет Версия Размер Описание
@aomao/toolbar Панель инструментов, подходящая для React
@aomao/toolbar-vue Панель инструментов, подходящая для Vue3
am-editor-toolbar-vue2 Панель инструментов, подходящая для Vue2
@aomao/plugin-alignment ugin-alignment/dist/index.js)
@aomao/plugin-embed Вставка URL
@aomao/plugin-backcolor Цвет фона
@aomao/plugin-bold Жирный шрифт
@aomao/plugin-code Код
@aomao/plugin-fontsize Размер шрифта
@aomao/plugin-header Заголовок
@aomao/plugin-image Изображение
@aomao/plugin-indentation Отступ
@aomao/plugin-italic Курсив
@aomao/plugin-link Ссылка
@aomao/plugin-list Список
@aomao/plugin-quote Цитата
@aomao/plugin-strikethrough Зачеркнутый текст
@aomao/plugin-subscript Нижний индекс
@aomao/plugin-superscript Верхний индекс
@aomao/plugin-table js) Таблица
@aomao/plugin-text Версия Размер Текстовый формат
@aomao/plugin-underline Версия Размер Подчеркивание
@aomao/plugin-video Версия Размер Видео
@aomao/plugin-code Версия Размер Встроенный код
@aomao/plugin-codeblock Версия Размер Кодовый блок, подходящий для React
@aomao/plugin-codeblock-vue Версия Размер Кодовый блок, подходящий для Vue3
am-editor-codeblock-vue2 ```markdown
Кодовый блок, подходящий для Vue2 Версия Размер
--- --- ---
@aomao/plugin-fontcolor Версия Размер Цвет шрифта
@aomao/plugin-fontfamily Версия Размер Шрифтовая семья
@aomao/plugin-fontsize Версия Размер Размер шрифта
@aomao/plugin-heading Версия Размер Заголовок
@aomao/plugin-hr Версия Размер Горизонтальная линия
com/@aomao/plugin-hr/dist/index.js?compression=gzip&label= )(<https://unpkg.com/@aomao/plugin-hr/dist/index.js>) | Горизонтальная черта
| [`@aomao/plugin-indent`](./plugins/indent) | ![npm version](https://img.shields.io/npm/v/@aomao/plugin-indent.svg?maxAge=3600&label=&colorB=007ec6)(./plugins/indent/package.json) | ![gzip size](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-indent/dist/index.js?compression=gzip&label=)(https://unpkg.com/@aomao/plugin-indent/dist/index.js) | Отступ
| [`@aomao/plugin-indent`](./plugins/indent) | ![npm version](https://img.shields.io/npm/v/@aomao/plugin-indent.svg?maxAge=3600&label=&colorB=007ec6)(./plugins/indent/package.json) | ![gzip size](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-indent/dist/index.js?compression=gzip&label=)(https://unpkg.com/@aomao/plugin-indent/dist/index.js) | Отступ
| [`@aomao/plugin-italic`](./plugins/italic) | ![npm version](https://img.shields.io/npm/v/@aomao/plugin-italic.svg?maxAge=3600&label=&colorB=007ec6)(./plugins/italic/package.json) | ![gzip size](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-italic/dist/index.js?compression=gzip&label=)(https://unpkg.com/@aomao/plugin-italic/dist/index.js) | Курсив
| [`@aomao/plugin-link`](./plugins/link) | ![npm version](https://img.shields.io/npm/v/@aomao/plugin-link.svg?maxAge=3600&label=&colorB=007ec6)(./plugins/link/package.json) | ![gzip size](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-link/dist/index.js?compression=gzip&label=)(https://unpkg.com/@aomao/plugin-link/dist/index.js) | Ссылка, подходящая для `React`
| [`@aomao/plugin-link-vue`](./plugins/link-vue) | ![npm version](https://img.shields.io/npm/v/@aomao/plugin-link-vue.svg?maxAge=3600&label=&colorB=007ec6)(./plugins/link-vue/package.json)
```/plugins/link-vue/package.json) |              [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-link-vue/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-link-vue/dist/index.js) | Ссылка, предназначенная для `Vue3`   |
| [`am-editor-link-vue2`](https://github.com/zb201307/am-editor-vue2/tree/main/packages/link)               |               [![](https://img.shields.io/npm/v/am-editor-link-vue2.svg?maxAge=3600&label=&colorB=007ec6)](https://github.com/zb201307/am-editor-vue2/tree/main/packages/link/package.json) |             [![](http://img.badgesize.io/https://unpkg.com/am-editor-link-vue2/dist/index.js?compression=gzip&label=)](https://unpkg.com/am-editor-link-vue2/dist/index.js) | Ссылка, предназначенная для `Vue2`   |
| [`@aomao/plugin-line-height`](./plugins/line-height)                                                     |                                                     [![](https://img.shields.io/npm/v/@aomao/plugin-line-height.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/line-height/package.json) || [`@aomao/plugin-line-height`](./plugins/line-height) | [![](https://img.shields.io/npm/v/@aomao/plugin-line-height.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/line-height/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-line-height/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-line-height/dist/index.js) | Высота строки |
| [`@aomao/plugin-mark`](./plugins/mark) | [![](https://img.shields.io/npm/v/@aomao/plugin-mark.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/mark/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-mark/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-mark/dist/index.js) | Зачёркивание |
| [`@aomao/plugin-mention`](./plugins/mention) | [![](https://img.shields.io/npm/v/@aomao/plugin-mention.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/mention/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-mention/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-mention/dist/index.js) | Упоминание |
| [`@aomao/plugin-orderedlist`](./plugins/orderedlist) | [![](https://img.shields.io/npm/v/@aomao/plugin-orderedlist.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/orderedlist/package.json) | [!```
[](/http://img.shields.io/https://unpkg.com/%40aomao/plugin-orderedlist/dist/index.js?compression=gzip&label=)/](https://unpkg.com/%40aomao/plugin-orderedlist/dist/index.js) | Нумерованный список |
| [`@aomao/plugin-paintformat`](./plugins/paintformat) | ![](https://img.shields.io/npm/v/%40aomao/plugin-paintformat.svg?maxAge=3600&label=)&nbsp;![](http://img.shields.io/badge.compression--gzip-green.svg)| ![](http://img.badgesize.io/https://unpkg.com/%40aomao/plugin-paintformat/dist/index.js?compression=gzip&label=)/](https://unpkg.com/%40aomao/plugin-paintformat/dist/index.js) | Форматирование кистью |
| [`@aomao/plugin-quote`](./plugins/quote) | ![](https://img.shields.io/npm/v/%40aomao/plugin-quote.svg?maxAge=3600&label=)&nbsp;![](http://img.badgesize.io/https://unpkg.com/%40aomao/plugin-quote/dist/index.js?compression=gzip&label=)/](https://unpkg.com/%40aomao/plugin-quote/dist/index.js) | Цитата |
| [`@aomao/plugin-redo`](./plugins/redo) | ![](https://img.shields.io/npm/v/%40aomao/plugin-redo.svg?maxAge=3600&label=)&nbsp;![](http://img.badgesize.io/https://unpkg.com/%40aomao/plugin-redo/dist/index.js?compression=gzip&label=)/](https://unpkg.com/%40aomao/plugin-redo/dist/index.js) | Отменить удаление |
| [`@aomao/plugin-removeformat`](./plugins/removeformat) | ![](https://img.shields.io/npm/v/%40aomao/plugin-removeformat.svg?maxAge=3600&label=)&nbsp;![](http://img.badgesize.io/https://unpkg.com/%40aomao/plugin-removeformat/dist/index.js?compression=gzip&label=)/](https://unpkg.com/%40aomao/plugin-removeformat/dist/index.js) | Удалить формат |
| [`@aomao/plugin-selectall`](./plugins/selectall) | ![](https://img.shields.io/npm/v/%40aomao/plugin-selectall.svg?maxAge=3600&label=)
```| [`@aomao/plugin-selectall`](./plugins/selectall)                                                         |                                                                 [![](https://img.shields.io/npm/v/@aomao/plugin-selectall.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/selectall/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-selectall/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-selectall/dist/index.js) | Выбор всего                    |
| [`@aomao/plugin-status`](./plugins/status)                                                              |                                                                 [![](https://img.shields.io/npm/v/@aomao/plugin-status.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/status/package.json)      | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-status/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-status/dist/index.js)     | Статус                        |
| [`@aomao/plugin-strikethrough`](./plugins/strikethrough)                                                |                                                                 [![](https://img.shields.io/npm/v/@aomao/plugin-strikethrough.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/strikethrough/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-strikethrough/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-strikethrough/dist/index.js) | Зачёркивание                  |
| [`@aomao/plugin-sub`](./plugins/sub)                                                                    |                                                                 [![](https://img.shields.io/npm/v/@aomao/plugin-sub.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/sub/package.json)             | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-sub/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-sub/dist/index.js)            | Подстрочный текст             |
| [`@aomao/plugin-sup`](./plugins/sup)                                                                    |                                                                 [![](https://img.shields.io/npm/v/@aomao/plugin-sup.svg?maxAge=3600&label=&colorB=007ec6)](./plugins/sup/package.json)               | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-sup/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-sup/dist/index.js)             | Надстрочный текст             |```markdown
| [`@aomao/plugin-sup`](. /plugins/sup) | Надстрочный текст              |
| [`@aomao/plugin-tasklist`](. /plugins/tasklist) | Список задач                   |
| [`@aomao/plugin-underline`](. /plugins/underline) | Подчеркивание                      |
| [`@aomao/plugin-undo`](. /plugins/undo) | Отмена                             |
| [`@aomao/plugin-unorderedlist`](. /plugins/unorderedlist) | Несắpированный список              |
| [`@aomao/plugin-image`](. /plugins/image) | Изображение                        |
| [`@aomao/plugin-table`](. /plugins/table) | Таблица                            |
| [`@aomao/plugin-file`](. /plugins/file) | Файл                               |
```

Полностью:

```markdown
| [`@aomao/plugin-sup`](. /plugins/sup) | Надстрочный текст              |
| [`@aomao/plugin-tasklist`](. /plugins/tasklist) | Список задач                   |
| [`@aomao/plugin-underline`](. /plugins/underline) | Подчеркивание                  |
| [`@aomao/plugin-undo`](. /plugins/undo) | Отмена                           |
| [`@aomao/plugin-unorderedlist`](. /plugins/unorderedlist) | Несắpированный список         |
| [`@aomao/plugin-image`](. /plugins/image) | Изображение                     |
| [`@aomao/plugin-table`](. /plugins/table) | Таблица                         |
| [`@aomao/plugin-file`](. /plugins/file) | Файл                            |
```| [`@aomao/plugin-file`](. /plugins/file/package.json)                                                                            | [![](https://img.shields.io/npm/v/@aomao/plugin-file.svg?maxAge=3600&label=&colorB=007ec6)](. /plugins/file/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-file/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-file/dist/index.js) | Файл                            |
| [`@aomao/plugin-mark-range`](. /plugins/mark-range)                                                                              | [![](https://img.shields.io/npm/v/@aomao/plugin-mark-range.svg?maxAge=3600&label=&colorB=007ec6)](. /plugins/mark-range/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-mark-range/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-mark-range/dist/index.js) | Выделенный диапазон             |
| [`@aomao/plugin-math`](. /plugins/math)                                                                                           | [![](https://img.shields.io/npm/v/@aomao/plugin-math.svg?maxAge=3600&label=&colorB=007ec6)](. /plugins/math/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-math/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-math/dist/index.js) | Математическая формула           |
| [`@aomao/plugin-video`](. /plugins/video)                                                                                        | [![](https://img.shields.io/npm/v/@aomao/plugin-video.svg?maxAge=3600&label=&colorB=007ec6)](. /plugins/video/package.json) | [![](http://img.badgesize.io/https://unpkg.com/@aomao/plugin-video/dist/index.js?compression=gzip&label=)](https://unpkg.com/@aomao/plugin-video/dist/index.js) | Видео                           |

## Начало работы### Установка

Редактор состоит из `engine`, `toolbar` и `plugins`. `engine` предоставляет основные возможности редактирования.

Используйте `npm` или `yarn` для установки пакета engine.

```bash
$ npm install @aomao/engine
# или
$ yarn add @aomao/engine
```

### Использование

Начнем с вывода сообщения "Hello world!" как обычно.

```tsx
import React, { useEffect, useRef, useState } from 'react';
import Engine, { EngineInterface } from '@aomao/engine';

const EngineDemo = () => {
    //Контейнер редактора
    const ref = useRef<HTMLDivElement | null>(null);
    //Экземпляр движка
    const [engine, setEngine] = useState<EngineInterface>();
    //Содержимое редактора
    const [content, setContent] = useState<string>('<p>Hello world!</p>');

    useEffect(() => {
        if (!ref.current) return;
        //Инициализация движка
        const engine = new Engine(ref.current);
        //Установка значения редактора
        engine.setValue(content);
        //Отслеживание события изменения значения редактора
        engine.on('change', () => {
            const value = engine.getValue();
            setContent(value);
            console.log(`value:${value}`);
        });
        //Установка экземпляра движка
        setEngine(engine);
    }, []);

    return <div ref={ref} />;
};

export default EngineDemo;
```

### Плагины

Импортируйте плагин жирного начертания `@aomao/plugin-bold`.

```tsx
import Bold from '@aomao/plugin-bold';
```

Добавьте плагин `Bold` в движок.

```tsx
//Инициализация движка
const engine = new Engine(ref.current, {
    plugins: [Bold],
});
```

### Карты

Карта — это отдельно определенная область внутри редактора со своим пользовательским интерфейсом и логикой отображения пользовательского контента внутри карты с использованием `React`, `Vue` или других библиотек фронтенд-разработки перед монтированием на редактор.Приведите пример использования плагина `@aomao/plugin-codeblock`, который представляет собой плагин для блока кода с выпадающим списком языков, отрисованного с помощью React, что отличает его от Vue3 с использованием `@aomao/plugin-codeblock-vue`.

```tsx
import CodeBlock, { CodeBlockComponent } from '@aomao/plugin-codeblock';
```

Добавьте плагин `CodeBlock` и компонент карты `CodeBlockComponent` в движок.

```tsx
// Инициализация движка
const engine = new Engine(ref.current, {
    plugins: [CodeBlock],
    cards: [CodeBlockComponent],
});
```

Плагин `CodeBlock` поддерживает `markdown` по умолчанию. Вы можете активировать его, набрав синтаксис блока кода в начале строки в редакторе, за которым следует пробел и имя языка, например ```javascript.

## Ограничения узлов

Для удобного управления узлами и снижения сложности редактор абстрагирует свойства узлов и их функциональность, а также определяет четыре типа узлов: `mark`, `inline`, `block` и `card`. Они состоят из различных атрибутов, стилей или структур `HTML` и унифицировано ограничиваются с помощью схемы.

Простая схема выглядит следующим образом:

```ts
{
  name: 'p', // имя узла
  type: 'block' // тип узла
}
```

Кроме того, могут быть указаны свойства, стили и т.д., например:```ts
{
  name: 'span', // имя узла
  type: 'mark', // тип узла
  attributes: {
    // Узел имеет атрибут стиля
    style: {
      // Должен содержать стиль цвета
      color: {
        required: true, // обязательно
        value: '@color' // Значение должно соответствовать спецификациям CSS. @color — это валидация цвета, определенная в редакторе. Здесь можно использовать методы и регулярные выражения для проверки выполнения требуемых правил
      }
    },
    // Включает опциональный атрибут test, значение которого может быть произвольным, но он не является обязательным
    test: '*'
  }
}
```Следующие типы узлов соответствуют вышеописанным правилам:

```html
<span style="color:#fff"></span>
<span style="color:#fff" test="test123" test1="test1"></span>
<span style="color:#fff;background-color:#000;"></span>
<span style="color:#fff;background-color:#000;" test="test123"></span>
```

Однако, кроме цвета и теста, определённых в схеме, остальные атрибуты (background-color, test1) будут отсеиваться редактором при обработке.

Узлы в редактируемой области имеют четыре типа объединённых узлов `mark`, `inline`, `block` и `card` через правило `schema`. Они состоят из различных атрибутов, стилей или структур `HTML`. Некоторым ограничениям накладывается условие на вложенность.

### Панель инструментов

Импортируйте панель инструментов `@aomao/toolbar`. Из-за сложной взаимодействия панель инструментов основана на рендере с использованием `React` + компонентов UI `Antd`, в то время как `Vue3` использует `@aomao/toolbar-vue`.

Помимо взаимодействия с пользовательским интерфейсом, большую часть работы панели инструментов составляет вызов движка для выполнения команд плагинов после активации событий кнопок. При сложных требованиях или необходимости переопределения пользовательского интерфейса проще сделать изменения после форка.```tsx
import Toolbar, { ToolbarPlugin, ToolbarComponent } from '@aomao/toolbar';
```

Добавьте плагин `ToolbarPlugin` и компонент карточки `ToolbarComponent` в движок, что позволяет использовать сочетание клавиш `/` в редакторе для активации панели инструментов карточек.```tsx
// Создайте экземпляр движка
const engine = new Engine(ref.current, {
	plugins: [ToolbarPlugin],
	cards: [ToolbarComponent],
});
```

Отображение панели инструментов, где все плагины уже настроены, здесь нам нужно передать только имя плагина.

```tsx
return (
    ...
    {
        engine && (
            <Toolbar
                engine={engine}
                items={[
                    ['collapse'],
                    [
                        'bold',
                    ],
                ]}
            />
        )
    }
    ...
)
```

Для более сложной конфигурации панели инструментов, пожалуйста, проверьте документацию [https://editor.aomao.com/config/toolbar](https://editor.aomao.com/config/toolbar).

### Коллаборативное редактирование

Эта открытая библиотека прослушивает изменения в структуре `HTML` области редактирования (корневой узел contenteditable), использует `MutationObserver` для восстановления структуры данных, а затем связывается и взаимодействует с [Yjs](https://github.com/yjs/yjs) через `WebSocket`, чтобы обеспечить многопользовательское коллаборативное редактирование.

#### Интерактивный режим

Каждый редактор, как [клиент](https://github.com/red-axe/am-editor/blob/master/examples/react/components/editor/index.tsx#L250), общается и взаимодействует с [сервером](https://github.com/big-camel/am-editor/tree/master/yjs-server) через функцию `WebSocket` в плагине `@aomao/plugin-yjs-websocket`.

-   `@aomao/yjs` реализует преобразование данных редактора и `Yjs`.
-   `@aomao/plugin-yjs-websocket` предоставляет функцию клиентского `WebSocket` для редактора и `Yjs`.
-   `@aomao/plugin-yjs-websocket/server` предоставляет серверный `WebSocket` для `Yjs`, написанный на Node.js, и поддерживающий хранение данных с использованием `MongoDB` и `LevelDB`.
```### Проектная иконка

[Iconfont](https://at.alicdn.com/t/project/1456030/0cbd04d3-3ca1-4898-b345-e0a9150fcc80.html?spm=a313x.7781069.1998910419.35)

## Разработка

### React

Перед использованием этой открытой библиотеки вам потребуется установить зависимости в корневом каталоге проекта.

```base
yarn install
```

Учиться использовать Bootstrap

После установки зависимостей вам нужно выполнить следующую команду в корневой директории для запуска проекта:

```bash
yarn start
```

Структура разработки открытой библиотеки выглядит следующим образом:

-   `packages` содержит код движка и связанный с панелью инструментов
-   `plugins` содержит все плагины
-   `api` предоставляет доступ к API, необходимый некоторым плагинам, и использует https://editor.aomao.com как основной сервис API
-   `yjs-server` содержит код сервера для совместной работы, который можно запустить через `yarn dev`.

### Vue

[пример am-editor vue](https://github.com/red-axe/am-editor-vue3-demo)

## Вклад

Благодарность [pleasedmi](https://github.com/pleasedmi)、[Elena211314](https://github.com/Elena211314)、[zb201307](https://github.com/zb201307)、[cheon](https://github.com/number317) за пожертвования

### AliPay

![alipay](https://cdn-object.aomao.com/contribution/alipay.png?x-oss-process=image/resize,w_200)

### WeChat Pay

![wechat](https://cdn-object.aomao.com/contribution/weichat.png?x-oss-process=image/resize,w_200)

### PayPal

[https://paypal.me/aomaocom](https://paypal.me/aomaocom)

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Рамка для редактора с поддержкой форматированного текста и возможностью совместной работы в реальном времени, которую можно настроить с помощью React и Vue. Развернуть Свернуть
MIT
Отмена

Обновления (50)

все

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/aomao-am-editor.git
git@api.gitlife.ru:oschina-mirror/aomao-am-editor.git
oschina-mirror
aomao-am-editor
aomao-am-editor
master