Feature/add embed icon to editor toolbar (#17781)

* Finished task 1 and task 3

* Task 2:  If the user already has text selected inside syntax

* Added comments

* Tests added

* Nit fixes

* Code optimisation

* Nit fixes

* Fix typo

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>

* Removed console log statements

* Minor fix

* Simplified code

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
This commit is contained in:
Rajat Talesra 2022-06-10 17:33:23 +05:30 committed by GitHub
parent 686be06009
commit 27c6f07686
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 169 additions and 0 deletions

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M13 9h8L11 24v-9H4l9-15v9Zm-2 2V7.22L7.532 13H13v4.394L17.263 11H11Z"/>
</svg>

After

Width:  |  Height:  |  Size: 176 B

View file

@ -41,6 +41,7 @@ describe('<MarkdownToolbar />', () => {
expect(getByLabelText('Quote')).toBeInTheDocument();
expect(getByLabelText('Code')).toBeInTheDocument();
expect(getByLabelText('Code block')).toBeInTheDocument();
expect(getByLabelText('Embed')).toBeInTheDocument();
});
it('should render an overflow menu with secondary formatters and help link', async () => {

View file

@ -1516,6 +1516,151 @@ describe('markdownSyntaxFormatters', () => {
expect(newCursorEnd).toEqual(4);
});
});
describe('embed', () => {
it('inserts embed syntax and place cursor inside embed syntax, when no selection is given', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one two {% embed %}three';
const {
newCursorStart,
newCursorEnd,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
} = coreSyntaxFormatters['embed'].getFormatting({
value: textAreaValue,
selectionStart: 8,
selectionEnd: 8,
});
const editedString = getNewTextAreaValueWithEdits({
textAreaValue,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
});
expect(editedString).toEqual(expectedNewTextAreaValue);
expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
'',
);
});
it('inserts embed syntax and highlights text, when text is selected', () => {
const textAreaValue = 'one two three';
const expectedNewTextAreaValue = 'one {% embed two %} three';
const {
newCursorStart,
newCursorEnd,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
} = coreSyntaxFormatters['embed'].getFormatting({
value: textAreaValue,
selectionStart: 4,
selectionEnd: 7,
});
const editedString = getNewTextAreaValueWithEdits({
textAreaValue,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
});
expect(editedString).toEqual(expectedNewTextAreaValue);
expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
'two',
);
});
it('removes embed syntax, when cursor is inside empty embed syntax', () => {
const textAreaValue = 'one {% embed %} two';
const expectedNewTextAreaValue = 'one two';
const {
newCursorStart,
newCursorEnd,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
} = coreSyntaxFormatters['embed'].getFormatting({
value: textAreaValue,
selectionStart: 13,
selectionEnd: 13,
});
const editedString = getNewTextAreaValueWithEdits({
textAreaValue,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
});
expect(editedString).toEqual(expectedNewTextAreaValue);
expect(newCursorStart).toEqual(4);
expect(newCursorEnd).toEqual(4);
});
it('removes embed syntax and highlights the selected text, when selected text is inside embed syntax', () => {
const textAreaValue = 'one {% embed random-selected-text %} three';
const expectedNewTextAreaValue = 'one random-selected-text three';
const {
newCursorStart,
newCursorEnd,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
} = coreSyntaxFormatters['embed'].getFormatting({
value: textAreaValue,
selectionStart: 13,
selectionEnd: 33,
});
const editedString = getNewTextAreaValueWithEdits({
textAreaValue,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
});
expect(editedString).toEqual(expectedNewTextAreaValue);
expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
'random-selected-text',
);
});
it('removes embed syntax and highlights the text, when full embed syntax is selected', () => {
const textAreaValue = 'one {% embed https://example.com %} three';
const expectedNewTextAreaValue = 'one https://example.com three';
const {
newCursorStart,
newCursorEnd,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
} = coreSyntaxFormatters['embed'].getFormatting({
value: textAreaValue,
selectionStart: 4,
selectionEnd: 35,
});
const editedString = getNewTextAreaValueWithEdits({
textAreaValue,
editSelectionStart,
editSelectionEnd,
replaceSelectionWith,
});
expect(editedString).toEqual(expectedNewTextAreaValue);
expect(editedString.substring(newCursorStart, newCursorEnd)).toEqual(
'https://example.com',
);
});
});
});
describe('multiline formatters', () => {

View file

@ -16,6 +16,7 @@ import HeadingIcon from '@images/heading.svg';
import QuoteIcon from '@images/quote.svg';
import CodeIcon from '@images/code.svg';
import CodeBlockIcon from '@images/codeblock.svg';
import EmbedIcon from '@images/lightning.svg';
import UnderlineIcon from '@images/underline.svg';
import StrikethroughIcon from '@images/strikethrough.svg';
import DividerIcon from '@images/divider.svg';
@ -714,6 +715,25 @@ export const coreSyntaxFormatters = {
blockSuffix: '\n```',
}),
},
embed: {
icon: () => <Icon src={EmbedIcon} />,
label: 'Embed',
getKeyboardShortcut: () => {
const modifier = getOSKeyboardModifierKeyString();
return {
command: `${modifier}+shift+k`,
tooltipHint: `${modifier.toUpperCase()} + SHIFT + K`,
};
},
getFormatting: ({ selectionStart, selectionEnd, value }) =>
undoOrAddFormattingForInlineSyntax({
value,
selectionStart,
selectionEnd,
prefix: '{% embed ',
suffix: ' %}',
}),
},
};
export const secondarySyntaxFormatters = {