phlexible 3.2.0 → 3.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba0c7764b691fdb2ea92f5d8ef9389e1eb31bd97483f210e1b5e8f7c9fcd0c09
4
- data.tar.gz: 80b397992cf20e11e9e971d744f6a7cea5bfa56a1b1186c4a629ec04bb836624
3
+ metadata.gz: 7d77a1775f2cf5e96455ca326a6589a00bb0400f5bf4f01f0af1268c01579e0b
4
+ data.tar.gz: b68f67d1bcc7c913177efdb1aec44fe866cde16d30fdc6215dc9760cb7ac1c3d
5
5
  SHA512:
6
- metadata.gz: 375b7283fa50d41cf9e94bdc131f5faa469d73f67c8f2f8fdf34badb6c722edf193c9d9d64ffb7fee6f565d7d2a7a853a91f2d3f4ffed901e8d8b4421b967e9b
7
- data.tar.gz: b5fba4880d3a63faca0e67fe09a422a34b12b322ae6dd73ebca5b3a4b0137db0b80f177df306f18b27942a9d57fcd1501da6a2b8d9bafc5c3f6899fa729f4b90
6
+ metadata.gz: 83a9a3082006f0ec7fcaa46fd7d492a09928c07419639ff15da929b3fb27bec5ec0576c6e2a20b3e29666899820882029b798df9d88ed6865bacc77fd80a2cf6
7
+ data.tar.gz: b615b0e6f37147e44868398f6e5180fa2f095b39300ad9f8d97d0e1f58e5981ceae1df444d6b446885c3d06f1387a1ce31b1c0522dd6e50dce149d5b445f0bc1
data/README.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  A bunch of helpers and goodies intended to make life with [Phlex](https://phlex.fun) even easier!
4
4
 
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Usage](#usage)
9
+ - [AliasView](#aliasview)
10
+ - [Callbacks](#callbacks)
11
+ - [ElementVariants](#elementvariants)
12
+ - [PageTitle](#pagetitle)
13
+ - [ProcessAttributes](#processattributes)
14
+ - [Rails::ActionController::ImplicitRender](#railsactioncontrollerimplicitrender)
15
+ - [Rails::ControllerVariables](#railscontrollervariables)
16
+ - [Rails::AutoLayout](#railsautolayout)
17
+ - [Rails::AElement](#railsaelement)
18
+ - [Rails::ButtonTo](#railsbuttonto)
19
+ - [Rails::MetaTags](#railsmetatags)
20
+ - [Rails::Responder](#railsresponder)
21
+ - [Development](#development)
22
+ - [Contributing](#contributing)
23
+ - [License](#license)
24
+ - [Code of Conduct](#code-of-conduct)
25
+
5
26
  ## Installation
6
27
 
7
28
  Install the gem and add to the application's Gemfile by executing:
@@ -14,6 +35,182 @@ If bundler is not being used to manage dependencies, install the gem by executin
14
35
 
15
36
  ## Usage
16
37
 
38
+ ### `AliasView`
39
+
40
+ Create an alias at a given `element`, to the given view class.
41
+
42
+ So instead of:
43
+
44
+ ```ruby
45
+ class MyView < Phlex::HTML
46
+ def view_template
47
+ div do
48
+ render My::Awesome::Component.new
49
+ end
50
+ end
51
+ end
52
+ ```
53
+
54
+ You can instead do:
55
+
56
+ ```ruby
57
+ class MyView < Phlex::HTML
58
+ extend Phlexible::AliasView
59
+
60
+ alias_view :awesome, -> { My::Awesome::Component }
61
+
62
+ def view_template
63
+ div do
64
+ awesome
65
+ end
66
+ end
67
+ end
68
+ ```
69
+
70
+ ### `Callbacks`
71
+
72
+ While Phlex does have `before_template`, `after_template`, and `around_template` hooks, they must be defined as regular Ruby methods, meaning you have to always remember to call `super` when redefining any hook method.
73
+
74
+ This module provides a more Rails-like interface for defining callbacks in your Phlex views, using `ActiveSupport::Callbacks`. It implements the same `before_template`, `after_template`, and `around_template` hooks as callbacks.
75
+
76
+ ```ruby
77
+ class Views::Users::Index < Views::Base
78
+ include Phlexible::Callbacks
79
+
80
+ before_template :set_title
81
+
82
+ def view_template
83
+ h1 { @title }
84
+ end
85
+
86
+ private
87
+
88
+ def set_title
89
+ @title = 'Users'
90
+ end
91
+ end
92
+ ```
93
+
94
+ You can still use the regular `before_template`, `after_template`, and `around_template` hooks as well, but I recommend that if you include this module, that you use callbacks instead.
95
+
96
+ When used with `Rails::AutoLayout`, layout callbacks (`before_layout`, `after_layout`, `around_layout`) are also available. See the `Rails::AutoLayout` section below.
97
+
98
+ ### `ElementVariants`
99
+
100
+ Declare named variants for one or more HTML elements, then apply them by passing the variant name as a Symbol (or Symbols) in the first argument to the element method. By default, each variant adds a `data-variant-<name>` attribute to the element.
101
+
102
+ Extend your view class with `Phlexible::ElementVariants` and declare variants with `variant`:
103
+
104
+ ```ruby
105
+ class MyView < Phlex::HTML
106
+ extend Phlexible::ElementVariants
107
+
108
+ variant :divider, on: [:h1, :h2, :h3, :h4, :h5, :h6]
109
+
110
+ def view_template
111
+ h1(:divider) { 'My Title' }
112
+ end
113
+ end
114
+ ```
115
+
116
+ This will output:
117
+
118
+ ```html
119
+ <h1 data-variant-divider>My Title</h1>
120
+ ```
121
+
122
+ Underscored names are rendered as dashes in the data attribute (e.g. `:super_big` becomes `data-variant-super-big`).
123
+
124
+ #### Modifying attributes
125
+
126
+ Pass a block to `variant` to modify the element's attributes when the variant is used. The block receives the attributes hash:
127
+
128
+ ```ruby
129
+ class MyView < Phlex::HTML
130
+ extend Phlexible::ElementVariants
131
+
132
+ variant :external, on: :a do |attributes|
133
+ attributes[:target] = '_blank'
134
+ end
135
+
136
+ def view_template
137
+ a(:external, href: 'https://example.com') { 'Link' }
138
+ end
139
+ end
140
+ ```
141
+
142
+ #### Multiple variants
143
+
144
+ You can apply multiple variants to a single element by passing more than one Symbol:
145
+
146
+ ```ruby
147
+ a(:external, :primary, href: '/foo') { 'Link' }
148
+ ```
149
+
150
+ Passing an unregistered variant raises `ArgumentError`.
151
+
152
+ ### `PageTitle`
153
+
154
+ Helper to assist in defining page titles within Phlex views. Also includes support for nested views, where each desendent view class will have its title prepended to the page title. Simply include *Phlexible::PageTitle* module and assign the title to the `page_title` class variable:
155
+
156
+ ```ruby
157
+ class MyView
158
+ include Phlexible::PageTitle
159
+ self.page_title = 'My Title'
160
+ end
161
+ ```
162
+
163
+ Then call the `page_title` method in the `<head>` of your page.
164
+
165
+ ### `ProcessAttributes`
166
+
167
+ > This functionality is already built in to **Phlex >= 1**. This module is only needed for **Phlex >= 2**.
168
+
169
+ Allows you to intercept and modify HTML element attributes before they are rendered. This is useful for adding default attributes, transforming values, or conditionally modifying attributes based on other attributes.
170
+
171
+ Extend your view class with `Phlexible::ProcessAttributes` and define a `process_attributes` instance method that receives the attributes hash and returns the modified hash.
172
+
173
+ ```ruby
174
+ class MyView < Phlex::HTML
175
+ extend Phlexible::ProcessAttributes
176
+
177
+ def process_attributes(attrs)
178
+ # Add a default class to all elements
179
+ attrs[:class] ||= 'my-default-class'
180
+ attrs
181
+ end
182
+
183
+ def view_template
184
+ div(id: 'container') { 'Hello' }
185
+ end
186
+ end
187
+ ```
188
+
189
+ This will output:
190
+
191
+ ```html
192
+ <div id="container" class="my-default-class">Hello</div>
193
+ ```
194
+
195
+ The `process_attributes` method is called for all standard HTML elements and void elements, as well as any custom elements registered with `register_element`.
196
+
197
+ ```ruby
198
+ class MyView < Phlex::HTML
199
+ extend Phlexible::ProcessAttributes
200
+
201
+ register_element :my_custom_element
202
+
203
+ def process_attributes(attrs)
204
+ attrs[:data_processed] = true
205
+ attrs
206
+ end
207
+
208
+ def view_template
209
+ my_custom_element(name: 'test') { 'Custom content' }
210
+ end
211
+ end
212
+ ```
213
+
17
214
  ### `Rails::ActionController::ImplicitRender`
18
215
 
19
216
  Adds support for default and `action_missing` rendering of Phlex views. So instead of this:
@@ -58,33 +255,48 @@ end
58
255
 
59
256
  This would resolve `UsersController#index` to `Views::Users::Index` instead.
60
257
 
61
- ### `Callbacks`
258
+ ### `Rails::ControllerVariables`
62
259
 
63
- While Phlex does have `before_template`, `after_template`, and `around_template` hooks, they must be defined as regular Ruby methods, meaning you have to always remember to call `super` when redefining any hook method.
260
+ > **NOTE:** Prior to **1.0.0**, this module was called `ControllerAttributes` with a very different API. This is no longer available since **1.0.0**.
64
261
 
65
- This module provides a more Rails-like interface for defining callbacks in your Phlex views, using `ActiveSupport::Callbacks`. It implements the same `before_template`, `after_template`, and `around_template` hooks as callbacks.
262
+ Include this module in your Phlex views to get access to the controller's instance variables. It provides an explicit interface for accessing controller instance variables from within the view.
66
263
 
67
264
  ```ruby
68
265
  class Views::Users::Index < Views::Base
69
- include Phlexible::Callbacks
266
+ include Phlexible::Rails::ControllerVariables
70
267
 
71
- before_template :set_title
268
+ controller_variable :first_name, :last_name
72
269
 
73
270
  def view_template
74
- h1 { @title }
271
+ h1 { "#{@first_name} #{@last_name}" }
75
272
  end
273
+ end
274
+ ```
76
275
 
77
- private
276
+ #### Options
78
277
 
79
- def set_title
80
- @title = 'Users'
81
- end
278
+ `controller_variable` accepts one or many symbols, or a hash of symbols to options.
279
+
280
+ - `as:` - If set, the given attribute will be renamed to the given value. Helpful to avoid naming conflicts.
281
+ - `allow_undefined:` - By default, if the instance variable is not defined in the controller, an
282
+ exception will be raised. If this option is to `true`, an error will not be raised.
283
+
284
+ You can also pass a hash of attributes to `controller_variable`, where the key is the controller
285
+ attribute, and the value is the renamed value, or options hash.
286
+
287
+ ```ruby
288
+ class Views::Users::Index < Views::Base
289
+ include Phlexible::Rails::ControllerVariables
290
+
291
+ controller_variable last_name: :surname, first_name: { as: :given_name, allow_undefined: true }
292
+
293
+ def view_template
294
+ h1 { "#{@given_name} #{@surname}" }
295
+ end
82
296
  end
83
297
  ```
84
298
 
85
- You can still use the regular `before_template`, `after_template`, and `around_template` hooks as well, but I recommend that if you include this module, that you use callbacks instead.
86
-
87
- When used with `Rails::AutoLayout`, layout callbacks (`before_layout`, `after_layout`, `around_layout`) are also available. See the `Rails::AutoLayout` section below.
299
+ Please note that defining a variable with the same name as an existing variable in the view will be overwritten.
88
300
 
89
301
  ### `Rails::AutoLayout`
90
302
 
@@ -182,80 +394,6 @@ end
182
394
 
183
395
  Layout resolution is cached per class in production. In development (when `Rails.configuration.enable_reloading` is enabled), layouts are resolved fresh on each render. You can manually clear the cache with `reset_resolved_layout!`.
184
396
 
185
- ### `Rails::ControllerVariables`
186
-
187
- > **NOTE:** Prior to **1.0.0**, this module was called `ControllerAttributes` with a very different API. This is no longer available since **1.0.0**.
188
-
189
- Include this module in your Phlex views to get access to the controller's instance variables. It provides an explicit interface for accessing controller instance variables from within the view.
190
-
191
- ```ruby
192
- class Views::Users::Index < Views::Base
193
- include Phlexible::Rails::ControllerVariables
194
-
195
- controller_variable :first_name, :last_name
196
-
197
- def view_template
198
- h1 { "#{@first_name} #{@last_name}" }
199
- end
200
- end
201
- ```
202
-
203
- #### Options
204
-
205
- `controller_variable` accepts one or many symbols, or a hash of symbols to options.
206
-
207
- - `as:` - If set, the given attribute will be renamed to the given value. Helpful to avoid naming conflicts.
208
- - `allow_undefined:` - By default, if the instance variable is not defined in the controller, an
209
- exception will be raised. If this option is to `true`, an error will not be raised.
210
-
211
- You can also pass a hash of attributes to `controller_variable`, where the key is the controller
212
- attribute, and the value is the renamed value, or options hash.
213
-
214
- ```ruby
215
- class Views::Users::Index < Views::Base
216
- include Phlexible::Rails::ControllerVariables
217
-
218
- controller_variable last_name: :surname, first_name: { as: :given_name, allow_undefined: true }
219
-
220
- def view_template
221
- h1 { "#{@given_name} #{@surname}" }
222
- end
223
- end
224
- ```
225
-
226
- Please note that defining a variable with the same name as an existing variable in the view will be overwritten.
227
-
228
- ### `Rails::Responder`
229
-
230
- If you use [Responders](https://github.com/heartcombo/responders), Phlexible provides a responder to support implicit rendering similar to `Rails::ActionController::ImplicitRender` above. It will render the Phlex view using `respond_with` if one exists, and fall back to default rendering.
231
-
232
- Just include it in your ApplicationResponder:
233
-
234
- ```ruby
235
- class ApplicationResponder < ActionController::Responder
236
- include Phlexible::Rails::ActionController::ImplicitRender
237
- include Phlexible::Rails::Responder
238
- end
239
- ```
240
-
241
- Then simply `respond_with` in your action method as normal:
242
-
243
- ```ruby
244
- class UsersController < ApplicationController
245
- def new
246
- respond_with User.new
247
- end
248
-
249
- def index
250
- respond_with User.all
251
- end
252
- end
253
- ```
254
-
255
- This responder requires the use of `ActionController::ImplicitRender`, so don't forget to include that in your `ApplicationController`.
256
-
257
- If you use `Rails::ControllerVariables` in your view, and define a `resource` attribute, the responder will pass that to your view.
258
-
259
397
  ### `Rails::AElement`
260
398
 
261
399
  No need to call Rails `link_to` helper, when you can simply render an anchor tag directly with Phlex. But unfortunately that means you lose some of the magic that `link_to` provides. Especially the automatic resolution of URL's and Rails routes.
@@ -278,6 +416,12 @@ class MyView < Phlex::HTML
278
416
  end
279
417
  ```
280
418
 
419
+ You can also pass `:back` as the `href` value, which will use the referrer URL if available, or fall back to `javascript:history.back()`:
420
+
421
+ ```ruby
422
+ a(href: :back) { 'Go back' }
423
+ ```
424
+
281
425
  ### `Rails::ButtonTo`
282
426
 
283
427
  Generates a form containing a single button that submits to the URL created by the set of options.
@@ -333,99 +477,36 @@ class MyView < Phlex::HTML
333
477
  end
334
478
  ```
335
479
 
336
- ### `AliasView`
337
-
338
- Create an alias at a given `element`, to the given view class.
339
-
340
- So instead of:
341
-
342
- ```ruby
343
- class MyView < Phlex::HTML
344
- def view_template
345
- div do
346
- render My::Awesome::Component.new
347
- end
348
- end
349
- end
350
- ```
351
-
352
- You can instead do:
353
-
354
- ```ruby
355
- class MyView < Phlex::HTML
356
- extend Phlexible::AliasView
357
-
358
- alias_view :awesome, -> { My::Awesome::Component }
359
-
360
- def view_template
361
- div do
362
- awesome
363
- end
364
- end
365
- end
366
- ```
480
+ ### `Rails::Responder`
367
481
 
368
- ### `PageTitle`
482
+ If you use [Responders](https://github.com/heartcombo/responders), Phlexible provides a responder to support implicit rendering similar to `Rails::ActionController::ImplicitRender` above. It will render the Phlex view using `respond_with` if one exists, and fall back to default rendering.
369
483
 
370
- Helper to assist in defining page titles within Phlex views. Also includes support for nested views, where each desendent view class will have its title prepended to the page title. Simply include *Phlexible::PageTitle* module and assign the title to the `page_title` class variable:
484
+ Just include it in your ApplicationResponder:
371
485
 
372
486
  ```ruby
373
- class MyView
374
- include Phlexible::PageTitle
375
- self.page_title = 'My Title'
487
+ class ApplicationResponder < ActionController::Responder
488
+ include Phlexible::Rails::ActionController::ImplicitRender
489
+ include Phlexible::Rails::Responder
376
490
  end
377
491
  ```
378
492
 
379
- Then call the `page_title` method in the `<head>` of your page.
380
-
381
- ### `ProcessAttributes`
382
-
383
- > This functionality is already built in to **Phlex >= 1**. This module is only needed for **Phlex >= 2**.
384
-
385
- Allows you to intercept and modify HTML element attributes before they are rendered. This is useful for adding default attributes, transforming values, or conditionally modifying attributes based on other attributes.
386
-
387
- Extend your view class with `Phlexible::ProcessAttributes` and define a `process_attributes` instance method that receives the attributes hash and returns the modified hash.
493
+ Then simply `respond_with` in your action method as normal:
388
494
 
389
495
  ```ruby
390
- class MyView < Phlex::HTML
391
- extend Phlexible::ProcessAttributes
392
-
393
- def process_attributes(attrs)
394
- # Add a default class to all elements
395
- attrs[:class] ||= 'my-default-class'
396
- attrs
496
+ class UsersController < ApplicationController
497
+ def new
498
+ respond_with User.new
397
499
  end
398
500
 
399
- def view_template
400
- div(id: 'container') { 'Hello' }
501
+ def index
502
+ respond_with User.all
401
503
  end
402
504
  end
403
505
  ```
404
506
 
405
- This will output:
406
-
407
- ```html
408
- <div id="container" class="my-default-class">Hello</div>
409
- ```
410
-
411
- The `process_attributes` method is called for all standard HTML elements and void elements, as well as any custom elements registered with `register_element`.
412
-
413
- ```ruby
414
- class MyView < Phlex::HTML
415
- extend Phlexible::ProcessAttributes
416
-
417
- register_element :my_custom_element
418
-
419
- def process_attributes(attrs)
420
- attrs[:data_processed] = true
421
- attrs
422
- end
507
+ This responder requires the use of `ActionController::ImplicitRender`, so don't forget to include that in your `ApplicationController`.
423
508
 
424
- def view_template
425
- my_custom_element(name: 'test') { 'Custom content' }
426
- end
427
- end
428
- ```
509
+ If you use `Rails::ControllerVariables` in your view, and define a `resource` attribute, the responder will pass that to your view.
429
510
 
430
511
  ## Development
431
512