diff --git a/app/helpers/format_helper.rb b/app/helpers/format_helper.rb index a2bff0cec..4395300b4 100644 --- a/app/helpers/format_helper.rb +++ b/app/helpers/format_helper.rb @@ -180,6 +180,15 @@ def restricted_markdown(text, truncate: 2000) truncate(sanitize(markdown.render(text), remove_elements: %w[a]), length: truncate) end + def markdown_with_variables(text, conference, escape_html = true) + return '' if text.nil? + + parser = EmailTemplateParser.new(conference) + values = parser.retrieve_values + text = EmailTemplateParser.parse_template(text, values) + markdown(text, escape_html) + end + def markdown(text, escape_html = true) return '' if text.nil? diff --git a/app/services/email_template_parser.rb b/app/services/email_template_parser.rb index 9c74e2d78..1d40942b5 100644 --- a/app/services/email_template_parser.rb +++ b/app/services/email_template_parser.rb @@ -1,5 +1,5 @@ class EmailTemplateParser - def initialize(conference, user) + def initialize(conference, user = nil) @conference = conference @user = user end @@ -7,8 +7,6 @@ def initialize(conference, user) # rubocop:disable Metrics/AbcSize, Metrics/ParameterLists def retrieve_values(event = nil, booth = nil, quantity = nil, ticket = nil) h = { - 'email' => @user.email, - 'name' => @user.name, 'conference' => @conference.title, 'conference_start_date' => @conference.start_date, 'conference_end_date' => @conference.end_date, @@ -23,6 +21,10 @@ def retrieve_values(event = nil, booth = nil, quantity = nil, ticket = nil) @conference.short_title, host: Rails.application.routes.default_url_options[:host] ) } + if @user + h['email'] = @user.email + h['name'] = @user.name + end if @conference.program.cfp h['cfp_start_date'] = @conference.program.cfp.start_date h['cfp_end_date'] = @conference.program.cfp.end_date diff --git a/app/views/admin/conferences/_form_fields.html.haml b/app/views/admin/conferences/_form_fields.html.haml index c5439f1ac..cdd280c4a 100644 --- a/app/views/admin/conferences/_form_fields.html.haml +++ b/app/views/admin/conferences/_form_fields.html.haml @@ -23,10 +23,12 @@ = f.label :description = f.text_area :description, rows: 5, data: { provide: 'markdown' }, class: 'form-control' .help-block= markdown_hint('Splash page content') + = render partial: 'shared/help', locals: { id: 'description_help', show_event_variables: false, show_ticket_variables: false, show_user_variables: false } .form-group = f.label :registered_attendees_message, 'Message for Registered Attendees' = f.text_area :registered_attendees_message, rows: 5, data: { provide: 'markdown' }, class: 'form-control' .help-block= markdown_hint('Splash page content') + = render partial: 'shared/help', locals: { id: 'registered_attendees_help', show_event_variables: false, show_ticket_variables: false, show_user_variables: false } .form-group = f.color_field :color, size: 6, class: 'form-control' %span.help-block diff --git a/app/views/conferences/_about_and_happening_now.haml b/app/views/conferences/_about_and_happening_now.haml index 05141967d..4017e0238 100644 --- a/app/views/conferences/_about_and_happening_now.haml +++ b/app/views/conferences/_about_and_happening_now.haml @@ -9,8 +9,8 @@ = content_for :about do #about -if @user_registered && conference.registered_attendees_message.present? - = markdown(conference.registered_attendees_message, false) - = markdown(conference.description, false) + = markdown_with_variables(conference.registered_attendees_message, conference, false) + = markdown_with_variables(conference.description, conference, false) %section#about-and-happening-now .container diff --git a/app/views/conferences/_conference_details.html.haml b/app/views/conferences/_conference_details.html.haml index b860d609a..2c87c2df7 100644 --- a/app/views/conferences/_conference_details.html.haml +++ b/app/views/conferences/_conference_details.html.haml @@ -20,7 +20,7 @@ %span>= conference.country_name - unless conference.description.blank? %p - = markdown(truncate(conference.description, length: 1000, separator: "\n", escape: false), escape_html=false) + = markdown_with_variables(truncate(conference.description, length: 1000, separator: "\n", escape: false), conference, escape_html=false) .col-md-2 .btn-group-vertical - if !@conference || @conference != conference diff --git a/app/views/shared/_help.html.haml b/app/views/shared/_help.html.haml index 8bf1ffc33..2ac9c3881 100644 --- a/app/views/shared/_help.html.haml +++ b/app/views/shared/_help.html.haml @@ -1,12 +1,13 @@ .template-help{ id: id } Valid attributes: %table.table - %tr - %td {email} - %td The user's email address - %tr - %td {name} - %td The user's full name + - if local_assigns.fetch(:show_user_variables, true) + %tr + %td {email} + %td The user's email address + %tr + %td {name} + %td The user's full name %tr %td {conference} %td The full conference title diff --git a/spec/helpers/format_helper_spec.rb b/spec/helpers/format_helper_spec.rb index 80c512529..7bb2beaa3 100644 --- a/spec/helpers/format_helper_spec.rb +++ b/spec/helpers/format_helper_spec.rb @@ -30,4 +30,35 @@ .to eq "

a

\n" end end + + describe 'markdown_with_variables' do + let(:conference) do + create(:conference, short_title: 'snap21', title: 'SnapCon 2021', + start_date: Date.new(2021, 7, 12), end_date: Date.new(2021, 7, 16)) + end + + it 'substitutes conference variables and renders markdown' do + text = 'Welcome to **{conference}**, running {conference_start_date} to {conference_end_date}.' + result = markdown_with_variables(text, conference, false) + expect(result).to include('Welcome to SnapCon 2021') + expect(result).to include('2021-07-12') + expect(result).to include('2021-07-16') + end + + it 'returns empty string for nil text' do + expect(markdown_with_variables(nil, conference)).to eq '' + end + + it 'renders normally when there are no placeholders' do + text = 'Just a regular description.' + expect(markdown_with_variables(text, conference, false)).to eq "

Just a regular description.

\n" + end + + it 'includes venue when conference has one' do + conference.venue = create(:venue) + text = 'Join us at {venue}.' + result = markdown_with_variables(text, conference, false) + expect(result).to include(conference.venue.name) + end + end end diff --git a/spec/services/email_template_parser_spec.rb b/spec/services/email_template_parser_spec.rb new file mode 100644 index 000000000..2877d8b45 --- /dev/null +++ b/spec/services/email_template_parser_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe EmailTemplateParser do + let(:conference) do + create(:conference, short_title: 'goto', start_date: Date.new(2014, 5, 1), end_date: Date.new(2014, 5, 6)) + end + let(:user) { create(:user, username: 'johnd', email: 'john@doe.com', name: 'John Doe') } + + describe '#retrieve_values' do + context 'without a user' do + let(:parser) { described_class.new(conference, nil) } + + it 'returns conference values without user values' do + values = parser.retrieve_values + expect(values['conference']).to eq conference.title + expect(values['conference_start_date']).to eq Date.new(2014, 5, 1) + expect(values['conference_end_date']).to eq Date.new(2014, 5, 6) + expect(values).not_to have_key('email') + expect(values).not_to have_key('name') + end + + it 'includes venue when conference has one' do + conference.venue = create(:venue) + values = parser.retrieve_values + expect(values['venue']).to eq conference.venue.name + expect(values['venue_address']).to eq conference.venue.address + end + + it 'includes cfp dates when conference has cfp' do + create(:cfp, start_date: Date.new(2014, 4, 29), end_date: Date.new(2014, 5, 6), + program: conference.program) + values = parser.retrieve_values + expect(values['cfp_start_date']).to eq Date.new(2014, 4, 29) + expect(values['cfp_end_date']).to eq Date.new(2014, 5, 6) + end + end + + context 'with a user' do + let(:parser) { described_class.new(conference, user) } + + it 'includes user values' do + values = parser.retrieve_values + expect(values['email']).to eq 'john@doe.com' + expect(values['name']).to eq 'John Doe' + expect(values['conference']).to eq conference.title + end + end + end + + describe '.parse_template' do + it 'substitutes conference variables in text' do + values = { 'conference' => 'SnapCon 2014', 'conference_start_date' => Date.new(2014, 5, 1) } + text = 'Welcome to {conference}, starting {conference_start_date}!' + result = described_class.parse_template(text, values) + expect(result).to eq 'Welcome to SnapCon 2014, starting 2014-05-01!' + end + + it 'leaves unknown placeholders alone' do + values = { 'conference' => 'SnapCon 2014' } + text = 'Welcome to {conference}, dear {name}!' + result = described_class.parse_template(text, values) + expect(result).to eq 'Welcome to SnapCon 2014, dear {name}!' + end + end +end