thredded 0.14.4 → 0.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/app/assets/javascripts/thredded/components/preview_area.es6 +3 -0
- data/app/assets/javascripts/thredded/components/spoilers.es6 +37 -0
- data/app/assets/stylesheets/thredded/_email.scss +25 -0
- data/app/assets/stylesheets/thredded/_thredded.scss +1 -0
- data/app/assets/stylesheets/thredded/base/_typography.scss +1 -1
- data/app/assets/stylesheets/thredded/base/_variables.scss +2 -3
- data/app/assets/stylesheets/thredded/components/_post.scss +0 -11
- data/app/assets/stylesheets/thredded/components/_spoiler.scss +41 -0
- data/app/commands/thredded/mark_all_read.rb +1 -7
- data/app/controllers/concerns/thredded/new_post_params.rb +1 -1
- data/app/controllers/concerns/thredded/new_private_post_params.rb +1 -1
- data/app/controllers/concerns/thredded/new_private_topic_params.rb +1 -2
- data/app/controllers/concerns/thredded/new_topic_params.rb +0 -1
- data/app/controllers/thredded/application_controller.rb +10 -0
- data/app/controllers/thredded/posts_controller.rb +1 -2
- data/app/controllers/thredded/private_posts_controller.rb +1 -2
- data/app/controllers/thredded/private_topics_controller.rb +10 -12
- data/app/controllers/thredded/topics_controller.rb +14 -17
- data/app/forms/thredded/edit_topic_form.rb +2 -1
- data/app/forms/thredded/post_form.rb +3 -1
- data/app/forms/thredded/private_post_form.rb +3 -1
- data/app/forms/thredded/private_topic_form.rb +1 -0
- data/app/jobs/thredded/activity_updater_job.rb +18 -8
- data/app/jobs/thredded/auto_follow_and_notify_job.rb +2 -1
- data/app/models/concerns/thredded/post_common.rb +3 -4
- data/app/models/concerns/thredded/topic_common.rb +7 -0
- data/app/models/concerns/thredded/user_topic_read_state_common.rb +62 -5
- data/app/models/thredded/null_user_topic_read_state.rb +8 -0
- data/app/policies/thredded/private_post_policy.rb +16 -0
- data/app/view_hooks/thredded/all_view_hooks.rb +3 -0
- data/app/view_models/thredded/base_topic_view.rb +5 -1
- data/app/view_models/thredded/post_view.rb +13 -1
- data/app/view_models/thredded/posts_page_view.rb +1 -1
- data/app/view_models/thredded/topic_posts_page_view.rb +13 -1
- data/app/views/thredded/posts/_post.html.erb +1 -0
- data/app/views/thredded/posts/edit.html.erb +1 -0
- data/app/views/thredded/posts_common/_before_first_unread_post.html.erb +7 -0
- data/app/views/thredded/posts_common/form/_after_content.html.erb +8 -0
- data/app/views/thredded/posts_common/form/_before_content.html.erb +8 -0
- data/app/views/thredded/private_posts/_private_post.html.erb +2 -1
- data/app/views/thredded/private_posts/edit.html.erb +1 -0
- data/app/views/thredded/private_topics/_form.html.erb +1 -0
- data/app/views/thredded/private_topics/edit.html.erb +2 -1
- data/app/views/thredded/shared/_field_errors.html.erb +3 -0
- data/app/views/thredded/shared/_nav.html.erb +1 -1
- data/app/views/thredded/shared/_page.html.erb +1 -1
- data/app/views/thredded/topics/_form.html.erb +1 -0
- data/app/views/thredded/topics/edit.html.erb +2 -1
- data/config/locales/de.yml +2 -0
- data/config/locales/en.yml +2 -0
- data/config/locales/es.yml +2 -0
- data/config/locales/fr.yml +2 -0
- data/config/locales/it.yml +2 -0
- data/config/locales/pl.yml +2 -0
- data/config/locales/pt-BR.yml +2 -0
- data/config/locales/ru.yml +2 -0
- data/config/locales/zh-CN.yml +2 -0
- data/db/migrate/20160329231848_create_thredded.rb +37 -23
- data/db/upgrade_migrations/{20170811090735_upgrade_thredded_v0_13_to_v_014.rb → 20170811090735_upgrade_thredded_v0_13_to_v0_14.rb} +0 -0
- data/db/upgrade_migrations/20180110200009_upgrade_thredded_v0_14_to_v0_15.rb +91 -0
- data/lib/generators/thredded/install/templates/initializer.rb +16 -7
- data/lib/thredded.rb +143 -125
- data/lib/thredded/arel_compat.rb +57 -0
- data/lib/thredded/base_migration.rb +10 -0
- data/lib/thredded/collection_to_strings_with_cache_renderer.rb +35 -9
- data/lib/thredded/content_formatter.rb +27 -18
- data/lib/thredded/database_seeder.rb +218 -64
- data/lib/thredded/email_transformer.rb +5 -2
- data/lib/thredded/email_transformer/spoiler.rb +25 -0
- data/lib/thredded/formatting_demo_content.rb +12 -0
- data/lib/thredded/html_pipeline/onebox_filter.rb +3 -38
- data/lib/thredded/html_pipeline/spoiler_tag_filter.rb +128 -0
- data/lib/thredded/html_pipeline/utils.rb +47 -0
- data/lib/thredded/rails_lt_5_2_arel_case_node.rb +119 -0
- data/lib/thredded/version.rb +1 -1
- metadata +17 -21
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'thredded/email_transformer/onebox'
|
4
|
+
require 'thredded/email_transformer/spoiler'
|
4
5
|
|
5
6
|
module Thredded
|
6
7
|
# This transformer should applied to emails so that they render correctly in the email clients.
|
@@ -11,8 +12,10 @@ module Thredded
|
|
11
12
|
# Rails.application.config.roadie.before_transformation = Thredded::EmailTransformer
|
12
13
|
#
|
13
14
|
module EmailTransformer
|
14
|
-
|
15
|
-
|
15
|
+
class << self
|
16
|
+
attr_accessor :transformers
|
17
|
+
end
|
18
|
+
@transformers = [Onebox, Spoiler]
|
16
19
|
|
17
20
|
# @param doc [Nokogiri::HTML::Document]
|
18
21
|
def self.call(doc)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thredded/email_transformer/base'
|
4
|
+
module Thredded
|
5
|
+
module EmailTransformer
|
6
|
+
# Changes the spoiler tags to work in emails.
|
7
|
+
class Spoiler < Base
|
8
|
+
def call
|
9
|
+
doc.css('.thredded--post--content--spoiler--summary').each do |node|
|
10
|
+
node.content = I18n.t('thredded.posts.spoiler_summary_for_email')
|
11
|
+
end
|
12
|
+
doc.css('.thredded--post--content--spoiler--contents img').each do |img|
|
13
|
+
text = "#{img['src']} #{" (#{img['alt']})" if img['alt'].present?}"
|
14
|
+
img.swap(
|
15
|
+
if img.parent.name == 'a' && img.parent.children.size == 1
|
16
|
+
doc.document.create_text_node(text)
|
17
|
+
else
|
18
|
+
doc.document.create_element('a', text, href: img['src'], target: '_blank')
|
19
|
+
end
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -8,6 +8,18 @@ module Thredded
|
|
8
8
|
end
|
9
9
|
self.parts = [
|
10
10
|
<<-'MARKDOWN',
|
11
|
+
#### Spoilers
|
12
|
+
|
13
|
+
Use `<spoiler></spoiler>` tags to create spoiler boxes like this one:
|
14
|
+
|
15
|
+
<spoiler>
|
16
|
+
Harry Potter books are better than the movies.
|
17
|
+
|
18
|
+
![nyancat](https://storage.googleapis.com/glebm-stuff/nyancat.gif)
|
19
|
+
|
20
|
+
https://www.youtube.com/watch?v=5lBBUPVuusM
|
21
|
+
</spoiler>
|
22
|
+
|
11
23
|
#### Oneboxes
|
12
24
|
|
13
25
|
URLs of supported resources are replaced with boxes like these:
|
@@ -5,6 +5,8 @@ require 'onebox'
|
|
5
5
|
module Thredded
|
6
6
|
module HtmlPipeline
|
7
7
|
class OneboxFilter < ::HTML::Pipeline::Filter
|
8
|
+
include ::Thredded::HtmlPipeline::Utils
|
9
|
+
|
8
10
|
SANITIZE_CONFIG = Sanitize::Config.merge(
|
9
11
|
Sanitize::Config::ONEBOX,
|
10
12
|
attributes: {
|
@@ -51,7 +53,7 @@ module Thredded
|
|
51
53
|
next unless url.present? && url == element.content && on_its_own_line?(element)
|
52
54
|
onebox_html = render_onebox_with_cache(url)
|
53
55
|
next if onebox_html.empty?
|
54
|
-
|
56
|
+
extract_block_from_paragraph! element
|
55
57
|
element.swap onebox_html
|
56
58
|
end
|
57
59
|
doc
|
@@ -101,43 +103,6 @@ module Thredded
|
|
101
103
|
nodes.take_while { |node| !node_name?(node, 'br') }
|
102
104
|
.all? { |node| node.text? && node.blank? }
|
103
105
|
end
|
104
|
-
|
105
|
-
def fixup_paragraph!(element)
|
106
|
-
# Can't have a div inside a paragraph, so split the paragraph
|
107
|
-
p = element.parent
|
108
|
-
return unless node_name?(p, 'p')
|
109
|
-
children_after = p.children[p.children.index(element) + 1..-1]
|
110
|
-
remove_leading_blanks! children_after
|
111
|
-
# Move the onebox out of and after the paragraph
|
112
|
-
p.add_next_sibling element
|
113
|
-
# Move all the elements after the onebox to a new paragraph
|
114
|
-
unless children_after.empty?
|
115
|
-
new_p = Nokogiri::XML::Node.new 'p', doc
|
116
|
-
element.add_next_sibling new_p
|
117
|
-
children_after.each { |child| new_p.add_child child }
|
118
|
-
end
|
119
|
-
# The original paragraph might have been split just after a <br> or whitespace, remove them if so:
|
120
|
-
remove_leading_blanks! p.children.reverse
|
121
|
-
p.remove if p.children.empty?
|
122
|
-
end
|
123
|
-
|
124
|
-
# @param children [Nokogiri::XML::NodeSet]
|
125
|
-
def remove_leading_blanks!(children)
|
126
|
-
to_remove = children.take_while do |c|
|
127
|
-
if node_name?(c, 'br') || c.text? && c.content.blank?
|
128
|
-
c.remove
|
129
|
-
true
|
130
|
-
else
|
131
|
-
c.content = c.content.lstrip
|
132
|
-
false
|
133
|
-
end
|
134
|
-
end
|
135
|
-
to_remove.each { |c| children.delete(c) }
|
136
|
-
end
|
137
|
-
|
138
|
-
def node_name?(node, node_name)
|
139
|
-
node && node.node_name && node.node_name.casecmp(node_name).zero?
|
140
|
-
end
|
141
106
|
end
|
142
107
|
end
|
143
108
|
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thredded
|
4
|
+
module HtmlPipeline
|
5
|
+
module SpoilerTagFilter
|
6
|
+
PLACEHOLDER_START_CLASS = 'thredded-spoiler-placeholder-start-24uob7bajv5'
|
7
|
+
PLACEHOLDER_END_CLASS = 'thredded-spoiler-placeholder-end-24uob7bajv5'
|
8
|
+
PLACEHOLDER_START_BLOCK = "<p class='#{PLACEHOLDER_START_CLASS}' title='%s'></p>"
|
9
|
+
PLACEHOLDER_END_BLOCK = "<p class='#{PLACEHOLDER_END_CLASS}' title='%s'></p>"
|
10
|
+
PLACEHOLDER_START_SPAN = "<i class='#{PLACEHOLDER_START_CLASS}' title='%s'></i>"
|
11
|
+
PLACEHOLDER_END_SPAN = "<i class='#{PLACEHOLDER_END_CLASS}' title='%s'></i>"
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# @return [[[String, String]]] Pairs of opening and closing spoiler tags.
|
15
|
+
attr_reader :spoiler_tags
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
attr_reader :spoiler_tags_replacements
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
attr_reader :spoiler_tags_inverse_replacements
|
22
|
+
|
23
|
+
# @param [[[String, String]]] spoiler_tags
|
24
|
+
def spoiler_tags=(spoiler_tags)
|
25
|
+
@spoiler_tags = spoiler_tags.freeze
|
26
|
+
@spoiler_tags_replacements = spoiler_tags.flat_map.with_index do |(open, close), i|
|
27
|
+
[[/((?:\A|\r?\n|>)[ ]*)#{Regexp.escape(open)}(?=[ \t]*\r?(?:\n|\z))/, "\\1#{PLACEHOLDER_START_BLOCK % i}"],
|
28
|
+
[/((?:\A|\r?\n|>)[ ]*)#{Regexp.escape(close)}(?=[ \t]*\r?(?:\n|\z))/, "\\1#{PLACEHOLDER_END_BLOCK % i}"],
|
29
|
+
[open, PLACEHOLDER_START_SPAN % i],
|
30
|
+
[close, PLACEHOLDER_END_SPAN % i]]
|
31
|
+
end
|
32
|
+
@spoiler_tags_inverse_replacements = spoiler_tags.flat_map.with_index do |(open, close), i|
|
33
|
+
[[PLACEHOLDER_START_BLOCK % i, open],
|
34
|
+
[PLACEHOLDER_END_BLOCK % i, close],
|
35
|
+
[PLACEHOLDER_START_SPAN % i, open],
|
36
|
+
[PLACEHOLDER_END_SPAN % i, close]]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
self.spoiler_tags = [
|
42
|
+
%w[<spoiler> </spoiler>],
|
43
|
+
].freeze
|
44
|
+
|
45
|
+
class BeforeMarkup < ::HTML::Pipeline::Filter
|
46
|
+
def call
|
47
|
+
@html = +html # Unfreeze
|
48
|
+
SpoilerTagFilter.spoiler_tags_replacements.each do |(pattern, replacement)|
|
49
|
+
html.gsub! pattern, replacement
|
50
|
+
end
|
51
|
+
html
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class AfterMarkup < ::HTML::Pipeline::Filter
|
56
|
+
include ::Thredded::HtmlPipeline::Utils
|
57
|
+
|
58
|
+
SPOILER_START = [PLACEHOLDER_START_BLOCK, PLACEHOLDER_START_SPAN].freeze
|
59
|
+
SPOILER_END = [PLACEHOLDER_END_BLOCK, PLACEHOLDER_END_SPAN].freeze
|
60
|
+
|
61
|
+
def call
|
62
|
+
doc.css(".#{PLACEHOLDER_START_CLASS}").each do |placeholder_start|
|
63
|
+
process(placeholder_start)
|
64
|
+
end
|
65
|
+
doc.search('.//text()').each do |node|
|
66
|
+
content = +node.content # Unfreeze
|
67
|
+
SpoilerTagFilter.spoiler_tags_inverse_replacements.each do |(pattern, replacement)|
|
68
|
+
content.gsub! pattern, replacement
|
69
|
+
end
|
70
|
+
node.content = content
|
71
|
+
end
|
72
|
+
doc
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
# @param [Nokogiri::XML::Document] document
|
78
|
+
# @param [Array<Nokogiri::XML::Node>] children
|
79
|
+
def build_spoiler_tag(document, children)
|
80
|
+
document.create_element(
|
81
|
+
'div',
|
82
|
+
class: 'thredded--post--content--spoiler',
|
83
|
+
tabindex: 0,
|
84
|
+
role: 'figure',
|
85
|
+
'aria-expanded' => 'false',
|
86
|
+
) << document.create_element(
|
87
|
+
'div',
|
88
|
+
I18n.t('thredded.posts.spoiler_summary'),
|
89
|
+
class: 'thredded--post--content--spoiler--summary',
|
90
|
+
'aria-hidden' => 'false',
|
91
|
+
) << document.create_element(
|
92
|
+
'div',
|
93
|
+
class: 'thredded--post--content--spoiler--contents',
|
94
|
+
'aria-hidden' => 'true',
|
95
|
+
) { |contents_tag| children.each { |child| contents_tag.add_child child } }
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def process(placeholder_start)
|
101
|
+
placeholder_end, children = find_placeholder_end(placeholder_start)
|
102
|
+
placeholder_start.remove
|
103
|
+
return if !placeholder_end || children.empty?
|
104
|
+
spoiler_tag = placeholder_end.replace(build_spoiler_tag(doc.document, children))
|
105
|
+
extract_block_from_paragraph! spoiler_tag
|
106
|
+
spoiler_tag
|
107
|
+
end
|
108
|
+
|
109
|
+
def find_placeholder_end(sibling)
|
110
|
+
children = []
|
111
|
+
placeholder_end = nil
|
112
|
+
loop do
|
113
|
+
sibling = sibling.next_sibling
|
114
|
+
break if sibling.nil?
|
115
|
+
if sibling[:class] == PLACEHOLDER_START_CLASS
|
116
|
+
sibling = process(sibling) || sibling
|
117
|
+
elsif sibling[:class] == PLACEHOLDER_END_CLASS
|
118
|
+
placeholder_end = sibling
|
119
|
+
break
|
120
|
+
end
|
121
|
+
children << sibling
|
122
|
+
end
|
123
|
+
[placeholder_end, children]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thredded
|
4
|
+
module HtmlPipeline
|
5
|
+
module Utils
|
6
|
+
private
|
7
|
+
|
8
|
+
# If the given block element is contained in a paragraph, splits the paragraph and removes unnecessary whitespace.
|
9
|
+
# @param [Nokogiri::HTML::Node] element the block element that may be inside a paragraph.
|
10
|
+
def extract_block_from_paragraph!(element)
|
11
|
+
p = element.parent
|
12
|
+
return unless node_name?(p, 'p')
|
13
|
+
children_after = p.children[p.children.index(element) + 1..-1]
|
14
|
+
remove_leading_blanks! children_after
|
15
|
+
# Move the element out of and after the paragraph
|
16
|
+
p.add_next_sibling element
|
17
|
+
# Move all the elements after the onebox to a new paragraph
|
18
|
+
unless children_after.empty?
|
19
|
+
new_p = Nokogiri::XML::Node.new 'p', doc
|
20
|
+
element.add_next_sibling new_p
|
21
|
+
children_after.each { |child| new_p.add_child child }
|
22
|
+
end
|
23
|
+
# The original paragraph might have been split just after a <br> or whitespace, remove them if so:
|
24
|
+
remove_leading_blanks! p.children.reverse
|
25
|
+
p.remove if p.children.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param children [Nokogiri::XML::NodeSet]
|
29
|
+
def remove_leading_blanks!(children)
|
30
|
+
to_remove = children.take_while do |c|
|
31
|
+
if node_name?(c, 'br') || c.text? && c.content.blank?
|
32
|
+
c.remove
|
33
|
+
true
|
34
|
+
else
|
35
|
+
c.content = c.content.lstrip
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
to_remove.each { |c| children.delete(c) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def node_name?(node, node_name)
|
43
|
+
node && node.node_name && node.node_name.casecmp(node_name).zero?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
module Nodes
|
5
|
+
class Case < Arel::Nodes::Node
|
6
|
+
include Arel::OrderPredications
|
7
|
+
include Arel::Predications
|
8
|
+
include Arel::AliasPredication
|
9
|
+
|
10
|
+
attr_accessor :case, :conditions, :default
|
11
|
+
|
12
|
+
def initialize(expression = nil, default = nil)
|
13
|
+
@case = expression
|
14
|
+
@conditions = []
|
15
|
+
@default = default
|
16
|
+
end
|
17
|
+
|
18
|
+
def when(condition, expression = nil)
|
19
|
+
@conditions << When.new(Nodes.build_quoted(condition), expression)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def then(expression)
|
24
|
+
@conditions.last.right = Nodes.build_quoted(expression)
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def else(expression)
|
29
|
+
@default = Else.new Nodes.build_quoted(expression)
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize_copy(other)
|
34
|
+
super
|
35
|
+
@case = @case.clone if @case
|
36
|
+
@conditions = @conditions.map(&:clone)
|
37
|
+
@default = @default.clone if @default
|
38
|
+
end
|
39
|
+
|
40
|
+
def hash
|
41
|
+
[@case, @conditions, @default].hash
|
42
|
+
end
|
43
|
+
|
44
|
+
def eql?(other)
|
45
|
+
self.class == other.class &&
|
46
|
+
self.case == other.case &&
|
47
|
+
conditions == other.conditions &&
|
48
|
+
default == other.default
|
49
|
+
end
|
50
|
+
|
51
|
+
alias == eql?
|
52
|
+
end
|
53
|
+
|
54
|
+
class When < Binary
|
55
|
+
end
|
56
|
+
|
57
|
+
class Else < Unary
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Arel
|
63
|
+
module Visitors
|
64
|
+
class DepthFirst < Arel::Visitors::Visitor
|
65
|
+
alias visit_Arel_Nodes_Else unary
|
66
|
+
|
67
|
+
def visit_Arel_Nodes_Case(o) # rubocop:disable Style/MethodName
|
68
|
+
visit o.case
|
69
|
+
visit o.conditions
|
70
|
+
visit o.default
|
71
|
+
end
|
72
|
+
|
73
|
+
alias visit_Arel_Nodes_When binary
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module Arel
|
79
|
+
module Predications
|
80
|
+
def when(right)
|
81
|
+
Nodes::Case.new(self).when quoted_node(right)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
module Arel
|
87
|
+
module Visitors
|
88
|
+
class ToSql < Arel::Visitors::Reduce
|
89
|
+
def visit_Arel_Nodes_Case(o, collector) # rubocop:disable Style/MethodName
|
90
|
+
collector << 'CASE '
|
91
|
+
if o.case
|
92
|
+
visit o.case, collector
|
93
|
+
collector << ' '
|
94
|
+
end
|
95
|
+
o.conditions.each do |condition|
|
96
|
+
visit condition, collector
|
97
|
+
collector << ' '
|
98
|
+
end
|
99
|
+
if o.default
|
100
|
+
visit o.default, collector
|
101
|
+
collector << ' '
|
102
|
+
end
|
103
|
+
collector << 'END'
|
104
|
+
end
|
105
|
+
|
106
|
+
def visit_Arel_Nodes_When(o, collector) # rubocop:disable Style/MethodName
|
107
|
+
collector << 'WHEN '
|
108
|
+
visit o.left, collector
|
109
|
+
collector << ' THEN '
|
110
|
+
visit o.right, collector
|
111
|
+
end
|
112
|
+
|
113
|
+
def visit_Arel_Nodes_Else(o, collector) # rubocop:disable Style/MethodName
|
114
|
+
collector << 'ELSE '
|
115
|
+
visit o.expr, collector
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/thredded/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thredded
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Oliveira
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-
|
12
|
+
date: 2018-06-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pundit
|
@@ -157,14 +157,14 @@ dependencies:
|
|
157
157
|
requirements:
|
158
158
|
- - ">="
|
159
159
|
- !ruby/object:Gem::Version
|
160
|
-
version:
|
160
|
+
version: 1.17.0
|
161
161
|
type: :runtime
|
162
162
|
prerelease: false
|
163
163
|
version_requirements: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
165
|
- - ">="
|
166
166
|
- !ruby/object:Gem::Version
|
167
|
-
version:
|
167
|
+
version: 1.17.0
|
168
168
|
- !ruby/object:Gem::Dependency
|
169
169
|
name: onebox
|
170
170
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,7 +174,7 @@ dependencies:
|
|
174
174
|
version: '1.8'
|
175
175
|
- - ">="
|
176
176
|
- !ruby/object:Gem::Version
|
177
|
-
version: 1.8.
|
177
|
+
version: 1.8.48
|
178
178
|
type: :runtime
|
179
179
|
prerelease: false
|
180
180
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -184,7 +184,7 @@ dependencies:
|
|
184
184
|
version: '1.8'
|
185
185
|
- - ">="
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: 1.8.
|
187
|
+
version: 1.8.48
|
188
188
|
- !ruby/object:Gem::Dependency
|
189
189
|
name: html-pipeline
|
190
190
|
requirement: !ruby/object:Gem::Requirement
|
@@ -633,20 +633,6 @@ dependencies:
|
|
633
633
|
- - ">="
|
634
634
|
- !ruby/object:Gem::Version
|
635
635
|
version: '0'
|
636
|
-
- !ruby/object:Gem::Dependency
|
637
|
-
name: coffee-rails
|
638
|
-
requirement: !ruby/object:Gem::Requirement
|
639
|
-
requirements:
|
640
|
-
- - ">="
|
641
|
-
- !ruby/object:Gem::Version
|
642
|
-
version: '0'
|
643
|
-
type: :development
|
644
|
-
prerelease: false
|
645
|
-
version_requirements: !ruby/object:Gem::Requirement
|
646
|
-
requirements:
|
647
|
-
- - ">="
|
648
|
-
- !ruby/object:Gem::Version
|
649
|
-
version: '0'
|
650
636
|
description: |-
|
651
637
|
The best Rails 4.2+ forums engine ever. Its goal is to be as simple and feature rich as possible.
|
652
638
|
Thredded works with SQLite, MySQL (v5.6.4+), and PostgreSQL. See the demo at https://thredded.org/.
|
@@ -686,6 +672,7 @@ files:
|
|
686
672
|
- app/assets/javascripts/thredded/components/post_form.es6
|
687
673
|
- app/assets/javascripts/thredded/components/preview_area.es6
|
688
674
|
- app/assets/javascripts/thredded/components/quote_post.es6
|
675
|
+
- app/assets/javascripts/thredded/components/spoilers.es6
|
689
676
|
- app/assets/javascripts/thredded/components/time_stamps.es6
|
690
677
|
- app/assets/javascripts/thredded/components/topic_form.es6
|
691
678
|
- app/assets/javascripts/thredded/components/topics.es6
|
@@ -738,6 +725,7 @@ files:
|
|
738
725
|
- app/assets/stylesheets/thredded/components/_post.scss
|
739
726
|
- app/assets/stylesheets/thredded/components/_preferences.scss
|
740
727
|
- app/assets/stylesheets/thredded/components/_preview_area.scss
|
728
|
+
- app/assets/stylesheets/thredded/components/_spoiler.scss
|
741
729
|
- app/assets/stylesheets/thredded/components/_topic-delete.scss
|
742
730
|
- app/assets/stylesheets/thredded/components/_topic-header.scss
|
743
731
|
- app/assets/stylesheets/thredded/components/_topics.scss
|
@@ -900,6 +888,7 @@ files:
|
|
900
888
|
- app/views/thredded/posts/edit.html.erb
|
901
889
|
- app/views/thredded/posts/new.html.erb
|
902
890
|
- app/views/thredded/posts_common/_actions.html.erb
|
891
|
+
- app/views/thredded/posts_common/_before_first_unread_post.html.erb
|
903
892
|
- app/views/thredded/posts_common/_content.html.erb
|
904
893
|
- app/views/thredded/posts_common/_form.html.erb
|
905
894
|
- app/views/thredded/posts_common/_header.html.erb
|
@@ -943,6 +932,7 @@ files:
|
|
943
932
|
- app/views/thredded/shared/_breadcrumbs.html.erb
|
944
933
|
- app/views/thredded/shared/_content_moderation_blocked_state.html.erb
|
945
934
|
- app/views/thredded/shared/_currently_online.html.erb
|
935
|
+
- app/views/thredded/shared/_field_errors.html.erb
|
946
936
|
- app/views/thredded/shared/_flash_messages.html.erb
|
947
937
|
- app/views/thredded/shared/_header.html.erb
|
948
938
|
- app/views/thredded/shared/_nav.html.erb
|
@@ -995,12 +985,14 @@ files:
|
|
995
985
|
- db/upgrade_migrations/20170125033319_upgrade_v0_9_to_v0_10.rb
|
996
986
|
- db/upgrade_migrations/20170312131417_upgrade_thredded_v0_10_to_v0_11.rb
|
997
987
|
- db/upgrade_migrations/20170420163138_upgrade_thredded_v0_11_to_v0_12.rb
|
998
|
-
- db/upgrade_migrations/
|
988
|
+
- db/upgrade_migrations/20170811090735_upgrade_thredded_v0_13_to_v0_14.rb
|
989
|
+
- db/upgrade_migrations/20180110200009_upgrade_thredded_v0_14_to_v0_15.rb
|
999
990
|
- lib/generators/thredded/install/USAGE
|
1000
991
|
- lib/generators/thredded/install/install_generator.rb
|
1001
992
|
- lib/generators/thredded/install/templates/initializer.rb
|
1002
993
|
- lib/tasks/thredded_tasks.rake
|
1003
994
|
- lib/thredded.rb
|
995
|
+
- lib/thredded/arel_compat.rb
|
1004
996
|
- lib/thredded/base_migration.rb
|
1005
997
|
- lib/thredded/base_notifier.rb
|
1006
998
|
- lib/thredded/collection_to_strings_with_cache_renderer.rb
|
@@ -1010,6 +1002,7 @@ files:
|
|
1010
1002
|
- lib/thredded/email_transformer.rb
|
1011
1003
|
- lib/thredded/email_transformer/base.rb
|
1012
1004
|
- lib/thredded/email_transformer/onebox.rb
|
1005
|
+
- lib/thredded/email_transformer/spoiler.rb
|
1013
1006
|
- lib/thredded/engine.rb
|
1014
1007
|
- lib/thredded/errors.rb
|
1015
1008
|
- lib/thredded/formatting_demo_content.rb
|
@@ -1017,7 +1010,10 @@ files:
|
|
1017
1010
|
- lib/thredded/html_pipeline/autolink_filter.rb
|
1018
1011
|
- lib/thredded/html_pipeline/kramdown_filter.rb
|
1019
1012
|
- lib/thredded/html_pipeline/onebox_filter.rb
|
1013
|
+
- lib/thredded/html_pipeline/spoiler_tag_filter.rb
|
1014
|
+
- lib/thredded/html_pipeline/utils.rb
|
1020
1015
|
- lib/thredded/html_pipeline/wrap_iframes_filter.rb
|
1016
|
+
- lib/thredded/rails_lt_5_2_arel_case_node.rb
|
1021
1017
|
- lib/thredded/version.rb
|
1022
1018
|
- lib/thredded/view_hooks/config.rb
|
1023
1019
|
- lib/thredded/view_hooks/renderer.rb
|