thredded 0.14.4 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+

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