@shelamkoff/rector 1.0.0 → 1.0.2
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/README.md +25 -23
- package/dist/core/clipboard/Clipboard.d.ts +2 -0
- package/dist/core/clipboard/Clipboard.js +52 -24
- package/dist/core/index.js +195 -194
- package/dist/core/locale/en.d.ts +1 -0
- package/dist/core/locale/en.js +1 -0
- package/dist/core/locale/ru.d.ts +1 -0
- package/dist/core/locale/ru.js +1 -0
- package/dist/core/themes/light.css +1 -1
- package/dist/core/themes/variables.css +72 -10
- package/dist/inline-plugins/mention/index.js +1 -2
- package/dist/locale/en.d.ts +41 -0
- package/dist/locale/ru.d.ts +41 -0
- package/dist/plugins/attaches/attaches.css +16 -14
- package/dist/plugins/attaches/index.js +997 -921
- package/dist/plugins/attaches/locale/en.d.ts +9 -0
- package/dist/plugins/attaches/locale/en.js +11 -2
- package/dist/plugins/attaches/locale/ru.d.ts +9 -0
- package/dist/plugins/attaches/locale/ru.js +11 -2
- package/dist/plugins/carousel/carousel.css +213 -49
- package/dist/plugins/carousel/index.js +918 -859
- package/dist/plugins/carousel/locale/en.d.ts +15 -0
- package/dist/plugins/carousel/locale/en.js +18 -3
- package/dist/plugins/carousel/locale/ru.d.ts +15 -0
- package/dist/plugins/carousel/locale/ru.js +18 -3
- package/dist/plugins/checklist/index.js +1 -2
- package/dist/plugins/code/index.js +1 -2
- package/dist/plugins/columns/index.js +1 -2
- package/dist/plugins/delimiter/index.js +1 -2
- package/dist/plugins/embed/index.js +1 -2
- package/dist/plugins/gallery/gallery.css +6 -1
- package/dist/plugins/gallery/index.js +375 -355
- package/dist/plugins/gallery/locale/en.d.ts +8 -0
- package/dist/plugins/gallery/locale/en.js +11 -3
- package/dist/plugins/gallery/locale/ru.d.ts +8 -0
- package/dist/plugins/gallery/locale/ru.js +11 -3
- package/dist/plugins/gallery/view-empty.d.ts +2 -0
- package/dist/plugins/gallery/view-empty.js +21 -15
- package/dist/plugins/gallery/view-filled.d.ts +2 -2
- package/dist/plugins/gallery/view-filled.js +61 -56
- package/dist/plugins/heading/index.js +1 -2
- package/dist/plugins/image/image.css +7 -2
- package/dist/plugins/image/index.js +365 -346
- package/dist/plugins/image/locale/en.d.ts +8 -0
- package/dist/plugins/image/locale/en.js +11 -3
- package/dist/plugins/image/locale/ru.d.ts +8 -0
- package/dist/plugins/image/locale/ru.js +11 -3
- package/dist/plugins/image/view-empty.d.ts +2 -0
- package/dist/plugins/image/view-empty.js +21 -15
- package/dist/plugins/image/view-filled.d.ts +2 -2
- package/dist/plugins/image/view-filled.js +77 -72
- package/dist/plugins/link-preview/index.js +1 -2
- package/dist/plugins/list/index.js +1 -2
- package/dist/plugins/paragraph/index.js +1 -2
- package/dist/plugins/person/index.js +1 -2
- package/dist/plugins/poll/index.js +1 -2
- package/dist/plugins/quote/index.js +1 -2
- package/dist/plugins/raw/index.js +1 -2
- package/dist/plugins/shared/dropzone.d.ts +6 -0
- package/dist/plugins/shared/dropzone.js +47 -36
- package/dist/plugins/shared/layer.d.ts +13 -0
- package/dist/plugins/shared/layer.js +45 -0
- package/dist/plugins/shared/sourceEditor.css +165 -0
- package/dist/plugins/shared/sourceEditor.d.ts +97 -0
- package/dist/plugins/shared/sourceEditor.js +260 -0
- package/dist/plugins/spoiler/index.js +1 -2
- package/dist/plugins/table/index.js +1 -2
- package/dist/plugins/toggle/index.js +1 -2
- package/dist/plugins/warning/index.js +1 -2
- package/dist/renderer/index.js +1 -2
- package/dist/renderer/renderers/attaches/index.js +1 -2
- package/dist/renderer/renderers/carousel/index.js +24 -24
- package/dist/renderer/renderers/carousel/styles.css +8 -2
- package/dist/renderer/renderers/checklist/index.js +1 -2
- package/dist/renderer/renderers/code/index.js +1 -2
- package/dist/renderer/renderers/columns/index.js +1 -2
- package/dist/renderer/renderers/delimiter/index.js +1 -2
- package/dist/renderer/renderers/embed/index.js +1 -2
- package/dist/renderer/renderers/gallery/index.js +1 -2
- package/dist/renderer/renderers/heading/index.js +1 -2
- package/dist/renderer/renderers/image/index.js +1 -2
- package/dist/renderer/renderers/link-preview/index.js +1 -2
- package/dist/renderer/renderers/list/index.js +1 -2
- package/dist/renderer/renderers/paragraph/index.js +1 -2
- package/dist/renderer/renderers/person/index.js +1 -2
- package/dist/renderer/renderers/poll/index.js +1 -2
- package/dist/renderer/renderers/quote/index.js +1 -2
- package/dist/renderer/renderers/spoiler/index.js +1 -2
- package/dist/renderer/renderers/table/index.js +1 -2
- package/dist/renderer/renderers/toggle/index.js +1 -2
- package/dist/renderer/renderers/warning/index.js +1 -2
- package/package.json +27 -29
- package/dist/shared/resolvePath.d.ts +0 -8
- package/dist/shared/resolvePath.js +0 -10
package/dist/core/index.js
CHANGED
|
@@ -30,12 +30,12 @@ import { TriggerManager } from './TriggerManager.js'
|
|
|
30
30
|
import { InlinePatternMatcher } from './InlinePatternMatcher.js'
|
|
31
31
|
import { PopupManager } from './PopupManager.js'
|
|
32
32
|
import { injectStyleUrls } from './StyleInjector.js'
|
|
33
|
-
import { resolveTuning } from './config.js'
|
|
34
|
-
import {DEFAULT_BLOCK_TYPE, DEFAULT_THEME} from './constants.js'
|
|
35
|
-
import { claimPluginInstances } from './PluginOwnership.js'
|
|
36
|
-
import { claimEditorHolder } from './EditorHolderOwnership.js'
|
|
37
|
-
import { LifecycleScope } from './LifecycleScope.js'
|
|
38
|
-
import en from './locale/en.js'
|
|
33
|
+
import { resolveTuning } from './config.js'
|
|
34
|
+
import {DEFAULT_BLOCK_TYPE, DEFAULT_THEME} from './constants.js'
|
|
35
|
+
import { claimPluginInstances } from './PluginOwnership.js'
|
|
36
|
+
import { claimEditorHolder } from './EditorHolderOwnership.js'
|
|
37
|
+
import { LifecycleScope } from './LifecycleScope.js'
|
|
38
|
+
import en from './locale/en.js'
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Resolve inline tools config into tool instances.
|
|
@@ -119,26 +119,26 @@ function injectPluginI18n(plugin, i18n) {
|
|
|
119
119
|
* @param {number} [minHeight]
|
|
120
120
|
* @returns {{ rootEl: HTMLElement, blocksEl: HTMLElement, clickArea: HTMLElement }}
|
|
121
121
|
*/
|
|
122
|
-
function buildEditorDOM(holder, theme, minHeight) {
|
|
123
|
-
const rootEl = el('div', `oe-editor oe-theme-${theme}`, { tabindex: '-1' })
|
|
124
|
-
if (minHeight !== undefined) rootEl.style.minHeight = `${minHeight}px`
|
|
122
|
+
function buildEditorDOM(holder, theme, minHeight) {
|
|
123
|
+
const rootEl = el('div', `oe-editor oe-theme-${theme}`, { tabindex: '-1' })
|
|
124
|
+
if (minHeight !== undefined) rootEl.style.minHeight = `${minHeight}px`
|
|
125
125
|
const blocksEl = el('div', 'oe-blocks')
|
|
126
126
|
const clickArea = el('div', 'oe-click-area')
|
|
127
127
|
rootEl.appendChild(blocksEl)
|
|
128
128
|
rootEl.appendChild(clickArea)
|
|
129
|
-
return { rootEl, blocksEl, clickArea }
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Synchronize the editor root's read-only class and accessibility state.
|
|
134
|
-
* @param {HTMLElement} rootEl Editor root element.
|
|
135
|
-
* @param {boolean} readOnly Whether document mutations are disabled.
|
|
136
|
-
*/
|
|
137
|
-
function applyReadOnlyAttributes(rootEl, readOnly) {
|
|
138
|
-
rootEl.classList.toggle('oe-editor--read-only', readOnly)
|
|
139
|
-
if (readOnly) rootEl.setAttribute('aria-readonly', 'true')
|
|
140
|
-
else rootEl.removeAttribute('aria-readonly')
|
|
141
|
-
}
|
|
129
|
+
return { rootEl, blocksEl, clickArea }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Synchronize the editor root's read-only class and accessibility state.
|
|
134
|
+
* @param {HTMLElement} rootEl Editor root element.
|
|
135
|
+
* @param {boolean} readOnly Whether document mutations are disabled.
|
|
136
|
+
*/
|
|
137
|
+
function applyReadOnlyAttributes(rootEl, readOnly) {
|
|
138
|
+
rootEl.classList.toggle('oe-editor--read-only', readOnly)
|
|
139
|
+
if (readOnly) rootEl.setAttribute('aria-readonly', 'true')
|
|
140
|
+
else rootEl.removeAttribute('aria-readonly')
|
|
141
|
+
}
|
|
142
142
|
|
|
143
143
|
/**
|
|
144
144
|
* Wire focusin and input tracking on the editor root.
|
|
@@ -149,7 +149,7 @@ function applyReadOnlyAttributes(rootEl, readOnly) {
|
|
|
149
149
|
*/
|
|
150
150
|
function wireInputTracking(rootEl, blocks, events) {
|
|
151
151
|
const onFocusIn = (/** @type {FocusEvent} */ e) => {
|
|
152
|
-
const target = /** @type {import('./types').DOMNode} */ (e.target)
|
|
152
|
+
const target = /** @type {import('./types').DOMNode} */ (e.target)
|
|
153
153
|
const block = blocks.getBlockByChildNode(target)
|
|
154
154
|
if (!block) return
|
|
155
155
|
const index = blocks.getBlockIndex(block.id)
|
|
@@ -159,7 +159,7 @@ function wireInputTracking(rootEl, blocks, events) {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
const onInput = (/** @type {InputEvent} */ event) => {
|
|
162
|
-
const target = /** @type {import('./types').DOMNode} */ (event.target)
|
|
162
|
+
const target = /** @type {import('./types').DOMNode} */ (event.target)
|
|
163
163
|
// Editor controls (URL/color/font inputs, filters, dialogs) also bubble
|
|
164
164
|
// `input` through rootEl. They are not document mutations and must never
|
|
165
165
|
// advance block history by falling back to the currently focused block.
|
|
@@ -199,8 +199,8 @@ function injectPluginStyles(plugins) {
|
|
|
199
199
|
? plugin.getPluginConfig()
|
|
200
200
|
: undefined
|
|
201
201
|
if (cfg?.injectStyles !== false) {
|
|
202
|
-
const constructor = /** @type {import('./types').BlockPluginConstructor} */ (plugin.constructor)
|
|
203
|
-
const urls = constructor.styles
|
|
202
|
+
const constructor = /** @type {import('./types').BlockPluginConstructor} */ (plugin.constructor)
|
|
203
|
+
const urls = constructor.styles
|
|
204
204
|
if (urls) styleUrls.push(...urls)
|
|
205
205
|
}
|
|
206
206
|
if (cfg?.css) styleUrls.push(cfg.css)
|
|
@@ -227,10 +227,10 @@ function injectPluginStyles(plugins) {
|
|
|
227
227
|
* @property {DocumentSnapshotStore} snapshots
|
|
228
228
|
* @property {import('./config').EditorTuning} tuning
|
|
229
229
|
* @property {import('./types').EditorConfig} config
|
|
230
|
-
* @property {Diagnostics} diagnostics
|
|
231
|
-
* @property {LifecycleScope} scope
|
|
232
|
-
* @property {UndoManager} undoManager
|
|
233
|
-
*/
|
|
230
|
+
* @property {Diagnostics} diagnostics
|
|
231
|
+
* @property {LifecycleScope} scope
|
|
232
|
+
* @property {UndoManager} undoManager
|
|
233
|
+
*/
|
|
234
234
|
|
|
235
235
|
/**
|
|
236
236
|
* Wire all edit-mode managers (toolbar, undo, clipboard, drag, keyboard, etc.).
|
|
@@ -241,19 +241,19 @@ function wireEditMode(deps) {
|
|
|
241
241
|
const {
|
|
242
242
|
rootEl, blocksEl, clickArea, plugins, blocks, selection,
|
|
243
243
|
i18n, events, commands, crossBlockSelection, defaultBlockType,
|
|
244
|
-
inlinePluginRegistry, inlinePluginCtx, facade, snapshots, tuning, config, diagnostics,
|
|
245
|
-
scope, undoManager,
|
|
246
|
-
} = deps
|
|
247
|
-
|
|
248
|
-
const blockOps = new BlockOperations(blocks, selection, defaultBlockType, events)
|
|
249
|
-
blocks.setPluginStructuralCommands({
|
|
250
|
-
splitBlock: () => blockOps.splitBlock(),
|
|
251
|
-
exitEmptyBlock: () => blockOps.exitEmptyBlock(),
|
|
252
|
-
})
|
|
253
|
-
scope.register({
|
|
254
|
-
destroy: () => blocks.setPluginStructuralCommands({ splitBlock: null, exitEmptyBlock: null }),
|
|
255
|
-
})
|
|
256
|
-
const pluginMutations = commands
|
|
244
|
+
inlinePluginRegistry, inlinePluginCtx, facade, snapshots, tuning, config, diagnostics,
|
|
245
|
+
scope, undoManager,
|
|
246
|
+
} = deps
|
|
247
|
+
|
|
248
|
+
const blockOps = new BlockOperations(blocks, selection, defaultBlockType, events)
|
|
249
|
+
blocks.setPluginStructuralCommands({
|
|
250
|
+
splitBlock: () => blockOps.splitBlock(),
|
|
251
|
+
exitEmptyBlock: () => blockOps.exitEmptyBlock(),
|
|
252
|
+
})
|
|
253
|
+
scope.register({
|
|
254
|
+
destroy: () => blocks.setPluginStructuralCommands({ splitBlock: null, exitEmptyBlock: null }),
|
|
255
|
+
})
|
|
256
|
+
const pluginMutations = commands
|
|
257
257
|
|
|
258
258
|
const duplicateBlock = (current, index) => {
|
|
259
259
|
const snapshot = snapshots.capture().blocks.find(block => block.id === current.id)
|
|
@@ -283,12 +283,12 @@ function wireEditMode(deps) {
|
|
|
283
283
|
moveAnimationMs: tuning.animations.blockMoveMs,
|
|
284
284
|
},
|
|
285
285
|
})
|
|
286
|
-
scope.register(toolbar)
|
|
287
|
-
|
|
288
|
-
const unsubscribeInlineInsert = events.on(EditorEvent.INLINE_PLUGIN_INSERT, (/** @type {{ type: string }} */ payload) => {
|
|
289
|
-
facade.insertInlinePlugin(payload.type)
|
|
290
|
-
})
|
|
291
|
-
scope.register({ destroy: unsubscribeInlineInsert })
|
|
286
|
+
scope.register(toolbar)
|
|
287
|
+
|
|
288
|
+
const unsubscribeInlineInsert = events.on(EditorEvent.INLINE_PLUGIN_INSERT, (/** @type {{ type: string }} */ payload) => {
|
|
289
|
+
facade.insertInlinePlugin(payload.type)
|
|
290
|
+
})
|
|
291
|
+
scope.register({ destroy: unsubscribeInlineInsert })
|
|
292
292
|
|
|
293
293
|
const inlineTools = resolveInlineTools(config.inlineTools, i18n, crossBlockSelection)
|
|
294
294
|
|
|
@@ -309,7 +309,7 @@ function wireEditMode(deps) {
|
|
|
309
309
|
crossBlockSelection,
|
|
310
310
|
commands,
|
|
311
311
|
)
|
|
312
|
-
scope.register(inlineToolbar)
|
|
312
|
+
scope.register(inlineToolbar)
|
|
313
313
|
|
|
314
314
|
const shortcuts = new ShortcutRegistry()
|
|
315
315
|
shortcuts.register('Mod+Z', () => undoManager.undo(), { scope: 'editor' })
|
|
@@ -326,7 +326,7 @@ function wireEditMode(deps) {
|
|
|
326
326
|
inlinePluginRegistry,
|
|
327
327
|
inlinePluginCtx,
|
|
328
328
|
})
|
|
329
|
-
scope.register(slashCommands)
|
|
329
|
+
scope.register(slashCommands)
|
|
330
330
|
|
|
331
331
|
shortcuts.register('Escape', () => {
|
|
332
332
|
toolbar.closeToolbox()
|
|
@@ -357,14 +357,14 @@ function wireEditMode(deps) {
|
|
|
357
357
|
const uiActivePredicate = () => inlineToolbar.hasActiveUI() || slashCommands.isOpen
|
|
358
358
|
|
|
359
359
|
const keyboardManager = new KeyboardManager(rootEl, blockOps, shortcuts, blocks, events, defaultBlockType, uiActivePredicate)
|
|
360
|
-
scope.register(keyboardManager)
|
|
360
|
+
scope.register(keyboardManager)
|
|
361
361
|
|
|
362
362
|
if (inlinePluginRegistry.hasTriggers) {
|
|
363
|
-
scope.register(new TriggerManager(rootEl, inlinePluginRegistry, inlinePluginCtx, events))
|
|
363
|
+
scope.register(new TriggerManager(rootEl, inlinePluginRegistry, inlinePluginCtx, events))
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
if (inlinePluginRegistry.size > 0) {
|
|
367
|
-
scope.register(new InlinePatternMatcher(
|
|
367
|
+
scope.register(new InlinePatternMatcher(
|
|
368
368
|
rootEl,
|
|
369
369
|
inlinePluginRegistry,
|
|
370
370
|
inlinePluginCtx,
|
|
@@ -377,11 +377,12 @@ function wireEditMode(deps) {
|
|
|
377
377
|
const clipboard = new Clipboard(rootEl, {
|
|
378
378
|
blocks, selection, plugins, defaultBlockType, crossBlockSelection, events, commands,
|
|
379
379
|
blockOps, inlinePluginRegistry, inlinePluginCtx, diagnostics, uiActivePredicate,
|
|
380
|
+
pendingPasteLabel: i18n.t('clipboard.processingFile'),
|
|
380
381
|
captureSnapshot: () => snapshots.capture(),
|
|
381
382
|
})
|
|
382
|
-
scope.register(clipboard)
|
|
383
|
-
scope.register(new DragManager(rootEl, blocks, toolbar.dragHandle, events, tuning.drag))
|
|
384
|
-
scope.register(new MouseSelectionManager(rootEl, { blocksEl, clickArea, blocks, selection, events, crossBlockSelection, defaultBlockType }))
|
|
383
|
+
scope.register(clipboard)
|
|
384
|
+
scope.register(new DragManager(rootEl, blocks, toolbar.dragHandle, events, tuning.drag))
|
|
385
|
+
scope.register(new MouseSelectionManager(rootEl, { blocksEl, clickArea, blocks, selection, events, crossBlockSelection, defaultBlockType }))
|
|
385
386
|
|
|
386
387
|
// Re-emit block:focused so Toolbar positions itself
|
|
387
388
|
// (initial setCurrentIndex fired before Toolbar was created)
|
|
@@ -396,13 +397,13 @@ function wireEditMode(deps) {
|
|
|
396
397
|
* @param {import('./types').EditorConfig} config
|
|
397
398
|
* @returns {I18n}
|
|
398
399
|
*/
|
|
399
|
-
function initI18n(config) {
|
|
400
|
-
const localeMessages = /** @type {Record<string, import('./types').LocaleValue>} */ (
|
|
401
|
-
config.locale ?? en
|
|
402
|
-
)
|
|
403
|
-
const configuredLang = localeMessages.__lang
|
|
404
|
-
const lang = typeof configuredLang === 'string' ? configuredLang : 'en'
|
|
405
|
-
return new I18n(localeMessages, localeMessages === en ? undefined : en, lang)
|
|
400
|
+
function initI18n(config) {
|
|
401
|
+
const localeMessages = /** @type {Record<string, import('./types').LocaleValue>} */ (
|
|
402
|
+
config.locale ?? en
|
|
403
|
+
)
|
|
404
|
+
const configuredLang = localeMessages.__lang
|
|
405
|
+
const lang = typeof configuredLang === 'string' ? configuredLang : 'en'
|
|
406
|
+
return new I18n(localeMessages, localeMessages === en ? undefined : en, lang)
|
|
406
407
|
}
|
|
407
408
|
|
|
408
409
|
/**
|
|
@@ -427,8 +428,8 @@ function registerPlugins(pluginList, i18n, defaultBlockType, placeholder) {
|
|
|
427
428
|
throw new Error(`Duplicate block plugin type: "${plugin.type}"`)
|
|
428
429
|
}
|
|
429
430
|
injectPluginI18n(plugin, i18n)
|
|
430
|
-
if (placeholder !== undefined && plugin.type === defaultBlockType && typeof plugin.setPlaceholder === 'function') {
|
|
431
|
-
plugin.setPlaceholder(placeholder)
|
|
431
|
+
if (placeholder !== undefined && plugin.type === defaultBlockType && typeof plugin.setPlaceholder === 'function') {
|
|
432
|
+
plugin.setPlaceholder(placeholder)
|
|
432
433
|
}
|
|
433
434
|
plugins.set(plugin.type, plugin)
|
|
434
435
|
}
|
|
@@ -444,27 +445,27 @@ function registerPlugins(pluginList, i18n, defaultBlockType, placeholder) {
|
|
|
444
445
|
* @param {import('./types').EditorConfig} config
|
|
445
446
|
* @returns {import('./types').IEditor}
|
|
446
447
|
*/
|
|
447
|
-
export function createEditor(config) {
|
|
448
|
+
export function createEditor(config) {
|
|
448
449
|
if (!(config?.holder instanceof HTMLElement)) {
|
|
449
450
|
throw new TypeError('createEditor() requires an HTMLElement holder')
|
|
450
451
|
}
|
|
451
|
-
if (!Array.isArray(config.plugins)) {
|
|
452
|
-
throw new TypeError('createEditor() requires a plugins array')
|
|
453
|
-
}
|
|
454
|
-
if (config.readOnly !== undefined && typeof config.readOnly !== 'boolean') {
|
|
455
|
-
throw new TypeError('createEditor() readOnly must be a boolean')
|
|
456
|
-
}
|
|
457
|
-
if (config.placeholder !== undefined && typeof config.placeholder !== 'string') {
|
|
458
|
-
throw new TypeError('createEditor() placeholder must be a string')
|
|
459
|
-
}
|
|
460
|
-
if (
|
|
461
|
-
config.minHeight !== undefined
|
|
462
|
-
&& (typeof config.minHeight !== 'number' || !Number.isFinite(config.minHeight) || config.minHeight < 0)
|
|
463
|
-
) {
|
|
464
|
-
throw new RangeError('createEditor() minHeight must be a finite number greater than or equal to 0')
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
let readOnly = config.readOnly ?? false
|
|
452
|
+
if (!Array.isArray(config.plugins)) {
|
|
453
|
+
throw new TypeError('createEditor() requires a plugins array')
|
|
454
|
+
}
|
|
455
|
+
if (config.readOnly !== undefined && typeof config.readOnly !== 'boolean') {
|
|
456
|
+
throw new TypeError('createEditor() readOnly must be a boolean')
|
|
457
|
+
}
|
|
458
|
+
if (config.placeholder !== undefined && typeof config.placeholder !== 'string') {
|
|
459
|
+
throw new TypeError('createEditor() placeholder must be a string')
|
|
460
|
+
}
|
|
461
|
+
if (
|
|
462
|
+
config.minHeight !== undefined
|
|
463
|
+
&& (typeof config.minHeight !== 'number' || !Number.isFinite(config.minHeight) || config.minHeight < 0)
|
|
464
|
+
) {
|
|
465
|
+
throw new RangeError('createEditor() minHeight must be a finite number greater than or equal to 0')
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
let readOnly = config.readOnly ?? false
|
|
468
469
|
const defaultBlockType = config.defaultBlock
|
|
469
470
|
|| (config.plugins?.some(plugin => plugin?.type === DEFAULT_BLOCK_TYPE)
|
|
470
471
|
? DEFAULT_BLOCK_TYPE
|
|
@@ -475,10 +476,10 @@ export function createEditor(config) {
|
|
|
475
476
|
let rootEl
|
|
476
477
|
let blocks
|
|
477
478
|
let inlinePluginRegistry
|
|
478
|
-
let facade
|
|
479
|
-
let pluginOwnership
|
|
480
|
-
const diagnostics = new Diagnostics(config.onDiagnostic, config.diagnosticThresholds)
|
|
481
|
-
const holderOwnership = claimEditorHolder(config.holder)
|
|
479
|
+
let facade
|
|
480
|
+
let pluginOwnership
|
|
481
|
+
const diagnostics = new Diagnostics(config.onDiagnostic, config.diagnosticThresholds)
|
|
482
|
+
const holderOwnership = claimEditorHolder(config.holder)
|
|
482
483
|
|
|
483
484
|
try {
|
|
484
485
|
pluginOwnership = claimPluginInstances([
|
|
@@ -495,8 +496,8 @@ export function createEditor(config) {
|
|
|
495
496
|
const plugins = registerPlugins(config.plugins, i18n, defaultBlockType, config.placeholder)
|
|
496
497
|
|
|
497
498
|
const dom = buildEditorDOM(config.holder, theme, config.minHeight)
|
|
498
|
-
rootEl = dom.rootEl
|
|
499
|
-
applyReadOnlyAttributes(rootEl, readOnly)
|
|
499
|
+
rootEl = dom.rootEl
|
|
500
|
+
applyReadOnlyAttributes(rootEl, readOnly)
|
|
500
501
|
const { blocksEl, clickArea } = dom
|
|
501
502
|
|
|
502
503
|
blocks = new BlockManager(
|
|
@@ -528,13 +529,13 @@ export function createEditor(config) {
|
|
|
528
529
|
|
|
529
530
|
const crossBlockSelection = new CrossBlockSelection()
|
|
530
531
|
|
|
531
|
-
const inlinePluginCtx = new PopupManager(
|
|
532
|
-
events,
|
|
533
|
-
EditorEvent.CHANGED,
|
|
534
|
-
blocks,
|
|
535
|
-
commands,
|
|
536
|
-
() => readOnly,
|
|
537
|
-
)
|
|
532
|
+
const inlinePluginCtx = new PopupManager(
|
|
533
|
+
events,
|
|
534
|
+
EditorEvent.CHANGED,
|
|
535
|
+
blocks,
|
|
536
|
+
commands,
|
|
537
|
+
() => readOnly,
|
|
538
|
+
)
|
|
538
539
|
inlinePluginCtx.setRoot(rootEl)
|
|
539
540
|
inlinePluginRegistry.mount(rootEl, inlinePluginCtx)
|
|
540
541
|
|
|
@@ -551,12 +552,12 @@ export function createEditor(config) {
|
|
|
551
552
|
diagnostics,
|
|
552
553
|
initialDocument?.version ?? documentSchema.currentVersion,
|
|
553
554
|
)
|
|
554
|
-
const publicBlocks = new EditorBlocksApi(blocks, events)
|
|
555
|
+
const publicBlocks = new EditorBlocksApi(blocks, events)
|
|
555
556
|
const publicEvents = new EditorEventSubscriptions(events)
|
|
556
|
-
facade = new EditorFacade(rootEl, {
|
|
557
|
-
blocks,
|
|
558
|
-
selection,
|
|
559
|
-
events,
|
|
557
|
+
facade = new EditorFacade(rootEl, {
|
|
558
|
+
blocks,
|
|
559
|
+
selection,
|
|
560
|
+
events,
|
|
560
561
|
defaultBlockType,
|
|
561
562
|
inlinePluginRegistry,
|
|
562
563
|
inlinePluginCtx,
|
|
@@ -565,96 +566,96 @@ export function createEditor(config) {
|
|
|
565
566
|
documentSchema,
|
|
566
567
|
diagnostics,
|
|
567
568
|
snapshots,
|
|
568
|
-
publicBlocks,
|
|
569
|
-
publicEvents,
|
|
570
|
-
readOnly,
|
|
571
|
-
})
|
|
572
|
-
facade.registerDestroyable(holderOwnership)
|
|
573
|
-
facade.registerDestroyable(pluginOwnership)
|
|
569
|
+
publicBlocks,
|
|
570
|
+
publicEvents,
|
|
571
|
+
readOnly,
|
|
572
|
+
})
|
|
573
|
+
facade.registerDestroyable(holderOwnership)
|
|
574
|
+
facade.registerDestroyable(pluginOwnership)
|
|
574
575
|
facade.registerDestroyable(inlinePluginCtx)
|
|
575
576
|
facade.registerDestroyable(inlinePluginRegistry)
|
|
576
577
|
commands.configureRollback(
|
|
577
578
|
() => snapshots.capture(),
|
|
578
579
|
document => facade.render(document),
|
|
579
580
|
)
|
|
580
|
-
const changeNotifier = new ChangeNotifier(() => facade.save(), config.onChange, tuning.change.debounceMs)
|
|
581
|
-
facade.registerDestroyable(changeNotifier)
|
|
582
|
-
events.on(EditorEvent.CHANGED, () => changeNotifier.schedule())
|
|
583
|
-
|
|
584
|
-
const undoManager = new UndoManager(
|
|
585
|
-
blocks, events,
|
|
586
|
-
() => snapshots.capture(),
|
|
587
|
-
(data, caret) => facade.render(data, caret),
|
|
588
|
-
() => selection.getCaret(),
|
|
589
|
-
tuning.undo,
|
|
590
|
-
)
|
|
591
|
-
undoManager.setCommandsEnabled(!readOnly, { notify: false })
|
|
592
|
-
facade.configureHistory(undoManager)
|
|
593
|
-
facade.registerDestroyable(undoManager)
|
|
594
|
-
|
|
595
|
-
/** @type {LifecycleScope | null} */
|
|
596
|
-
let editModeScope = null
|
|
597
|
-
const mountEditMode = () => {
|
|
598
|
-
if (editModeScope) return
|
|
599
|
-
const scope = new LifecycleScope()
|
|
600
|
-
try {
|
|
601
|
-
scope.register(wireInputTracking(rootEl, blocks, events))
|
|
602
|
-
wireEditMode({
|
|
603
|
-
rootEl, blocksEl, clickArea, plugins, blocks, selection,
|
|
604
|
-
i18n, events, commands, crossBlockSelection, defaultBlockType,
|
|
605
|
-
inlinePluginRegistry, inlinePluginCtx, facade, snapshots, tuning, config, diagnostics,
|
|
606
|
-
scope, undoManager,
|
|
607
|
-
})
|
|
608
|
-
editModeScope = scope
|
|
609
|
-
} catch (error) {
|
|
610
|
-
scope.destroy()
|
|
611
|
-
throw error
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const unmountEditMode = () => {
|
|
616
|
-
editModeScope?.destroy()
|
|
617
|
-
editModeScope = null
|
|
618
|
-
crossBlockSelection.deactivate(rootEl)
|
|
619
|
-
blocks.clearSelection()
|
|
620
|
-
}
|
|
621
|
-
facade.registerDestroyable({ destroy: unmountEditMode })
|
|
622
|
-
|
|
623
|
-
facade.configureReadOnlyTransition(nextReadOnly => {
|
|
624
|
-
const previousReadOnly = facade.readOnly
|
|
625
|
-
// Cancel transient widget previews before capturing the canonical
|
|
626
|
-
// document. Otherwise a preview could be serialized as a committed edit.
|
|
627
|
-
inlinePluginCtx.hidePopup()
|
|
628
|
-
undoManager.commit()
|
|
629
|
-
const document = facade.save()
|
|
630
|
-
unmountEditMode()
|
|
631
|
-
readOnly = nextReadOnly
|
|
632
|
-
blocks.setReadOnly(nextReadOnly)
|
|
633
|
-
applyReadOnlyAttributes(rootEl, nextReadOnly)
|
|
634
|
-
|
|
635
|
-
try {
|
|
636
|
-
facade.render(document, undefined, { focus: false, notifyChange: false })
|
|
637
|
-
if (!nextReadOnly) mountEditMode()
|
|
638
|
-
undoManager.setCommandsEnabled(!nextReadOnly, { notify: false })
|
|
639
|
-
} catch (transitionError) {
|
|
640
|
-
unmountEditMode()
|
|
641
|
-
readOnly = previousReadOnly
|
|
642
|
-
blocks.setReadOnly(previousReadOnly)
|
|
643
|
-
applyReadOnlyAttributes(rootEl, previousReadOnly)
|
|
644
|
-
try {
|
|
645
|
-
facade.render(document, undefined, { focus: false, notifyChange: false })
|
|
646
|
-
if (!previousReadOnly) mountEditMode()
|
|
647
|
-
} catch (rollbackError) {
|
|
648
|
-
throw new AggregateError(
|
|
649
|
-
[transitionError, rollbackError],
|
|
650
|
-
'Editor read-only transition and rollback failed',
|
|
651
|
-
)
|
|
652
|
-
}
|
|
653
|
-
throw transitionError
|
|
654
|
-
}
|
|
655
|
-
})
|
|
656
|
-
|
|
657
|
-
if (!readOnly) mountEditMode()
|
|
581
|
+
const changeNotifier = new ChangeNotifier(() => facade.save(), config.onChange, tuning.change.debounceMs)
|
|
582
|
+
facade.registerDestroyable(changeNotifier)
|
|
583
|
+
events.on(EditorEvent.CHANGED, () => changeNotifier.schedule())
|
|
584
|
+
|
|
585
|
+
const undoManager = new UndoManager(
|
|
586
|
+
blocks, events,
|
|
587
|
+
() => snapshots.capture(),
|
|
588
|
+
(data, caret) => facade.render(data, caret),
|
|
589
|
+
() => selection.getCaret(),
|
|
590
|
+
tuning.undo,
|
|
591
|
+
)
|
|
592
|
+
undoManager.setCommandsEnabled(!readOnly, { notify: false })
|
|
593
|
+
facade.configureHistory(undoManager)
|
|
594
|
+
facade.registerDestroyable(undoManager)
|
|
595
|
+
|
|
596
|
+
/** @type {LifecycleScope | null} */
|
|
597
|
+
let editModeScope = null
|
|
598
|
+
const mountEditMode = () => {
|
|
599
|
+
if (editModeScope) return
|
|
600
|
+
const scope = new LifecycleScope()
|
|
601
|
+
try {
|
|
602
|
+
scope.register(wireInputTracking(rootEl, blocks, events))
|
|
603
|
+
wireEditMode({
|
|
604
|
+
rootEl, blocksEl, clickArea, plugins, blocks, selection,
|
|
605
|
+
i18n, events, commands, crossBlockSelection, defaultBlockType,
|
|
606
|
+
inlinePluginRegistry, inlinePluginCtx, facade, snapshots, tuning, config, diagnostics,
|
|
607
|
+
scope, undoManager,
|
|
608
|
+
})
|
|
609
|
+
editModeScope = scope
|
|
610
|
+
} catch (error) {
|
|
611
|
+
scope.destroy()
|
|
612
|
+
throw error
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const unmountEditMode = () => {
|
|
617
|
+
editModeScope?.destroy()
|
|
618
|
+
editModeScope = null
|
|
619
|
+
crossBlockSelection.deactivate(rootEl)
|
|
620
|
+
blocks.clearSelection()
|
|
621
|
+
}
|
|
622
|
+
facade.registerDestroyable({ destroy: unmountEditMode })
|
|
623
|
+
|
|
624
|
+
facade.configureReadOnlyTransition(nextReadOnly => {
|
|
625
|
+
const previousReadOnly = facade.readOnly
|
|
626
|
+
// Cancel transient widget previews before capturing the canonical
|
|
627
|
+
// document. Otherwise a preview could be serialized as a committed edit.
|
|
628
|
+
inlinePluginCtx.hidePopup()
|
|
629
|
+
undoManager.commit()
|
|
630
|
+
const document = facade.save()
|
|
631
|
+
unmountEditMode()
|
|
632
|
+
readOnly = nextReadOnly
|
|
633
|
+
blocks.setReadOnly(nextReadOnly)
|
|
634
|
+
applyReadOnlyAttributes(rootEl, nextReadOnly)
|
|
635
|
+
|
|
636
|
+
try {
|
|
637
|
+
facade.render(document, undefined, { focus: false, notifyChange: false })
|
|
638
|
+
if (!nextReadOnly) mountEditMode()
|
|
639
|
+
undoManager.setCommandsEnabled(!nextReadOnly, { notify: false })
|
|
640
|
+
} catch (transitionError) {
|
|
641
|
+
unmountEditMode()
|
|
642
|
+
readOnly = previousReadOnly
|
|
643
|
+
blocks.setReadOnly(previousReadOnly)
|
|
644
|
+
applyReadOnlyAttributes(rootEl, previousReadOnly)
|
|
645
|
+
try {
|
|
646
|
+
facade.render(document, undefined, { focus: false, notifyChange: false })
|
|
647
|
+
if (!previousReadOnly) mountEditMode()
|
|
648
|
+
} catch (rollbackError) {
|
|
649
|
+
throw new AggregateError(
|
|
650
|
+
[transitionError, rollbackError],
|
|
651
|
+
'Editor read-only transition and rollback failed',
|
|
652
|
+
)
|
|
653
|
+
}
|
|
654
|
+
throw transitionError
|
|
655
|
+
}
|
|
656
|
+
})
|
|
657
|
+
|
|
658
|
+
if (!readOnly) mountEditMode()
|
|
658
659
|
|
|
659
660
|
const styleCleanup = injectPluginStyles(plugins)
|
|
660
661
|
if (styleCleanup) facade.registerDestroyable(styleCleanup)
|
|
@@ -677,12 +678,12 @@ export function createEditor(config) {
|
|
|
677
678
|
diagnostics.emit('editor.create.failed', { errorName: diagnostics.errorName(error) })
|
|
678
679
|
if (facade) {
|
|
679
680
|
facade.destroy()
|
|
680
|
-
} else {
|
|
681
|
-
blocks?.clear()
|
|
682
|
-
inlinePluginRegistry?.destroy()
|
|
683
|
-
pluginOwnership?.destroy()
|
|
684
|
-
holderOwnership.destroy()
|
|
685
|
-
rootEl?.remove()
|
|
681
|
+
} else {
|
|
682
|
+
blocks?.clear()
|
|
683
|
+
inlinePluginRegistry?.destroy()
|
|
684
|
+
pluginOwnership?.destroy()
|
|
685
|
+
holderOwnership.destroy()
|
|
686
|
+
rootEl?.remove()
|
|
686
687
|
}
|
|
687
688
|
throw error
|
|
688
689
|
}
|
|
@@ -699,5 +700,5 @@ export { createColorSwatchPlugin } from '../inline-plugins/color.js'
|
|
|
699
700
|
export { createMentionPlugin } from '../inline-plugins/mention/index.js'
|
|
700
701
|
|
|
701
702
|
// Block plugins are NOT re-exported here — import them directly from their
|
|
702
|
-
// own entry points to keep bundles tree-shakeable. See
|
|
703
|
-
// canonical import shape.
|
|
703
|
+
// own entry points to keep bundles tree-shakeable. See index.html for the
|
|
704
|
+
// canonical import shape.
|
package/dist/core/locale/en.d.ts
CHANGED
package/dist/core/locale/en.js
CHANGED
package/dist/core/locale/ru.d.ts
CHANGED
package/dist/core/locale/ru.js
CHANGED