Wiki source code of Default Editor Resolution
Last modified by Eleni Cojocariu on 2026/10/14 10:42
Show last authors
| author | version | line-number | content |
|---|---|---|---|
| 1 | Several editors can edit the same data. Wiki page content is edited visually by CKEditor, as wiki syntax by the Wiki editor and collaboratively by the realtime editor, and all of them are registered for the same data type. Something has to decide which one an edit request gets. | ||
| 2 | |||
| 3 | ##EditConfiguration## decides it by reading four [[configuration sources>>doc:extensions:Extension.Configuration Module]] in a fixed order and returning the first editor hint it finds. ##EditorManager## then turns that hint into an editor, with two fallbacks of its own for the case where the chain found nothing, or named something that does not exist. | ||
| 4 | |||
| 5 | {{plantuml}} | ||
| 6 | @startuml | ||
| 7 | !theme bluegray | ||
| 8 | skinparam nodesep 20 | ||
| 9 | skinparam ranksep 30 | ||
| 10 | |||
| 11 | start | ||
| 12 | :1. request parameter\nSyntaxContent.wysiwyg.editor; | ||
| 13 | :2. editor bindings\nXWiki.EditorBindingClass objects; | ||
| 14 | :3. xwiki.properties\nedit.defaultEditor keys; | ||
| 15 | :4. EditorConfiguration\nof the data type; | ||
| 16 | note right | ||
| 17 | The chain stops at the first | ||
| 18 | source that returns a value. | ||
| 19 | end note | ||
| 20 | if (a hint?) then (yes) | ||
| 21 | if (a registered editor?) then (yes) | ||
| 22 | else (no) | ||
| 23 | :retry the hint as a category; | ||
| 24 | endif | ||
| 25 | else (no) | ||
| 26 | :first editor in the category,\nelse first for the data type; | ||
| 27 | endif | ||
| 28 | :Editor; | ||
| 29 | stop | ||
| 30 | @enduml | ||
| 31 | {{/plantuml}} | ||
| 32 | |||
| 33 | == The Chain == | ||
| 34 | |||
| 35 | A request parameter overrides a user binding, a user binding overrides the wiki preferences, and anything configured at all overrides the data type's own logic. | ||
| 36 | |||
| 37 | **The request.** An editor hint can be passed as a request parameter, which is how a link opens a specific editor without any configuration being changed. The value lives only as long as the request, so this is the right level for a temporary override and the wrong one for a setting. | ||
| 38 | |||
| 39 | **The editor bindings.** The ##editorBindings/all## source reads ##XWiki.EditorBindingClass## xobjects from three places, in this order: the current user's profile, the ##WebPreferences## page of the current page's space and then of every one of its ancestor spaces, nearest first, and finally the wiki preferences. [[Configure the Default Editor>>doc:documentation.xs.dev.edit.configure-default-editor.WebHome]] is how these xobjects are added. | ||
| 40 | |||
| 41 | **##xwiki.properties##.** The ##xwikiproperties## source reads the ##edit.defaultEditor## keys of ##xwiki.properties##, the instance-wide default an administrator sets on the file system. | ||
| 42 | |||
| 43 | **The data type's own logic.** A data type can supply its own resolution logic by registering an ##EditorConfiguration## component for it. In XWiki this hook exists for backward compatibility and to supply a hard default: ##SyntaxContentEditorConfiguration## delegates to ##XDOMEditorConfiguration##, which still reads the pre-8.2 ##editor## property from the user profile and then from the page preferences, falls back to ##xwiki.editor## in ##xwiki.cfg##, lower-cases the result and defaults to ##text##. It answers the lookup made without a category and the ##text## category; asked for any other category, it returns nothing. | ||
| 44 | |||
| 45 | == The Keys == | ||
| 46 | |||
| 47 | Each source looks the editor up under its own key, built from the data type and, when the lookup has one, the category. | ||
| 48 | |||
| 49 | |=Order|=Source|=Key format|=Example | ||
| 50 | |1|##request##|##~<SimpleTypeName~>[.~<category~>].editor##|##SyntaxContent.wysiwyg.editor## | ||
| 51 | |2|##editorBindings/all##|##~<fullTypeName~>[#~<category~>]##|##org.xwiki.rendering.syntax.SyntaxContent#wysiwyg## | ||
| 52 | |3|##xwikiproperties##|##edit.defaultEditor.~<fullTypeName~>[#~<category~>]##|##edit.defaultEditor.org.xwiki.rendering.syntax.SyntaxContent#wysiwyg## | ||
| 53 | |4|##EditorConfiguration##|its own|its own | ||
| 54 | |||
| 55 | The first row is the odd one out. The request key uses the **simple** type name and separates the category with a dot, because it travels in the URL query string where length is limited and the value is temporary anyway; the name collisions that short keys invite are an accepted trade-off. Every other source uses the **full** type name and separates the category with a hash sign. Writing one form where the other is expected is the usual reason a binding silently does nothing: nothing fails and no error is reported, the key simply never matches and the chain moves on to the next source. | ||
| 56 | |||
| 57 | == The Two Fallbacks == | ||
| 58 | |||
| 59 | The chain returns a hint, not an editor. ##EditorManager## resolves that hint and covers the two cases where it cannot be used as it stands. | ||
| 60 | |||
| 61 | **A hint that matches no editor is retried as a category.** Configuring ##wysiwyg## as the editor of a data type works even though no editor is registered under that hint, because the lookup is made again, this time for the default editor of the ##wysiwyg## category. | ||
| 62 | |||
| 63 | **With nothing configured, the first editor in the category wins.** When the chain returns no hint at all, the first editor registered in the requested category is used; if that category has no editor, the first one registered for the data type is. A category that holds a single editor therefore needs no configuration. | ||
| 64 | |||
| 65 | == What a Standard XWiki Does == | ||
| 66 | |||
| 67 | These fallbacks are why a standard XWiki opens page content in CKEditor without a line of configuration anywhere. Page content is edited through the ##wysiwyg## category, and for that category nothing answers: no request parameter is passed, no ##XWiki.EditorBindingClass## xobject exists, the ##edit.defaultEditor## keys ship commented out in ##xwiki.properties##, and ##XDOMEditorConfiguration## returns nothing for a category other than ##text##. The chain comes back empty and the second fallback picks the first editor registered in the category, which is CKEditor. | ||
| 68 | |||
| 69 | The lookup made with no category at all answers differently, because ##XDOMEditorConfiguration## does supply a value for it: ##xwiki.editor## from ##xwiki.cfg##, or its ##text## default. A data type and each of its categories are resolved independently, so the editor a reader gets depends on which of the two lookups the calling code made. |