Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added configurable checkbox marker (Closes #13) #14

Merged
merged 4 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ Example
+ [ ] plus
```

### Type of checkmark
Select a type of checkmark:

options: "X" | "x"

```json
"markdown-checkbox.checkmark": "X"
```

Example
```
- [X] uppercase checkmark
- [x] lowercase checkmark
```

### Italic
Italic font style of line of the checkbox after the checkbox has been checked:

Expand Down
11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@
"type": "boolean",
"default": true,
"description": "Show the amount of selected checkboxes in the status bar."
},
"markdown-checkbox.checkmark": {
"type": "string",
"enum": [
"X",
"x"
],
"default": "X",
"description": "Checkmark of the checkbox."
}
}
}
Expand All @@ -153,4 +162,4 @@
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0"
}
}
}
2 changes: 1 addition & 1 deletion src/createCheckbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const createCheckbox = (editor: TextEditor): any => {
const line = editor.document.lineAt(cursorPosition.line);
const hasBullet = helpers.lineHasBulletPointAlready(line);

if (!helpers.lineHasCheckbox(line)) {
if (!helpers.getCheckboxOfLine(line)) {
return editor.edit((editBuilder: TextEditorEdit) => {
editBuilder.insert(new Position(
line.lineNumber,
Expand Down
19 changes: 11 additions & 8 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,20 @@ export const lineHasBulletPointAlready = (line: TextLine): { pos: number, bullet
}
};

/** Check if a line has a checkbox */
export const lineHasCheckbox = (line: TextLine): Checkbox => {
/** Get the checkbox of a specific line */
export const getCheckboxOfLine = (line: TextLine): Checkbox => {
const lineText = line.text.toString();
const cbPosition = lineText.indexOf('[ ]');
const cbPositionMarked = lineText.search(/\[x\]/gi);
const cbPositionMarked = lineText.search(new RegExp(/\[.\]/));
const plainText = getPlainLineText(lineText);

if (cbPosition > -1) {
return { checked: false, position: new Position(line.lineNumber, cbPosition), text: plainText, lineNumber: line.lineNumber };
} else if (cbPositionMarked > -1) {
return { checked: true, position: new Position(line.lineNumber, cbPositionMarked), text: plainText, lineNumber: line.lineNumber };
if (cbPosition > -1 || cbPositionMarked > -1) {
return {
checked: cbPosition > -1 ? false : true,
position: new Position(line.lineNumber, cbPosition > -1 ? cbPosition : cbPositionMarked),
text: plainText,
lineNumber: line.lineNumber
};
} else {
return undefined;
}
Expand All @@ -50,7 +53,7 @@ export const getAllCheckboxes = (): Checkbox[] => {

for (let l = 0; l < lineCount; l++) {
const line = editor.document.lineAt(l);
const lhc = lineHasCheckbox(line);
const lhc = getCheckboxOfLine(line);
if (lhc) {
result.push(lhc);
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ suite('helpers', () => {
};

const expectedResult: Checkbox = { checked: false, position: new vscode.Position(1, 2), text: 'this is the text', lineNumber: 1 };
assert.deepStrictEqual(helpers.lineHasCheckbox(line), expectedResult);
assert.deepStrictEqual(helpers.getCheckboxOfLine(line), expectedResult);
});

test('should check if the line has a checked checkbox', () => {
Expand All @@ -36,7 +36,7 @@ suite('helpers', () => {
};

const expectedResult: Checkbox = { checked: true, position: new vscode.Position(1, 2), text: 'this is the text', lineNumber: 1 };
assert.deepStrictEqual(helpers.lineHasCheckbox(line), expectedResult);
assert.deepStrictEqual(helpers.getCheckboxOfLine(line), expectedResult);
});

test('should check if the line has a bullet point already', () => {
Expand Down
28 changes: 28 additions & 0 deletions src/test/toggleCheckbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,32 @@ suite('toggle checkboxes', () => {

assert.equal(content, expectedResult);
});

test('should be toggled with configured checkmark', async () => {
// create new document
const newDocument = await vscode.workspace.openTextDocument({
content: '[ ] this is a text\n[ ] this is another text\n[ ] another new line',
language: 'markdown'
});
await vscode.window.showTextDocument(newDocument);

// create a selection over the text to toggle all lines
const editor = getEditor();
const startPosition = new vscode.Position(0, 0);
const endPosition = new vscode.Position(2, 100);
const newSelection = new vscode.Selection(startPosition, endPosition);
editor.selection = newSelection;

// update config to use configured checkmark
await vscode.workspace.getConfiguration('markdown-checkbox').update('checkmark', 'x');
await toggleCheckbox();
// revert checkmark to default
await vscode.workspace.getConfiguration('markdown-checkbox').update('checkmark', 'X');

const content = editor.document.getText();
const dateNow = getDateString(new Date());
const expectedResult = `[x] ~~*this is a text*~~ [${dateNow}]\n[x] ~~*this is another text*~~ [${dateNow}]\n[x] ~~*another new line*~~ [${dateNow}]`;

assert.equal(content, expectedResult);
});
});
31 changes: 17 additions & 14 deletions src/toggleCheckbox.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import * as vscode from 'vscode';
import { Position, Range, TextEditorEdit } from 'vscode';
import { getConfig, getCursorPosition, getDateString, getEditor, lineHasCheckbox } from './helpers';
import * as helpers from './helpers';

/** Mark a checkbox as checked or unchecked */
export const toggleCheckbox = async () => {
// the position object gives you the line and character where the cursor is
const editor = getEditor();
const editor = helpers.getEditor();
if (editor.selection.isEmpty) {
const cursorPosition = getCursorPosition();
const cursorPosition = helpers.getCursorPosition();
const line = editor.document.lineAt(cursorPosition.line);
await toggleCheckboxOfLine(line);
const endLine = editor.document.lineAt(editor.selection.end.line);
const selectionPosition = new vscode.Position(endLine.lineNumber, 20000);
getEditor().selection = new vscode.Selection(selectionPosition, selectionPosition);
helpers.getEditor().selection = new vscode.Selection(selectionPosition, selectionPosition);
} else {
const selection = editor.selection;

Expand All @@ -26,7 +26,7 @@ export const toggleCheckbox = async () => {

/** mark or unmark the checkbox of a given line in the editor */
export const toggleCheckboxOfLine = (line: vscode.TextLine, checkIt?: boolean) => {
const lhc = lineHasCheckbox(line);
const lhc = helpers.getCheckboxOfLine(line);

// no edit action required
if (!lhc || !lhc.checked && checkIt === false || lhc.checked === true && checkIt === true) {
Expand All @@ -37,28 +37,31 @@ export const toggleCheckboxOfLine = (line: vscode.TextLine, checkIt?: boolean) =

// if the checkbox is not checked or it must be checked
if (checkIt === true || checkIt === undefined && !lhc.checked) {
value = 'X';
value = helpers.getConfig<string>('checkmark');
}

return markField(lhc.position, value);
};

/** Marks the field inside the checkbox with a character */
const markField = (checkboxPosition: Position, char: string, editor = getEditor()): Thenable<boolean> => {
const markField = (checkboxPosition: Position, replacement: string): Thenable<boolean> => {
const editor = helpers.getEditor();
const checkmark = helpers.getConfig<string>('checkmark');

return editor.edit((editBuilder: TextEditorEdit) => {
editBuilder.replace(new Range(
new Position(checkboxPosition.line, checkboxPosition.character + 1),
new Position(checkboxPosition.line, checkboxPosition.character + 2)
), char);
new Position(checkboxPosition.line, checkboxPosition.character + (replacement !== ' ' ? 2 : checkmark.length + 1))
), replacement);

// get settings from config
const italicWhenChecked = getConfig<boolean>('italicWhenChecked');
const strikeThroughWhenChecked = getConfig<boolean>('strikeThroughWhenChecked');
const dateWhenChecked = getConfig<boolean>('dateWhenChecked');
const italicWhenChecked = helpers.getConfig<boolean>('italicWhenChecked');
const strikeThroughWhenChecked = helpers.getConfig<boolean>('strikeThroughWhenChecked');
const dateWhenChecked = helpers.getConfig<boolean>('dateWhenChecked');

// get line of the checkbox
const line = editor.document.lineAt(checkboxPosition.line);
const lhc = lineHasCheckbox(line);
const lhc = helpers.getCheckboxOfLine(line);
const lineText = line.text;
const textWithoutCheckbox = lineText.substr(checkboxPosition.character + 4, lineText.length).trim();

Expand All @@ -69,7 +72,7 @@ const markField = (checkboxPosition: Position, char: string, editor = getEditor(
if (!lhc.checked && textWithoutCheckbox.length > 0) {
let newText = (strikeThroughWhenChecked ? '~~' : '') + (italicWhenChecked ? '*' : '') + textWithoutCheckbox + (italicWhenChecked ? '*' : '') + (strikeThroughWhenChecked ? '~~' : '');
// add the date string
newText = newText + (dateWhenChecked ? ' [' + getDateString(new Date()) + ']' : '') + whitespace;
newText = newText + (dateWhenChecked ? ' [' + helpers.getDateString(new Date()) + ']' : '') + whitespace;

editBuilder.replace(new Range(
new Position(checkboxPosition.line, checkboxPosition.character + 4),
Expand Down