Skip to content

Commit

Permalink
fix(links): Ensure that CTRL+K on Windows toggles link. Fixes #452 (#453
Browse files Browse the repository at this point in the history
)
  • Loading branch information
bantic committed Aug 16, 2016
1 parent b75bb7d commit 3220534
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 79 deletions.
75 changes: 44 additions & 31 deletions src/js/editor/key-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,44 @@ function gotoEndOfLine(editor) {
});
}

function deleteToEndOfSection(editor) {
let { range } = editor;
if (range.isCollapsed) {
let { head, head: { section } } = range;
range = head.toRange(section.tailPosition());
}
editor.run(postEditor => {
let nextPosition = postEditor.deleteRange(range);
postEditor.setRange(nextPosition);
});
}

function toggleLink(editor) {
if (editor.range.isCollapsed) {
return;
}

let selectedText = editor.cursor.selectedText();
let defaultUrl = '';
if (selectedText.indexOf('http') !== -1) { defaultUrl = selectedText; }

let {range} = editor;
let hasLink = editor.detectMarkupInRange(range, 'a');

if (hasLink) {
editor.run(postEditor => postEditor.toggleMarkup('a'));
} else {
editor.showPrompt('Enter a URL', defaultUrl, url => {
if (!url) { return; }

editor.run(postEditor => {
let markup = postEditor.builder.createMarkup('a', {href: url});
postEditor.toggleMarkup(markup);
});
});
}
}

export const DEFAULT_KEY_COMMANDS = [{
str: 'META+B',
run(editor) {
Expand All @@ -48,15 +86,11 @@ export const DEFAULT_KEY_COMMANDS = [{
}, {
str: 'CTRL+K',
run(editor) {
let { range } = editor;
if (range.isCollapsed) {
let { head, head: { section } } = range;
range = head.toRange(section.tailPosition());
if (Browser.isMac()) {
return deleteToEndOfSection(editor);
} else if (Browser.isWin()) {
return toggleLink(editor);
}
editor.run(postEditor => {
let nextPosition = postEditor.deleteRange(range);
postEditor.setRange(nextPosition);
});
}
}, {
str: 'CTRL+A',
Expand Down Expand Up @@ -84,30 +118,9 @@ export const DEFAULT_KEY_COMMANDS = [{
}, {
str: 'META+K',
run(editor) {
if (editor.range.isCollapsed) {
return;
}
return toggleLink(editor);
},

let selectedText = editor.cursor.selectedText();
let defaultUrl = '';
if (selectedText.indexOf('http') !== -1) { defaultUrl = selectedText; }

let {range} = editor;
let hasLink = editor.detectMarkupInRange(range, 'a');

if (hasLink) {
editor.run(postEditor => postEditor.toggleMarkup('a'));
} else {
editor.showPrompt('Enter a URL', defaultUrl, url => {
if (!url) { return; }

editor.run(postEditor => {
let markup = postEditor.builder.createMarkup('a', {href: url});
postEditor.toggleMarkup(markup);
});
});
}
}
}, {
str: 'META+Z',
run(editor) {
Expand Down
136 changes: 88 additions & 48 deletions tests/acceptance/editor-key-commands-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { MODIFIERS } from 'mobiledoc-kit/utils/key';
import Keycodes from 'mobiledoc-kit/utils/keycodes';
import Helpers from '../test-helpers';
import Range from 'mobiledoc-kit/utils/cursor/range';
import Browser from 'mobiledoc-kit/utils/browser';

const { module, test } = Helpers;
const { module, test, skip } = Helpers;

let editor, editorElement;

Expand Down Expand Up @@ -152,57 +153,59 @@ testStatefulCommand({
markupName: 'em'
});

test(`ctrl-k clears to the end of a line`, (assert) => {
let initialText = 'something';
editor = renderIntoAndFocusTail(({post, markupSection, marker}) => post([
markupSection('p', [marker(initialText)])
]));
if (Browser.isMac()) {
test(`[Mac] ctrl-k clears to the end of a line`, (assert) => {
let initialText = 'something';
editor = renderIntoAndFocusTail(({post, markupSection, marker}) => post([
markupSection('p', [marker(initialText)])
]));

assert.ok(editor.hasCursor(), 'has cursor');
assert.ok(editor.hasCursor(), 'has cursor');

let textElement = editor.post.sections.head.markers.head.renderNode.element;
Helpers.dom.moveCursorTo(editor, textElement, 4);
Helpers.dom.triggerKeyCommand(editor, 'K', MODIFIERS.CTRL);

let changedMobiledoc = editor.serialize();
let expectedMobiledoc = Helpers.mobiledoc.build(
({post, markupSection, marker}) => {
return post([
markupSection('p', [
marker('some')
])
]);
let textElement = editor.post.sections.head.markers.head.renderNode.element;
Helpers.dom.moveCursorTo(editor, textElement, 4);
Helpers.dom.triggerKeyCommand(editor, 'K', MODIFIERS.CTRL);

let changedMobiledoc = editor.serialize();
let expectedMobiledoc = Helpers.mobiledoc.build(
({post, markupSection, marker}) => {
return post([
markupSection('p', [
marker('some')
])
]);
});
assert.deepEqual(changedMobiledoc, expectedMobiledoc,
'mobiledoc updated appropriately');
});
assert.deepEqual(changedMobiledoc, expectedMobiledoc,
'mobiledoc updated appropriately');
});

test(`ctrl-k clears selected text`, (assert) => {
let initialText = 'something';
editor = renderIntoAndFocusTail( ({post, markupSection, marker}) => post([
markupSection('p', [marker(initialText)])
]));
test(`[Mac] ctrl-k clears selected text`, (assert) => {
let initialText = 'something';
editor = renderIntoAndFocusTail( ({post, markupSection, marker}) => post([
markupSection('p', [marker(initialText)])
]));

assert.ok(editor.hasCursor(), 'has cursor');
assert.ok(editor.hasCursor(), 'has cursor');

let textElement = editor.post.sections.head.markers.head.renderNode.element;
Helpers.dom.moveCursorTo(editor, textElement, 4, textElement, 8);
Helpers.dom.triggerKeyCommand(editor, 'K', MODIFIERS.CTRL);

let changedMobiledoc = editor.serialize();
let expectedMobiledoc = Helpers.mobiledoc.build(
({post, markupSection, marker}) => {
return post([
markupSection('p', [
marker('someg')
])
]);
let textElement = editor.post.sections.head.markers.head.renderNode.element;
Helpers.dom.moveCursorTo(editor, textElement, 4, textElement, 8);
Helpers.dom.triggerKeyCommand(editor, 'K', MODIFIERS.CTRL);

let changedMobiledoc = editor.serialize();
let expectedMobiledoc = Helpers.mobiledoc.build(
({post, markupSection, marker}) => {
return post([
markupSection('p', [
marker('someg')
])
]);
});
assert.deepEqual(changedMobiledoc, expectedMobiledoc,
'mobiledoc updated appropriately');
});
assert.deepEqual(changedMobiledoc, expectedMobiledoc,
'mobiledoc updated appropriately');
});
}

test('cmd-k links selected text', (assert) => {
let toggleLinkTest = (assert, modifier) => {
assert.expect(3);

let url = 'http://bustle.com';
Expand All @@ -218,12 +221,12 @@ test('cmd-k links selected text', (assert) => {
};

Helpers.dom.selectText(editor ,'something', editorElement);
Helpers.dom.triggerKeyCommand(editor, 'K', MODIFIERS.META);
Helpers.dom.triggerKeyCommand(editor, 'K', modifier);

assert.hasElement(`#editor a[href="${url}"]:contains(something)`);
});
};

test('cmd-k unlinks selected text if it was already linked', (assert) => {
let toggleLinkUnlinkTest = (assert, modifier) => {
assert.expect(4);

let url = 'http://bustle.com';
Expand All @@ -240,11 +243,48 @@ test('cmd-k unlinks selected text if it was already linked', (assert) => {
'precond -- has link');

Helpers.dom.selectText(editor ,'something', editorElement);
Helpers.dom.triggerKeyCommand(editor, 'K', MODIFIERS.META);
Helpers.dom.triggerKeyCommand(editor, 'K', modifier);

assert.hasNoElement(`#editor a[href="${url}"]:contains(something)`,
'removes linked text');
assert.hasElement(`#editor p:contains(something)`, 'unlinked text remains');
};

let toggleTests = [
{
precondition: () => Browser.isMac(),
msg: '[Mac] cmd-k links selected text',
testFn: toggleLinkTest,
modifier: MODIFIERS.META
},
{
precondition: () => Browser.isMac(),
msg: '[Mac] cmd-k unlinks selected text if it was already linked',
testFn: toggleLinkUnlinkTest,
modifier: MODIFIERS.META
},
{
precondition: () => Browser.isWin(),
msg: '[Windows] ctrl-k links selected text',
testFn: toggleLinkTest,
modifier: MODIFIERS.CTRL
},
{
precondition: () => Browser.isWin(),
msg: '[Windows] ctrl-k unlinks selected text if it was already linked',
testFn: toggleLinkUnlinkTest,
modifier: MODIFIERS.CTRL
},
];

toggleTests.forEach(({precondition, msg, testFn, modifier}) => {
if (!precondition()) {
skip(msg);
} else {
test(msg, (assert) => {
testFn(assert, modifier);
});
}
});

test('new key commands can be registered', (assert) => {
Expand Down
1 change: 1 addition & 0 deletions tests/test-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default {
test,
module,
skipInIE11,
skip,
wait,
postEditor: { run, renderBuiltAbstract, MockEditor }
};

0 comments on commit 3220534

Please sign in to comment.