prosemirror-flat-list
Version:
Powerful list support for ProseMirror
541 lines (441 loc) • 8.35 kB
text/typescript
import type { TaggedProsemirrorNode } from 'jest-remirror'
import type { Node as ProsemirrorNode } from 'prosemirror-model'
import { describe, expect, it } from 'vitest'
import { setupTestingEditor } from '../../test/setup-editor'
import { createDedentListCommand } from './dedent-list'
describe('dedentList', () => {
const t = setupTestingEditor()
const markdown = t.markdown
it('can dedent a list node to outer list', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B<cursor>1
`,
markdown`
- A1
- B<cursor>1
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- - <cursor>B1
- A1
`,
markdown`
- B1
- A1
`,
)
})
it('can dedent a paragraph node to outer list', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1a
B1b<cursor>
`,
markdown`
- A1
- B1a
B1b<cursor>
`,
)
})
it('can unwrap a list node', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1<cursor>
paragraph
`,
markdown`
A1<cursor>
paragraph
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- A1<cursor>
- A2
`,
markdown`
A1<cursor>
- A2
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- A2<cursor>
`,
markdown`
- A1
A2
`,
)
})
it('can unwrap multiple list nodes', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1<start>
- A2<end>
`,
markdown`
A1
A2
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- A2<start>
- A3<end>
- A4
`,
markdown`
- A1
A2
A3
- A4
`,
)
})
it('can keep siblings after the lifted items at the same position', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1
- B2<start>
- B3
- C1<end>
B3
- B4
`,
markdown`
- A1
- B1
- B2<start>
- B3
- C1<end>
B3
- B4
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1
- B2<cursor>
A1
`,
markdown`
- A1
- B1
- B2<cursor>
A1
`,
)
})
it('can only dedent selected part when the selection across multiple depth of a nested lists', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1
- B2
- C1<start>
- B3<end>
`,
markdown`
- A1
- B1
- B2
- C1<start>
- B3<end>
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1
- B2
- C1<start>
- B3<end>
- C2
`,
markdown`
- A1
- B1
- B2
- C1<start>
- B3<end>
- - C2
`,
)
})
it('can wrap unselected paragraphs with a list node if necessary', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1
- B2<start>
- B3<end>
B3
B3
- B4
`,
markdown`
- A1
- B1
- B2<start>
- B3<end>
- B3
B3
- B4
`,
)
})
it('can keep the indentation of sub list', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1<cursor>
- C1
`,
markdown`
- A1
- B1<cursor>
- - C1
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- A1<cursor>
- B1
`,
markdown`
A1<cursor>
- - B1
`,
)
})
it('do nothing when not inside a list', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
Hello<cursor>
paragraph
`,
markdown`
Hello<cursor>
paragraph
`,
)
})
it('can dedent a nested list item', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- - B1<cursor>
B1
A1
`,
markdown`
- B1
- B1
A1
`,
)
})
it('can dedent a blockquote inside a list', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- > A1
>
> A2<cursor>
`,
markdown`
- > A1
A2<cursor>
`,
)
})
it('can accept custom positions', () => {
t.applyCommand(
createDedentListCommand({ from: 13, to: 17 }),
t.doc(
/*0*/
t.bulletList(/*1*/ t.p('A1') /*5*/),
/*6*/
t.bulletList(/*7*/ t.p('A2<cursor>') /*11*/),
/*12*/
t.bulletList(/*13*/ t.p('A3') /*17*/),
/*18*/
),
t.doc(
//
t.bulletList(t.p('A1')),
t.bulletList(t.p('A2')),
t.p('A3'),
),
)
t.applyCommand(
createDedentListCommand({ from: 10, to: 14 }),
t.doc(
/*0*/
t.bulletList(/*1*/ t.p('A1') /*5*/),
/*6*/
t.bulletList(/*7*/ t.p('A2<cursor>') /*11*/),
/*12*/
t.bulletList(/*13*/ t.p('A3') /*17*/),
/*18*/
),
t.doc(
//
t.bulletList(t.p('A1')),
t.p('A2'),
t.p('A3'),
),
)
})
it('can handle some complex nested lists', () => {
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1
- <start>B2
- A2
- B3
- C1<end>
- D1
- B4
`,
markdown`
- A1
- B1
- <start>B2
A2
- B3
- C1<end>
- - D1
- B4
`,
)
t.applyCommand(
createDedentListCommand(),
markdown`
- A1
- B1
- B2
- C1
- D1
D1<start>
- A2
- B3
- C2
C2
- D2<end>
C2
- C3
`,
markdown`
- A1
- B1
- B2
- C1
- D1
D1<start>
A2
- B3
- C2
C2
- D2<end>
C2
- C3
`,
)
})
it('only needs one step for some of the most comment indent action', () => {
const countSteps = (
doc: TaggedProsemirrorNode,
expected: TaggedProsemirrorNode,
) => {
t.add(doc)
const state = t.view.state
const command = createDedentListCommand()
let count = -1
let actual: ProsemirrorNode | null = null
command(state, (tr) => {
count = tr.steps.length
actual = tr.doc
})
expect(actual).not.equal(null)
expect(actual).toEqualRemirrorDocument(expected)
return count
}
expect(
countSteps(
markdown`
- A1
- B1<cursor>
`,
markdown`
- A1
- B1<cursor>
`,
),
).toBe(1)
expect(
countSteps(
markdown`
- A1
- A2<cursor>
`,
markdown`
- A1
A2<cursor>
`,
),
).toBe(1)
expect(
countSteps(
markdown`
# heading
- A1<cursor>
`,
markdown`
# heading
A1<cursor>
`,
),
).toBe(1)
expect(
countSteps(
markdown`
# heading
- - A1<cursor>
`,
markdown`
# heading
- A1<cursor>
`,
),
).toBe(1)
})
})