coupdoeil 1.0.3 → 1.1.0
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/CHANGELOG.md +18 -0
- data/app/assets/javascripts/coupdoeil.js +1 -1
- data/app/assets/javascripts/coupdoeil.min.js +1 -1
- data/app/assets/javascripts/coupdoeil.min.js.map +1 -1
- data/app/controllers/coupdoeil/popovers_controller.rb +3 -2
- data/app/javascript/coupdoeil/popover/opening.js +1 -1
- data/app/models/coupdoeil/popover/options_set.rb +8 -10
- data/app/models/coupdoeil/popover.rb +42 -18
- data/app/models/coupdoeil/tag.rb +1 -1
- data/lib/coupdoeil/config.rb +53 -0
- data/lib/coupdoeil/engine.rb +19 -12
- data/lib/coupdoeil/version.rb +1 -1
- data/lib/coupdoeil.rb +9 -0
- metadata +6 -3
- data/app/models/coupdoeil/popover/view_context_delegation.rb +0 -19
@@ -12,7 +12,7 @@ module Coupdoeil
|
|
12
12
|
skip_around_action(*filters, raise: false)
|
13
13
|
|
14
14
|
def create
|
15
|
-
popover = @popover_klass.new(@popover_params,
|
15
|
+
popover = @popover_klass.new(@popover_params, self)
|
16
16
|
render plain: popover.process(@action_name), layout: false
|
17
17
|
end
|
18
18
|
|
@@ -35,7 +35,7 @@ module Coupdoeil
|
|
35
35
|
def set_popover_params
|
36
36
|
@popover_params =
|
37
37
|
if params[:params].blank?
|
38
|
-
@popover_params = {}.
|
38
|
+
@popover_params = {}.with_indifferent_access
|
39
39
|
else
|
40
40
|
raw_params = JSON.parse(params[:params])
|
41
41
|
card_params = Coupdoeil::Params.deserialize(raw_params).sole
|
@@ -44,3 +44,4 @@ module Coupdoeil
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
+
ActiveSupport.run_load_hooks(:coupdoeil_popovers_controller, Coupdoeil::PopoversController)
|
@@ -10,7 +10,7 @@ import {cancelCloseRequest, clear as clearPopover} from "./closing"
|
|
10
10
|
function fetchPopoverContent(controller) {
|
11
11
|
const type = getType(controller)
|
12
12
|
const params = getParams(controller)
|
13
|
-
const authenticityToken = document.querySelector('meta[name=csrf-token]')
|
13
|
+
const authenticityToken = document.querySelector('meta[name=csrf-token]')?.content
|
14
14
|
let url = `/coupdoeil/popover`
|
15
15
|
const opts = {
|
16
16
|
method: 'POST',
|
@@ -32,17 +32,15 @@ module Coupdoeil
|
|
32
32
|
OptionsSet.new(options.merge(options_set.options))
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
def validate!
|
36
|
+
return if Coupdoeil.config.validate_options == false || @to_base36.present?
|
37
|
+
|
38
|
+
ORDERED_OPTIONS.map do |option|
|
39
|
+
next unless options.key?(option.key)
|
40
|
+
|
41
|
+
value = options[option.key]
|
42
|
+
option.new(value).validate!
|
43
43
|
end
|
44
|
-
else
|
45
|
-
def validate! = nil # no-op
|
46
44
|
end
|
47
45
|
|
48
46
|
def to_base36
|
@@ -4,22 +4,35 @@ module Coupdoeil
|
|
4
4
|
class Popover < AbstractController::Base
|
5
5
|
abstract!
|
6
6
|
|
7
|
-
include AbstractController::
|
8
|
-
|
9
|
-
include AbstractController::Logger
|
7
|
+
include AbstractController::Caching
|
8
|
+
include AbstractController::Callbacks
|
10
9
|
include AbstractController::Helpers
|
10
|
+
include AbstractController::Logger
|
11
|
+
include AbstractController::Rendering
|
11
12
|
include AbstractController::Translation
|
12
|
-
include AbstractController::Callbacks
|
13
|
-
include AbstractController::Caching
|
14
13
|
|
15
14
|
include ActionView::Layouts
|
16
15
|
include ActionView::Rendering
|
17
16
|
|
17
|
+
include ActionController::Cookies
|
18
|
+
include ActionController::Helpers
|
19
|
+
|
20
|
+
# For forgery protection
|
21
|
+
forgery_protection_methods = [
|
22
|
+
:form_authenticity_token,
|
23
|
+
:protect_against_forgery?,
|
24
|
+
:config,
|
25
|
+
:request_forgery_protection_token,
|
26
|
+
]
|
27
|
+
delegate(*forgery_protection_methods, to: "context_controller.helpers")
|
28
|
+
helper_method forgery_protection_methods
|
29
|
+
|
18
30
|
include Rails.application.routes.url_helpers
|
19
31
|
|
20
32
|
layout "popover"
|
21
33
|
|
22
|
-
# so coupdoeil helpers are always available within popovers
|
34
|
+
# so coupdoeil helpers are always available within popovers,
|
35
|
+
# even if include_all_helpers config is set to false
|
23
36
|
helper Coupdoeil::ApplicationHelper
|
24
37
|
|
25
38
|
@registry = Registry.new
|
@@ -91,24 +104,35 @@ module Coupdoeil
|
|
91
104
|
end
|
92
105
|
end
|
93
106
|
|
94
|
-
attr_reader :params
|
107
|
+
attr_reader :params, :context_controller
|
108
|
+
|
109
|
+
helper_method :params
|
95
110
|
|
96
|
-
|
111
|
+
delegate :request, :session, to: :context_controller
|
112
|
+
|
113
|
+
# @param [HashWithIndifferentAccess] params the deserialized popover params that were given to `.with`
|
114
|
+
# @param [ActionController::Base] context_controller an instance of Coupdoeil::PopoversController or the current controller if the popover is rendered inline because of `loading: :preload` option.
|
115
|
+
def initialize(params, context_controller)
|
97
116
|
super()
|
98
117
|
@params = params
|
99
|
-
@
|
118
|
+
@context_controller = context_controller
|
100
119
|
end
|
101
120
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
def view_context
|
106
|
-
super.tap do |context|
|
107
|
-
context.extend(ViewContextDelegation)
|
108
|
-
context.popover = self
|
109
|
-
context.__cp_view_context = @__cp_view_context
|
110
|
-
end
|
121
|
+
_helpers_for_modification.define_method(:helpers) do
|
122
|
+
controller.context_controller.send(:helpers)
|
111
123
|
end
|
124
|
+
_helpers_for_modification.deprecate(
|
125
|
+
helpers: "helpers are now available in popover templates without calling helpers method. \
|
126
|
+
See documentation on helpers at https://coupdoeil.org/guides/controller-api.html#helpers.",
|
127
|
+
deprecator: Coupdoeil.deprecator,
|
128
|
+
)
|
129
|
+
|
130
|
+
def controller = context_controller
|
131
|
+
deprecate(
|
132
|
+
controller: "use self instead, helper_methods are available in popovers by default. \
|
133
|
+
See documentation on helpers at https://coupdoeil.org/guides/controller-api.html#helpers.",
|
134
|
+
deprecator: Coupdoeil.deprecator,
|
135
|
+
)
|
112
136
|
|
113
137
|
def render(...)
|
114
138
|
return super unless response_body
|
data/app/models/coupdoeil/tag.rb
CHANGED
@@ -36,7 +36,7 @@ module Coupdoeil
|
|
36
36
|
attributes.merge!("popover-type" => popover_setup.identifier, "popover-params" => params)
|
37
37
|
end
|
38
38
|
|
39
|
-
if
|
39
|
+
if Coupdoeil.config.options_html_attributes
|
40
40
|
attributes.merge!(popover_options.to_h.transform_keys { "popover-#{_1}" })
|
41
41
|
end
|
42
42
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coupdoeil
|
4
|
+
class Config
|
5
|
+
class << self
|
6
|
+
def defaults
|
7
|
+
ActiveSupport::OrderedOptions.new.merge!({
|
8
|
+
validate_options: Rails.env.local?,
|
9
|
+
options_html_attributes: Rails.env.local?,
|
10
|
+
include_all_helpers: true,
|
11
|
+
delegate_helper_methods: true,
|
12
|
+
})
|
13
|
+
end
|
14
|
+
|
15
|
+
# @!attribute validate_options
|
16
|
+
# @return [Boolean]
|
17
|
+
# Whether to validate popover options when building it.
|
18
|
+
# It will raise an error with a hint on how to fix it if an option's value is not valid.
|
19
|
+
# Defaults to `Rails.env.local?`.
|
20
|
+
|
21
|
+
# @!attribute options_html_attributes
|
22
|
+
# @return [Boolean]
|
23
|
+
# Whether to insert options as HTML attributes of the <coupdoeil> tag.
|
24
|
+
# This is not required for Coupdoeil to work since options are compressed to base 36 to lighten the HTML payload.
|
25
|
+
# This option is here to help for debug or testing.
|
26
|
+
# Defaults to `Rails.env.local?`.
|
27
|
+
|
28
|
+
# @!attribute include_all_helpers
|
29
|
+
# @return [Boolean]
|
30
|
+
# Whether to load all application helpers so they are available when rendering a popover.
|
31
|
+
# This mimics the default behavior of Rails.
|
32
|
+
# It is advised to set it to true so that rendering popovers is seamless compared to rendering any other template.
|
33
|
+
# For all helpers to be included it is also required that `config.action_controller.include_all_helpers` is set to true.
|
34
|
+
|
35
|
+
# @!attribute delegate_helper_methods
|
36
|
+
# @return [Boolean]
|
37
|
+
# Similarly to `include_all_helpers`, to offer a seamless experience when rendering popovers, Coupdoeil will delegate
|
38
|
+
# any helper methods defined on ApplicationController when this option is set to true.
|
39
|
+
# Such helper methods could include `current_user` from Devise or `allowed_to?` from ActionPolicy, for example.
|
40
|
+
# As these helpers are not defined on modules like other helpers, they cannot be included and their call must
|
41
|
+
# therefore be delegated to the context controller.
|
42
|
+
# If this behavior causes unexpected behavior you can disable it with this configuration option, and/or [submit an issue](https://gitlab.com/Pagehey/coupdoeil/-/issues) so it can be investigated.
|
43
|
+
# However, in absence of problem, it is still recommended to let it `true` by default.
|
44
|
+
end
|
45
|
+
# @!attribute current
|
46
|
+
# @return [Coupdoeil::Config]
|
47
|
+
# Returns the current Coupdoeil::Config. This is persisted against this
|
48
|
+
# class so that config options remain accessible before the rest of
|
49
|
+
# Coupdoeil has loaded. Defaults to an instance of Coupdoeil::Config
|
50
|
+
# with all other documented defaults set.
|
51
|
+
class_attribute :current, default: defaults, instance_predicate: false
|
52
|
+
end
|
53
|
+
end
|
data/lib/coupdoeil/engine.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "coupdoeil/config"
|
4
|
+
|
3
5
|
module Coupdoeil
|
4
6
|
class Engine < ::Rails::Engine
|
5
|
-
isolate_namespace Coupdoeil
|
6
7
|
config.eager_load_namespaces << Coupdoeil
|
7
|
-
config.coupdoeil =
|
8
|
+
config.coupdoeil = Coupdoeil::Config.current
|
8
9
|
|
9
10
|
config.autoload_once_paths = [
|
10
11
|
"#{root}/app/controllers",
|
@@ -14,8 +15,8 @@ module Coupdoeil
|
|
14
15
|
"#{root}/app/models/concerns",
|
15
16
|
]
|
16
17
|
|
17
|
-
# If you don't want to precompile Coupdoeil's assets (
|
18
|
-
# you can do this in an
|
18
|
+
# If you don't want to precompile Coupdoeil's assets (e.g. because you're using webpack),
|
19
|
+
# you can do this in an initializer:
|
19
20
|
#
|
20
21
|
# config.after_initialize do
|
21
22
|
# config.assets.precompile -= Coupdoeil::Engine::PRECOMPILE_ASSETS
|
@@ -41,16 +42,22 @@ module Coupdoeil
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
|
-
initializer "coupdoeil.
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
initializer "coupdoeil.helpers", before: :load_config_initializers do
|
46
|
+
ActiveSupport.on_load(:coupdoeil_popovers_controller) do
|
47
|
+
next unless Coupdoeil.config.include_all_helpers && include_all_helpers
|
48
|
+
|
49
|
+
Coupdoeil::Popover.helpers_path = helpers_path
|
50
|
+
Coupdoeil::Popover.helper(:all) if include_all_helpers
|
51
|
+
end
|
49
52
|
end
|
50
53
|
|
51
|
-
initializer "coupdoeil.
|
52
|
-
ActiveSupport.on_load(:
|
53
|
-
|
54
|
+
initializer "coupdoeil.helper_methods", before: :load_config_initializers do
|
55
|
+
ActiveSupport.on_load(:coupdoeil_popovers_controller) do
|
56
|
+
next unless Coupdoeil.config.delegate_helper_methods
|
57
|
+
|
58
|
+
helpers_to_delegate = _helper_methods - Coupdoeil::Popover._helper_methods
|
59
|
+
Coupdoeil::Popover.delegate(*helpers_to_delegate, to: "context_controller.helpers", private: true)
|
60
|
+
Coupdoeil::Popover.helper_method(helpers_to_delegate)
|
54
61
|
end
|
55
62
|
end
|
56
63
|
|
data/lib/coupdoeil/version.rb
CHANGED
data/lib/coupdoeil.rb
CHANGED
@@ -5,4 +5,13 @@ require "coupdoeil/engine"
|
|
5
5
|
|
6
6
|
module Coupdoeil
|
7
7
|
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def config = Coupdoeil::Config.current
|
11
|
+
def configure = yield(Coupdoeil::Config.current)
|
12
|
+
|
13
|
+
def deprecator # :nodoc:
|
14
|
+
@deprecator ||= ActiveSupport::Deprecation.new("2.0.0", "Coupdoeil")
|
15
|
+
end
|
16
|
+
end
|
8
17
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coupdoeil
|
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
|
- PageHey
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-08-11 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: actionpack
|
@@ -178,7 +178,6 @@ files:
|
|
178
178
|
- app/models/coupdoeil/popover/options_set.rb
|
179
179
|
- app/models/coupdoeil/popover/registry.rb
|
180
180
|
- app/models/coupdoeil/popover/setup.rb
|
181
|
-
- app/models/coupdoeil/popover/view_context_delegation.rb
|
182
181
|
- app/models/coupdoeil/tag.rb
|
183
182
|
- app/style/popover-animation.scss
|
184
183
|
- app/style/popover-arrow.scss
|
@@ -186,6 +185,7 @@ files:
|
|
186
185
|
- app/views/layouts/coupdoeil/application.html.erb
|
187
186
|
- config/routes.rb
|
188
187
|
- lib/coupdoeil.rb
|
188
|
+
- lib/coupdoeil/config.rb
|
189
189
|
- lib/coupdoeil/engine.rb
|
190
190
|
- lib/coupdoeil/version.rb
|
191
191
|
- lib/generators/coupdoeil/install/install_generator.rb
|
@@ -201,6 +201,9 @@ metadata:
|
|
201
201
|
homepage_uri: https://coupdoeil.org
|
202
202
|
source_code_uri: https://gitlab.com/Pagehey/coupdoeil
|
203
203
|
changelog_uri: https://gitlab.com/Pagehey/coupdoeil/-/blob/main/CHANGELOG.md
|
204
|
+
post_install_message: |
|
205
|
+
Coupdoeil v.1.1.0 fixed the helper usage in popovers and should allow some refactoring.
|
206
|
+
See CHANGELOG for details: https://gitlab.com/Pagehey/coupdoeil/-/blob/main/CHANGELOG.md?ref_type=heads#v110
|
204
207
|
rdoc_options: []
|
205
208
|
require_paths:
|
206
209
|
- lib
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Coupdoeil
|
4
|
-
class Popover
|
5
|
-
module ViewContextDelegation
|
6
|
-
attr_accessor :__cp_view_context, :popover
|
7
|
-
|
8
|
-
# For CSRF authenticity tokens in forms
|
9
|
-
def config = __cp_view_context.config
|
10
|
-
def form_authenticity_token(...) = __cp_view_context.form_authenticity_token(...)
|
11
|
-
def protect_against_forgery? = __cp_view_context.protect_against_forgery?
|
12
|
-
def request_forgery_protection_token = __cp_view_context.request_forgery_protection_token
|
13
|
-
|
14
|
-
def helpers = __cp_view_context
|
15
|
-
def controller = __cp_view_context.controller
|
16
|
-
def params = popover.params
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|