Content Editor
The Content Editor is a UI component that provides a WYSIWYG editing experience for GitLab Flavored Markdown (GFM) in the GitLab application. It also serves as the foundation for implementing Markdown-focused editors that target other engines, like static site generators.
We use tiptap 2.0 and ProseMirror
to build the Content Editor. These frameworks provide a level of abstraction on top of
the native
contenteditable
web technology.
Architecture remarks
At a high level, the Content Editor:
- Imports arbitrary Markdown.
- Renders it in a HTML editing area.
- Exports it back to Markdown with changes introduced by the user.
The Content Editor relies on the Markdown API endpoint to transform Markdown into HTML. It sends the Markdown input to the REST API and displays the API’s HTML output in the editing area. The editor exports the content back to Markdown using a client-side library that serializes editable documents into Markdown.
Check the Content Editor technical design document for more information about the design decisions that drive the development of the editor.
NOTE: We also designed the Content Editor to be extensible. We intend to provide more information about extension development for supporting new types of content in upcoming milestones.
GitLab Flavored Markdown support
The GitLab Flavored Markdown extends the CommonMark specification with support for a variety of content types like diagrams, math expressions, and tables. Supporting all GitLab Flavored Markdown content types in the Content Editor is a work in progress. For the status of the ongoing development for CommonMark and GitLab Flavored Markdown support, read:
Usage
To include the Content Editor in your feature, import the createContentEditor
factory
function and the ContentEditor
Vue component. createContentEditor
sets up an instance
of tiptap’s Editor class with all the necessary
extensions to support editing GitLab Flavored Markdown content. It also creates
a Markdown serializer that allows exporting tiptap’s document format to Markdown.
createContentEditor
requires a renderMarkdown
parameter invoked
by the editor every time it needs to convert Markdown to HTML. The Content Editor
does not provide a default value for this function yet.
NOTE: The Content Editor is in an early development stage. Usage and development guidelines are subject to breaking changes in the upcoming months.
<script>
import { GlButton } from '@gitlab/ui';
import { createContentEditor, ContentEditor } from '~/content_editor';
import { __ } from '~/locale';
import createFlash from '~/flash';
export default {
components: {
ContentEditor,
GlButton,
},
data() {
return {
contentEditor: null,
}
},
created() {
this.contentEditor = createContentEditor({
renderMarkdown: (markdown) => Api.markdown({ text: markdown }),
});
try {
await this.contentEditor.setSerializedContent(this.content);
} catch (e) {
createFlash({
message: __('There was an error loading content in the editor'), error: e
});
}
},
methods: {
async save() {
await Api.updateContent({
content: this.contentEditor.getSerializedContent(),
});
},
},
};
</script>
<template>
<div>
<content-editor :content-editor="contentEditor" />
<gl-button @click="save()">Save</gl-button>
</div>
</template>
Call setSerializedContent
to set initial Markdown in the Editor. This method is
asynchronous because it makes an API request to render the Markdown input.
getSerializedContent
returns a Markdown string that represents the serialized
version of the editable document.