Commit fc618d94 authored by Simon Knox's avatar Simon Knox

Merge branch 'bw-surround-text-wth-char-2' into 'master'

Fixed: Surround selected text with typed backtick or single quote in markdown fields

See merge request gitlab-org/gitlab!37151
parents a29daf8b 70aec343
...@@ -303,7 +303,41 @@ function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select, tagCo ...@@ -303,7 +303,41 @@ function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select, tagCo
}); });
} }
/* eslint-disable @gitlab/require-i18n-strings */
export function keypressNoteText(e) {
if (this.selectionStart === this.selectionEnd) {
return;
}
const keys = {
'*': '**{text}**', // wraps with bold character
_: '_{text}_', // wraps with italic character
'`': '`{text}`', // wraps with inline character
"'": "'{text}'", // single quotes
'"': '"{text}"', // double quotes
'[': '[{text}]', // brackets
'{': '{{text}}', // braces
'(': '({text})', // parentheses
'<': '<{text}>', // angle brackets
};
const tag = keys[e.key];
if (tag) {
e.preventDefault();
updateText({
tag,
textArea: this,
blockTag: '',
wrap: true,
select: '',
tagContent: '',
});
}
}
/* eslint-enable @gitlab/require-i18n-strings */
export function addMarkdownListeners(form) { export function addMarkdownListeners(form) {
$('.markdown-area', form).on('keydown', keypressNoteText);
return $('.js-md', form) return $('.js-md', form)
.off('click') .off('click')
.on('click', function() { .on('click', function() {
...@@ -342,5 +376,6 @@ export function addEditorMarkdownListeners(editor) { ...@@ -342,5 +376,6 @@ export function addEditorMarkdownListeners(editor) {
} }
export function removeMarkdownListeners(form) { export function removeMarkdownListeners(form) {
$('.markdown-area', form).off('keydown', keypressNoteText);
return $('.js-md', form).off('click'); return $('.js-md', form).off('click');
} }
---
title: Surround selected text in markdown fields on certain key presses
merge_request: 37151
author:
type: added
...@@ -8,6 +8,7 @@ RSpec.describe 'Projects > Wiki > User previews markdown changes', :js do ...@@ -8,6 +8,7 @@ RSpec.describe 'Projects > Wiki > User previews markdown changes', :js do
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)') } let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)') }
let(:wiki_content) do let(:wiki_content) do
<<-HEREDOC <<-HEREDOC
Some text so key event for [ does not trigger an incorrect replacement.
[regular link](regular) [regular link](regular)
[relative link 1](../relative) [relative link 1](../relative)
[relative link 2](./relative) [relative link 2](./relative)
......
import { insertMarkdownText } from '~/lib/utils/text_markdown'; import { insertMarkdownText, keypressNoteText } from '~/lib/utils/text_markdown';
describe('init markdown', () => { describe('init markdown', () => {
let textArea; let textArea;
...@@ -115,14 +115,15 @@ describe('init markdown', () => { ...@@ -115,14 +115,15 @@ describe('init markdown', () => {
describe('with selection', () => { describe('with selection', () => {
const text = 'initial selected value'; const text = 'initial selected value';
const selected = 'selected'; const selected = 'selected';
let selectedIndex;
beforeEach(() => { beforeEach(() => {
textArea.value = text; textArea.value = text;
const selectedIndex = text.indexOf(selected); selectedIndex = text.indexOf(selected);
textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length); textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
}); });
it('applies the tag to the selected value', () => { it('applies the tag to the selected value', () => {
const selectedIndex = text.indexOf(selected);
const tag = '*'; const tag = '*';
insertMarkdownText({ insertMarkdownText({
...@@ -153,6 +154,29 @@ describe('init markdown', () => { ...@@ -153,6 +154,29 @@ describe('init markdown', () => {
expect(textArea.value).toEqual(text.replace(selected, `[${selected}](url)`)); expect(textArea.value).toEqual(text.replace(selected, `[${selected}](url)`));
}); });
it.each`
key | expected
${'['} | ${`[${selected}]`}
${'*'} | ${`**${selected}**`}
${"'"} | ${`'${selected}'`}
${'_'} | ${`_${selected}_`}
${'`'} | ${`\`${selected}\``}
${'"'} | ${`"${selected}"`}
${'{'} | ${`{${selected}}`}
${'('} | ${`(${selected})`}
${'<'} | ${`<${selected}>`}
`('generates $expected when $key is pressed', ({ key, expected }) => {
const event = new KeyboardEvent('keydown', { key });
textArea.addEventListener('keydown', keypressNoteText);
textArea.dispatchEvent(event);
expect(textArea.value).toEqual(text.replace(selected, expected));
// cursor placement should be after selection + 2 tag lengths
expect(textArea.selectionStart).toBe(selectedIndex + expected.length);
});
describe('and text to be selected', () => { describe('and text to be selected', () => {
const tag = '[{text}](url)'; const tag = '[{text}](url)';
const select = 'url'; const select = 'url';
...@@ -178,7 +202,7 @@ describe('init markdown', () => { ...@@ -178,7 +202,7 @@ describe('init markdown', () => {
it('selects the right text when multiple tags are present', () => { it('selects the right text when multiple tags are present', () => {
const initialValue = `${tag} ${tag} ${selected}`; const initialValue = `${tag} ${tag} ${selected}`;
textArea.value = initialValue; textArea.value = initialValue;
const selectedIndex = initialValue.indexOf(selected); selectedIndex = initialValue.indexOf(selected);
textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length); textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
insertMarkdownText({ insertMarkdownText({
textArea, textArea,
...@@ -204,7 +228,7 @@ describe('init markdown', () => { ...@@ -204,7 +228,7 @@ describe('init markdown', () => {
const initialValue = `text ${expectedUrl} text`; const initialValue = `text ${expectedUrl} text`;
textArea.value = initialValue; textArea.value = initialValue;
const selectedIndex = initialValue.indexOf(expectedUrl); selectedIndex = initialValue.indexOf(expectedUrl);
textArea.setSelectionRange(selectedIndex, selectedIndex + expectedUrl.length); textArea.setSelectionRange(selectedIndex, selectedIndex + expectedUrl.length);
insertMarkdownText({ insertMarkdownText({
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment