thredded 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -4
- data/app/helpers/thredded/urls_helper.rb +2 -0
- data/app/view_models/thredded/topics_page_view.rb +1 -0
- data/bin/run_specs_repeatedly +9 -0
- data/lib/thredded/collection_to_strings_with_cache_renderer.rb +29 -39
- data/lib/thredded/compat.rb +0 -6
- data/lib/thredded/content_formatter.rb +11 -18
- data/lib/thredded/db_tools.rb +1 -5
- data/lib/thredded/version.rb +1 -1
- metadata +8 -14
- data/lib/thredded/rails_lt_5_2_arel_case_node.rb +0 -119
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19cde941264a9f9b9427694c27cc5f2a668fd18debbfe459d3fc58087e5636bf
|
4
|
+
data.tar.gz: 0d4eec1e395f2265783f9283ad958ec2a7f486a017bb961af87b26c2fd711c20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7d6aa4fd6d1eaecda06e839b757d6fa2bbf7fd24ae6ef4ba3c238a5d8880baeff1be6b9ee2aae21b34c8f844d0aa5eb5c41a1f70e7841cbe867a900e29b980a
|
7
|
+
data.tar.gz: 04af99833299683e35b13468e957bd75880a1627db1ff6c9ab53e1678f99842b273cc50ed529c9cddeedb7600c0d54b404550fd8858a7901346d6c72df77bdb2
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Thredded [![Code Climate](https://codeclimate.com/github/thredded/thredded/badges/gpa.svg)](https://codeclimate.com/github/thredded/thredded) [![Travis-CI](https://api.travis-ci.org/thredded/thredded.svg?branch=main)](https://travis-ci.org/thredded/thredded/) [![Test Coverage](https://codeclimate.com/github/thredded/thredded/badges/coverage.svg)](https://codeclimate.com/github/thredded/thredded/coverage) [![Inline docs](http://inch-ci.org/github/thredded/thredded.svg?branch=main)](http://inch-ci.org/github/thredded/thredded) [![Gitter](https://badges.gitter.im/thredded/thredded.svg)](https://gitter.im/thredded/thredded?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
2
2
|
|
3
|
-
_Thredded_ is a Rails
|
3
|
+
_Thredded_ is a Rails 6.0+ forum/messageboard engine. Its goal is to be as simple and feature rich as possible.
|
4
4
|
|
5
5
|
Some of the features currently in Thredded:
|
6
6
|
|
@@ -38,6 +38,7 @@ Table of Contents
|
|
38
38
|
* [Adding Thredded to an existing Rails app](#adding-thredded-to-an-existing-rails-app)
|
39
39
|
* [Upgrading an existing install](#upgrading-an-existing-install)
|
40
40
|
* [Migrating from Forem](#migrating-from-forem)
|
41
|
+
* [Rails compatibility](#rails-compatibility)
|
41
42
|
* [Views and other assets](#views-and-other-assets)
|
42
43
|
* [Standalone layout](#standalone-layout)
|
43
44
|
* [Application layout](#application-layout)
|
@@ -96,7 +97,7 @@ Then, see the rest of this Readme for more information about using and customizi
|
|
96
97
|
Add the gem to your Gemfile:
|
97
98
|
|
98
99
|
```ruby
|
99
|
-
gem 'thredded', '~> 1.
|
100
|
+
gem 'thredded', '~> 1.1'
|
100
101
|
```
|
101
102
|
|
102
103
|
Add the Thredded [initializer] to your parent app by running the install generator.
|
@@ -155,6 +156,15 @@ to Thredded.
|
|
155
156
|
[forem-to-thredded]: https://github.com/thredded/thredded/wiki/Migrate-from-Forem
|
156
157
|
[Forem]: https://github.com/rubysherpas/forem
|
157
158
|
|
159
|
+
## Rails compatibility
|
160
|
+
|
161
|
+
| Rails | Latest Thredded |
|
162
|
+
| ------------- |------------------|
|
163
|
+
| Rails 6.0+ | Thredded 1.1+ |
|
164
|
+
| Rails 5.2 | Thredded 1.0.1 |
|
165
|
+
| Rails 4.2 | Thredded 0.16.16 |
|
166
|
+
|
167
|
+
|
158
168
|
## Views and other assets
|
159
169
|
|
160
170
|
### Standalone layout
|
@@ -596,8 +606,6 @@ Rails.application.config.to_prepare do
|
|
596
606
|
Thredded::ApplicationController.module_eval do
|
597
607
|
# Require authentication to access the forums:
|
598
608
|
before_action :thredded_require_login!
|
599
|
-
# NB: in rails 4.2 you will need to change this to:
|
600
|
-
# before_action { thredded_require_login! }
|
601
609
|
|
602
610
|
# You may also want to render a login form after the
|
603
611
|
# "Please sign in first" message:
|
@@ -47,7 +47,8 @@ module Thredded
|
|
47
47
|
|
48
48
|
ordered_keys.map do |cache_key|
|
49
49
|
[keyed_collection[cache_key], cached_partials[cache_key] || rendered_partials.next.tap do |rendered|
|
50
|
-
|
50
|
+
cache.write(cache_key, rendered, expires_in: expires_in)
|
51
|
+
cached_partials[cache_key] = rendered
|
51
52
|
end]
|
52
53
|
end
|
53
54
|
end
|
@@ -82,18 +83,29 @@ module Thredded
|
|
82
83
|
else
|
83
84
|
collection.each_slice(collection.size / num_threads).map do |slice|
|
84
85
|
Thread.start do
|
85
|
-
# `ActionView::PartialRenderer` mutates the contents of `opts[:locals]`, `opts[:locals][:as]` in particular:
|
86
|
-
# https://github.com/rails/rails/blob/v6.0.2.1/actionview/lib/action_view/renderer/partial_renderer.rb#L379
|
87
|
-
# https://github.com/rails/rails/blob/v6.0.2.1/actionview/lib/action_view/renderer/partial_renderer.rb#L348-L356
|
88
|
-
opts[:locals] = opts[:locals].dup if opts[:locals]
|
89
86
|
ActiveRecord::Base.connection_pool.with_connection do
|
90
|
-
render_partials_serial(view_context.dup, slice, opts)
|
87
|
+
render_partials_serial(view_context.dup, slice, dup_opts(opts))
|
91
88
|
end
|
92
89
|
end
|
93
90
|
end.flat_map(&:value)
|
94
91
|
end
|
95
92
|
end
|
96
93
|
|
94
|
+
# `ActionView::PartialRenderer` mutates the contents of `opts[:locals]`, `opts[:locals][:as]` in particular:
|
95
|
+
# https://github.com/rails/rails/blob/v6.0.2.1/actionview/lib/action_view/renderer/partial_renderer.rb#L379
|
96
|
+
# https://github.com/rails/rails/blob/v6.0.2.1/actionview/lib/action_view/renderer/partial_renderer.rb#L348-L356
|
97
|
+
def dup_opts(opts)
|
98
|
+
if opts[:locals]
|
99
|
+
opts = opts.dup
|
100
|
+
# sometimes have a thread safe :users_provider, preserve that for performance reasons
|
101
|
+
# hence not doing a deep_dup
|
102
|
+
opts[:locals] = opts[:locals].dup
|
103
|
+
opts
|
104
|
+
else
|
105
|
+
opts.dup
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
97
109
|
if Thredded::Compat.rails_gte_61?
|
98
110
|
# @param [Array<Object>] collection
|
99
111
|
# @param [Hash] opts
|
@@ -121,42 +133,20 @@ module Thredded
|
|
121
133
|
view.combined_fragment_cache_key(key)
|
122
134
|
end
|
123
135
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
view.cache_fragment_name(key, virtual_path: virtual_path, digest_path: digest_path)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def digest_path_from_template(view, template)
|
134
|
-
view.digest_path_from_template(template)
|
135
|
-
end
|
136
|
-
|
137
|
-
def render_partial(partial_renderer, view_context, opts)
|
138
|
-
partial_renderer.render(view_context, opts, nil).body
|
139
|
-
end
|
140
|
-
else
|
141
|
-
def cache_fragment_name(_view, key, virtual_path:, digest_path:)
|
142
|
-
if digest_path
|
143
|
-
["#{virtual_path}:#{digest_path}", key]
|
144
|
-
else
|
145
|
-
[virtual_path, key]
|
146
|
-
end
|
136
|
+
def cache_fragment_name(view, key, virtual_path:, digest_path:)
|
137
|
+
if Thredded::Compat.rails_gte_61?
|
138
|
+
view.cache_fragment_name(key, digest_path: digest_path)
|
139
|
+
else
|
140
|
+
view.cache_fragment_name(key, virtual_path: virtual_path, digest_path: digest_path)
|
147
141
|
end
|
142
|
+
end
|
148
143
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
finder: @lookup_context,
|
153
|
-
dependencies: view.view_cache_dependencies
|
154
|
-
).presence
|
155
|
-
end
|
144
|
+
def digest_path_from_template(view, template)
|
145
|
+
view.digest_path_from_template(template)
|
146
|
+
end
|
156
147
|
|
157
|
-
|
158
|
-
|
159
|
-
end
|
148
|
+
def render_partial(partial_renderer, view_context, opts)
|
149
|
+
partial_renderer.render(view_context, opts, nil).body
|
160
150
|
end
|
161
151
|
end
|
162
152
|
end
|
data/lib/thredded/compat.rb
CHANGED
@@ -3,12 +3,6 @@
|
|
3
3
|
module Thredded
|
4
4
|
module Compat
|
5
5
|
class << self
|
6
|
-
# @api private
|
7
|
-
def rails_gte_60?
|
8
|
-
@rails_gte_60 = (Rails.gem_version >= Gem::Version.new('6.0.0')) if @rails_gte_60.nil?
|
9
|
-
@rails_gte_60
|
10
|
-
end
|
11
|
-
|
12
6
|
# @api private
|
13
7
|
def rails_gte_61?
|
14
8
|
@rails_gte_61 = (Rails.gem_version >= Gem::Version.new('6.1.0')) if @rails_gte_61.nil?
|
@@ -8,7 +8,15 @@ module Thredded
|
|
8
8
|
attr_accessor :allowlist
|
9
9
|
|
10
10
|
# TODO: v2.0: drop alias and just use allowlist
|
11
|
-
|
11
|
+
# @deprecated use allowlist
|
12
|
+
def whitelist
|
13
|
+
ActiveSupport::Deprecation.warn(<<~MESSAGE.squish)
|
14
|
+
ContentFormatter.whitelist is deprecated and will be removed in Thredded 2.0.
|
15
|
+
Use ContentFormatter.allowlist instead
|
16
|
+
MESSAGE
|
17
|
+
|
18
|
+
allowlist
|
19
|
+
end
|
12
20
|
|
13
21
|
# Filters that run before processing the markup.
|
14
22
|
# input: markup, output: markup.
|
@@ -30,17 +38,8 @@ module Thredded
|
|
30
38
|
# input: sanitized html, output: html
|
31
39
|
attr_accessor :after_sanitization_filters
|
32
40
|
|
33
|
-
# TODO: v1.1: only allow html-pipeline >= 2.14.1 and drop this
|
34
|
-
def sanitization_filter_uses_allowlist?
|
35
|
-
defined?(HTML::Pipeline::SanitizationFilter::ALLOWLIST)
|
36
|
-
end
|
37
|
-
|
38
41
|
def sanitization_filter_allowlist_config
|
39
|
-
|
40
|
-
HTML::Pipeline::SanitizationFilter::ALLOWLIST
|
41
|
-
else
|
42
|
-
HTML::Pipeline::SanitizationFilter::WHITELIST
|
43
|
-
end
|
42
|
+
HTML::Pipeline::SanitizationFilter::ALLOWLIST
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
@@ -150,15 +149,9 @@ module Thredded
|
|
150
149
|
|
151
150
|
# @return [Hash] options for HTML::Pipeline.new
|
152
151
|
def content_pipeline_options
|
153
|
-
option = if self.class.sanitization_filter_uses_allowlist?
|
154
|
-
:allowlist
|
155
|
-
else
|
156
|
-
# TODO: v1.1: only allow html-pipeline >= 2.14.1 and drop this
|
157
|
-
:whitelist
|
158
|
-
end
|
159
152
|
{
|
160
153
|
asset_root: Rails.application.config.action_controller.asset_host || '',
|
161
|
-
|
154
|
+
allowlist: ContentFormatter.allowlist
|
162
155
|
}
|
163
156
|
end
|
164
157
|
end
|
data/lib/thredded/db_tools.rb
CHANGED
@@ -10,11 +10,7 @@ module Thredded
|
|
10
10
|
verbose_was = ActiveRecord::Migration.verbose
|
11
11
|
ActiveRecord::Migration.verbose = !quiet
|
12
12
|
migrate =
|
13
|
-
|
14
|
-
-> { ActiveRecord::MigrationContext.new(paths, ActiveRecord::SchemaMigration).migrate(nil, &filter) }
|
15
|
-
else # Rails 5.2
|
16
|
-
-> { ActiveRecord::MigrationContext.new(paths).migrate(nil, &filter) }
|
17
|
-
end
|
13
|
+
-> { ActiveRecord::MigrationContext.new(paths, ActiveRecord::SchemaMigration).migrate(nil, &filter) }
|
18
14
|
if quiet
|
19
15
|
silence_active_record(&migrate)
|
20
16
|
else
|
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: 1.0
|
4
|
+
version: 1.1.0
|
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:
|
12
|
+
date: 2023-02-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: active_record_union
|
@@ -127,20 +127,14 @@ dependencies:
|
|
127
127
|
name: rails
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
129
129
|
requirements:
|
130
|
-
- - "
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
version: 5.2.0
|
133
|
-
- - "!="
|
130
|
+
- - ">"
|
134
131
|
- !ruby/object:Gem::Version
|
135
132
|
version: 6.0.0.rc2
|
136
133
|
type: :runtime
|
137
134
|
prerelease: false
|
138
135
|
version_requirements: !ruby/object:Gem::Requirement
|
139
136
|
requirements:
|
140
|
-
- - "
|
141
|
-
- !ruby/object:Gem::Version
|
142
|
-
version: 5.2.0
|
143
|
-
- - "!="
|
137
|
+
- - ">"
|
144
138
|
- !ruby/object:Gem::Version
|
145
139
|
version: 6.0.0.rc2
|
146
140
|
- !ruby/object:Gem::Dependency
|
@@ -163,14 +157,14 @@ dependencies:
|
|
163
157
|
requirements:
|
164
158
|
- - ">="
|
165
159
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
160
|
+
version: 2.14.1
|
167
161
|
type: :runtime
|
168
162
|
prerelease: false
|
169
163
|
version_requirements: !ruby/object:Gem::Requirement
|
170
164
|
requirements:
|
171
165
|
- - ">="
|
172
166
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
167
|
+
version: 2.14.1
|
174
168
|
- !ruby/object:Gem::Dependency
|
175
169
|
name: kramdown
|
176
170
|
requirement: !ruby/object:Gem::Requirement
|
@@ -634,7 +628,7 @@ dependencies:
|
|
634
628
|
- !ruby/object:Gem::Version
|
635
629
|
version: '0'
|
636
630
|
description: |-
|
637
|
-
The best Rails
|
631
|
+
The best Rails 6.0+ forums engine ever. Its goal is to be as simple and feature rich as possible.
|
638
632
|
Thredded works with SQLite, MySQL (v5.6.4+), and PostgreSQL. See the demo at https://thredded.org/.
|
639
633
|
email:
|
640
634
|
- joel@thredded.com
|
@@ -985,6 +979,7 @@ files:
|
|
985
979
|
- bin/create_migration_fixture
|
986
980
|
- bin/rails
|
987
981
|
- bin/rubocop
|
982
|
+
- bin/run_specs_repeatedly
|
988
983
|
- config/i18n-tasks.yml
|
989
984
|
- config/locales/de.yml
|
990
985
|
- config/locales/en.yml
|
@@ -1034,7 +1029,6 @@ files:
|
|
1034
1029
|
- lib/thredded/html_pipeline/spoiler_tag_filter.rb
|
1035
1030
|
- lib/thredded/html_pipeline/utils.rb
|
1036
1031
|
- lib/thredded/html_pipeline/wrap_iframes_filter.rb
|
1037
|
-
- lib/thredded/rails_lt_5_2_arel_case_node.rb
|
1038
1032
|
- lib/thredded/users_provider.rb
|
1039
1033
|
- lib/thredded/version.rb
|
1040
1034
|
- lib/thredded/view_hooks/config.rb
|
@@ -1,119 +0,0 @@
|
|
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 Naming/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 Naming/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 Naming/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 Naming/MethodName
|
114
|
-
collector << 'ELSE '
|
115
|
-
visit o.expr, collector
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|