ckeditor / ckeditor5

Powerful rich text editor framework with a modular architecture, modern integrations, and features like collaborative editing.
https://ckeditor.com/ckeditor-5
Other
9.34k stars 3.68k forks source link

Paragraphs with lots of child tags very slow to edit #15233

Open DEfusion opened 10 months ago

DEfusion commented 10 months ago

📝 Provide detailed reproduction steps (if any)

We have users that are creating paragraphs with lots of child tags, usually <a> and <strong>, sometimes separated by <br> tags for tighter spacing. This results in CKEditor being very slow to type into.

This can be replicated by pasting this gist into the source demo https://ckeditor.com/ckeditor-5/demo/html-support/

✔️ Expected result

What is the expected result of the above steps?

Being able to type text without it being slow.

❌ Actual result

What is the actual result of the above steps?

https://github.com/ckeditor/ckeditor5/assets/117200/9177ec67-6000-47a7-b1b2-a2d66b1a61a9

📃 Other details


If you'd like to see this fixed sooner, add a 👍 reaction to this post.

Witoso commented 10 months ago

Hi!

We have users that are creating paragraphs with lots of child tags

In the example you've sent, it's actually one big paragraph (br's are not creating new paragraphs). Our internal model representation:

@niegowski I remember a similar case but not the conclusions? WDYT?

niegowski commented 8 months ago

I was able to reproduce the same issue without GHS, only a simple plugin:

function SpanPlugin( editor ) {
    editor.model.schema.extend( '$text', { allowAttributes: 'span' } );
    editor.conversion.attributeToElement( { model: 'span', view: 'span' } );
}

and it takes a lot of time to process such content:

<p>
    <span>CKEditor</span> <span>5</span> <span>is</span> <span>a</span> <span>project</span> <span>that</span>
    <span>allows</span> <span>you</span>
    <span>to</span> <span>quickly</span> <span>and</span> <span>easily</span> <span>initialize</span> <span>one</span> <span>of</span>
    <span>the</span> <span>many</span> <span>types</span> <span>of</span> <span>editors</span> <span>it</span> <span>offers</span>
    <span>in</span> <span>your</span> <span>application.</span> <span>At</span> <span>the</span> <span>same</span> <span>time,</span>
    <span>it</span> <span>is</span> <span>a</span> <span>framework</span> <span>for</span> <span>creating</span>
    <span>custom-tailored</span> <span>rich-text</span> <span>editing</span> <span>solutions.</span> <span>The</span>
    <span>former</span> <span>requirement</span> <span>is</span> <span>met</span> <span>thanks</span> <span>to</span> <span>the</span>
    <span>predefined</span> <span>CKEditor</span> <span>5</span> <span>builds.</span> <span>The</span> <span>latter</span>
    <span>–</span> <span>thanks</span> <span>to</span> <span>CKEditor</span> <span>5</span> <span>Framework.</span>
    <span>CKEditor</span> <span>5</span> <span>Framework</span> <span>is</span> <span>a</span> <span>highly-flexible</span>
    <span>and</span> <span>universal</span> <span>platform</span> <span>that</span> <span>provides</span> <span>a</span>
    <span>set</span> <span>of</span> <span>components</span> <span>allowing</span> <span>you</span> <span>to</span> <span>create</span>
    <span>any</span> <span>kind</span> <span>of</span> <span>rich</span> <span>text</span> <span>editing</span> <span>solution.</span>
    <span>It</span> <span>enables</span> <span>the</span> <span>building</span> <span>of</span> <span>different,</span>
    <span>custom-tailored</span>
    <span>editors</span> <span>that</span> <span>suit</span> <span>specific</span> <span>needs.</span> <span>It</span> <span>also</span>
    <span>provides</span> <span>tools</span> <span>for</span> <span>the</span> <span>creation</span> <span>and</span>
    <span>integration</span> <span>of</span> <span>user-made</span> <span>features</span> <span>and</span> <span>for</span>
    <span>customizing</span>
    <span>existing</span> <span>ones.</span> <span>This</span> <span>guide</span> <span>explains</span> <span>how</span>
    <span>the</span> <span>framework</span> <span>is</span> <span>built</span> <span>and</span> <span>how</span> <span>to</span>
    <span>start</span>
    <span>using</span> <span>it.</span> <span>Please</span> <span>note</span> <span>that</span> <span>the</span> <span>CKEditor</span>
    <span>5</span> <span>Framework</span> <span>documentation</span> <span>is</span> <span>constantly</span> <span>updated</span>
    <span>and</span>
    <span>expanded,</span> <span>but</span> <span>it</span> <span>may</span> <span>still</span> <span>be</span> <span>lacking</span>
    <span>some</span> <span>things.</span> <span>Feel</span> <span>free</span> <span>to</span> <span>suggest</span>
    <span>documentation</span> <span>enhancements</span> <span>and</span> <span>share</span> <span>your</span> <span>feedback</span>
    <span>about</span> <span>the</span> <span>framework.</span> <span>If</span> <span>the</span> <span>documentation</span>
    <span>is</span> <span>insufficient,</span> <span>do</span> <span>not</span> <span>be</span> <span>afraid</span> <span>to</span>
    <span>look</span> <span>into</span> <span>the</span> <span>source</span> <span>code</span> <span>of</span> <span>CKEditor</span>
    <span>5</span> <span>packages.</span> <span>For</span> <span>example,</span> <span>if</span> <span>you</span> <span>plan</span>
    <span>to</span> <span>create</span> <span>a</span> <span>new</span> <span>feature,</span> <span>check</span> <span>if</span>
    <span>a</span> <span>similar</span> <span>one</span> <span>already</span> <span>exists</span> <span>and</span> <span>try</span>
    <span>to</span> <span>take</span> <span>inspiration</span> <span>from</span> <span>its</span> <span>source</span> <span>code.</span>
    <span>When</span> <span>to</span> <span>use</span> <span>the</span> <span>framework?</span> <span>The</span> <span>CKEditor</span>
    <span>5</span> <span>predefined</span> <span>builds</span> <span>can</span> <span>be</span> <span>customized,</span>
    <span>but</span> <span>certain</span> <span>types</span> <span>of</span> <span>customizations</span> <span>require</span>
    <span>using</span>
    <span>the</span> <span>framework.</span> <span>Writing</span> <span>your</span> <span>own</span> <span>features.</span>
    <span>New</span> <span>features</span> <span>are</span> <span>implemented</span> <span>using</span> <span>the</span>
    <span>framework.</span>
    <span>Customizing</span> <span>existing</span> <span>features.</span> <span>Changing</span> <span>the</span> <span>behavior</span>
    <span>or</span> <span>look</span> <span>of</span> <span>existing</span> <span>features</span> <span>can</span> <span>be</span>
    <span>done</span> <span>thanks</span> <span>to</span> <span>the</span> <span>framework’s</span> <span>capabilities.</span>
    <span>Creating</span>
    <span>new</span> <span>types</span> <span>of</span> <span>editors.</span> <span>You</span> <span>can</span> <span>create</span>
    <span>new</span> <span>editor</span> <span>types</span> <span>using</span> <span>the</span> <span>framework.</span> <span>To</span>
    <span>sum</span> <span>up:</span> <span>you</span> <span>need</span> <span>to</span> <span>start</span> <span>using</span>
    <span>the</span> <span>framework</span> <span>as</span> <span>soon</span> <span>as</span> <span>existing</span> <span>builds</span>
    <span>do</span> <span>not</span> <span>meet</span> <span>your</span> <span>requirements</span> <span>or</span> <span>cannot</span>
    <span>be</span> <span>customized</span> <span>to</span> <span>the</span> <span>extent</span> <span>you</span> <span>need.</span>
    <span>Design</span> <span>The</span> <span>framework</span> <span>was</span> <span>designed</span> <span>to</span> <span>be</span>
    <span>a</span> <span>highly</span> <span>flexible</span> <span>and</span> <span>universal</span> <span>platform</span>
    <span>for</span> <span>creating</span> <span>custom</span> <span>rich-text</span> <span>editing</span> <span>solutions.</span>
    <span>At</span> <span>the</span> <span>same</span> <span>time,</span> <span>it</span> <span>meets</span> <span>several</span>
    <span>goals</span>
    <span>that</span> <span>make</span> <span>implementing</span> <span>features</span> <span>as</span> <span>easy</span> <span>a</span>
    <span>task</span> <span>as</span> <span>possible.</span> <span>Plugin-based</span> <span>architecture.</span>
    <span>Everything</span> <span>is</span> <span>a</span> <span>plugin</span> <span>–</span> <span>even</span> <span>such</span>
    <span>crucial</span>
    <span>features</span> <span>as</span> <span>support</span> <span>for</span> <span>typing</span> <span>or</span>
    <span>elements.</span> <span>You</span> <span>can</span> <span>remove</span> <span>plugins</span> <span>or</span>
    <span>replace</span> <span>them</span> <span>with</span> <span>your</span> <span>own</span> <span>implementations</span>
    <span>to</span> <span>achieve</span> <span>fully</span> <span>customized</span> <span>results.</span> <span>Schema-less</span>
    <span>core.</span> <span>The</span> <span>core</span> <span>makes</span> <span>minimal</span> <span>assumptions</span>
    <span>and</span> <span>can</span> <span>be</span> <span>controlled</span> <span>through</span> <span>the</span> <span>schema.</span>
    <span>This</span> <span>leaves</span> <span>all</span> <span>decisions</span> <span>to</span> <span>plugins</span> <span>and</span>
    <span>hence</span> <span>to</span> <span>you.</span> <span>Collaboration-ready.</span> <span>Or</span> <span>rather,</span>
    <span>real-time</span>
    <span>collaboration</span> <span>is</span> <span>ready</span> <span>for</span> <span>you</span> <span>to</span> <span>use!</span>
    <span>The</span> <span>editor</span> <span>implements</span> <span>Operational</span> <span>Transformation</span> <span>for</span>
    <span>the</span> <span>tree-structured</span> <span>model</span> <span>as</span> <span>well</span> <span>as</span> <span>many</span>
    <span>other</span> <span>mechanisms</span> <span>which</span> <span>were</span> <span>required</span> <span>to</span>
    <span>create</span> <span>a</span> <span>seamless</span> <span>collaborative</span> <span>UX.</span> <span>Additionally,</span>
    <span>we</span> <span>provide</span> <span>cloud</span> <span>infrastructure</span> <span>and</span> <span>plugins</span>
    <span>enabling</span>
    <span>real-time</span> <span>collaborative</span> <span>editing</span> <span>in</span> <span>your</span> <span>application!</span>
    <span>Check</span> <span>the</span> <span>collaboration</span> <span>demo.</span> <span>Custom</span> <span>data</span>
    <span>model.</span> <span>The</span> <span>editing</span> <span>engine</span> <span>implements</span> <span>a</span>
    <span>tree-structured</span>
    <span>custom</span> <span>data</span> <span>model,</span> <span>designed</span> <span>to</span> <span>fit</span>
    <span>multiple</span> <span>requirements</span> <span>such</span> <span>as</span> <span>enabling</span> <span>real-time</span>
    <span>collaboration</span> <span>and</span> <span>complex</span> <span>editing</span> <span>features</span> <span>(like</span>
    <span>tables</span> <span>or</span> <span>nested</span> <span>blocks).</span> <span>Virtual</span> <span>DOM.</span>
    <span>The</span> <span>editing</span> <span>engine</span> <span>features</span> <span>a</span> <span>custom,</span>
    <span>editing-oriented</span>
    <span>virtual</span> <span>DOM</span> <span>implementation</span> <span>that</span> <span>aims</span> <span>to</span>
    <span>hide</span> <span>browser</span> <span>quirks</span> <span>from</span> <span>your</span> <span>sight.</span> <span>No</span>
    <span>more</span> <span>contentEditable</span> <span>nightmares!</span> <span>TypeScript.</span> <span>The</span>
    <span>project</span> <span>is</span> <span>written</span> <span>in</span> <span>TypeScript</span> <span>and</span>
    <span>provides</span> <span>native</span> <span>type</span> <span>definitions.</span> <span>This</span> <span>helps</span>
    <span>create</span>
    <span>better,</span> <span>more</span> <span>reliable</span> <span>code</span> <span>that</span> <span>is</span> <span>easier</span>
    <span>to</span> <span>understand</span> <span>and</span> <span>maintain.</span> <span>Granular,</span> <span>reusable</span>
    <span>features.</span>
    <span>Features</span> <span>are</span> <span>implemented</span> <span>in</span> <span>a</span> <span>granular</span>
    <span>way.</span> <span>This</span> <span>allows</span> <span>for</span> <span>reusing</span> <span>and</span>
    <span>recomposing</span> <span>them</span> <span>which,</span> <span>in</span> <span>turn,</span> <span>makes</span> <span>it</span>
    <span>possible</span> <span>to</span> <span>customize</span> <span>and</span> <span>extend</span> <span>the</span>
    <span>editor.</span> <span>For</span> <span>instance,</span> <span>the</span> <span>image</span> <span>feature</span>
    <span>consists</span> <span>of</span> <span>over</span> <span>10</span> <span>plugins</span> <span>at</span> <span>the</span>
    <span>moment.</span>
    <span>Extensibility.</span> <span>The</span> <span>entire</span> <span>editor</span> <span>architecture</span> <span>was</span>
    <span>designed</span> <span>for</span> <span>maximum</span> <span>flexibility.</span> <span>The</span> <span>code</span>
    <span>is</span> <span>event-based</span> <span>and</span> <span>highly</span> <span>decoupled,</span> <span>allowing</span>
    <span>you</span>
    <span>to</span> <span>plug</span> <span>in</span> <span>or</span> <span>replace</span> <span>selected</span> <span>pieces.</span>
    <span>Features</span> <span>do</span> <span>not</span> <span>directly</span> <span>depend</span> <span>on</span> <span>one</span>
    <span>another</span> <span>and</span> <span>communicate</span> <span>in</span> <span>standardized</span> <span>ways.</span>
    <span>A</span> <span>beautiful</span> <span>UI.</span> <span>Text</span> <span>editing</span> <span>is</span> <span>not</span>
    <span>only</span> <span>about</span> <span>typing</span> <span>–</span> <span>your</span> <span>users</span> <span>will</span>
    <span>need</span> <span>a</span> <span>UI</span> <span>to</span> <span>create</span> <span>links</span> <span>or</span>
    <span>manage</span> <span>images.</span> <span>We</span> <span>believe</span> <span>that</span> <span>a</span> <span>proper</span>
    <span>UX</span> <span>needs</span> <span>to</span> <span>be</span> <span>carefully</span> <span>designed</span> <span>and</span>
    <span>we</span> <span>did</span> <span>not</span> <span>skip</span> <span>this</span> <span>part.</span> <span>Having</span>
    <span>second</span>
    <span>thoughts</span> <span>about</span> <span>the</span> <span>proposed</span> <span>UI?</span> <span>No</span>
    <span>problem</span> <span>at</span> <span>all!</span> <span>You</span> <span>can</span> <span>always</span> <span>create</span>
    <span>your</span> <span>custom</span> <span>interface</span> <span>for</span> <span>CKEditor</span> <span>5</span>
    <span>thanks</span> <span>to</span> <span>its</span> <span>decoupled</span> <span>UI.</span> <span>Quality.</span> <span>All</span>
    <span>official</span> <span>packages</span> <span>have</span> <span>extensive</span> <span>test</span> <span>suites</span>
    <span>(100%</span>
    <span>code</span> <span>coverage</span> <span>is</span> <span>merely</span> <span>a</span> <span>step</span> <span>to</span>
    <span>that).</span>
    <span>All</span> <span>code</span> <span>has</span> <span>extensive</span> <span>API</span> <span>documentation.</span>
    <span>Minimal</span>
    <span>configuration.</span> <span>To</span> <span>avoid</span> <span>bloat,</span> <span>features</span> <span>have</span>
    <span>minimal</span>
    <span>configuration.</span> <span>Deeper</span> <span>changes</span> <span>in</span> <span>their</span> <span>behavior</span>
    <span>can</span>
    <span>be</span> <span>done</span> <span>by</span> <span>recomposing</span> <span>them</span> <span>with</span> <span>custom</span>
    <span>features.</span> <span>8+</span> <span>years</span> <span>of</span> <span>support.</span> <span>It</span> <span>is</span>
    <span>not</span> <span>yet</span> <span>another</span> <span>framework</span> <span>to</span> <span>be</span> <span>gone</span>
    <span>next</span> <span>year</span> <span>or</span> <span>a</span> <span>hyped</span> <span>proof-of-concept</span> <span>to</span>
    <span>fail</span> <span>in</span> <span>a</span> <span>real-life</span> <span>scenario.</span> <span>We</span> <span>have</span>
    <span>over</span> <span>20</span> <span>years</span> <span>of</span> <span>experience</span> <span>in</span> <span>creating</span>
    <span>rich-text</span> <span>editors</span> <span>and</span> <span>continue</span> <span>working</span> <span>day</span>
    <span>in</span> <span>and</span> <span>day</span> <span>out</span> <span>on</span> <span>improving</span> <span>your</span>
    <span>future-proof</span>
    <span>rich-text</span> <span>editor</span> <span>of</span> <span>choice.</span> <span>Overview</span> <span>The</span>
    <span>editing</span> <span>engine</span> <span>implements</span> <span>an</span> <span>MVC</span> <span>architecture.</span>
    <span>The</span>
    <span>shape</span> <span>of</span> <span>it</span> <span>is</span> <span>not</span> <span>enforced</span> <span>by</span>
    <span>the</span> <span>engine</span> <span>itself</span> <span>but</span> <span>in</span> <span>most</span>
    <span>implementations</span> <span>it</span> <span>can</span> <span>be</span> <span>described</span> <span>by</span>
    <span>this</span> <span>diagram:</span> <span>What</span> <span>you</span> <span>can</span> <span>see,</span> <span>are</span>
    <span>three</span> <span>layers:</span> <span>model,</span> <span>controller</span> <span>and</span> <span>view.</span>
    <span>There</span> <span>is</span> <span>one</span> <span>model</span> <span>document</span> <span>which</span> <span>is</span>
    <span>converted</span> <span>into</span> <span>separate</span> <span>views</span> <span>–</span> <span>the</span>
    <span>editing</span> <span>view</span> <span>and</span> <span>the</span> <span>data</span> <span>view.</span> <span>These</span>
    <span>two</span> <span>views</span> <span>represent,</span> <span>respectively,</span> <span>the</span> <span>content</span>
    <span>that</span>
    <span>the</span> <span>user</span> <span>is</span> <span>editing</span> <span>(the</span> <span>DOM</span> <span>structure</span>
    <span>that</span> <span>you</span> <span>see</span> <span>in</span> <span>the</span> <span>browser)</span> <span>and</span>
    <span>the</span>
    <span>editor</span> <span>input</span> <span>and</span> <span>output</span> <span>data</span> <span>(in</span> <span>a</span>
    <span>format</span>
    <span>that</span> <span>the</span> <span>plugged</span> <span>data</span> <span>processor</span> <span>understands).</span>
    <span>Both</span>
    <span>views</span> <span>feature</span> <span>virtual</span> <span>DOM</span> <span>structures</span> <span>(custom,</span>
    <span>DOM-like</span>
    <span>structures)</span> <span>on</span> <span>which</span> <span>converters</span> <span>and</span> <span>features</span>
    <span>work</span>
    <span>and</span> <span>which</span> <span>are</span> <span>then</span> <span>rendered</span> <span>to</span> <span>the</span>
    <span>DOM.</span>
    <span>The</span> <span>green</span> <span>blocks</span> <span>are</span> <span>the</span> <span>code</span> <span>introduced</span>
    <span>by</span> <span>editor</span> <span>features</span> <span>(plugins).</span> <span>These</span> <span>features</span>
    <span>control</span>
    <span>what</span> <span>changes</span> <span>are</span> <span>made</span> <span>to</span> <span>the</span> <span>model,</span>
    <span>how</span> <span>they</span> <span>are</span> <span>converted</span> <span>to</span> <span>the</span> <span>view</span>
    <span>and</span>
    <span>how</span> <span>the</span> <span>model</span> <span>needs</span> <span>to</span> <span>be</span> <span>changed</span>
    <span>based</span>
    <span>on</span> <span>fired</span> <span>events</span> <span>(the</span> <span>view’s</span> <span>and</span> <span>model’s</span>
    <span>ones).</span> <span>Let’s</span> <span>now</span> <span>talk</span> <span>about</span> <span>each</span> <span>layer</span>
    <span>separately.</span> <span>Model</span> <span>The</span> <span>model</span> <span>is</span> <span>implemented</span>
    <span>by</span> <span>a</span> <span>DOM-like</span> <span>tree</span> <span>structure</span> <span>of</span> <span>elements</span>
    <span>and</span> <span>text</span> <span>nodes.</span> <span>Unlike</span> <span>in</span> <span>the</span> <span>actual</span>
    <span>DOM,</span> <span>in</span> <span>the</span> <span>model,</span> <span>both</span> <span>elements</span> <span>and</span>
    <span>text</span> <span>nodes</span> <span>can</span> <span>have</span> <span>attributes.</span> <span>Like</span> <span>in</span>
    <span>the</span> <span>DOM,</span> <span>the</span> <span>model</span> <span>structure</span> <span>is</span> <span>contained</span>
    <span>within</span> <span>a</span> <span>document</span> <span>that</span> <span>contains</span> <span>root</span>
    <span>elements</span> <span>(the</span> <span>model,</span> <span>as</span> <span>well</span> <span>as</span> <span>the</span>
    <span>view,</span> <span>may</span> <span>have</span> <span>multiple</span> <span>roots).</span> <span>The</span>
    <span>document</span> <span>also</span> <span>holds</span> <span>its</span> <span>selection</span> <span>and</span> <span>the</span>
    <span>history</span> <span>of</span> <span>its</span> <span>changes.</span> <span>Finally,</span> <span>the</span>
    <span>document,</span> <span>its</span> <span>schema</span> <span>and</span> <span>document</span> <span>markers</span>
    <span>are</span> <span>properties</span> <span>of</span> <span>the</span> <span>Model.</span> <span>An</span> <span>instance</span>
    <span>of</span> <span>the</span> <span>Model</span> <span>class</span> <span>is</span> <span>available</span> <span>in</span>
    <span>the</span>
    <span>editor.model</span> <span>property.</span> <span>The</span> <span>model,</span> <span>besides</span> <span>holding</span>
    <span>the</span> <span>properties</span> <span>described</span> <span>above,</span> <span>provides</span> <span>the</span>
    <span>API</span> <span>for</span> <span>changing</span> <span>the</span> <span>document</span> <span>and</span> <span>its</span>
    <span>markers,</span> <span>too.</span> <span>Selection</span> <span>attributes</span> <span>OK,</span> <span>but</span>
    <span>how</span> <span>to</span> <span>let</span> <span>CKEditor</span> <span>5</span> <span>know</span> <span>that</span>
    <span>I</span> <span>want</span> <span>the</span> <span>selection</span> <span>to</span> <span>“be</span> <span>bold”</span>
    <span>in</span>
    <span>the</span> <span>case</span> <span>described</span> <span>above?</span> <span>This</span> <span>is</span>
    <span>important</span> <span>information</span> <span>because</span> <span>it</span> <span>affects</span> <span>whether</span>
    <span>or</span> <span>not</span> <span>the</span> <span>typed</span> <span>text</span> <span>will</span> <span>be</span>
    <span>bold,</span> <span>too.</span> <span>To</span> <span>handle</span> <span>that,</span> <span>the</span> <span>selection</span>
    <span>also</span> <span>has</span> <span>attributes.</span> <span>If</span> <span>the</span> <span>selection</span> <span>is</span>
    <span>placed</span> <span>in</span> <span>"Foo</span> <span>^bar"</span> <span>and</span> <span>it</span> <span>has</span>
    <span>the</span> <span>attribute</span> <span>bold=true,</span> <span>you</span> <span>know</span> <span>that</span>
    <span>the</span> <span>user</span> <span>will</span> <span>type</span> <span>bold</span> <span>text.</span> <span>Indexes</span>
    <span>and</span> <span>offsets</span> <span>However,</span> <span>it</span> <span>has</span> <span>just</span> <span>been</span>
    <span>said</span> <span>that</span> <span>inside</span> <span>paragraph</span> <span>there</span> <span>are</span> <span>two</span>
    <span>text</span> <span>nodes:</span> <span>"Foo</span> <span>"</span> <span>and</span> <span>"bar".</span> <span>If</span>
    <span>you</span>
    <span>know</span> <span>how</span> <span>native</span> <span>DOM</span> <span>Ranges</span> <span>work</span> <span>you</span>
    <span>might</span> <span>thus</span> <span>ask:</span> <span>“But</span> <span>if</span> <span>the</span> <span>selection</span>
    <span>is</span> <span>at</span> <span>the</span> <span>boundary</span> <span>of</span> <span>two</span> <span>text</span>
    <span>nodes,</span>
    <span>is</span> <span>it</span> <span>anchored</span> <span>in</span> <span>the</span> <span>left</span> <span>one,</span>
    <span>the</span> <span>right</span> <span>one,</span> <span>or</span> <span>in</span> <span>the</span> <span>containing</span>
    <span>element?”</span> <span>This</span> <span>is,</span> <span>indeed,</span> <span>another</span> <span>problem</span>
    <span>with</span> <span>DOM</span> <span>APIs.</span> <span>Not</span> <span>only</span> <span>can</span> <span>positions</span>
    <span>outside</span> <span>and</span> <span>inside</span> <span>some</span> <span>element</span> <span>be</span>
    <span>identical</span> <span>visually</span> <span>but</span> <span>also</span> <span>they</span> <span>can</span> <span>be</span>
    <span>anchored</span> <span>inside</span> <span>or</span> <span>outside</span> <span>a</span> <span>text</span> <span>node</span>
    <span>(if</span> <span>the</span> <span>position</span> <span>is</span> <span>at</span> <span>a</span> <span>text</span>
    <span>node</span> <span>boundary).</span> <span>This</span> <span>all</span> <span>creates</span> <span>extreme</span>
    <span>complications</span>
    <span>when</span> <span>implementing</span> <span>editing</span> <span>algorithms.</span> <span>To</span> <span>avoid</span>
    <span>such</span>
    <span>troubles,</span> <span>and</span> <span>to</span> <span>make</span> <span>collaborative</span> <span>editing</span>
    <span>possible</span>
    <span>for</span> <span>real,</span> <span>CKEditor</span> <span>5</span> <span>uses</span> <span>the</span> <span>concepts</span>
    <span>of</span> <span>indexes</span> <span>and</span> <span>offsets.</span> <span>Indexes</span> <span>relate</span> <span>to</span>
    <span>nodes</span> <span>(elements</span> <span>and</span> <span>text</span> <span>nodes)</span> <span>while</span>
    <span>offsets</span> <span>relate</span> <span>to</span> <span>positions.</span> <span>For</span> <span>example,</span>
    <span>in</span> <span>the</span> <span>following</span> <span>structure:</span> <span>Positions,</span> <span>ranges</span>
    <span>and</span>
    <span>selections</span> <span>The</span> <span>engine</span> <span>also</span> <span>defines</span> <span>three</span>
    <span>levels</span> <span>of</span> <span>classes</span> <span>that</span> <span>operate</span> <span>on</span>
    <span>offsets:</span> <span>A</span> <span>Position</span> <span>instance</span> <span>contains</span> <span>an</span>
    <span>array</span> <span>of</span> <span>offsets</span> <span>(which</span> <span>is</span> <span>called</span> <span>a</span>
    <span>“path”).</span> <span>See</span> <span>the</span> <span>examples</span> <span>in</span> <span>the</span>
    <span>Position#path</span> <span>API</span> <span>documentation</span> <span>to</span> <span>better</span> <span>understand</span>
    <span>how</span> <span>paths</span> <span>work.</span> <span>A</span> <span>Range</span> <span>contains</span> <span>two</span>
    <span>positions:</span> <span>start</span> <span>and</span> <span>end</span> <span>ones.</span> <span>Finally,</span>
    <span>there</span> <span>is</span> <span>a</span> <span>Selection</span> <span>which</span> <span>contains</span> <span>one</span>
    <span>or</span> <span>more</span> <span>ranges,</span> <span>attributes,</span> <span>and</span> <span>has</span> <span>a</span>
    <span>direction</span> <span>(whether</span> <span>it</span> <span>was</span> <span>done</span> <span>from</span> <span>left</span>
    <span>to</span> <span>right</span> <span>or</span> <span>right</span> <span>to</span> <span>left).</span> <span>You</span>
    <span>can</span> <span>make</span> <span>as</span> <span>many</span> <span>instances</span> <span>of</span> <span>it</span>
    <span>as</span> <span>you</span> <span>need</span> <span>and</span> <span>you</span> <span>can</span> <span>freely</span>
    <span>modify</span>
    <span>it</span> <span>whenever</span> <span>you</span> <span>want.</span> <span>Additionally,</span> <span>there</span>
    <span>is</span> <span>a</span> <span>single</span> <span>DocumentSelection.</span> <span>It</span> <span>represents</span>
    <span>the</span> <span>document’s</span> <span>selection</span> <span>and</span> <span>can</span> <span>only</span> <span>be</span>
    <span>changed</span> <span>through</span> <span>the</span> <span>model</span> <span>writer.</span> <span>It</span> <span>is</span>
    <span>automatically</span> <span>updated</span> <span>when</span> <span>the</span> <span>document’s</span> <span>structure</span>
    <span>is</span> <span>changed.</span> <span>Markers</span> <span>Markers</span> <span>are</span> <span>a</span> <span>special</span>
    <span>type</span> <span>of</span> <span>ranges.</span> <span>They</span> <span>are</span> <span>managed</span> <span>by</span>
    <span>MarkerCollection.</span> <span>They</span> <span>can</span> <span>only</span> <span>be</span> <span>created</span>
    <span>and</span> <span>changed</span> <span>through</span> <span>the</span> <span>model</span> <span>writer.</span>
    <span>They</span> <span>can</span> <span>be</span> <span>synchronized</span> <span>over</span> <span>the</span> <span>network</span>
    <span>with</span> <span>other</span> <span>collaborating</span> <span>clients.</span> <span>They</span> <span>are</span>
    <span>automatically</span>
    <span>updated</span> <span>when</span> <span>the</span> <span>document’s</span> <span>structure</span> <span>is</span>
    <span>changed.</span>
    <span>They</span> <span>can</span> <span>be</span> <span>converted</span> <span>to</span> <span>the</span> <span>editing</span>
    <span>view</span> <span>to</span> <span>show</span> <span>them</span> <span>in</span> <span>the</span> <span>editor</span>
    <span>(as</span> <span>highlights</span> <span>or</span> <span>elements).</span> <span>They</span> <span>can</span> <span>be</span>
    <span>converted</span> <span>to</span> <span>the</span> <span>data</span> <span>view</span> <span>to</span> <span>store</span>
    <span>them</span> <span>with</span> <span>the</span> <span>document</span> <span>data.</span> <span>They</span> <span>can</span>
    <span>be</span> <span>loaded</span> <span>with</span> <span>the</span> <span>document</span> <span>data.</span> <span>Markers</span>
    <span>are</span> <span>perfect</span> <span>for</span> <span>storing</span> <span>and</span> <span>maintaining</span>
    <span>additional</span>
    <span>data</span> <span>related</span> <span>to</span> <span>portions</span> <span>of</span> <span>the</span> <span>document</span>
    <span>such</span> <span>as</span> <span>comments</span> <span>or</span> <span>selections</span> <span>of</span> <span>other</span>
    <span>users.</span> <span>Schema</span> <span>The</span> <span>model’s</span> <span>schema</span> <span>defines</span>
    <span>several</span> <span>aspects</span> <span>of</span> <span>how</span> <span>the</span> <span>model</span> <span>should</span>
    <span>look:</span> <span>Where</span> <span>a</span> <span>node</span> <span>is</span> <span>allowed</span> <span>or</span>
    <span>disallowed.</span>
    <span>For</span> <span>example,</span> <span>paragraph</span> <span>is</span> <span>allowed</span> <span>in</span>
    <span>$root,</span> <span>but</span> <span>not</span> <span>in</span> <span>heading1.</span> <span>What</span>
    <span>attributes</span> <span>are</span> <span>allowed</span> <span>for</span> <span>a</span> <span>certain</span>
    <span>node.</span> <span>For</span> <span>example,</span> <span>image</span> <span>can</span> <span>have</span> <span>the</span>
    <span>src</span> <span>and</span> <span>alt</span> <span>attributes.</span> <span>Additional</span> <span>semantics</span>
    <span>of</span> <span>model</span> <span>nodes.</span> <span>For</span> <span>example,</span> <span>image</span> <span>is</span>
    <span>of</span> <span>the</span> <span>“object”</span> <span>type</span> <span>and</span> <span>paragraph</span> <span>of</span>
    <span>the</span> <span>“block”</span> <span>type.</span> <span>This</span> <span>information</span> <span>is</span>
    <span>then</span> <span>used</span> <span>by</span> <span>the</span> <span>features</span> <span>and</span> <span>the</span>
    <span>engine</span>
    <span>to</span> <span>make</span> <span>decisions</span> <span>on</span> <span>how</span> <span>to</span> <span>process</span>
    <span>the</span> <span>model.</span> <span>For</span> <span>instance,</span> <span>the</span> <span>information</span>
    <span>from</span> <span>the</span> <span>schema</span> <span>will</span> <span>affect:</span> <span>What</span> <span>happens</span>
    <span>with</span> <span>the</span> <span>pasted</span> <span>content</span> <span>and</span> <span>what</span> <span>is</span>
    <span>filtered</span> <span>out</span> <span>(note:</span> <span>in</span> <span>case</span> <span>of</span> <span>pasting</span>
    <span>the</span> <span>other</span> <span>important</span> <span>mechanism</span> <span>is</span> <span>the</span>
    <span>conversion.</span> <span>HTML</span> <span>elements</span> <span>and</span> <span>attributes</span> <span>which</span>
    <span>are</span>
    <span>not</span> <span>upcasted</span> <span>by</span> <span>any</span> <span>of</span> <span>the</span> <span>registered</span>
    <span>converters</span> <span>are</span> <span>filtered</span> <span>out</span> <span>before</span> <span>they</span>
    <span>even</span> <span>become</span> <span>model</span> <span>nodes,</span> <span>so</span> <span>the</span> <span>schema</span>
    <span>is</span> <span>not</span> <span>applied</span> <span>to</span> <span>them;</span> <span>the</span> <span>conversion</span>
    <span>will</span> <span>be</span> <span>covered</span> <span>later</span> <span>in</span> <span>this</span> <span>guide).</span>
    <span>To</span> <span>which</span> <span>elements</span> <span>the</span> <span>heading</span> <span>feature</span> <span>can</span>
    <span>be</span> <span>applied</span> <span>(which</span> <span>blocks</span> <span>can</span> <span>be</span> <span>turned</span>
    <span>to</span> <span>headings</span> <span>and</span> <span>which</span> <span>elements</span> <span>are</span> <span>blocks</span>
    <span>in</span> <span>the</span> <span>first</span> <span>place).</span> <span>Which</span> <span>elements</span> <span>can</span>
    <span>be</span> <span>wrapped</span> <span>with</span> <span>a</span> <span>block</span> <span>quote.</span> <span>Whether</span>
    <span>the</span> <span>bold</span> <span>button</span> <span>is</span> <span>enabled</span> <span>when</span> <span>the</span>
    <span>selection</span> <span>is</span> <span>in</span> <span>a</span> <span>heading</span> <span>(and</span> <span>whether</span>
    <span>the</span> <span>text</span> <span>in</span> <span>this</span> <span>heading</span> <span>can</span> <span>be</span>
    <span>bolded).</span>
    <span>Where</span> <span>the</span> <span>selection</span> <span>can</span> <span>be</span> <span>placed</span> <span>(which</span>
    <span>is</span> <span>–</span> <span>only</span> <span>in</span> <span>text</span> <span>nodes</span> <span>and</span>
    <span>on</span> <span>object</span> <span>elements).</span> <span>etc.</span> <span>The</span> <span>schema</span> <span>is,</span>
    <span>by</span> <span>default,</span> <span>configured</span> <span>by</span> <span>editor</span> <span>plugins.</span>
    <span>It</span> <span>is</span> <span>recommended</span> <span>that</span> <span>every</span> <span>editor</span>
    <span>feature</span> <span>comes</span> <span>with</span> <span>rules</span> <span>that</span> <span>enable</span> <span>and</span>
    <span>preconfigure</span> <span>it</span> <span>in</span> <span>the</span> <span>editor.</span> <span>This</span> <span>will</span>
    <span>make</span> <span>sure</span> <span>that</span> <span>the</span> <span>plugin</span> <span>user</span> <span>can</span>
    <span>enable</span>
    <span>it</span> <span>without</span> <span>worrying</span> <span>to</span> <span>re-configure</span> <span>their</span>
    <span>schema.</span>
    <span>Currently,</span> <span>there</span> <span>is</span> <span>no</span> <span>straightforward</span> <span>way</span>
    <span>to</span> <span>override</span> <span>the</span> <span>schema</span> <span>preconfigured</span> <span>by</span>
    <span>features.</span>
    <span>If</span> <span>you</span> <span>want</span> <span>to</span> <span>override</span> <span>the</span> <span>default</span>
    <span>settings</span> <span>when</span> <span>initializing</span> <span>the</span> <span>editor,</span> <span>the</span>
    <span>best</span> <span>solution</span> <span>is</span> <span>to</span> <span>replace</span> <span>editor.model.schema</span>
    <span>with</span>
    <span>a</span> <span>new</span> <span>instance</span> <span>of</span> <span>it.</span> <span>This,</span> <span>however,</span>
    <span>requires</span> <span>rebuilding</span> <span>the</span> <span>editor.</span> <span>The</span> <span>instance</span>
    <span>of</span> <span>the</span> <span>schema</span> <span>is</span> <span>available</span> <span>in</span>
    <span>editor.model.schema.</span>
    <span>Read</span> <span>an</span> <span>extensive</span> <span>guide</span> <span>about</span> <span>using</span> <span>the</span>
    <span>schema</span> <span>API</span> <span>in</span> <span>the</span> <span>Schema</span> <span>deep</span> <span>dive</span>
    <span>guide.</span>
</p>