Skip to content

Commit a17c3e8

Browse files
committed
make code easier to test
1 parent 68fa996 commit a17c3e8

File tree

2 files changed

+44
-17
lines changed

2 files changed

+44
-17
lines changed

web_src/js/features/comp/EditorMarkdown.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {initTextareaMarkdown} from './EditorMarkdown.ts';
1+
import {initTextareaMarkdown, markdownHandleListNumbers} from './EditorMarkdown.ts';
22

33
test('EditorMarkdown', () => {
44
const textarea = document.createElement('textarea');
@@ -33,9 +33,12 @@ test('EditorMarkdown', () => {
3333

3434
testInput('- x', '- x\n- ');
3535
testInput('1. foo', '1. foo\n2. ');
36-
testInput({value: '1. a\n2. b\n3. c', pos: 4}, {value: '1. a\n2. \n2. b\n3. c', pos: 8});
36+
testInput({value: '1. a\n2. b\n3. c', pos: 4}, {value: '1. a\n2. \n3. b\n4. c', pos: 8});
3737
testInput('- [ ]', '- [ ]\n- ');
3838
testInput('- [ ] foo', '- [ ] foo\n- [ ] ');
3939
testInput('* [x] foo', '* [x] foo\n* [ ] ');
4040
testInput('1. [x] foo', '1. [x] foo\n2. [ ] ');
41+
42+
// TODO: test separately
43+
markdownHandleListNumbers({value: '1.', selStart: 1, selEnd: 2});
4144
});

web_src/js/features/comp/EditorMarkdown.ts

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ export function textareaInsertText(textarea, value) {
1414
triggerEditorContentChanged(textarea);
1515
}
1616

17-
function handleIndentSelection(textarea, e) {
17+
type TextareaValueSelection = {
18+
value: string;
19+
selStart: number;
20+
selEnd: number;
21+
}
22+
23+
function handleIndentSelection(textarea: HTMLTextAreaElement, e) {
1824
const selStart = textarea.selectionStart;
1925
const selEnd = textarea.selectionEnd;
2026
if (selEnd === selStart) return; // do not process when no selection
@@ -56,18 +62,21 @@ function handleIndentSelection(textarea, e) {
5662
triggerEditorContentChanged(textarea);
5763
}
5864

59-
function handleNewline(textarea: HTMLTextAreaElement, e: Event) {
60-
const selStart = textarea.selectionStart;
61-
const selEnd = textarea.selectionEnd;
62-
if (selEnd !== selStart) return; // do not process when there is a selection
65+
type MarkdownHandleListNumbersResult = {
66+
handled: boolean;
67+
valueSelection?: TextareaValueSelection;
68+
}
6369

64-
const value = textarea.value;
70+
export function markdownHandleListNumbers(tvs: TextareaValueSelection): MarkdownHandleListNumbersResult {
71+
const ret: MarkdownHandleListNumbersResult = {handled: false};
72+
if (tvs.selEnd !== tvs.selStart) return ret; // do not process when there is a selection
6573

74+
const value = tvs.value;
6675
// find the current line
6776
// * if selStart is 0, lastIndexOf(..., -1) is the same as lastIndexOf(..., 0)
6877
// * if lastIndexOf reruns -1, lineStart is 0 and it is still correct.
69-
const lineStart = value.lastIndexOf('\n', selStart - 1) + 1;
70-
let lineEnd = value.indexOf('\n', selStart);
78+
const lineStart = value.lastIndexOf('\n', tvs.selStart - 1) + 1;
79+
let lineEnd = value.indexOf('\n', tvs.selStart);
7180
lineEnd = lineEnd < 0 ? value.length : lineEnd;
7281
let line = value.slice(lineStart, lineEnd);
7382
if (!line) return; // if the line is empty, do nothing, let the browser handle it
@@ -82,17 +91,20 @@ function handleNewline(textarea: HTMLTextAreaElement, e: Event) {
8291
let prefix = '';
8392
if (prefixMatch) {
8493
prefix = prefixMatch[0];
85-
if (lineStart + prefix.length > selStart) prefix = ''; // do not add new line if cursor is at prefix
94+
if (lineStart + prefix.length > tvs.selStart) prefix = ''; // do not add new line if cursor is at prefix
8695
}
8796

8897
line = line.slice(prefix.length);
89-
if (!indention && !prefix) return; // if no indention and no prefix, do nothing, let the browser handle it
98+
if (!indention && !prefix) return ret; // if no indention and no prefix, do nothing, let the browser handle it
9099

91-
e.preventDefault();
100+
ret.handled = true;
92101
if (!line) {
93102
// clear current line if we only have i.e. '1. ' and the user presses enter again to finish creating a list
94-
textarea.value = value.slice(0, lineStart) + value.slice(lineEnd);
95-
textarea.setSelectionRange(selStart - prefix.length, selStart - prefix.length);
103+
ret.valueSelection = {
104+
value: value.slice(0, lineStart) + value.slice(lineEnd),
105+
selStart: tvs.selStart - prefix.length,
106+
selEnd: tvs.selStart - prefix.length,
107+
};
96108
} else {
97109
// start a new line with the same indention and prefix
98110
let newPrefix = prefix;
@@ -104,9 +116,21 @@ function handleNewline(textarea: HTMLTextAreaElement, e: Event) {
104116
}
105117
newPrefix = newPrefix.replace('[x]', '[ ]');
106118
const newLine = `\n${indention}${newPrefix}`;
107-
textarea.value = value.slice(0, selStart) + newLine + value.slice(selEnd);
108-
textarea.setSelectionRange(selStart + newLine.length, selStart + newLine.length);
119+
ret.valueSelection = {
120+
value: value.slice(0, tvs.selStart) + newLine + value.slice(tvs.selEnd),
121+
selStart: tvs.selStart + newLine.length,
122+
selEnd: tvs.selStart + newLine.length,
123+
};
109124
}
125+
return ret;
126+
}
127+
128+
function handleNewline(textarea: HTMLTextAreaElement, e: Event) {
129+
const ret = markdownHandleListNumbers({value: textarea.value, selStart: textarea.selectionStart, selEnd: textarea.selectionEnd});
130+
if (!ret.handled) return;
131+
e.preventDefault();
132+
textarea.value = ret.valueSelection.value;
133+
textarea.setSelectionRange(ret.valueSelection.selStart, ret.valueSelection.selEnd);
110134
triggerEditorContentChanged(textarea);
111135
}
112136

0 commit comments

Comments
 (0)