mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop: Codemirror: clean up list indent code (#3581)
This commit is contained in:
parent
bab29cd582
commit
bbfed9bca8
@ -13,7 +13,7 @@ export default function useListIdent(CodeMirror: any) {
|
|||||||
function getIndentLevel(cm: any, line: number) {
|
function getIndentLevel(cm: any, line: number) {
|
||||||
const tokens = cm.getLineTokens(line);
|
const tokens = cm.getLineTokens(line);
|
||||||
let indentLevel = 0;
|
let indentLevel = 0;
|
||||||
if (tokens.length > 0 && tokens[0].string.match(/\s/)) {
|
if (tokens.length > 0 && tokens[0].string.match(/^\s/)) {
|
||||||
indentLevel = tokens[0].string.length;
|
indentLevel = tokens[0].string.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,79 +63,103 @@ export default function useListIdent(CodeMirror: any) {
|
|||||||
if (cm.getOption('disableInput')) return CodeMirror.Pass;
|
if (cm.getOption('disableInput')) return CodeMirror.Pass;
|
||||||
|
|
||||||
const ranges = cm.listSelections();
|
const ranges = cm.listSelections();
|
||||||
for (let i = 0; i < ranges.length; i++) {
|
|
||||||
const { anchor, head } = ranges[i];
|
|
||||||
|
|
||||||
const line = cm.getLine(anchor.line);
|
cm.operation(() => {
|
||||||
|
for (let i = 0; i < ranges.length; i++) {
|
||||||
|
const { anchor, head } = ranges[i];
|
||||||
|
|
||||||
// This is an actual selection and we should indent
|
const line = cm.getLine(anchor.line);
|
||||||
if (isSelection(anchor, head) || !isListItem(line)) {
|
|
||||||
cm.execCommand('defaultTab');
|
// This is an actual selection and we should indent
|
||||||
} else {
|
if (isSelection(anchor, head)) {
|
||||||
if (olLineNumber(line)) {
|
cm.execCommand('defaultTab');
|
||||||
const tokens = cm.getLineTokens(anchor.line);
|
// This will apply to all selections so it makes sense to stop processing here
|
||||||
const { start, end } = getListSpan(tokens, line);
|
// this is an edge case for users because there is no clear intended behavior
|
||||||
// Resets numbered list to 1.
|
// if the use multicursor with a mix of selected and not selected
|
||||||
cm.replaceRange('1. ', { line: anchor.line, ch: start }, { line: anchor.line, ch: end });
|
break;
|
||||||
|
} else if (!isListItem(line) || !isEmptyListItem(line)) {
|
||||||
|
cm.replaceRange('\t', anchor, head);
|
||||||
|
} else {
|
||||||
|
if (olLineNumber(line)) {
|
||||||
|
const tokens = cm.getLineTokens(anchor.line);
|
||||||
|
const { start, end } = getListSpan(tokens, line);
|
||||||
|
// Resets numbered list to 1.
|
||||||
|
cm.replaceRange('1. ', { line: anchor.line, ch: start }, { line: anchor.line, ch: end });
|
||||||
|
}
|
||||||
|
|
||||||
|
cm.indentLine(anchor.line, 'add');
|
||||||
}
|
}
|
||||||
|
|
||||||
cm.indentLine(anchor.line, 'add');
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
CodeMirror.commands.smartListUnindent = function(cm: any) {
|
CodeMirror.commands.smartListUnindent = function(cm: any) {
|
||||||
if (cm.getOption('disableInput')) return CodeMirror.Pass;
|
if (cm.getOption('disableInput')) return CodeMirror.Pass;
|
||||||
|
|
||||||
const ranges = cm.listSelections();
|
const ranges = cm.listSelections();
|
||||||
for (let i = 0; i < ranges.length; i++) {
|
|
||||||
const { anchor, head } = ranges[i];
|
|
||||||
|
|
||||||
const line = cm.getLine(anchor.line);
|
cm.operation(() => {
|
||||||
|
for (let i = 0; i < ranges.length; i++) {
|
||||||
|
const { anchor, head } = ranges[i];
|
||||||
|
|
||||||
// This is an actual selection and we should unindent
|
const line = cm.getLine(anchor.line);
|
||||||
if (isSelection(anchor, head) || !isListItem(line)) {
|
|
||||||
cm.execCommand('indentLess');
|
|
||||||
} else {
|
|
||||||
const newToken = newListToken(cm, anchor.line);
|
|
||||||
const tokens = cm.getLineTokens(anchor.line);
|
|
||||||
const { start, end } = getListSpan(tokens, line);
|
|
||||||
|
|
||||||
cm.replaceRange(newToken, { line: anchor.line, ch: start }, { line: anchor.line, ch: end });
|
// This is an actual selection and we should unindent
|
||||||
|
if (isSelection(anchor, head)) {
|
||||||
|
cm.execCommand('indentLess');
|
||||||
|
// This will apply to all selections so it makes sense to stop processing here
|
||||||
|
// this is an edge case for users because there is no clear intended behavior
|
||||||
|
// if the use multicursor with a mix of selected and not selected
|
||||||
|
break;
|
||||||
|
} else if (!isListItem(line) || !isEmptyListItem(line)) {
|
||||||
|
cm.indentLine(anchor.line, 'subtract');
|
||||||
|
} else {
|
||||||
|
const newToken = newListToken(cm, anchor.line);
|
||||||
|
const tokens = cm.getLineTokens(anchor.line);
|
||||||
|
const { start, end } = getListSpan(tokens, line);
|
||||||
|
|
||||||
cm.indentLine(anchor.line, 'subtract');
|
cm.replaceRange(newToken, { line: anchor.line, ch: start }, { line: anchor.line, ch: end });
|
||||||
|
|
||||||
|
cm.indentLine(anchor.line, 'subtract');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
CodeMirror.commands.insertListElement = function(cm: any) {
|
CodeMirror.commands.insertListElement = function(cm: any) {
|
||||||
if (cm.getOption('disableInput')) return CodeMirror.Pass;
|
if (cm.getOption('disableInput')) return CodeMirror.Pass;
|
||||||
|
|
||||||
const ranges = cm.listSelections();
|
const ranges = cm.listSelections();
|
||||||
for (let i = 0; i < ranges.length; i++) {
|
if (ranges.length === 0) return;
|
||||||
const { anchor } = ranges[i];
|
const { anchor } = ranges[0];
|
||||||
|
|
||||||
|
// Only perform the extra smart code if there is a single cursor
|
||||||
|
// otherwise fallback on the default codemirror behavior
|
||||||
|
if (ranges.length === 1) {
|
||||||
const line = cm.getLine(anchor.line);
|
const line = cm.getLine(anchor.line);
|
||||||
|
|
||||||
if (isEmptyListItem(line)) {
|
if (isEmptyListItem(line)) {
|
||||||
const tokens = cm.getLineTokens(anchor.line);
|
const tokens = cm.getLineTokens(anchor.line);
|
||||||
// A empty list item with an indent will have whitespace as the first token
|
// A empty list item with an indent will have whitespace as the first token
|
||||||
if (tokens.length > 1 && tokens[0].string.match(/\s/)) {
|
if (tokens.length > 1 && tokens[0].string.match(/^\s/)) {
|
||||||
cm.execCommand('smartListUnindent');
|
cm.execCommand('smartListUnindent');
|
||||||
} else {
|
} else {
|
||||||
cm.replaceRange('', { line: anchor.line, ch: 0 }, anchor);
|
cm.replaceRange('', { line: anchor.line, ch: 0 }, anchor);
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
// Disable automatic indent for html/xml outside of codeblocks
|
|
||||||
const state = cm.getTokenAt(anchor).state;
|
|
||||||
const mode = cm.getModeAt(anchor);
|
|
||||||
// html/xml inside of a codeblock is fair game for auto-indent
|
|
||||||
if (mode.name !== 'xml' || state.overlay.codeBlock) {
|
|
||||||
cm.execCommand('newlineAndIndentContinueMarkdownList');
|
|
||||||
} else {
|
|
||||||
cm.replaceSelection('\n');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable automatic indent for html/xml outside of codeblocks
|
||||||
|
const state = cm.getTokenAt(anchor).state;
|
||||||
|
const mode = cm.getModeAt(anchor);
|
||||||
|
|
||||||
|
// html/xml inside of a codeblock is fair game for auto-indent
|
||||||
|
// for states who's mode is xml, having the localState property means they are within a code block
|
||||||
|
if (mode.name !== 'xml' || !!state.outer.localState) {
|
||||||
|
cm.execCommand('newlineAndIndentContinueMarkdownList');
|
||||||
|
} else {
|
||||||
|
cm.replaceSelection('\n');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user