diff --git a/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx b/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx
index 47bc75536..7e5efd0eb 100644
--- a/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx
+++ b/app/javascript/crayons/MarkdownToolbar/MarkdownToolbar.jsx
@@ -4,6 +4,7 @@ import { ImageUploader } from '../../article-form/components/ImageUploader';
import {
coreSyntaxFormatters,
secondarySyntaxFormatters,
+ getNewTextAreaValueWithEdits,
} from './markdownSyntaxFormatters';
import { Overflow, Help } from './icons';
import { Button } from '@crayons';
@@ -181,12 +182,40 @@ export const MarkdownToolbar = ({ textAreaId }) => {
const insertSyntax = (syntaxName) => {
setOverflowMenuOpen(false);
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- markdownSyntaxFormatters[syntaxName].getFormatting(textArea);
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = markdownSyntaxFormatters[syntaxName].getFormatting(textArea);
- textArea.value = newTextAreaValue;
- textArea.dispatchEvent(new Event('input'));
+ // We try to update the textArea with document.execCommand, which requires the contentEditable attribute to be true.
+ // The value is later toggled back to 'false'
+ textArea.contentEditable = 'true';
textArea.focus({ preventScroll: true });
+ textArea.setSelectionRange(editSelectionStart, editSelectionEnd);
+
+ try {
+ // We first try to use execCommand which allows the change to be correctly added to the undo queue.
+ // document.execCommand is deprecated, but the API which will eventually replace it is still incoming (https://w3c.github.io/input-events/)
+ if (replaceSelectionWith === '') {
+ document.execCommand('delete', false);
+ } else {
+ document.execCommand('insertText', false, replaceSelectionWith);
+ }
+ } catch {
+ // In the event of any error using execCommand, we make sure the text area updates (but undo queue will not)
+ textArea.value = getNewTextAreaValueWithEdits({
+ textAreaValue: textArea.value,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+ }
+
+ textArea.contentEditable = 'false';
+ textArea.dispatchEvent(new Event('input'));
textArea.setSelectionRange(newCursorStart, newCursorEnd);
};
diff --git a/app/javascript/crayons/MarkdownToolbar/__tests__/markdownSyntaxFormatters.test.js b/app/javascript/crayons/MarkdownToolbar/__tests__/markdownSyntaxFormatters.test.js
index bf613d098..515ef4e65 100644
--- a/app/javascript/crayons/MarkdownToolbar/__tests__/markdownSyntaxFormatters.test.js
+++ b/app/javascript/crayons/MarkdownToolbar/__tests__/markdownSyntaxFormatters.test.js
@@ -1,6 +1,7 @@
import {
coreSyntaxFormatters,
secondarySyntaxFormatters,
+ getNewTextAreaValueWithEdits,
} from '../markdownSyntaxFormatters';
describe('markdownSyntaxFormatters', () => {
@@ -10,31 +11,55 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one **two** three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats an empty selection as bold, keeping cursor inside formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one ****two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(6);
expect(newCursorEnd).toEqual(6);
});
@@ -43,102 +68,174 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one **two** three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 11,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 11,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as bold, when only the start of the selection already has bold formatting', () => {
const textAreaValue = 'one **two three';
const expectedNewTextAreaValue = 'one ****two** three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('**two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '**two',
+ );
});
it('Formats a selection as bold, when only the end of the selection already has bold formatting', () => {
const textAreaValue = 'one two** three';
const expectedNewTextAreaValue = 'one **two**** three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two**');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two**',
+ );
});
it('Unformats a selection when text immediately before and after have bold formatting', () => {
const textAreaValue = 'one **two** three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 11,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 11,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as bold, when only the text immediately before already has bold formatting', () => {
const textAreaValue = 'one **two three';
const expectedNewTextAreaValue = 'one ****two** three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 6,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 6,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as bold, when only the text immediately after already has bold formatting', () => {
const textAreaValue = 'one two** three';
const expectedNewTextAreaValue = 'one **two**** three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['bold'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['bold'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
});
@@ -147,31 +244,55 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one _two_ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats an empty selection as italic, keeping cursor inside formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one __two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(5);
expect(newCursorEnd).toEqual(5);
});
@@ -180,102 +301,174 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one _two_ three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as italic, when only the start of the selection already has italic formatting', () => {
const textAreaValue = 'one _two three';
const expectedNewTextAreaValue = 'one __two_ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('_two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '_two',
+ );
});
it('Formats a selection as italic, when only the end of the selection already has italic formatting', () => {
const textAreaValue = 'one two_ three';
const expectedNewTextAreaValue = 'one _two__ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two_');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two_',
+ );
});
it('Unformats a selection when text immediately before and after have italic formatting', () => {
const textAreaValue = 'one _two_ three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 5,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 5,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as italic, when only the text immediately before already has italic formatting', () => {
const textAreaValue = 'one _two three';
const expectedNewTextAreaValue = 'one __two_ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 5,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 5,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as italic, when only the text immediately after already has italic formatting', () => {
const textAreaValue = 'one two_ three';
const expectedNewTextAreaValue = 'one _two__ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['italic'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['italic'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
});
@@ -284,31 +477,55 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one `two` three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats an empty selection as code, keeping cursor inside formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one ``two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(5);
expect(newCursorEnd).toEqual(5);
});
@@ -317,102 +534,174 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one `two` three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as code, when only the start of the selection already has code formatting', () => {
const textAreaValue = 'one `two three';
const expectedNewTextAreaValue = 'one ``two` three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('`two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '`two',
+ );
});
it('Formats a selection as code, when only the end of the selection already has code formatting', () => {
const textAreaValue = 'one two` three';
const expectedNewTextAreaValue = 'one `two`` three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two`');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two`',
+ );
});
it('Unformats a selection when text immediately before and after have code formatting', () => {
const textAreaValue = 'one `two` three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 5,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 5,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as code, when only the text immediately before already has italic formatting', () => {
const textAreaValue = 'one `two three';
const expectedNewTextAreaValue = 'one ``two` three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 5,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 5,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as code, when only the text immediately after already has code formatting', () => {
const textAreaValue = 'one two` three';
const expectedNewTextAreaValue = 'one `two`` three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['code'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['code'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
});
@@ -421,31 +710,55 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats an empty selection as underline, keeping cursor inside formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(7);
expect(newCursorEnd).toEqual(7);
});
@@ -454,102 +767,174 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 14,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 14,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as underline, when only the start of the selection already has underline formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 10,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 10,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as underline, when only the end of the selection already has underline formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 11,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 11,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Unformats a selection when text immediately before and after have underline formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 7,
- selectionEnd: 10,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 7,
+ selectionEnd: 10,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as underline, when only the text immediately before already has underline formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 7,
- selectionEnd: 10,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 7,
+ selectionEnd: 10,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as underline, when only the text immediately after already has underline formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['underline'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['underline'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
});
@@ -558,31 +943,55 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one ~~two~~ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats an empty selection as strikethrough, keeping cursor inside formatting', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one ~~~~two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(6);
expect(newCursorEnd).toEqual(6);
});
@@ -591,102 +1000,174 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one ~~two~~ three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 11,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 11,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as strikethrough, when only the start of the selection already has strikethrough formatting', () => {
const textAreaValue = 'one ~~two three';
const expectedNewTextAreaValue = 'one ~~~~two~~ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('~~two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '~~two',
+ );
});
it('Formats a selection as strikethrough, when only the end of the selection already has strikethrough formatting', () => {
const textAreaValue = 'one two~~ three';
const expectedNewTextAreaValue = 'one ~~two~~~~ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two~~');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two~~',
+ );
});
it('Unformats a selection when text immediately before and after have strikethrough formatting', () => {
const textAreaValue = 'one ~~two~~ three';
const expectedNewTextAreaValue = 'one two three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 6,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 6,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as strikethrough, when only the text immediately before already has strikethrough formatting', () => {
const textAreaValue = 'one ~~two three';
const expectedNewTextAreaValue = 'one ~~~~two~~ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 6,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 6,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('Formats a selection as strikethrough, when only the text immediately after already has strikethrough formatting', () => {
const textAreaValue = 'one two~~ three';
const expectedNewTextAreaValue = 'one ~~two~~~~ three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['strikethrough'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['strikethrough'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
});
@@ -695,48 +1176,84 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two [](url)three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 8,
- selectionEnd: 8,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 8,
+ selectionEnd: 8,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('url');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'url',
+ );
});
it('inserts link markdown, and highlights url when selected text does not begin with http:// or https://', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one [two](url) three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('url');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'url',
+ );
});
it('inserts link markdown, and places cursor inside [], when selected text begins with http://', () => {
const textAreaValue = 'one http://something.com three';
const expectedNewTextAreaValue = 'one [](http://something.com) three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 24,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 24,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(5);
expect(newCursorEnd).toEqual(5);
});
@@ -745,14 +1262,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one https://something.com three';
const expectedNewTextAreaValue = 'one [](https://something.com) three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 25,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 25,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(5);
expect(newCursorEnd).toEqual(5);
});
@@ -761,14 +1290,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one [](url) three';
const expectedNewTextAreaValue = 'one three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 5,
- selectionEnd: 5,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 5,
+ selectionEnd: 5,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(4);
expect(newCursorEnd).toEqual(4);
});
@@ -777,14 +1318,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one [](url) three';
const expectedNewTextAreaValue = 'one three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 7,
- selectionEnd: 10,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 7,
+ selectionEnd: 10,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(4);
expect(newCursorEnd).toEqual(4);
});
@@ -793,51 +1346,87 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one [something](url) three';
const expectedNewTextAreaValue = 'one something three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 16,
- selectionEnd: 19,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 16,
+ selectionEnd: 19,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('something');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'something',
+ );
});
it('removes link markdown when selected text is a url and full markdown formatting present, no link description', () => {
const textAreaValue = 'one [](http://example.com) three';
const expectedNewTextAreaValue = 'one http://example.com three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 7,
- selectionEnd: 25,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 7,
+ selectionEnd: 25,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('http://example.com');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'http://example.com',
+ );
});
it('removes link markdown when url is selected, and full markdown formatting present, link description present', () => {
const textAreaValue = 'one [something](http://example.com) three';
const expectedNewTextAreaValue = 'one something three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 16,
- selectionEnd: 34,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 16,
+ selectionEnd: 34,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('something');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'something',
+ );
});
it('removes link markdown when full markdown syntax is selected, preserving link description', () => {
@@ -845,48 +1434,84 @@ describe('markdownSyntaxFormatters', () => {
'one [text description](http://example.com) three';
const expectedNewTextAreaValue = 'one text description three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 42,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 42,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('text description');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'text description',
+ );
});
it('removes link markdown when full markdown syntax is selected, preserving URL if link description does not exist', () => {
const textAreaValue = 'one [](http://example.com) three';
const expectedNewTextAreaValue = 'one http://example.com three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 26,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 26,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('http://example.com');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'http://example.com',
+ );
});
it('removes link markdown when full markdown syntax is selected, preserving no content if no link description exists, and URL is placeholder', () => {
const textAreaValue = 'one [](url) three';
const expectedNewTextAreaValue = 'one three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['link'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 11,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['link'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 11,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(4);
expect(newCursorEnd).toEqual(4);
});
@@ -899,82 +1524,142 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n1. two\n three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. two',
+ );
});
it('formats multiple lines of text as an ordered list', () => {
const textAreaValue = 'one\ntwo\nthree';
const expectedNewTextAreaValue = '1. one\n2. two\n3. three\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 13,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 13,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. one\n2. two\n3. three');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. one\n2. two\n3. three',
+ );
});
it('inserts an empty list when no selection is provided', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n1. \ntwo three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '',
+ );
});
it('unformats a single line of text if selection starts with ordered list format', () => {
const textAreaValue = 'one\n1. two\nthree';
const expectedNewTextAreaValue = 'one\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 10,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 10,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('unformats a single line of text if no selection is given, and current line start contains 1. ', () => {
const textAreaValue = 'one\n\n1. two\nthree';
const expectedNewTextAreaValue = 'one\n\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 9,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(6);
expect(newCursorEnd).toEqual(6);
});
@@ -983,119 +1668,203 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = '1. one\n2. two\n3. three';
const expectedNewTextAreaValue = 'one\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 22,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 22,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ expectedNewTextAreaValue,
+ );
});
it("formats as an ordered list if at least one line of selection doesn't match ordered list format", () => {
const textAreaValue = '1. one\ntwo\n3. three';
const expectedNewTextAreaValue = '1. 1. one\n2. two\n3. 3. three\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 19,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 19,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. 1. one\n2. two\n3. 3. three');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. 1. one\n2. two\n3. 3. three',
+ );
});
it("doesn't add new lines before list, if at the beginning of text area", () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '1. one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. one',
+ );
});
it('adds one new line before list, if directly preceded by a single new line', () => {
const textAreaValue = '\none';
const expectedNewTextAreaValue = '\n\n1. one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 1,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 1,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. one',
+ );
});
it('adds two new lines before list, if no new lines already exist before it', () => {
const textAreaValue = 'one two';
const expectedNewTextAreaValue = 'one \n\n1. two\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. two',
+ );
});
it("doesn't add a new line after list if one already exists", () => {
const textAreaValue = 'one\n';
const expectedNewTextAreaValue = '1. one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. one',
+ );
});
it('adds a new line after list if none exists', () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '1. one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['orderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['orderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('1. one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '1. one',
+ );
});
});
@@ -1104,203 +1873,347 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n- two\n three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- two',
+ );
});
it('formats multiple lines of text as an unordered list', () => {
const textAreaValue = 'one\ntwo\nthree';
const expectedNewTextAreaValue = '- one\n- two\n- three\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 13,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 13,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- one\n- two\n- three');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- one\n- two\n- three',
+ );
});
it('inserts an empty list when no selection is provided', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n- \ntwo three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '',
+ );
});
it('unformats a single line of text if selection starts with unordered list format', () => {
const textAreaValue = 'one\n- two\nthree';
const expectedNewTextAreaValue = 'one\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('unformats a single line of text if no selection is given, and current line only contains - ', () => {
- const textAreaValue = 'one\n\n- two\nthree';
- const expectedNewTextAreaValue = 'one\n\ntwo\nthree';
+ const textAreaValue = 'one\n\n- \ntwo';
+ const expectedNewTextAreaValue = 'one\n\n\ntwo';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 7,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(newCursorStart).toEqual(7);
- expect(newCursorEnd).toEqual(7);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(newCursorStart).toEqual(5);
+ expect(newCursorEnd).toEqual(5);
});
it('unformats multiple lines of text if every line starts with unordered list format', () => {
const textAreaValue = '- one\n- two\n- three';
const expectedNewTextAreaValue = 'one\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 20,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 20,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual(newTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ expectedNewTextAreaValue,
+ );
});
it("formats as an unordered list if at least one line of selection doesn't match unordered list format", () => {
const textAreaValue = '- one\ntwo\n- three';
const expectedNewTextAreaValue = '- - one\n- two\n- - three\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 17,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 17,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- - one\n- two\n- - three');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- - one\n- two\n- - three',
+ );
});
it("doesn't add new lines before list, if at the beginning of text area", () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '- one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- one',
+ );
});
it('adds one new line before list, if directly preceded by a single new line', () => {
const textAreaValue = '\none';
const expectedNewTextAreaValue = '\n\n- one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 1,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 1,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- one',
+ );
});
it('adds two new lines before list, if no new lines already exist before it', () => {
const textAreaValue = 'one two';
const expectedNewTextAreaValue = 'one \n\n- two\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- two',
+ );
});
it("doesn't add a new line after list if one already exists", () => {
const textAreaValue = 'one\n';
const expectedNewTextAreaValue = '- one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- one',
+ );
});
it('adds a new line after list if none exists', () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '- one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['unorderedList'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['unorderedList'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('- one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '- one',
+ );
});
});
@@ -1309,14 +2222,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n## \ntwo three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(9);
expect(newCursorEnd).toEqual(9);
});
@@ -1325,14 +2250,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n## two\n three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(9);
expect(newCursorEnd).toEqual(12);
});
@@ -1341,14 +2278,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one\n\n## two\nthree';
const expectedNewTextAreaValue = 'one\n\n### two\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 11,
- selectionEnd: 11,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 11,
+ selectionEnd: 11,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(12);
expect(newCursorEnd).toEqual(12);
});
@@ -1357,14 +2306,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one\n\n## two\nthree';
const expectedNewTextAreaValue = 'one\n\n### two\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 8,
- selectionEnd: 11,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 8,
+ selectionEnd: 11,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(9);
expect(newCursorEnd).toEqual(12);
});
@@ -1373,14 +2334,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one\n\n### two\nthree';
const expectedNewTextAreaValue = 'one\n\n#### two\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 12,
- selectionEnd: 12,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 12,
+ selectionEnd: 12,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(13);
expect(newCursorEnd).toEqual(13);
});
@@ -1389,14 +2362,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one\n\n### two\nthree';
const expectedNewTextAreaValue = 'one\n\n#### two\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 12,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 9,
+ selectionEnd: 12,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(10);
expect(newCursorEnd).toEqual(13);
});
@@ -1405,14 +2390,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one\n\n#### two\nthree';
const expectedNewTextAreaValue = 'one\n\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 13,
- selectionEnd: 13,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 13,
+ selectionEnd: 13,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(8);
expect(newCursorEnd).toEqual(8);
});
@@ -1421,14 +2418,26 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one\n\n#### two\nthree';
const expectedNewTextAreaValue = 'one\n\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 10,
- selectionEnd: 13,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 10,
+ selectionEnd: 13,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(5);
expect(newCursorEnd).toEqual(8);
});
@@ -1437,85 +2446,145 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '## one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds one new line before heading, if directly preceded by a single new line', () => {
const textAreaValue = '\none';
const expectedNewTextAreaValue = '\n\n## one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 1,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 1,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds two new lines before heading, if no new lines already exist before it', () => {
const textAreaValue = 'one two';
const expectedNewTextAreaValue = 'one \n\n## two\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it("doesn't add a new line after heading if one already exists", () => {
const textAreaValue = 'one\n';
const expectedNewTextAreaValue = '## one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds a new line after heading if none exists', () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '## one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['heading'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['heading'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
});
@@ -1524,203 +2593,347 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n> two\n three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> two',
+ );
});
it('formats multiple lines of text as a quote', () => {
const textAreaValue = 'one\ntwo\nthree';
const expectedNewTextAreaValue = '> one\n> two\n> three\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 13,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 13,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> one\n> two\n> three');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> one\n> two\n> three',
+ );
});
it('inserts an empty quote when no selection is provided', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n> \ntwo three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '',
+ );
});
it('unformats a single line of text if selection starts with quote format', () => {
const textAreaValue = 'one\n> two\nthree';
const expectedNewTextAreaValue = 'one\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('unformats a single line of text if no selection is given, and current line only contains > ', () => {
- const textAreaValue = 'one\n\n> two\nthree';
- const expectedNewTextAreaValue = 'one\n\ntwo\nthree';
+ const textAreaValue = 'one\n\n> \ntwo';
+ const expectedNewTextAreaValue = 'one\n\n\ntwo';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 7,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(newCursorStart).toEqual(7);
- expect(newCursorEnd).toEqual(7);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(newCursorStart).toEqual(5);
+ expect(newCursorEnd).toEqual(5);
});
it('unformats multiple lines of text if every line starts with quote format', () => {
const textAreaValue = '> one\n> two\n> three';
const expectedNewTextAreaValue = 'one\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 20,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 20,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual(newTextAreaValue);
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ expectedNewTextAreaValue,
+ );
});
it("formats as a quote if at least one line of selection doesn't match quote format", () => {
const textAreaValue = '> one\ntwo\n> three';
const expectedNewTextAreaValue = '> > one\n> two\n> > three\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 17,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 17,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> > one\n> two\n> > three');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> > one\n> two\n> > three',
+ );
});
it("doesn't add new lines before quote, if at the beginning of text area", () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '> one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> one',
+ );
});
it('adds one new line before quote, if directly preceded by a single new line', () => {
const textAreaValue = '\none';
const expectedNewTextAreaValue = '\n\n> one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 1,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 1,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> one',
+ );
});
it('adds two new lines before quote, if no new lines already exist before it', () => {
const textAreaValue = 'one two';
const expectedNewTextAreaValue = 'one \n\n> two\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> two',
+ );
});
it("doesn't add a new line after quote if one already exists", () => {
const textAreaValue = 'one\n';
const expectedNewTextAreaValue = '> one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> one',
+ );
});
it('adds a new line after quote if none exists', () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '> one\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['quote'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['quote'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('> one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '> one',
+ );
});
});
@@ -1729,204 +2942,348 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n```\ntwo\n```\n three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('formats multiple lines of text as a code block', () => {
const textAreaValue = 'one\ntwo\nthree';
const expectedNewTextAreaValue = '```\none\ntwo\nthree\n```\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 13,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 13,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one\ntwo\nthree');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one\ntwo\nthree',
+ );
});
it('inserts an empty code block when no selection is provided', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n```\n\n```\ntwo three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '',
+ );
});
it('unformats a single line of text if selection is wrapped in a code block', () => {
const textAreaValue = 'one\n\n```\ntwo\n```\nthree';
const expectedNewTextAreaValue = 'one\n\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 12,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 9,
+ selectionEnd: 12,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('unformats multiple lines of text if selection is wrapped in a code block', () => {
const textAreaValue = 'one\n\n```\ntwo\nthree\n```\nfour';
const expectedNewTextAreaValue = 'one\n\ntwo\nthree\nfour';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 18,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 9,
+ selectionEnd: 18,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two\nthree');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two\nthree',
+ );
});
it('unformats if no selection is given, but cursor is wrapped in a code block', () => {
const textAreaValue = 'one\n\n```\n\n```\ntwo';
const expectedNewTextAreaValue = 'one\n\n\ntwo';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 9,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '',
+ );
});
it('unformats if selection starts and ends with code block formatting', () => {
const textAreaValue = 'one\n\n```\ntwo\n```\nthree';
const expectedNewTextAreaValue = 'one\n\ntwo\nthree';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 5,
- selectionEnd: 16,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 5,
+ selectionEnd: 16,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it("doesn't add new lines before code block, if at the beginning of text area", () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '```\none\n```\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds one new line before code block, if directly preceded by a single new line', () => {
const textAreaValue = '\none';
const expectedNewTextAreaValue = '\n\n```\none\n```\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 1,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 1,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds two new lines before code block, if no new lines already exist before it', () => {
const textAreaValue = 'one two';
const expectedNewTextAreaValue = 'one \n\n```\ntwo\n```\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it("doesn't add a new line after code block if one already exists", () => {
const textAreaValue = 'one\n';
const expectedNewTextAreaValue = '```\none\n```\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds a new line after code block if none exists', () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '```\none\n```\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- coreSyntaxFormatters['codeBlock'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = coreSyntaxFormatters['codeBlock'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
});
@@ -1935,134 +3292,230 @@ describe('markdownSyntaxFormatters', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n---\n\ntwo three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '',
+ );
});
it('inserts any selected text after the divider', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one \n\n---\ntwo\n three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it('removes the divider if no selected text, and cursor directly preceded by line formatting', () => {
const textAreaValue = 'one\n\n---\ntwo';
const expectedNewTextAreaValue = 'one\n\ntwo';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 9,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 9,
+ selectionEnd: 9,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ '',
+ );
});
it('removes the divider if selected text is directly preceded by line formatting', () => {
const textAreaValue = 'one\n\n---\ntwo three';
const expectedNewTextAreaValue = 'one\n\ntwo three';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 9,
- selectionEnd: 12,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 9,
+ selectionEnd: 12,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it("doesn't add new lines before divider, if at the beginning of text area", () => {
const textAreaValue = 'one';
const expectedNewTextAreaValue = '---\none\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds one new line before divider, if directly preceded by a single new line', () => {
const textAreaValue = '\none';
const expectedNewTextAreaValue = '\n\n---\none\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 1,
- selectionEnd: 4,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 1,
+ selectionEnd: 4,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
it('adds two new lines before divider, if no new lines already exist before it', () => {
const textAreaValue = 'one two';
const expectedNewTextAreaValue = 'one \n\n---\ntwo\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 4,
- selectionEnd: 7,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 4,
+ selectionEnd: 7,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('two');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'two',
+ );
});
it("doesn't add a new line after divider if one already exists", () => {
const textAreaValue = 'one\n';
const expectedNewTextAreaValue = '---\none\n';
- const { newTextAreaValue, newCursorStart, newCursorEnd } =
- secondarySyntaxFormatters['divider'].getFormatting({
- value: textAreaValue,
- selectionStart: 0,
- selectionEnd: 3,
- });
+ const {
+ newCursorStart,
+ newCursorEnd,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ } = secondarySyntaxFormatters['divider'].getFormatting({
+ value: textAreaValue,
+ selectionStart: 0,
+ selectionEnd: 3,
+ });
- expect(newTextAreaValue).toEqual(expectedNewTextAreaValue);
- expect(
- newTextAreaValue.substring(newCursorStart, newCursorEnd),
- ).toEqual('one');
+ const editedString = getNewTextAreaValueWithEdits({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+ });
+
+ expect(editedString).toEqual(expectedNewTextAreaValue);
+ expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
+ 'one',
+ );
});
});
});
diff --git a/app/javascript/crayons/MarkdownToolbar/markdownSyntaxFormatters.js b/app/javascript/crayons/MarkdownToolbar/markdownSyntaxFormatters.js
index f05639c3f..4cf0a0806 100644
--- a/app/javascript/crayons/MarkdownToolbar/markdownSyntaxFormatters.js
+++ b/app/javascript/crayons/MarkdownToolbar/markdownSyntaxFormatters.js
@@ -65,7 +65,9 @@ const handleLinkFormattingForEmptyTextSelection = ({
selectionEnd,
}) => {
const basicFormattingForEmptySelection = {
- newTextAreaValue: `${textBeforeSelection}[](${URL_PLACEHOLDER_TEXT})${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: `[](${URL_PLACEHOLDER_TEXT})`,
newCursorStart: selectionStart + 3,
newCursorEnd: selectionEnd + 6,
};
@@ -93,9 +95,9 @@ const handleLinkFormattingForEmptyTextSelection = ({
const urlText = value.slice(selectionEnd + 2, indexOfLinkStructureEnd);
return {
- newTextAreaValue: `${textBeforeSelection.slice(0, -1)}${
- urlText === URL_PLACEHOLDER_TEXT ? '' : urlText
- }${value.slice(indexOfLinkStructureEnd + 1)}`,
+ editSelectionStart: selectionStart - 1,
+ editSelectionEnd: indexOfLinkStructureEnd + 1,
+ replaceSelectionWith: urlText === URL_PLACEHOLDER_TEXT ? '' : urlText,
newCursorStart: selectionStart - 1,
newCursorEnd: selectionEnd - 1,
};
@@ -106,10 +108,13 @@ const handleLinkFormattingForUrlSelection = ({
textAfterSelection,
value,
selectionStart,
+ selectionEnd,
selectedText,
}) => {
const basicFormattingForLinkSelection = {
- newTextAreaValue: `${textBeforeSelection}[](${selectedText})${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: `[](${selectedText})`,
newCursorStart: selectionStart + 1,
newCursorEnd: selectionStart + 1,
};
@@ -145,10 +150,9 @@ const handleLinkFormattingForUrlSelection = ({
}
return {
- newTextAreaValue: `${textBeforeSelection.slice(
- 0,
- indexOfSyntaxOpen,
- )}${textToReplaceMarkdown}${textAfterSelection.slice(1)}`,
+ editSelectionStart: indexOfSyntaxOpen,
+ editSelectionEnd: selectionEnd + 1,
+ replaceSelectionWith: textToReplaceMarkdown,
newCursorStart: indexOfSyntaxOpen,
newCursorEnd: indexOfSyntaxOpen + textToReplaceMarkdown.length,
};
@@ -157,8 +161,7 @@ const handleLinkFormattingForUrlSelection = ({
const handleUndoMarkdownLinkSelection = ({
selectedText,
selectionStart,
- textBeforeSelection,
- textAfterSelection,
+ selectionEnd,
}) => {
const linkDescriptionEnd = getNextIndexOfCharacter({
content: selectedText,
@@ -175,7 +178,9 @@ const handleUndoMarkdownLinkSelection = ({
}
return {
- newTextAreaValue: `${textBeforeSelection}${textToReplaceMarkdown}${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: textToReplaceMarkdown,
newCursorStart: selectionStart,
newCursorEnd: selectionStart + textToReplaceMarkdown.length,
};
@@ -205,10 +210,9 @@ const undoOrAddFormattingForInlineSyntax = ({
if (selectedTextAlreadyFormatted) {
return {
- newTextAreaValue: `${textBeforeSelection}${selectedText.slice(
- prefixLength,
- -1 * suffixLength,
- )}${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: selectedText.slice(prefixLength, -1 * suffixLength),
newCursorStart: selectionStart,
newCursorEnd: selectionEnd - (prefixLength + suffixLength),
};
@@ -221,10 +225,9 @@ const undoOrAddFormattingForInlineSyntax = ({
if (surroundingTextHasFormatting) {
return {
- newTextAreaValue: `${textBeforeSelection.slice(
- 0,
- -1 * prefixLength,
- )}${selectedText}${textAfterSelection.slice(suffixLength)}`,
+ editSelectionStart: selectionStart - prefixLength,
+ editSelectionEnd: selectionEnd + suffixLength,
+ replaceSelectionWith: selectedText,
newCursorStart: selectionStart - prefixLength,
newCursorEnd: selectionEnd - prefixLength,
};
@@ -232,7 +235,9 @@ const undoOrAddFormattingForInlineSyntax = ({
// No formatting to undo - format the selected text
return {
- newTextAreaValue: `${textBeforeSelection}${prefix}${selectedText}${suffix}${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: `${prefix}${selectedText}${suffix}`,
newCursorStart: selectionStart + prefixLength,
newCursorEnd: selectionEnd + prefixLength,
};
@@ -255,25 +260,28 @@ const undoOrAddFormattingForMultilineSyntax = ({
const { length: prefixLength } = linePrefix;
// If no selection, check if we're in a freshly inserted syntax
- if (selectedText === '' && textBeforeSelection !== '') {
- const lastNewLine = getLastIndexOfCharacter({
- content: value,
- selectionIndex: selectionStart - 1,
- character: '\n',
- });
+ if (selectedText === '') {
+ const lastNewLine =
+ textBeforeSelection === ''
+ ? -1
+ : getLastIndexOfCharacter({
+ content: value,
+ selectionIndex: selectionStart - 1,
+ character: '\n',
+ });
+
+ const lineStart = lastNewLine === -1 ? 0 : lastNewLine + 1;
if (
- lastNewLine !== -1 &&
- textBeforeSelection.slice(
- lastNewLine + 1,
- lastNewLine + prefixLength + 1,
- ) === linePrefix
+ textBeforeSelection.slice(lineStart, lineStart + prefixLength) ===
+ linePrefix
) {
// Remove the list formatting
+
return {
- newTextAreaValue: `${value.slice(0, lastNewLine + 1)}${value.slice(
- lastNewLine + prefixLength + 1,
- )}`,
+ editSelectionStart: lineStart,
+ editSelectionEnd: lineStart + prefixLength,
+ replaceSelectionWith: '',
newCursorStart: selectionStart - prefixLength,
newCursorEnd: selectionEnd - prefixLength,
};
@@ -298,7 +306,9 @@ const undoOrAddFormattingForMultilineSyntax = ({
.join('\n');
return {
- newTextAreaValue: `${textBeforeSelection}${unformattedText}${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: unformattedText,
newCursorStart: selectionStart,
newCursorEnd:
selectionEnd + (unformattedText.length - selectedText.length),
@@ -322,10 +332,12 @@ const undoOrAddFormattingForMultilineSyntax = ({
if (selectionIsFormatted) {
return {
- newTextAreaValue: `${textBeforeSelection}${selectedText.slice(
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: selectedText.slice(
prefixLength,
-1 * suffixLength,
- )}${textAfterSelection}`,
+ ),
newCursorStart: selectionStart,
newCursorEnd: selectionEnd - prefixLength - suffixLength,
};
@@ -338,10 +350,9 @@ const undoOrAddFormattingForMultilineSyntax = ({
if (surroundingTextIsFormatted) {
return {
- newTextAreaValue: `${textBeforeSelection.slice(
- 0,
- -1 * prefixLength,
- )}${selectedText}${textAfterSelection.slice(suffixLength)}`,
+ editSelectionStart: selectionStart - prefixLength,
+ editSelectionEnd: selectionEnd + suffixLength,
+ replaceSelectionWith: selectedText,
newCursorStart: selectionStart - prefixLength,
newCursorEnd: selectionEnd - prefixLength,
};
@@ -357,20 +368,17 @@ const undoOrAddFormattingForMultilineSyntax = ({
});
const { length: newLinePrefixLength } = newLinesPrefix;
- // Multiline insertions should occur after two new lines (whether added already by user or inserted automatically)
- const newtextBeforeSelection = `${textBeforeSelection}${newLinesPrefix}`;
-
const cursorStartBaseline = selectionStart + newLinePrefixLength;
const cursorStartBlockPrefixOffset = blockPrefix ? blockPrefix.length : 0;
const cursorStartLinePrefixOffset =
selectedText === '' && linePrefix ? linePrefix.length : 0;
return {
- newTextAreaValue: `${newtextBeforeSelection}${
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: `${newLinesPrefix}${
blockPrefix ? blockPrefix : ''
- }${formattedText}${
- blockSuffix ? blockSuffix : ''
- }${newLinesSuffix}${textAfterSelection}`,
+ }${formattedText}${blockSuffix ? blockSuffix : ''}${newLinesSuffix}`,
newCursorStart:
cursorStartBaseline +
cursorStartBlockPrefixOffset +
@@ -384,6 +392,17 @@ const undoOrAddFormattingForMultilineSyntax = ({
};
};
+export const getNewTextAreaValueWithEdits = ({
+ textAreaValue,
+ editSelectionStart,
+ editSelectionEnd,
+ replaceSelectionWith,
+}) =>
+ `${textAreaValue.substring(
+ 0,
+ editSelectionStart,
+ )}${replaceSelectionWith}${textAreaValue.substring(editSelectionEnd)}`;
+
export const coreSyntaxFormatters = {
bold: {
icon: Bold,
@@ -468,6 +487,7 @@ export const coreSyntaxFormatters = {
return handleUndoMarkdownLinkSelection({
selectedText,
selectionStart,
+ selectionEnd,
textBeforeSelection,
textAfterSelection,
});
@@ -475,7 +495,9 @@ export const coreSyntaxFormatters = {
// Finally, handle the case where link syntax is inserted for a selection other than a URL
return {
- newTextAreaValue: `${textBeforeSelection}[${selectedText}](${URL_PLACEHOLDER_TEXT})${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: `[${selectedText}](${URL_PLACEHOLDER_TEXT})`,
newCursorStart: selectionStart + selectedText.length + 3,
newCursorEnd: selectionEnd + 6,
};
@@ -485,8 +507,11 @@ export const coreSyntaxFormatters = {
icon: OrderedList,
label: 'Ordered list',
getFormatting: ({ selectionStart, selectionEnd, value }) => {
- const { selectedText, textBeforeSelection, textAfterSelection } =
- getSelectionData({ selectionStart, selectionEnd, value });
+ const { selectedText, textBeforeSelection } = getSelectionData({
+ selectionStart,
+ selectionEnd,
+ value,
+ });
const { newLinesPrefix, newLinesSuffix } = getNewLinePrefixSuffixes({
selectionStart,
@@ -496,23 +521,25 @@ export const coreSyntaxFormatters = {
const { length: newLinePrefixLength } = newLinesPrefix;
const { length: newLineSuffixLength } = newLinesSuffix;
- if (selectedText === '' && textBeforeSelection !== '') {
+ if (selectedText === '') {
// Check start of line for whether we're in an empty ordered list
- const lastNewLine = getLastIndexOfCharacter({
- content: value,
- selectionIndex: selectionStart - 1,
- character: '\n',
- });
+ const lastNewLine =
+ textBeforeSelection === ''
+ ? -1
+ : getLastIndexOfCharacter({
+ content: value,
+ selectionIndex: selectionStart - 1,
+ character: '\n',
+ });
- if (
- lastNewLine !== -1 &&
- textBeforeSelection.slice(lastNewLine + 1, lastNewLine + 4) === '1. '
- ) {
+ const lineStart = lastNewLine === -1 ? 0 : lastNewLine + 1;
+
+ if (textBeforeSelection.slice(lineStart, lineStart + 3) === '1. ') {
// Remove the list formatting
return {
- newTextAreaValue: `${value.slice(0, lastNewLine + 1)}${value.slice(
- lastNewLine + 4,
- )}`,
+ editSelectionStart: lineStart,
+ editSelectionEnd: lineStart + 3,
+ replaceSelectionWith: '',
newCursorStart: selectionStart - 3,
newCursorEnd: selectionEnd - 3,
};
@@ -522,7 +549,9 @@ export const coreSyntaxFormatters = {
if (selectedText === '') {
// Otherwise insert an empty list for an empty selection
return {
- newTextAreaValue: `${textBeforeSelection}${newLinesPrefix}1. ${newLinesSuffix}${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: `${newLinesPrefix}1. ${newLinesSuffix}`,
newCursorStart: selectionStart + 3 + newLinePrefixLength,
newCursorEnd: selectionEnd + 3 + newLinePrefixLength,
};
@@ -545,7 +574,9 @@ export const coreSyntaxFormatters = {
.join('\n');
return {
- newTextAreaValue: `${textBeforeSelection}${newText}${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: newText,
newCursorStart: selectionStart + selectedText.indexOf('.') - 1,
newCursorEnd: selectionEnd + newText.length - selectedText.length,
};
@@ -559,7 +590,9 @@ export const coreSyntaxFormatters = {
selectedText.length === 0 ? 4 : newLinePrefixLength;
return {
- newTextAreaValue: `${textBeforeSelection}${formattedList}${textAfterSelection}`,
+ editSelectionStart: selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: formattedList,
newCursorStart: selectionStart + cursorOffsetStart,
newCursorEnd:
selectionStart + formattedList.length - newLineSuffixLength,
@@ -601,12 +634,11 @@ export const coreSyntaxFormatters = {
}
}
- const { selectedText, textBeforeSelection, textAfterSelection } =
- getSelectionData({
- selectionStart: currentLineSelectionStart,
- selectionEnd,
- value,
- });
+ const { selectedText } = getSelectionData({
+ selectionStart: currentLineSelectionStart,
+ selectionEnd,
+ value,
+ });
let currentHeadingIndex = 0;
while (selectedText.charAt(currentHeadingIndex) === '#') {
@@ -616,9 +648,9 @@ export const coreSyntaxFormatters = {
// After h4, revert to no heading at all
if (currentHeadingIndex >= 4) {
return {
- newTextAreaValue: `${textBeforeSelection}${selectedText.substring(
- 5,
- )}${textAfterSelection}`,
+ editSelectionStart: currentLineSelectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: selectedText.substring(5),
newCursorStart: selectionStart - 5,
newCursorEnd: selectionEnd - 5,
};
@@ -635,9 +667,13 @@ export const coreSyntaxFormatters = {
const cursorOffset = adjustingHeading ? 1 : 3 + newLinePrefixLength;
return {
- newTextAreaValue: adjustingHeading
- ? `${textBeforeSelection}#${selectedText}${textAfterSelection}`
- : `${textBeforeSelection}${newLinesPrefix}## ${selectedText}${newLinesSuffix}${textAfterSelection}`,
+ editSelectionStart: adjustingHeading
+ ? currentLineSelectionStart
+ : selectionStart,
+ editSelectionEnd: selectionEnd,
+ replaceSelectionWith: adjustingHeading
+ ? `#${selectedText}`
+ : `${newLinesPrefix}## ${selectedText}${newLinesSuffix}`,
newCursorStart: selectionStart + cursorOffset,
newCursorEnd: selectionEnd + cursorOffset,
};