diff --git a/app/assets/javascripts/discourse/dialects/quote_dialect.js b/app/assets/javascripts/discourse/dialects/quote_dialect.js index 28f8de131cb..df299b1337a 100644 --- a/app/assets/javascripts/discourse/dialects/quote_dialect.js +++ b/app/assets/javascripts/discourse/dialects/quote_dialect.js @@ -23,11 +23,11 @@ Discourse.BBCode.register('quote', {noWrap: true, singlePara: true}, function(co } var avatarImg; + var postNumber = parseInt(params['data-post'], 10); + var topicId = parseInt(params['data-topic'], 10); + if (options.lookupAvatarByPostNumber) { // client-side, we can retrieve the avatar from the post - var postNumber = parseInt(params['data-post'], 10); - var topicId = parseInt(params['data-topic'], 10); - avatarImg = options.lookupAvatarByPostNumber(postNumber, topicId); } else if (options.lookupAvatar) { // server-side, we need to lookup the avatar from the username @@ -39,12 +39,22 @@ Discourse.BBCode.register('quote', {noWrap: true, singlePara: true}, function(co return ['p', ['aside', params, ['blockquote'].concat(contents)]]; } - return ['aside', params, - ['div', {'class': 'title'}, - ['div', {'class': 'quote-controls'}], - avatarImg ? ['__RAW', avatarImg] : "", - username ? I18n.t('user.said', {username: username}) : "" - ], - ['blockquote'].concat(contents) - ]; + var header = [ 'div', {'class': 'title'}, + ['div', {'class': 'quote-controls'}], + avatarImg ? ['__RAW', avatarImg] : "", + username ? I18n.t('user.said', {username: username}) : "" + ]; + + if (options.topicId && postNumber && options.getTopicInfo && topicId !== options.topicId) { + var topicInfo = options.getTopicInfo(topicId); + if (topicInfo) { + header.push(' '); + var href = topicInfo.href; + if (postNumber > 0) { href += "/" + postNumber; } + header.push(['a', {'href': href}, topicInfo.title]); + } + } + + + return ['aside', params, header, ['blockquote'].concat(contents)]; }); diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index 1b43959482c..0881296e8ba 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -39,6 +39,18 @@ module PrettyText username = username.downcase User.exec_sql('SELECT 1 FROM users WHERE username_lower = ?', username).values.length == 1 end + + def get_topic_info(topic_id) + return unless Fixnum === topic_id + # TODO this only handles public topics, secured one do not get this + topic = Topic.find_by(id: topic_id) + if topic && Guardian.new.can_see?(topic) + { + title: topic.title, + href: topic.url + } + end + end end @mutex = Mutex.new @@ -184,6 +196,7 @@ module PrettyText context.eval('opts["mentionLookup"] = function(u){return helpers.is_username_valid(u);}') context.eval('opts["lookupAvatar"] = function(p){return Discourse.Utilities.avatarImg({size: "tiny", avatarTemplate: helpers.avatar_template(p)});}') + context.eval('opts["getTopicInfo"] = function(i){return helpers.get_topic_info(i)};') baked = context.eval('Discourse.Markdown.markdownConverter(opts).makeHtml(raw)') end diff --git a/spec/components/pretty_text_spec.rb b/spec/components/pretty_text_spec.rb index f9c7333c611..b62875affc8 100644 --- a/spec/components/pretty_text_spec.rb +++ b/spec/components/pretty_text_spec.rb @@ -8,10 +8,23 @@ describe PrettyText do describe "Cooking" do + describe "off topic quoting" do + it "can correctly populate topic title" do + topic = Fabricate(:topic, title: "this is a test topic") + expected = <
+
EvilTrout: This is a test topic +
+

ddd

+HTML + expect(PrettyText.cook("[quote=\"EvilTrout, post:2, topic:#{topic.id}\"]ddd\n[/quote]", topic_id: 1)).to match_html expected + end + end + describe "with avatar" do let(:default_avatar) { "//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/{size}.png" } - before(:each) do + before do eviltrout = User.new User.stubs(:default_template).returns(default_avatar) User.expects(:find_by).with(username_lower: "eviltrout").returns(eviltrout)