Repository navigation
[QTI/RTE] Add a format prop to the TipTap editor to support HTML input/output #5966
Description
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
The shared TipTap editor (shared/views/TipTapEditor/TipTapEditor/TipTapEditor.vue) currently reads and writes Markdown only. Add a format prop — either 'markdown' or 'html', defaulting to 'markdown' — so a consumer can choose to drive the editor with HTML instead. When format is 'html', the editor's value prop is treated as HTML and the update event emits HTML; when it is 'markdown' (the default), behavior is unchanged.
This is needed for the new QTI editor, where the data must be XML rather than Markdown: its rich-text fields are stored as XML strings produced by editor.getHTML(), so the editor has to be able to consume and emit HTML.
Complexity: Low
Target branch: unstable
Context
There is no way for a consumer to get HTML out from the TipTap editor, even though TipTap can produce it directly via editor.getHTML(). The QTI editor (and potentially other consumers) needs HTML/XML, so it requires the editor to (a) accept its value as HTML and (b) emit HTML on update.
The format prop is a transitional measure. In the future, once the QTI editor has replaced the current (Markdown-based) assessment editing, we expect to remove the format prop entirely and have the TipTap editor always consume and emit HTML. The prop exists only so Markdown and HTML consumers can coexist during that transition.
Relevant spots in TipTapEditor.vue:
getMarkdownContent()— the output helper.watch(() => props.value, ...)— the input/sync-from-parent path (usespreprocessMarkdown).- the editor-state
watch(() => editor.value?.state, ...)— the sync-to-parent path (emits Markdown). - the
propsblock — wherevalue,mode, etc. are declared.
The Change
- Add a
formatprop: a string defaulting to'markdown', accepting only'markdown'or'html'(with a prop validator). - Make the output path format-aware: in
'markdown'it returnsstorage.markdown.getMarkdown()(current behavior); in'html'it returnseditor.getHTML(). - Make the input path format-aware: in
'markdown'it preprocesses withpreprocessMarkdownthen sets content (current behavior); in'html'it setsvalueas HTML content directly (no Markdown preprocessing). - The sync-to-parent comparison/emit and the sync-from-parent comparison should use the same format-aware content helper, so the loop-prevention logic keeps working in both formats.
'markdown'remains the default, so all current consumers are unaffected (backward compatible).
Out of Scope
- Changing any current consumer to use
format="html"(this task only adds the capability; the QTI editor will opt in separately). - Toolbar/feature differences between formats (the same editing features apply; only the serialization in/out changes).
- Markdown-vs-HTML sanitization policy changes beyond what the editor already does.
Acceptance Criteria
General
-
TipTapEditor.vuedeclares aformatprop (String) defaulting to'markdown', validated to accept only'markdown'or'html'. - With
format="markdown"(and when the prop is omitted), input and output behavior are unchanged from today (Markdown in, Markdown out) — existing consumers are unaffected. - With
format="html", thevalueprop is treated as HTML and set as editor content without Markdown preprocessing. - With
format="html", theupdateevent emits the editor's HTML (editor.getHTML()). - The sync-from-parent and sync-to-parent paths both use the format-aware content helper, so external updates and the loop-prevention flag work correctly in both formats.
- Content round-trips in each format: setting
valueand reading backupdateis consistent within'markdown'and within'html'.
Accessibility and i18n
- No user-facing strings are added; if any are, they come from the editor's existing strings module.
Testing
- Unit tests cover
format="markdown"(default) emitting Markdown andformat="html"emitting HTML. - A test confirms the default (no
formatprop) preserves current Markdown behavior. - Existing lint and test suites pass.
References
shared/views/TipTapEditor/TipTapEditor/TipTapEditor.vue—getMarkdownContent(), theprops.valuewatch (input viapreprocessMarkdown), the editor-state watch (output viagetMarkdown()), and thepropsblock.editor.getHTML()(TipTap) — the HTML serialization counterpart to the Markdown storage'sgetMarkdown().
AI usage
I used Claude (Claude Code) to draft this issue. I specified the change; Claude read the current TipTapEditor.vue to ground the description and acceptance criteria, and I reviewed every section.

Activity