Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve bullet list style and change default style to - #3523

Merged
merged 4 commits into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cypress/e2e/ListItem.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import TaskItem from './../../src/nodes/TaskItem.js'
import BulletList from './../../src/nodes/BulletList.js'
import Markdown, { createMarkdownSerializer } from './../../src/extensions/Markdown.js'
import { findChildren } from 'prosemirror-utils'
import createEditor from './../../src/tests/createEditor.js'
import { createCustomEditor } from './../support/components.js'
import testData from '../fixtures/ListItem.md'
import markdownit from './../../src/markdownit/index.js'

describe('ListItem extension integrated in the editor', () => {

const editor = createEditor({
const editor = createCustomEditor({
content: '',
extensions: [
Markdown,
Expand Down
11 changes: 6 additions & 5 deletions cypress/e2e/Table.spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { User } from '@nextcloud/cypress'
import { findChildren } from 'prosemirror-utils'
import { initUserAndFiles, randHash } from '../utils/index.js'
import { createCustomEditor } from './../support/components.js'

import markdownit from './../../src/markdownit/index.js'
import testData from '../fixtures/Table.md'
import createEditor from './../../src/tests/createEditor.js'
import EditableTable from './../../src/nodes/EditableTable.js'
import Markdown, { createMarkdownSerializer } from './../../src/extensions/Markdown.js'

import { User } from '@nextcloud/cypress'
import { initUserAndFiles, randHash } from '../utils/index.js'
import testData from '../fixtures/Table.md'

const randUser = new User(randHash(), 'password')
const fileName = 'empty.md'
Expand Down Expand Up @@ -125,7 +126,7 @@ describe('table plugin', () => {

describe('Table extension integrated in the editor', () => {

const editor = createEditor({
const editor = createCustomEditor({
content: '',
extensions: [
Markdown,
Expand Down
10 changes: 5 additions & 5 deletions cypress/fixtures/ListItem.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

---

* [ ] did toggleTaskList
- [ ] did toggleTaskList

* keep

Expand Down Expand Up @@ -76,7 +76,7 @@ toggleBulletList

---

* did toggleBulletList
- did toggleBulletList

## Splits bullet list when turning one item into task

Expand All @@ -85,7 +85,7 @@ toggleBulletList

---

* [ ] did toggleTaskList
- [ ] did toggleTaskList

* not todo

Expand All @@ -97,11 +97,11 @@ toggleBulletList

---

* [ ] did toggleTaskList
- [ ] did toggleTaskList

* not todo

* [ ] did toggleTaskList
- [ ] did toggleTaskList

## toggle off task list item should turn it into normal list item

Expand Down
11 changes: 11 additions & 0 deletions cypress/support/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Editor } from '@tiptap/core'
import { Document } from '@tiptap/extension-document'
import { Text } from '@tiptap/extension-text'
import Paragraph from '../../src/nodes/Paragraph.js'

export const createCustomEditor = ({ content, extensions }) => {
return new Editor({
content,
extensions: [Document, Paragraph, Text, ...extensions],
})
}
4 changes: 2 additions & 2 deletions js/editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/editor.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-files.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-files.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-public.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-public.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-text.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-text.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-viewer.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-viewer.js.map

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/markdownit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,13 @@ const markdownit = MarkdownIt('commonmark', { html: false, breaks: false })
// Render front matter tokens
markdownit.renderer.rules.front_matter = (tokens, idx, options) => `<pre id="frontmatter"><code>${escapeHtml(tokens[idx].meta)}</code></pre>`

// Render lists with bullet attribute
markdownit.renderer.rules.bullet_list_open = (tokens, idx, options) => {
tokens[idx].attrs = [
...(tokens[idx].attrs || []),
['data-bullet', tokens[idx].markup],
]
return markdownit.renderer.renderToken(tokens, idx, options)
}

export default markdownit
3 changes: 2 additions & 1 deletion src/markdownit/splitMixedLists.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/

/**
* @param {object} md Markdown object
* @param {import('markdown-it')} md Markdown object
*/
export default function splitMixedLists(md) {
md.core.ruler.after('task-lists', 'split-mixed-task-lists', state => {
Expand Down Expand Up @@ -72,6 +72,7 @@ function splitListAt(tokens, index, TokenConstructor) {
const openList = new TokenConstructor('bullet_list_open', 'ul', 1)
openList.attrSet('class', 'contains-task-list')
openList.block = true
openList.markup = tokens[index].markup
tokens.splice(index, 0, closeList, openList)
}

Expand Down
12 changes: 12 additions & 0 deletions src/nodes/BulletList.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ const BulletList = TiptapBulletList.extend({
return this.parent().map(rule => Object.assign(rule, { preserveWhitespace: true }))
},

addAttributes() {
return {
...this.parent?.(),
bullet: {
default: '-',
rendered: false,
isRequired: true,
parseHTML: (el) => el.getAttribute('data-bullet'),
},
}
},

addInputRules() {
return [
listInputRule(
Expand Down
14 changes: 13 additions & 1 deletion src/nodes/TaskList.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,20 @@ const TaskList = TiptapTaskList.extend({
},
],

addAttributes() {
return {
...this.parent?.(),
bullet: {
default: '-',
rendered: false,
isRequired: true,
parseHTML: (el) => el.getAttribute('data-bullet'),
},
}
},

toMarkdown: (state, node) => {
state.renderList(node, ' ', () => (node.attrs.bullet || '*') + ' ')
state.renderList(node, ' ', () => `${node.attrs.bullet} `)
},

})
Expand Down
16 changes: 0 additions & 16 deletions src/tests/createEditor.js

This file was deleted.

16 changes: 8 additions & 8 deletions src/tests/extensions/Markdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import TaskItem from './../../nodes/TaskItem.js'
import Underline from './../../marks/Underline.js'
import TiptapImage from '@tiptap/extension-image'
import { getExtensionField } from '@tiptap/core'
import createEditor from './../createEditor.js'
import { createCustomEditor } from '../helpers.js'

describe('Markdown extension unit', () => {
it('has a config', () => {
Expand All @@ -20,7 +20,7 @@ describe('Markdown extension unit', () => {
})

it('makes toMarkdown available in prose mirror schema', () => {
const editor = createEditor({
const editor = createCustomEditor({
extensions: [Markdown, Underline],
})
const serializer = createMarkdownSerializer(editor.schema)
Expand All @@ -33,7 +33,7 @@ describe('Markdown extension unit', () => {

describe('Markdown extension integrated in the editor', () => {
it('serializes marks according to their spec', () => {
const editor = createEditor({
const editor = createCustomEditor({
content: '<p><u>Test</u></p>',
extensions: [Markdown, Underline],
})
Expand All @@ -42,16 +42,16 @@ describe('Markdown extension integrated in the editor', () => {
})

it('serializes nodes according to their spec', () => {
const editor = createEditor({
const editor = createCustomEditor({
content: '<p><ul class="contains-task-list"><li><input type="checkbox">Hello</li></ul></p>',
extensions: [Markdown, TaskList, TaskItem],
})
const serializer = createMarkdownSerializer(editor.schema)
expect(serializer.serialize(editor.state.doc)).toBe('\n* [ ] Hello')
expect(serializer.serialize(editor.state.doc)).toBe('\n- [ ] Hello')
})

it('serializes images with the default prosemirror way', () => {
const editor = createEditor({
const editor = createCustomEditor({
content: '<p><img alt="Hello" src="test"></p>',
extensions: [Markdown, TiptapImage.configure({ inline: true })],
})
Expand All @@ -60,7 +60,7 @@ describe('Markdown extension integrated in the editor', () => {
})

it('serializes block images with the default prosemirror way', () => {
const editor = createEditor({
const editor = createCustomEditor({
content: '<figure><img alt="Hello" src="test"></figure><p>hello</p>',
extensions: [Markdown, Image, ImageInline],
})
Expand All @@ -69,7 +69,7 @@ describe('Markdown extension integrated in the editor', () => {
})

it('serializes inline images with the default prosemirror way', () => {
const editor = createEditor({
const editor = createCustomEditor({
content: '<p>inline image <img alt="Hello" src="test"> inside text</p>',
extensions: [Markdown, Image, ImageInline],
})
Expand Down
51 changes: 51 additions & 0 deletions src/tests/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { createMarkdownSerializer } from '../extensions/Markdown'
import { Editor } from '@tiptap/core'

import Document from '@tiptap/extension-document'
import Paragraph from '../nodes/Paragraph'
import Text from '@tiptap/extension-text'

import createEditor from '../EditorFactory'
import markdownit from '../markdownit'

export function createCustomEditor({ content, extensions }) {
return new Editor({
content,
extensions: [
Document,
Paragraph,
Text,
...extensions,
]
})
}

/**
* Ease markdown through TipTap editor and return serialized markdown
*
* @param {string} markdown
* @returns {string}
*/
export function markdownThroughEditor(markdown) {
const tiptap = createEditor({
content: markdownit.render(markdown),
enableRichEditing: true
})
const serializer = createMarkdownSerializer(tiptap.schema)
return serializer.serialize(tiptap.state.doc)
}

/**
* Ease HTML as input through the Editor and return the serialized markdown
*
* @param {string} html
* @returns {string}
*/
export function markdownThroughEditorHtml(html) {
const tiptap = createEditor({
content: html,
enableRichEditing: true
})
const serializer = createMarkdownSerializer(tiptap.schema)
return serializer.serialize(tiptap.state.doc)
}
Loading