mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 10:33:51 +08:00
Email parsing uses Traditional Markdown Linebreaks by default. Added JS tests for line breaks.
This commit is contained in:
parent
bfdbf373f3
commit
bb908d5913
|
@ -122,7 +122,8 @@ Discourse.Markdown = {
|
|||
});
|
||||
|
||||
// newline prediction in trivial cases
|
||||
if (!Discourse.SiteSettings.traditional_markdown_linebreaks) {
|
||||
var linebreaks = opts.traditional_markdown_linebreaks || Discourse.SiteSettings.traditional_markdown_linebreaks;
|
||||
if (!linebreaks) {
|
||||
converter.hooks.chain("preConversion", function(text) {
|
||||
return text.replace(/(^[\w<][^\n]*\n+)/gim, function(t) {
|
||||
if (t.match(/\n{2}/gim)) return t;
|
||||
|
|
|
@ -34,8 +34,8 @@ class Post < ActiveRecord::Base
|
|||
|
||||
validates_with ::Validators::PostValidator
|
||||
|
||||
# We can pass a hash of image sizes when saving to prevent crawling those images
|
||||
attr_accessor :image_sizes, :quoted_post_numbers, :no_bump, :invalidate_oneboxes
|
||||
# We can pass several creating options to a post via attributes
|
||||
attr_accessor :image_sizes, :quoted_post_numbers, :no_bump, :invalidate_oneboxes, :cooking_options
|
||||
|
||||
SHORT_POST_CHARS = 1200
|
||||
|
||||
|
|
|
@ -82,7 +82,8 @@ module Email
|
|||
creator = PostCreator.new(email_log.user,
|
||||
raw: @body,
|
||||
topic_id: @email_log.topic_id,
|
||||
reply_to_post_number: @email_log.post.post_number)
|
||||
reply_to_post_number: @email_log.post.post_number,
|
||||
cooking_options: {traditional_markdown_linebreaks: true})
|
||||
|
||||
creator.create
|
||||
end
|
||||
|
|
|
@ -32,11 +32,13 @@ class PostCreator
|
|||
# target_usernames - comma delimited list of usernames for membership (private message)
|
||||
# target_group_names - comma delimited list of groups for membership (private message)
|
||||
# meta_data - Topic meta data hash
|
||||
# cooking_options - Options for rendering the text
|
||||
#
|
||||
def initialize(user, opts)
|
||||
# TODO: we should reload user in case it is tainted, should take in a user_id as opposed to user
|
||||
# If we don't do this we introduce a rather risky dependency
|
||||
@user = user
|
||||
@opts = opts
|
||||
@opts = opts || {}
|
||||
@spam = false
|
||||
end
|
||||
|
||||
|
@ -87,14 +89,17 @@ class PostCreator
|
|||
end
|
||||
|
||||
post.post_number ||= Topic.next_post_number(post.topic_id, post.reply_to_post_number.present?)
|
||||
post.cooked ||= post.cook(post.raw, topic_id: post.topic_id)
|
||||
|
||||
cooking_options = post.cooking_options || {}
|
||||
cooking_options[:topic_id] = post.topic_id
|
||||
|
||||
post.cooked ||= post.cook(post.raw, cooking_options)
|
||||
post.sort_order = post.post_number
|
||||
DiscourseEvent.trigger(:before_create_post, post)
|
||||
post.last_version_at ||= Time.now
|
||||
end
|
||||
|
||||
def self.after_create_tasks(post)
|
||||
Rails.logger.info (">" * 30) + "#{post.no_bump} #{post.created_at}"
|
||||
# Update attributes on the topic - featured users and last posted.
|
||||
attrs = {last_posted_at: post.created_at, last_post_user_id: post.user_id}
|
||||
attrs[:bumped_at] = post.created_at unless post.no_bump
|
||||
|
@ -183,14 +188,13 @@ class PostCreator
|
|||
user: @user,
|
||||
reply_to_post_number: @opts[:reply_to_post_number])
|
||||
|
||||
post.post_type = @opts[:post_type] if @opts[:post_type].present?
|
||||
post.no_bump = @opts[:no_bump] if @opts[:no_bump].present?
|
||||
post.extract_quoted_post_numbers
|
||||
post.acting_user = @opts[:acting_user] if @opts[:acting_user].present?
|
||||
post.created_at = Time.zone.parse(@opts[:created_at].to_s) if @opts[:created_at].present?
|
||||
# Attributes we pass through to the post instance if present
|
||||
[:post_type, :no_bump, :cooking_options, :image_sizes, :acting_user, :invalidate_oneboxes].each do |a|
|
||||
post.send("#{a}=", @opts[a]) if @opts[a].present?
|
||||
end
|
||||
|
||||
post.image_sizes = @opts[:image_sizes] if @opts[:image_sizes].present?
|
||||
post.invalidate_oneboxes = @opts[:invalidate_oneboxes] if @opts[:invalidate_oneboxes].present?
|
||||
post.extract_quoted_post_numbers
|
||||
post.created_at = Time.zone.parse(@opts[:created_at].to_s) if @opts[:created_at].present?
|
||||
@post = post
|
||||
end
|
||||
|
||||
|
|
|
@ -40,16 +40,6 @@ stripped from my reply?")
|
|||
end
|
||||
end
|
||||
|
||||
describe "with a content boundary" do
|
||||
let(:bounded_email) { File.read("#{Rails.root}/spec/fixtures/emails/boundary.eml") }
|
||||
let(:receiver) { Email::Receiver.new(bounded_email) }
|
||||
|
||||
it "does something" do
|
||||
receiver.process
|
||||
expect(receiver.body).to eq("I'll look into it, thanks!")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a valid email" do
|
||||
let(:reply_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" }
|
||||
let(:valid_reply) { File.read("#{Rails.root}/spec/fixtures/emails/valid_reply.eml") }
|
||||
|
@ -83,7 +73,11 @@ greatest show ever created. Everyone should watch it.
|
|||
EmailLog.expects(:for).with(reply_key).returns(email_log)
|
||||
|
||||
creator = mock
|
||||
PostCreator.expects(:new).with(instance_of(User), has_entry(raw: reply_body)).returns(creator)
|
||||
PostCreator.expects(:new).with(instance_of(User),
|
||||
has_entries(raw: reply_body,
|
||||
cooking_options: {traditional_markdown_linebreaks: true}))
|
||||
.returns(creator)
|
||||
|
||||
creator.expects(:create)
|
||||
end
|
||||
|
||||
|
|
|
@ -253,6 +253,20 @@ describe PostCreator do
|
|||
|
||||
end
|
||||
|
||||
context "cooking options" do
|
||||
let(:raw) { "this is my awesome message body hello world" }
|
||||
|
||||
it "passes the cooking options through correctly" do
|
||||
creator = PostCreator.new(user,
|
||||
title: 'hi there welcome to my topic',
|
||||
raw: raw,
|
||||
cooking_options: { traditional_markdown_linebreaks: true })
|
||||
|
||||
Post.any_instance.expects(:cook).with(raw, has_key(:traditional_markdown_linebreaks)).returns(raw)
|
||||
creator.create
|
||||
end
|
||||
end
|
||||
|
||||
# integration test ... minimise db work
|
||||
context 'private message' do
|
||||
let(:target_user1) { Fabricate(:coding_horror) }
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/*global sanitizeHtml:true */
|
||||
|
||||
module("Discourse.Markdown");
|
||||
module("Discourse.Markdown", {
|
||||
setup: function() {
|
||||
Discourse.SiteSettings.traditional_markdown_linebreaks = false;
|
||||
}
|
||||
});
|
||||
|
||||
var cooked = function(input, expected, text) {
|
||||
equal(Discourse.Markdown.cook(input, {mentionLookup: false }), expected, text);
|
||||
|
@ -12,7 +16,24 @@ var cookedOptions = function(input, opts, expected, text) {
|
|||
|
||||
test("basic cooking", function() {
|
||||
cooked("hello", "<p>hello</p>", "surrounds text with paragraphs");
|
||||
cooked("1\n2\n3", "<p>1 <br>\n2 <br>\n3</p>", "automatically handles trivial newlines");
|
||||
|
||||
});
|
||||
|
||||
test("Line Breaks", function() {
|
||||
|
||||
var input = "1\n2\n3";
|
||||
cooked(input, "<p>1 <br>\n2 <br>\n3</p>", "automatically handles trivial newlines");
|
||||
|
||||
var traditionalOutput = "<p>1\n2\n3</p>";
|
||||
|
||||
cookedOptions(input,
|
||||
{traditional_markdown_linebreaks: true},
|
||||
traditionalOutput,
|
||||
"It supports traditional markdown via an option")
|
||||
|
||||
Discourse.SiteSettings.traditional_markdown_linebreaks = true;
|
||||
cooked(input, traditionalOutput, "It supports traditional markdown via a Site Setting")
|
||||
|
||||
});
|
||||
|
||||
test("Links", function() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user