Commit 9453a015 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '338269-content-editor-task-list' into 'master'

Add support for task lists in content editor

See merge request gitlab-org/gitlab!68121
parents 6aeddcba 0f07bf94
import { TaskItem } from '@tiptap/extension-task-item';
export default TaskItem.extend({
defaultOptions: {
nested: true,
HTMLAttributes: {},
},
addAttributes() {
return {
checked: {
default: false,
parseHTML: (element) => {
const checkbox = element.querySelector('input[type=checkbox].task-list-item-checkbox');
return { checked: checkbox?.checked };
},
renderHTML: (attributes) => ({
'data-checked': attributes.checked,
}),
keepOnSplit: false,
},
};
},
parseHTML() {
return [
{
tag: 'li.task-list-item',
priority: 100,
},
];
},
});
import { mergeAttributes } from '@tiptap/core';
import { TaskList } from '@tiptap/extension-task-list';
export default TaskList.extend({
addAttributes() {
return {
type: {
default: 'ul',
parseHTML: (element) => {
return {
type: element.tagName.toLowerCase() === 'ol' ? 'ol' : 'ul',
};
},
},
};
},
parseHTML() {
return [
{
tag: '.task-list',
priority: 100,
},
];
},
renderHTML({ HTMLAttributes: { type, ...HTMLAttributes } }) {
return [type, mergeAttributes(HTMLAttributes, { 'data-type': 'taskList' }), 0];
},
});
...@@ -29,6 +29,8 @@ import Table from '../extensions/table'; ...@@ -29,6 +29,8 @@ import Table from '../extensions/table';
import TableCell from '../extensions/table_cell'; import TableCell from '../extensions/table_cell';
import TableHeader from '../extensions/table_header'; import TableHeader from '../extensions/table_header';
import TableRow from '../extensions/table_row'; import TableRow from '../extensions/table_row';
import TaskItem from '../extensions/task_item';
import TaskList from '../extensions/task_list';
import Text from '../extensions/text'; import Text from '../extensions/text';
import { ContentEditor } from './content_editor'; import { ContentEditor } from './content_editor';
import createMarkdownSerializer from './markdown_serializer'; import createMarkdownSerializer from './markdown_serializer';
...@@ -85,6 +87,8 @@ export const createContentEditor = ({ ...@@ -85,6 +87,8 @@ export const createContentEditor = ({
TableHeader, TableHeader,
TableRow, TableRow,
Table, Table,
TaskItem,
TaskList,
Text, Text,
]; ];
......
...@@ -25,6 +25,8 @@ import Table from '../extensions/table'; ...@@ -25,6 +25,8 @@ import Table from '../extensions/table';
import TableCell from '../extensions/table_cell'; import TableCell from '../extensions/table_cell';
import TableHeader from '../extensions/table_header'; import TableHeader from '../extensions/table_header';
import TableRow from '../extensions/table_row'; import TableRow from '../extensions/table_row';
import TaskItem from '../extensions/task_item';
import TaskList from '../extensions/task_list';
import Text from '../extensions/text'; import Text from '../extensions/text';
const defaultSerializerConfig = { const defaultSerializerConfig = {
...@@ -133,6 +135,14 @@ const defaultSerializerConfig = { ...@@ -133,6 +135,14 @@ const defaultSerializerConfig = {
renderRow(); renderRow();
} }
}, },
[TaskItem.name]: (state, node) => {
state.write(`[${node.attrs.checked ? 'x' : ' '}] `);
state.renderContent(node);
},
[TaskList.name]: (state, node) => {
if (node.attrs.type === 'ul') defaultMarkdownSerializer.nodes.bullet_list(state, node);
else defaultMarkdownSerializer.nodes.ordered_list(state, node);
},
[Text.name]: defaultMarkdownSerializer.nodes.text, [Text.name]: defaultMarkdownSerializer.nodes.text,
}, },
}; };
......
.ProseMirror {
td,
th,
li {
:only-child {
margin-bottom: 0 !important;
}
}
ul[data-type='taskList'] {
list-style: none;
padding: 0;
li {
margin: 0 !important;
}
}
[data-type='taskList'] {
p {
margin-bottom: 0;
}
li {
> label,
> div {
display: inline-block;
vertical-align: top;
}
> label {
padding: $gl-spacing-scale-1 $gl-spacing-scale-3 0 0;
margin: 0;
}
}
}
}
@import 'mixins_and_variables_and_functions'; @import 'mixins_and_variables_and_functions';
@import 'highlight.js/scss/a11y-light'; @import 'highlight.js/scss/a11y-light';
@import 'components/content_editor';
.title .edit-wiki-header { .title .edit-wiki-header {
width: 780px; width: 780px;
......
...@@ -72,6 +72,22 @@ ...@@ -72,6 +72,22 @@
1. list item 1 1. list item 1
2. list item 2 2. list item 2
3. list item 3 3. list item 3
- name: task_list
markdown: |-
* [x] hello
* [x] world
* [ ] example
* [ ] of nested
* [x] task list
* [ ] items
- name: ordered_task_list
markdown: |-
1. [x] hello
2. [x] world
3. [ ] example
1. [ ] of nested
1. [x] task list
2. [ ] items
- name: image - name: image
markdown: '![alt text](https://gitlab.com/logo.png)' markdown: '![alt text](https://gitlab.com/logo.png)'
- name: hard_break - name: hard_break
......
...@@ -1507,6 +1507,18 @@ ...@@ -1507,6 +1507,18 @@
prosemirror-tables "^1.1.1" prosemirror-tables "^1.1.1"
prosemirror-view "^1.18.8" prosemirror-view "^1.18.8"
"@tiptap/extension-task-item@^2.0.0-beta.17":
version "2.0.0-beta.17"
resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.17.tgz#e4e010c321b8f9aa5f49847c48e4e3a0695a47a9"
integrity sha512-uV5f9rWo9NAZ+oyt/mkhFEZfcngr92pVL2sn291RiT0qw9NRvdIQ6PLH24il9zu+jjeWmh1cJnBuQos+MQqjyg==
dependencies:
prosemirror-inputrules "^1.1.3"
"@tiptap/extension-task-list@^2.0.0-beta.17":
version "2.0.0-beta.17"
resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.17.tgz#c0f40325abf1b6a23868e72ab32f9724a8b42a7b"
integrity sha512-E17VBqW2lXF59hCQ/3/Kg0hYSDGvVC4B3W8miZwCXt5WTOl98Gk6qAiDXl+2mDKZvnsLty/YrgkD88OlZSIEbQ==
"@tiptap/extension-text@^2.0.0-beta.12": "@tiptap/extension-text@^2.0.0-beta.12":
version "2.0.0-beta.12" version "2.0.0-beta.12"
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.12.tgz#b857f36dda5e8cedd350f9bad7115e4060f8d9c0" resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.12.tgz#b857f36dda5e8cedd350f9bad7115e4060f8d9c0"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment