diff --git a/.eslintignore b/.eslintignore index 4ba01112a..3ee6d36d7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -886,6 +886,9 @@ packages/lib/locale.js.map packages/lib/markdownUtils.d.ts packages/lib/markdownUtils.js packages/lib/markdownUtils.js.map +packages/lib/markdownUtils.test.d.ts +packages/lib/markdownUtils.test.js +packages/lib/markdownUtils.test.js.map packages/lib/markupLanguageUtils.d.ts packages/lib/markupLanguageUtils.js packages/lib/markupLanguageUtils.js.map diff --git a/.gitignore b/.gitignore index e3220be5a..ae093bced 100644 --- a/.gitignore +++ b/.gitignore @@ -873,6 +873,9 @@ packages/lib/locale.js.map packages/lib/markdownUtils.d.ts packages/lib/markdownUtils.js packages/lib/markdownUtils.js.map +packages/lib/markdownUtils.test.d.ts +packages/lib/markdownUtils.test.js +packages/lib/markdownUtils.test.js.map packages/lib/markupLanguageUtils.d.ts packages/lib/markupLanguageUtils.js packages/lib/markupLanguageUtils.js.map diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.ts b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.ts index 961b646be..9e507d785 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.ts +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.ts @@ -155,14 +155,18 @@ export default function useListIdent(CodeMirror: any) { // otherwise fallback on the default codemirror behavior if (ranges.length === 1) { const line = cm.getLine(anchor.line); + // if cursor on 0th line set previousLine='' + const previousLine = anchor.line ? cm.getLine(anchor.line - 1) : ''; if (markdownUtils.isEmptyListItem(line)) { const tokens = cm.getLineTokens(anchor.line); // A empty list item with an indent will have whitespace as the first token if (tokens.length > 1 && tokens[0].string.match(/^\s/)) { cm.execCommand('smartListUnindent'); - } else { + } else if (markdownUtils.isListItem(previousLine)) { cm.replaceRange('', { line: anchor.line, ch: 0 }, anchor); + } else { // perform normal enter key operation + cm.replaceRange('\n', anchor); } return; } diff --git a/packages/lib/.gitignore b/packages/lib/.gitignore index 6a64b44e9..a7b962ffe 100644 --- a/packages/lib/.gitignore +++ b/packages/lib/.gitignore @@ -1 +1,2 @@ plugin_types/ +markdownUtils.test.js \ No newline at end of file diff --git a/packages/lib/markdownUtils.test.ts b/packages/lib/markdownUtils.test.ts new file mode 100644 index 000000000..a6e9223cd --- /dev/null +++ b/packages/lib/markdownUtils.test.ts @@ -0,0 +1,94 @@ +import markdownUtils from './markdownUtils'; + +describe('Should detect list items', () => { + test('should detect `- lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('- lorem ipsum')).toBe(true); + }); + test('should detect `+ lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('+ lorem ipsum')).toBe(true); + }); + test('should detect `* lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('* lorem ipsum')).toBe(true); + }); + + // ordered list + test('should detect `1. lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('1. lorem ipsum')).toBe(true); + }); + test('should detect `1) lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('1) lorem ipsum')).toBe(true); + }); + // checkbox list + test('should detect `+ [x] lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('+ [x] lorem ipsum')).toBe(true); + }); + + // ordered list + test('should NOT detect `-lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('-lorem ipsum')).toBe(false); + }); + test('should NOT detect `+lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('+lorem ipsum')).toBe(false); + }); + test('should NOT detect `*lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('*lorem ipsum')).toBe(false); + }); + + // ordered list + test('should NOT detect `1.lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('1.lorem ipsum')).toBe(false); + }); + test('should NOT detect `1)lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('1)lorem ipsum')).toBe(false); + }); + + test('should NOT detect `+[x]lorem ipsum` as list item ', () => { + expect(markdownUtils.isListItem('+[x]lorem ipsum')).toBe(false); + }); + // Empty list detection + test('should detect `- ` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('- ')).toBe(true); + }); + test('should detect `+ ` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('+ ')).toBe(true); + }); + test('should detect `* ` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('* ')).toBe(true); + }); + + // ordered list + test('should detect `1. ` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('1. ')).toBe(true); + }); + test('should detect `1) ` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('1) ')).toBe(true); + }); + // checkbox list + test('should detect `+ [x] ` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('+ [x] ')).toBe(true); + }); + + // unordered list + test('should NOT detect `-` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('-')).toBe(false); + }); + test('should NOT detect `+` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('+')).toBe(false); + }); + test('should NOT detect `*` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('*')).toBe(false); + }); + + // ordered list + test('should NOT detect `1.` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('1.')).toBe(false); + }); + test('should NOT detect `1)` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('1)')).toBe(false); + }); + // checbox list + test('should NOT detect `+ [x]` as empty list item ', () => { + expect(markdownUtils.isEmptyListItem('+ [x]')).toBe(false); + }); + +}); diff --git a/packages/lib/markdownUtils.ts b/packages/lib/markdownUtils.ts index 6dc588609..f2692bbe8 100644 --- a/packages/lib/markdownUtils.ts +++ b/packages/lib/markdownUtils.ts @@ -5,7 +5,7 @@ const MarkdownIt = require('markdown-it'); // Taken from codemirror/addon/edit/continuelist.js const listRegex = /^(\s*)([*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]\s))(\s*)/; -const emptyListRegex = /^(\s*)([*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/; +const emptyListRegex = /^(\s*)([*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s+)$/; export interface MarkdownTableHeader { name: string;