diff --git a/app/src/components/composer-editor/link-plugins.jsx b/app/src/components/composer-editor/link-plugins.jsx index 319e6ff5d..66886f741 100644 --- a/app/src/components/composer-editor/link-plugins.jsx +++ b/app/src/components/composer-editor/link-plugins.jsx @@ -22,6 +22,22 @@ function onPaste(event, change, editor) { } } +function buildAutoReplaceHandler({ hrefPrefix = '' } = {}) { + return function(transform, e, matches) { + if (transform.value.activeMarks.find(m => m.type === LINK_TYPE)) + return transform.insertText(TriggerKeyValues[e.key]); + + const link = matches.before[0]; + const mark = Mark.create({ type: LINK_TYPE, data: { href: hrefPrefix + matches.before[0] } }); + return transform + .deleteBackward(link.length) + .addMark(mark) + .insertText(link) + .removeMark(mark) + .insertText(TriggerKeyValues[e.key]); + }; +} + function renderMark({ mark, children, targetIsHTML }) { if (mark.type !== LINK_TYPE) { return; @@ -121,21 +137,14 @@ export default [ }, }, }, + AutoReplace({ + trigger: e => !!TriggerKeyValues[e.key], + before: RegExpUtils.emailRegex({ requireStartOrWhitespace: true, matchTailOfString: true }), + transform: buildAutoReplaceHandler({ hrefPrefix: 'mailto:' }), + }), AutoReplace({ trigger: e => !!TriggerKeyValues[e.key], before: RegExpUtils.urlRegex({ matchTailOfString: true }), - transform: (transform, e, matches) => { - if (transform.value.activeMarks.find(m => m.type === LINK_TYPE)) - return transform.insertText(TriggerKeyValues[e.key]); - - const link = matches.before[0]; - const mark = Mark.create({ type: LINK_TYPE, data: { href: matches.before[0] } }); - return transform - .deleteBackward(link.length) - .addMark(mark) - .insertText(link) - .removeMark(mark) - .insertText(TriggerKeyValues[e.key]); - }, + transform: buildAutoReplaceHandler(), }), ]; diff --git a/app/src/regexp-utils.es6 b/app/src/regexp-utils.es6 index 80c3047c6..a2669ce28 100644 --- a/app/src/regexp-utils.es6 +++ b/app/src/regexp-utils.es6 @@ -17,11 +17,22 @@ const RegExpUtils = { // See http://tools.ietf.org/html/rfc5322#section-3.4 and // https://tools.ietf.org/html/rfc6531 and // https://en.wikipedia.org/wiki/Email_address#Local_part - emailRegex() { - return new RegExp( - `([a-z.A-Z${UnicodeEmailChars}0-9!#$%&\\'*+\\-/=?^_\`{|}~]+@[A-Za-z${UnicodeEmailChars}0-9.-]+\\.[A-Za-z]{2,63})`, - 'g' - ); + emailRegex({ requireStartOrWhitespace, matchTailOfString } = {}) { + const parts = [ + `(`, + `[a-z.A-Z${UnicodeEmailChars}0-9!#$%&\\'*+\\-/=?^_\`{|}~]+`, + '@', + `[A-Za-z${UnicodeEmailChars}0-9.-]+\\.[A-Za-z]{2,63}`, + `)`, + ]; + if (requireStartOrWhitespace) { + parts.unshift('(?:^|\\s{1})'); + } + if (matchTailOfString) { + parts.push('$'); + } + + return new RegExp(parts.join(''), 'g'); }, // http://stackoverflow.com/questions/16631571/javascript-regular-expression-detect-all-the-phone-number-from-the-page-source