Email parsing uses Traditional Markdown Linebreaks by default. Added JS tests for line breaks.

This commit is contained in:
Robin Ward 2013-06-21 11:36:33 -04:00
parent bfdbf373f3
commit bb908d5913
7 changed files with 62 additions and 27 deletions

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) }

View File

@ -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() {