From caa38aaaad625d4479c9dc82353624ee52b289cc Mon Sep 17 00:00:00 2001 From: scossar Date: Sun, 28 Jan 2018 18:33:55 -0800 Subject: [PATCH 1/5] Add support for mixed text directions --- app/assets/javascripts/application.js | 1 + .../discourse/components/d-editor.js.es6 | 21 +++++++++++++ .../discourse/components/text-field.js.es6 | 30 ++++++++++++++++++- .../discourse/helpers/category-link.js.es6 | 10 +++++-- .../discourse/helpers/dir-span.js.es6 | 14 +++++++++ .../initializers/post-decorations.js.es6 | 7 ++++- .../discourse/lib/text-direction.js.es6 | 28 +++++++++++++++++ .../javascripts/discourse/models/topic.js.es6 | 9 +++++- .../templates/components/categories-only.hbs | 2 +- .../components/category-title-link.hbs | 2 +- .../templates/list/topic-excerpt.raw.hbs | 2 +- .../templates/navigation/category.hbs | 2 +- .../templates/components/category-row.hbs | 2 +- config/locales/client.en.yml | 1 + config/locales/server.en.yml | 1 + config/site_settings.yml | 3 ++ 16 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 app/assets/javascripts/discourse/helpers/dir-span.js.es6 create mode 100644 app/assets/javascripts/discourse/lib/text-direction.js.es6 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 02bc257b12b..c6ca0b0c90c 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -25,6 +25,7 @@ //= require ./discourse/lib/key-value-store //= require ./discourse/lib/computed //= require ./discourse/lib/formatter +//= require ./discourse/lib/text-direction //= require ./discourse/lib/eyeline //= require ./discourse/lib/show-modal //= require ./discourse/mixins/scrolling diff --git a/app/assets/javascripts/discourse/components/d-editor.js.es6 b/app/assets/javascripts/discourse/components/d-editor.js.es6 index c70f0b3bc96..10d1a4fa534 100644 --- a/app/assets/javascripts/discourse/components/d-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/d-editor.js.es6 @@ -8,6 +8,7 @@ import { emojiSearch, isSkinTonableEmoji } from 'pretty-text/emoji'; import { emojiUrlFor } from 'discourse/lib/text'; import { getRegister } from 'discourse-common/lib/get-owner'; import { findRawTemplate } from 'discourse/lib/raw-templates'; +import { siteDir } from 'discourse/lib/text-direction'; import { determinePostReplaceSelection, clipboardData } from 'discourse/lib/utilities'; import toMarkdown from 'discourse/lib/to-markdown'; import deprecated from 'discourse-common/lib/deprecated'; @@ -107,6 +108,17 @@ class Toolbar { perform: e => e.applyList(i => !i ? "1. " : `${parseInt(i) + 1}. `, 'list_item') }); + if (Discourse.SiteSettings.support_mixed_text_direction) { + this.addButton({ + id: 'toggle-direction', + group: 'extras', + icon: 'arrows-h', + shortcut: 'Shift+6', + title: 'composer.toggle_direction', + perform: e => e.toggleDirection(), + }); + } + if (site.mobileView) { this.groups.push({group: 'mobileExtras', buttons: []}); } @@ -647,6 +659,14 @@ export default Ember.Component.extend({ return null; }, + _toggleDirection() { + const $textArea = $(".d-editor-input"); + let currentDir = $textArea.attr('dir') ? $textArea.attr('dir') : siteDir(), + newDir = currentDir === 'ltr' ? 'rtl' : 'ltr'; + + $textArea.attr('dir', newDir).focus(); + }, + paste(e) { if (!$(".d-editor-input").is(":focus")) { return; @@ -724,6 +744,7 @@ export default Ember.Component.extend({ addText: text => this._addText(selected, text), replaceText: text => this._addText({pre: '', post: ''}, text), getText: () => this.get('value'), + toggleDirection: () => this._toggleDirection(), }; if (button.sendAction) { diff --git a/app/assets/javascripts/discourse/components/text-field.js.es6 b/app/assets/javascripts/discourse/components/text-field.js.es6 index a9246efa7db..c2bb0eaf51c 100644 --- a/app/assets/javascripts/discourse/components/text-field.js.es6 +++ b/app/assets/javascripts/discourse/components/text-field.js.es6 @@ -1,7 +1,35 @@ import computed from "ember-addons/ember-computed-decorators"; +import { siteDir } from "discourse/lib/text-direction"; +import { isRTL } from "discourse/lib/text-direction"; +import { isLTR } from "discourse/lib/text-direction"; export default Ember.TextField.extend({ - attributeBindings: ['autocorrect', 'autocapitalize', 'autofocus', 'maxLength'], + attributeBindings: ['autocorrect', 'autocapitalize', 'autofocus', 'maxLength', 'dir'], + + @computed + dir() { + if (Discourse.SiteSettings.support_mixed_text_direction) { + let val = this.value; + if (val) { + return isRTL(val) ? 'rtl' : 'ltr'; + } else { + return siteDir(); + } + } + }, + + keyUp() { + if (Discourse.SiteSettings.support_mixed_text_direction) { + let val = this.value; + if (isRTL(val)) { + this.set('dir', 'rtl'); + } else if (isLTR(val)) { + this.set('dir', 'ltr'); + } else { + this.set('dir', siteDir()); + } + } + }, @computed("placeholderKey") placeholder(placeholderKey) { diff --git a/app/assets/javascripts/discourse/helpers/category-link.js.es6 b/app/assets/javascripts/discourse/helpers/category-link.js.es6 index 336e25314ee..de7f73f5793 100644 --- a/app/assets/javascripts/discourse/helpers/category-link.js.es6 +++ b/app/assets/javascripts/discourse/helpers/category-link.js.es6 @@ -1,4 +1,5 @@ import { registerUnbound } from 'discourse-common/lib/helpers'; +import { isRTL } from "discourse/lib/text-direction"; import { iconHTML } from 'discourse-common/lib/icon-library'; var get = Em.get, @@ -38,6 +39,7 @@ export function categoryBadgeHTML(category, opts) { let color = get(category, 'color'); let html = ""; let parentCat = null; + let categoryDir = ""; if (!opts.hideParent) { parentCat = Discourse.Category.findById(get(category, 'parent_category_id')); @@ -66,10 +68,14 @@ export function categoryBadgeHTML(category, opts) { let categoryName = escapeExpression(get(category, 'name')); + if (Discourse.SiteSettings.support_mixed_text_direction) { + categoryDir = isRTL(categoryName) ? 'dir="rtl"' : 'dir="ltr"'; + } + if (restricted) { - html += `${iconHTML('lock')}${categoryName}`; + html += `${iconHTML('lock')}${categoryName}`; } else { - html += `${categoryName}`; + html += `${categoryName}`; } html += ""; diff --git a/app/assets/javascripts/discourse/helpers/dir-span.js.es6 b/app/assets/javascripts/discourse/helpers/dir-span.js.es6 new file mode 100644 index 00000000000..6ce29e8f598 --- /dev/null +++ b/app/assets/javascripts/discourse/helpers/dir-span.js.es6 @@ -0,0 +1,14 @@ +import { registerUnbound } from "discourse-common/lib/helpers"; +import { isRTL } from 'discourse/lib/text-direction'; + +function setDir(text) { + if (Discourse.SiteSettings.support_mixed_text_direction) { + let textDir = isRTL(text) ? 'rtl' : 'ltr'; + return `${text}`; + } + return text; +} + +export default registerUnbound('dir-span', function(str) { + return new Handlebars.SafeString(setDir(str)); +}); diff --git a/app/assets/javascripts/discourse/initializers/post-decorations.js.es6 b/app/assets/javascripts/discourse/initializers/post-decorations.js.es6 index d17b2087acd..0cab9b554de 100644 --- a/app/assets/javascripts/discourse/initializers/post-decorations.js.es6 +++ b/app/assets/javascripts/discourse/initializers/post-decorations.js.es6 @@ -1,13 +1,18 @@ import highlightSyntax from 'discourse/lib/highlight-syntax'; import lightbox from 'discourse/lib/lightbox'; +import { setTextDirections } from "discourse/lib/text-direction"; import { withPluginApi } from 'discourse/lib/plugin-api'; export default { name: "post-decorations", - initialize() { + initialize(container) { withPluginApi('0.1', api => { + const siteSettings = container.lookup('site-settings:main'); api.decorateCooked(highlightSyntax); api.decorateCooked(lightbox); + if (siteSettings.support_mixed_text_direction) { + api.decorateCooked(setTextDirections); + } api.decorateCooked($elem => { const players = $('audio', $elem); diff --git a/app/assets/javascripts/discourse/lib/text-direction.js.es6 b/app/assets/javascripts/discourse/lib/text-direction.js.es6 new file mode 100644 index 00000000000..2a4b9da2c36 --- /dev/null +++ b/app/assets/javascripts/discourse/lib/text-direction.js.es6 @@ -0,0 +1,28 @@ +const ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF'; +const rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC'; + +export function isRTL(text) { + const rtlDirCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']'); + + return rtlDirCheck.test(text); +} + +export function isLTR(text) { + const ltrDirCheck = new RegExp('^[^'+rtlChars+']*['+ltrChars+']'); + + return ltrDirCheck.test(text); +} + +export function setTextDirections($elem) { + $elem.find('*').each((i, e) => { + let $e = $(e), + textContent = $e.text(); + if (textContent) { + isRTL(textContent) ? $e.attr('dir', 'rtl') : $e.attr('dir', 'ltr'); + } + }); +} + +export function siteDir() { + return $('html').hasClass('rtl') ? 'rtl' : 'ltr'; +} diff --git a/app/assets/javascripts/discourse/models/topic.js.es6 b/app/assets/javascripts/discourse/models/topic.js.es6 index 69a4f9c27f2..4239398f053 100644 --- a/app/assets/javascripts/discourse/models/topic.js.es6 +++ b/app/assets/javascripts/discourse/models/topic.js.es6 @@ -3,6 +3,7 @@ import { flushMap } from 'discourse/models/store'; import RestModel from 'discourse/models/rest'; import { propertyEqual } from 'discourse/lib/computed'; import { longDate } from 'discourse/lib/formatter'; +import { isRTL } from 'discourse/lib/text-direction'; import computed from 'ember-addons/ember-computed-decorators'; import ActionSummary from 'discourse/models/action-summary'; import { popupAjaxError } from 'discourse/lib/ajax-error'; @@ -58,7 +59,13 @@ const Topic = RestModel.extend({ @computed('fancy_title') fancyTitle(title) { - return censor(emojiUnescape(title || ""), Discourse.Site.currentProp('censored_words')); + let fancyTitle = censor(emojiUnescape(title || ""), Discourse.Site.currentProp('censored_words')); + + if (Discourse.SiteSettings.support_mixed_text_direction) { + let titleDir = isRTL(title) ? 'rtl' : 'ltr'; + return '' + fancyTitle + ''; + } + return fancyTitle; }, // returns createdAt if there's no bumped date diff --git a/app/assets/javascripts/discourse/templates/components/categories-only.hbs b/app/assets/javascripts/discourse/templates/components/categories-only.hbs index f10712bb61e..2fa528e3a92 100644 --- a/app/assets/javascripts/discourse/templates/components/categories-only.hbs +++ b/app/assets/javascripts/discourse/templates/components/categories-only.hbs @@ -16,7 +16,7 @@
{{category-title-link category=c}}
- {{{c.description_excerpt}}} + {{{dir-span c.description_excerpt}}}
diff --git a/app/assets/javascripts/discourse/templates/components/category-title-link.hbs b/app/assets/javascripts/discourse/templates/components/category-title-link.hbs index fcb0bdeb071..3403e70d494 100644 --- a/app/assets/javascripts/discourse/templates/components/category-title-link.hbs +++ b/app/assets/javascripts/discourse/templates/components/category-title-link.hbs @@ -3,7 +3,7 @@ {{d-icon 'lock'}} {{/if}} - {{category.name}} + {{dir-span category.name}} {{#if category.uploaded_logo.url}}
{{cdn-img src=category.uploaded_logo.url class="category-logo"}}
diff --git a/app/assets/javascripts/discourse/templates/list/topic-excerpt.raw.hbs b/app/assets/javascripts/discourse/templates/list/topic-excerpt.raw.hbs index 0a42a6a0c56..1c7b5eead0e 100644 --- a/app/assets/javascripts/discourse/templates/list/topic-excerpt.raw.hbs +++ b/app/assets/javascripts/discourse/templates/list/topic-excerpt.raw.hbs @@ -1,6 +1,6 @@ {{#if topic.hasExcerpt}}
- {{{topic.escapedExcerpt}}} + {{{dir-span topic.escapedExcerpt}}} {{#if topic.excerptTruncated}} {{i18n 'read_more'}} {{/if}} diff --git a/app/assets/javascripts/discourse/templates/navigation/category.hbs b/app/assets/javascripts/discourse/templates/navigation/category.hbs index d8dcac7040c..55c7e7ef849 100644 --- a/app/assets/javascripts/discourse/templates/navigation/category.hbs +++ b/app/assets/javascripts/discourse/templates/navigation/category.hbs @@ -5,7 +5,7 @@ {{#if category.uploaded_logo.url}} {{cdn-img src=category.uploaded_logo.url class="category-logo"}} {{#if category.description}} -

{{{category.description}}}

+

{{{dir-span category.description}}}

{{/if}} {{/if}} diff --git a/app/assets/javascripts/select-kit/templates/components/category-row.hbs b/app/assets/javascripts/select-kit/templates/components/category-row.hbs index 985fe9cd74a..85cdfd8f156 100644 --- a/app/assets/javascripts/select-kit/templates/components/category-row.hbs +++ b/app/assets/javascripts/select-kit/templates/components/category-row.hbs @@ -15,7 +15,7 @@ {{/if}} {{#if shouldDisplayDescription}} -
{{{description}}}
+
{{{dir-span description}}}
{{/if}} {{else}} {{{label}}} diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index dc948cbbdb6..0edc451ef10 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1278,6 +1278,7 @@ en: olist_title: "Numbered List" ulist_title: "Bulleted List" list_item: "List item" + toggle_direction: "Toggle Direction" help: "Markdown Editing Help" collapse: "minimize the composer panel" abandon: "close composer and discard draft" diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index d698d82fbab..a328a54a71a 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -966,6 +966,7 @@ en: default_locale: "The default language of this Discourse instance" allow_user_locale: "Allow users to choose their own language interface preference" set_locale_from_accept_language_header: "set interface language for anonymous users from their web browser's language headers. (EXPERIMENTAL, does not work with anonymous cache)" + support_mixed_text_direction: "Support mixed left-to-right and right-to-left text directions." min_post_length: "Minimum allowed post length in characters" min_first_post_length: "Minimum allowed first post (topic body) length in characters" min_private_message_post_length: "Minimum allowed post length in characters for messages" diff --git a/config/site_settings.yml b/config/site_settings.yml index e02399e1515..3fddeee679f 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -79,6 +79,9 @@ basic: set_locale_from_accept_language_header: default: false validator: "AllowUserLocaleEnabledValidator" + support_mixed_text_direction: + client: true + default: false categories_topics: default: 20 min: 5 From 42970e758e80b1dccf7aaeee637e36a4c7f2cf83 Mon Sep 17 00:00:00 2001 From: scossar Date: Sun, 28 Jan 2018 18:45:11 -0800 Subject: [PATCH 2/5] Use consistent style for string concatenation --- app/assets/javascripts/discourse/models/topic.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/discourse/models/topic.js.es6 b/app/assets/javascripts/discourse/models/topic.js.es6 index 4239398f053..b8e6f897259 100644 --- a/app/assets/javascripts/discourse/models/topic.js.es6 +++ b/app/assets/javascripts/discourse/models/topic.js.es6 @@ -63,7 +63,7 @@ const Topic = RestModel.extend({ if (Discourse.SiteSettings.support_mixed_text_direction) { let titleDir = isRTL(title) ? 'rtl' : 'ltr'; - return '' + fancyTitle + ''; + return `${fancyTitle}`; } return fancyTitle; }, From 41f1e7430c2c01d158247a470f81a92158aafb09 Mon Sep 17 00:00:00 2001 From: scossar Date: Mon, 29 Jan 2018 17:42:19 -0800 Subject: [PATCH 3/5] Refactor code; add tests --- .../discourse/components/d-editor.js.es6 | 2 +- .../discourse/components/text-field.js.es6 | 8 +++--- .../discourse/lib/text-direction.js.es6 | 12 +++++---- .../components/d-editor-test.js.es6 | 20 +++++++++++++++ .../components/text-field-test.js.es6 | 24 ++++++++++++++++++ .../lib/category-badge-test.js.es6 | 25 +++++++++++++++++++ test/javascripts/models/topic-test.js.es6 | 9 +++++++ 7 files changed, 89 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/discourse/components/d-editor.js.es6 b/app/assets/javascripts/discourse/components/d-editor.js.es6 index 10d1a4fa534..010f11bd2ba 100644 --- a/app/assets/javascripts/discourse/components/d-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/d-editor.js.es6 @@ -112,7 +112,7 @@ class Toolbar { this.addButton({ id: 'toggle-direction', group: 'extras', - icon: 'arrows-h', + icon: 'exchange', shortcut: 'Shift+6', title: 'composer.toggle_direction', perform: e => e.toggleDirection(), diff --git a/app/assets/javascripts/discourse/components/text-field.js.es6 b/app/assets/javascripts/discourse/components/text-field.js.es6 index c2bb0eaf51c..ae26f6e99f0 100644 --- a/app/assets/javascripts/discourse/components/text-field.js.es6 +++ b/app/assets/javascripts/discourse/components/text-field.js.es6 @@ -1,14 +1,12 @@ import computed from "ember-addons/ember-computed-decorators"; -import { siteDir } from "discourse/lib/text-direction"; -import { isRTL } from "discourse/lib/text-direction"; -import { isLTR } from "discourse/lib/text-direction"; +import { siteDir, isRTL, isLTR } from "discourse/lib/text-direction"; export default Ember.TextField.extend({ attributeBindings: ['autocorrect', 'autocapitalize', 'autofocus', 'maxLength', 'dir'], @computed dir() { - if (Discourse.SiteSettings.support_mixed_text_direction) { + if (this.siteSettings.support_mixed_text_direction) { let val = this.value; if (val) { return isRTL(val) ? 'rtl' : 'ltr'; @@ -19,7 +17,7 @@ export default Ember.TextField.extend({ }, keyUp() { - if (Discourse.SiteSettings.support_mixed_text_direction) { + if (this.siteSettings.support_mixed_text_direction) { let val = this.value; if (isRTL(val)) { this.set('dir', 'rtl'); diff --git a/app/assets/javascripts/discourse/lib/text-direction.js.es6 b/app/assets/javascripts/discourse/lib/text-direction.js.es6 index 2a4b9da2c36..928b147ed79 100644 --- a/app/assets/javascripts/discourse/lib/text-direction.js.es6 +++ b/app/assets/javascripts/discourse/lib/text-direction.js.es6 @@ -1,15 +1,14 @@ const ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF'; const rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC'; +const rtlDirCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']'); +const ltrDirCheck = new RegExp('^[^'+rtlChars+']*['+ltrChars+']'); +let _siteDir; export function isRTL(text) { - const rtlDirCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']'); - return rtlDirCheck.test(text); } export function isLTR(text) { - const ltrDirCheck = new RegExp('^[^'+rtlChars+']*['+ltrChars+']'); - return ltrDirCheck.test(text); } @@ -24,5 +23,8 @@ export function setTextDirections($elem) { } export function siteDir() { - return $('html').hasClass('rtl') ? 'rtl' : 'ltr'; + if (!_siteDir) { + _siteDir = $('html').hasClass('rtl') ? 'rtl' : 'ltr'; + } + return _siteDir; } diff --git a/test/javascripts/components/d-editor-test.js.es6 b/test/javascripts/components/d-editor-test.js.es6 index faf4f30b3b8..e0409e4957d 100644 --- a/test/javascripts/components/d-editor-test.js.es6 +++ b/test/javascripts/components/d-editor-test.js.es6 @@ -715,6 +715,26 @@ testCase(`list button with line sequence`, function(assert, textarea) { }); }); +componentTest('clicking the toggle-direction button toggles the direction', { + template: '{{d-editor value=value}}', + beforeEach() { + this.siteSettings.support_mixed_text_direction = true; + this.siteSettings.default_locale = "en"; + }, + + test(assert) { + const textarea = this.$('textarea.d-editor-input'); + click('button.toggle-direction'); + andThen(() => { + assert.equal(textarea.attr('dir'), 'rtl'); + }); + click('button.toggle-direction'); + andThen(() => { + assert.equal(textarea.attr('dir'), 'ltr'); + }); + } +}); + testCase(`doesn't jump to bottom with long text`, function(assert, textarea) { let longText = 'hello world.'; diff --git a/test/javascripts/components/text-field-test.js.es6 b/test/javascripts/components/text-field-test.js.es6 index e18662c2ab9..7a2de69a5a2 100644 --- a/test/javascripts/components/text-field-test.js.es6 +++ b/test/javascripts/components/text-field-test.js.es6 @@ -22,3 +22,27 @@ componentTest("support a placeholder", { assert.equal(this.$('input').prop('placeholder'), 'placeholder.i18n.key'); } }); + +componentTest("sets the dir attribute to ltr for Hebrew text", { + template: `{{text-field value='זהו שם עברי עם מקום עברי'}}`, + beforeEach() { + this.siteSettings.support_mixed_text_direction = true; + }, + + test(assert) { + assert.equal(this.$('input').attr('dir'), 'rtl'); + } +}); + +componentTest("sets the dir attribute to ltr for English text", { + template: `{{text-field value='This is a ltr title'}}`, + beforeEach() { + this.siteSettings.support_mixed_text_direction = true; + }, + + test(assert) { + assert.equal(this.$('input').attr('dir'), 'ltr'); + } +}); + + diff --git a/test/javascripts/lib/category-badge-test.js.es6 b/test/javascripts/lib/category-badge-test.js.es6 index 17322d46191..5fdc807dec4 100644 --- a/test/javascripts/lib/category-badge-test.js.es6 +++ b/test/javascripts/lib/category-badge-test.js.es6 @@ -45,3 +45,28 @@ QUnit.test("allowUncategorized", assert => { assert.blank(categoryBadgeHTML(uncategorized), "it doesn't return HTML for uncategorized by default"); assert.present(categoryBadgeHTML(uncategorized, {allowUncategorized: true}), "it returns HTML"); }); + +QUnit.test("category names are wrapped in dir-spans", assert => { + Discourse.SiteSettings.support_mixed_text_direction = true; + const store = createStore(); + const rtlCategory = store.createRecord('category', { + name: 'תכנות עם Ruby', + id: 123, + description_text: 'cool description', + color: 'ff0', + text_color: 'f00' + }); + + const ltrCategory = store.createRecord('category', { + name: 'Programming in Ruby', + id: 234 + }); + + let tag = parseHTML(categoryBadgeHTML(rtlCategory))[0]; + let dirSpan = tag.children[1].children[0]; + assert.equal(dirSpan.attributes.dir, 'rtl'); + + tag = parseHTML(categoryBadgeHTML(ltrCategory))[0]; + dirSpan = tag.children[1].children[0]; + assert.equal(dirSpan.attributes.dir, 'ltr'); +}); diff --git a/test/javascripts/models/topic-test.js.es6 b/test/javascripts/models/topic-test.js.es6 index 2e9ce444365..7c33bceff03 100644 --- a/test/javascripts/models/topic-test.js.es6 +++ b/test/javascripts/models/topic-test.js.es6 @@ -98,6 +98,15 @@ QUnit.test('fancyTitle', assert => { "supports emojis"); }); +QUnit.test('fancyTitle direction', assert => { + const rtlTopic = Topic.create({ fancy_title: "هذا اختبار" }); + const ltrTopic = Topic.create({ fancy_title: "This is a test"}); + + Discourse.SiteSettings.support_mixed_text_direction = true; + assert.equal(rtlTopic.get('fancyTitle'), `هذا اختبار`, "sets the dir-span to rtl"); + assert.equal(ltrTopic.get('fancyTitle'), `This is a test`, "sets the dir-span to ltr"); +}); + QUnit.test('excerpt', assert => { const topic = Topic.create({ excerpt: "This is a test topic :smile:", pinned: true }); From 5d18f72b8c17d09917a52c7f0ab4bbdbae41a7d9 Mon Sep 17 00:00:00 2001 From: scossar Date: Mon, 29 Jan 2018 19:16:35 -0800 Subject: [PATCH 4/5] Add tests for text-direction functions --- .../lib/text-direction-test.js.es6 | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test/javascripts/lib/text-direction-test.js.es6 diff --git a/test/javascripts/lib/text-direction-test.js.es6 b/test/javascripts/lib/text-direction-test.js.es6 new file mode 100644 index 00000000000..c12c03cb1e6 --- /dev/null +++ b/test/javascripts/lib/text-direction-test.js.es6 @@ -0,0 +1,23 @@ +import { isRTL, isLTR, setTextDirections, siteDir } from 'discourse/lib/text-direction'; + +QUnit.module('lib:text-direction'); + +QUnit.test("isRTL", assert => { + // Hebrew + assert.equal(isRTL('זה מבחן'), true); + + // Arabic + assert.equal(isRTL('هذا اختبار'), true); + + // Persian + assert.equal(isRTL('این یک امتحان است'), true); + + assert.equal(isRTL('This is a test'), false); + assert.equal(isRTL(''), false); +}); + +QUnit.test("isLTR", assert => { + assert.equal(isLTR('This is a test'), true); + assert.equal(isLTR('זה מבחן'), false); +}); + From 843d88c5d0a3b937ef48f4ffa0df3e73572629e3 Mon Sep 17 00:00:00 2001 From: scossar Date: Mon, 29 Jan 2018 20:11:12 -0800 Subject: [PATCH 5/5] Remove unused imports --- test/javascripts/lib/text-direction-test.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/javascripts/lib/text-direction-test.js.es6 b/test/javascripts/lib/text-direction-test.js.es6 index c12c03cb1e6..c8ddee262b8 100644 --- a/test/javascripts/lib/text-direction-test.js.es6 +++ b/test/javascripts/lib/text-direction-test.js.es6 @@ -1,4 +1,4 @@ -import { isRTL, isLTR, setTextDirections, siteDir } from 'discourse/lib/text-direction'; +import { isRTL, isLTR } from 'discourse/lib/text-direction'; QUnit.module('lib:text-direction');