@olddevs/ui 4.4.0 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/editor/RichTextEditor.d.ts +11 -4
- package/dist/editor/RichTextEditor.d.ts.map +1 -1
- package/dist/editor/RichTextEditor.js +90 -60
- package/dist/editor/RichTextEditor.js.map +1 -1
- package/dist/editor/RichTextView.d.ts +2 -1
- package/dist/editor/RichTextView.d.ts.map +1 -1
- package/dist/editor/RichTextView.js.map +1 -1
- package/dist/editor/core/containers.d.ts +2 -6
- package/dist/editor/core/containers.d.ts.map +1 -1
- package/dist/editor/core/containers.js +2 -1
- package/dist/editor/core/containers.js.map +1 -1
- package/dist/editor/core/customTool.d.ts +8 -2
- package/dist/editor/core/customTool.d.ts.map +1 -1
- package/dist/editor/core/customTool.js.map +1 -1
- package/dist/editor/core/customToolEngine.d.ts +9 -1
- package/dist/editor/core/customToolEngine.d.ts.map +1 -1
- package/dist/editor/core/customToolEngine.js +12 -0
- package/dist/editor/core/customToolEngine.js.map +1 -1
- package/dist/editor/core/extensions.d.ts.map +1 -1
- package/dist/editor/core/extensions.js +1 -1
- package/dist/editor/core/extensions.js.map +1 -1
- package/dist/editor/core/handle.d.ts +18 -1
- package/dist/editor/core/handle.d.ts.map +1 -1
- package/dist/editor/core/handle.js +2 -1
- package/dist/editor/core/handle.js.map +1 -1
- package/dist/editor/core/handleWatchers.d.ts +30 -0
- package/dist/editor/core/handleWatchers.d.ts.map +1 -1
- package/dist/editor/core/handleWatchers.js +15 -0
- package/dist/editor/core/handleWatchers.js.map +1 -1
- package/dist/editor/core/nodeNames.d.ts +7 -0
- package/dist/editor/core/nodeNames.d.ts.map +1 -0
- package/dist/editor/core/nodeNames.js +2 -0
- package/dist/editor/core/nodeNames.js.map +1 -0
- package/dist/editor/core/schema.d.ts.map +1 -1
- package/dist/editor/core/schema.js +4 -2
- package/dist/editor/core/schema.js.map +1 -1
- package/dist/editor/core/toolCommands.d.ts +78 -0
- package/dist/editor/core/toolCommands.d.ts.map +1 -0
- package/dist/editor/core/toolCommands.js +2 -0
- package/dist/editor/core/toolCommands.js.map +1 -0
- package/dist/editor/core/toolDefinition.d.ts +139 -0
- package/dist/editor/core/toolDefinition.d.ts.map +1 -0
- package/dist/editor/core/toolDefinition.js +28 -0
- package/dist/editor/core/toolDefinition.js.map +1 -0
- package/dist/editor/core/toolDescriptor.d.ts +71 -2
- package/dist/editor/core/toolDescriptor.d.ts.map +1 -1
- package/dist/editor/core/toolDescriptor.js +6 -2
- package/dist/editor/core/toolDescriptor.js.map +1 -1
- package/dist/editor/core/toolOptions.d.ts +157 -0
- package/dist/editor/core/toolOptions.d.ts.map +1 -0
- package/dist/editor/core/toolOptions.js +21 -0
- package/dist/editor/core/toolOptions.js.map +1 -0
- package/dist/editor/core/toolState.d.ts +46 -0
- package/dist/editor/core/toolState.d.ts.map +1 -0
- package/dist/editor/core/toolState.js +2 -0
- package/dist/editor/core/toolState.js.map +1 -0
- package/dist/editor/core/tools.d.ts +3 -1
- package/dist/editor/core/tools.d.ts.map +1 -1
- package/dist/editor/core/tools.js.map +1 -1
- package/dist/editor/core/viewIsland.d.ts.map +1 -1
- package/dist/editor/core/viewIsland.js +2 -1
- package/dist/editor/core/viewIsland.js.map +1 -1
- package/dist/editor/features/builtins.d.ts +9 -4
- package/dist/editor/features/builtins.d.ts.map +1 -1
- package/dist/editor/features/builtins.js +36 -7
- package/dist/editor/features/builtins.js.map +1 -1
- package/dist/editor/features/search/SearchPanel.d.ts.map +1 -1
- package/dist/editor/features/search/SearchPanel.js +26 -12
- package/dist/editor/features/search/SearchPanel.js.map +1 -1
- package/dist/editor/features/search/revealMatch.d.ts +16 -0
- package/dist/editor/features/search/revealMatch.d.ts.map +1 -1
- package/dist/editor/features/search/revealMatch.js +22 -0
- package/dist/editor/features/search/revealMatch.js.map +1 -1
- package/dist/editor/features/search/searchPlugin.d.ts +8 -3
- package/dist/editor/features/search/searchPlugin.d.ts.map +1 -1
- package/dist/editor/features/search/searchPlugin.js +17 -6
- package/dist/editor/features/search/searchPlugin.js.map +1 -1
- package/dist/editor/features/search/searchSnapshot.d.ts +14 -0
- package/dist/editor/features/search/searchSnapshot.d.ts.map +1 -0
- package/dist/editor/features/search/searchSnapshot.js +17 -0
- package/dist/editor/features/search/searchSnapshot.js.map +1 -0
- package/dist/editor/features/search/searchTool.d.ts +3 -0
- package/dist/editor/features/search/searchTool.d.ts.map +1 -1
- package/dist/editor/features/search/searchTool.js +30 -1
- package/dist/editor/features/search/searchTool.js.map +1 -1
- package/dist/editor/features/toc/RichTextToc.d.ts +29 -1
- package/dist/editor/features/toc/RichTextToc.d.ts.map +1 -1
- package/dist/editor/features/toc/RichTextToc.js +64 -12
- package/dist/editor/features/toc/RichTextToc.js.map +1 -1
- package/dist/editor/features/toc/documentHeadings.d.ts +30 -0
- package/dist/editor/features/toc/documentHeadings.d.ts.map +1 -0
- package/dist/editor/features/toc/documentHeadings.js +20 -0
- package/dist/editor/features/toc/documentHeadings.js.map +1 -0
- package/dist/editor/features/toc/headings.d.ts +6 -2
- package/dist/editor/features/toc/headings.d.ts.map +1 -1
- package/dist/editor/features/toc/headings.js +4 -2
- package/dist/editor/features/toc/headings.js.map +1 -1
- package/dist/editor/features/toc/tocSnapshot.d.ts +10 -0
- package/dist/editor/features/toc/tocSnapshot.d.ts.map +1 -0
- package/dist/editor/features/toc/tocSnapshot.js +8 -0
- package/dist/editor/features/toc/tocSnapshot.js.map +1 -0
- package/dist/editor/features/toc/tocTool.d.ts +6 -0
- package/dist/editor/features/toc/tocTool.d.ts.map +1 -0
- package/dist/editor/features/toc/tocTool.js +21 -0
- package/dist/editor/features/toc/tocTool.js.map +1 -0
- package/dist/editor/hooks/useRichTextToolState.d.ts +43 -0
- package/dist/editor/hooks/useRichTextToolState.d.ts.map +1 -0
- package/dist/editor/hooks/useRichTextToolState.js +77 -0
- package/dist/editor/hooks/useRichTextToolState.js.map +1 -0
- package/dist/editor/index.d.ts +8 -0
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js +3 -0
- package/dist/editor/index.js.map +1 -1
- package/docs/api/editor-extension.en.md +223 -23
- package/docs/api/editor-extension.md +224 -22
- package/docs/api/migration-notes.en.md +36 -1
- package/docs/api/migration-notes.md +35 -0
- package/docs/components/content/rich-text-toc.en.md +13 -11
- package/docs/components/content/rich-text-toc.md +12 -10
- package/docs/components/index.en.md +2 -2
- package/docs/components/index.md +1 -1
- package/docs/components/inputs/rich-text-editor.en.md +227 -11
- package/docs/components/inputs/rich-text-editor.md +228 -10
- package/docs/getting-started.en.md +7 -7
- package/docs/getting-started.md +6 -6
- package/docs/glossary.en.md +52 -48
- package/docs/glossary.md +51 -47
- package/package.json +1 -1
- package/src/editor/RichTextEditor.tsx +94 -39
- package/src/editor/RichTextView.tsx +2 -1
- package/src/editor/core/containers.ts +8 -6
- package/src/editor/core/customTool.ts +8 -2
- package/src/editor/core/customToolEngine.ts +20 -1
- package/src/editor/core/extensions.ts +2 -1
- package/src/editor/core/handle.ts +25 -1
- package/src/editor/core/handleWatchers.ts +45 -0
- package/src/editor/core/nodeNames.ts +7 -0
- package/src/editor/core/schema.ts +5 -2
- package/src/editor/core/toolCommands.ts +85 -0
- package/src/editor/core/toolDefinition.ts +208 -0
- package/src/editor/core/toolDescriptor.ts +94 -3
- package/src/editor/core/toolOptions.ts +211 -0
- package/src/editor/core/toolState.ts +56 -0
- package/src/editor/core/tools.ts +3 -1
- package/src/editor/core/viewIsland.ts +5 -4
- package/src/editor/features/builtins.ts +72 -13
- package/src/editor/features/search/SearchPanel.tsx +38 -14
- package/src/editor/features/search/revealMatch.ts +45 -0
- package/src/editor/features/search/searchPlugin.ts +40 -11
- package/src/editor/features/search/searchSnapshot.ts +29 -0
- package/src/editor/features/search/searchTool.ts +51 -1
- package/src/editor/features/toc/RichTextToc.tsx +122 -13
- package/src/editor/features/toc/documentHeadings.ts +59 -0
- package/src/editor/features/toc/headings.ts +10 -3
- package/src/editor/features/toc/tocSnapshot.ts +24 -0
- package/src/editor/features/toc/tocTool.ts +41 -0
- package/src/editor/hooks/useRichTextToolState.ts +153 -0
- package/src/editor/index.ts +19 -0
|
@@ -7,6 +7,24 @@ exports:
|
|
|
7
7
|
RichTextEditorHandle,
|
|
8
8
|
RichTextDocument,
|
|
9
9
|
useRichTextEditorState,
|
|
10
|
+
useRichTextToolState,
|
|
11
|
+
RichTextToolState,
|
|
12
|
+
tool,
|
|
13
|
+
defineTool,
|
|
14
|
+
ConfiguredTool,
|
|
15
|
+
ToolDefinition,
|
|
16
|
+
ToolDefinitionInput,
|
|
17
|
+
ToolDefinitionContext,
|
|
18
|
+
CustomToolBody,
|
|
19
|
+
RichTextTools,
|
|
20
|
+
SearchToolOptions,
|
|
21
|
+
TocToolOptions,
|
|
22
|
+
TocLevel,
|
|
23
|
+
SearchToolCommands,
|
|
24
|
+
TocToolCommands,
|
|
25
|
+
SearchToolState,
|
|
26
|
+
TocToolState,
|
|
27
|
+
TocToolHeading,
|
|
10
28
|
Tool,
|
|
11
29
|
ToolName,
|
|
12
30
|
RichTextEditorPreset,
|
|
@@ -54,7 +72,8 @@ story: src/editor/RichTextEditor.stories.tsx
|
|
|
54
72
|
- **Блок кода.** С шапкой (язык слева, «Копировать» справа), языком (Python, TypeScript, JavaScript, Go, HTML, JSON, YAML, Markdown или обычный текст) и подсветкой lowlight. В Документ пишется только `class="language-…"`, а для `RichTextView` Блоки подсвечивает серверный хелпер из `@olddevs/ui/editor/highlight`.
|
|
55
73
|
- **HTML-режим.** Кнопка «HTML» фиксированной Панели (Инструмент `source`) меняет Документ на поле с его исходным HTML; выход, `blur`, отправка формы и `getHTML()` применяют правку через Схему, как входящий `value`.
|
|
56
74
|
- **Набор возможностей.** `preset="full" | "basic"` или точный список `tools`; выключенный Инструмент убирает и кнопку, и разметку из Схемы.
|
|
57
|
-
-
|
|
75
|
+
- **Опции, Состояние и Команды Инструмента.** У встроенных `search` и `toc` есть Опции: запись `tool("toc", { offsetVar: "--header-h", levels: [2, 3] })` стоит в `tools` рядом с именами, включает Инструмент и настраивает его (у Поиска — стартовые флажки `matchCase`, `wholeWord`, `regex`; у Оглавления — `offsetVar`, `levels`, `listWidth`). Состояние читает хук `useRichTextToolState(ref, "search")`: у Поиска — открыта ли панель поиска, запрос, число совпадений и номер текущего, у Оглавления — заголовки и текущий раздел; хук отдаёт `null` до монтажа, на сервере, после размонтирования Редактора и без Инструмента в наборе. Команды вызываются через Хэндл: `ref.current?.tool("search")?.open()`, `ref.current?.tool("toc")?.jumpTo(2)`; каждая возвращает `boolean`. Опции читаются один раз, при создании движка. Свой Инструмент с теми же тремя частями описывается `defineTool` ([«Опции, Состояние и Команды»](../../api/editor-extension.md#опции-состояние-и-команды)).
|
|
76
|
+
- **Хэндл (`ref`).** Экран управляет полем через `ref`: `insertHTML`, `insertText`, `getText`, `getSelectedText`, `isEmpty`, `focus(position?)`, `blur`, `undo`, `redo`, `tool(name)`; `getJSON()`/`setJSON()` выгружают и загружают Документ JSON-конвертом без потерь (раздел «JSON»), конверт принимает и `defaultValue`. Свою панель экран строит на хуке `useRichTextEditorState(ref, selector)`. `openSearch` устарел (удаляется в 5.0): его замена — `tool("search")?.open()`. До Готовности (на сервере, до монтажа, пока работают Загрузчики Инструментов) методы тихие: раздел «Хэндл (`ref`) и своя панель вне поля».
|
|
58
77
|
- **События.** О событиях поля экран узнаёт колбэками `onReady()`, `onFocus()` и `onBlur()` (раздел «События»).
|
|
59
78
|
- **Скелет и Загрузчик.** До Готовности поле показывает Скелет: рамку и Документ статичным HTML без ввода, без прыжка высоты. Документ Скелета — `value`, очищенный Схемой, и только в браузере; на сервере Скелет — рамка без Документа. Часть для движка своего Инструмента можно передать Загрузчиком (`engine: () => import(…)`); его сбой — ошибка поля с «Повторить».
|
|
60
79
|
- **Строка статуса и Сообщение поля.** Под полем внутри рамки — Строка статуса (`status`: React-узел экрана у начала, счётчик кита в конце, без `role`) и Сообщение поля: команда движка `showNotice({ tone: "status" | "error", text })` / `showNotice(null)`. `status` только озвучивается, `error` видна строкой `role="alert"` до следующей правки; тем же каналом идут сообщения о картинках.
|
|
@@ -304,7 +323,7 @@ import { RichTextEditor } from "@olddevs/ui/editor";
|
|
|
304
323
|
|
|
305
324
|
## Инструменты и Пресеты
|
|
306
325
|
|
|
307
|
-
`preset="full"` (по умолчанию) — всё, что есть в выпуске, кроме Оглавления `toc`: оно меняет раскладку поля, и его включают только явно. `preset="basic"` — для комментариев и коротких описаний. `tools` — точный список, сильнее Пресета; в нём вперемешку с именами кита стоят описания своих Инструментов (раздел «Свой Инструмент»). Тип элемента `tools` — `Tool` (имя
|
|
326
|
+
`preset="full"` (по умолчанию) — всё, что есть в выпуске, кроме Оглавления `toc`: оно меняет раскладку поля, и его включают только явно. `preset="basic"` — для комментариев и коротких описаний. `tools` — точный список, сильнее Пресета; в нём вперемешку с именами кита стоят описания своих Инструментов (раздел «Свой Инструмент»). Тип элемента `tools` — `Tool` (имя кита, Настроенный Инструмент `tool(…)`, определение `defineTool(…)` или `CustomTool`), тип имени кита — `ToolName`; оба экспортируются из `@olddevs/ui/editor`.
|
|
308
327
|
|
|
309
328
|
Пресеты экспортируются и массивами имён — `RICH_TEXT_PRESETS.full` и `RICH_TEXT_PRESETS.basic`, чтобы собирать из них свой набор: `tools={[...RICH_TEXT_PRESETS.full, mergeTagTool]}`. Массивы заморожены. Состав Пресета — «то, что кит считает полным набором», а не замороженный список: новый встроенный Инструмент приходит в Пресет minor-версией. Нужен стабильный состав — передайте точный список имён.
|
|
310
329
|
|
|
@@ -353,6 +372,34 @@ import { RichTextEditor } from "@olddevs/ui/editor";
|
|
|
353
372
|
|
|
354
373
|
`preset` и `tools` читаются **при создании движка**: Схему живого ProseMirror не поменять. Чтобы сменить набор у смонтированного поля, перемонтируйте его ключом (`key`) — история правок при этом теряется.
|
|
355
374
|
|
|
375
|
+
### Опции встроенного Инструмента: `tool()`
|
|
376
|
+
|
|
377
|
+
Опции есть у двух встроенных Инструментов — `search` и `toc`. Их задаёт помощник `tool(name, options)`: он возвращает Настроенный Инструмент, запись для `tools`, которая стоит рядом с именами и описаниями своих Инструментов (ADR-0069).
|
|
378
|
+
|
|
379
|
+
```tsx
|
|
380
|
+
import { RICH_TEXT_PRESETS, RichTextEditor, tool } from "@olddevs/ui/editor";
|
|
381
|
+
|
|
382
|
+
// Набор собирается один раз на модуль, а не в рендере: `tools` читается при создании движка.
|
|
383
|
+
const tools = [
|
|
384
|
+
...RICH_TEXT_PRESETS.full,
|
|
385
|
+
tool("toc", { offsetVar: "--header-h", levels: [2, 3] }),
|
|
386
|
+
tool("search", { matchCase: true }),
|
|
387
|
+
];
|
|
388
|
+
|
|
389
|
+
<RichTextEditor tools={tools} defaultValue={html} />;
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
- **Запись включает Инструмент.** `tool("toc", …)` включает `toc` без строки `"toc"`. Если в `tools` есть и голое имя (например, `search` из `full`), побеждает Настроенный Инструмент: кнопка и панель поиска остаются одни.
|
|
393
|
+
- **Передавайте только то, что меняете.** Остальные опции берутся из умолчаний кита. Вложенные объекты сливаются, массивы заменяются целиком: `levels: [2, 3]` — именно эти уровни, а не дополнение к умолчанию.
|
|
394
|
+
- **Место на поверхности не меняется.** Настроенный встроенный Инструмент стоит там же, где стоял бы по имени; свой — в порядке `tools`.
|
|
395
|
+
- **Типы выводят опции из имени.** `tool("toc", { matchCase: true })` и `tool("bold", {})` не компилируются: `tool()` принимает только Инструменты с Опциями, сейчас это `search` и `toc`.
|
|
396
|
+
- **Две записи `tool()` с одним именем** — ошибка набора, как два своих Инструмента с одним именем: ошибка поля «Редактор не запустился» и `console.error` в разработке.
|
|
397
|
+
- **Неверное значение** (из JS без типов: `levels: [5]`, `offsetVar: "header"`) заменяется умолчанием, в разработке — одним `console.error` на Инструмент; поле продолжает работать.
|
|
398
|
+
- **Опции читаются один раз**, вместе с набором `tools`, при создании движка. Чтобы сменить их у смонтированного поля, перемонтируйте его ключом (`key`) — история правок при этом теряется.
|
|
399
|
+
- **Сервер.** `tool()` не тянет в модуль ни Tiptap, ни React, поэтому набор `tools` с ним собирается в серверном модуле. Настроенный встроенный Инструмент состоит из данных, и если его опции — данные, его можно передать клиентскому компоненту пропом.
|
|
400
|
+
|
|
401
|
+
Опции каждого Инструмента описаны в его разделе: «Поиск и замена» и «Оглавление». Опции своего Инструмента задаёт `defineTool` ([«Опции, Состояние и Команды»](../../api/editor-extension.md#опции-состояние-и-команды)).
|
|
402
|
+
|
|
356
403
|
## Свой Инструмент
|
|
357
404
|
|
|
358
405
|
Свой Инструмент — описание одной возможности Редактора: его Блоки и Метки, правила Схемы данными и Часть для движка (расширения Tiptap). Он передаётся в `tools` вперемешку с именами кита и подчиняется тем же правилам: **не переданный Инструмент убирает свои Блоки и Метки из Схемы** — из `value`, вставки и команд они не проходят, Блок разворачивается в своё содержимое, Атом пропадает. Решение — ADR-0058, разделы 1 и 2.
|
|
@@ -442,7 +489,7 @@ HTML внутри атрибута не бывает: значение с `<` н
|
|
|
442
489
|
|
|
443
490
|
При ошибке движок не создаётся: под рамкой поля — строка `role="alert"` «Редактор не запустился. Документ не изменён.» (`editor.toolsFailed`), скрытое поле формы и `getHTML()` отдают входящее значение, `onChange` молчит, `ref.current.editor` — `null`. Причина — в `console.error` в режиме разработки, с именем Инструмента. Так потеря данных видна до первого сохранения, а не на сервере. **Неизвестная строка в `tools` по-прежнему отбрасывается молча**: ошибка относится только к описаниям своих Инструментов.
|
|
444
491
|
|
|
445
|
-
Кнопки, пункты Меню вставки, Действия над Блоком и Карточки у текста описаны в разделах ниже; сообщить автору об ошибке Инструмент может командой `showNotice` (раздел «Сообщение поля»). Всё API расширения и граница его стабильности (что подчиняется semver, что считается ломающим) описаны на странице [API расширения Редактора](../../api/editor-extension.md).
|
|
492
|
+
Кнопки, пункты Меню вставки, Действия над Блоком и Карточки у текста описаны в разделах ниже; сообщить автору об ошибке Инструмент может командой `showNotice` (раздел «Сообщение поля»). Всё API расширения и граница его стабильности (что подчиняется semver, что считается ломающим) описаны на странице [API расширения Редактора](../../api/editor-extension.md). Если у Инструмента есть настройки, а экрану нужны его Состояние и Команды, описывайте его через `defineTool`: [«Опции, Состояние и Команды»](../../api/editor-extension.md#опции-состояние-и-команды).
|
|
446
493
|
|
|
447
494
|
### Загрузчик Части для движка
|
|
448
495
|
|
|
@@ -1151,7 +1198,7 @@ ARIA сетки — шаблон `grid` из APG: `role="grid"` → `row` → `g
|
|
|
1151
1198
|
|
|
1152
1199
|
## Поиск и замена
|
|
1153
1200
|
|
|
1154
|
-
Инструмент `search` (есть в `full` и в `basic`) — поиск и замена по Документу. Кнопка «Найти» (лупа) стоит у правого края фиксированной Панели, перед Справочником сочетаний; `Ctrl/⌘+F`, когда фокус в Документе, открывает панель поиска (вне поля работает поиск браузера), `Ctrl/⌘+Alt+F` — с фокусом в поле замены, из кода экрана — `
|
|
1201
|
+
Инструмент `search` (есть в `full` и в `basic`) — поиск и замена по Документу. Кнопка «Найти» (лупа) стоит у правого края фиксированной Панели, перед Справочником сочетаний; `Ctrl/⌘+F`, когда фокус в Документе, открывает панель поиска (вне поля работает поиск браузера), `Ctrl/⌘+Alt+F` — с фокусом в поле замены, из кода экрана — Команда `open` Инструмента (`ref.current?.tool("search")?.open()`).
|
|
1155
1202
|
|
|
1156
1203
|
```tsx
|
|
1157
1204
|
<RichTextEditor preset="basic" /> // кнопка «Найти» и Ctrl/⌘+F уже есть
|
|
@@ -1170,6 +1217,76 @@ ARIA сетки — шаблон `grid` из APG: `role="grid"` → `row` → `g
|
|
|
1170
1217
|
|
|
1171
1218
|
Строки каталога сообщений: `editor.search` (кнопка и строка Справочника сочетаний `Ctrl/⌘+F`), `searchReplace` (`Ctrl/⌘+Alt+F`), `searchPanel`, `searchField`, `replaceField`, `searchPrevious`, `searchNext`, `searchClose`, `searchMatchCase`, `searchWholeWord`, `searchRegex`, `replaceOne`, `replaceAll`, `searchCount({ current, total })`, `searchNoMatches`, `searchInvalid`.
|
|
1172
1219
|
|
|
1220
|
+
### Опции Поиска
|
|
1221
|
+
|
|
1222
|
+
Запись `tool("search", options)` задаёт **стартовые флажки**: с ними открывается панель и работают Команды, пока поиск не закрыт. Флажки остаются переключаемыми в панели, кит не запоминает их между открытиями: закрытие панели возвращает их к стартовым.
|
|
1223
|
+
|
|
1224
|
+
| Опция | Значение | По умолчанию |
|
|
1225
|
+
| ----------- | ------------------------------------------------------ | ------------ |
|
|
1226
|
+
| `matchCase` | Панель открывается с включённым «Учитывать регистр» | `false` |
|
|
1227
|
+
| `wholeWord` | Панель открывается с включённым «Слово целиком» | `false` |
|
|
1228
|
+
| `regex` | Панель открывается с включённым «Регулярное выражение» | `false` |
|
|
1229
|
+
|
|
1230
|
+
```tsx
|
|
1231
|
+
// Поиск по коду в Документах: регистр важен, флажок не нужно включать каждый раз.
|
|
1232
|
+
<RichTextEditor tools={[...RICH_TEXT_PRESETS.full, tool("search", { matchCase: true })]} />
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
### Состояние и Команды Поиска
|
|
1236
|
+
|
|
1237
|
+
Состояние читает `useRichTextToolState(ref, "search")`, Команды вызывает `ref.current?.tool("search")`. Общие правила обоих — в разделе «Хэндл (`ref`) и своя панель вне поля».
|
|
1238
|
+
|
|
1239
|
+
| Поле Состояния | Значение |
|
|
1240
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1241
|
+
| `open` | Панель поиска открыта. |
|
|
1242
|
+
| `query` | Запрос. Закрытие панели убирает запрос и подсветку; без панели запрос ставит Команда `setQuery`. |
|
|
1243
|
+
| `flags` | Флажки `{ matchCase, wholeWord, regex }`. Закрытие панели возвращает их к стартовым из Опций. |
|
|
1244
|
+
| `total` | Сколько совпадений запроса в Документе. |
|
|
1245
|
+
| `current` | Индекс текущего совпадения от 0; `-1` — совпадений нет. |
|
|
1246
|
+
| `error` | Текст ошибки, если запрос — неверное регулярное выражение (сообщение движка JavaScript, не локализованное); иначе `null`. При ошибке совпадений нет. |
|
|
1247
|
+
|
|
1248
|
+
Позиций совпадений в Состоянии нет.
|
|
1249
|
+
|
|
1250
|
+
| Команда | Что делает |
|
|
1251
|
+
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1252
|
+
| `open({ replace?, query? })` | Открыть панель, как кнопка «Найти» и `Ctrl/⌘+F`. `query` сразу ставит запрос в поле и в подсветку Документа, без него запросом становится текст, выделенный в одном Блоке; `replace: true` — фокус в поле замены. `false` — в HTML-режиме. |
|
|
1253
|
+
| `close()` | Закрыть панель и убрать подсветку. Фокус и каретка остаются где были, в отличие от `Escape` в панели. Уже закрытая панель — не ошибка. |
|
|
1254
|
+
| `setQuery(query, flags?)` | Задать запрос. Не названные в `flags` флажки (и флажки со значением `undefined`) берутся из открытой панели, а без неё — из Опций. Непустой запрос прокручивает к первому совпадению после каретки. `true` — запрос применён, даже если совпадений нет; `false` — в HTML-режиме. |
|
|
1255
|
+
| `next()`, `previous()` | Следующее и предыдущее совпадение по кругу: выделяют его и прокручивают к нему область поля или окно, даже когда фокус вне Документа; фокус не забирают. `false` — совпадений нет. |
|
|
1256
|
+
| `replace(text)` | Заменить текущее совпадение: одна правка, одна отмена; текущим становится следующее. `false` — совпадений нет или поле нельзя править. |
|
|
1257
|
+
| `replaceAll(text)` | Заменить все совпадения: одна правка, одна отмена. Условия — как у `replace`. |
|
|
1258
|
+
|
|
1259
|
+
Запрос и флажки живут в движке, поэтому `setQuery`, `next` и `replace` работают и без открытой панели: на них можно собрать свой интерфейс поиска. Панель и Команды делят один поиск — замена из кода видна в панели. Прокрутка после `next`, `previous` и `setQuery` приходит чуть позже вызова: её код грузится при первом обращении и в стартовый кусок Редактора не входит.
|
|
1260
|
+
|
|
1261
|
+
**Счётчик в Строке статуса.** Пока открыта панель поиска, экран может показывать «3 из 12» рядом со счётчиком символов. Закрытие панели убирает запрос, и счётчик гаснет.
|
|
1262
|
+
|
|
1263
|
+
```tsx
|
|
1264
|
+
import { useRef } from "react";
|
|
1265
|
+
import { RichTextEditor, useRichTextToolState } from "@olddevs/ui/editor";
|
|
1266
|
+
import type { RichTextEditorHandle } from "@olddevs/ui/editor";
|
|
1267
|
+
|
|
1268
|
+
function ArticleBody({ html }: { html: string }) {
|
|
1269
|
+
const ref = useRef<RichTextEditorHandle>(null);
|
|
1270
|
+
// `null` до монтажа и на сервере: экран рендерится одинаково там и там.
|
|
1271
|
+
const search = useRichTextToolState(ref, "search");
|
|
1272
|
+
|
|
1273
|
+
return (
|
|
1274
|
+
<RichTextEditor
|
|
1275
|
+
ref={ref}
|
|
1276
|
+
aria-label="Текст статьи"
|
|
1277
|
+
defaultValue={html}
|
|
1278
|
+
status={
|
|
1279
|
+
search?.open && search.query ? (
|
|
1280
|
+
<span>
|
|
1281
|
+
{search.total ? `${search.current + 1} из ${search.total}` : "Нет совпадений"}
|
|
1282
|
+
</span>
|
|
1283
|
+
) : null
|
|
1284
|
+
}
|
|
1285
|
+
/>
|
|
1286
|
+
);
|
|
1287
|
+
}
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1173
1290
|
## Оглавление
|
|
1174
1291
|
|
|
1175
1292
|
Инструмент `toc` — Оглавление Документа в левом поле Редактора: та же полоса штрихов и тот же список, что у [`RichTextToc`](../content/rich-text-toc.md), но место держит сам Редактор (ADR-0068). В Пресеты он не входит — ни в `full`, ни в `basic`: Оглавление сдвигает текст, и обновление кита не меняет раскладку экранов, которые его не просили. Включают его именем:
|
|
@@ -1178,6 +1295,8 @@ ARIA сетки — шаблон `grid` из APG: `role="grid"` → `row` → `g
|
|
|
1178
1295
|
<RichTextEditor tools={[...RICH_TEXT_PRESETS.full, "toc"]} defaultValue={html} />
|
|
1179
1296
|
```
|
|
1180
1297
|
|
|
1298
|
+
Запись `tool("toc", options)` тоже включает Инструмент и заодно настраивает его (раздел «Опции Оглавления» ниже).
|
|
1299
|
+
|
|
1181
1300
|
- **Место.** Колонка слева от Документа внутри рамки поля. Она есть, только пока есть полоса — от двух заголовков `h1`–`h4` на верхнем уровне и в Обёртке: со вторым заголовком текст сдвигается вправо, без него стоит у края, как без Инструмента. Первый штрих стоит на уровне первой строки первого заголовка.
|
|
1182
1301
|
- **Липкость.** Полоса липнет под фиксированной Панелью (и под шапкой приложения: `--topbar-h`, ADR-0016), без Панели — к краю окна. В поле с `maxHeight` или `resizable` она липнет к верху прокручиваемой области, а подсветка и переход считают от неё — страница при этом не прокручивается.
|
|
1183
1302
|
- **Список** — как у `RichTextToc`: наведение раскрывает его справа от полосы, Enter и Space — с клавиатуры, стрелки ходят по пунктам, Escape закрывает; текущий раздел подсвечен в полосе и в списке; ширина 240px, длинный заголовок обрезан многоточием. Клик по пункту список не закрывает: его закрывает уход курсора.
|
|
@@ -1187,6 +1306,70 @@ ARIA сетки — шаблон `grid` из APG: `role="grid"` → `row` → `g
|
|
|
1187
1306
|
|
|
1188
1307
|
Строка каталога сообщений — `editor.toc` («Оглавление»): имя полосы и подпись списка.
|
|
1189
1308
|
|
|
1309
|
+
### Опции Оглавления
|
|
1310
|
+
|
|
1311
|
+
Запись `tool("toc", options)` включает Инструмент и настраивает его. Те же `offsetVar`, `levels` и `listWidth` принимает отдельный [`RichTextToc`](../content/rich-text-toc.md#public-api): ядро у них общее.
|
|
1312
|
+
|
|
1313
|
+
| Опция | Значение | По умолчанию |
|
|
1314
|
+
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
|
|
1315
|
+
| `offsetVar` | Имя CSS-переменной с высотой липкой шапки экрана (ADR-0016), целиком, с двумя дефисами: `--header-h`. Переход ставит заголовок под шапку, а подсветка считает раздел текущим от её нижнего края. Липкую Панель Редактора опция не двигает: она по-прежнему стоит под `--topbar-h`. | `--topbar-h` |
|
|
1316
|
+
| `levels` | Уровни заголовков в Оглавлении: подмножество 1–4. Заголовка другого уровня нет ни в полосе, ни в списке, а отступ пунктов считается от самого крупного из оставшихся. Пустой массив и неверные значения заменяет умолчание. Остаётся меньше двух заголовков — колонки слева нет. | `[1, 2, 3, 4]` |
|
|
1317
|
+
| `listWidth` | Ширина списка: пиксели или длина CSS. Постоянная, а не по самому длинному заголовку. | `240` |
|
|
1318
|
+
|
|
1319
|
+
```tsx
|
|
1320
|
+
// Шапка экрана публикует свою высоту в `--header-h`; в Оглавлении нужны только H2 и H3.
|
|
1321
|
+
<RichTextEditor
|
|
1322
|
+
tools={[...RICH_TEXT_PRESETS.full, tool("toc", { offsetVar: "--header-h", levels: [2, 3] })]}
|
|
1323
|
+
defaultValue={html}
|
|
1324
|
+
/>
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
### Состояние и Команды Оглавления
|
|
1328
|
+
|
|
1329
|
+
Состояние читает `useRichTextToolState(ref, "toc")`, Команду вызывает `ref.current?.tool("toc")`.
|
|
1330
|
+
|
|
1331
|
+
| Поле Состояния | Значение |
|
|
1332
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1333
|
+
| `headings` | Заголовки в порядке чтения, те же, что в полосе и списке: верхний уровень и Обёртки, только уровни из `levels`, без пустых. Каждый — `{ level, text, index }`: уровень 1–4, текст без разметки, номер пункта списка от 0. Список отдаётся и при одном заголовке, хотя колонки тогда нет. |
|
|
1334
|
+
| `current` | Индекс текущего раздела в `headings` от 0; `-1` — заголовков нет. Следует за прокруткой. После правки Документа `headings` меняется сразу, а `current` догоняет с задержкой пересборки списка. |
|
|
1335
|
+
|
|
1336
|
+
Заголовки берутся из Документа, а не из DOM: список готов с первого кадра, не дожидаясь ленивого интерфейса Оглавления, и меняется вместе с правкой. DOM-узлов и позиций ProseMirror в Состоянии нет.
|
|
1337
|
+
|
|
1338
|
+
Команда одна — `jumpTo(index)`: перейти к заголовку списка, как по клику на пункт. Индекс считается в том же списке (с учётом `levels`, от 0, пустые заголовки пропущены) и берётся из снимка Состояния: сразу после правки Документа он ведёт к тому заголовку, который назван в снимке, хотя список интерфейса Оглавления пересобирается с задержкой. В правке каретка встаёт в конец заголовка, в `readOnly` фокус получает сам заголовок; прокрутка ставит его под липкую шапку (`offsetVar`) и Панель, подсветка заголовка гаснет. `false` — заголовка с таким индексом нет, интерфейс Оглавления ещё не загружен или включён HTML-режим. Заголовков меньше двух — не причина отказа: колонки нет, но список есть, и переход работает.
|
|
1339
|
+
|
|
1340
|
+
**Внешняя навигация.** Хлебные крошки, мини-карту или список разделов рядом с полем экран строит из Состояния, а не разбирает DOM Документа второй раз.
|
|
1341
|
+
|
|
1342
|
+
```tsx
|
|
1343
|
+
import type { RefObject } from "react";
|
|
1344
|
+
import { useRichTextToolState } from "@olddevs/ui/editor";
|
|
1345
|
+
import type { RichTextEditorHandle } from "@olddevs/ui/editor";
|
|
1346
|
+
|
|
1347
|
+
function SectionNav({ target }: { target: RefObject<RichTextEditorHandle | null> }) {
|
|
1348
|
+
const toc = useRichTextToolState(target, "toc");
|
|
1349
|
+
if (!toc) return null;
|
|
1350
|
+
|
|
1351
|
+
return (
|
|
1352
|
+
<nav aria-label="Разделы">
|
|
1353
|
+
<ul>
|
|
1354
|
+
{toc.headings.map((heading) => (
|
|
1355
|
+
<li
|
|
1356
|
+
key={heading.index}
|
|
1357
|
+
aria-current={heading.index === toc.current ? "location" : undefined}
|
|
1358
|
+
>
|
|
1359
|
+
<button
|
|
1360
|
+
type="button"
|
|
1361
|
+
onClick={() => target.current?.tool("toc")?.jumpTo(heading.index)}
|
|
1362
|
+
>
|
|
1363
|
+
{heading.text}
|
|
1364
|
+
</button>
|
|
1365
|
+
</li>
|
|
1366
|
+
))}
|
|
1367
|
+
</ul>
|
|
1368
|
+
</nav>
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
```
|
|
1372
|
+
|
|
1190
1373
|
## Строка статуса и Сообщение поля
|
|
1191
1374
|
|
|
1192
1375
|
Под полем внутри рамки две независимые области. **Строка статуса** — то, что экран кладёт сам: «Сохранено», число слов, соавтор. **Сообщение поля** — то, что сообщают кит и Инструменты: результат загрузки, отказ вставки. Первое — React-узел пропа `status`, второе — данные и команда движка.
|
|
@@ -1293,7 +1476,8 @@ import type { RichTextEditorHandle } from "@olddevs/ui/editor";
|
|
|
1293
1476
|
| `focus(position?)` | `"end"` (по умолчанию), `"start"` или `"restore"`: вернуть фокус туда, где было выделение, например после своего диалога или меню. |
|
|
1294
1477
|
| `blur()` | Снять фокус с Документа. |
|
|
1295
1478
|
| `undo()`, `redo()` | Отменить и повторить правку; работают при включённом Инструменте `history`. |
|
|
1296
|
-
| `
|
|
1479
|
+
| `tool(name)` | Команды Инструмента: `tool("search")?.open()`, `tool("toc")?.jumpTo(2)`. `null` — Инструмента нет в наборе, у него нет Команд или движок ещё не создан. См. «Команды Инструмента: `handle.tool()`». |
|
|
1480
|
+
| `openSearch({ replace? })` | **Устарел**, удаляется в 5.0: то же, что `tool("search")?.open({ replace })`; в разработке один раз предупреждает. |
|
|
1297
1481
|
| `canUndo()`, `canRedo()` | Доступность `undo` и `redo`: `false` без `history`. |
|
|
1298
1482
|
| `getHTML()`, `getMarkdown()`, `setMarkdown(md)`, `clear()` | См. «Public API» и «Markdown». |
|
|
1299
1483
|
| `getJSON()`, `setJSON(document): boolean` | Документ JSON-конвертом без потерь и замена Документа конвертом; `false` — конверт отвергнут. См. «JSON». |
|
|
@@ -1361,6 +1545,35 @@ function Screen() {
|
|
|
1361
1545
|
|
|
1362
1546
|
**История с внешней панелью.** Хэндл даёт `undo()` и `redo()` и их доступность. Для `disabled` кнопки «Отменить» берите доступность из среза хука — `editor.can().undo?.() === true`: срез перерисует панель сразу после правки. `ref.current.canUndo()` — разовое чтение в обработчике, на перерисовку оно не подписано. Без Инструмента `history` команды `undo` у движка нет (отсюда `?.`), и обе кнопки остаются недоступными.
|
|
1363
1547
|
|
|
1548
|
+
### Состояние Инструмента: `useRichTextToolState`
|
|
1549
|
+
|
|
1550
|
+
`useRichTextToolState(ref, name, selector?)` отдаёт экрану Состояние Инструмента: «3 из 12» в Строке статуса из Поиска, внешнюю навигацию из заголовков Оглавления. Хук стоит рядом с `useRichTextEditorState` и так же следит за движком Хэндла, но возвращает не срез движка Tiptap, а типизированный снимок контракта кита. Поля Состояния встроенных — в разделах «Поиск и замена» и «Оглавление».
|
|
1551
|
+
|
|
1552
|
+
- **Имя и тип.** `name` — Инструмент из набора `tools`; тип снимка выводится из карты `RichTextTools`: `search` отдаёт `SearchToolState`, `toc` — `TocToolState`. Имя вне карты (свой Инструмент без типизации) даёт `unknown`.
|
|
1553
|
+
- **Перерисовка — только при смене снимка.** Снимок пересчитывается на каждую транзакцию движка и на сигналы кита, которых в движке нет: открытие и закрытие панели поиска, смена текущего раздела Оглавления при прокрутке. Экран перерисовывается, когда результат стал другим (простые данные — примитивы, массивы, простые объекты — сравниваются по значению, как у `useRichTextEditorState`; `Date`, `Map`, `Set` и экземпляры классов — по ссылке), поэтому набор текста, не меняющий снимок, его не трогает. Свой `state`, который создаёт такие значения заново на каждый вызов, перерисует экран на каждой транзакции.
|
|
1554
|
+
- **Селектор.** Третий аргумент подписывает экран на срез: `useRichTextToolState(ref, "search", (state) => state.total)` перерисовывает его, только когда меняется число совпадений. При `null` селектор не вызывается.
|
|
1555
|
+
- **`null`** хук отдаёт до монтажа и в первом рендере экрана, на сервере, после размонтирования Редактора, а также когда Инструмента нет в наборе: Пресеты `toc` не включают, его включают именем или записью `tool("toc")`. Так экран рендерится одинаково на сервере и в браузере.
|
|
1556
|
+
- **Снимок — данные**: без DOM-узлов, функций и позиций ProseMirror. Менять его не нужно.
|
|
1557
|
+
- **Цена.** Хук в стартовый граф `RichTextEditor` не входит: его вес несёт только экран, который его импортировал.
|
|
1558
|
+
|
|
1559
|
+
Состояние своего Инструмента объявляет `defineTool` (поле `state`), читается оно тем же хуком: [«Опции, Состояние и Команды»](../../api/editor-extension.md#опции-состояние-и-команды).
|
|
1560
|
+
|
|
1561
|
+
### Команды Инструмента: `handle.tool()`
|
|
1562
|
+
|
|
1563
|
+
`ref.current?.tool(name)` отдаёт объект Команд Инструмента: `tool("search")?.open({ query: "TODO" })`, `tool("toc")?.jumpTo(2)`. Команды встроенных описаны в разделах «Поиск и замена» и «Оглавление».
|
|
1564
|
+
|
|
1565
|
+
```tsx
|
|
1566
|
+
<button type="button" onClick={() => ref.current?.tool("search")?.open({ query: "TODO" })}>
|
|
1567
|
+
Найти TODO
|
|
1568
|
+
</button>
|
|
1569
|
+
```
|
|
1570
|
+
|
|
1571
|
+
- **Тип выводится из карты `RichTextTools`**, по имени Инструмента. Имя вне карты даёт `unknown`.
|
|
1572
|
+
- **`null`**, если Инструмента нет в наборе `tools`, у него нет Команд или движок ещё не создан. Поэтому Команды выключенного Инструмента недоступны и в типах (`?.`), и во время работы.
|
|
1573
|
+
- **Каждая Команда возвращает `boolean`:** выполнена или нет (HTML-режим, нет совпадений, нет заголовка, поле нельзя править). Отказ — это `false`, как у `insertHTML`, а не исключение.
|
|
1574
|
+
- **Берите объект при каждом вызове**, а не храните его между рендерами: он дешёвый, и так вы всегда работаете с живым движком.
|
|
1575
|
+
- **Новых методов Хэндла на каждую Команду нет.** Команды встроенных идут через `tool(name)`; `openSearch` остался только для совместимости. Команды Меток, Блоков и всего, что Инструмент не объявил, по-прежнему вызываются через `ref.current.editor`.
|
|
1576
|
+
|
|
1364
1577
|
## События
|
|
1365
1578
|
|
|
1366
1579
|
Экран узнаёт о Редакторе колбэк-пропсами; шины событий нет. Решение — ADR-0058, раздел 9.
|
|
@@ -1422,9 +1635,10 @@ export const pdfTool: CustomTool = { name: "acme_pdfDrop", engine: [PdfDrop] };
|
|
|
1422
1635
|
- `maxHeight` — предел высоты области Документа (число — пиксели, строка — CSS-длина), дальше Документ прокручивается внутри рамки; `resizable` — ручка высоты у нижнего края области (ползунок с клавиатуры), `maxHeight` с ней — стартовая высота. См. «Высота поля».
|
|
1423
1636
|
- `surface` — `"theme"` (по умолчанию) или `"paper"`: светлый Лист в любой теме, см. «Поверхность». Тип — `RichTextSurface`.
|
|
1424
1637
|
- `status` — React-узел Строки статуса внутри рамки поля, у начала строки счётчика; кит её не озвучивает. Команда движка `showNotice({ tone, text } | null)` — Сообщение поля. Оба — в «Строка статуса и Сообщение поля»; подчиняются semver кита.
|
|
1425
|
-
- `tools` — имена
|
|
1426
|
-
- `ref` (`RichTextEditorHandle`): `getHTML()` — текущий HTML, без ожидания задержки и без `onChange` (в HTML-режиме сначала применяет правку поля — тогда `onChange` вызывается, если Документ изменился; то же у `getMarkdown()`); `getMarkdown()` и `setMarkdown(md)` — см. «Markdown»; `getJSON()` и `setJSON(document)` — см. «JSON»; `clear()` — очистить Документ, экран узнаёт об этом через `onChange("")`; `focus(position?)`, `blur()`, `insertHTML`, `insertText`, `getText`, `getSelectedText`, `isEmpty`, `undo`, `redo`, `canUndo`, `canRedo` — см. «Хэндл (`ref`) и своя панель вне поля»; `openSearch({ replace? })` —
|
|
1638
|
+
- `tools` — имена кита, Настроенные Инструменты `tool(name, options)` для `search` и `toc`, определения `defineTool(…)` и описания своих Инструментов (`CustomTool`, в том числе их `buttons`, `insertItems`, `blockActions`, `textCards` и `trigger`), Пресеты массивами — `RICH_TEXT_PRESETS`; см. «Инструменты и Пресеты» и «Свой Инструмент». Описание с ошибкой — ошибка поля.
|
|
1639
|
+
- `ref` (`RichTextEditorHandle`): `getHTML()` — текущий HTML, без ожидания задержки и без `onChange` (в HTML-режиме сначала применяет правку поля — тогда `onChange` вызывается, если Документ изменился; то же у `getMarkdown()`); `getMarkdown()` и `setMarkdown(md)` — см. «Markdown»; `getJSON()` и `setJSON(document)` — см. «JSON»; `clear()` — очистить Документ, экран узнаёт об этом через `onChange("")`; `focus(position?)`, `blur()`, `insertHTML`, `insertText`, `getText`, `getSelectedText`, `isEmpty`, `undo`, `redo`, `canUndo`, `canRedo` — см. «Хэндл (`ref`) и своя панель вне поля»; `tool(name)` — Команды Инструмента, см. «Команды Инструмента: `handle.tool()`»; `openSearch({ replace? })` — устарел, удаляется в 5.0, замена — `tool("search")?.open({ replace })`; `editor` — исходный `Editor` Tiptap, его API **следует мажорной версии Tiptap**, до монтажа и на сервере он `null`. `focus()` без аргумента ставит каретку в конец Документа (в HTML-режиме — в поле HTML).
|
|
1427
1640
|
- `useRichTextEditorState(ref, selector)` — хук для своей панели вне поля, см. «Хэндл (`ref`) и своя панель вне поля».
|
|
1641
|
+
- `useRichTextToolState(ref, name, selector?)` — хук Состояния Инструмента (`search`, `toc` и свои с `defineTool`): снимок данных, `null` до монтажа, после размонтирования и без Инструмента; см. «Состояние Инструмента: `useRichTextToolState`». Подчиняется semver кита, как и `tool()`, `defineTool()`, `handle.tool()` и карта `RichTextTools`.
|
|
1428
1642
|
- SSR: движок создаётся только в браузере (`immediatelyRender: false`). На сервере рисуется Скелет без Документа — рамка и зарезервированное под Панель место — и скрытое поле с входящим значением. После гидратации Скелет показывает Документ, очищенный Схемой, а редактируемая область встаёт на его место после Загрузчиков, без прыжка высоты. Исключение — JSON-конверт в `defaultValue`: его HTML собирает только движок, поэтому Скелет при нём — рамка без Документа, скрытое поле до Готовности пустое, а высота один раз меняется, когда Документ встаёт.
|
|
1429
1643
|
|
|
1430
1644
|
## Markdown
|
|
@@ -1545,12 +1759,16 @@ const opened: boolean = ref.current?.setJSON(JSON.parse(fileText)) ?? false;
|
|
|
1545
1759
|
- Менять `tools` у смонтированного поля в расчёте на то, что Схема перестроится: набор читается при создании движка.
|
|
1546
1760
|
- Передавать смысл заметки одним тоном Обёртки: подложку не видит скринридер и не различает дальтоник, а в Markdown без поддержки alerts остаётся цитата. Пишите словом — «Внимание: …» (WCAG 1.4.1).
|
|
1547
1761
|
- Красить текст внутри Обёртки с тоном цветом палитры или своим цветом: на цветной подложке его контраст может оказаться ниже 4.5:1 — гейт проверяет основной и вторичный текст Документа, а не цвет автора.
|
|
1762
|
+
- Менять `tool(…)` у смонтированного поля в расчёте на новые Опции: они читаются при создании движка, как `tools`. Чтобы сменить Опции, перемонтируйте поле ключом.
|
|
1763
|
+
- Брать число совпадений Поиска или заголовки Оглавления из `ref.current.editor`, из DOM Документа или по внутренним ключам плагинов: такой доступ не входит в контракт кита и следует мажору Tiptap. Для этого есть `useRichTextToolState`.
|
|
1764
|
+
- Звать `openSearch()` в новом коде: метод устарел и исчезнет в 5.0. Берите `tool("search")?.open()`.
|
|
1765
|
+
- Писать в `tools` `tool("bold", …)` или опции, которых у Инструмента нет: компилятор остановит, а на JS без типов лишняя опция будет отброшена с `console.error`.
|
|
1548
1766
|
|
|
1549
1767
|
## Ссылки
|
|
1550
1768
|
|
|
1551
|
-
- Исходник: `src/editor/RichTextEditor.tsx`; Панель — `src/editor/ui/EditorToolbar.tsx`, меню форматирования («¶», «…», «Выравнивание», «Списки») — `src/editor/ui/FormatMenus.tsx` и `src/editor/core/blockTypes.ts`, плавающая — `src/editor/ui/FloatingToolbar.tsx`, Меню выделения — `src/editor/ui/SelectionBubble.tsx`, общее условие показа и позиция — `src/editor/ui/selectionMenu.ts`; ссылка — `src/editor/features/link/link.ts`, описание Инструмента `src/editor/features/link/linkTool.tsx` и форма адреса `src/editor/features/link/LinkPopover.tsx`; эмодзи — описание Инструмента `src/editor/features/emoji/emojiTool.tsx` и сетка `src/editor/features/emoji/EmojiGrid.tsx`; кнопки из описаний Инструментов и рамка их поповеров — `src/editor/ui/ToolButtonView.tsx`, их сочетания — `src/editor/core/toolButtons.ts`, сочетания их Пунктов вставки и Действий над Блоком — `src/editor/core/toolEntryShortcuts.ts`; картинка — `src/editor/features/image/image.ts` (узел, загрузка, вставка файлов), `src/editor/features/image/ImagePopover.tsx`, `src/editor/features/image/ImageToolbar.tsx`; Сообщение поля — команда `src/editor/core/fieldNotice.ts`, тексты о файлах `src/editor/features/image/imageNotice.ts`, живой регион, строка ошибки и Строка статуса `src/editor/ui/FieldStatus.tsx`; свой Инструмент — публичная форма `src/editor/core/customTool.ts`, движок и проверка набора `src/editor/core/customToolEngine.ts`, разворот `tools` `src/editor/features/builtins.ts`; таблица — `src/editor/features/table/tables.ts` (узлы, слияние, выравнивание, Markdown), `src/editor/features/table/tableActions.ts` (команды меню, сортировка, память размера), `src/editor/features/table/TableMenuButton.tsx` (меню «Таблица»), `src/editor/features/table/TableSizeGrid.tsx` и `src/editor/features/table/TableInsertDialog.tsx`; Раскладка — `src/editor/features/layout/layout.ts` (узлы, команды, клавиатура) и `src/editor/features/layout/columnLayouts.ts` (варианты данными); Обёртка — `src/editor/features/wrapper/wrapper.ts` (узел, вставка, снятие, тон, клавиатура, Markdown) и `src/editor/features/wrapper/wrapperTones.ts` (тоны и метки GitHub alerts данными); Документ с контейнерами Блоков — `src/editor/core/document.ts`; Хэндл — `src/editor/core/handle.ts`, хук — `src/editor/hooks/useRichTextEditorState.ts`; HTML-режим — состояние и применение в `src/editor/RichTextEditor.tsx`, форматирование HTML — `src/editor/core/sourceFormat.ts`; Инструменты и Пресеты — `src/editor/core/tools.ts`; команды над Блоками — `src/editor/core/blockCommands.ts`; Ручка Блока — `src/editor/ui/BlockHandle.tsx`; таблица сочетаний и подписи — `src/editor/core/shortcuts.ts`, Справочник сочетаний — `src/editor/ui/ShortcutsButton.tsx`; Стекло всплывающих поверхностей — `src/editor/styles/glass.ts`; Меню вставки — `src/editor/core/insertItems.ts` (реестр пунктов), `src/editor/ui/SlashMenu.tsx`, `src/editor/ui/InsertMenuButton.tsx`, `src/editor/core/slashCommand.ts`; Схема данными — `src/editor/core/schema.ts`; палитра и выравнивания — `src/editor/styles/palette.ts`, расширения цвета — `src/editor/features/color/styleExtensions.ts`; цвет автора — форма и разбор `src/editor/features/color/customColor.ts`, контраст `src/editor/features/color/contrast.ts`, поповер `src/editor/features/color/CustomColorPopover.tsx`; типографика — `src/editor/styles/prose.ts`; блок кода — `src/editor/features/code/codeBlock.ts` (расширение, псевдонимы, `Alt+F10`), `src/editor/features/code/CodeBlockView.tsx` (шапка: язык и «Копировать»), `src/editor/features/code/CodeCopyButton.tsx` (кнопка с подсказкой), `src/editor/features/code/codeHeader.ts` (классы шапки, общие с Просмотром), Лист `surface="paper"` — `src/editor/styles/surface.ts` и `src/editor/styles/tokens.ts`, `src/editor/features/code/codeLanguages.ts` (языки данными), `src/editor/features/code/lowlight.ts` (грамматики), `src/editor/styles/codeTheme.ts` (тема подсветки синтаксиса), серверный хелпер — `src/editor/features/code/highlight.ts`; поиск и замена — `src/editor/features/search/searchTool.ts` (Инструмент), `src/editor/features/search/searchPlugin.ts` и `src/editor/features/search/SearchPanel.tsx`; JSON — `src/editor/core/jsonDocument.ts`; Высота поля — Ручка высоты `src/editor/ui/FieldResizer.tsx`; эмодзи (данные набора) — `src/editor/features/emoji/emoji.ts`; предел символов — `src/editor/core/maxLength.ts`; Markdown — `src/editor/core/markdown.ts`.
|
|
1552
|
-
- Тесты: `tests/rich-text-editor-text-card.test.tsx` (Карточка у текста), `tests/rich-text-editor.test.tsx`, `tests/rich-text-editor-handle.test.tsx` и `tests/rich-text-editor-handle-ssr.test.tsx` (Хэндл и хук), `tests/rich-text-editor-toolbar.test.tsx`, `tests/rich-text-editor-block-menu.test.tsx`, `tests/rich-text-editor-more-menu.test.tsx`, `tests/rich-text-editor-align-list-menus.test.tsx`, `tests/rich-text-editor-insert-menu.test.tsx`, `tests/rich-text-editor-schema.test.tsx`, `tests/rich-text-editor-markdown.test.tsx`, `tests/rich-text-editor-color.test.tsx`, `tests/rich-text-editor-custom-color.test.tsx`, `tests/rich-text-editor-link.test.tsx`, `tests/rich-text-editor-floating.test.tsx`, `tests/rich-text-editor-bubble.test.tsx`, `tests/rich-text-editor-glass.test.tsx`, `tests/rich-text-editor-table.test.tsx`, `tests/rich-text-editor-lazy-builtins.test.tsx` (ленивые блок кода и таблица: `basic` их не грузит, `full` — Скелет до чанков), `tests/rich-text-editor-image.test.tsx`, `tests/rich-text-editor-notice.test.tsx`, `tests/rich-text-editor-code-block.test.tsx`, `tests/rich-text-editor-block-commands.test.tsx`, `tests/rich-text-editor-block-handle.test.tsx`, `tests/rich-text-editor-shortcuts.test.tsx`, `tests/rich-text-editor-layout.test.tsx`, `tests/rich-text-editor-wrapper.test.tsx`, `tests/rich-text-editor-wrapper-tone.test.tsx`, `tests/rich-text-editor-source.test.tsx`, `tests/rich-text-editor-custom-tool.test.tsx` (свой Инструмент; тестовые Инструменты — `tests/editor-test-tools.ts`), `tests/rich-text-editor-custom-ui.test.tsx` (Пункты вставки и Действия над Блоком своего Инструмента), `tests/rich-text-editor-trigger.test.tsx` (свой символ-триггер: открытие, выбор, запрос, асинхронные пункты, ошибки набора), `tests/rich-text-editor-custom-button.test.tsx` (кнопки своего Инструмента), `tests/rich-text-editor-custom-markdown.test.tsx` (Markdown своего Блока по умолчанию и по своим правилам), `tests/rich-text-editor-atom-text.test.tsx` (Текст атома, вес в `maxLength`, пустота), `tests/rich-text-editor-empty-table.test.tsx` (пустая таблица — содержимое), `tests/rich-text-editor-max-height.test.tsx` (`maxHeight` и `resizable`: что внутри области прокрутки, место Ручки Блока при прокрутке), `tests/rich-text-editor-events.test.tsx` (`onReady`, `onFocus`, `onBlur`, порядок вставки и drop), `tests/rich-text-editor-loaders.test.tsx` (Загрузчики Части для движка, «Повторить»), `tests/rich-text-editor-skeleton.test.tsx` (Скелет), `tests/rich-text-editor-emoji.test.tsx` (эмодзи), `tests/rich-text-editor-json.test.tsx` (JSON), `tests/editor-search.test.tsx`, `tests/editor-search-panel.test.tsx` и `tests/editor-search-replace.test.tsx` (поиск и замена), `tests/rich-text-paper.test.tsx`, `tests/rich-text-paper-css.test.tsx`, `tests/editor-entry.test.ts`, `tests/editor-schema-entry.test.ts`, `tests/editor-highlight-entry.test.ts`; в браузере — `tests-visual/interactions.spec.ts` («RichTextEditor inside Dialog» — Escape в списке стилей, в Меню вставки, в поповере ссылки и в меню языка блока кода; «RichTextEditor inside-dialog» и «inside-drawer» — меню «…» и поповеры цвета мышью и клавиатурой; «RichTextEditor insert menu»; «RichTextEditor block commands» — настоящие `⌥⇧↑/↓`, `⌘]`, `⌘[` и `⌘⇧D`), `tests-visual/rich-text-editor-image.spec.ts` (перетаскивание файла и ручки ширины), `tests-visual/rich-text-editor-bubble.spec.ts` (Меню выделения в `Dialog`, `Drawer` и контейнере прокрутки, у края окна, инверсная поверхность в трёх темах), `tests-visual/rich-text-editor-layout.spec.ts` (Раскладка в `Dialog`: колонки рядом и Tab по ним, стрелки, столбец на телефоне), `tests-visual/rich-text-editor-wrapper.spec.ts` (Обёртка: пунктир в Редакторе и без рамки в `RichTextView`, тон одним видом в обоих, выход по Enter, `↑` из Обёртки), `tests-visual/rich-text-editor-block-handle.spec.ts` (меню ручки в `Dialog`: `Ctrl/⌘+/`, Escape по уровням; место ручки у первой строки Блока), `tests-visual/rich-text-editor-trigger.spec.ts` (свой символ-триггер: список у каретки, настоящий ввод `@`, выбор мышью и Enter, `a@b` внутри слова, axe в трёх темах), `tests-visual/rich-text-editor-source.spec.ts` (HTML-режим: высота поля, рост по содержимому, фокус на входе и выходе), `tests-visual/rich-text-editor-height.spec.ts` (Высота поля), `tests-visual/rich-text-editor-emoji.spec.ts` (эмодзи), `tests-visual/rich-text-editor-skeleton.spec.ts` (Скелет).
|
|
1769
|
+
- Исходник: `src/editor/RichTextEditor.tsx`; Панель — `src/editor/ui/EditorToolbar.tsx`, меню форматирования («¶», «…», «Выравнивание», «Списки») — `src/editor/ui/FormatMenus.tsx` и `src/editor/core/blockTypes.ts`, плавающая — `src/editor/ui/FloatingToolbar.tsx`, Меню выделения — `src/editor/ui/SelectionBubble.tsx`, общее условие показа и позиция — `src/editor/ui/selectionMenu.ts`; ссылка — `src/editor/features/link/link.ts`, описание Инструмента `src/editor/features/link/linkTool.tsx` и форма адреса `src/editor/features/link/LinkPopover.tsx`; эмодзи — описание Инструмента `src/editor/features/emoji/emojiTool.tsx` и сетка `src/editor/features/emoji/EmojiGrid.tsx`; кнопки из описаний Инструментов и рамка их поповеров — `src/editor/ui/ToolButtonView.tsx`, их сочетания — `src/editor/core/toolButtons.ts`, сочетания их Пунктов вставки и Действий над Блоком — `src/editor/core/toolEntryShortcuts.ts`; картинка — `src/editor/features/image/image.ts` (узел, загрузка, вставка файлов), `src/editor/features/image/ImagePopover.tsx`, `src/editor/features/image/ImageToolbar.tsx`; Сообщение поля — команда `src/editor/core/fieldNotice.ts`, тексты о файлах `src/editor/features/image/imageNotice.ts`, живой регион, строка ошибки и Строка статуса `src/editor/ui/FieldStatus.tsx`; свой Инструмент — публичная форма `src/editor/core/customTool.ts`, движок и проверка набора `src/editor/core/customToolEngine.ts`, разворот `tools` и Опции встроенных `src/editor/features/builtins.ts`; `tool()` и карта `RichTextTools` — `src/editor/core/toolOptions.ts`, типы Команд — `src/editor/core/toolCommands.ts`, типы Состояния — `src/editor/core/toolState.ts`, хук Состояния — `src/editor/hooks/useRichTextToolState.ts`, описания Поиска и Оглавления — `src/editor/features/search/searchTool.ts` и `src/editor/features/toc/tocTool.ts`; таблица — `src/editor/features/table/tables.ts` (узлы, слияние, выравнивание, Markdown), `src/editor/features/table/tableActions.ts` (команды меню, сортировка, память размера), `src/editor/features/table/TableMenuButton.tsx` (меню «Таблица»), `src/editor/features/table/TableSizeGrid.tsx` и `src/editor/features/table/TableInsertDialog.tsx`; Раскладка — `src/editor/features/layout/layout.ts` (узлы, команды, клавиатура) и `src/editor/features/layout/columnLayouts.ts` (варианты данными); Обёртка — `src/editor/features/wrapper/wrapper.ts` (узел, вставка, снятие, тон, клавиатура, Markdown) и `src/editor/features/wrapper/wrapperTones.ts` (тоны и метки GitHub alerts данными); Документ с контейнерами Блоков — `src/editor/core/document.ts`; Хэндл — `src/editor/core/handle.ts`, хук — `src/editor/hooks/useRichTextEditorState.ts`; HTML-режим — состояние и применение в `src/editor/RichTextEditor.tsx`, форматирование HTML — `src/editor/core/sourceFormat.ts`; Инструменты и Пресеты — `src/editor/core/tools.ts`; команды над Блоками — `src/editor/core/blockCommands.ts`; Ручка Блока — `src/editor/ui/BlockHandle.tsx`; таблица сочетаний и подписи — `src/editor/core/shortcuts.ts`, Справочник сочетаний — `src/editor/ui/ShortcutsButton.tsx`; Стекло всплывающих поверхностей — `src/editor/styles/glass.ts`; Меню вставки — `src/editor/core/insertItems.ts` (реестр пунктов), `src/editor/ui/SlashMenu.tsx`, `src/editor/ui/InsertMenuButton.tsx`, `src/editor/core/slashCommand.ts`; Схема данными — `src/editor/core/schema.ts`; палитра и выравнивания — `src/editor/styles/palette.ts`, расширения цвета — `src/editor/features/color/styleExtensions.ts`; цвет автора — форма и разбор `src/editor/features/color/customColor.ts`, контраст `src/editor/features/color/contrast.ts`, поповер `src/editor/features/color/CustomColorPopover.tsx`; типографика — `src/editor/styles/prose.ts`; блок кода — `src/editor/features/code/codeBlock.ts` (расширение, псевдонимы, `Alt+F10`), `src/editor/features/code/CodeBlockView.tsx` (шапка: язык и «Копировать»), `src/editor/features/code/CodeCopyButton.tsx` (кнопка с подсказкой), `src/editor/features/code/codeHeader.ts` (классы шапки, общие с Просмотром), Лист `surface="paper"` — `src/editor/styles/surface.ts` и `src/editor/styles/tokens.ts`, `src/editor/features/code/codeLanguages.ts` (языки данными), `src/editor/features/code/lowlight.ts` (грамматики), `src/editor/styles/codeTheme.ts` (тема подсветки синтаксиса), серверный хелпер — `src/editor/features/code/highlight.ts`; поиск и замена — `src/editor/features/search/searchTool.ts` (Инструмент), `src/editor/features/search/searchPlugin.ts` и `src/editor/features/search/SearchPanel.tsx`; JSON — `src/editor/core/jsonDocument.ts`; Высота поля — Ручка высоты `src/editor/ui/FieldResizer.tsx`; эмодзи (данные набора) — `src/editor/features/emoji/emoji.ts`; предел символов — `src/editor/core/maxLength.ts`; Markdown — `src/editor/core/markdown.ts`.
|
|
1770
|
+
- Тесты: `tests/rich-text-editor-text-card.test.tsx` (Карточка у текста), `tests/rich-text-editor.test.tsx`, `tests/rich-text-editor-handle.test.tsx` и `tests/rich-text-editor-handle-ssr.test.tsx` (Хэндл и хук), `tests/rich-text-editor-toolbar.test.tsx`, `tests/rich-text-editor-block-menu.test.tsx`, `tests/rich-text-editor-more-menu.test.tsx`, `tests/rich-text-editor-align-list-menus.test.tsx`, `tests/rich-text-editor-insert-menu.test.tsx`, `tests/rich-text-editor-schema.test.tsx`, `tests/rich-text-editor-markdown.test.tsx`, `tests/rich-text-editor-color.test.tsx`, `tests/rich-text-editor-custom-color.test.tsx`, `tests/rich-text-editor-link.test.tsx`, `tests/rich-text-editor-floating.test.tsx`, `tests/rich-text-editor-bubble.test.tsx`, `tests/rich-text-editor-glass.test.tsx`, `tests/rich-text-editor-table.test.tsx`, `tests/rich-text-editor-lazy-builtins.test.tsx` (ленивые блок кода и таблица: `basic` их не грузит, `full` — Скелет до чанков), `tests/rich-text-editor-image.test.tsx`, `tests/rich-text-editor-notice.test.tsx`, `tests/rich-text-editor-code-block.test.tsx`, `tests/rich-text-editor-block-commands.test.tsx`, `tests/rich-text-editor-block-handle.test.tsx`, `tests/rich-text-editor-shortcuts.test.tsx`, `tests/rich-text-editor-layout.test.tsx`, `tests/rich-text-editor-wrapper.test.tsx`, `tests/rich-text-editor-wrapper-tone.test.tsx`, `tests/rich-text-editor-source.test.tsx`, `tests/rich-text-editor-custom-tool.test.tsx` (свой Инструмент; тестовые Инструменты — `tests/editor-test-tools.ts`), `tests/rich-text-editor-custom-ui.test.tsx` (Пункты вставки и Действия над Блоком своего Инструмента), `tests/rich-text-editor-trigger.test.tsx` (свой символ-триггер: открытие, выбор, запрос, асинхронные пункты, ошибки набора), `tests/rich-text-editor-custom-button.test.tsx` (кнопки своего Инструмента), `tests/rich-text-editor-custom-markdown.test.tsx` (Markdown своего Блока по умолчанию и по своим правилам), `tests/rich-text-editor-atom-text.test.tsx` (Текст атома, вес в `maxLength`, пустота), `tests/rich-text-editor-empty-table.test.tsx` (пустая таблица — содержимое), `tests/rich-text-editor-max-height.test.tsx` (`maxHeight` и `resizable`: что внутри области прокрутки, место Ручки Блока при прокрутке), `tests/rich-text-editor-events.test.tsx` (`onReady`, `onFocus`, `onBlur`, порядок вставки и drop), `tests/rich-text-editor-loaders.test.tsx` (Загрузчики Части для движка, «Повторить»), `tests/rich-text-editor-skeleton.test.tsx` (Скелет), `tests/rich-text-editor-emoji.test.tsx` (эмодзи), `tests/rich-text-editor-json.test.tsx` (JSON), `tests/editor-search.test.tsx`, `tests/editor-search-panel.test.tsx` и `tests/editor-search-replace.test.tsx` (поиск и замена), `tests/rich-text-editor-tool-options.test.tsx` и `tests/editor-tool-options-types.test.ts` (Опции `tool()`), `tests/rich-text-editor-tool-state.test.tsx`, `tests/rich-text-editor-tool-state-ssr.test.tsx` и `tests/editor-tool-state-types.test.ts` (Состояние), `tests/rich-text-editor-tool-commands.test.tsx`, `tests/editor-search-commands-reveal.test.tsx` и `tests/editor-tool-commands-types.test.ts` (Команды `handle.tool()`), `tests/rich-text-editor-define-tool.test.tsx`, `tests/editor-define-tool-types.test.ts` и `tests/editor-define-tool-server.test.tsx` (`defineTool`), `tests/rich-text-paper.test.tsx`, `tests/rich-text-paper-css.test.tsx`, `tests/editor-entry.test.ts`, `tests/editor-schema-entry.test.ts`, `tests/editor-highlight-entry.test.ts`; в браузере — `tests-visual/interactions.spec.ts` («RichTextEditor inside Dialog» — Escape в списке стилей, в Меню вставки, в поповере ссылки и в меню языка блока кода; «RichTextEditor inside-dialog» и «inside-drawer» — меню «…» и поповеры цвета мышью и клавиатурой; «RichTextEditor insert menu»; «RichTextEditor block commands» — настоящие `⌥⇧↑/↓`, `⌘]`, `⌘[` и `⌘⇧D`), `tests-visual/rich-text-editor-image.spec.ts` (перетаскивание файла и ручки ширины), `tests-visual/rich-text-editor-bubble.spec.ts` (Меню выделения в `Dialog`, `Drawer` и контейнере прокрутки, у края окна, инверсная поверхность в трёх темах), `tests-visual/rich-text-editor-layout.spec.ts` (Раскладка в `Dialog`: колонки рядом и Tab по ним, стрелки, столбец на телефоне), `tests-visual/rich-text-editor-wrapper.spec.ts` (Обёртка: пунктир в Редакторе и без рамки в `RichTextView`, тон одним видом в обоих, выход по Enter, `↑` из Обёртки), `tests-visual/rich-text-editor-block-handle.spec.ts` (меню ручки в `Dialog`: `Ctrl/⌘+/`, Escape по уровням; место ручки у первой строки Блока), `tests-visual/rich-text-editor-trigger.spec.ts` (свой символ-триггер: список у каретки, настоящий ввод `@`, выбор мышью и Enter, `a@b` внутри слова, axe в трёх темах), `tests-visual/rich-text-editor-source.spec.ts` (HTML-режим: высота поля, рост по содержимому, фокус на входе и выходе), `tests-visual/rich-text-editor-height.spec.ts` (Высота поля), `tests-visual/rich-text-editor-emoji.spec.ts` (эмодзи), `tests-visual/rich-text-editor-skeleton.spec.ts` (Скелет).
|
|
1553
1771
|
- API расширения одной картой, «Стабильность» и рецепты — [API расширения Редактора](../../api/editor-extension.md).
|
|
1554
1772
|
- Показ без правки — [RichTextView](../content/rich-text-view.md).
|
|
1555
|
-
- Storybook: `Inputs/RichTextEditor
|
|
1773
|
+
- Storybook: `Inputs/RichTextEditor` (истории `SearchStatusLine`, `TableOfContentsOptions`, `TableOfContentsExternalNavigation`, `ToolCommands`, `DefinedTool` и `DefinedToolConfigured`).
|
|
1556
1774
|
- Происхождение кода: minimal-tiptap (MIT); цвета темы подсветки синтаксиса — highlight.js (BSD-3-Clause); лицензии — в `NOTICE` пакета.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
sourceHash:
|
|
2
|
+
sourceHash: 340e1ec512cb
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Setting up `@olddevs/ui`
|
|
@@ -133,11 +133,11 @@ peer dependencies are treated as external, and the metric is gzip:
|
|
|
133
133
|
| one `Button` | 1.6 kB |
|
|
134
134
|
| `DataTable` | 9.0 kB |
|
|
135
135
|
| the whole kit (`import *`) | 77.1 kB |
|
|
136
|
-
| `RichTextEditor` from `@olddevs/ui/editor`, without the engine, "start" |
|
|
137
|
-
| `RichTextEditor` with the Tiptap engine, "start" (static graph, `basic`) |
|
|
138
|
-
| `RichTextEditor` with the Tiptap engine, "full" (with all lazy chunks, `full`) |
|
|
139
|
-
| `RichTextView` from `@olddevs/ui/editor`, Tiptap engine included in the measurement | 12.
|
|
140
|
-
| `sanitizeRichText` and `richTextSanitizeConfig` from `@olddevs/ui/editor/schema`, Tiptap engine included | 3.
|
|
136
|
+
| `RichTextEditor` from `@olddevs/ui/editor`, without the engine, "start" | 72.7 kB |
|
|
137
|
+
| `RichTextEditor` with the Tiptap engine, "start" (static graph, `basic`) | 297.5 kB |
|
|
138
|
+
| `RichTextEditor` with the Tiptap engine, "full" (with all lazy chunks, `full`) | 346.6 kB |
|
|
139
|
+
| `RichTextView` from `@olddevs/ui/editor`, Tiptap engine included in the measurement | 12.3 kB |
|
|
140
|
+
| `sanitizeRichText` and `richTextSanitizeConfig` from `@olddevs/ui/editor/schema`, Tiptap engine included | 3.9 kB |
|
|
141
141
|
| `highlightCodeBlocks` from `@olddevs/ui/editor/highlight`, with lowlight | 22.6 kB |
|
|
142
142
|
| `highlightCodeNodes` from `@olddevs/ui/editor/highlight`, with lowlight | 22.6 kB |
|
|
143
143
|
|
|
@@ -158,7 +158,7 @@ an app bundler with full minification produced about 133 kB (measured before the
|
|
|
158
158
|
For `RichTextView`, Tiptap and lowlight are included in the measurement as a check. Its row contains only
|
|
159
159
|
typography and the Island of the "Copy" button on code Blocks (the kit's button and tooltip, the message catalog),
|
|
160
160
|
and the measurement proves that its graph contains neither the engine nor a highlighter. The lightweight
|
|
161
|
-
`@olddevs/ui/editor/schema` entry point is measured the same way (3.
|
|
161
|
+
`@olddevs/ui/editor/schema` entry point is measured the same way (3.9 kB): the Schema, `richTextSchema`, the
|
|
162
162
|
`sanitizeRichText` sanitizer with hooks for DOMPurify, including for the rules of custom Tools, and `markRange`.
|
|
163
163
|
|
|
164
164
|
Server-side highlighting in `@olddevs/ui/editor/highlight` (22.6 kB — almost entirely the highlight.js core and
|
package/docs/getting-started.md
CHANGED
|
@@ -130,11 +130,11 @@ peer-зависимости внешние, метрика gzip:
|
|
|
130
130
|
| одна `Button` | 1,6 кБ |
|
|
131
131
|
| `DataTable` | 9,0 кБ |
|
|
132
132
|
| весь кит целиком (`import *`) | 77,1 кБ |
|
|
133
|
-
| `RichTextEditor` из `@olddevs/ui/editor`, без движка, «старт» |
|
|
134
|
-
| `RichTextEditor` вместе с движком Tiptap, «старт» (статический граф, `basic`) |
|
|
135
|
-
| `RichTextEditor` вместе с движком Tiptap, «полный» (со всеми ленивыми чанками, `full`) |
|
|
136
|
-
| `RichTextView` из `@olddevs/ui/editor`, движок Tiptap в замер включён | 12,
|
|
137
|
-
| `sanitizeRichText` и `richTextSanitizeConfig` из `@olddevs/ui/editor/schema`, движок Tiptap в замер включён | 3,
|
|
133
|
+
| `RichTextEditor` из `@olddevs/ui/editor`, без движка, «старт» | 72,7 кБ |
|
|
134
|
+
| `RichTextEditor` вместе с движком Tiptap, «старт» (статический граф, `basic`) | 297,5 кБ |
|
|
135
|
+
| `RichTextEditor` вместе с движком Tiptap, «полный» (со всеми ленивыми чанками, `full`) | 346,6 кБ |
|
|
136
|
+
| `RichTextView` из `@olddevs/ui/editor`, движок Tiptap в замер включён | 12,3 кБ |
|
|
137
|
+
| `sanitizeRichText` и `richTextSanitizeConfig` из `@olddevs/ui/editor/schema`, движок Tiptap в замер включён | 3,9 кБ |
|
|
138
138
|
| `highlightCodeBlocks` из `@olddevs/ui/editor/highlight`, вместе с lowlight | 22,6 кБ |
|
|
139
139
|
| `highlightCodeNodes` из `@olddevs/ui/editor/highlight`, вместе с lowlight | 22,6 кБ |
|
|
140
140
|
|
|
@@ -155,7 +155,7 @@ peer-зависимости внешние, метрика gzip:
|
|
|
155
155
|
У `RichTextView` Tiptap и lowlight внесены в замер ради проверки. В его строку входят только
|
|
156
156
|
типографика и Остров кнопки «Копировать» у Блоков кода (кнопка и подсказка кита, каталог сообщений),
|
|
157
157
|
и замер доказывает, что в графе нет ни движка, ни подсветчика. Так же меряется лёгкий вход
|
|
158
|
-
`@olddevs/ui/editor/schema` (3,
|
|
158
|
+
`@olddevs/ui/editor/schema` (3,9 кБ): Схема, `richTextSchema`, очистка `sanitizeRichText` с хуками для
|
|
159
159
|
DOMPurify, в том числе по правилам своих Инструментов, и `markRange`.
|
|
160
160
|
|
|
161
161
|
Серверная подсветка `@olddevs/ui/editor/highlight` (22,6 кБ — почти целиком ядро highlight.js и
|