@olddevs/ui 4.5.0 → 4.6.0
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 +24 -0
- package/dist/editor/RichTextEditor.d.ts +2 -2
- package/dist/editor/RichTextEditor.d.ts.map +1 -1
- package/dist/editor/RichTextEditor.js +3 -0
- package/dist/editor/RichTextEditor.js.map +1 -1
- package/dist/editor/core/blockTypes.d.ts +2 -8
- package/dist/editor/core/blockTypes.d.ts.map +1 -1
- package/dist/editor/core/blockTypes.js +11 -54
- package/dist/editor/core/blockTypes.js.map +1 -1
- package/dist/editor/core/containers.d.ts.map +1 -1
- package/dist/editor/core/containers.js +1 -0
- package/dist/editor/core/containers.js.map +1 -1
- package/dist/editor/core/customMarkdown.js +1 -1
- package/dist/editor/core/customMarkdown.js.map +1 -1
- package/dist/editor/core/customTool.d.ts +6 -6
- package/dist/editor/core/customTool.d.ts.map +1 -1
- package/dist/editor/core/customToolEngine.d.ts +2 -2
- package/dist/editor/core/extensions.d.ts +7 -2
- package/dist/editor/core/extensions.d.ts.map +1 -1
- package/dist/editor/core/extensions.js +96 -64
- package/dist/editor/core/extensions.js.map +1 -1
- package/dist/editor/core/fieldNotice.d.ts +1 -1
- package/dist/editor/core/insertItems.d.ts +5 -28
- package/dist/editor/core/insertItems.d.ts.map +1 -1
- package/dist/editor/core/insertItems.js +3 -94
- package/dist/editor/core/insertItems.js.map +1 -1
- package/dist/editor/core/insertMenuTool.d.ts +13 -0
- package/dist/editor/core/insertMenuTool.d.ts.map +1 -0
- package/dist/editor/core/insertMenuTool.js +20 -0
- package/dist/editor/core/insertMenuTool.js.map +1 -0
- package/dist/editor/core/schema.d.ts +20 -5
- package/dist/editor/core/schema.d.ts.map +1 -1
- package/dist/editor/core/schema.js +18 -3
- package/dist/editor/core/schema.js.map +1 -1
- package/dist/editor/core/shortcuts.d.ts +56 -5
- package/dist/editor/core/shortcuts.d.ts.map +1 -1
- package/dist/editor/core/shortcuts.js +91 -156
- package/dist/editor/core/shortcuts.js.map +1 -1
- package/dist/editor/core/skeleton.d.ts +1 -1
- package/dist/editor/core/skeleton.d.ts.map +1 -1
- package/dist/editor/core/skeleton.js +1 -0
- package/dist/editor/core/skeleton.js.map +1 -1
- package/dist/editor/core/toolButtons.d.ts +3 -3
- package/dist/editor/core/toolDefinition.d.ts +3 -3
- package/dist/editor/core/toolDescriptor.d.ts +49 -30
- package/dist/editor/core/toolDescriptor.d.ts.map +1 -1
- package/dist/editor/core/toolDescriptor.js +2 -5
- package/dist/editor/core/toolDescriptor.js.map +1 -1
- package/dist/editor/core/toolLoader.d.ts +1 -1
- package/dist/editor/core/toolLoader.d.ts.map +1 -1
- package/dist/editor/core/toolOptions.d.ts +19 -2
- package/dist/editor/core/toolOptions.d.ts.map +1 -1
- package/dist/editor/core/toolOptions.js.map +1 -1
- package/dist/editor/core/tools.d.ts +10 -2
- package/dist/editor/core/tools.d.ts.map +1 -1
- package/dist/editor/core/tools.js +1 -0
- package/dist/editor/core/tools.js.map +1 -1
- package/dist/editor/features/builtins.d.ts +6 -8
- package/dist/editor/features/builtins.d.ts.map +1 -1
- package/dist/editor/features/builtins.js +48 -21
- package/dist/editor/features/builtins.js.map +1 -1
- package/dist/editor/features/code/codeBlockTool.d.ts +5 -6
- package/dist/editor/features/code/codeBlockTool.d.ts.map +1 -1
- package/dist/editor/features/code/codeBlockTool.js +10 -1
- package/dist/editor/features/code/codeBlockTool.js.map +1 -1
- package/dist/editor/features/color/colorTools.d.ts +14 -0
- package/dist/editor/features/color/colorTools.d.ts.map +1 -0
- package/dist/editor/features/color/colorTools.js +39 -0
- package/dist/editor/features/color/colorTools.js.map +1 -0
- package/dist/editor/features/details/details.d.ts +68 -0
- package/dist/editor/features/details/details.d.ts.map +1 -0
- package/dist/editor/features/details/details.js +237 -0
- package/dist/editor/features/details/details.js.map +1 -0
- package/dist/editor/features/details/detailsMarkdown.d.ts +17 -0
- package/dist/editor/features/details/detailsMarkdown.d.ts.map +1 -0
- package/dist/editor/features/details/detailsMarkdown.js +84 -0
- package/dist/editor/features/details/detailsMarkdown.js.map +1 -0
- package/dist/editor/features/details/detailsTool.d.ts +16 -0
- package/dist/editor/features/details/detailsTool.d.ts.map +1 -0
- package/dist/editor/features/details/detailsTool.js +39 -0
- package/dist/editor/features/details/detailsTool.js.map +1 -0
- package/dist/editor/features/emoji/emojiTool.d.ts +1 -1
- package/dist/editor/features/heading/headingTool.d.ts +18 -0
- package/dist/editor/features/heading/headingTool.d.ts.map +1 -0
- package/dist/editor/features/heading/headingTool.js +59 -0
- package/dist/editor/features/heading/headingTool.js.map +1 -0
- package/dist/editor/features/history/historyTool.d.ts +15 -0
- package/dist/editor/features/history/historyTool.d.ts.map +1 -0
- package/dist/editor/features/history/historyTool.js +28 -0
- package/dist/editor/features/history/historyTool.js.map +1 -0
- package/dist/editor/features/image/imageTool.d.ts +19 -0
- package/dist/editor/features/image/imageTool.d.ts.map +1 -0
- package/dist/editor/features/image/imageTool.js +28 -0
- package/dist/editor/features/image/imageTool.js.map +1 -0
- package/dist/editor/features/layout/layoutTool.d.ts +11 -0
- package/dist/editor/features/layout/layoutTool.d.ts.map +1 -0
- package/dist/editor/features/layout/layoutTool.js +20 -0
- package/dist/editor/features/layout/layoutTool.js.map +1 -0
- package/dist/editor/features/lists/listTools.d.ts +15 -0
- package/dist/editor/features/lists/listTools.d.ts.map +1 -0
- package/dist/editor/features/lists/listTools.js +78 -0
- package/dist/editor/features/lists/listTools.js.map +1 -0
- package/dist/editor/features/marks/markTools.d.ts +16 -0
- package/dist/editor/features/marks/markTools.d.ts.map +1 -0
- package/dist/editor/features/marks/markTools.js +43 -0
- package/dist/editor/features/marks/markTools.js.map +1 -0
- package/dist/editor/features/search/searchTool.d.ts +1 -1
- package/dist/editor/features/table/tableTool.d.ts +3 -3
- package/dist/editor/features/toc/RichTextToc.d.ts.map +1 -1
- package/dist/editor/features/toc/RichTextToc.js +9 -2
- package/dist/editor/features/toc/RichTextToc.js.map +1 -1
- package/dist/editor/features/wrapper/wrapperTool.d.ts +11 -0
- package/dist/editor/features/wrapper/wrapperTool.d.ts.map +1 -0
- package/dist/editor/features/wrapper/wrapperTool.js +32 -0
- package/dist/editor/features/wrapper/wrapperTool.js.map +1 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js.map +1 -1
- package/dist/editor/schema-entry.d.ts +1 -1
- package/dist/editor/styles/prose.d.ts.map +1 -1
- package/dist/editor/styles/prose.js +26 -0
- package/dist/editor/styles/prose.js.map +1 -1
- package/dist/editor/ui/EditorToolbar.d.ts.map +1 -1
- package/dist/editor/ui/EditorToolbar.js +5 -38
- package/dist/editor/ui/EditorToolbar.js.map +1 -1
- package/dist/editor/ui/SelectionBubble.d.ts.map +1 -1
- package/dist/editor/ui/SelectionBubble.js +1 -1
- package/dist/editor/ui/SelectionBubble.js.map +1 -1
- package/dist/editor/ui/ToolButtonView.d.ts.map +1 -1
- package/dist/editor/ui/ToolButtonView.js +1 -1
- package/dist/editor/ui/ToolButtonView.js.map +1 -1
- package/dist/i18n/defaults.d.ts.map +1 -1
- package/dist/i18n/defaults.js +3 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/messages.d.ts +16 -1
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/icons.d.ts +8 -1
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +1 -1
- package/dist/icons.js.map +1 -1
- package/dist/locales/ru.d.ts.map +1 -1
- package/dist/locales/ru.js +3 -0
- package/dist/locales/ru.js.map +1 -1
- package/docs/api/editor-extension.en.md +56 -56
- package/docs/api/editor-extension.md +55 -55
- package/docs/api/messages.en.md +4 -1
- package/docs/api/messages.md +3 -0
- package/docs/api/migration-notes.en.md +3 -3
- package/docs/api/migration-notes.md +2 -2
- package/docs/components/content/rich-text-view.en.md +18 -12
- package/docs/components/content/rich-text-view.md +17 -11
- package/docs/components/inputs/rich-text-editor.en.md +140 -87
- package/docs/components/inputs/rich-text-editor.md +139 -86
- package/docs/conventions.en.md +2 -2
- package/docs/conventions.md +1 -1
- package/docs/getting-started.en.md +9 -9
- package/docs/getting-started.md +8 -8
- package/docs/glossary.en.md +80 -52
- package/docs/glossary.md +79 -51
- package/docs/icons.en.md +4 -1
- package/docs/icons.md +3 -0
- package/package.json +2 -1
- package/src/editor/RichTextEditor.tsx +9 -6
- package/src/editor/core/atomText.ts +2 -2
- package/src/editor/core/blockTypes.ts +19 -83
- package/src/editor/core/containers.ts +4 -2
- package/src/editor/core/customMarkdown.ts +2 -2
- package/src/editor/core/customTool.ts +6 -6
- package/src/editor/core/customToolEngine.ts +9 -9
- package/src/editor/core/extensions.ts +165 -110
- package/src/editor/core/fieldNotice.ts +1 -1
- package/src/editor/core/handle.ts +2 -2
- package/src/editor/core/insertItems.ts +12 -158
- package/src/editor/core/insertMenuTool.ts +32 -0
- package/src/editor/core/jsonDocument.ts +1 -1
- package/src/editor/core/schema.ts +42 -7
- package/src/editor/core/shortcuts.ts +116 -177
- package/src/editor/core/skeleton.ts +4 -3
- package/src/editor/core/toolButtons.ts +3 -3
- package/src/editor/core/toolDefinition.ts +4 -4
- package/src/editor/core/toolDescriptor.ts +65 -52
- package/src/editor/core/toolLoader.ts +3 -3
- package/src/editor/core/toolOptions.ts +21 -2
- package/src/editor/core/tools.ts +10 -1
- package/src/editor/core/viewIsland.ts +1 -1
- package/src/editor/features/builtins.ts +76 -41
- package/src/editor/features/code/codeBlockTool.ts +16 -8
- package/src/editor/features/color/colorTools.ts +68 -0
- package/src/editor/features/details/details.ts +389 -0
- package/src/editor/features/details/detailsMarkdown.ts +158 -0
- package/src/editor/features/details/detailsTool.ts +69 -0
- package/src/editor/features/emoji/emojiTool.tsx +1 -1
- package/src/editor/features/heading/headingTool.ts +96 -0
- package/src/editor/features/history/historyTool.ts +42 -0
- package/src/editor/features/image/imageTool.ts +49 -0
- package/src/editor/features/layout/layoutTool.ts +40 -0
- package/src/editor/features/lists/listTools.ts +112 -0
- package/src/editor/features/marks/markTools.ts +78 -0
- package/src/editor/features/search/searchTool.ts +1 -1
- package/src/editor/features/table/tableTool.ts +3 -3
- package/src/editor/features/toc/RichTextToc.tsx +14 -3
- package/src/editor/features/toc/tocTool.ts +1 -1
- package/src/editor/features/wrapper/wrapperTool.ts +52 -0
- package/src/editor/index.ts +1 -0
- package/src/editor/schema-entry.ts +1 -1
- package/src/editor/styles/prose.ts +49 -0
- package/src/editor/ui/EditorToolbar.tsx +7 -50
- package/src/editor/ui/SelectionBubble.tsx +2 -5
- package/src/editor/ui/ToolButtonView.tsx +2 -1
- package/src/i18n/defaults.ts +3 -0
- package/src/i18n/messages.ts +14 -1
- package/src/icons.ts +7 -0
- package/src/locales/ru.ts +3 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { UiMessages } from "../../i18n/messages.js";
|
|
2
|
-
import {
|
|
2
|
+
import { toolLabel, type ToolList } from "./toolDescriptor.js";
|
|
3
3
|
import type { PrefixedName } from "./customTool.js";
|
|
4
4
|
import type { Tool } from "./tools.js";
|
|
5
5
|
|
|
@@ -65,7 +65,94 @@ export interface ShortcutCommand {
|
|
|
65
65
|
const LIST_TOOLS: readonly Tool[] = ["bulletList", "orderedList", "taskList"];
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
68
|
+
* Сочетания встроенных команд по id — данные, а не привязки. Строка справочника
|
|
69
|
+
* берёт клавиши отсюда, где бы она ни жила: в `SHORTCUTS` или в описании
|
|
70
|
+
* Инструмента (`shortcuts`, `keys` кнопки). Поэтому подписи Меню вставки и «¶»,
|
|
71
|
+
* которые читаются при загрузке модуля (`shortcutKeys`), не зависят от того,
|
|
72
|
+
* где лежит строка.
|
|
73
|
+
*/
|
|
74
|
+
export const SHORTCUT_KEYS = {
|
|
75
|
+
selectBlock: ["mod", "A"],
|
|
76
|
+
selectDocument: ["mod", "A"],
|
|
77
|
+
undo: ["mod", "Z"],
|
|
78
|
+
redo: ["mod", "shift", "Z"],
|
|
79
|
+
duplicateBlock: ["mod", "shift", "D"],
|
|
80
|
+
moveBlockUp: ["alt", "shift", "↑"],
|
|
81
|
+
moveBlockDown: ["alt", "shift", "↓"],
|
|
82
|
+
blockActions: ["mod", "/"],
|
|
83
|
+
clearFormatting: ["mod", "\\"],
|
|
84
|
+
bold: ["mod", "B"],
|
|
85
|
+
italic: ["mod", "I"],
|
|
86
|
+
strike: ["mod", "shift", "S"],
|
|
87
|
+
underline: ["mod", "U"],
|
|
88
|
+
code: ["mod", "E"],
|
|
89
|
+
superscript: ["mod", "."],
|
|
90
|
+
subscript: ["mod", ","],
|
|
91
|
+
paragraph: ["mod", "alt", "0"],
|
|
92
|
+
h1: ["mod", "alt", "1"],
|
|
93
|
+
h2: ["mod", "alt", "2"],
|
|
94
|
+
h3: ["mod", "alt", "3"],
|
|
95
|
+
h4: ["mod", "alt", "4"],
|
|
96
|
+
blockquote: ["mod", "shift", "B"],
|
|
97
|
+
codeBlock: ["mod", "alt", "C"],
|
|
98
|
+
bulletList: ["mod", "shift", "8"],
|
|
99
|
+
orderedList: ["mod", "shift", "7"],
|
|
100
|
+
taskList: ["mod", "shift", "9"],
|
|
101
|
+
indentListItem: ["mod", "]"],
|
|
102
|
+
outdentListItem: ["mod", "["],
|
|
103
|
+
alignLeft: ["mod", "shift", "L"],
|
|
104
|
+
alignCenter: ["mod", "shift", "E"],
|
|
105
|
+
alignRight: ["mod", "shift", "R"],
|
|
106
|
+
focusToolbar: ["alt", "F10"],
|
|
107
|
+
} as const satisfies Record<string, readonly string[]>;
|
|
108
|
+
|
|
109
|
+
/** Id строки справочника из таблицы кита. */
|
|
110
|
+
export type ShortcutId = keyof typeof SHORTCUT_KEYS;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Порядок строк справочника внутри групп — привилегия кита, как `INSERT_ORDER`
|
|
114
|
+
* у Меню вставки, и не зависит от того, где живёт строка: в `SHORTCUTS` или в
|
|
115
|
+
* описании Инструмента. Строки вне списка (кнопки описаний, свои Инструменты)
|
|
116
|
+
* встают в конец своей группы в порядке набора.
|
|
117
|
+
*/
|
|
118
|
+
export const SHORTCUT_ORDER: readonly ShortcutId[] = [
|
|
119
|
+
"selectBlock",
|
|
120
|
+
"selectDocument",
|
|
121
|
+
"undo",
|
|
122
|
+
"redo",
|
|
123
|
+
"duplicateBlock",
|
|
124
|
+
"moveBlockUp",
|
|
125
|
+
"moveBlockDown",
|
|
126
|
+
"blockActions",
|
|
127
|
+
"clearFormatting",
|
|
128
|
+
"bold",
|
|
129
|
+
"italic",
|
|
130
|
+
"strike",
|
|
131
|
+
"underline",
|
|
132
|
+
"code",
|
|
133
|
+
"superscript",
|
|
134
|
+
"subscript",
|
|
135
|
+
"paragraph",
|
|
136
|
+
"h1",
|
|
137
|
+
"h2",
|
|
138
|
+
"h3",
|
|
139
|
+
"h4",
|
|
140
|
+
"blockquote",
|
|
141
|
+
"codeBlock",
|
|
142
|
+
"bulletList",
|
|
143
|
+
"orderedList",
|
|
144
|
+
"taskList",
|
|
145
|
+
"indentListItem",
|
|
146
|
+
"outdentListItem",
|
|
147
|
+
"alignLeft",
|
|
148
|
+
"alignCenter",
|
|
149
|
+
"alignRight",
|
|
150
|
+
"focusToolbar",
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Таблица — сочетания кита: команды, которые есть при любом наборе (выделение,
|
|
155
|
+
* Блоки, сдвиг пункта списка, `Alt+F10`). Строки Инструментов — в их описаниях.
|
|
69
156
|
* Сочетание кнопки описания — поле самой кнопки (`toolDescriptor.ts`): её
|
|
70
157
|
* строку справочник берёт оттуда, клавишу вешает `toolButtons.ts`.
|
|
71
158
|
*/
|
|
@@ -75,45 +162,36 @@ export const SHORTCUTS: readonly ShortcutCommand[] = [
|
|
|
75
162
|
id: "selectBlock",
|
|
76
163
|
group: "selection",
|
|
77
164
|
tool: null,
|
|
78
|
-
keys:
|
|
165
|
+
keys: SHORTCUT_KEYS.selectBlock,
|
|
79
166
|
label: (m) => m.selectBlock,
|
|
80
167
|
},
|
|
81
168
|
{
|
|
82
169
|
id: "selectDocument",
|
|
83
170
|
group: "selection",
|
|
84
171
|
tool: null,
|
|
85
|
-
keys:
|
|
172
|
+
keys: SHORTCUT_KEYS.selectDocument,
|
|
86
173
|
label: (m) => m.selectDocument,
|
|
87
174
|
},
|
|
88
175
|
|
|
89
|
-
{ id: "undo", group: "history", tool: "history", keys: ["mod", "Z"], label: (m) => m.undo },
|
|
90
|
-
{
|
|
91
|
-
id: "redo",
|
|
92
|
-
group: "history",
|
|
93
|
-
tool: "history",
|
|
94
|
-
keys: ["mod", "shift", "Z"],
|
|
95
|
-
label: (m) => m.redo,
|
|
96
|
-
},
|
|
97
|
-
|
|
98
176
|
{
|
|
99
177
|
id: "duplicateBlock",
|
|
100
178
|
group: "blocks",
|
|
101
179
|
tool: null,
|
|
102
|
-
keys:
|
|
180
|
+
keys: SHORTCUT_KEYS.duplicateBlock,
|
|
103
181
|
label: (m) => m.duplicateBlock,
|
|
104
182
|
},
|
|
105
183
|
{
|
|
106
184
|
id: "moveBlockUp",
|
|
107
185
|
group: "blocks",
|
|
108
186
|
tool: null,
|
|
109
|
-
keys:
|
|
187
|
+
keys: SHORTCUT_KEYS.moveBlockUp,
|
|
110
188
|
label: (m) => m.moveBlockUp,
|
|
111
189
|
},
|
|
112
190
|
{
|
|
113
191
|
id: "moveBlockDown",
|
|
114
192
|
group: "blocks",
|
|
115
193
|
tool: null,
|
|
116
|
-
keys:
|
|
194
|
+
keys: SHORTCUT_KEYS.moveBlockDown,
|
|
117
195
|
label: (m) => m.moveBlockDown,
|
|
118
196
|
},
|
|
119
197
|
// Меню ручки Блока: ручка есть в любой правке, при любой Панели.
|
|
@@ -121,172 +199,41 @@ export const SHORTCUTS: readonly ShortcutCommand[] = [
|
|
|
121
199
|
id: "blockActions",
|
|
122
200
|
group: "blocks",
|
|
123
201
|
tool: null,
|
|
124
|
-
keys:
|
|
202
|
+
keys: SHORTCUT_KEYS.blockActions,
|
|
125
203
|
label: (m) => m.blockActions,
|
|
126
204
|
},
|
|
127
205
|
|
|
128
|
-
{
|
|
129
|
-
id: "clearFormatting",
|
|
130
|
-
group: "clear",
|
|
131
|
-
tool: "clearFormatting",
|
|
132
|
-
keys: ["mod", "\\"],
|
|
133
|
-
label: (m) => m.clearFormatting,
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
{ id: "bold", group: "marks", tool: "bold", keys: ["mod", "B"], label: (m) => m.bold },
|
|
137
|
-
{ id: "italic", group: "marks", tool: "italic", keys: ["mod", "I"], label: (m) => m.italic },
|
|
138
|
-
{
|
|
139
|
-
id: "strike",
|
|
140
|
-
group: "marks",
|
|
141
|
-
tool: "strike",
|
|
142
|
-
keys: ["mod", "shift", "S"],
|
|
143
|
-
label: (m) => m.strike,
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
id: "underline",
|
|
147
|
-
group: "marks",
|
|
148
|
-
tool: "underline",
|
|
149
|
-
keys: ["mod", "U"],
|
|
150
|
-
label: (m) => m.underline,
|
|
151
|
-
},
|
|
152
|
-
{ id: "code", group: "marks", tool: "code", keys: ["mod", "E"], label: (m) => m.code },
|
|
153
|
-
{
|
|
154
|
-
id: "superscript",
|
|
155
|
-
group: "marks",
|
|
156
|
-
tool: "superscript",
|
|
157
|
-
keys: ["mod", "."],
|
|
158
|
-
label: (m) => m.superscript,
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
id: "subscript",
|
|
162
|
-
group: "marks",
|
|
163
|
-
tool: "subscript",
|
|
164
|
-
keys: ["mod", ","],
|
|
165
|
-
label: (m) => m.subscript,
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
// Подпись — как у пункта «¶» («Текст»), а не «Абзац» Меню вставки: справочник
|
|
169
|
-
// называет команду тем словом, которым её выбирают на Панели.
|
|
170
|
-
{
|
|
171
|
-
id: "paragraph",
|
|
172
|
-
group: "blockType",
|
|
173
|
-
tool: "heading",
|
|
174
|
-
keys: ["mod", "alt", "0"],
|
|
175
|
-
label: (m) => m.textBlock,
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
id: "h1",
|
|
179
|
-
group: "blockType",
|
|
180
|
-
tool: "heading1",
|
|
181
|
-
requires: "heading",
|
|
182
|
-
keys: ["mod", "alt", "1"],
|
|
183
|
-
label: (m) => m.heading({ level: 1 }),
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
id: "h2",
|
|
187
|
-
group: "blockType",
|
|
188
|
-
tool: "heading",
|
|
189
|
-
keys: ["mod", "alt", "2"],
|
|
190
|
-
label: (m) => m.heading({ level: 2 }),
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
id: "h3",
|
|
194
|
-
group: "blockType",
|
|
195
|
-
tool: "heading",
|
|
196
|
-
keys: ["mod", "alt", "3"],
|
|
197
|
-
label: (m) => m.heading({ level: 3 }),
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
id: "h4",
|
|
201
|
-
group: "blockType",
|
|
202
|
-
tool: "heading",
|
|
203
|
-
keys: ["mod", "alt", "4"],
|
|
204
|
-
label: (m) => m.heading({ level: 4 }),
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
id: "codeBlock",
|
|
208
|
-
group: "blockType",
|
|
209
|
-
tool: "codeBlock",
|
|
210
|
-
keys: ["mod", "alt", "C"],
|
|
211
|
-
label: (m) => m.codeBlock,
|
|
212
|
-
},
|
|
213
|
-
|
|
214
|
-
{
|
|
215
|
-
id: "bulletList",
|
|
216
|
-
group: "lists",
|
|
217
|
-
tool: "bulletList",
|
|
218
|
-
keys: ["mod", "shift", "8"],
|
|
219
|
-
label: (m) => m.bulletList,
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
id: "orderedList",
|
|
223
|
-
group: "lists",
|
|
224
|
-
tool: "orderedList",
|
|
225
|
-
keys: ["mod", "shift", "7"],
|
|
226
|
-
label: (m) => m.orderedList,
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
id: "taskList",
|
|
230
|
-
group: "lists",
|
|
231
|
-
tool: "taskList",
|
|
232
|
-
keys: ["mod", "shift", "9"],
|
|
233
|
-
label: (m) => m.taskList,
|
|
234
|
-
},
|
|
235
206
|
{
|
|
236
207
|
id: "indentListItem",
|
|
237
208
|
group: "lists",
|
|
238
209
|
tool: LIST_TOOLS,
|
|
239
|
-
keys:
|
|
210
|
+
keys: SHORTCUT_KEYS.indentListItem,
|
|
240
211
|
label: (m) => m.indentListItem,
|
|
241
212
|
},
|
|
242
213
|
{
|
|
243
214
|
id: "outdentListItem",
|
|
244
215
|
group: "lists",
|
|
245
216
|
tool: LIST_TOOLS,
|
|
246
|
-
keys:
|
|
217
|
+
keys: SHORTCUT_KEYS.outdentListItem,
|
|
247
218
|
label: (m) => m.outdentListItem,
|
|
248
219
|
},
|
|
249
220
|
|
|
250
|
-
{
|
|
251
|
-
id: "alignLeft",
|
|
252
|
-
group: "align",
|
|
253
|
-
tool: "align",
|
|
254
|
-
keys: ["mod", "shift", "L"],
|
|
255
|
-
label: (m) => m.alignLeft,
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
id: "alignCenter",
|
|
259
|
-
group: "align",
|
|
260
|
-
tool: "align",
|
|
261
|
-
keys: ["mod", "shift", "E"],
|
|
262
|
-
label: (m) => m.alignCenter,
|
|
263
|
-
},
|
|
264
|
-
{
|
|
265
|
-
id: "alignRight",
|
|
266
|
-
group: "align",
|
|
267
|
-
tool: "align",
|
|
268
|
-
keys: ["mod", "shift", "R"],
|
|
269
|
-
label: (m) => m.alignRight,
|
|
270
|
-
},
|
|
271
|
-
|
|
272
221
|
{
|
|
273
222
|
id: "focusToolbar",
|
|
274
223
|
group: "toolbar",
|
|
275
224
|
tool: null,
|
|
276
|
-
keys:
|
|
225
|
+
keys: SHORTCUT_KEYS.focusToolbar,
|
|
277
226
|
label: (m) => m.focusToolbar,
|
|
278
227
|
},
|
|
279
228
|
];
|
|
280
229
|
|
|
281
|
-
const BY_ID = new Map(SHORTCUTS.map((command) => [command.id, command]));
|
|
282
|
-
|
|
283
230
|
/**
|
|
284
231
|
* Сочетание команды по id или `undefined`, если у команды его нет. Панель
|
|
285
232
|
* спрашивает так про каждую свою кнопку: у горизонтальной линии, картинки и
|
|
286
233
|
* меню цвета сочетаний нет.
|
|
287
234
|
*/
|
|
288
235
|
export function findShortcutKeys(id: string): readonly string[] | undefined {
|
|
289
|
-
return
|
|
236
|
+
return Object.hasOwn(SHORTCUT_KEYS, id) ? SHORTCUT_KEYS[id as ShortcutId] : undefined;
|
|
290
237
|
}
|
|
291
238
|
|
|
292
239
|
/**
|
|
@@ -318,21 +265,13 @@ export interface ShortcutSection {
|
|
|
318
265
|
commands: readonly ShortcutRow[];
|
|
319
266
|
}
|
|
320
267
|
|
|
321
|
-
/**
|
|
322
|
-
* Место строки переехавшего Инструмента в своей группе: id строки → id строки
|
|
323
|
-
* из `SHORTCUTS`, перед которой она встаёт. Остальные переехавшие строки идут
|
|
324
|
-
* в конец группы. Порядок справочника — не поле описания: место на поверхности
|
|
325
|
-
* держит кит, как `INSERT_ORDER` у Меню вставки.
|
|
326
|
-
*/
|
|
327
|
-
const MOVED_BEFORE: Readonly<Record<string, string>> = { blockquote: "codeBlock" };
|
|
328
|
-
|
|
329
268
|
/**
|
|
330
269
|
* Команды включённых инструментов по группам; пустые группы не возвращаются.
|
|
331
270
|
*
|
|
332
|
-
* Проекция списка описаний: строки
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
271
|
+
* Проекция списка описаний: строки кита — из `SHORTCUTS`, строки Инструментов —
|
|
272
|
+
* из их описаний (`toolDescriptor.ts`): клавиши
|
|
273
|
+
* Extensions — поле `shortcuts`, сочетания кнопок — поле кнопки. Место
|
|
274
|
+
* строки в группе — `SHORTCUT_ORDER`, а строки вне него — следом в порядке набора;
|
|
336
275
|
* кнопка без группы кита — в группу своего Инструмента после групп кита, в
|
|
337
276
|
* порядке списка (ADR-0058, п. 6.8).
|
|
338
277
|
*/
|
|
@@ -341,25 +280,18 @@ export function shortcutGroupsFor(
|
|
|
341
280
|
/** Локаль `UiProvider` — для подписи кнопки, заданной функцией от контекста. */
|
|
342
281
|
locale = "en-US"
|
|
343
282
|
): readonly ShortcutSection[] {
|
|
344
|
-
const described =
|
|
283
|
+
const described = tools.descriptors;
|
|
345
284
|
const moved = described.flatMap((descriptor) => descriptor.shortcuts ?? []);
|
|
346
|
-
const
|
|
347
|
-
SHORTCUTS.some((command) => command.id === MOVED_BEFORE[row.id]);
|
|
348
|
-
const commands = [
|
|
349
|
-
...SHORTCUTS.flatMap((command) => [
|
|
350
|
-
...moved.filter((row) => MOVED_BEFORE[row.id] === command.id),
|
|
351
|
-
command,
|
|
352
|
-
]),
|
|
353
|
-
...moved.filter((row) => !anchored(row)),
|
|
354
|
-
].filter((command) => enabled(command, tools));
|
|
285
|
+
const commands = [...SHORTCUTS, ...moved].filter((command) => enabled(command, tools));
|
|
355
286
|
const ownGroups: ShortcutSection[] = [];
|
|
356
287
|
for (const descriptor of described) {
|
|
357
288
|
const own: ShortcutRow[] = [];
|
|
358
289
|
for (const button of descriptor.buttons ?? []) {
|
|
359
|
-
|
|
290
|
+
const keys = button.shortcut ?? button.keys;
|
|
291
|
+
if (!keys) continue;
|
|
360
292
|
const row: ShortcutRow = {
|
|
361
293
|
id: button.id,
|
|
362
|
-
keys
|
|
294
|
+
keys,
|
|
363
295
|
label: (messages) => toolLabel(button.label, { locale, messages }),
|
|
364
296
|
};
|
|
365
297
|
// Набор уже отфильтрован: кнопка есть только у включённого Инструмента.
|
|
@@ -380,10 +312,17 @@ export function shortcutGroupsFor(
|
|
|
380
312
|
}
|
|
381
313
|
if (own.length > 0) ownGroups.push({ group: descriptor.name, commands: own });
|
|
382
314
|
}
|
|
315
|
+
// Сортировка устойчивая: строки вне `SHORTCUT_ORDER` сохраняют порядок набора.
|
|
316
|
+
const rank = (id: string) => {
|
|
317
|
+
const index = (SHORTCUT_ORDER as readonly string[]).indexOf(id);
|
|
318
|
+
return index === -1 ? SHORTCUT_ORDER.length : index;
|
|
319
|
+
};
|
|
383
320
|
return [
|
|
384
321
|
...SHORTCUT_GROUPS.map((group) => ({
|
|
385
322
|
group,
|
|
386
|
-
commands: commands
|
|
323
|
+
commands: commands
|
|
324
|
+
.filter((command) => command.group === group)
|
|
325
|
+
.sort((left, right) => rank(left.id) - rank(right.id)),
|
|
387
326
|
})),
|
|
388
327
|
...ownGroups,
|
|
389
328
|
].filter((entry) => entry.commands.length > 0);
|
|
@@ -19,9 +19,9 @@ import type { ToolLoader } from "./toolLoader.js";
|
|
|
19
19
|
набора и выгружается обратно в HTML — в документ, тоже инертный. Что Схема не
|
|
20
20
|
знает (теги, атрибуты, обработчики, `javascript:`), не доходит до страницы.
|
|
21
21
|
|
|
22
|
-
Схема — та, что получит движок, но без
|
|
22
|
+
Схема — та, что получит движок, но без Extensions, чьи загрузчики ещё
|
|
23
23
|
не отработали: их Блоки видны текстом, обёртку Схема снимает. Ленивый
|
|
24
|
-
встроенный (`codeBlock`, `table`) вместо
|
|
24
|
+
встроенный (`codeBlock`, `table`) вместо Extensions даёт
|
|
25
25
|
форму Блоков (`skeleton` описания) — его Блоки видны своей разметкой, и поле
|
|
26
26
|
не прыгает с приходом чанка. Шапка блока кода — та же, что у `RichTextView`
|
|
27
27
|
(`withCodeHeaders`): в Редакторе она есть, и без неё Скелет был бы ниже. Набор
|
|
@@ -37,6 +37,7 @@ const SCHEMA_ONLY: Omit<EditorExtensionOptions, "tools"> = {
|
|
|
37
37
|
placeholder: () => "",
|
|
38
38
|
limit: () => undefined,
|
|
39
39
|
taskCheckbox: (text) => text,
|
|
40
|
+
detailsToggle: (text) => text,
|
|
40
41
|
openPopover: quiet,
|
|
41
42
|
focusToolbar: no,
|
|
42
43
|
openBlockMenu: no,
|
|
@@ -83,7 +84,7 @@ function cleaned(html: string, tools: ToolList): string | null {
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
/**
|
|
86
|
-
* Документ Скелета: `html`, очищенный Схемой набора без
|
|
87
|
+
* Документ Скелета: `html`, очищенный Схемой набора без Extensions ещё не
|
|
87
88
|
* отработавших загрузчиков (`pending`). Только в браузере.
|
|
88
89
|
*
|
|
89
90
|
* Набор с ошибкой своих Инструментов Схемы не даёт (ошибка поля, ADR-0058,
|
|
@@ -70,9 +70,9 @@ export function keymapName(keys: readonly string[]): string {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
74
|
-
* записи и единственный его источник, поэтому клавишу вешает кит, а не
|
|
75
|
-
*
|
|
73
|
+
* Сочетания у кнопок описаний (ADR-0058, п. 5.7): сочетание — поле
|
|
74
|
+
* записи и единственный его источник, поэтому клавишу вешает кит, а не
|
|
75
|
+
* Extensions Инструмента. `run` выполняется, поповер открывается у выделения.
|
|
76
76
|
* Недоступная кнопка клавишу не берёт: она идёт дальше, в Документ.
|
|
77
77
|
*/
|
|
78
78
|
export const ToolButtons = Extension.create<ToolButtonsOptions>({
|
|
@@ -10,7 +10,7 @@ import { isConfiguredTool, mergeOptions } from "./toolOptions.js";
|
|
|
10
10
|
же формой `CustomTool` (ADR-0058): отдельного пути сборки у определения нет,
|
|
11
11
|
кит собирает из него обычное описание Инструмента (`describeDefinition`), и
|
|
12
12
|
все правила своего Инструмента — Префикс потребителя, уникальность имени,
|
|
13
|
-
проверки набора, загрузчик
|
|
13
|
+
проверки набора, загрузчик Extensions — действуют как были.
|
|
14
14
|
|
|
15
15
|
ИМЯ ФАЙЛА — НЕ `defineTool.ts`. Под этим именем сборка потребителя на Next.js
|
|
16
16
|
15.5 (`check:consumer`) теряла `RichTextEditor` из клиентского манифеста RSC:
|
|
@@ -107,14 +107,14 @@ export interface ToolDefinition<
|
|
|
107
107
|
* - `defaults` — полный набор Опций; тип Опций выводится из него, второй раз его
|
|
108
108
|
* объявлять не нужно.
|
|
109
109
|
* - `create(options)` отдаёт тело описания — ту же форму, что `CustomTool`, без
|
|
110
|
-
* имени:
|
|
110
|
+
* имени: Extensions, правила Схемы, UI-записи. Зовётся один раз на запись
|
|
111
111
|
* `tools` (определение само или объект, что вернул `tool(definition, options)`):
|
|
112
112
|
* кит запоминает результат, и Остров, замкнутый над Опциями, один и тот же на
|
|
113
113
|
* каждом рендере. Запись, созданная заново на каждом рендере экрана
|
|
114
114
|
* (`tools={[tool(mention, …)]}` в теле компонента), для кита новая — выносите
|
|
115
|
-
* `tools` из рендера. Загрузчик
|
|
115
|
+
* `tools` из рендера. Загрузчик Extensions стоит держать константой
|
|
116
116
|
* модуля: кэш загрузчика живёт на самой функции, а новая функция на каждый
|
|
117
|
-
* вызов `create` загружала бы
|
|
117
|
+
* вызов `create` загружала бы Extensions заново для каждой записи.
|
|
118
118
|
* - `state({ editor, options })` — Состояние для `useRichTextToolState(ref, name)`.
|
|
119
119
|
* Зовётся при каждой транзакции и при каждом чтении хука, поэтому должна быть
|
|
120
120
|
* быстрой и без побочных эффектов; вернуть — данные без DOM-узлов. Простые данные
|