@ckeditor/ckeditor5-engine
Advanced tools
Comparing version 0.0.0-nightly-20230726.0 to 0.0.0-nightly-20230727.0
{ | ||
"name": "@ckeditor/ckeditor5-engine", | ||
"version": "0.0.0-nightly-20230726.0", | ||
"version": "0.0.0-nightly-20230727.0", | ||
"description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.", | ||
@@ -26,3 +26,3 @@ "keywords": [ | ||
"dependencies": { | ||
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20230726.0", | ||
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20230727.0", | ||
"lodash-es": "4.17.21" | ||
@@ -29,0 +29,0 @@ }, |
@@ -13,3 +13,3 @@ /** | ||
import DowncastDispatcher from '../conversion/downcastdispatcher'; | ||
import { clearAttributes, convertCollapsedSelection, convertRangeSelection, insertAttributesAndChildren, insertText, remove } from '../conversion/downcasthelpers'; | ||
import { cleanSelection, convertCollapsedSelection, convertRangeSelection, insertAttributesAndChildren, insertText, remove } from '../conversion/downcasthelpers'; | ||
import { convertSelectionChange } from '../conversion/upcasthelpers'; | ||
@@ -71,3 +71,3 @@ import { tryFixingRange } from '../model/utils/selection-post-fixer'; | ||
// Attach default model selection converters. | ||
this.downcastDispatcher.on('selection', clearAttributes(), { priority: 'high' }); | ||
this.downcastDispatcher.on('cleanSelection', cleanSelection()); | ||
this.downcastDispatcher.on('selection', convertRangeSelection(), { priority: 'low' }); | ||
@@ -74,0 +74,0 @@ this.downcastDispatcher.on('selection', convertCollapsedSelection(), { priority: 'low' }); |
@@ -349,2 +349,5 @@ /** | ||
}; | ||
cleanSelection: { | ||
selection: Selection | DocumentSelection; | ||
}; | ||
selection: { | ||
@@ -438,2 +441,14 @@ selection: Selection | DocumentSelection; | ||
/** | ||
* Fired at the beginning of selection conversion, before | ||
* {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:selection selection} events. | ||
* | ||
* Should be used to clean up the view state at the current selection position, before the selection is moved to another place. | ||
* | ||
* @eventName ~DowncastDispatcher#cleanSelection | ||
* @param {module:engine/model/selection~Selection} selection Selection that is converted. | ||
* @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface | ||
* to be used by callback, passed in `DowncastDispatcher` constructor. | ||
*/ | ||
export type DowncastCleanSelectionEvent = DowncastEvent<'cleanSelection'>; | ||
/** | ||
* Fired when a new marker is added to the model. Also fired when a collapsed model selection that is inside a marker is converted. | ||
@@ -440,0 +455,0 @@ * |
@@ -201,4 +201,12 @@ /** | ||
convertSelection(selection, markers, writer) { | ||
const conversionApi = this._createConversionApi(writer); | ||
// First perform a clean-up at the current position of the selection. | ||
this.fire('cleanSelection', { selection }, conversionApi); | ||
// Don't convert selection if it is in a model root that does not have a view root (for now this is only the graveyard root). | ||
const modelRoot = selection.getFirstPosition().root; | ||
if (!conversionApi.mapper.toViewElement(modelRoot)) { | ||
return; | ||
} | ||
// Now, perform actual selection conversion. | ||
const markersAtSelection = Array.from(markers.getMarkersAtPosition(selection.getFirstPosition())); | ||
const conversionApi = this._createConversionApi(writer); | ||
this._addConsumablesForSelection(conversionApi.consumable, selection, markersAtSelection); | ||
@@ -210,12 +218,13 @@ this.fire('selection', { selection }, conversionApi); | ||
for (const marker of markersAtSelection) { | ||
const markerRange = marker.getRange(); | ||
if (!shouldMarkerChangeBeConverted(selection.getFirstPosition(), marker, conversionApi.mapper)) { | ||
continue; | ||
} | ||
const data = { | ||
item: selection, | ||
markerName: marker.name, | ||
markerRange | ||
}; | ||
// Do not fire event if the marker has been consumed. | ||
if (conversionApi.consumable.test(selection, 'addMarker:' + marker.name)) { | ||
const markerRange = marker.getRange(); | ||
if (!shouldMarkerChangeBeConverted(selection.getFirstPosition(), marker, conversionApi.mapper)) { | ||
continue; | ||
} | ||
const data = { | ||
item: selection, | ||
markerName: marker.name, | ||
markerRange | ||
}; | ||
this.fire(`addMarker:${marker.name}`, data, conversionApi); | ||
@@ -225,12 +234,12 @@ } | ||
for (const key of selection.getAttributeKeys()) { | ||
const data = { | ||
item: selection, | ||
range: selection.getFirstRange(), | ||
attributeKey: key, | ||
attributeOldValue: null, | ||
attributeNewValue: selection.getAttribute(key) | ||
}; | ||
// Do not fire event if the attribute has been consumed. | ||
if (conversionApi.consumable.test(selection, 'attribute:' + data.attributeKey)) { | ||
this.fire(`attribute:${data.attributeKey}:$text`, data, conversionApi); | ||
if (conversionApi.consumable.test(selection, 'attribute:' + key)) { | ||
const data = { | ||
item: selection, | ||
range: selection.getFirstRange(), | ||
attributeKey: key, | ||
attributeOldValue: null, | ||
attributeNewValue: selection.getAttribute(key) | ||
}; | ||
this.fire(`attribute:${key}:$text`, data, conversionApi); | ||
} | ||
@@ -237,0 +246,0 @@ } |
@@ -883,3 +883,3 @@ /** | ||
* | ||
* See also {@link module:engine/conversion/downcasthelpers~clearAttributes} which does a clean-up | ||
* See also {@link module:engine/conversion/downcasthelpers~cleanSelection} which does a clean-up | ||
* by merging attributes. | ||
@@ -893,3 +893,3 @@ * | ||
/** | ||
* Function factory that creates a converter which clears artifacts after the previous | ||
* Function factory that creates a converter which cleans artifacts after the previous | ||
* {@link module:engine/model/selection~Selection model selection} conversion. It removes all empty | ||
@@ -913,3 +913,3 @@ * {@link module:engine/view/attributeelement~AttributeElement view attribute elements} and merges sibling attributes at all start and end | ||
* ```ts | ||
* modelDispatcher.on( 'selection', clearAttributes() ); | ||
* modelDispatcher.on( 'cleanSelection', cleanSelection() ); | ||
* ``` | ||
@@ -922,3 +922,3 @@ * | ||
*/ | ||
export declare function clearAttributes(): (evt: EventInfo, data: unknown, conversionApi: DowncastConversionApi) => void; | ||
export declare function cleanSelection(): (evt: EventInfo, data: unknown, conversionApi: DowncastConversionApi) => void; | ||
/** | ||
@@ -925,0 +925,0 @@ * Function factory that creates a converter which converts the set/change/remove attribute changes from the model to the view. |
@@ -92,2 +92,3 @@ /** | ||
export { default as TabObserver } from './view/observer/tabobserver'; | ||
export { default as FocusObserver } from './view/observer/focusobserver'; | ||
export { default as DowncastWriter } from './view/downcastwriter'; | ||
@@ -94,0 +95,0 @@ export { default as UpcastWriter } from './view/upcastwriter'; |
@@ -66,2 +66,3 @@ /** | ||
export { default as TabObserver } from './view/observer/tabobserver'; | ||
export { default as FocusObserver } from './view/observer/focusobserver'; | ||
export { default as DowncastWriter } from './view/downcastwriter'; | ||
@@ -68,0 +69,0 @@ export { default as UpcastWriter } from './view/upcastwriter'; |
@@ -12,2 +12,3 @@ /** | ||
import type Item from './item'; | ||
import type RootElement from './rootelement'; | ||
import type Operation from './operation/operation'; | ||
@@ -196,2 +197,15 @@ /** | ||
/** | ||
* Buffers all the data related to given root like it was all just added to the editor. | ||
* | ||
* Following changes are buffered: | ||
* | ||
* * root is attached, | ||
* * all root content is inserted, | ||
* * all root attributes are added, | ||
* * all markers inside the root are added. | ||
* | ||
* @internal | ||
*/ | ||
_bufferRootLoad(root: RootElement): void; | ||
/** | ||
* Saves and handles an insert change. | ||
@@ -198,0 +212,0 @@ */ |
@@ -97,2 +97,5 @@ /** | ||
const operation = operationToBuffer; | ||
// Note: an operation that happens inside a non-loaded root will be ignored. If the operation happens partially inside | ||
// a non-loaded root, that part will be ignored (this may happen for move or marker operations). | ||
// | ||
switch (operation.type) { | ||
@@ -183,2 +186,10 @@ case 'insert': { | ||
case 'addRoot': { | ||
const root = operation.affectedSelectable; | ||
if (!root._isLoaded) { | ||
return; | ||
} | ||
// Don't buffer if the root state does not change. | ||
if (root.isAttached() == operation.isAdd) { | ||
return; | ||
} | ||
this._bufferRootStateChange(operation.rootName, operation.isAdd); | ||
@@ -190,2 +201,5 @@ break; | ||
case 'changeRootAttribute': { | ||
if (!operation.root._isLoaded) { | ||
return; | ||
} | ||
const rootName = operation.root.rootName; | ||
@@ -207,17 +221,21 @@ this._bufferRootAttributeChange(rootName, operation.key, operation.oldValue, operation.newValue); | ||
bufferMarkerChange(markerName, oldMarkerData, newMarkerData) { | ||
const buffered = this._changedMarkers.get(markerName); | ||
if (oldMarkerData.range && oldMarkerData.range.root.is('rootElement') && !oldMarkerData.range.root._isLoaded) { | ||
oldMarkerData.range = null; | ||
} | ||
if (newMarkerData.range && newMarkerData.range.root.is('rootElement') && !newMarkerData.range.root._isLoaded) { | ||
newMarkerData.range = null; | ||
} | ||
let buffered = this._changedMarkers.get(markerName); | ||
if (!buffered) { | ||
this._changedMarkers.set(markerName, { | ||
newMarkerData, | ||
oldMarkerData | ||
}); | ||
buffered = { newMarkerData, oldMarkerData }; | ||
this._changedMarkers.set(markerName, buffered); | ||
} | ||
else { | ||
buffered.newMarkerData = newMarkerData; | ||
if (buffered.oldMarkerData.range == null && newMarkerData.range == null) { | ||
// The marker is going to be removed (`newMarkerData.range == null`) but it did not exist before the first buffered change | ||
// (`buffered.oldMarkerData.range == null`). In this case, do not keep the marker in buffer at all. | ||
this._changedMarkers.delete(markerName); | ||
} | ||
} | ||
if (buffered.oldMarkerData.range == null && newMarkerData.range == null) { | ||
// The marker is going to be removed (`newMarkerData.range == null`) but it did not exist before the first buffered change | ||
// (`buffered.oldMarkerData.range == null`). In this case, do not keep the marker in buffer at all. | ||
this._changedMarkers.delete(markerName); | ||
} | ||
} | ||
@@ -503,3 +521,3 @@ /** | ||
if (diffItem.state !== undefined) { | ||
// Root `state` can only toggle between of the values ('attached' or 'detached') and no value. It cannot be any other way, | ||
// Root `state` can only toggle between one of the values and no value. It cannot be any other way, | ||
// because if the root was originally attached it can only become detached. Then, if it is re-attached in the same batch of | ||
@@ -576,5 +594,40 @@ // changes, it gets back to "no change" (which means no value). Same if the root was originally detached. | ||
/** | ||
* Buffers all the data related to given root like it was all just added to the editor. | ||
* | ||
* Following changes are buffered: | ||
* | ||
* * root is attached, | ||
* * all root content is inserted, | ||
* * all root attributes are added, | ||
* * all markers inside the root are added. | ||
* | ||
* @internal | ||
*/ | ||
_bufferRootLoad(root) { | ||
if (!root.isAttached()) { | ||
return; | ||
} | ||
this._bufferRootStateChange(root.rootName, true); | ||
this._markInsert(root, 0, root.maxOffset); | ||
// Buffering root attribute changes makes sense and is actually needed, even though we buffer root state change above. | ||
// Because the root state change is buffered, the root attributes changes are not returned by the differ. | ||
// But, if the root attribute is removed in the same change block, or the root is detached, then the differ results would be wrong. | ||
// | ||
for (const key of root.getAttributeKeys()) { | ||
this._bufferRootAttributeChange(root.rootName, key, null, root.getAttribute(key)); | ||
} | ||
for (const marker of this._markerCollection) { | ||
if (marker.getRange().root == root) { | ||
const markerData = marker.getData(); | ||
this.bufferMarkerChange(marker.name, { ...markerData, range: null }, markerData); | ||
} | ||
} | ||
} | ||
/** | ||
* Saves and handles an insert change. | ||
*/ | ||
_markInsert(parent, offset, howMany) { | ||
if (parent.root.is('rootElement') && !parent.root._isLoaded) { | ||
return; | ||
} | ||
const changeItem = { type: 'insert', offset, howMany, count: this._changeCount++ }; | ||
@@ -587,2 +640,5 @@ this._markChange(parent, changeItem); | ||
_markRemove(parent, offset, howMany) { | ||
if (parent.root.is('rootElement') && !parent.root._isLoaded) { | ||
return; | ||
} | ||
const changeItem = { type: 'remove', offset, howMany, count: this._changeCount++ }; | ||
@@ -596,2 +652,5 @@ this._markChange(parent, changeItem); | ||
_markAttribute(item) { | ||
if (item.root.is('rootElement') && !item.root._isLoaded) { | ||
return; | ||
} | ||
const changeItem = { type: 'attribute', offset: item.startOffset, howMany: item.offsetSize, count: this._changeCount++ }; | ||
@@ -598,0 +657,0 @@ this._markChange(item.parent, changeItem); |
@@ -128,6 +128,14 @@ /** | ||
* @param includeDetached Specified whether detached roots should be returned as well. | ||
* @returns Roots names. | ||
*/ | ||
getRootNames(includeDetached?: boolean): Array<string>; | ||
/** | ||
* Returns an array with all roots added to the document (except the {@link #graveyard graveyard root}). | ||
* | ||
* Detached roots **are not** returned by this method by default. This is to make sure that all features or algorithms that operate | ||
* on the document data know which roots are still a part of the document and should be processed. | ||
* | ||
* @param includeDetached Specified whether detached roots should be returned as well. | ||
*/ | ||
getRoots(includeDetached?: boolean): Array<RootElement>; | ||
/** | ||
* Used to register a post-fixer callback. A post-fixer mechanism guarantees that the features | ||
@@ -134,0 +142,0 @@ * will operate on a correct model state. |
@@ -182,8 +182,17 @@ /** | ||
* @param includeDetached Specified whether detached roots should be returned as well. | ||
* @returns Roots names. | ||
*/ | ||
getRootNames(includeDetached = false) { | ||
return this.getRoots(includeDetached).map(root => root.rootName); | ||
} | ||
/** | ||
* Returns an array with all roots added to the document (except the {@link #graveyard graveyard root}). | ||
* | ||
* Detached roots **are not** returned by this method by default. This is to make sure that all features or algorithms that operate | ||
* on the document data know which roots are still a part of the document and should be processed. | ||
* | ||
* @param includeDetached Specified whether detached roots should be returned as well. | ||
*/ | ||
getRoots(includeDetached = false) { | ||
return Array.from(this.roots) | ||
.filter(root => root.rootName != graveyardName && (includeDetached || root.isAttached())) | ||
.map(root => root.rootName); | ||
.filter(root => root != this.graveyard && (includeDetached || root.isAttached()) && root._isLoaded); | ||
} | ||
@@ -287,8 +296,4 @@ /** | ||
_getDefaultRoot() { | ||
for (const root of this.roots) { | ||
if (root !== this.graveyard) { | ||
return root; | ||
} | ||
} | ||
return this.graveyard; | ||
const roots = this.getRoots(); | ||
return roots.length ? roots[0] : this.graveyard; | ||
} | ||
@@ -295,0 +300,0 @@ /** |
@@ -869,2 +869,5 @@ /** | ||
const schema = this._model.schema; | ||
if (position.root.rootName == '$graveyard') { | ||
return null; | ||
} | ||
let attrs = null; | ||
@@ -871,0 +874,0 @@ if (!this.isCollapsed) { |
@@ -772,3 +772,2 @@ /** | ||
* which calls callbacks and returns array of values returned by these callbacks. | ||
* | ||
*/ | ||
@@ -775,0 +774,0 @@ private _runPendingChanges; |
@@ -795,3 +795,2 @@ /** | ||
* which calls callbacks and returns array of values returned by these callbacks. | ||
* | ||
*/ | ||
@@ -798,0 +797,0 @@ _runPendingChanges() { |
@@ -60,6 +60,2 @@ /** | ||
*/ | ||
_validate(): void; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
_execute(): void; | ||
@@ -66,0 +62,0 @@ /** |
@@ -9,3 +9,2 @@ /** | ||
import Operation from './operation'; | ||
import { CKEditorError } from '@ckeditor/ckeditor5-utils'; | ||
/** | ||
@@ -66,25 +65,2 @@ * Operation that creates (or attaches) or detaches a root element. | ||
*/ | ||
_validate() { | ||
// Keep in mind that at this point the root will always exist as it was created in the `constructor()`, even for detach operation. | ||
const root = this._document.getRoot(this.rootName); | ||
if (root.isAttached() && this.isAdd) { | ||
/** | ||
* Trying to attach a root that is already attached. | ||
* | ||
* @error root-operation-root-attached | ||
*/ | ||
throw new CKEditorError('root-operation-root-attached', this); | ||
} | ||
else if (!root.isAttached() && !this.isAdd) { | ||
/** | ||
* Trying to detach a root that is already detached. | ||
* | ||
* @error root-operation-root-detached | ||
*/ | ||
throw new CKEditorError('root-operation-root-detached', this); | ||
} | ||
} | ||
/** | ||
* @inheritDoc | ||
*/ | ||
_execute() { | ||
@@ -91,0 +67,0 @@ this._document.getRoot(this.rootName)._isAttached = this.isAdd; |
@@ -27,2 +27,8 @@ /** | ||
/** | ||
* Informs if the root element is loaded (default). | ||
* | ||
* @internal | ||
*/ | ||
_isLoaded: boolean; | ||
/** | ||
* Creates root element. | ||
@@ -29,0 +35,0 @@ * |
@@ -26,2 +26,8 @@ /** | ||
this._isAttached = true; | ||
/** | ||
* Informs if the root element is loaded (default). | ||
* | ||
* @internal | ||
*/ | ||
this._isLoaded = true; | ||
this._document = document; | ||
@@ -28,0 +34,0 @@ this.rootName = rootName; |
@@ -680,2 +680,7 @@ /** | ||
getNearestSelectionRange(position, direction = 'both') { | ||
if (position.root.rootName == '$graveyard') { | ||
// No valid selection range in the graveyard. | ||
// This is important when getting the document selection default range. | ||
return null; | ||
} | ||
// Return collapsed range if provided position is valid. | ||
@@ -682,0 +687,0 @@ if (this.checkChild(position, '$text')) { |
@@ -17,4 +17,3 @@ /** | ||
const { schema, document } = writer.model; | ||
for (const rootName of document.getRootNames()) { | ||
const root = document.getRoot(rootName); | ||
for (const root of document.getRoots()) { | ||
if (root.isEmpty && !schema.checkChild(root, '$text')) { | ||
@@ -21,0 +20,0 @@ // If paragraph element is allowed in the root, create paragraph element. |
@@ -40,2 +40,12 @@ /** | ||
/** | ||
* Placeholder of editable element. | ||
* | ||
* ```ts | ||
* editor.editing.view.document.getRoot( 'main' ).placeholder = 'New placeholder'; | ||
* ``` | ||
* | ||
* @observable | ||
*/ | ||
placeholder?: string; | ||
/** | ||
* Creates an editable element. | ||
@@ -42,0 +52,0 @@ * |
@@ -34,2 +34,3 @@ /** | ||
this.set('isFocused', false); | ||
this.set('placeholder', undefined); | ||
this.bind('isReadOnly').to(document); | ||
@@ -36,0 +37,0 @@ this.bind('isFocused').to(document, 'isFocused', isFocused => isFocused && document.selection.editableElement == this); |
@@ -154,2 +154,4 @@ /** | ||
this.view.hasDomSelection = true; | ||
// Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element). | ||
this.focusObserver.flush(); | ||
if (this.selection.isEqual(newViewSelection) && this.domConverter.isDomSelectionCorrect(domSelection)) { | ||
@@ -169,4 +171,2 @@ return; | ||
} | ||
// Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element). | ||
this.focusObserver.flush(); | ||
if (this.selection.isSimilar(newViewSelection)) { | ||
@@ -173,0 +173,0 @@ // If selection was equal and we are at this point of algorithm, it means that it was incorrect. |
@@ -10,2 +10,3 @@ /** | ||
import type DowncastWriter from './downcastwriter'; | ||
import type EditableElement from './editableelement'; | ||
import type Element from './element'; | ||
@@ -17,3 +18,3 @@ import type View from './view'; | ||
* | ||
* To change the placeholder text, simply call this method again with new options. | ||
* To change the placeholder text, change value of the `placeholder` property in the provided `element`. | ||
* | ||
@@ -25,3 +26,2 @@ * To disable the placeholder, use {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} helper. | ||
* @param options.element Element that will gain a placeholder. See `options.isDirectHost` to learn more. | ||
* @param options.text Placeholder text. | ||
* @param options.isDirectHost If set `false`, the placeholder will not be enabled directly | ||
@@ -33,6 +33,5 @@ * in the passed `element` but in one of its children (selected automatically, i.e. a first empty child element). | ||
*/ | ||
export declare function enablePlaceholder({ view, element, text, isDirectHost, keepOnFocus }: { | ||
export declare function enablePlaceholder({ view, element, isDirectHost, keepOnFocus }: { | ||
view: View; | ||
element: Element; | ||
text: string; | ||
element: PlaceholderableElement | EditableElement; | ||
isDirectHost?: boolean; | ||
@@ -90,1 +89,10 @@ keepOnFocus?: boolean; | ||
export declare function needsPlaceholder(element: Element, keepOnFocus: boolean): boolean; | ||
/** | ||
* Element that could have a placeholder. | ||
*/ | ||
export interface PlaceholderableElement extends Element { | ||
/** | ||
* The text of element's placeholder. | ||
*/ | ||
placeholder?: string; | ||
} |
@@ -15,3 +15,3 @@ /** | ||
* | ||
* To change the placeholder text, simply call this method again with new options. | ||
* To change the placeholder text, change value of the `placeholder` property in the provided `element`. | ||
* | ||
@@ -23,3 +23,2 @@ * To disable the placeholder, use {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} helper. | ||
* @param options.element Element that will gain a placeholder. See `options.isDirectHost` to learn more. | ||
* @param options.text Placeholder text. | ||
* @param options.isDirectHost If set `false`, the placeholder will not be enabled directly | ||
@@ -31,3 +30,3 @@ * in the passed `element` but in one of its children (selected automatically, i.e. a first empty child element). | ||
*/ | ||
export function enablePlaceholder({ view, element, text, isDirectHost = true, keepOnFocus = false }) { | ||
export function enablePlaceholder({ view, element, isDirectHost = true, keepOnFocus = false }) { | ||
const doc = view.document; | ||
@@ -45,11 +44,21 @@ // Use a single a single post fixer per—document to update all placeholders. | ||
} | ||
// Store information about the element placeholder under its document. | ||
documentPlaceholders.get(doc).set(element, { | ||
text, | ||
isDirectHost, | ||
keepOnFocus, | ||
hostElement: isDirectHost ? element : null | ||
}); | ||
// Update the placeholders right away. | ||
view.change(writer => updateDocumentPlaceholders(doc, writer)); | ||
if (element.is('editableElement')) { | ||
element.on('change:placeholder', (evtInfo, evt, text) => { | ||
setPlaceholder(text); | ||
}); | ||
} | ||
if (element.placeholder) { | ||
setPlaceholder(element.placeholder); | ||
} | ||
function setPlaceholder(text) { | ||
// Store information about the element placeholder under its document. | ||
documentPlaceholders.get(doc).set(element, { | ||
text, | ||
isDirectHost, | ||
keepOnFocus, | ||
hostElement: isDirectHost ? element : null | ||
}); | ||
// Update the placeholders right away. | ||
view.change(writer => updateDocumentPlaceholders(doc, writer)); | ||
} | ||
} | ||
@@ -56,0 +65,0 @@ /** |
@@ -20,2 +20,11 @@ /** | ||
import type Item from './item'; | ||
import KeyObserver from './observer/keyobserver'; | ||
import FakeSelectionObserver from './observer/fakeselectionobserver'; | ||
import MutationObserver from './observer/mutationobserver'; | ||
import SelectionObserver from './observer/selectionobserver'; | ||
import FocusObserver from './observer/focusobserver'; | ||
import CompositionObserver from './observer/compositionobserver'; | ||
import InputObserver from './observer/inputobserver'; | ||
import ArrowKeysObserver from './observer/arrowkeysobserver'; | ||
import TabObserver from './observer/tabobserver'; | ||
type IfTrue<T> = T extends true ? true : never; | ||
@@ -172,10 +181,4 @@ type DomRange = globalThis.Range; | ||
addObserver(ObserverConstructor: ObserverConstructor): Observer; | ||
getObserver<T extends ObserverConstructor>(ObserverConstructor: T): T extends AlwaysRegisteredObservers ? InstanceType<T> : InstanceType<T> | undefined; | ||
/** | ||
* Returns observer of the given type or `undefined` if such observer has not been added yet. | ||
* | ||
* @param ObserverConstructor The constructor of an observer to get. | ||
* @returns Observer instance or undefined. | ||
*/ | ||
getObserver<T extends ObserverConstructor>(ObserverConstructor: T): InstanceType<T> | undefined; | ||
/** | ||
* Disables all added observers. | ||
@@ -482,2 +485,6 @@ */ | ||
}; | ||
/** | ||
* Observers that are always registered. | ||
*/ | ||
export type AlwaysRegisteredObservers = typeof MutationObserver | typeof FocusObserver | typeof SelectionObserver | typeof KeyObserver | typeof FakeSelectionObserver | typeof CompositionObserver | typeof ArrowKeysObserver | typeof InputObserver | typeof TabObserver; | ||
export {}; |
@@ -107,2 +107,3 @@ /** | ||
// Add default observers. | ||
// Make sure that this list matches AlwaysRegisteredObservers type. | ||
this.addObserver(MutationObserver); | ||
@@ -109,0 +110,0 @@ this.addObserver(FocusObserver); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2835679
62955
+ Added@ckeditor/ckeditor5-utils@0.0.0-nightly-20230727.0(transitive)
- Removed@ckeditor/ckeditor5-utils@0.0.0-nightly-20230726.0(transitive)