diff --git a/app/assets/javascripts/discourse/components/d-editor.js.es6 b/app/assets/javascripts/discourse/components/d-editor.js.es6 index 3b2aa374073..21639fd76f3 100644 --- a/app/assets/javascripts/discourse/components/d-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/d-editor.js.es6 @@ -32,6 +32,8 @@ const OP = { ADDED: 2 }; +const FOUR_SPACES_INDENT = '4-spaces-indent'; + const _createCallbacks = []; class Toolbar { @@ -534,14 +536,21 @@ export default Ember.Component.extend({ formatCode() { const sel = this._getSelected(); - if (sel.value.indexOf("\n") !== -1) { - return (this.siteSettings.code_formatting_style === "4-spaces-indent") ? + const hasNewLine = sel.value.indexOf("\n") !== -1 + + if (this.siteSettings.code_formatting_style === FOUR_SPACES_INDENT) { + return (hasNewLine ? this._applySurround(sel, ' ', '', 'code_text') : - this._addText(sel, '```\n' + sel.value + '\n```'); + this._applySurround(sel, '`', '`', 'code_text')); } else { - return (this.siteSettings.code_formatting_style === "4-spaces-indent") ? - this._applySurround(sel, '`', '`', 'code_text') : - this._applySurround(sel, '```\n', '\n```', 'paste_code_text'); + const preNewline = (sel.pre[-1] !== "\n" && sel.pre !== "") ? "\n" : ""; + const postNewline = sel.post[0] !== "\n" ? "\n" : ""; + + if (hasNewLine) { + return this._addText(sel, `${preNewline}\`\`\`\n${sel.value}\n\`\`\`${postNewline}`); + } else { + return this._applySurround(sel, `${preNewline}\`\`\`\n`, `\n\`\`\`${postNewline}`, 'paste_code_text'); + } } }, diff --git a/test/javascripts/components/d-editor-test.js.es6 b/test/javascripts/components/d-editor-test.js.es6 index abebfe9cf5b..eea8e277c87 100644 --- a/test/javascripts/components/d-editor-test.js.es6 +++ b/test/javascripts/components/d-editor-test.js.es6 @@ -259,11 +259,13 @@ componentTest('advanced code', { setup() { this.siteSettings.code_formatting_style = '4-spaces-indent'; this.set('value', -`function xyz(x, y, z) { +` +function xyz(x, y, z) { if (y === z) { return true; } -}`); +} +` ); }, test(assert) { @@ -274,11 +276,14 @@ componentTest('advanced code', { click('button.code'); andThen(() => { assert.equal(this.get('value'), -` function xyz(x, y, z) { +` + function xyz(x, y, z) { if (y === z) { return true; } - }`); + } +` + ); }); } @@ -338,6 +343,122 @@ componentTest('code button', { } }); +componentTest('code fences', { + template: '{{d-editor value=value}}', + setup() { + this.set('value', ''); + }, + + test(assert) { + const textarea = jumpEnd(this.$('textarea.d-editor-input')[0]); + + click('button.code'); + andThen(() => { + assert.equal(this.get('value'), +`\`\`\` +${I18n.t("composer.paste_code_text")} +\`\`\` +` + ); + + assert.equal(textarea.selectionStart, 4); + assert.equal(textarea.selectionEnd, 27); + + this.set('value', 'first line\nsecond line\nthird line'); + + textarea.selectionStart = 0; + textarea.selectionEnd = textarea.value.length; + }); + + click('button.code'); + andThen(() => { + assert.equal(this.get('value'), +`\`\`\` +first line +second line +third line +\`\`\` +` + ); + + assert.equal(textarea.selectionStart, textarea.value.length); + assert.equal(textarea.selectionEnd, textarea.value.length); + + this.set('value', 'first line\nsecond line\nthird line'); + + textarea.selectionStart = 0; + textarea.selectionEnd = 0; + }); + + click('button.code'); + andThen(() => { + assert.equal(this.get('value'), +`\`\`\` +${I18n.t('composer.paste_code_text')} +\`\`\` +first line +second line +third line` + ); + + assert.equal(textarea.selectionStart, 4); + assert.equal(textarea.selectionEnd, 27); + + this.set('value', 'first line\nsecond line\nthird line'); + + textarea.selectionStart = 0; + textarea.selectionEnd = 10; + }); + + click('button.code'); + andThen(() => { + assert.equal(this.get('value'), +`\`\`\` +first line +\`\`\` +second line +third line` + ); + + assert.equal(textarea.selectionStart, 4); + assert.equal(textarea.selectionEnd, 14); + + this.set('value', 'first line\nsecond line\nthird line'); + + textarea.selectionStart = 0; + textarea.selectionEnd = 23; + }); + + click('button.code'); + andThen(() => { + assert.equal(this.get('value'), +`\`\`\` +first line +second line +\`\`\` +third line` + ); + + assert.equal(textarea.selectionStart, 30); + assert.equal(textarea.selectionEnd, 30); + + this.set('value', 'first line\nsecond line\nthird line'); + + textarea.selectionStart = 6; + textarea.selectionEnd = 17; + }); + + click('button.code'); + andThen(() => { + assert.equal(this.get('value'), `first \n\`\`\`\nline\nsecond\n\`\`\`\n line\nthird line`); + + assert.equal(textarea.selectionStart, 27); + assert.equal(textarea.selectionEnd, 27); + }); + } +}); + + testCase('quote button', function(assert, textarea) { click('button.quote'); andThen(() => {