mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 00:55:06 +08:00
DEV: Correctly tag heredocs (#16061)
This allows text editors to use correct syntax coloring for the heredoc sections. Heredoc tag names we use: languages: SQL, JS, RUBY, LUA, HTML, CSS, SCSS, SH, HBS, XML, YAML/YML, MF, ICS other: MD, TEXT/TXT, RAW, EMAIL
This commit is contained in:
parent
7c4be7f649
commit
2fc70c5572
|
@ -45,14 +45,14 @@ class PostsController < ApplicationController
|
|||
opts[:limit] = MARKDOWN_TOPIC_PAGE_SIZE
|
||||
topic_view = TopicView.new(params[:topic_id], current_user, opts)
|
||||
content = topic_view.posts.map do |p|
|
||||
<<~HEREDOC
|
||||
<<~MD
|
||||
#{p.user.username} | #{p.updated_at} | ##{p.post_number}
|
||||
|
||||
#{p.raw}
|
||||
|
||||
-------------------------
|
||||
|
||||
HEREDOC
|
||||
MD
|
||||
end
|
||||
render plain: content.join
|
||||
end
|
||||
|
|
|
@ -247,7 +247,7 @@ class SessionController < ApplicationController
|
|||
rescue ActiveRecord::RecordInvalid => e
|
||||
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn(<<~EOF)
|
||||
Rails.logger.warn(<<~TEXT)
|
||||
Verbose SSO log: Record was invalid: #{e.record.class.name} #{e.record.id}
|
||||
#{e.record.errors.to_h}
|
||||
|
||||
|
@ -256,7 +256,7 @@ class SessionController < ApplicationController
|
|||
|
||||
SSO Diagnostics:
|
||||
#{sso.diagnostics}
|
||||
EOF
|
||||
TEXT
|
||||
end
|
||||
|
||||
text = nil
|
||||
|
|
|
@ -303,11 +303,11 @@ module Jobs
|
|||
# Simulate the args being dumped/parsed through JSON
|
||||
parsed_opts = JSON.parse(JSON.dump(opts))
|
||||
if opts != parsed_opts
|
||||
Discourse.deprecate(<<~MSG.squish, since: "2.9", drop_from: "3.0")
|
||||
Discourse.deprecate(<<~TEXT.squish, since: "2.9", drop_from: "3.0")
|
||||
#{klass.name} was enqueued with argument values which do not cleanly serialize to/from JSON.
|
||||
This means that the job will be run with slightly different values than the ones supplied to `enqueue`.
|
||||
Argument values should be strings, booleans, numbers, or nil (or arrays/hashes of those value types).
|
||||
MSG
|
||||
TEXT
|
||||
end
|
||||
opts = parsed_opts
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class ReviewableSerializer < ApplicationSerializer
|
|||
def self.create_attribute(name, field)
|
||||
attribute(name)
|
||||
|
||||
class_eval <<~GETTER
|
||||
class_eval <<~RUBY
|
||||
def #{name}
|
||||
#{field}
|
||||
end
|
||||
|
@ -67,7 +67,7 @@ class ReviewableSerializer < ApplicationSerializer
|
|||
def include_#{name}?
|
||||
#{name}.present?
|
||||
end
|
||||
GETTER
|
||||
RUBY
|
||||
end
|
||||
|
||||
# This is easier than creating an AMS method for each attribute
|
||||
|
|
|
@ -11,7 +11,7 @@ class UserActionManager
|
|||
end
|
||||
|
||||
[:notification, :post, :topic, :post_action].each do |type|
|
||||
self.class_eval(<<~METHODS)
|
||||
self.class_eval(<<~RUBY)
|
||||
def self.#{type}_created(*args)
|
||||
return if @disabled
|
||||
#{type}_rows(*args).each { |row| UserAction.log_action!(row) }
|
||||
|
@ -20,7 +20,7 @@ class UserActionManager
|
|||
return if @disabled
|
||||
#{type}_rows(*args).each { |row| UserAction.remove_action!(row) }
|
||||
end
|
||||
METHODS
|
||||
RUBY
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -39,7 +39,7 @@ if ENV["TRACE_PG_CONNECTIONS"]
|
|||
def log_access(&blk)
|
||||
@access_log_mutex.synchronize do
|
||||
if !@accessor_thread.nil?
|
||||
Rails.logger.error <<~STRING
|
||||
Rails.logger.error <<~TEXT
|
||||
PG Clash: A connection is being accessed from two locations
|
||||
|
||||
#{@accessor_thread} was using the connection. Backtrace:
|
||||
|
@ -49,7 +49,7 @@ if ENV["TRACE_PG_CONNECTIONS"]
|
|||
#{Thread.current} is now attempting to use the connection. Backtrace:
|
||||
|
||||
#{Thread.current&.backtrace&.join("\n")}
|
||||
STRING
|
||||
TEXT
|
||||
|
||||
if ENV["ON_PG_CLASH"] == "byebug"
|
||||
require "byebug"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
if defined?(Rails::Server) && Rails.env.production? # Only run these checks when starting up a production server
|
||||
|
||||
if ['localhost', 'production.localhost'].include?(Discourse.current_hostname)
|
||||
puts <<END
|
||||
puts <<~TEXT
|
||||
|
||||
Discourse.current_hostname = '#{Discourse.current_hostname}'
|
||||
|
||||
|
@ -13,20 +13,20 @@ if defined?(Rails::Server) && Rails.env.production? # Only run these checks when
|
|||
so that it uses the hostname of your site. Otherwise you will
|
||||
experience problems, like links in emails using #{Discourse.current_hostname}.
|
||||
|
||||
END
|
||||
TEXT
|
||||
|
||||
raise "Invalid host_names in database.yml"
|
||||
end
|
||||
|
||||
if !Dir.glob(File.join(Rails.root, 'public', 'assets', 'application*.js')).present?
|
||||
puts <<END
|
||||
puts <<~TEXT
|
||||
|
||||
Assets have not been precompiled. Please run the following command
|
||||
before starting the rails server in production mode:
|
||||
|
||||
rake assets:precompile
|
||||
|
||||
END
|
||||
TEXT
|
||||
|
||||
raise "Assets have not been precompiled"
|
||||
end
|
||||
|
|
|
@ -11,10 +11,10 @@ class FixIncorrectUserHistory < ActiveRecord::Migration[4.2]
|
|||
|
||||
# this is a :auto_trust_level_change mislabeled as :check_email
|
||||
# impersonate that was actually delete topic
|
||||
condition = <<CLAUSE
|
||||
(action = 16 AND previous_value in ('0','1','2','3','4')) OR
|
||||
(action = 19 AND target_user_id IS NULL AND details IS NOT NULL)
|
||||
CLAUSE
|
||||
condition = <<~SQL
|
||||
(action = 16 AND previous_value in ('0','1','2','3','4')) OR
|
||||
(action = 19 AND target_user_id IS NULL AND details IS NOT NULL)
|
||||
SQL
|
||||
|
||||
first_wrong_id = execute("SELECT min(id) FROM user_histories WHERE #{condition}").values[0][0].to_i
|
||||
last_wrong_id = execute("SELECT max(id) FROM user_histories WHERE #{condition}").values[0][0].to_i
|
||||
|
|
|
@ -1011,13 +1011,13 @@ module Email
|
|||
|
||||
def forwarded_email_quote_forwarded(destination, user)
|
||||
embedded = embedded_email_raw
|
||||
raw = <<~EOF
|
||||
raw = <<~MD
|
||||
#{@before_embedded}
|
||||
|
||||
[quote]
|
||||
#{PlainTextToMarkdown.new(embedded).to_markdown}
|
||||
[/quote]
|
||||
EOF
|
||||
MD
|
||||
|
||||
return true if forwarded_email_create_topic(destination: destination, user: user, raw: raw, title: subject)
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ class Barber::Precompiler
|
|||
# very hacky but lets us use ES6. I'm ashamed of this code -RW
|
||||
transpiled = transpiled[transpiled.index('var RawHandlebars = ')...transpiled.index('export ')]
|
||||
|
||||
@precompiler = StringIO.new <<~END
|
||||
@precompiler = StringIO.new <<~JS
|
||||
var __RawHandlebars;
|
||||
(function() {
|
||||
#{transpiled};
|
||||
|
@ -30,7 +30,7 @@ class Barber::Precompiler
|
|||
return __RawHandlebars.precompile(string, false).toString();
|
||||
}
|
||||
};
|
||||
END
|
||||
JS
|
||||
end
|
||||
|
||||
@precompiler
|
||||
|
@ -111,10 +111,10 @@ class Ember::Handlebars::Template
|
|||
"define('#{module_name}', ['exports'], function(__exports__){ __exports__['default'] = #{template} });"
|
||||
when :global
|
||||
if raw
|
||||
return <<~RAW_TEMPLATE
|
||||
return <<~JS
|
||||
var __t = #{template};
|
||||
requirejs('discourse-common/lib/raw-templates').addRawTemplate(#{path_for(template_name, config)}, __t);
|
||||
RAW_TEMPLATE
|
||||
JS
|
||||
end
|
||||
|
||||
target = global_template_target('Ember.TEMPLATES', template_name, config)
|
||||
|
|
|
@ -121,7 +121,7 @@ class Migration::SafeMigrate
|
|||
|
||||
def self.protect!(sql)
|
||||
if sql =~ /^\s*(?:drop\s+table|alter\s+table.*rename\s+to)\s+/i
|
||||
$stdout.puts("", <<~STR)
|
||||
$stdout.puts("", <<~TEXT)
|
||||
WARNING
|
||||
-------------------------------------------------------------------------------------
|
||||
An attempt was made to drop or rename a table in a migration
|
||||
|
@ -131,10 +131,10 @@ class Migration::SafeMigrate
|
|||
|
||||
This protection is in place to protect us against dropping tables that are currently
|
||||
in use by live applications.
|
||||
STR
|
||||
TEXT
|
||||
raise Discourse::InvalidMigration, "Attempt was made to drop a table"
|
||||
elsif sql =~ /^\s*alter\s+table.*(?:rename|drop)\s+/i
|
||||
$stdout.puts("", <<~STR)
|
||||
$stdout.puts("", <<~TEXT)
|
||||
WARNING
|
||||
-------------------------------------------------------------------------------------
|
||||
An attempt was made to drop or rename a column in a migration
|
||||
|
@ -148,7 +148,7 @@ class Migration::SafeMigrate
|
|||
|
||||
This protection is in place to protect us against dropping columns that are currently
|
||||
in use by live applications.
|
||||
STR
|
||||
TEXT
|
||||
raise Discourse::InvalidMigration, "Attempt was made to rename or delete column"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -218,14 +218,14 @@ module Onebox
|
|||
def card_html
|
||||
escaped_url = ::Onebox::Helpers.normalize_url_for_output(data[:player])
|
||||
|
||||
<<~RAW
|
||||
<<~HTML
|
||||
<iframe src="#{escaped_url}"
|
||||
width="#{data[:player_width] || "100%"}"
|
||||
height="#{data[:player_height]}"
|
||||
scrolling="no"
|
||||
frameborder="0">
|
||||
</iframe>
|
||||
RAW
|
||||
HTML
|
||||
end
|
||||
|
||||
def article_html
|
||||
|
|
|
@ -24,7 +24,7 @@ def plugin_initialization_guard(&block)
|
|||
end
|
||||
end.reverse.join("\n")
|
||||
|
||||
STDERR.puts <<~MESSAGE
|
||||
STDERR.puts <<~TEXT
|
||||
#{stack_trace}
|
||||
|
||||
** INCOMPATIBLE PLUGIN **
|
||||
|
@ -33,9 +33,9 @@ def plugin_initialization_guard(&block)
|
|||
#{plugin_path}
|
||||
|
||||
Please try removing this plugin and rebuilding again!
|
||||
MESSAGE
|
||||
TEXT
|
||||
else
|
||||
STDERR.puts <<~MESSAGE
|
||||
STDERR.puts <<~TEXT
|
||||
** PLUGIN FAILURE **
|
||||
|
||||
You are unable to build Discourse due to this error during plugin
|
||||
|
@ -44,7 +44,7 @@ def plugin_initialization_guard(&block)
|
|||
#{error}
|
||||
|
||||
#{error.backtrace.join("\n")}
|
||||
MESSAGE
|
||||
TEXT
|
||||
end
|
||||
exit 1
|
||||
end
|
||||
|
|
|
@ -34,23 +34,23 @@ module Stylesheet
|
|||
contents = +""
|
||||
|
||||
if body_font.present?
|
||||
contents << <<~EOF
|
||||
contents << <<~CSS
|
||||
#{font_css(body_font)}
|
||||
|
||||
:root {
|
||||
--font-family: #{body_font[:stack]};
|
||||
}
|
||||
EOF
|
||||
CSS
|
||||
end
|
||||
|
||||
if heading_font.present?
|
||||
contents << <<~EOF
|
||||
contents << <<~CSS
|
||||
#{font_css(heading_font)}
|
||||
|
||||
:root {
|
||||
--heading-font-family: #{heading_font[:stack]};
|
||||
}
|
||||
EOF
|
||||
CSS
|
||||
end
|
||||
|
||||
contents
|
||||
|
@ -70,14 +70,14 @@ module Stylesheet
|
|||
end
|
||||
|
||||
contents << font_css(font)
|
||||
contents << <<~EOF
|
||||
contents << <<~CSS
|
||||
.body-font-#{font[:key].tr("_", "-")} {
|
||||
font-family: #{font[:stack]};
|
||||
}
|
||||
.heading-font-#{font[:key].tr("_", "-")} h2 {
|
||||
font-family: #{font[:stack]};
|
||||
}
|
||||
EOF
|
||||
CSS
|
||||
end
|
||||
|
||||
contents
|
||||
|
@ -184,11 +184,11 @@ module Stylesheet
|
|||
fields.map do |field|
|
||||
value = field.value
|
||||
if value.present?
|
||||
contents << <<~COMMENT
|
||||
contents << <<~SCSS
|
||||
// Theme: #{field.theme.name}
|
||||
// Target: #{field.target_name} #{field.name}
|
||||
// Last Edited: #{field.updated_at}
|
||||
COMMENT
|
||||
SCSS
|
||||
|
||||
contents << value
|
||||
end
|
||||
|
@ -216,13 +216,13 @@ module Stylesheet
|
|||
fonts_dir = UrlHelper.absolute("#{Discourse.base_path}/fonts")
|
||||
font[:variants].each do |variant|
|
||||
src = variant[:src] ? variant[:src] : "url(\"#{fonts_dir}/#{variant[:filename]}?v=#{DiscourseFonts::VERSION}\") format(\"#{variant[:format]}\")"
|
||||
contents << <<~EOF
|
||||
contents << <<~CSS
|
||||
@font-face {
|
||||
font-family: #{font[:name]};
|
||||
src: #{src};
|
||||
font-weight: #{variant[:weight]};
|
||||
}
|
||||
EOF
|
||||
CSS
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -15,10 +15,10 @@ task 'assets:precompile:before' do
|
|||
|
||||
if EMBER_CLI && !(ENV["EMBER_CLI_COMPILE_DONE"] == "1")
|
||||
# Using exec to free up Rails app memory during ember build
|
||||
exec <<~SCRIPT
|
||||
exec <<~SH
|
||||
NODE_OPTIONS='--max-old-space-size=2048' yarn --cwd app/assets/javascripts/discourse run ember build -prod && \
|
||||
EMBER_CLI_COMPILE_DONE=1 bin/rake assets:precompile
|
||||
SCRIPT
|
||||
SH
|
||||
end
|
||||
|
||||
# Ensure we ALWAYS do a clean build
|
||||
|
@ -124,9 +124,9 @@ def compress_node(from, to)
|
|||
source_map_url = "#{File.basename(to)}.map"
|
||||
base_source_map = assets_path + assets_additional_path
|
||||
|
||||
cmd = <<~EOS
|
||||
cmd = <<~SH
|
||||
terser '#{assets_path}/#{from}' -m -c -o '#{to_path}' --source-map "base='#{base_source_map}',root='#{source_map_root}',url='#{source_map_url}',includeSources=true"
|
||||
EOS
|
||||
SH
|
||||
|
||||
STDERR.puts cmd
|
||||
result = `#{cmd} 2>&1`
|
||||
|
|
|
@ -65,7 +65,7 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
smtp = Discourse::Application.config.action_mailer.smtp_settings
|
||||
|
||||
if smtp[:address].match(/smtp\.gmail\.com/)
|
||||
puts <<~STR
|
||||
puts <<~TEXT
|
||||
#{smtp}
|
||||
============================== WARNING ==============================
|
||||
|
||||
|
@ -75,7 +75,7 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
https://meta.discourse.org/t/discourse-aws-ec2-g-suite-troubleshooting/62931?u=pfaffman
|
||||
|
||||
========================= CONTINUING TEST ============================
|
||||
STR
|
||||
TEXT
|
||||
end
|
||||
|
||||
puts "Testing sending to #{email} using #{smtp[:address]}:#{smtp[:port]}, username:#{smtp[:user_name]} with #{smtp[:authentication]} auth."
|
||||
|
@ -93,21 +93,21 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
rescue Exception => e
|
||||
|
||||
if e.to_s.match(/execution expired/)
|
||||
message = <<~STR
|
||||
message = <<~TEXT
|
||||
======================================== ERROR ========================================
|
||||
Connection to port #{smtp[:port]} failed.
|
||||
====================================== SOLUTION =======================================
|
||||
The most likely problem is that your server has outgoing SMTP traffic blocked.
|
||||
If you are using a service like Mailgun or Sendgrid, try using port 2525.
|
||||
=======================================================================================
|
||||
STR
|
||||
TEXT
|
||||
|
||||
elsif e.to_s.match(/530.*STARTTLS/)
|
||||
# We can't run a preliminary test with STARTTLS, we'll just try sending the test email.
|
||||
message = "OK"
|
||||
|
||||
elsif e.to_s.match(/535/)
|
||||
message = <<~STR
|
||||
message = <<~TEXT
|
||||
======================================== ERROR ========================================
|
||||
AUTHENTICATION FAILED
|
||||
|
||||
|
@ -117,10 +117,10 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
The most likely problem is that your SMTP username and/or Password is incorrect.
|
||||
Check them and try again.
|
||||
=======================================================================================
|
||||
STR
|
||||
TEXT
|
||||
|
||||
elsif e.to_s.match(/Connection refused/)
|
||||
message = <<~STR
|
||||
message = <<~TEXT
|
||||
======================================== ERROR ========================================
|
||||
CONNECTION REFUSED
|
||||
|
||||
|
@ -132,10 +132,10 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
|
||||
Check the port and your networking configuration.
|
||||
=======================================================================================
|
||||
STR
|
||||
TEXT
|
||||
|
||||
elsif e.to_s.match(/service not known/)
|
||||
message = <<~STR
|
||||
message = <<~TEXT
|
||||
======================================== ERROR ========================================
|
||||
SMTP SERVER NOT FOUND
|
||||
|
||||
|
@ -145,10 +145,10 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
The most likely problem is that the host name of your SMTP server is incorrect.
|
||||
Check it and try again.
|
||||
=======================================================================================
|
||||
STR
|
||||
TEXT
|
||||
|
||||
else
|
||||
message = <<~STR
|
||||
message = <<~TEXT
|
||||
======================================== ERROR ========================================
|
||||
UNEXPECTED ERROR
|
||||
|
||||
|
@ -160,7 +160,7 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
Please report the exact error message above to https://meta.discourse.org/
|
||||
(And a solution, if you find one!)
|
||||
=======================================================================================
|
||||
STR
|
||||
TEXT
|
||||
end
|
||||
end
|
||||
if message == "OK"
|
||||
|
@ -174,13 +174,13 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
email_log = Email::Sender.new(TestMailer.send_test(email), :test_message).send
|
||||
case email_log
|
||||
when SkippedEmailLog
|
||||
puts <<~STR
|
||||
puts <<~TEXT
|
||||
Mail was not sent.
|
||||
|
||||
Reason: #{email_log.reason}
|
||||
STR
|
||||
TEXT
|
||||
when EmailLog
|
||||
puts <<~STR
|
||||
puts <<~TEXT
|
||||
Mail accepted by SMTP server.
|
||||
Message-ID: #{email_log.message_id}
|
||||
|
||||
|
@ -190,20 +190,20 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
If the message is not delivered it is not a problem with Discourse.
|
||||
Check the SMTP server logs for the above Message ID to see why it
|
||||
failed to deliver the message.
|
||||
STR
|
||||
TEXT
|
||||
when nil
|
||||
puts <<~STR
|
||||
puts <<~TEXT
|
||||
Mail was not sent.
|
||||
|
||||
Verify the status of the `disable_emails` site setting.
|
||||
STR
|
||||
TEXT
|
||||
else
|
||||
puts <<~STR
|
||||
puts <<~TEXT
|
||||
SCRIPT BUG: Got back a #{email_log.class}
|
||||
#{email_log.inspect}
|
||||
|
||||
Mail may or may not have been sent. Check the destination mailbox.
|
||||
STR
|
||||
TEXT
|
||||
end
|
||||
rescue => error
|
||||
puts "Sending mail failed."
|
||||
|
@ -211,11 +211,11 @@ task 'emails:test', [:email] => [:environment] do |_, args|
|
|||
end
|
||||
|
||||
if SiteSetting.disable_emails != 'no'
|
||||
puts <<~STR
|
||||
puts <<~TEXT
|
||||
|
||||
### WARNING
|
||||
The `disable_emails` site setting is currently set to #{SiteSetting.disable_emails}.
|
||||
Consider changing it to 'no' before performing any further troubleshooting.
|
||||
STR
|
||||
TEXT
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ def html_for_section(group)
|
|||
" {{replace-emoji \":#{icon['name']}:\" (hash lazy=true#{class_attr})}}"
|
||||
end
|
||||
|
||||
<<~SECTION
|
||||
<<~HTML
|
||||
<div class="section" data-section="#{group["name"]}">
|
||||
<div class="section-header">
|
||||
<span class="title">{{i18n "emoji_picker.#{group["name"]}"}}</span>
|
||||
|
@ -31,14 +31,14 @@ def html_for_section(group)
|
|||
#{icons.join("\n").strip}
|
||||
</div>
|
||||
</div>
|
||||
SECTION
|
||||
HTML
|
||||
end
|
||||
|
||||
def write_template(path, task_name, template)
|
||||
header = <<~HEADER
|
||||
header = <<~JS
|
||||
// DO NOT EDIT THIS FILE!!!
|
||||
// Update it by running `rake javascript:#{task_name}`
|
||||
HEADER
|
||||
JS
|
||||
|
||||
basename = File.basename(path)
|
||||
output_path = "#{Rails.root}/app/assets/javascripts/#{path}"
|
||||
|
@ -50,10 +50,10 @@ def write_template(path, task_name, template)
|
|||
end
|
||||
|
||||
def write_hbs_template(path, task_name, template)
|
||||
header = <<~HEADER
|
||||
header = <<~HBS
|
||||
{{!-- DO NOT EDIT THIS FILE!!! --}}
|
||||
{{!-- Update it by running `rake javascript:#{task_name}` --}}
|
||||
HEADER
|
||||
HBS
|
||||
|
||||
basename = File.basename(path)
|
||||
output_path = "#{Rails.root}/app/assets/javascripts/#{path}"
|
||||
|
@ -244,11 +244,11 @@ task 'javascript:update_constants' => :environment do
|
|||
groups_json = JSON.parse(File.read("lib/emoji/groups.json"))
|
||||
|
||||
emoji_buttons = groups_json.map do |group|
|
||||
<<~BUTTON
|
||||
<<~HTML
|
||||
<button type="button" data-section="#{group["name"]}" {{action onCategorySelection "#{group["name"]}"}} class="btn btn-default category-button emoji">
|
||||
{{replace-emoji ":#{group["tabicon"]}:"}}
|
||||
</button>
|
||||
BUTTON
|
||||
HTML
|
||||
end
|
||||
|
||||
emoji_sections = groups_json.map { |group| html_for_section(group) }
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Generates posts and topics
|
||||
class Populate < Thor
|
||||
desc "posts", "Generate posts"
|
||||
long_desc <<-LONGDESC
|
||||
long_desc <<-MD
|
||||
Create topics with any number of posts, or add posts to an existing topic.
|
||||
|
||||
Examples:
|
||||
|
@ -20,7 +20,7 @@ class Populate < Thor
|
|||
|
||||
> $ thor populate:posts -p 10 -n 5
|
||||
|
||||
LONGDESC
|
||||
MD
|
||||
method_option :num_posts, aliases: '-n', type: :numeric, required: true, desc: "Number of posts to make"
|
||||
method_option :users, aliases: '-u', type: :array, desc: "Usernames of users who will make the posts"
|
||||
method_option :title, aliases: '-t', desc: "The title of the topic, if making a new topic"
|
||||
|
|
|
@ -118,7 +118,7 @@ task "themes:qunit", :type, :value do |t, args|
|
|||
type = args[:type]
|
||||
value = args[:value]
|
||||
if !%w(name url id).include?(type) || value.blank?
|
||||
raise <<~MSG
|
||||
raise <<~TEXT
|
||||
Wrong arguments type:#{type.inspect}, value:#{value.inspect}"
|
||||
Usage:
|
||||
`bundle exec rake "themes:qunit[url,<theme_url>]"`
|
||||
|
@ -126,7 +126,7 @@ task "themes:qunit", :type, :value do |t, args|
|
|||
`bundle exec rake "themes:qunit[name,<theme_name>]"`
|
||||
OR
|
||||
`bundle exec rake "themes:qunit[id,<theme_id>]"`
|
||||
MSG
|
||||
TEXT
|
||||
end
|
||||
ENV["THEME_#{type.upcase}"] = value.to_s
|
||||
ENV["QUNIT_RAILS_ENV"] ||= 'development' # qunit:test will switch to `test` by default
|
||||
|
|
|
@ -165,11 +165,11 @@ def clean_up_uploads
|
|||
exit 1
|
||||
end
|
||||
|
||||
puts <<~OUTPUT
|
||||
puts <<~TEXT
|
||||
This task will remove upload records and files permanently.
|
||||
|
||||
Would you like to take a full backup before the clean up? (Y/N)
|
||||
OUTPUT
|
||||
TEXT
|
||||
|
||||
if STDIN.gets.chomp.downcase == 'y'
|
||||
puts "Starting backup..."
|
||||
|
@ -420,7 +420,7 @@ task "uploads:analyze", [:cache_path, :limit] => :environment do |_, args|
|
|||
uploads_count = Upload.count
|
||||
optimized_images_count = OptimizedImage.count
|
||||
|
||||
puts <<~REPORT
|
||||
puts <<~TEXT
|
||||
Report for '#{current_db}'
|
||||
-----------#{'-' * current_db.length}
|
||||
Number of `Upload` records in DB: #{uploads_count}
|
||||
|
@ -430,7 +430,7 @@ task "uploads:analyze", [:cache_path, :limit] => :environment do |_, args|
|
|||
Number of images in uploads folder: #{paths_count}
|
||||
------------------------------------#{'-' * paths_count.to_s.length}
|
||||
|
||||
REPORT
|
||||
TEXT
|
||||
|
||||
helper = Class.new do
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
|
|
@ -28,13 +28,13 @@ describe PrettyText do
|
|||
end
|
||||
|
||||
it 'can replace spoilers in emails' do
|
||||
md = PrettyText.cook(<<~EOF)
|
||||
md = PrettyText.cook(<<~MD)
|
||||
hello
|
||||
|
||||
[details="Summary"]
|
||||
world
|
||||
[/details]
|
||||
EOF
|
||||
MD
|
||||
md = PrettyText.format_for_email(md, post)
|
||||
html = "<p>hello</p>\n\nSummary <a href=\"#{post.full_url}\">(click for more details)</a>"
|
||||
|
||||
|
@ -42,7 +42,7 @@ describe PrettyText do
|
|||
end
|
||||
|
||||
it 'properly handles multiple spoiler blocks in a post' do
|
||||
md = PrettyText.cook(<<~EOF)
|
||||
md = PrettyText.cook(<<~MD)
|
||||
[details="First"]
|
||||
body secret stuff very long
|
||||
[/details]
|
||||
|
@ -55,7 +55,7 @@ describe PrettyText do
|
|||
[details="Third"]
|
||||
body secret stuff very long
|
||||
[/details]
|
||||
EOF
|
||||
MD
|
||||
|
||||
md = PrettyText.format_for_email(md, post)
|
||||
expect(md).not_to include('secret stuff')
|
||||
|
@ -65,12 +65,12 @@ describe PrettyText do
|
|||
end
|
||||
|
||||
it 'escapes summary text' do
|
||||
md = PrettyText.cook(<<~EOF)
|
||||
md = PrettyText.cook(<<~MD)
|
||||
<script>alert('hello')</script>
|
||||
[details="<script>alert('hello')</script>"]
|
||||
<script>alert('hello')</script>
|
||||
[/details]
|
||||
EOF
|
||||
MD
|
||||
md = PrettyText.format_for_email(md, post)
|
||||
|
||||
expect(md).not_to include('<script>')
|
||||
|
|
|
@ -8,9 +8,9 @@ RSpec.describe "Local Dates" do
|
|||
end
|
||||
|
||||
it "should work without timezone" do
|
||||
post = Fabricate(:post, raw: <<~TXT)
|
||||
post = Fabricate(:post, raw: <<~MD)
|
||||
[date=2018-05-08 time=22:00 format="L LTS" timezones="Europe/Paris|America/Los_Angeles"]
|
||||
TXT
|
||||
MD
|
||||
|
||||
cooked = post.cooked
|
||||
|
||||
|
@ -28,9 +28,9 @@ RSpec.describe "Local Dates" do
|
|||
end
|
||||
|
||||
it "should work with timezone" do
|
||||
post = Fabricate(:post, raw: <<~TXT)
|
||||
post = Fabricate(:post, raw: <<~MD)
|
||||
[date=2018-05-08 time=22:00 format="L LTS" timezone="Asia/Calcutta" timezones="Europe/Paris|America/Los_Angeles"]
|
||||
TXT
|
||||
MD
|
||||
|
||||
cooked = post.cooked
|
||||
|
||||
|
@ -39,9 +39,9 @@ RSpec.describe "Local Dates" do
|
|||
end
|
||||
|
||||
it 'requires the right attributes to convert to a local date' do
|
||||
post = Fabricate(:post, raw: <<~TXT)
|
||||
post = Fabricate(:post, raw: <<~MD)
|
||||
[date]
|
||||
TXT
|
||||
MD
|
||||
|
||||
cooked = post.cooked
|
||||
|
||||
|
@ -50,9 +50,9 @@ RSpec.describe "Local Dates" do
|
|||
end
|
||||
|
||||
it 'requires the right attributes to convert to a local date' do
|
||||
post = Fabricate(:post, raw: <<~TXT)
|
||||
post = Fabricate(:post, raw: <<~MD)
|
||||
[date]
|
||||
TXT
|
||||
MD
|
||||
|
||||
cooked = post.cooked
|
||||
|
||||
|
|
|
@ -163,11 +163,11 @@ module DiscourseNarrativeBot
|
|||
def start_advanced_track
|
||||
raw = I18n.t("#{I18N_KEY}.start_message", i18n_post_args(username: @user.username))
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{raw}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
opts = {
|
||||
title: I18n.t("#{I18N_KEY}.title"),
|
||||
|
@ -197,11 +197,11 @@ module DiscourseNarrativeBot
|
|||
|
||||
fake_delay
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.edit.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
reply_to(@post, raw)
|
||||
end
|
||||
|
@ -227,11 +227,11 @@ module DiscourseNarrativeBot
|
|||
|
||||
fake_delay
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.delete.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
PostCreator.create!(self.discobot_user,
|
||||
raw: raw,
|
||||
|
@ -252,11 +252,11 @@ module DiscourseNarrativeBot
|
|||
|
||||
fake_delay
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.recover.reply", i18n_post_args(deletion_after: SiteSetting.delete_removed_posts_after))}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
PostCreator.create!(self.discobot_user,
|
||||
raw: raw,
|
||||
|
@ -279,11 +279,11 @@ module DiscourseNarrativeBot
|
|||
return unless valid_topic?(topic_id)
|
||||
|
||||
if Nokogiri::HTML5.fragment(@post.cooked).css('.hashtag').size > 0
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.category_hashtag.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
reply_to(@post, raw)
|
||||
|
@ -308,11 +308,11 @@ module DiscourseNarrativeBot
|
|||
return unless valid_topic?(@topic_id)
|
||||
|
||||
fake_delay
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.change_topic_notification_level.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -330,11 +330,11 @@ module DiscourseNarrativeBot
|
|||
return unless valid_topic?(topic_id)
|
||||
|
||||
if Nokogiri::HTML5.fragment(@post.cooked).css(".poll").size > 0
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.poll.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
reply_to(@post, raw)
|
||||
|
|
|
@ -175,11 +175,11 @@ module DiscourseNarrativeBot
|
|||
|
||||
MessageBus.publish('/new_user_narrative/tutorial_search', {}, user_ids: [@user.id])
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{post.raw}
|
||||
|
||||
#{I18n.t("#{I18N_KEY}.search.hidden_message", i18n_post_args.merge(search_answer: NewUserNarrative.search_answer))}
|
||||
RAW
|
||||
MD
|
||||
|
||||
PostRevisor.new(post, topic).revise!(
|
||||
self.discobot_user,
|
||||
|
@ -206,11 +206,11 @@ module DiscourseNarrativeBot
|
|||
)
|
||||
)
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{raw}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
title = I18n.t("#{I18N_KEY}.hello.title", title: SiteSetting.title)
|
||||
if SiteSetting.max_emojis_in_title == 0
|
||||
|
@ -259,11 +259,11 @@ module DiscourseNarrativeBot
|
|||
|
||||
profile_page_url = url_helpers(:user_url, username: @user.username)
|
||||
bookmark_url = "#{profile_page_url}/activity/bookmarks"
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.bookmark.reply", i18n_post_args(bookmark_url: bookmark_url))}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -279,11 +279,11 @@ module DiscourseNarrativeBot
|
|||
@post.post_analyzer.cook(@post.raw, {})
|
||||
|
||||
if @post.post_analyzer.found_oneboxes?
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.onebox.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -315,11 +315,11 @@ module DiscourseNarrativeBot
|
|||
fake_delay
|
||||
like_post(post)
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.images.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
reply = reply_to(@post, raw)
|
||||
enqueue_timeout_job(@user)
|
||||
|
@ -350,11 +350,11 @@ module DiscourseNarrativeBot
|
|||
set_state_data(:post_id, @post.id)
|
||||
|
||||
if get_state_data(:liked)
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.images.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
like_post(@post)
|
||||
else
|
||||
|
@ -405,11 +405,11 @@ module DiscourseNarrativeBot
|
|||
)
|
||||
|
||||
if post_liked
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.likes.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -426,11 +426,11 @@ module DiscourseNarrativeBot
|
|||
return unless valid_topic?(post_topic_id)
|
||||
|
||||
if Nokogiri::HTML5.fragment(@post.cooked).css("b", "strong", "em", "i", ".bbcode-i", ".bbcode-b").size > 0
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.formatting.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -452,11 +452,11 @@ module DiscourseNarrativeBot
|
|||
doc = Nokogiri::HTML5.fragment(@post.cooked)
|
||||
|
||||
if doc.css(".quote").size > 0
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.quoting.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -478,11 +478,11 @@ module DiscourseNarrativeBot
|
|||
doc = Nokogiri::HTML5.fragment(@post.cooked)
|
||||
|
||||
if doc.css(".emoji").size > 0
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.emoji.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -502,11 +502,11 @@ module DiscourseNarrativeBot
|
|||
return unless valid_topic?(post_topic_id)
|
||||
|
||||
if bot_mentioned?(@post)
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.mention.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
@ -552,11 +552,11 @@ module DiscourseNarrativeBot
|
|||
return unless valid_topic?(post_topic_id)
|
||||
return unless @post.user.id == -2
|
||||
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
#{I18n.t("#{I18N_KEY}.flag.reply", i18n_post_args)}
|
||||
|
||||
#{instance_eval(&@next_instructions)}
|
||||
RAW
|
||||
MD
|
||||
|
||||
fake_delay
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class Onebox::Engine::YoutubeOnebox
|
|||
# Put in the LazyYT div instead of the iframe
|
||||
escaped_title = ERB::Util.html_escape(video_title)
|
||||
|
||||
<<~EOF
|
||||
<<~HTML
|
||||
<div class="onebox lazyYT lazyYT-container"
|
||||
data-youtube-id="#{video_id}"
|
||||
data-youtube-title="#{escaped_title}"
|
||||
|
@ -49,7 +49,7 @@ class Onebox::Engine::YoutubeOnebox
|
|||
title="#{escaped_title}">
|
||||
</a>
|
||||
</div>
|
||||
EOF
|
||||
HTML
|
||||
else
|
||||
yt_onebox_to_html
|
||||
end
|
||||
|
|
|
@ -39,12 +39,12 @@ describe NewPostManager do
|
|||
end
|
||||
|
||||
it 're-validates the poll when the approve_post event is triggered' do
|
||||
invalid_raw_poll = <<~RAW
|
||||
invalid_raw_poll = <<~MD
|
||||
[poll type=multiple min=0]
|
||||
* 1
|
||||
* 2
|
||||
[/poll]
|
||||
RAW
|
||||
MD
|
||||
|
||||
result = NewPostManager.new(user, params).perform
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
require "pg"
|
||||
|
||||
usage = <<-END
|
||||
usage = <<-TEXT
|
||||
Commands:
|
||||
ruby db_timestamp_updater.rb yesterday <date> move all timestamps by x days so that <date> will be moved to yesterday
|
||||
ruby db_timestamp_updater.rb 100 move all timestamps forward by 100 days
|
||||
ruby db_timestamp_updater.rb -100 move all timestamps backward by 100 days
|
||||
END
|
||||
TEXT
|
||||
|
||||
class TimestampsUpdater
|
||||
def initialize(schema, ignore_tables)
|
||||
|
|
|
@ -9,7 +9,7 @@ class DiscourseCLI < Thor
|
|||
end
|
||||
|
||||
desc "remap [--global,--regex] FROM TO", "Remap a string sequence across all tables"
|
||||
long_desc <<-LONGDESC
|
||||
long_desc <<-TEXT
|
||||
Replace a string sequence FROM with TO across all tables.
|
||||
|
||||
With --global option, the remapping is run on ***ALL***
|
||||
|
@ -30,7 +30,7 @@ class DiscourseCLI < Thor
|
|||
discourse remap talk.foo.com talk.bar.com # renaming a Discourse domain name
|
||||
|
||||
discourse remap --regex "\[\/?color(=[^\]]*)*]" "" # removing "color" bbcodes
|
||||
LONGDESC
|
||||
TEXT
|
||||
option :global, type: :boolean
|
||||
option :regex, type: :boolean
|
||||
def remap(from, to)
|
||||
|
|
|
@ -85,11 +85,11 @@ def crawl_topics
|
|||
|
||||
begin
|
||||
if start == 1 && find("h2").text == "Error 403"
|
||||
exit_with_error(<<~MSG.red.bold)
|
||||
exit_with_error(<<~TEXT.red.bold)
|
||||
Unable to find topics. Try running the script with the "--domain example.com"
|
||||
option if you are a G Suite user and your group's URL contains a path with
|
||||
your domain that looks like "/a/example.com".
|
||||
MSG
|
||||
TEXT
|
||||
end
|
||||
rescue Selenium::WebDriver::Error::NoSuchElementError
|
||||
# Ignore this error. It simply means there wasn't an error.
|
||||
|
@ -151,10 +151,10 @@ def crawl_message(url, might_be_deleted)
|
|||
@first_message_checked = true
|
||||
|
||||
if content.match?(/From:.*\.\.\.@.*/i) && !@force_import
|
||||
exit_with_error(<<~MSG.red.bold)
|
||||
exit_with_error(<<~TEXT.red.bold)
|
||||
It looks like you do not have permissions to see email addresses. Aborting.
|
||||
Use the --force option to import anyway.
|
||||
MSG
|
||||
TEXT
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -114,28 +114,28 @@ class ImportScripts::IpboardSQL < ImportScripts::Base
|
|||
rescue Exception => e
|
||||
puts '=' * 50
|
||||
puts e.message
|
||||
puts <<EOM
|
||||
Cannot log in to database.
|
||||
puts <<~TEXT
|
||||
Cannot log in to database.
|
||||
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
|
||||
You should set these variables:
|
||||
You should set these variables:
|
||||
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="ipboard"
|
||||
export DB_PW="ipboard"
|
||||
export DB_USER="ipboard"
|
||||
export TABLE_PREFIX="ipb_"
|
||||
export IMPORT_AFTER="1970-01-01"
|
||||
export URL="http://example.com"
|
||||
export UPLOADS=
|
||||
export USERDIR="user"
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="ipboard"
|
||||
export DB_PW="ipboard"
|
||||
export DB_USER="ipboard"
|
||||
export TABLE_PREFIX="ipb_"
|
||||
export IMPORT_AFTER="1970-01-01"
|
||||
export URL="http://example.com"
|
||||
export UPLOADS=
|
||||
export USERDIR="user"
|
||||
|
||||
Exiting.
|
||||
EOM
|
||||
Exiting.
|
||||
TEXT
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
|
|
@ -43,25 +43,25 @@ class ImportScripts::Modx < ImportScripts::Base
|
|||
rescue Exception => e
|
||||
puts '=' * 50
|
||||
puts e.message
|
||||
puts <<EOM
|
||||
Cannot connect in to database.
|
||||
puts <<~TEXT
|
||||
Cannot connect in to database.
|
||||
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
|
||||
Edit the script or set these environment variables:
|
||||
Edit the script or set these environment variables:
|
||||
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="modx"
|
||||
export DB_PW="modx"
|
||||
export DB_USER="modx"
|
||||
export TABLE_PREFIX="modx_"
|
||||
export ATTACHMENT_DIR '/path/to/your/attachment/folder'
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="modx"
|
||||
export DB_PW="modx"
|
||||
export DB_USER="modx"
|
||||
export TABLE_PREFIX="modx_"
|
||||
export ATTACHMENT_DIR '/path/to/your/attachment/folder'
|
||||
|
||||
Exiting.
|
||||
EOM
|
||||
Exiting.
|
||||
TEXT
|
||||
exit
|
||||
end
|
||||
|
||||
|
@ -446,12 +446,12 @@ FROM #{TABLE_PREFIX}discuss_users
|
|||
# keep track of closed topics
|
||||
closed_topic_ids = []
|
||||
|
||||
topics = mysql_query <<-MYSQL
|
||||
topics = mysql_query <<-SQL
|
||||
SELECT t.threadid threadid, firstpostid, open
|
||||
FROM #{TABLE_PREFIX}thread t
|
||||
JOIN #{TABLE_PREFIX}post p ON p.postid = t.firstpostid
|
||||
ORDER BY t.threadid
|
||||
MYSQL
|
||||
SQL
|
||||
topics.each do |topic|
|
||||
topic_id = "thread-#{topic["threadid"]}"
|
||||
closed_topic_ids << topic_id if topic["open"] == 0
|
||||
|
|
|
@ -58,27 +58,27 @@ class ImportScripts::MylittleforumSQL < ImportScripts::Base
|
|||
rescue Exception => e
|
||||
puts '=' * 50
|
||||
puts e.message
|
||||
puts <<EOM
|
||||
Cannot log in to database.
|
||||
puts <<~TEXT
|
||||
Cannot log in to database.
|
||||
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
|
||||
You should set these variables:
|
||||
You should set these variables:
|
||||
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="mylittleforum"
|
||||
export DB_PW=""
|
||||
export DB_USER="root"
|
||||
export TABLE_PREFIX="forum_"
|
||||
export IMPORT_AFTER="1970-01-01"
|
||||
export IMAGE_BASE="http://www.example.com/forum"
|
||||
export BASE="forum"
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="mylittleforum"
|
||||
export DB_PW=""
|
||||
export DB_USER="root"
|
||||
export TABLE_PREFIX="forum_"
|
||||
export IMPORT_AFTER="1970-01-01"
|
||||
export IMAGE_BASE="http://www.example.com/forum"
|
||||
export BASE="forum"
|
||||
|
||||
Exiting.
|
||||
EOM
|
||||
Exiting.
|
||||
TEXT
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,10 +26,10 @@ module ImportScripts::PhpBB3
|
|||
require_relative 'database_3_1'
|
||||
Database_3_1.new(@database_client, @database_settings)
|
||||
else
|
||||
raise UnsupportedVersionError, <<~MSG
|
||||
raise UnsupportedVersionError, <<~TEXT
|
||||
Unsupported version (#{version}) of phpBB detected.
|
||||
Currently only version 3.0, 3.1 and 3.2 are supported by this importer.
|
||||
MSG
|
||||
TEXT
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -53,25 +53,25 @@ class ImportScripts::VBulletin < ImportScripts::Base
|
|||
rescue Exception => e
|
||||
puts '=' * 50
|
||||
puts e.message
|
||||
puts <<EOM
|
||||
Cannot connect in to database.
|
||||
puts <<~TEXT
|
||||
Cannot connect in to database.
|
||||
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
Hostname: #{DB_HOST}
|
||||
Username: #{DB_USER}
|
||||
Password: #{DB_PW}
|
||||
database: #{DB_NAME}
|
||||
|
||||
Edit the script or set these environment variables:
|
||||
Edit the script or set these environment variables:
|
||||
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="vbulletin"
|
||||
export DB_PW=""
|
||||
export DB_USER="root"
|
||||
export TABLE_PREFIX="vb_"
|
||||
export ATTACHMENT_DIR '/path/to/your/attachment/folder'
|
||||
export DB_HOST="localhost"
|
||||
export DB_NAME="vbulletin"
|
||||
export DB_PW=""
|
||||
export DB_USER="root"
|
||||
export TABLE_PREFIX="vb_"
|
||||
export ATTACHMENT_DIR '/path/to/your/attachment/folder'
|
||||
|
||||
Exiting.
|
||||
EOM
|
||||
Exiting.
|
||||
TEXT
|
||||
exit
|
||||
end
|
||||
|
||||
|
@ -674,12 +674,12 @@ EOM
|
|||
# keep track of closed topics
|
||||
closed_topic_ids = []
|
||||
|
||||
topics = mysql_query <<-MYSQL
|
||||
topics = mysql_query <<-SQL
|
||||
SELECT t.threadid threadid, firstpostid, open
|
||||
FROM #{TABLE_PREFIX}thread t
|
||||
JOIN #{TABLE_PREFIX}post p ON p.postid = t.firstpostid
|
||||
ORDER BY t.threadid
|
||||
MYSQL
|
||||
SQL
|
||||
topics.each do |topic|
|
||||
topic_id = "thread-#{topic["threadid"]}"
|
||||
closed_topic_ids << topic_id if topic["open"] == 0
|
||||
|
|
|
@ -100,9 +100,9 @@ end
|
|||
puts 'Done! File moves are staged and ready for commit.'
|
||||
puts 'Suggested commit message:'
|
||||
puts '-' * 20
|
||||
puts <<~MESSAGE
|
||||
puts <<~TEXT
|
||||
DEV: Promote historic post_deploy migrations
|
||||
|
||||
This commit promotes all post_deploy migrations which existed in Discourse #{previous_stable_version} (timestamp <= #{promote_threshold})
|
||||
MESSAGE
|
||||
TEXT
|
||||
puts '-' * 20
|
||||
|
|
|
@ -8,7 +8,7 @@ Fabricator(:incoming_email) do
|
|||
imap_sync false
|
||||
created_via 0
|
||||
|
||||
raw <<~RAW
|
||||
raw <<~EMAIL
|
||||
Return-Path: <foo@example.com>
|
||||
From: Foo <foo@example.com>
|
||||
To: someone@else.com
|
||||
|
@ -20,5 +20,5 @@ Fabricator(:incoming_email) do
|
|||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
The body contains "Hello world" too.
|
||||
RAW
|
||||
EMAIL
|
||||
end
|
||||
|
|
|
@ -102,20 +102,20 @@ Fabricator(:post_with_uploads, from: :post) do
|
|||
end
|
||||
|
||||
Fabricator(:post_with_uploads_and_links, from: :post) do
|
||||
raw <<~RAW
|
||||
raw <<~MD
|
||||
<a href="/#{Discourse.store.upload_path}/original/2X/2345678901234567.jpg">Link</a>
|
||||
<img src="/#{Discourse.store.upload_path}/original/1X/1234567890123456.jpg">
|
||||
<a href="http://www.google.com">Google</a>
|
||||
<img src="http://foo.bar/image.png">
|
||||
<a class="attachment" href="/#{Discourse.store.upload_path}/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)
|
||||
:smile:
|
||||
RAW
|
||||
MD
|
||||
end
|
||||
|
||||
Fabricator(:post_with_external_links, from: :post) do
|
||||
user
|
||||
topic
|
||||
raw <<~RAW
|
||||
raw <<~MD
|
||||
Here's a link to twitter: http://twitter.com
|
||||
And a link to google: http://google.com
|
||||
And a secure link to google: https://google.com
|
||||
|
@ -123,7 +123,7 @@ Fabricator(:post_with_external_links, from: :post) do
|
|||
And a markdown link with a period after it [codinghorror](http://www.codinghorror.com/blog).
|
||||
And one with a hash http://discourse.org#faq
|
||||
And one with a two hash http://discourse.org#a#b
|
||||
RAW
|
||||
MD
|
||||
end
|
||||
|
||||
Fabricator(:private_message_post, from: :post) do
|
||||
|
|
|
@ -25,13 +25,13 @@ describe 'Coding style' do
|
|||
js_files = list_js_files('app/assets/javascripts')
|
||||
offenses = grep_files(js_files, /this\.get\("\w+"\)/)
|
||||
|
||||
expect(offenses).to be_empty, <<~MSG
|
||||
expect(offenses).to be_empty, <<~TEXT
|
||||
Do not use this.get("foo") accessor for single property, instead
|
||||
prefer to use this.foo
|
||||
|
||||
Offenses:
|
||||
#{offenses.join("\n")}
|
||||
MSG
|
||||
TEXT
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -41,7 +41,7 @@ describe 'Coding style' do
|
|||
constant_name_regex = /#{Regexp.escape(constant_name)}/
|
||||
offenses = files.reject { |file| is_valid?(file, method_name_regex, constant_name_regex) }
|
||||
|
||||
expect(offenses).to be_empty, <<~MSG
|
||||
expect(offenses).to be_empty, <<~TEXT
|
||||
You need to use the constant #{constant_name} when you use
|
||||
#{method_name} in order to help with restoring backups.
|
||||
|
||||
|
@ -49,7 +49,7 @@ describe 'Coding style' do
|
|||
|
||||
Offenses:
|
||||
#{offenses.join("\n")}
|
||||
MSG
|
||||
TEXT
|
||||
end
|
||||
|
||||
def is_valid?(file, method_name_regex, constant_name_regex)
|
||||
|
|
|
@ -25,36 +25,36 @@ describe Jobs::OldKeysReminder do
|
|||
expect(post.archetype).to eq(Archetype.private_message)
|
||||
expect(post.topic.topic_allowed_users.map(&:user_id).sort).to eq([Discourse.system_user.id, admin.id, another_admin.id].sort)
|
||||
expect(post.topic.title).to eq('Reminder about old credentials')
|
||||
expect(post.raw).to eq(<<-MSG.rstrip)
|
||||
Hello! This is a routine yearly security reminder from your Discourse instance.
|
||||
expect(post.raw).to eq(<<~TEXT.rstrip)
|
||||
Hello! This is a routine yearly security reminder from your Discourse instance.
|
||||
|
||||
As a courtesy, we wanted to let you know that the following credentials used on your Discourse instance have not been updated in more than two years:
|
||||
As a courtesy, we wanted to let you know that the following credentials used on your Discourse instance have not been updated in more than two years:
|
||||
|
||||
google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_s(:db)}
|
||||
github_client_secret - #{github_secret.updated_at.to_date.to_s(:db)}
|
||||
api key description - #{api_key.created_at.to_date.to_s(:db)}
|
||||
google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_s(:db)}
|
||||
github_client_secret - #{github_secret.updated_at.to_date.to_s(:db)}
|
||||
api key description - #{api_key.created_at.to_date.to_s(:db)}
|
||||
|
||||
No action is required at this time, however, it is considered good security practice to cycle all your important credentials every few years.
|
||||
MSG
|
||||
No action is required at this time, however, it is considered good security practice to cycle all your important credentials every few years.
|
||||
TEXT
|
||||
|
||||
post.topic.destroy
|
||||
freeze_time 4.years.from_now
|
||||
described_class.new.execute({})
|
||||
post = Post.last
|
||||
expect(post.topic.title).to eq('Reminder about old credentials')
|
||||
expect(post.raw).to eq(<<-MSG.rstrip)
|
||||
Hello! This is a routine yearly security reminder from your Discourse instance.
|
||||
expect(post.raw).to eq(<<~TEXT.rstrip)
|
||||
Hello! This is a routine yearly security reminder from your Discourse instance.
|
||||
|
||||
As a courtesy, we wanted to let you know that the following credentials used on your Discourse instance have not been updated in more than two years:
|
||||
As a courtesy, we wanted to let you know that the following credentials used on your Discourse instance have not been updated in more than two years:
|
||||
|
||||
google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_s(:db)}
|
||||
github_client_secret - #{github_secret.updated_at.to_date.to_s(:db)}
|
||||
twitter_consumer_secret - #{recent_twitter_secret.updated_at.to_date.to_s(:db)}
|
||||
api key description - #{api_key.created_at.to_date.to_s(:db)}
|
||||
recent api key description - #{admin.username} - #{recent_api_key.created_at.to_date.to_s(:db)}
|
||||
google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_s(:db)}
|
||||
github_client_secret - #{github_secret.updated_at.to_date.to_s(:db)}
|
||||
twitter_consumer_secret - #{recent_twitter_secret.updated_at.to_date.to_s(:db)}
|
||||
api key description - #{api_key.created_at.to_date.to_s(:db)}
|
||||
recent api key description - #{admin.username} - #{recent_api_key.created_at.to_date.to_s(:db)}
|
||||
|
||||
No action is required at this time, however, it is considered good security practice to cycle all your important credentials every few years.
|
||||
MSG
|
||||
No action is required at this time, however, it is considered good security practice to cycle all your important credentials every few years.
|
||||
TEXT
|
||||
end
|
||||
|
||||
it 'does not send message when send_old_credential_reminder_days is set to 0 or no old keys' do
|
||||
|
|
|
@ -122,12 +122,12 @@ describe Jobs::PullHotlinkedImages do
|
|||
stub_request(:get, "http://test.localhost/uploads/short-url/z2QSs1KJWoj51uYhDjb6ifCzxH6.gif")
|
||||
.to_return(status: 200, body: "")
|
||||
|
||||
post = Fabricate(:post, raw: <<~RAW)
|
||||
post = Fabricate(:post, raw: <<~MD)
|
||||
<h1></h1>
|
||||
<a href="https://somelink.com">
|
||||
<img alt="somelink" src="#{image_url}" />
|
||||
</a>
|
||||
RAW
|
||||
MD
|
||||
|
||||
expect do
|
||||
Jobs::PullHotlinkedImages.new.execute(post_id: post.id)
|
||||
|
@ -135,12 +135,12 @@ describe Jobs::PullHotlinkedImages do
|
|||
|
||||
upload = post.uploads.last
|
||||
|
||||
expect(post.reload.raw).to eq(<<~RAW.chomp)
|
||||
expect(post.reload.raw).to eq(<<~MD.chomp)
|
||||
<h1></h1>
|
||||
<a href="https://somelink.com">
|
||||
![somelink](#{upload.short_url})
|
||||
</a>
|
||||
RAW
|
||||
MD
|
||||
end
|
||||
|
||||
it 'replaces correct image URL' do
|
||||
|
@ -371,12 +371,12 @@ describe Jobs::PullHotlinkedImages do
|
|||
end
|
||||
|
||||
it 'all combinations' do
|
||||
post = Fabricate(:post, raw: <<~BODY)
|
||||
post = Fabricate(:post, raw: <<~MD)
|
||||
<img src='#{image_url}'>
|
||||
#{url}
|
||||
<img src='#{broken_image_url}'>
|
||||
<a href='#{url}'><img src='#{large_image_url}'></a>
|
||||
BODY
|
||||
MD
|
||||
stub_image_size
|
||||
|
||||
2.times do
|
||||
|
|
|
@ -327,13 +327,13 @@ describe ContentSecurityPolicy do
|
|||
it 'is extended automatically when themes reference external scripts' do
|
||||
policy # call this first to make sure further actions clear the cache
|
||||
|
||||
theme.set_field(target: :common, name: "header", value: <<~SCRIPT)
|
||||
theme.set_field(target: :common, name: "header", value: <<~HTML)
|
||||
<script src='https://example.com/myscript.js'></script>
|
||||
<script src='https://example.com/myscript2.js?with=query'></script>
|
||||
<script src='//example2.com/protocol-less-script.js'></script>
|
||||
<script src='domain-only.com'></script>
|
||||
<script>console.log('inline script')</script>
|
||||
SCRIPT
|
||||
HTML
|
||||
|
||||
theme.set_field(target: :desktop, name: "header", value: "")
|
||||
theme.save!
|
||||
|
|
|
@ -14,10 +14,10 @@ describe Email::AuthenticationResults do
|
|||
|
||||
it "parses 'Service Provided, Authentication Done' correctly" do
|
||||
# https://tools.ietf.org/html/rfc8601#appendix-B.3
|
||||
results = described_class.new(<<~EOF
|
||||
results = described_class.new(<<~RAW
|
||||
example.com;
|
||||
spf=pass smtp.mailfrom=example.net
|
||||
EOF
|
||||
RAW
|
||||
).results
|
||||
expect(results[0][:authserv_id]).to eq "example.com"
|
||||
expect(results[0][:resinfo][0][:method]).to eq "spf"
|
||||
|
@ -30,15 +30,15 @@ describe Email::AuthenticationResults do
|
|||
|
||||
it "parses 'Service Provided, Several Authentications Done, Single MTA' correctly" do
|
||||
# https://tools.ietf.org/html/rfc8601#appendix-B.4
|
||||
results = described_class.new([<<~EOF ,
|
||||
results = described_class.new([<<~RAW ,
|
||||
example.com;
|
||||
auth=pass (cram-md5) smtp.auth=sender@example.net;
|
||||
spf=pass smtp.mailfrom=example.net
|
||||
EOF
|
||||
<<~EOF ,
|
||||
RAW
|
||||
<<~RAW ,
|
||||
example.com; iprev=pass
|
||||
policy.iprev=192.0.2.200
|
||||
EOF
|
||||
RAW
|
||||
]).results
|
||||
expect(results[0][:authserv_id]).to eq "example.com"
|
||||
expect(results[0][:resinfo][0][:method]).to eq "auth"
|
||||
|
@ -64,15 +64,15 @@ describe Email::AuthenticationResults do
|
|||
|
||||
it "parses 'Service Provided, Several Authentications Done, Different MTAs' correctly" do
|
||||
# https://tools.ietf.org/html/rfc8601#appendix-B.5
|
||||
results = described_class.new([<<~EOF ,
|
||||
results = described_class.new([<<~RAW ,
|
||||
example.com;
|
||||
dkim=pass (good signature) header.d=example.com
|
||||
EOF
|
||||
<<~EOF ,
|
||||
RAW
|
||||
<<~RAW ,
|
||||
example.com;
|
||||
auth=pass (cram-md5) smtp.auth=sender@example.com;
|
||||
spf=fail smtp.mailfrom=example.com
|
||||
EOF
|
||||
RAW
|
||||
]).results
|
||||
|
||||
expect(results[0][:authserv_id]).to eq "example.com"
|
||||
|
@ -99,17 +99,17 @@ describe Email::AuthenticationResults do
|
|||
|
||||
it "parses 'Service Provided, Multi-tiered Authentication Done' correctly" do
|
||||
# https://tools.ietf.org/html/rfc8601#appendix-B.6
|
||||
results = described_class.new([<<~EOF ,
|
||||
results = described_class.new([<<~RAW ,
|
||||
example.com;
|
||||
dkim=pass reason="good signature"
|
||||
header.i=@mail-router.example.net;
|
||||
dkim=fail reason="bad signature"
|
||||
header.i=@newyork.example.com
|
||||
EOF
|
||||
<<~EOF ,
|
||||
RAW
|
||||
<<~RAW ,
|
||||
example.net;
|
||||
dkim=pass (good signature) header.i=@newyork.example.com
|
||||
EOF
|
||||
RAW
|
||||
]).results
|
||||
|
||||
expect(results[0][:authserv_id]).to eq "example.com"
|
||||
|
@ -136,12 +136,12 @@ describe Email::AuthenticationResults do
|
|||
|
||||
it "parses 'Comment-Heavy Example' correctly" do
|
||||
# https://tools.ietf.org/html/rfc8601#appendix-B.7
|
||||
results = described_class.new(<<~EOF
|
||||
results = described_class.new(<<~RAW
|
||||
foo.example.net (foobar) 1 (baz);
|
||||
dkim (Because I like it) / 1 (One yay) = (wait for it) fail
|
||||
policy (A dot can go here) . (like that) expired
|
||||
(this surprised me) = (as I wasn't expecting it) 1362471462
|
||||
EOF
|
||||
RAW
|
||||
).results
|
||||
|
||||
expect(results[0][:authserv_id]).to eq "foo.example.net"
|
||||
|
@ -163,12 +163,12 @@ describe Email::AuthenticationResults do
|
|||
end
|
||||
|
||||
it "parses header with multiple props correctly" do
|
||||
results = described_class.new(<<~EOF
|
||||
results = described_class.new(<<~RAW
|
||||
mx.google.com;
|
||||
dkim=pass header.i=@email.example.com header.s=20111006 header.b=URn9MW+F;
|
||||
spf=pass (google.com: domain of foo@b.email.example.com designates 1.2.3.4 as permitted sender) smtp.mailfrom=foo@b.email.example.com;
|
||||
dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=email.example.com
|
||||
EOF
|
||||
RAW
|
||||
).results
|
||||
|
||||
expect(results[0][:authserv_id]).to eq "mx.google.com"
|
||||
|
|
|
@ -808,7 +808,7 @@ describe Email::Receiver do
|
|||
post = Post.last
|
||||
|
||||
expect(post.user.email).to eq("ba@bar.com")
|
||||
expect(post.raw).to eq(<<~EOF.chomp
|
||||
expect(post.raw).to eq(<<~RAW.chomp)
|
||||
@team, can you have a look at this email below?
|
||||
|
||||
[quote]
|
||||
|
@ -823,8 +823,7 @@ describe Email::Receiver do
|
|||
|
||||
XoXo
|
||||
[/quote]
|
||||
EOF
|
||||
)
|
||||
RAW
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -976,7 +975,7 @@ describe Email::Receiver do
|
|||
let!(:post) { Fabricate(:post, topic: topic) }
|
||||
|
||||
def process_mail_with_message_id(message_id)
|
||||
mail_string = <<~REPLY
|
||||
mail_string = <<~EMAIL
|
||||
Return-Path: <two@foo.com>
|
||||
From: Two <two@foo.com>
|
||||
To: one@foo.com
|
||||
|
@ -989,7 +988,7 @@ describe Email::Receiver do
|
|||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
This is email reply testing with Message-ID formats.
|
||||
REPLY
|
||||
EMAIL
|
||||
Email::Receiver.new(mail_string).process!
|
||||
end
|
||||
|
||||
|
@ -1867,7 +1866,7 @@ describe Email::Receiver do
|
|||
context "#select_body" do
|
||||
|
||||
let(:email) {
|
||||
<<~EOF
|
||||
<<~EMAIL
|
||||
MIME-Version: 1.0
|
||||
Date: Tue, 01 Jan 2019 00:00:00 +0300
|
||||
Subject: An email with whitespaces
|
||||
|
@ -1916,11 +1915,11 @@ describe Email::Receiver do
|
|||
This is going to be stripped too.
|
||||
|
||||
Bye!
|
||||
EOF
|
||||
EMAIL
|
||||
}
|
||||
|
||||
let(:stripped_text) {
|
||||
<<~EOF
|
||||
<<~MD
|
||||
This is a line that will be stripped
|
||||
This is another line that will be stripped
|
||||
|
||||
|
@ -1962,7 +1961,7 @@ describe Email::Receiver do
|
|||
This is going to be stripped too.
|
||||
|
||||
Bye!
|
||||
EOF
|
||||
MD
|
||||
}
|
||||
|
||||
it "strips lines if strip_incoming_email_lines is enabled" do
|
||||
|
@ -1976,7 +1975,7 @@ describe Email::Receiver do
|
|||
it "works with empty mail body" do
|
||||
SiteSetting.strip_incoming_email_lines = true
|
||||
|
||||
email = <<~EOF
|
||||
email = <<~EMAIL
|
||||
Date: Tue, 01 Jan 2019 00:00:00 +0300
|
||||
Subject: An email with whitespaces
|
||||
From: Foo <foo@discourse.org>
|
||||
|
@ -1986,7 +1985,7 @@ describe Email::Receiver do
|
|||
--
|
||||
my signature
|
||||
|
||||
EOF
|
||||
EMAIL
|
||||
|
||||
receiver = Email::Receiver.new(email)
|
||||
text, _elided, _format = receiver.select_body
|
||||
|
@ -2004,7 +2003,7 @@ describe Email::Receiver do
|
|||
message_id: digest_message_id
|
||||
)}
|
||||
let(:email) {
|
||||
<<~EOF
|
||||
<<~EMAIL
|
||||
MIME-Version: 1.0
|
||||
Date: Tue, 01 Jan 2019 00:00:00 +0300
|
||||
From: someone <#{user.email}>
|
||||
|
@ -2017,7 +2016,7 @@ describe Email::Receiver do
|
|||
|
||||
hello there! I like the digest!
|
||||
|
||||
EOF
|
||||
EMAIL
|
||||
}
|
||||
|
||||
before do
|
||||
|
@ -2034,7 +2033,7 @@ describe Email::Receiver do
|
|||
let(:user) { Fabricate(:user) }
|
||||
let(:group) { Fabricate(:group, users: [user]) }
|
||||
|
||||
let (:email_1) { <<~EOF
|
||||
let (:email_1) { <<~EMAIL
|
||||
MIME-Version: 1.0
|
||||
Date: Wed, 01 Jan 2019 12:00:00 +0200
|
||||
Message-ID: <7aN1uwcokt2xkfG3iYrpKmiuVhy4w9b5@mail.gmail.com>
|
||||
|
@ -2052,7 +2051,7 @@ describe Email::Receiver do
|
|||
Vivamus semper lacinia scelerisque. Cras urna magna, porttitor nec
|
||||
libero quis, congue viverra sapien. Nulla sodales ac tellus a
|
||||
suscipit.
|
||||
EOF
|
||||
EMAIL
|
||||
}
|
||||
|
||||
let (:post_2) {
|
||||
|
@ -2064,7 +2063,7 @@ describe Email::Receiver do
|
|||
)
|
||||
}
|
||||
|
||||
let (:email_3) { <<~EOF
|
||||
let (:email_3) { <<~EMAIL
|
||||
MIME-Version: 1.0
|
||||
Date: Wed, 01 Jan 2019 12:00:00 +0200
|
||||
References: <7aN1uwcokt2xkfG3iYrpKmiuVhy4w9b5@mail.gmail.com> <topic/#{post_2.topic_id}/#{post_2.id}@test.localhost>
|
||||
|
@ -2087,7 +2086,7 @@ describe Email::Receiver do
|
|||
felis. Sed pellentesque, massa auctor venenatis gravida, risus lorem
|
||||
iaculis mi, at hendrerit nisi turpis sit amet metus. Nulla egestas
|
||||
ante eget nisi luctus consectetur.
|
||||
EOF
|
||||
EMAIL
|
||||
}
|
||||
|
||||
def receive(email_string)
|
||||
|
|
|
@ -16,28 +16,28 @@ describe EmailCook do
|
|||
end
|
||||
|
||||
it "doesn't add linebreaks to long lines" do
|
||||
long = plaintext(<<~LONG_EMAIL)
|
||||
long = plaintext(<<~EMAIL)
|
||||
Hello,
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis volutpat
|
||||
risus. Nulla ac faucibus quam, quis cursus lorem. Sed rutrum eget nunc sed accumsan.
|
||||
Vestibulum feugiat mi vitae turpis tempor dignissim.
|
||||
LONG_EMAIL
|
||||
EMAIL
|
||||
|
||||
long_cooked = (+<<~LONG_COOKED).strip!
|
||||
long_cooked = (+<<~HTML).strip!
|
||||
Hello,
|
||||
<br>
|
||||
<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis volutpat
|
||||
risus. Nulla ac faucibus quam, quis cursus lorem. Sed rutrum eget nunc sed accumsan.
|
||||
Vestibulum feugiat mi vitae turpis tempor dignissim.
|
||||
<br>
|
||||
LONG_COOKED
|
||||
HTML
|
||||
|
||||
expect(cook(long)).to eq(long_cooked)
|
||||
end
|
||||
|
||||
it "replaces a blank line with 2 linebreaks" do
|
||||
long = plaintext(<<~LONG_EMAIL)
|
||||
long = plaintext(<<~EMAIL)
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis volutpat
|
||||
risus.
|
||||
Nulla ac faucibus quam, quis cursus lorem. Sed rutrum eget nunc sed accumsan.
|
||||
|
@ -45,9 +45,9 @@ describe EmailCook do
|
|||
Vestibulum feugiat mi vitae turpis tempor dignissim.
|
||||
|
||||
Stet clita kasd gubergren.
|
||||
LONG_EMAIL
|
||||
EMAIL
|
||||
|
||||
long_cooked = (+<<~LONG_COOKED).strip!
|
||||
long_cooked = (+<<~HTML).strip!
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis volutpat
|
||||
risus.
|
||||
<br>Nulla ac faucibus quam, quis cursus lorem. Sed rutrum eget nunc sed accumsan.
|
||||
|
@ -56,13 +56,13 @@ describe EmailCook do
|
|||
<br>
|
||||
<br>Stet clita kasd gubergren.
|
||||
<br>
|
||||
LONG_COOKED
|
||||
HTML
|
||||
|
||||
expect(cook(long)).to eq(long_cooked)
|
||||
end
|
||||
|
||||
it "escapes HTML" do
|
||||
long = plaintext(<<~LONG_EMAIL)
|
||||
long = plaintext(<<~EMAIL)
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
|
||||
<form name="f1" method="post" action="test.html" onsubmit="javascript:showAlert()">
|
||||
|
@ -70,9 +70,9 @@ describe EmailCook do
|
|||
</form>
|
||||
|
||||
Nunc convallis volutpat risus.
|
||||
LONG_EMAIL
|
||||
EMAIL
|
||||
|
||||
long_cooked = (+<<~LONG_COOKED).strip!
|
||||
long_cooked = (+<<~HTML).strip!
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<br>
|
||||
<br><form name="f1" method="post" action="test.html" onsubmit="javascript:showAlert()">
|
||||
|
@ -81,29 +81,29 @@ describe EmailCook do
|
|||
<br>
|
||||
<br>Nunc convallis volutpat risus.
|
||||
<br>
|
||||
LONG_COOKED
|
||||
HTML
|
||||
|
||||
expect(cook(long)).to eq(long_cooked)
|
||||
end
|
||||
|
||||
it "replaces indentation of more than 2 spaces with corresponding amount of non-breaking spaces" do
|
||||
nbsp = "\u00A0"
|
||||
long = plaintext(<<~LONG_EMAIL)
|
||||
long = plaintext(<<~EMAIL)
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
|
||||
this is intended by 4 spaces
|
||||
this is intended by 1 space
|
||||
no indentation, but lots of spaces
|
||||
LONG_EMAIL
|
||||
EMAIL
|
||||
|
||||
long_cooked = (+<<~LONG_COOKED).strip!
|
||||
long_cooked = (+<<~HTML).strip!
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<br>
|
||||
<br>#{nbsp}#{nbsp}#{nbsp}#{nbsp}this is intended by 4 spaces
|
||||
<br> this is intended by 1 space
|
||||
<br>no indentation, but lots of spaces
|
||||
<br>
|
||||
LONG_COOKED
|
||||
HTML
|
||||
|
||||
expect(cook(long)).to eq(long_cooked)
|
||||
end
|
||||
|
@ -129,7 +129,7 @@ describe EmailCook do
|
|||
end
|
||||
|
||||
it "it works and does not interpret Markdown in plaintext and elided" do
|
||||
long = <<~LONG_EMAIL
|
||||
long = <<~EMAIL
|
||||
[plaintext]
|
||||
*Lorem ipsum* dolor sit amet, consectetur adipiscing elit.
|
||||
[/plaintext]
|
||||
|
@ -139,9 +139,9 @@ describe EmailCook do
|
|||
[elided]
|
||||
At vero eos *et accusam* et justo duo dolores et ea rebum.
|
||||
[/elided]
|
||||
LONG_EMAIL
|
||||
EMAIL
|
||||
|
||||
long_cooked = <<~LONG_COOKED
|
||||
long_cooked = <<~HTML
|
||||
*Lorem ipsum* dolor sit amet, consectetur adipiscing elit.<br>
|
||||
<br><img src='some_image.png' width='100' height='100'>
|
||||
<br><br>
|
||||
|
@ -152,22 +152,22 @@ describe EmailCook do
|
|||
At vero eos *et accusam* et justo duo dolores et ea rebum.<br>
|
||||
|
||||
</details>
|
||||
LONG_COOKED
|
||||
HTML
|
||||
|
||||
expect(cook(long)).to eq(long_cooked)
|
||||
end
|
||||
|
||||
it "works without attachments" do
|
||||
long = <<~LONG_EMAIL
|
||||
long = <<~EMAIL
|
||||
[plaintext]
|
||||
*Lorem ipsum* dolor sit amet, consectetur adipiscing elit.
|
||||
[/plaintext]
|
||||
[elided]
|
||||
At vero eos *et accusam* et justo duo dolores et ea rebum.
|
||||
[/elided]
|
||||
LONG_EMAIL
|
||||
EMAIL
|
||||
|
||||
long_cooked = <<~LONG_COOKED
|
||||
long_cooked = <<~HTML
|
||||
*Lorem ipsum* dolor sit amet, consectetur adipiscing elit.<br>
|
||||
<br><br>
|
||||
|
||||
|
@ -177,7 +177,7 @@ describe EmailCook do
|
|||
At vero eos *et accusam* et justo duo dolores et ea rebum.<br>
|
||||
|
||||
</details>
|
||||
LONG_COOKED
|
||||
HTML
|
||||
|
||||
expect(cook(long)).to eq(long_cooked)
|
||||
end
|
||||
|
|
|
@ -353,7 +353,7 @@ describe PrettyText do
|
|||
expect(PrettyText.cook("[quote]\ntest")).not_to include('aside')
|
||||
expect(PrettyText.cook("[quote]\ntest\n[/quote]z")).not_to include('aside')
|
||||
|
||||
nested = <<~QUOTE
|
||||
nested = <<~MD
|
||||
[quote]
|
||||
a
|
||||
[quote]
|
||||
|
@ -361,7 +361,7 @@ describe PrettyText do
|
|||
[/quote]
|
||||
c
|
||||
[/quote]
|
||||
QUOTE
|
||||
MD
|
||||
|
||||
cooked = PrettyText.cook(nested)
|
||||
expect(cooked.scan('aside').length).to eq(4)
|
||||
|
@ -799,9 +799,9 @@ describe PrettyText do
|
|||
|
||||
context "emojis" do
|
||||
it "should remove broken emoji" do
|
||||
html = <<~EOS
|
||||
html = <<~HTML
|
||||
<img src=\"//localhost:3000/images/emoji/twitter/bike.png?v=#{Emoji::EMOJI_VERSION}\" title=\":bike:\" class=\"emoji\" alt=\":bike:\" loading=\"lazy\" width=\"20\" height=\"20\"> <img src=\"//localhost:3000/images/emoji/twitter/cat.png?v=#{Emoji::EMOJI_VERSION}\" title=\":cat:\" class=\"emoji\" alt=\":cat:\" loading=\"lazy\" width=\"20\" height=\"20\"> <img src=\"//localhost:3000/images/emoji/twitter/discourse.png?v=#{Emoji::EMOJI_VERSION}\" title=\":discourse:\" class=\"emoji\" alt=\":discourse:\" loading=\"lazy\" width=\"20\" height=\"20\">
|
||||
EOS
|
||||
HTML
|
||||
expect(PrettyText.excerpt(html, 7)).to eq(":bike: …")
|
||||
expect(PrettyText.excerpt(html, 8)).to eq(":bike: …")
|
||||
expect(PrettyText.excerpt(html, 9)).to eq(":bike: …")
|
||||
|
@ -914,7 +914,7 @@ describe PrettyText do
|
|||
end
|
||||
|
||||
it "should not extract links inside oneboxes" do
|
||||
onebox = <<~EOF
|
||||
onebox = <<~HTML
|
||||
<aside class="onebox twitterstatus" data-onebox-src="https://twitter.com/EDBPostgres/status/1402528437441634306">
|
||||
<header class="source">
|
||||
<a href="https://twitter.com/EDBPostgres/status/1402528437441634306" target="_blank" rel="noopener">twitter.com</a>
|
||||
|
@ -924,7 +924,7 @@ describe PrettyText do
|
|||
<div class="tweet">Example URL: <a target="_blank" href="https://example.com" rel="noopener">example.com</a></div>
|
||||
</article>
|
||||
</aside>
|
||||
EOF
|
||||
HTML
|
||||
|
||||
expect(PrettyText.extract_links(onebox).map(&:url)).to contain_exactly("https://twitter.com/EDBPostgres/status/1402528437441634306")
|
||||
end
|
||||
|
@ -938,12 +938,13 @@ describe PrettyText do
|
|||
end
|
||||
|
||||
it "handles custom bbcode excerpt" do
|
||||
raw = <<~RAW
|
||||
raw = <<~MD
|
||||
[excerpt]
|
||||
hello [site](https://site.com)
|
||||
[/excerpt]
|
||||
more stuff
|
||||
RAW
|
||||
MD
|
||||
|
||||
post = Fabricate(:post, raw: raw)
|
||||
expect(post.excerpt).to eq("hello <a href=\"https://site.com\" rel=\"noopener nofollow ugc\">site</a>")
|
||||
end
|
||||
|
@ -1929,17 +1930,17 @@ HTML
|
|||
|
||||
it "can properly allowlist iframes" do
|
||||
SiteSetting.allowed_iframes = "https://bob.com/a|http://silly.com?EMBED="
|
||||
raw = <<~IFRAMES
|
||||
raw = <<~HTML
|
||||
<iframe src='https://www.google.com/maps/Embed?testing'></iframe>
|
||||
<iframe src='https://bob.com/a?testing'></iframe>
|
||||
<iframe src='HTTP://SILLY.COM?EMBED=111'></iframe>
|
||||
IFRAMES
|
||||
HTML
|
||||
|
||||
# we require explicit HTTPS here
|
||||
html = <<~IFRAMES
|
||||
html = <<~HTML
|
||||
<iframe src="https://bob.com/a?testing"></iframe>
|
||||
<iframe src="HTTP://SILLY.COM?EMBED=111"></iframe>
|
||||
IFRAMES
|
||||
HTML
|
||||
|
||||
cooked = PrettyText.cook(raw).strip
|
||||
|
||||
|
|
|
@ -551,9 +551,9 @@ describe Search do
|
|||
|
||||
result = Search.execute('search term')
|
||||
|
||||
expect(result.posts.first.topic_title_headline).to eq(<<~TITLE.chomp)
|
||||
expect(result.posts.first.topic_title_headline).to eq(<<~HTML.chomp)
|
||||
Very very very very very very very long topic title with our <span class=\"#{Search::HIGHLIGHT_CSS_CLASS}\">search</span> <span class=\"#{Search::HIGHLIGHT_CSS_CLASS}\">term</span> in the middle of the title
|
||||
TITLE
|
||||
HTML
|
||||
end
|
||||
|
||||
it "limits the search headline to #{Search::GroupedSearchResults::BLURB_LENGTH} characters" do
|
||||
|
|
|
@ -76,25 +76,25 @@ describe Discourse::VERSION do
|
|||
end
|
||||
|
||||
context "with a regular compatible list" do
|
||||
let(:version_list) { <<~VERSION_LIST
|
||||
let(:version_list) { <<~YML
|
||||
2.5.0.beta6: twofivebetasix
|
||||
2.5.0.beta4: twofivebetafour
|
||||
2.5.0.beta2: twofivebetatwo
|
||||
2.4.4.beta6: twofourfourbetasix
|
||||
2.4.2.beta1: twofourtwobetaone
|
||||
VERSION_LIST
|
||||
YML
|
||||
}
|
||||
include_examples "test compatible resource"
|
||||
end
|
||||
|
||||
context "handle a compatible resource out of order" do
|
||||
let(:version_list) { <<~VERSION_LIST
|
||||
let(:version_list) { <<~YML
|
||||
2.4.2.beta1: twofourtwobetaone
|
||||
2.5.0.beta4: twofivebetafour
|
||||
2.5.0.beta6: twofivebetasix
|
||||
2.5.0.beta2: twofivebetatwo
|
||||
2.4.4.beta6: twofourfourbetasix
|
||||
VERSION_LIST
|
||||
YML
|
||||
}
|
||||
include_examples "test compatible resource"
|
||||
end
|
||||
|
|
|
@ -28,7 +28,7 @@ describe GroupSmtpMailer do
|
|||
end
|
||||
|
||||
let(:email) do
|
||||
<<~EOF
|
||||
<<~EMAIL
|
||||
Delivered-To: bugs@gmail.com
|
||||
MIME-Version: 1.0
|
||||
From: John Doe <john@doe.com>
|
||||
|
@ -41,7 +41,7 @@ describe GroupSmtpMailer do
|
|||
Hello,
|
||||
|
||||
How are you doing?
|
||||
EOF
|
||||
EMAIL
|
||||
end
|
||||
|
||||
let(:receiver) do
|
||||
|
|
|
@ -92,10 +92,10 @@ describe ThemeField do
|
|||
<script>var b = 10</script>
|
||||
HTML
|
||||
|
||||
extracted = <<~JavaScript
|
||||
extracted = <<~JS
|
||||
var a = 10
|
||||
var b = 10
|
||||
JavaScript
|
||||
JS
|
||||
|
||||
theme_field = ThemeField.create!(theme_id: 1, target_id: 0, name: "header", value: html)
|
||||
theme_field.ensure_baked!
|
||||
|
|
|
@ -326,10 +326,10 @@ HTML
|
|||
expect(scss).to include("font-size:30px")
|
||||
|
||||
# Escapes correctly. If not, compiling this would throw an exception
|
||||
setting.value = <<~MULTILINE
|
||||
setting.value = <<~CSS
|
||||
\#{$fakeinterpolatedvariable}
|
||||
andanothervalue 'withquotes'; margin: 0;
|
||||
MULTILINE
|
||||
CSS
|
||||
|
||||
theme.set_field(target: :common, name: :scss, value: 'body {font-size: quote($font-size)}')
|
||||
theme.save!
|
||||
|
|
|
@ -390,10 +390,10 @@ describe TopicEmbed do
|
|||
it "handles malformed links" do
|
||||
url = "https://somesource.com"
|
||||
|
||||
contents = <<~CONTENT
|
||||
contents = <<~HTML
|
||||
hello world new post <a href="mailto:somemail@somewhere.org>">hello</a>
|
||||
some image <img src="https:/><invalidimagesrc/">
|
||||
CONTENT
|
||||
HTML
|
||||
|
||||
raw = TopicEmbed.absolutize_urls(url, contents)
|
||||
expect(raw).to eq(contents)
|
||||
|
|
|
@ -454,14 +454,14 @@ RSpec.describe Admin::BackupsController do
|
|||
BackupRestore::S3BackupStore.any_instance.stubs(:temporary_upload_path).returns(
|
||||
"temp/default/#{test_bucket_prefix}/28fccf8259bbe75b873a2bd2564b778c/2u98j832nx93272x947823.gz"
|
||||
)
|
||||
create_multipart_result = <<~BODY
|
||||
create_multipart_result = <<~XML
|
||||
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
|
||||
<InitiateMultipartUploadResult>
|
||||
<Bucket>s3-backup-bucket</Bucket>
|
||||
<Key>temp/default/#{test_bucket_prefix}/28fccf8259bbe75b873a2bd2564b778c/2u98j832nx93272x947823.gz</Key>
|
||||
<UploadId>#{mock_multipart_upload_id}</UploadId>
|
||||
</InitiateMultipartUploadResult>
|
||||
BODY
|
||||
XML
|
||||
stub_request(:post, "https://s3-backup-bucket.s3.us-west-1.amazonaws.com/temp/default/#{test_bucket_prefix}/28fccf8259bbe75b873a2bd2564b778c/2u98j832nx93272x947823.gz?uploads").
|
||||
to_return(status: 200, body: create_multipart_result)
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ describe 'groups' do
|
|||
in: :query,
|
||||
type: :string,
|
||||
example: 'api @blake #support tags:api after:2021-06-04 in:unseen in:open order:latest_topic',
|
||||
description: <<~HEREDOC
|
||||
description: <<~MD
|
||||
The query string needs to be url encoded and is made up of the following options:
|
||||
- Search term. This is just a string. Usually it would be the first item in the query.
|
||||
- `@<username>`: Use the `@` followed by the username to specify posts by this user.
|
||||
|
@ -44,7 +44,7 @@ describe 'groups' do
|
|||
curl -i -sS -X GET -G "http://localhost:4200/search.json" \\
|
||||
--data-urlencode 'q=wordpress @scossar #fun after:2020-01-01'
|
||||
```
|
||||
HEREDOC
|
||||
MD
|
||||
)
|
||||
parameter name: :page, in: :query, type: :integer, example: 1
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ describe 'uploads' do
|
|||
tags 'Uploads'
|
||||
operationId 'generatePresignedPut'
|
||||
consumes 'application/json'
|
||||
description <<~HEREDOC
|
||||
description <<~TEXT
|
||||
Direct external uploads bypass the usual method of creating uploads
|
||||
via the POST /uploads route, and upload directly to an external provider,
|
||||
which by default is S3. This route begins the process, and will return
|
||||
|
@ -66,7 +66,7 @@ describe 'uploads' do
|
|||
destination in the external storage service.
|
||||
|
||||
#{direct_uploads_disclaimer}
|
||||
HEREDOC
|
||||
TEXT
|
||||
|
||||
expected_request_schema = load_spec_schema('upload_generate_presigned_put_request')
|
||||
parameter name: :params, in: :body, schema: expected_request_schema
|
||||
|
@ -108,7 +108,7 @@ describe 'uploads' do
|
|||
tags 'Uploads'
|
||||
operationId 'completeExternalUpload'
|
||||
consumes 'application/json'
|
||||
description <<~HEREDOC
|
||||
description <<~TEXT
|
||||
Completes an external upload initialized with /get-presigned-put. The
|
||||
file will be moved from its temporary location in external storage to
|
||||
a final destination in the S3 bucket. An Upload record will also be
|
||||
|
@ -119,7 +119,7 @@ describe 'uploads' do
|
|||
file was uploaded. The file size will be compared for the same reason.
|
||||
|
||||
#{direct_uploads_disclaimer}
|
||||
HEREDOC
|
||||
TEXT
|
||||
|
||||
expected_request_schema = load_spec_schema('upload_complete_external_upload_request')
|
||||
parameter name: :params, in: :body, schema: expected_request_schema
|
||||
|
@ -154,12 +154,12 @@ describe 'uploads' do
|
|||
tags 'Uploads'
|
||||
operationId 'createMultipartUpload'
|
||||
consumes 'application/json'
|
||||
description <<~HEREDOC
|
||||
description <<~TEXT
|
||||
Creates a multipart upload in the external storage provider, storing
|
||||
a temporary reference to the external upload similar to /get-presigned-put.
|
||||
|
||||
#{direct_uploads_disclaimer}
|
||||
HEREDOC
|
||||
TEXT
|
||||
|
||||
expected_request_schema = load_spec_schema('upload_create_multipart_request')
|
||||
parameter name: :params, in: :body, schema: expected_request_schema
|
||||
|
@ -200,7 +200,7 @@ describe 'uploads' do
|
|||
tags 'Uploads'
|
||||
operationId 'batchPresignMultipartParts'
|
||||
consumes 'application/json'
|
||||
description <<~HEREDOC
|
||||
description <<~TEXT
|
||||
Multipart uploads are uploaded in chunks or parts to individual presigned
|
||||
URLs, similar to the one generated by /generate-presigned-put. The part
|
||||
numbers provided must be between 1 and 10000. The total number of parts
|
||||
|
@ -215,7 +215,7 @@ describe 'uploads' do
|
|||
because this is needed to complete the multipart upload.
|
||||
|
||||
#{direct_uploads_disclaimer}
|
||||
HEREDOC
|
||||
TEXT
|
||||
|
||||
expected_request_schema = load_spec_schema('upload_batch_presign_multipart_parts_request')
|
||||
parameter name: :params, in: :body, schema: expected_request_schema
|
||||
|
@ -255,13 +255,13 @@ describe 'uploads' do
|
|||
tags 'Uploads'
|
||||
operationId 'abortMultipart'
|
||||
consumes 'application/json'
|
||||
description <<~HEREDOC
|
||||
description <<~TEXT
|
||||
This endpoint aborts the multipart upload initiated with /create-multipart.
|
||||
This should be used when cancelling the upload. It does not matter if parts
|
||||
were already uploaded into the external storage provider.
|
||||
|
||||
#{direct_uploads_disclaimer}
|
||||
HEREDOC
|
||||
TEXT
|
||||
|
||||
expected_request_schema = load_spec_schema('upload_abort_multipart_request')
|
||||
parameter name: :params, in: :body, schema: expected_request_schema
|
||||
|
@ -299,7 +299,7 @@ describe 'uploads' do
|
|||
tags 'Uploads'
|
||||
operationId 'completeMultipart'
|
||||
consumes 'application/json'
|
||||
description <<~HEREDOC
|
||||
description <<~TEXT
|
||||
Completes the multipart upload in the external store, and copies the
|
||||
file from its temporary location to its final location in the store.
|
||||
All of the parts must have been uploaded to the external storage provider.
|
||||
|
@ -307,7 +307,7 @@ describe 'uploads' do
|
|||
to its final location.
|
||||
|
||||
#{direct_uploads_disclaimer}
|
||||
HEREDOC
|
||||
TEXT
|
||||
|
||||
expected_request_schema = load_spec_schema('upload_complete_multipart_request')
|
||||
parameter name: :params, in: :body, schema: expected_request_schema
|
||||
|
|
|
@ -125,13 +125,13 @@ RSpec.describe MetadataController do
|
|||
end
|
||||
|
||||
it 'returns the right output' do
|
||||
SiteSetting.app_association_android = <<~EOF
|
||||
SiteSetting.app_association_android = <<~JSON
|
||||
[{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target" : { "namespace": "android_app", "package_name": "com.example.app",
|
||||
"sha256_cert_fingerprints": ["hash_of_app_certificate"] }
|
||||
}]
|
||||
EOF
|
||||
JSON
|
||||
get "/.well-known/assetlinks.json"
|
||||
|
||||
expect(response.headers["Cache-Control"]).to eq('max-age=60, private')
|
||||
|
@ -150,13 +150,13 @@ RSpec.describe MetadataController do
|
|||
end
|
||||
|
||||
it 'returns the right output' do
|
||||
SiteSetting.app_association_ios = <<~EOF
|
||||
SiteSetting.app_association_ios = <<~JSON
|
||||
{
|
||||
"applinks": {
|
||||
"apps": []
|
||||
}
|
||||
}
|
||||
EOF
|
||||
JSON
|
||||
get "/apple-app-site-association"
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
|
|
|
@ -831,14 +831,14 @@ describe UploadsController do
|
|||
FileStore::S3Store.any_instance.stubs(:temporary_upload_path).returns(
|
||||
"uploads/default/#{test_bucket_prefix}/temp/28fccf8259bbe75b873a2bd2564b778c/test.png"
|
||||
)
|
||||
create_multipart_result = <<~BODY
|
||||
create_multipart_result = <<~XML
|
||||
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
|
||||
<InitiateMultipartUploadResult>
|
||||
<Bucket>s3-upload-bucket</Bucket>
|
||||
<Key>uploads/default/#{test_bucket_prefix}/temp/28fccf8259bbe75b873a2bd2564b778c/test.png</Key>
|
||||
<UploadId>#{mock_multipart_upload_id}</UploadId>
|
||||
</InitiateMultipartUploadResult>
|
||||
BODY
|
||||
XML
|
||||
stub_request(
|
||||
:post,
|
||||
"https://s3-upload-bucket.s3.us-west-1.amazonaws.com/uploads/default/#{test_bucket_prefix}/temp/28fccf8259bbe75b873a2bd2564b778c/test.png?uploads"
|
||||
|
@ -948,7 +948,7 @@ describe UploadsController do
|
|||
end
|
||||
|
||||
def stub_list_multipart_request
|
||||
list_multipart_result = <<~BODY
|
||||
list_multipart_result = <<~XML
|
||||
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
|
||||
<ListPartsResult>
|
||||
<Bucket>s3-upload-bucket</Bucket>
|
||||
|
@ -974,7 +974,7 @@ describe UploadsController do
|
|||
</Owner>
|
||||
<StorageClass>STANDARD</StorageClass>
|
||||
</ListPartsResult>
|
||||
BODY
|
||||
XML
|
||||
stub_request(:get, "https://s3-upload-bucket.s3.us-west-1.amazonaws.com/#{external_upload_stub.key}?max-parts=1&uploadId=#{mock_multipart_upload_id}").to_return({ status: 200, body: list_multipart_result })
|
||||
end
|
||||
|
||||
|
@ -1092,7 +1092,7 @@ describe UploadsController do
|
|||
end
|
||||
|
||||
def stub_list_multipart_request
|
||||
list_multipart_result = <<~BODY
|
||||
list_multipart_result = <<~XML
|
||||
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
|
||||
<ListPartsResult>
|
||||
<Bucket>s3-upload-bucket</Bucket>
|
||||
|
@ -1118,7 +1118,7 @@ describe UploadsController do
|
|||
</Owner>
|
||||
<StorageClass>STANDARD</StorageClass>
|
||||
</ListPartsResult>
|
||||
BODY
|
||||
XML
|
||||
stub_request(:get, "#{upload_base_url}/#{external_upload_stub.key}?max-parts=1&uploadId=#{mock_multipart_upload_id}").to_return({ status: 200, body: list_multipart_result })
|
||||
end
|
||||
|
||||
|
|
|
@ -292,14 +292,14 @@ RSpec.describe ExternalUploadManager do
|
|||
end
|
||||
|
||||
def copy_object_result
|
||||
<<~BODY
|
||||
<<~XML
|
||||
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n
|
||||
<CopyObjectResult
|
||||
xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">
|
||||
<LastModified>2021-07-19T04:10:41.000Z</LastModified>
|
||||
<ETag>"#{etag}"</ETag>
|
||||
</CopyObjectResult>
|
||||
BODY
|
||||
XML
|
||||
end
|
||||
|
||||
def stub_copy_object
|
||||
|
|
|
@ -175,9 +175,9 @@ describe PostAlerter do
|
|||
|
||||
post = Fabricate(:post, topic: pm, user: user1)
|
||||
TopicUser.change(user1.id, pm.id, notification_level: TopicUser.notification_levels[:regular])
|
||||
quote_raw = <<~STRING
|
||||
quote_raw = <<~MD
|
||||
[quote="#{user1.username}, post:1, topic:#{pm.id}"]#{post.raw}[/quote]
|
||||
STRING
|
||||
MD
|
||||
|
||||
expect {
|
||||
create_post_with_alerts(
|
||||
|
@ -190,9 +190,9 @@ describe PostAlerter do
|
|||
group.add(admin)
|
||||
|
||||
TopicUser.change(user2.id, pm.id, notification_level: TopicUser.notification_levels[:regular])
|
||||
quote_raw = <<~STRING
|
||||
quote_raw = <<~MD
|
||||
[quote="#{user2.username}, post:1, topic:#{pm.id}"]#{op.raw}[/quote]
|
||||
STRING
|
||||
MD
|
||||
|
||||
expect {
|
||||
create_post_with_alerts(
|
||||
|
@ -1566,7 +1566,7 @@ describe PostAlerter do
|
|||
end
|
||||
|
||||
def create_post_with_incoming
|
||||
raw_mail = <<~MAIL
|
||||
raw_mail = <<~EMAIL
|
||||
From: Foo <foo@discourse.org>
|
||||
To: discourse@example.com
|
||||
Cc: bar@discourse.org, jim@othersite.com
|
||||
|
@ -1578,7 +1578,7 @@ describe PostAlerter do
|
|||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
This is the first email.
|
||||
MAIL
|
||||
EMAIL
|
||||
|
||||
Email::Receiver.new(raw_mail, {}).process!
|
||||
end
|
||||
|
@ -1716,7 +1716,7 @@ describe PostAlerter do
|
|||
email = ActionMailer::Base.deliveries.last
|
||||
|
||||
# the reply post from someone who was emailed
|
||||
reply_raw_mail = <<~MAIL
|
||||
reply_raw_mail = <<~EMAIL
|
||||
From: Bar <bar@discourse.org>
|
||||
To: discourse@example.com
|
||||
Cc: someothernewcc@baz.com, finalnewcc@doom.com
|
||||
|
@ -1729,7 +1729,7 @@ describe PostAlerter do
|
|||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Hey here is my reply!
|
||||
MAIL
|
||||
EMAIL
|
||||
|
||||
reply_post_from_email = nil
|
||||
expect {
|
||||
|
@ -1767,7 +1767,7 @@ describe PostAlerter do
|
|||
email = ActionMailer::Base.deliveries.last
|
||||
|
||||
# the reply post from someone who was emailed
|
||||
reply_raw_mail = <<~MAIL
|
||||
reply_raw_mail = <<~EMAIL
|
||||
From: Foo <foo@discourse.org>
|
||||
To: discourse@example.com
|
||||
Cc: someothernewcc@baz.com, finalnewcc@doom.com
|
||||
|
@ -1780,7 +1780,7 @@ describe PostAlerter do
|
|||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
I am ~~Commander Shepherd~~ the OP and I approve of this message.
|
||||
MAIL
|
||||
EMAIL
|
||||
|
||||
reply_post_from_email = nil
|
||||
expect {
|
||||
|
@ -1811,7 +1811,7 @@ describe PostAlerter do
|
|||
|
||||
# this is a special case where we are not CC'ing on the original email,
|
||||
# only on the follow up email
|
||||
raw_mail = <<~MAIL
|
||||
raw_mail = <<~EMAIL
|
||||
From: Foo <foo@discourse.org>
|
||||
To: discourse@example.com
|
||||
Subject: Full email group username flow
|
||||
|
@ -1822,7 +1822,7 @@ describe PostAlerter do
|
|||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
This is the first email.
|
||||
MAIL
|
||||
EMAIL
|
||||
|
||||
incoming_email_post = Email::Receiver.new(raw_mail, {}).process!
|
||||
topic = incoming_email_post.topic
|
||||
|
@ -1833,7 +1833,7 @@ describe PostAlerter do
|
|||
email = ActionMailer::Base.deliveries.last
|
||||
|
||||
# the reply post from the OP, cc'ing new people in
|
||||
reply_raw_mail = <<~MAIL
|
||||
reply_raw_mail = <<~EMAIL
|
||||
From: Foo <foo@discourse.org>
|
||||
To: discourse@example.com
|
||||
Cc: someothernewcc@baz.com, finalnewcc@doom.com
|
||||
|
@ -1846,7 +1846,7 @@ describe PostAlerter do
|
|||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
I am inviting my mates to this email party.
|
||||
MAIL
|
||||
EMAIL
|
||||
|
||||
reply_post_from_email = nil
|
||||
expect {
|
||||
|
|
|
@ -14,7 +14,7 @@ def load_spec_schema(name)
|
|||
end
|
||||
|
||||
def api_docs_description
|
||||
<<~HEREDOC
|
||||
<<~MD
|
||||
This page contains the documentation on how to use Discourse through API calls.
|
||||
|
||||
> Note: For any endpoints not listed you can follow the
|
||||
|
@ -71,11 +71,11 @@ def api_docs_description
|
|||
|
||||
If an endpoint accepts a boolean be sure to specify it as a lowercase
|
||||
`true` or `false` value unless noted otherwise.
|
||||
HEREDOC
|
||||
MD
|
||||
end
|
||||
|
||||
def direct_uploads_disclaimer
|
||||
<<~HEREDOC
|
||||
<<~MD
|
||||
You must have the correct permissions and CORS settings configured in your
|
||||
external provider. We support AWS S3 as the default. See:
|
||||
|
||||
|
@ -83,7 +83,7 @@ def direct_uploads_disclaimer
|
|||
|
||||
An external file store must be set up and `enable_direct_s3_uploads` must
|
||||
be set to true for this endpoint to function.
|
||||
HEREDOC
|
||||
MD
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
|
|
Loading…
Reference in New Issue
Block a user