Skip to content
Permalink
Browse files

fix: nested bold breaks syntax (close #247) (#248)

* fix: nested bold breaks syntax

* refactor: apply code review (ref #248)
  • Loading branch information...
kyuwoo-choi committed Jul 4, 2018
1 parent 5759bce commit 83bc8778f3ba51cc6d662881cdd4acc3157a59a4
@@ -4,7 +4,8 @@
*/
import CommandManager from '../commandManager';

const boldRegex = /^[*_]{2,}[^*_]*[*_]{2,}$/;
const boldRangeRegex = /^[*_]{2,}[^*_]+[*_]{2,}$/;
const boldContentRegex = /[*_]{2,}([^*_]+)[*_]{2,}/g;

/**
* Bold
@@ -35,7 +36,14 @@ const Bold = CommandManager.command('markdown', /** @lends Bold */{
}

const isRemoved = this.isNeedRemove(selection);
const result = isRemoved ? this.remove(selection) : this.append(selection);
let result;
if (isRemoved) {
result = this.remove(selection);
result = this._removeBoldSyntax(result);
} else {
result = this._removeBoldSyntax(selection);
result = this.append(result);
}

doc.replaceSelection(result, 'around');

@@ -52,7 +60,7 @@ const Bold = CommandManager.command('markdown', /** @lends Bold */{
* @returns {boolean} - true if it has bold
*/
isNeedRemove(text) {
return boldRegex.test(text);
return boldRangeRegex.test(text);
},

/**
@@ -109,6 +117,16 @@ const Bold = CommandManager.command('markdown', /** @lends Bold */{
*/
setCursorToCenter(doc, cursor) {
doc.setCursor(cursor.line, cursor.ch + 2);
},

/**
* remove bold syntax in the middle of given text
* @param {string} text - text selected
* @returns {string} - text eliminated all bold in the middle of it's content
* @private
*/
_removeBoldSyntax(text) {
return text ? text.replace(boldContentRegex, '$1') : '';
}
});

@@ -4,6 +4,9 @@
*/
import CommandManager from '../commandManager';

const codeRangeRegex = /^`([^`]+)`$/;
const codeContentRegex = /`([^`]+)`/g;

/**
* Code
* Add code markdown syntax to markdown editor
@@ -21,25 +24,74 @@ const Code = CommandManager.command('markdown', /** @lends Code */{
exec(mde) {
const cm = mde.getEditor();
const doc = cm.getDoc();

const selection = doc.getSelection();
const range = cm.getCursor();
const cursor = cm.getCursor();
const hasSyntax = this.hasStrikeSyntax(selection);

let result;
if (hasSyntax) {
result = this.remove(selection);
result = this._removeCodeSyntax(result);
} else {
result = this._removeCodeSyntax(selection);
result = this.append(result);
}

doc.replaceSelection(this.append(selection), 'around');
doc.replaceSelection(result, 'around');

if (!selection) {
doc.setCursor(range.line, range.ch + 1);
if (!selection && !hasSyntax) {
this.setCursorToCenter(doc, cursor, hasSyntax);
}

cm.focus();
},

/**
* set cursor to center
* @param {CodeMirror.doc} doc - codemirror document
* @param {object} cursor - codemirror cursor
* @param {boolean} isRemoved - whether it involes deletion
*/
setCursorToCenter(doc, cursor, isRemoved) {
const pos = isRemoved ? -1 : 1;
doc.setCursor(cursor.line, cursor.ch + pos);
},

/**
* has code syntax
* @param {string} text Source text
* @returns {boolean} true if the given text has a code syntax
*/
hasStrikeSyntax(text) {
return codeRangeRegex.test(text);
},

/**
* apply Code
* @param {string} text - selected text
* @returns {string} - text after code syntax applied
*/
append(text) {
return `\`${text}\``;
},

/**
* remove Code
* @param {string} text - selected text
* @returns {string} - text after code syntax removed
*/
remove(text) {
return text.substr(1, text.length - 2);
},

/**
* remove bold syntax in the middle of given text
* @param {string} text - text selected
* @returns {string} - text eliminated all code in the middle of it's content
* @private
*/
_removeCodeSyntax(text) {
return text ? text.replace(codeContentRegex, '$1') : '';
}
});

@@ -4,8 +4,9 @@
*/
import CommandManager from '../commandManager';

const boldItalicRegex = /^[*_]{3,}[^*_]*[*_]{3,}$/;
const italicRegex = /^[*_][^*_]*[*_]$/;
const boldItalicRangeRegex = /^[*_]{3,}[^*_]+[*_]{3,}$/;
const italicRangeRegex = /^[*_][^*_]+[*_]$/;
const italicContentRegex = /[*_]([^*_]+)[*_]/g;

/**
* Italic
@@ -52,7 +53,14 @@ const Italic = CommandManager.command('markdown', /** @lends Italic */{
}

const isRemoved = this.isNeedRemove(selection);
const result = isRemoved ? this.remove(selection) : this.append(selection);
let result;
if (isRemoved) {
result = this.remove(selection);
result = this._removeItalicSyntax(result);
} else {
result = this._removeItalicSyntax(selection);
result = this.append(result);
}

doc.replaceSelection(result, 'around');

@@ -70,7 +78,7 @@ const Italic = CommandManager.command('markdown', /** @lends Italic */{
* @returns {boolean} - true if it has italic or bold
*/
isNeedRemove(text) {
return italicRegex.test(text) || boldItalicRegex.test(text);
return italicRangeRegex.test(text) || boldItalicRangeRegex.test(text);
},

/**
@@ -185,6 +193,16 @@ const Italic = CommandManager.command('markdown', /** @lends Italic */{
setCursorToCenter(doc, cursor, isRemoved) {
const pos = isRemoved ? -1 : 1;
doc.setCursor(cursor.line, cursor.ch + pos);
},

/**
* remove italic syntax in the middle of given text
* @param {string} text - text selected
* @returns {string} - text eliminated all italic in the middle of it's content
* @private
*/
_removeItalicSyntax(text) {
return text ? text.replace(italicContentRegex, '$1') : '';
}
});

@@ -4,7 +4,8 @@
*/
import CommandManager from '../commandManager';

const strikeRegex = /^[~~](.*[\s\n]*.*)*[~~]$/;
const strikeRangeRegex = /^~~[^~]+~~$/;
const strikeContentRegex = /~~([^~]+)~~/g;

/**
* Strike
@@ -31,15 +32,15 @@ const Strike = CommandManager.command('markdown', /** @lends Strike */{

if (isNeedToRemove) {
result = this.remove(selection);
result = this._removeStrikeSyntax(result);
} else {
result = this.append(selection);
result = this._removeStrikeSyntax(selection);
result = this.append(result);
}

doc.replaceSelection(result, 'around');

const isEmptySelection = !selection;

if (isEmptySelection && !isNeedToRemove) {
if (!selection && !isNeedToRemove) {
this.setCursorToCenter(doc, cursor, isNeedToRemove);
}

@@ -52,7 +53,7 @@ const Strike = CommandManager.command('markdown', /** @lends Strike */{
* @returns {boolean} Boolean value of strike syntax removal
*/
hasStrikeSyntax(text) {
return strikeRegex.test(text);
return strikeRangeRegex.test(text);
},

/**
@@ -82,6 +83,16 @@ const Strike = CommandManager.command('markdown', /** @lends Strike */{
setCursorToCenter(doc, cursor, isRemoved) {
const pos = isRemoved ? -2 : 2;
doc.setCursor(cursor.line, cursor.ch + pos);
},

/**
* remove strike syntax in the middle of given text
* @param {string} text - text selected
* @returns {string} - text eliminated all strike in the middle of it's content
* @private
*/
_removeStrikeSyntax(text) {
return text ? text.replace(strikeContentRegex, '$1') : '';
}
});

@@ -9,10 +9,10 @@ import MarkdownEditor from '../../../src/js/markdownEditor';
import EventManager from '../../../src/js/eventManager';

describe('Bold', () => {
let cm, doc, mde;
let cm, doc, mde, $container;

beforeEach(() => {
const $container = $('<div />');
$container = $('<div />');

$('body').append($container);

@@ -27,7 +27,7 @@ describe('Bold', () => {
});

afterEach(() => {
$('body').empty();
$container.remove();
});

describe('add bold syntax', () => {
@@ -60,5 +60,21 @@ describe('Bold', () => {

expect(cm.getValue()).toEqual(['**mytext1**', '', 'mytext2', 'mytext3'].join('\n'));
});

it('should remove bold syntax in the middle of the given range', () => {
cm.setValue('my**text**1');

doc.setSelection({
line: 0,
ch: 0
}, {
line: 0,
ch: 11
});

Bold.exec(mde);

expect(cm.getValue()).toEqual('**mytext1**');
});
});
});
@@ -9,10 +9,10 @@ import MarkdownEditor from '../../../src/js/markdownEditor';
import EventManager from '../../../src/js/eventManager';

describe('Code', () => {
let cm, doc, mde;
let cm, doc, mde, $container;

beforeEach(() => {
const $container = $('<div />');
$container = $('<div />');

$('body').append($container);

@@ -27,7 +27,7 @@ describe('Code', () => {
});

afterEach(() => {
$('body').empty();
$container.remove();
});

it('Add code', () => {
@@ -53,4 +53,36 @@ describe('Code', () => {
expect(cm.getValue()).toEqual(['`mytext1`', '', 'mytext2', 'mytext3'].join('\n'));
expect(cm.getCursor().ch).toEqual(9);
});

it('should remove code for selection', () => {
cm.setValue('`mytext1`');

doc.setSelection({
line: 0,
ch: 0
}, {
line: 0,
ch: 9
});

Code.exec(mde);

expect(cm.getValue()).toEqual('mytext1');
});

it('should remove code syntax in the middle of the given range', () => {
cm.setValue('my`text`1');

doc.setSelection({
line: 0,
ch: 0
}, {
line: 0,
ch: 9
});

Code.exec(mde);

expect(cm.getValue()).toEqual('`mytext1`');
});
});
@@ -9,10 +9,10 @@ import MarkdownEditor from '../../../src/js/markdownEditor';
import EventManager from '../../../src/js/eventManager';

describe('Italic', () => {
let cm, doc, mde;
let cm, doc, mde, $container;

beforeEach(() => {
const $container = $('<div />');
$container = $('<div />');

$('body').append($container);

@@ -27,7 +27,7 @@ describe('Italic', () => {
});

afterEach(() => {
$('body').empty();
$container.remove();
});

describe('add italic', () => {
@@ -60,5 +60,21 @@ describe('Italic', () => {

expect(cm.getValue()).toEqual(['_mytext1_', '', 'mytext2', 'mytext3'].join('\n'));
});

it('should remove italic syntax in the middle of the given range', () => {
cm.setValue('my _text_ 1');

doc.setSelection({
line: 0,
ch: 0
}, {
line: 0,
ch: 11
});

Italic.exec(mde);

expect(cm.getValue()).toEqual('_my text 1_');
});
});
});

0 comments on commit 83bc877

Please sign in to comment.
You can’t perform that action at this time.