Remove list items when list is toggled off (#13580)

GitOrigin-RevId: 19c63b26798fcf3c8e631090c614f0a693d4f071
This commit is contained in:
Alf Eaton 2023-07-04 09:15:18 +01:00 committed by Copybot
parent 52d9ee79a3
commit 7e20d41c4c
3 changed files with 198 additions and 25 deletions

View file

@ -229,39 +229,52 @@ const toggleListForRange = (
// toggle list off
const changeSpec: ChangeSpec[] = [
{
from: emptyBeginLine ? beginLine.from - 1 : beginEnvNode.from,
to: emptyBeginLine ? beginLine.to : beginEnvNode.to,
from: emptyBeginLine ? beginLine.from : beginEnvNode.from,
to: emptyBeginLine
? Math.min(beginLine.to + 1, view.state.doc.length)
: beginEnvNode.to,
insert: '',
},
{
from: emptyEndLine ? endLine.from : endEnvNode.from,
to: emptyEndLine ? endLine.to + 1 : endEnvNode.to,
from: emptyEndLine
? Math.max(endLine.from - 1, 0)
: endEnvNode.from,
to: emptyEndLine ? endLine.to : endEnvNode.to,
insert: '',
},
]
const commandNodes = descendantsOfNodeWithType(
// items that aren't within nested list environments
const itemNodes = descendantsOfNodeWithType(
ancestorNode,
'Item'
).filter(
commandNode =>
view.state.sliceDoc(commandNode.from, commandNode.to) === '\\item'
'Item',
ListEnvironment
)
if (commandNodes.length > 0) {
// whether the command is the only content on this line, apart from whitespace
const emptyLineBeforeItem = /^\s*\\item\{/.test(beginLine.text)
if (itemNodes.length > 0) {
const indentUnit = getIndentUnit(view.state)
const indentUnit = emptyLineBeforeItem
? getIndentUnit(view.state)
: 0
for (const commandNode of commandNodes) {
changeSpec.push({
from: commandNode.from - indentUnit,
to: commandNode.to + 1,
for (const itemNode of itemNodes) {
const change: ChangeSpec = {
from: itemNode.from,
to: itemNode.to,
insert: '',
})
}
const line = view.state.doc.lineAt(itemNode.from)
const lineBeforeCommand = view.state.sliceDoc(
line.from,
itemNode.from
)
// if the line before the command is empty, remove one unit of indentation
if (lineBeforeCommand.trim().length === 0) {
const indentation = getIndentation(view.state, itemNode.from)
change.from -= Math.min(indentation ?? 0, indentUnit)
}
changeSpec.push(change)
}
}

View file

@ -138,16 +138,16 @@ export const lastAncestorAtEndPosition = (
export const descendantsOfNodeWithType = (
node: SyntaxNode,
type: string | number,
nested = false
leaveType?: string | number
): SyntaxNode[] => {
const children: SyntaxNode[] = []
node.cursor().iterate(nodeRef => {
if (nodeRef.type.is(type)) {
children.push(nodeRef.node)
if (!nested) {
return false
}
}
if (leaveType && nodeRef.type.is(leaveType) && nodeRef.node !== node) {
return false
}
})

View file

@ -147,4 +147,164 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
cy.get('.cm-line').eq(0).type('ing')
cy.get('.cm-line').eq(0).should('have.text', ' testing')
})
it('should toggle between list types', function () {
mountEditor('test')
selectAll()
clickToolbarButton('Numbered List')
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{enumerate}',
' test',
'\\end{enumerate}',
].join('')
)
cy.get('.cm-line').eq(1).click()
clickToolbarButton('Bullet List')
cy.get('.cm-line').eq(1).click()
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{itemize}',
' test',
'\\end{itemize}',
].join('')
)
})
it('should remove a list', function () {
mountEditor('test')
selectAll()
clickToolbarButton('Numbered List')
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{enumerate}',
' test',
'\\end{enumerate}',
].join('')
)
cy.get('.cm-line').eq(0).click()
clickToolbarButton('Numbered List')
cy.get('.cm-line').eq(0).click()
cy.get('.cm-content').should('have.text', 'test')
})
it('should not remove a parent list', function () {
mountEditor('test\ntest')
selectAll()
clickToolbarButton('Numbered List')
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{enumerate}',
' test',
' test',
'\\end{enumerate}',
].join('')
)
cy.get('.cm-line').eq(2).click()
clickToolbarButton('Increase Indent')
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{enumerate}',
' test',
' \\begin{enumerate}',
' test',
' \\end{enumerate}',
'\\end{enumerate}',
].join('')
)
cy.get('.cm-line').eq(2).click()
clickToolbarButton('Numbered List')
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{enumerate}',
' test',
' test',
'\\end{enumerate}',
].join('')
)
})
it('should not remove a nested list', function () {
mountEditor('test\ntest')
selectAll()
clickToolbarButton('Numbered List')
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{enumerate}',
' test',
' test',
'\\end{enumerate}',
].join('')
)
cy.get('.cm-line').eq(2).click()
clickToolbarButton('Increase Indent')
cy.get('.cm-content').should(
'have.text',
[
//
'\\begin{enumerate}',
' test',
' \\begin{enumerate}',
' test',
' \\end{enumerate}',
'\\end{enumerate}',
].join('')
)
cy.get('.cm-line').eq(1).click()
clickToolbarButton('Numbered List')
cy.get('.cm-line').eq(1).click()
cy.get('.cm-content').should(
'have.text',
[
//
'test',
' \\begin{enumerate}',
' test',
' \\end{enumerate}',
].join('')
)
})
})