diff options
author | multiple creatures <dev@multiple-creature.party> | 2019-05-18 13:03:36 -0500 |
---|---|---|
committer | multiple creatures <dev@multiple-creature.party> | 2019-05-21 03:16:50 -0500 |
commit | 7a0dc34cad955fecba8072f5ed3c179ba5a3fd98 (patch) | |
tree | 7e539207950bc274c5504bf5904a49abf0d9aca2 /app/lib | |
parent | 09b7532805a349d1a57f4a650c7f41456cda184b (diff) |
reimplement monsterpit bbcode and markdown extensions on top of new glitch-soc formatting system + bbcode feature parity + new `i:am` footer + set content type from `format` bangtag
Diffstat (limited to 'app/lib')
-rw-r--r-- | app/lib/bangtags.rb | 51 | ||||
-rw-r--r-- | app/lib/formatter.rb | 178 | ||||
-rw-r--r-- | app/lib/sanitize_config.rb | 5 |
3 files changed, 213 insertions, 21 deletions
diff --git a/app/lib/bangtags.rb b/app/lib/bangtags.rb index 404d20a0f..4ba6b5e92 100644 --- a/app/lib/bangtags.rb +++ b/app/lib/bangtags.rb @@ -26,7 +26,7 @@ class Bangtags # list of transformation commands @tf_cmds = [] # list of post-processing commands - @post_cmds = [['signature']] + @post_cmds = [] # hash of bangtag variables @vars = account.vars # keep track of what variables we're appending the value of between chunks @@ -36,7 +36,7 @@ class Bangtags end def process - return unless status.text&.present? + return unless status.text&.present? && status.text.include?('#!') status.text.gsub!('#!!', "#\u200c!") @@ -367,16 +367,19 @@ class Bangtags who = cmd[2] if who.blank? @vars.delete('_they:are') + status.footer = nil next elsif who == 'not' who = cmd[3] next if who.blank? name = who.downcase.gsub(/\s+/, '') @vars.delete("_they:are:#{name}") - @vars.delete('_they:are') if @vars['_they:are'] == name + next unless @vars['_they:are'] == name + @vars.delete('_they:are') + status.footer = nil next end - name = who.downcase.gsub(/\s+/, '') + name = who.downcase.gsub(/\s+/, '').strip description = cmd[3..-1].join(':').strip if description.blank? if @vars["_they:are:#{name}"].nil? @@ -385,7 +388,8 @@ class Bangtags else @vars["_they:are:#{name}"] = description end - @vars['_they:are'] = name.strip + @vars['_they:are'] = name + status.footer = @vars["_they:are:#{name}"] end when 'sharekey' next if cmd[1].nil? @@ -401,6 +405,30 @@ class Bangtags @vore_stack.push('_draft') @component_stack.push(:var) add_tags(status, 'self:draft') + when 'format', 'type' + chunk = nil + next if cmd[1].nil? + content_types = { + 't' => 'text/plain', + 'txt' => 'text/plain', + 'text' => 'text/plain', + 'plain' => 'text/plain', + 'plaintext' => 'text/plain', + + 'm' => 'text/markdown', + 'md' => 'text/markdown', + 'markdown' => 'text/markdown', + + 'b' => 'text/x-bbcode', + 'bbc' => 'text/x-bbcode', + 'bbcode' => 'text/x-bbcode', + + 'bm' => 'text/x-bbcode+markdown', + 'bbm' => 'text/x-bbcode+markdown', + 'bbdown' => 'text/x-bbcode+markdown', + } + v = cmd[1].downcase + status.content_type = content_types[c] unless content_types[c].nil? when 'visibility' chunk = nil next if cmd[1].nil? @@ -421,7 +449,7 @@ class Bangtags 'world' => :public, } v = cmd[1].downcase - status.visibility = visibilities[v] if visibilities[v].nil? + status.visibility = visibilities[v] unless visibilities[v].nil? end end @@ -472,17 +500,6 @@ class Bangtags def postprocess_before_save @post_cmds.each do |post_cmd| case post_cmd[0] - when 'signature' - name = @vars['_they:are'] - next if name.blank? - description = @vars["_they:are:#{name}"] - next if description.blank? || @chunks.last(5).join.include?('—') - status.local_only = true if Status::LOCAL_ONLY_TOKENS.match?(@chunks.last) - if @chunks.first(5).any? { |c| c.strip.match?(/[\r\n]/) || c.lstrip.match?(/^(?:[>#]|```|---|\* |\d+\)|\[\wi+)/) } - @chunks << "\n\n[right]— #{description}\u200c[/right]" - else - @chunks << " [rfloat]— #{description}\u200c[/rfloat]" - end when 'media' media_idx = post_cmd[1] media_cmd = post_cmd[2] diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index cb9ca8336..42911b52a 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -30,6 +30,141 @@ class Formatter include ActionView::Helpers::TextHelper + BBCODE_TAGS = { + :url => { + :html_open => '<a href="%url%" rel="noopener nofollow" target="_blank">', :html_close => '</a>', + :description => '', :example => '', + :allow_quick_param => true, :allow_between_as_param => false, + :quick_param_format => /(\S+)/, + :quick_param_format_description => 'The size parameter \'%param%\' is incorrect, a number is expected', + :param_tokens => [{:token => :url}] + }, + :ul => { + :html_open => '<ul>', :html_close => '</ul>', + :description => '', :example => '', + }, + :ol => { + :html_open => '<ol>', :html_close => '</ol>', + :description => '', :example => '', + }, + :li => { + :html_open => '<li>', :html_close => '</li>', + :description => '', :example => '', + }, + :sub => { + :html_open => '<sub>', :html_close => '</sub>', + :description => '', :example => '', + }, + :sup => { + :html_open => '<sup>', :html_close => '</sup>', + :description => '', :example => '', + }, + :h1 => { + :html_open => '<h1>', :html_close => '</h1>', + :description => '', :example => '', + }, + :h2 => { + :html_open => '<h2>', :html_close => '</h2>', + :description => '', :example => '', + }, + :h3 => { + :html_open => '<h3>', :html_close => '</h3>', + :description => '', :example => '', + }, + :h4 => { + :html_open => '<h4>', :html_close => '</h4>', + :description => '', :example => '', + }, + :h5 => { + :html_open => '<h5>', :html_close => '</h5>', + :description => '', :example => '', + }, + :h6 => { + :html_open => '<h6>', :html_close => '</h6>', + :description => '', :example => '', + }, + :abbr => { + :html_open => '<abbr>', :html_close => '</abbr>', + :description => '', :example => '', + }, + :hr => { + :html_open => '<hr>', :html_close => '</hr>', + :description => '', :example => '', + }, + :b => { + :html_open => '<strong>', :html_close => '</strong>', + :description => '', :example => '', + }, + :i => { + :html_open => '<em>', :html_close => '</em>', + :description => '', :example => '', + }, + :flip => { + :html_open => '<span class="bbcode__flip-%direction%">', :html_close => '</span>', + :description => '', :example => '', + :allow_quick_param => true, :allow_between_as_param => false, + :quick_param_format => /(h|v)/, + :quick_param_format_description => 'The size parameter \'%param%\' is incorrect, a number is expected', + :param_tokens => [{:token => :direction}] + }, + :size => { + :html_open => '<span class="bbcode__size-%size%">', :html_close => '</span>', + :description => '', :example => '', + :allow_quick_param => true, :allow_between_as_param => false, + :quick_param_format => /([1-6])/, + :quick_param_format_description => 'The size parameter \'%param%\' is incorrect, a number is expected', + :param_tokens => [{:token => :size}] + }, + :quote => { + :html_open => '<blockquote>', :html_close => '</blockquote>', + :description => '', :example => '', + }, + :kbd => { + :html_open => '<pre><code>', :html_close => '</code></pre>', + :description => '', :example => '', + }, + :code => { + :html_open => '<pre>', :html_close => '</pre>', + :description => '', :example => '', + }, + :u => { + :html_open => '<u>', :html_close => '</u>', + :description => '', :example => '', + }, + :s => { + :html_open => '<s>', :html_close => '</s>', + :description => '', :example => '', + }, + :del => { + :html_open => '<del>', :html_close => '</del>', + :description => '', :example => '', + }, + :left => { + :html_open => '<span class="bbcode__left">', :html_close => '</span>', + :description => '', :example => '', + }, + :center => { + :html_open => '<span class="bbcode__center">', :html_close => '</span>', + :description => '', :example => '', + }, + :right => { + :html_open => '<span class="bbcode__right">', :html_close => '</span>', + :description => '', :example => '', + }, + :lfloat => { + :html_open => '<span class="bbcode__lfloat">', :html_close => '</span>', + :description => '', :example => '', + }, + :rfloat => { + :html_open => '<span class="bbcode__rfloat">', :html_close => '</span>', + :description => '', :example => '', + }, + :spoiler => { + :html_open => '<span class="bbcode__spoiler-wrapper"><span class="bbcode__spoiler">', :html_close => '</span></span>', + :description => '', :example => '', + }, + } + def format(status, **options) if status.reblog? prepend_reblog = status.reblog.account.acct @@ -57,15 +192,26 @@ class Formatter html = raw_content html = "RT @#{prepend_reblog} #{html}" if prepend_reblog - html = format_markdown(html) if status.content_type == 'text/markdown' - html = encode_and_link_urls(html, linkable_accounts, keep_html: %w(text/markdown text/html).include?(status.content_type)) + + case status.content_type + when 'text/markdown' + html = format_markdown(html) + when 'text/x-bbcode' + html = format_bbcode(html) + when 'text/x-bbcode+markdown' + html = format_bbdown(html) + end + + html = encode_and_link_urls(html, linkable_accounts, keep_html: %w(text/markdown text/x-bbcode text/x-bbcode+markdown text/html).include?(status.content_type)) html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify] - unless %w(text/markdown text/html).include?(status.content_type) + unless %w(text/markdown text/x-bbcode text/x-bbcode+markdown text/html).include?(status.content_type) html = simple_format(html, {}, sanitize: false) html = html.delete("\n") end + html = append_footer(html, status.footer) + html.html_safe # rubocop:disable Rails/OutputSafety end @@ -74,6 +220,19 @@ class Formatter html.delete("\r").delete("\n") end + def format_bbcode(html, sanitize = true) + html = bbcode_formatter(html) + html = html.gsub(/<hr>.*<\/hr>/im, '<hr />') + return html unless sanitize + html = reformat(html) + html.delete("\n") + end + + def format_bbdown(html) + html = format_bbcode(html, false) + format_markdown(html) + end + def reformat(html) sanitize(html, Sanitize::Config::MASTODON_STRICT) end @@ -134,6 +293,19 @@ class Formatter private + def append_footer(html, footer) + return html if footer.blank? + "#{html.strip}<p class=\"signature\">— #{encode(footer)}</p>" + end + + def bbcode_formatter(html) + begin + html = html.bbcode_to_html(false, BBCODE_TAGS, :enable, *BBCODE_TAGS.keys) + rescue Exception => e + end + html + end + def markdown_formatter return @markdown_formatter if defined?(@markdown_formatter) diff --git a/app/lib/sanitize_config.rb b/app/lib/sanitize_config.rb index db6f50ed1..9756f2ef6 100644 --- a/app/lib/sanitize_config.rb +++ b/app/lib/sanitize_config.rb @@ -14,6 +14,8 @@ class Sanitize next true if e =~ /^(h|p|u|dt|e)-/ # microformats classes next true if e =~ /^(mention|hashtag)$/ # semantic classes next true if e =~ /^(ellipsis|invisible)$/ # link formatting classes + next true if e =~ /^bbcode__([a-z1-6\-]+)$/ # bbcode + next true if e == 'signature' end node['class'] = class_list.join(' ') @@ -23,10 +25,11 @@ class Sanitize elements: %w(p br span a abbr del pre sub sup blockquote code b strong u i em h1 h2 h3 h4 h5 h6 ul ol li hr), attributes: { - 'a' => %w(href rel class title), + 'a' => %w(href rel class title alt), 'span' => %w(class), 'abbr' => %w(title), 'blockquote' => %w(cite), + 'p' => %w(class), }, add_attributes: { |