mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
Koenig - Fixed trailing-spaces when using markdown text expansions
refs https://github.com/TryGhost/Ghost/issues/9505 - previous attempts at toggling the markup state failed because mobiledoc-kit was automatically setting the activeMarkupState after we made the replacement - by scheduling the toggle we change the active markup state after mobiledoc has done it's thing so you can continue typing without the markdown markup being applied and without needing to insert an unexpected space
This commit is contained in:
parent
0c3879294b
commit
f18a23434f
1 changed files with 65 additions and 44 deletions
|
@ -2,6 +2,7 @@ import {
|
||||||
replaceWithHeaderSection,
|
replaceWithHeaderSection,
|
||||||
replaceWithListSection
|
replaceWithListSection
|
||||||
} from 'mobiledoc-kit/editor/text-input-handlers';
|
} from 'mobiledoc-kit/editor/text-input-handlers';
|
||||||
|
import {run} from '@ember/runloop';
|
||||||
|
|
||||||
// Text expansions watch text entry events and will look for matches, replacing
|
// Text expansions watch text entry events and will look for matches, replacing
|
||||||
// the matches with additional markup, atoms, or cards
|
// the matches with additional markup, atoms, or cards
|
||||||
|
@ -22,26 +23,25 @@ export default function (editor) {
|
||||||
match: /[*_)~`]$/,
|
match: /[*_)~`]$/,
|
||||||
run(editor, matches) {
|
run(editor, matches) {
|
||||||
let text = editor.range.head.section.textUntil(editor.range.head);
|
let text = editor.range.head.section.textUntil(editor.range.head);
|
||||||
let hasTextAfter = editor.range.head.section.text.length > text.length;
|
|
||||||
|
|
||||||
switch (matches[0]) {
|
switch (matches[0]) {
|
||||||
case '*':
|
case '*':
|
||||||
matchStrongStar(editor, text, hasTextAfter);
|
matchStrongStar(editor, text);
|
||||||
matchEmStar(editor, text, hasTextAfter);
|
matchEmStar(editor, text);
|
||||||
break;
|
break;
|
||||||
case '_':
|
case '_':
|
||||||
matchStrongUnderscore(editor, text, hasTextAfter);
|
matchStrongUnderscore(editor, text);
|
||||||
matchEmUnderscore(editor, text, hasTextAfter);
|
matchEmUnderscore(editor, text);
|
||||||
break;
|
break;
|
||||||
case ')':
|
case ')':
|
||||||
matchLink(editor, text, hasTextAfter);
|
matchLink(editor, text);
|
||||||
matchImage(editor, text, hasTextAfter);
|
matchImage(editor, text);
|
||||||
break;
|
break;
|
||||||
case '~':
|
case '~':
|
||||||
matchStrikethrough(editor, text, hasTextAfter);
|
matchStrikethrough(editor, text);
|
||||||
break;
|
break;
|
||||||
case '`':
|
case '`':
|
||||||
matchCode(editor, text, hasTextAfter);
|
matchCode(editor, text);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,109 +100,127 @@ export default function (editor) {
|
||||||
|
|
||||||
/* inline markdown ------------------------------------------------------ */
|
/* inline markdown ------------------------------------------------------ */
|
||||||
|
|
||||||
function matchStrongStar(editor, text, hasTextAfter = false) {
|
function matchStrongStar(editor, text) {
|
||||||
let {range} = editor;
|
let {range} = editor;
|
||||||
let matches = text.match(/(^|\s)\*\*([^\s*].+?[^\s*])\*\*/);
|
let matches = text.match(/(^|\s)\*\*([^\s*].+?[^\s*])\*\*/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
|
let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
|
||||||
range = range.extend(-(match.length));
|
range = range.extend(-(match.length));
|
||||||
|
|
||||||
editor.run((postEditor) => {
|
editor.run((postEditor) => {
|
||||||
let position = postEditor.deleteRange(range);
|
let position = postEditor.deleteRange(range);
|
||||||
let bold = postEditor.builder.createMarkup('strong');
|
let bold = postEditor.builder.createMarkup('strong');
|
||||||
let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [bold]);
|
postEditor.insertTextWithMarkup(position, matches[2], [bold]);
|
||||||
if (!hasTextAfter) {
|
|
||||||
postEditor.insertTextWithMarkup(nextPosition, ' ', []);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// must be scheduled so that the toggle isn't reset automatically
|
||||||
|
run.schedule('actions', this, function () {
|
||||||
|
editor.toggleMarkup('strong');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchStrongUnderscore(editor, text, hasTextAfter = false) {
|
function matchStrongUnderscore(editor, text) {
|
||||||
let {range} = editor;
|
let {range} = editor;
|
||||||
let matches = text.match(/(^|\s)__([^\s_].+?[^\s_])__/);
|
let matches = text.match(/(^|\s)__([^\s_].+?[^\s_])__/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
|
let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
|
||||||
range = range.extend(-(match.length));
|
range = range.extend(-(match.length));
|
||||||
|
|
||||||
editor.run((postEditor) => {
|
editor.run((postEditor) => {
|
||||||
let position = postEditor.deleteRange(range);
|
let position = postEditor.deleteRange(range);
|
||||||
let bold = postEditor.builder.createMarkup('strong');
|
let bold = postEditor.builder.createMarkup('strong');
|
||||||
let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [bold]);
|
postEditor.insertTextWithMarkup(position, matches[2], [bold]);
|
||||||
if (!hasTextAfter) {
|
});
|
||||||
postEditor.insertTextWithMarkup(nextPosition, ' ', []);
|
|
||||||
}
|
// must be scheduled so that the toggle isn't reset automatically
|
||||||
|
run.schedule('actions', this, function () {
|
||||||
|
editor.toggleMarkup('strong');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchEmStar(editor, text, hasTextAfter = false) {
|
function matchEmStar(editor, text) {
|
||||||
let {range} = editor;
|
let {range} = editor;
|
||||||
let matches = text.match(/(^|\s)\*([^\s*][^*]+?[^\s])\*/);
|
let matches = text.match(/(^|\s)\*([^\s*][^*]+?[^\s])\*/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
|
let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
|
||||||
range = range.extend(-(match.length));
|
range = range.extend(-(match.length));
|
||||||
|
|
||||||
editor.run((postEditor) => {
|
editor.run((postEditor) => {
|
||||||
let position = postEditor.deleteRange(range);
|
let position = postEditor.deleteRange(range);
|
||||||
let em = postEditor.builder.createMarkup('em');
|
let em = postEditor.builder.createMarkup('em');
|
||||||
let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [em]);
|
postEditor.insertTextWithMarkup(position, matches[2], [em]);
|
||||||
if (!hasTextAfter) {
|
});
|
||||||
postEditor.insertTextWithMarkup(nextPosition, ' ', []);
|
|
||||||
}
|
// must be scheduled so that the toggle isn't reset automatically
|
||||||
|
run.schedule('actions', this, function () {
|
||||||
|
editor.toggleMarkup('em');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchEmUnderscore(editor, text, hasTextAfter = false) {
|
function matchEmUnderscore(editor, text) {
|
||||||
let {range} = editor;
|
let {range} = editor;
|
||||||
let matches = text.match(/(^|\s)_([^\s_][^_]+?[^\s])_/);
|
let matches = text.match(/(^|\s)_([^\s_][^_]+?[^\s])_/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
|
let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
|
||||||
range = range.extend(-(match.length));
|
range = range.extend(-(match.length));
|
||||||
|
|
||||||
editor.run((postEditor) => {
|
editor.run((postEditor) => {
|
||||||
let position = postEditor.deleteRange(range);
|
let position = postEditor.deleteRange(range);
|
||||||
let em = postEditor.builder.createMarkup('em');
|
let em = postEditor.builder.createMarkup('em');
|
||||||
let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [em]);
|
postEditor.insertTextWithMarkup(position, matches[2], [em]);
|
||||||
if (!hasTextAfter) {
|
});
|
||||||
postEditor.insertTextWithMarkup(nextPosition, ' ', []);
|
|
||||||
}
|
// must be scheduled so that the toggle isn't reset automatically
|
||||||
|
run.schedule('actions', this, function () {
|
||||||
|
editor.toggleMarkup('code');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchStrikethrough(editor, text, hasTextAfter = false) {
|
function matchStrikethrough(editor, text) {
|
||||||
let {range} = editor;
|
let {range} = editor;
|
||||||
let matches = text.match(/(^|\s)~([^\s~][^~]+?[^\s])~/);
|
let matches = text.match(/(^|\s)~([^\s~][^~]+?[^\s])~/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let match = matches[0][0] === '~' ? matches[0] : matches[0].substr(1);
|
let match = matches[0][0] === '~' ? matches[0] : matches[0].substr(1);
|
||||||
range = range.extend(-(match.length));
|
range = range.extend(-(match.length));
|
||||||
|
|
||||||
editor.run((postEditor) => {
|
editor.run((postEditor) => {
|
||||||
let position = postEditor.deleteRange(range);
|
let position = postEditor.deleteRange(range);
|
||||||
let s = postEditor.builder.createMarkup('s');
|
let s = postEditor.builder.createMarkup('s');
|
||||||
let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [s]);
|
postEditor.insertTextWithMarkup(position, matches[2], [s]);
|
||||||
if (!hasTextAfter) {
|
});
|
||||||
postEditor.insertTextWithMarkup(nextPosition, ' ', []); // insert the un-marked-up space
|
|
||||||
}
|
// must be scheduled so that the toggle isn't reset automatically
|
||||||
|
run.schedule('actions', this, function () {
|
||||||
|
editor.toggleMarkup('s');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchCode(editor, text, hasTextAfter = false) {
|
function matchCode(editor, text) {
|
||||||
let {range} = editor;
|
let {range} = editor;
|
||||||
let matches = text.match(/(^|\s)`([^\s`][^`]+?[^\s])`/);
|
let matches = text.match(/(^|\s)`([^\s`][^`]+?[^\s])`/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let match = matches[0][0] === '`' ? matches[0] : matches[0].substr(1);
|
let match = matches[0][0] === '`' ? matches[0] : matches[0].substr(1);
|
||||||
range = range.extend(-(match.length));
|
range = range.extend(-(match.length));
|
||||||
|
|
||||||
editor.run((postEditor) => {
|
editor.run((postEditor) => {
|
||||||
let position = postEditor.deleteRange(range);
|
let position = postEditor.deleteRange(range);
|
||||||
let code = postEditor.builder.createMarkup('code');
|
let code = postEditor.builder.createMarkup('code');
|
||||||
let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [code]);
|
postEditor.insertTextWithMarkup(position, matches[2], [code]);
|
||||||
if (!hasTextAfter) {
|
});
|
||||||
postEditor.insertTextWithMarkup(nextPosition, ' ', []); // insert the un-marked-up space
|
|
||||||
}
|
// must be scheduled so that the toggle isn't reset automatically
|
||||||
|
run.schedule('actions', this, function () {
|
||||||
|
editor.toggleMarkup('code');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchLink(editor, text, hasTextAfter = false) {
|
function matchLink(editor, text) {
|
||||||
let {range} = editor;
|
let {range} = editor;
|
||||||
let matches = text.match(/(^|[^!])\[(.*?)\]\((.*?)\)$/);
|
let matches = text.match(/(^|[^!])\[(.*?)\]\((.*?)\)$/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
|
@ -210,13 +228,16 @@ export default function (editor) {
|
||||||
let text = matches[2];
|
let text = matches[2];
|
||||||
let match = matches[0][0] === '[' ? matches[0] : matches[0].substr(1);
|
let match = matches[0][0] === '[' ? matches[0] : matches[0].substr(1);
|
||||||
range = range.extend(-match.length);
|
range = range.extend(-match.length);
|
||||||
|
|
||||||
editor.run((postEditor) => {
|
editor.run((postEditor) => {
|
||||||
let position = postEditor.deleteRange(range);
|
let position = postEditor.deleteRange(range);
|
||||||
let a = postEditor.builder.createMarkup('a', {href: url});
|
let a = postEditor.builder.createMarkup('a', {href: url});
|
||||||
let nextPosition = postEditor.insertTextWithMarkup(position, text, [a]);
|
postEditor.insertTextWithMarkup(position, text, [a]);
|
||||||
if (!hasTextAfter) {
|
});
|
||||||
postEditor.insertTextWithMarkup(nextPosition, ' ', []); // insert the un-marked-up space
|
|
||||||
}
|
// must be scheduled so that the toggle isn't reset automatically
|
||||||
|
run.schedule('actions', this, function () {
|
||||||
|
editor.toggleMarkup('code');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue