@olddevs/ui 4.5.1 → 4.6.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 +26 -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/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 +68 -68
- 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 +11 -11
- package/docs/api/migration-notes.md +2 -2
- package/docs/api/utilities.en.md +6 -6
- package/docs/components/actions/split-button.en.md +9 -9
- package/docs/components/content/data-display.en.md +1 -1
- package/docs/components/content/layout-primitives.en.md +3 -3
- package/docs/components/content/rich-text-toc.en.md +1 -1
- package/docs/components/content/rich-text-view.en.md +23 -17
- package/docs/components/content/rich-text-view.md +17 -11
- package/docs/components/content/virtual-grid.en.md +2 -2
- package/docs/components/date-time/date-picker.en.md +1 -1
- package/docs/components/inputs/rich-text-editor.en.md +283 -230
- package/docs/components/inputs/rich-text-editor.md +139 -86
- package/docs/components/navigation/mega-menu.en.md +10 -10
- package/docs/components/overlays/menu.en.md +2 -2
- package/docs/components/overlays/shortcuts-help.en.md +1 -1
- package/docs/components/table/data-table.en.md +3 -3
- package/docs/components/table/filter-bar.en.md +1 -1
- package/docs/components/table/toolbar.en.md +1 -1
- 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 +193 -133
- package/docs/glossary.md +191 -132
- package/docs/icons.en.md +12 -9
- package/docs/icons.md +3 -0
- package/docs/palette.en.md +3 -3
- package/docs/theming.en.md +6 -6
- 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/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
package/docs/icons.en.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
entrypoint: "@olddevs/ui/icons"
|
|
3
3
|
source: src/icons.ts
|
|
4
4
|
status: stable
|
|
5
|
-
sourceHash:
|
|
5
|
+
sourceHash: 8b6aa04a1c0a
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Icons `@olddevs/ui/icons`
|
|
@@ -113,9 +113,10 @@ import { DeleteIcon, SearchIcon } from "@olddevs/ui/icons";
|
|
|
113
113
|
| Vertical "more": the Block menu | `MoreVerticalIcon` | `MoreIcon`, `DragHandleIcon` |
|
|
114
114
|
| Duplicate next to the original | `DuplicateIcon` | `CopyIcon` |
|
|
115
115
|
| Arrow up / down | `ArrowUpIcon`, `ArrowDownIcon` | `ChevronUpIcon`, `SortIcon` |
|
|
116
|
-
|
|
|
116
|
+
| A Column layout of the Document | `ColumnLayoutIcon` | `ColumnsIcon` |
|
|
117
117
|
| Wrapper: a group of Blocks | `WrapperIcon` | `ColumnLayoutIcon` |
|
|
118
118
|
| Remove the Wrapper, keep the Blocks | `UnwrapIcon` | `DeleteIcon` |
|
|
119
|
+
| Collapsible Block of the Editor | `DetailsIcon` | `ChevronDownIcon` |
|
|
119
120
|
|
|
120
121
|
## Subject topics
|
|
121
122
|
|
|
@@ -184,15 +185,15 @@ has no checkboxes, so that a list of records does not read as "done".
|
|
|
184
185
|
The only visible label on the Toolbar buttons is the icon; the button's name
|
|
185
186
|
comes from `aria-label`, and the keyboard shortcut is shown by a tooltip.
|
|
186
187
|
|
|
187
|
-
The
|
|
188
|
+
The Slash menu added `ParagraphIcon` (¶) — the "Turn into
|
|
188
189
|
paragraph" item. `HeadingIcon` does not fit it: that one is a heading in general, with no
|
|
189
|
-
level. The "+" button of the
|
|
190
|
+
level. The "+" button of the Slash menu reuses the existing `AddIcon`.
|
|
190
191
|
|
|
191
192
|
The Block type menu "¶" (under ADR-0049) added
|
|
192
193
|
`Heading1Icon`–`Heading4Icon` (a heading with the level digit) and `TextIcon` (the letter
|
|
193
194
|
"T", the "Text" item). `HeadingIcon` remains the icon of a heading without a level: the items of the
|
|
194
|
-
|
|
195
|
-
the "paragraph" pilcrow in the
|
|
195
|
+
Slash menu need it that way. `TextIcon` does not repeat `ParagraphIcon`: that one is
|
|
196
|
+
the "paragraph" pilcrow in the Slash menu, and this one is "Text" in the Block type menu. The "¶" button
|
|
196
197
|
on the Toolbar shows the icon of the current type: the icon of its menu item,
|
|
197
198
|
`CodeBlockIcon` in a code Block, or the pilcrow `ParagraphIcon` when there is no text
|
|
198
199
|
Block under the caret (an image is selected).
|
|
@@ -211,11 +212,13 @@ The Block handle added four names: `MoreVerticalIcon` — "⋮", the button of t
|
|
|
211
212
|
|
|
212
213
|
Emoji added `EmojiIcon` — a smiley face, the button of the emoji grid in the Toolbar. The name is by the meaning "emoji", not by the glyph: a face elsewhere would mean mood or rating, and that would be a different decision under ADR-0049.
|
|
213
214
|
|
|
214
|
-
|
|
215
|
+
Source mode added `SourceIcon` — a sheet with `</>` (`FileCode`), the "HTML" button of the Toolbar: the source code of the whole Document. `CodeBlockIcon` already means a code Block inside a Document, and `CodeIcon` the subject topic "development"; a third meaning is not attached to them (ADR-0049).
|
|
215
216
|
|
|
216
|
-
|
|
217
|
+
Column layout added `ColumnLayoutIcon` — two columns, the "Layout" item of the Slash menu. `ColumnsIcon` with three columns already means "choosing the columns of a data table", and a second meaning is not attached to it (ADR-0049): the Column layout has its own glyph.
|
|
217
218
|
|
|
218
|
-
Wrapper added the pair `WrapperIcon` and `UnwrapIcon` — lucide's `Group` and `Ungroup`: a frame with dashed corners around two Blocks and the same Blocks without a frame. The icons sit at the "Wrapper" item of the
|
|
219
|
+
Wrapper added the pair `WrapperIcon` and `UnwrapIcon` — lucide's `Group` and `Ungroup`: a frame with dashed corners around two Blocks and the same Blocks without a frame. The icons sit at the "Wrapper" item of the Slash menu and the "Remove Wrapper" item in the Block handle menu. This is not `ColumnLayoutIcon`: columns put Blocks side by side, while a Wrapper groups them without changing their order. `DeleteIcon` does not fit removal: only the container is deleted, not the content.
|
|
220
|
+
|
|
221
|
+
Collapsible block added `DetailsIcon` — lucide's `ListCollapse`: a list with collapse arrows, the "Collapsible block" item of the Slash menu. The dictionary had no fitting name: `ChevronDownIcon` is a step and nesting, `CollapseIcon` is collapsing a window, while here it is a whole Block with a title and hidden content. Removing the Block uses the already taken `UnwrapIcon` (ADR-0049).
|
|
219
222
|
|
|
220
223
|
The first iteration of the table made do with two icons for four directions
|
|
221
224
|
(`AddRowIcon`, `AddColumnIcon`) and an icon for the separate "Table
|
package/docs/icons.md
CHANGED
|
@@ -115,6 +115,7 @@ import { DeleteIcon, SearchIcon } from "@olddevs/ui/icons";
|
|
|
115
115
|
| Раскладка Документа колонками | `ColumnLayoutIcon` | `ColumnsIcon` |
|
|
116
116
|
| Обёртка: группа Блоков | `WrapperIcon` | `ColumnLayoutIcon` |
|
|
117
117
|
| Снять Обёртку, Блоки остаются | `UnwrapIcon` | `DeleteIcon` |
|
|
118
|
+
| Сворачиваемый Блок Редактора | `DetailsIcon` | `ChevronDownIcon` |
|
|
118
119
|
|
|
119
120
|
## Предметные темы
|
|
120
121
|
|
|
@@ -216,6 +217,8 @@ HTML-режим добавил `SourceIcon` — лист с `</>` (`FileCode`),
|
|
|
216
217
|
|
|
217
218
|
Обёртка добавила пару `WrapperIcon` и `UnwrapIcon` — `Group` и `Ungroup` у lucide: рамка пунктирными углами вокруг двух Блоков и те же Блоки без рамки. Иконки стоят у пункта «Обёртка» Меню вставки и пункта «Снять обёртку» в меню Ручки Блока. Это не `ColumnLayoutIcon`: колонки ставят Блоки рядом, а Обёртка группирует их, не меняя порядка. Для снятия не подходит `DeleteIcon`: удаляется только контейнер, а не содержимое.
|
|
218
219
|
|
|
220
|
+
Сворачиваемый Блок добавил `DetailsIcon` — `ListCollapse` у lucide: список со стрелками сворачивания, пункт «Сворачиваемый блок» Меню вставки. Подходящего имени в словаре не было: `ChevronDownIcon` — шаг и вложенность, `CollapseIcon` — свернуть окно, а здесь Блок целиком с заголовком и спрятанным содержимым. Снять Блок — уже занятый `UnwrapIcon` (ADR-0049).
|
|
221
|
+
|
|
219
222
|
Первый срез таблицы обходился двумя рисунками на четыре направления
|
|
220
223
|
(`AddRowIcon`, `AddColumnIcon`) и иконкой отдельной кнопки «Действия с
|
|
221
224
|
таблицей» (`TableEditIcon`). С меню «Таблица» кнопка ушла, а направление
|
package/docs/palette.en.md
CHANGED
|
@@ -61,7 +61,7 @@ blue tint of `cloud`: the background of the inverse surface in the light theme.
|
|
|
61
61
|
|
|
62
62
|
### Tones
|
|
63
63
|
|
|
64
|
-
The "Used by" column is the only way to see why a
|
|
64
|
+
The "Used by" column is the only way to see why a color scale has exactly this many
|
|
65
65
|
steps: each one exists for a specific role in a specific theme, and there are no spare ones.
|
|
66
66
|
|
|
67
67
|
| Primitive | Value | Used by |
|
|
@@ -155,7 +155,7 @@ text, borders, shadows and `--topbar-bg`, and takes tones and accent from the da
|
|
|
155
155
|
### Inverse surface
|
|
156
156
|
|
|
157
157
|
A pill that has to differ from everything around it by sign, not by step
|
|
158
|
-
of brightness: the Editor's
|
|
158
|
+
of brightness: the Editor's Bubble menu (`toolbar="bubble"`), which sits directly on the
|
|
159
159
|
Document. Light in the dark themes, dark in the light one. It has the utilities
|
|
160
160
|
`bg-surface-inverse`, `bg-surface-inverse-hover`, `bg-surface-inverse-pressed`,
|
|
161
161
|
`text-text-on-inverse`, `outline-accent-on-inverse`.
|
|
@@ -366,7 +366,7 @@ VS Code and macOS; 3:1 is not the goal, because in a dark theme such a fill no l
|
|
|
366
366
|
holds 4.5:1 for light text on top of it. `--selection-light` is the light variant in
|
|
367
367
|
any app theme: the Editor's Paper (`surface="paper"`) takes it.
|
|
368
368
|
`--selection-dark` is the dark mirror in any theme: the Editor's
|
|
369
|
-
|
|
369
|
+
Source mode field takes it, dark in the light theme too; the dark themes assign
|
|
370
370
|
it to `--selection`.
|
|
371
371
|
|
|
372
372
|
The `teal` brand primitives are declared inside its own block and are not part of the shared
|
package/docs/theming.en.md
CHANGED
|
@@ -25,11 +25,11 @@ it writes the class `bg-bg-0`, backed by the `@theme` bridge.
|
|
|
25
25
|
|
|
26
26
|
### Layer 1 — primitives
|
|
27
27
|
|
|
28
|
-
Three neutral
|
|
29
|
-
`navy` for dim), and seven tone
|
|
28
|
+
Three neutral scales, one per theme (`slate` for dark, `cloud` for light,
|
|
29
|
+
`navy` for dim), and seven tone scales. Within a scale the step number increases with lightness:
|
|
30
30
|
1 is the darkest, 12 the lightest.
|
|
31
31
|
|
|
32
|
-
Three
|
|
32
|
+
Three scales instead of one is not duplication: each theme's neutrals are tuned
|
|
33
33
|
by hand for its own background, and reducing them to one scale would mean recoloring two
|
|
34
34
|
themes out of three.
|
|
35
35
|
|
|
@@ -58,7 +58,7 @@ cover both; details and numbers are in the comments of `styles.css`.
|
|
|
58
58
|
|
|
59
59
|
**Inverse surface** is a separate group of roles for a pill
|
|
60
60
|
that sits directly on the Document and has to differ from it by polarity, not by a single
|
|
61
|
-
step: the Editor's
|
|
61
|
+
step: the Editor's Bubble menu. `--surface-inverse` (the background),
|
|
62
62
|
`--surface-inverse-hover` and `--surface-inverse-pressed` (hover and press),
|
|
63
63
|
`--text-on-inverse` (text and icons) are light in `dark` and `dim`, and dark in
|
|
64
64
|
`light`. The focus outline on it is `--accent-on-inverse`: it is the `--accent-strong`
|
|
@@ -71,7 +71,7 @@ a compatibility layer. Components get their colors through them, via Tailwind cl
|
|
|
71
71
|
|
|
72
72
|
### Layer 3 — component tokens
|
|
73
73
|
|
|
74
|
-
The list is **closed**. A component token is added when a family has a real
|
|
74
|
+
The list is **closed**. A component token is added when a component family has a real
|
|
75
75
|
reason to differ from the semantics, not "just in case"; a token with no reader is
|
|
76
76
|
not added at all.
|
|
77
77
|
|
|
@@ -346,7 +346,7 @@ The order is exactly this, checked on `teal`, which ships in the package as a sa
|
|
|
346
346
|
|
|
347
347
|
**3. Check the light theme separately.** `--accent-strong` is read on a background,
|
|
348
348
|
and the light theme almost certainly needs its own step; `--accent-on-inverse` is
|
|
349
|
-
the opposite, light: the
|
|
349
|
+
the opposite, light: the Bubble menu pill is dark in the light theme. `--selection`
|
|
350
350
|
returns to the light variant only here: the brand block comes after the light theme
|
|
351
351
|
in the file and would override it with the dark one.
|
|
352
352
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olddevs/ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.1",
|
|
4
4
|
"description": "Olddevs UI — design system: tokens, themes and accessible UI primitives",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"@tiptap/core": "^3.31.4",
|
|
118
118
|
"@tiptap/extension-blockquote": "^3.31.4",
|
|
119
119
|
"@tiptap/extension-code-block-lowlight": "^3.31.4",
|
|
120
|
+
"@tiptap/extension-details": "^3.31.4",
|
|
120
121
|
"@tiptap/extension-highlight": "^3.31.4",
|
|
121
122
|
"@tiptap/extension-horizontal-rule": "^3.31.4",
|
|
122
123
|
"@tiptap/extension-link": "^3.31.4",
|
|
@@ -157,7 +157,7 @@ export interface RichTextEditorProps {
|
|
|
157
157
|
* Редактор готов: движок создан, методы Хэндла (`ref`) уже действуют — например,
|
|
158
158
|
* вставить шаблон. Без аргументов, один раз за монтаж, в том числе при
|
|
159
159
|
* `readOnly` и `disabled`; перерисовка и смена колбэка повторного вызова не
|
|
160
|
-
* дают. Ждёт загрузчики
|
|
160
|
+
* дают. Ждёт загрузчики Extensions своих Инструментов. Серверный
|
|
161
161
|
* рендер, ошибка набора `tools` и упавший загрузчик (движка нет) его не вызывают.
|
|
162
162
|
*/
|
|
163
163
|
onReady?: () => void;
|
|
@@ -261,7 +261,7 @@ export interface RichTextEditorProps {
|
|
|
261
261
|
* включает Инструмент и без имени, а имя из пресета уступает ей; две записи
|
|
262
262
|
* `tool()` с одним именем — ошибка поля. Неизвестное имя отбрасывается
|
|
263
263
|
* молча; описание с ошибкой (имя без Префикса потребителя, совпадение имён,
|
|
264
|
-
*
|
|
264
|
+
* Extensions мимо правил Схемы) — ошибка поля: движок не создаётся,
|
|
265
265
|
* значение формы остаётся входящим, причина — в консоли разработчика.
|
|
266
266
|
*
|
|
267
267
|
* `preset` и `tools`, а с ними и Опции Инструментов, читаются при создании
|
|
@@ -522,17 +522,17 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
|
|
|
522
522
|
Набор инструментов замораживается при монтаже: из него собрана Схема, а
|
|
523
523
|
Схему у живого движка не поменять. Панель читает тот же замороженный
|
|
524
524
|
набор — иначе новый `tools` показал бы кнопку, которой Схема не знает.
|
|
525
|
-
Набор — список описаний Инструментов (`features/builtins.ts`),
|
|
525
|
+
Набор — список описаний Инструментов (`features/builtins.ts`), поверхности
|
|
526
526
|
читают его проекцию.
|
|
527
527
|
*/
|
|
528
528
|
const [enabledTools] = useState(() => expandTools(preset, tools));
|
|
529
529
|
/*
|
|
530
|
-
Загрузчики
|
|
530
|
+
Загрузчики Extensions (ADR-0058, п. 11.3–11.6). Загрузка стартует
|
|
531
531
|
в рендере, а не в эффекте: с первого рендера в браузере, ещё до монтажа;
|
|
532
532
|
на сервере — никогда. Промис кэширован на загрузчике (`toolLoader.ts`):
|
|
533
533
|
повторный рендер и второй Редактор его не зовут. Набор движка собирается,
|
|
534
534
|
только когда отработали все (`ready`): Схема фиксируется при создании, и
|
|
535
|
-
Блоки из `value` без
|
|
535
|
+
Блоки из `value` без Extensions потерялись бы при разборе.
|
|
536
536
|
*/
|
|
537
537
|
const loaders = enabledTools.descriptors.flatMap((descriptor) => descriptor.load ?? []);
|
|
538
538
|
const loads = loaders.map((loader) =>
|
|
@@ -603,6 +603,8 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
|
|
|
603
603
|
placeholderRef.current = placeholderText;
|
|
604
604
|
const taskCheckboxRef = useRef(messages.editor.taskCheckbox);
|
|
605
605
|
taskCheckboxRef.current = messages.editor.taskCheckbox;
|
|
606
|
+
const detailsToggleRef = useRef(messages.editor.detailsToggle);
|
|
607
|
+
detailsToggleRef.current = messages.editor.detailsToggle;
|
|
606
608
|
// Загрузчик и строки картинки — тоже через ref: расширение их читает в
|
|
607
609
|
// момент вставки файла и при перерисовке подписи, а не при создании движка.
|
|
608
610
|
const uploadRef = useRef(onUploadImage);
|
|
@@ -887,6 +889,7 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
|
|
|
887
889
|
placeholder: () => placeholderRef.current,
|
|
888
890
|
limit: () => limitRef.current,
|
|
889
891
|
taskCheckbox: (text) => taskCheckboxRef.current({ text }),
|
|
892
|
+
detailsToggle: (text) => detailsToggleRef.current({ text }),
|
|
890
893
|
slash: slashBridge,
|
|
891
894
|
triggers: triggerBindings,
|
|
892
895
|
openPopover: (request) => setToolPopover({ request, open: true }),
|
|
@@ -917,7 +920,7 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
|
|
|
917
920
|
`value`. Движок тогда собирается из запасного набора и пустым, а наружу
|
|
918
921
|
не выходит (`editor` ниже — `null`, как до монтажа): Хэндл тихий,
|
|
919
922
|
скрытое поле несёт входящее значение, `onChange` молчит. Набор с
|
|
920
|
-
загрузчиками проверяется, когда они отработали:
|
|
923
|
+
загрузчиками проверяется, когда они отработали: Extensions — их итог.
|
|
921
924
|
*/
|
|
922
925
|
const toolsError = useMemo(
|
|
923
926
|
() => extensions && customToolsError(enabledTools, extensions),
|
|
@@ -16,7 +16,7 @@ import { MARKDOWN_FALLBACK, warnNoMarkdown } from "./customMarkdown.js";
|
|
|
16
16
|
Текст атома (ADR-0058, раздел 4). Одно правило для встроенных и
|
|
17
17
|
своих атомов, и всё, что выдаёт текст Документа, читает его отсюда:
|
|
18
18
|
|
|
19
|
-
- Текст атома даёт `renderText` из
|
|
19
|
+
- Текст атома даёт `renderText` из Extensions. Листовой атом без него —
|
|
20
20
|
пустая строка, атом с содержимым (картинка с подписью) — текст своих детей;
|
|
21
21
|
- вес атома в `maxLength` — длина этого текста (`countCharacters`);
|
|
22
22
|
- `getText`, `getSelectedText`, копирование текстом и Markdown отдают тот же
|
|
@@ -90,7 +90,7 @@ export function atomText(node: ProseMirrorNode): string {
|
|
|
90
90
|
*/
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
|
-
* Узлы по выгрузке в Markdown: `true` —
|
|
93
|
+
* Узлы по выгрузке в Markdown: `true` — Extensions умеют сами, строка —
|
|
94
94
|
* атом своего Инструмента без правил (имя Инструмента — для предупреждения).
|
|
95
95
|
*/
|
|
96
96
|
function markdownHandled(editor: Editor): Map<string, true | string> {
|
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import type { ChainedCommands } from "@tiptap/core";
|
|
4
3
|
import type { Node as PmNode } from "@tiptap/pm/model";
|
|
5
4
|
import type { EditorState } from "@tiptap/pm/state";
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
Heading1Icon,
|
|
9
|
-
Heading2Icon,
|
|
10
|
-
Heading3Icon,
|
|
11
|
-
Heading4Icon,
|
|
12
|
-
ListIcon,
|
|
13
|
-
OrderedListIcon,
|
|
14
|
-
TaskListIcon,
|
|
15
|
-
TextIcon,
|
|
16
|
-
type IconProps,
|
|
17
|
-
} from "../../icons.js";
|
|
5
|
+
import { TextIcon } from "../../icons.js";
|
|
18
6
|
import type { PrefixedName } from "./customTool.js";
|
|
19
7
|
import type { InsertItem } from "./insertItems.js";
|
|
20
8
|
import { shortcutKeys } from "./shortcuts.js";
|
|
@@ -30,8 +18,8 @@ import type { Tool } from "./tools.js";
|
|
|
30
18
|
* заново — одной транзакцией, на одну отмену. Своего пути смены типа у меню
|
|
31
19
|
* нет: два пути разошлись бы на первом же списке внутри цитаты.
|
|
32
20
|
*
|
|
33
|
-
*
|
|
34
|
-
* другие слова и иконки: «Текст» с иконкой `T`, а не
|
|
21
|
+
* Пункты «¶» — поле описания `blockTypes`, а не выборка из `insertItems`,
|
|
22
|
+
* потому что у меню «¶» могут быть другие слова и иконки: «Текст» с иконкой `T`, а не
|
|
35
23
|
* «Абзац» с пилкроу, и уровень заголовка на иконке. Блока кода в нём нет — у
|
|
36
24
|
* него своя кнопка Панели.
|
|
37
25
|
*/
|
|
@@ -61,70 +49,24 @@ export function turnIntoTypes(
|
|
|
61
49
|
.map((item) => ({ ...item, section: "turnInto", tool, keys: item.keys ?? [] }));
|
|
62
50
|
}
|
|
63
51
|
|
|
64
|
-
const heading = (level: 1 | 2 | 3 | 4, icon: ComponentType<IconProps>): BlockTypeItem => ({
|
|
65
|
-
id: `heading${level}`,
|
|
66
|
-
section: "turnInto",
|
|
67
|
-
tool: "heading",
|
|
68
|
-
alsoTool: level === 1 ? "heading1" : undefined,
|
|
69
|
-
label: (m) => m.heading({ level }),
|
|
70
|
-
icon,
|
|
71
|
-
keys: shortcutKeys(`h${level}`),
|
|
72
|
-
run: (chain: ChainedCommands) => chain.setHeading({ level }),
|
|
73
|
-
});
|
|
74
|
-
|
|
75
52
|
/**
|
|
76
|
-
*
|
|
77
|
-
* (`shortcuts.ts`)
|
|
78
|
-
* вешают их расширения движка, и подпись обязана совпадать с ними.
|
|
53
|
+
* «Текст» — пункт кита, а не Инструмента: абзац есть в любом наборе. Сочетание —
|
|
54
|
+
* подпись из общей таблицы (`shortcuts.ts`): вешает его расширение движка.
|
|
79
55
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
},
|
|
90
|
-
heading(1, Heading1Icon),
|
|
91
|
-
heading(2, Heading2Icon),
|
|
92
|
-
heading(3, Heading3Icon),
|
|
93
|
-
heading(4, Heading4Icon),
|
|
94
|
-
{
|
|
95
|
-
id: "bulletList",
|
|
96
|
-
section: "turnInto",
|
|
97
|
-
tool: "bulletList",
|
|
98
|
-
label: (m) => m.bulletList,
|
|
99
|
-
icon: ListIcon,
|
|
100
|
-
keys: shortcutKeys("bulletList"),
|
|
101
|
-
run: (chain) => chain.toggleBulletList(),
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: "orderedList",
|
|
105
|
-
section: "turnInto",
|
|
106
|
-
tool: "orderedList",
|
|
107
|
-
label: (m) => m.orderedList,
|
|
108
|
-
icon: OrderedListIcon,
|
|
109
|
-
keys: shortcutKeys("orderedList"),
|
|
110
|
-
run: (chain) => chain.toggleOrderedList(),
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
id: "taskList",
|
|
114
|
-
section: "turnInto",
|
|
115
|
-
tool: "taskList",
|
|
116
|
-
label: (m) => m.taskList,
|
|
117
|
-
icon: TaskListIcon,
|
|
118
|
-
keys: shortcutKeys("taskList"),
|
|
119
|
-
run: (chain) => chain.toggleTaskList(),
|
|
120
|
-
},
|
|
121
|
-
];
|
|
56
|
+
const TEXT_ITEM: BlockTypeItem = {
|
|
57
|
+
id: "text",
|
|
58
|
+
section: "turnInto",
|
|
59
|
+
tool: null,
|
|
60
|
+
label: (m) => m.textBlock,
|
|
61
|
+
icon: TextIcon,
|
|
62
|
+
keys: shortcutKeys("paragraph"),
|
|
63
|
+
run: (chain) => chain.setParagraph(),
|
|
64
|
+
};
|
|
122
65
|
|
|
123
66
|
/**
|
|
124
67
|
* Место встроенных Инструментов в «¶». «Текст» стоит первым всегда: абзац —
|
|
125
|
-
* не Инструмент.
|
|
126
|
-
*
|
|
127
|
-
* остаётся здесь.
|
|
68
|
+
* не Инструмент. Пункты живут в описаниях, а место на поверхности — привилегия
|
|
69
|
+
* кита.
|
|
128
70
|
*/
|
|
129
71
|
const BLOCK_TYPE_ORDER: readonly Tool[] = [
|
|
130
72
|
"heading",
|
|
@@ -135,18 +77,12 @@ const BLOCK_TYPE_ORDER: readonly Tool[] = [
|
|
|
135
77
|
];
|
|
136
78
|
|
|
137
79
|
/**
|
|
138
|
-
* Пункты «¶»
|
|
139
|
-
* из описания (`blockTypes`), у остальных — из `BLOCK_TYPE_ITEMS`.
|
|
80
|
+
* Пункты «¶» набора: «Текст» и проекция списка описаний (`blockTypes`).
|
|
140
81
|
*/
|
|
141
82
|
function blockTypeItemsOf(tools: ToolList): readonly BlockTypeItem[] {
|
|
142
83
|
return [
|
|
143
|
-
|
|
144
|
-
...projectRecords(
|
|
145
|
-
tools,
|
|
146
|
-
BLOCK_TYPE_ORDER,
|
|
147
|
-
(tool) => BLOCK_TYPE_ITEMS.filter((item) => item.tool === tool),
|
|
148
|
-
(descriptor) => descriptor.blockTypes
|
|
149
|
-
),
|
|
84
|
+
TEXT_ITEM,
|
|
85
|
+
...projectRecords(tools, BLOCK_TYPE_ORDER, (descriptor) => descriptor.blockTypes),
|
|
150
86
|
].filter((item) => item.alsoTool === undefined || tools.has(item.alsoTool));
|
|
151
87
|
}
|
|
152
88
|
|
|
@@ -24,8 +24,9 @@ export { WRAPPER_NODE };
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Узлы, внутри которых контейнерного Блока нет ни одного: Обёртка, цитата,
|
|
27
|
-
* пункты
|
|
28
|
-
*
|
|
27
|
+
* пункты списков, ячейки таблицы и содержимое сворачиваемого Блока
|
|
28
|
+
* (`details.ts`). Колонки здесь нет — Обёртку она принимает; Раскладка
|
|
29
|
+
* добавляет её своим аргументом.
|
|
29
30
|
*/
|
|
30
31
|
const CONTAINER_FREE_NODES = [
|
|
31
32
|
WRAPPER_NODE,
|
|
@@ -34,6 +35,7 @@ const CONTAINER_FREE_NODES = [
|
|
|
34
35
|
"taskItem",
|
|
35
36
|
"tableCell",
|
|
36
37
|
"tableHeader",
|
|
38
|
+
"detailsContent",
|
|
37
39
|
];
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -12,7 +12,7 @@ import { devWarn } from "../../lib/dev-warn.js";
|
|
|
12
12
|
/*
|
|
13
13
|
Markdown своего Инструмента по умолчанию (ADR-0058, п. 3.1).
|
|
14
14
|
|
|
15
|
-
Свои правила Markdown — в
|
|
15
|
+
Свои правила Markdown — в Extensions: `renderMarkdown` и токенайзер
|
|
16
16
|
Tiptap, отдельного поля в описании нет. Без них `@tiptap/markdown` молча
|
|
17
17
|
выгрузил бы узел пустой строкой — вместе со всем текстом внутри. Поэтому
|
|
18
18
|
Node и Mark без `renderMarkdown` кит дописывает сам: Блок выгружается своим
|
|
@@ -31,7 +31,7 @@ export const MARKDOWN_FALLBACK = "kitMarkdownFallback";
|
|
|
31
31
|
/** Предупреждение о Markdown по умолчанию — одно на Инструмент (`devWarn` помнит текст). */
|
|
32
32
|
export function warnNoMarkdown(tool: string): void {
|
|
33
33
|
devWarn(
|
|
34
|
-
`custom tool "${tool}" has no Markdown rules (renderMarkdown in its
|
|
34
|
+
`custom tool "${tool}" has no Markdown rules (renderMarkdown in its Extensions): ` +
|
|
35
35
|
"getMarkdown() writes its blocks as their content and its atoms as their text"
|
|
36
36
|
);
|
|
37
37
|
}
|
|
@@ -67,7 +67,7 @@ export interface CustomBlock {
|
|
|
67
67
|
/**
|
|
68
68
|
* Остров Блока в `RichTextView` — клиентский компонент из модуля с
|
|
69
69
|
* директивой `"use client"` (ADR-0058, п. 3.3). Без него Блок в Просмотре —
|
|
70
|
-
* очищенный HTML. Редактор поле не читает: его вид
|
|
70
|
+
* очищенный HTML. Редактор поле не читает: его вид задают Extensions.
|
|
71
71
|
*
|
|
72
72
|
* Только компонент из модуля с директивой: серверный компонент и функция-
|
|
73
73
|
* загрузчик через границу RSC не проходят — сервер получает ссылку на
|
|
@@ -103,7 +103,7 @@ export interface CustomMark {
|
|
|
103
103
|
* встроенных (`ToolDescriptor`, ADR-0058, п. 10). Передаётся в `tools`
|
|
104
104
|
* вперемешку с именами Инструментов кита.
|
|
105
105
|
*
|
|
106
|
-
* Обязательное — имя,
|
|
106
|
+
* Обязательное — имя, Extensions и правила Схемы для каждого Блока и
|
|
107
107
|
* Метки, которые она определяет. Остальное — по умолчанию (ADR-0058, п. 1.6):
|
|
108
108
|
* обычный Блок без Признаков, без UI-записей.
|
|
109
109
|
*/
|
|
@@ -111,8 +111,8 @@ export interface CustomTool {
|
|
|
111
111
|
/** Имя с Префиксом потребителя, уникальное в `tools`. */
|
|
112
112
|
name: PrefixedName;
|
|
113
113
|
/**
|
|
114
|
-
*
|
|
115
|
-
* ProseMirror, React-вид узла, `renderText` атома.
|
|
114
|
+
* Extensions — расширения Tiptap: Node, Mark, Extension, плагины
|
|
115
|
+
* ProseMirror, React-вид узла, `renderText` атома. Их контракт следует
|
|
116
116
|
* мажору Tiptap. Node и Mark стоят на верхнем уровне массива: группу,
|
|
117
117
|
* разбор HTML и свои атрибуты им ставит кит по правилам.
|
|
118
118
|
*
|
|
@@ -123,9 +123,9 @@ export interface CustomTool {
|
|
|
123
123
|
* того поле показывает Скелет; промис кэшируется на функции загрузчика.
|
|
124
124
|
*/
|
|
125
125
|
engine: Extensions | (() => Promise<Extensions>);
|
|
126
|
-
/** Правила Схемы для каждого Node
|
|
126
|
+
/** Правила Схемы для каждого Node из Extensions — по имени узла. */
|
|
127
127
|
blocks?: Readonly<Record<PrefixedName, CustomBlock>>;
|
|
128
|
-
/** Правила Схемы для каждой Mark
|
|
128
|
+
/** Правила Схемы для каждой Mark из Extensions — по имени Метки. */
|
|
129
129
|
marks?: Readonly<Record<PrefixedName, CustomMark>>;
|
|
130
130
|
|
|
131
131
|
/* UI-записи (ADR-0058, п. 5 и 6): кнопки, пункты вставки и Действия над Блоком. */
|
|
@@ -43,13 +43,13 @@ import { loaded } from "./toolLoader.js";
|
|
|
43
43
|
Свой Инструмент в движке (ADR-0058, разделы 1 и 2): из
|
|
44
44
|
публичного описания — внутреннее, и проверка набора при сборке.
|
|
45
45
|
|
|
46
|
-
ПРАВИЛА СХЕМЫ — ЕДИНСТВЕННЫЙ ИСТОЧНИК HTML. Node и Mark
|
|
46
|
+
ПРАВИЛА СХЕМЫ — ЕДИНСТВЕННЫЙ ИСТОЧНИК HTML. Node и Mark из Extensions кит
|
|
47
47
|
дописывает сам: группу и строчность — по виду Блока, разбор HTML — только
|
|
48
48
|
`div|span[data-block="<имя>"]` и `span[data-mark="<имя>"]`, свои атрибуты —
|
|
49
49
|
`data-<имя>` со значением по виду из правил, Признаки Блока — в spec узла.
|
|
50
50
|
Своё правило разбора чужого Блока поэтому не займёт тег кита, а значение вне
|
|
51
51
|
правил не войдёт в Документ ни из `value`, ни из вставки: проверяет код кита,
|
|
52
|
-
и ослабить проверку
|
|
52
|
+
и ослабить проверку через Extensions нельзя. Поведение — содержимое,
|
|
53
53
|
`atom`, React-вид, `renderText`, команды — остаётся за потребителем.
|
|
54
54
|
*/
|
|
55
55
|
|
|
@@ -67,7 +67,7 @@ function allowed(rule: CustomAttribute, value: unknown): string | null {
|
|
|
67
67
|
return isAllowedAttributeValue(rule, text) ? text : null;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
/** Node или Mark
|
|
70
|
+
/** Node или Mark из Extensions, дописанный по своим правилам Схемы. */
|
|
71
71
|
function bindRules(extension: AnyExtension, tool: CustomTool): AnyExtension {
|
|
72
72
|
const { name } = extension;
|
|
73
73
|
const block = extension.type === "node" ? blocksOf(tool)[name] : undefined;
|
|
@@ -80,7 +80,7 @@ function bindRules(extension: AnyExtension, tool: CustomTool): AnyExtension {
|
|
|
80
80
|
const config = {
|
|
81
81
|
...markdownFallback(extension, tool.name),
|
|
82
82
|
parseHTML: () => [{ tag: selector }],
|
|
83
|
-
// Свой `renderHTML` остаётся у
|
|
83
|
+
// Свой `renderHTML` остаётся у Extensions (текст внутри атома);
|
|
84
84
|
// соглашение с ним сверяет `customToolsError`.
|
|
85
85
|
...(getExtensionField(extension, "renderHTML") === undefined && {
|
|
86
86
|
renderHTML: ({ node, HTMLAttributes }: { node?: PmNode; HTMLAttributes: object }) =>
|
|
@@ -211,7 +211,7 @@ function uiRecords(tool: CustomTool) {
|
|
|
211
211
|
return { insertItems, blockTypes, blockActions, textCards };
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
/**
|
|
214
|
+
/** Extensions: массив сразу или то, что отдал загрузчик; не массив — пустой массив. */
|
|
215
215
|
function engineOf(tool: CustomTool): Extensions {
|
|
216
216
|
const engine = typeof tool.engine === "function" ? loaded(tool.engine) : tool.engine;
|
|
217
217
|
return Array.isArray(engine) ? engine : [];
|
|
@@ -222,7 +222,7 @@ export function describeCustomTool(tool: CustomTool): ToolDescriptor {
|
|
|
222
222
|
return {
|
|
223
223
|
name: tool.name,
|
|
224
224
|
custom: tool,
|
|
225
|
-
// Загрузчик: правила Схемы ложатся на
|
|
225
|
+
// Загрузчик: правила Схемы ложатся на Extensions, когда они пришли (`engineOf`).
|
|
226
226
|
load: typeof tool.engine === "function" ? tool.engine : undefined,
|
|
227
227
|
engine: () => engineOf(tool).map((extension) => bindRules(extension, tool)),
|
|
228
228
|
...uiRecords(tool),
|
|
@@ -330,8 +330,8 @@ export interface CustomToolsError {
|
|
|
330
330
|
/**
|
|
331
331
|
* Ошибка сборки набора Инструментов или `null` (ADR-0058, п. 1.5, 2.4).
|
|
332
332
|
*
|
|
333
|
-
* Имя без Префикса потребителя, совпадение имён, Node или Mark
|
|
334
|
-
*
|
|
333
|
+
* Имя без Префикса потребителя, совпадение имён, Node или Mark из
|
|
334
|
+
* Extensions без правил Схемы (и правило без них), атрибут, которого нет в
|
|
335
335
|
* правилах, HTML мимо соглашения, Схема, которую движок не собрал, — всё это
|
|
336
336
|
* потеря данных на сервере или в самом Редакторе, и автор должен увидеть её
|
|
337
337
|
* до первого сохранения. `extensions` — полный набор движка, свои уже в нём.
|
|
@@ -442,7 +442,7 @@ export function customToolsError(tools: ToolList, extensions: Extensions): Custo
|
|
|
442
442
|
if (extra) return fail(`has attribute "${extra}" with no rule`);
|
|
443
443
|
/*
|
|
444
444
|
HTML — по соглашению: `toDOM` экземпляра по умолчанию даёт тег и
|
|
445
|
-
метку с именем. Свой `renderHTML`
|
|
445
|
+
метку с именем. Свой `renderHTML` в Extensions мог уйти от них, и
|
|
446
446
|
тогда Блок не прочитался бы обратно из собственного `getHTML()`.
|
|
447
447
|
*/
|
|
448
448
|
const { tag, marker } = customElement(
|