cocooned 2.2.0 → 2.3.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: ec1afe38e7db15aee028d1890edcb0cb661bf62c696b2a79aa5102c573a8a1fe
4
- data.tar.gz: df9f13885a634db0e7b3f1f1348573b0aa6bfa1f73a488de918dbaf3cf07dc15
3
+ metadata.gz: '09dea153d60f4775a1971687cd1559ee09ef878f97ce865088ab76189db919e7'
4
+ data.tar.gz: dea0da54a7111ac9723faec4ea74f3f058e3db2884aecd14233b0e13c74881e5
5
5
  SHA512:
6
- metadata.gz: 8562d9fe1b0a704991ad1ba284e3e219a62e9da606b8791aa5ffbca23647f80abed6d3826f730533d7bb2dbb12c3b3c9ecfd2d670d17f6929ad0c72ca027f37e
7
- data.tar.gz: 4e3157dbe296abd6b18162e34e7f98d8cba90ad14c7f449cb9cc56ad66bca9a8cee31c6a04d3ed8cbbf35832e420c2b05adccb1e9ea0ad1f5c82ac058c5bd2d7
6
+ metadata.gz: aa27825fcb619f22b8bf86472a367c2ad131b8b84fffbabc2a80a7b90d50aa42a0a5dbaf8c873c751e7f043a527a044d4bce84706f3c1808297c26bcf3d658f5
7
+ data.tar.gz: b1338f4ff4433fd28cd967475d49dddc638df8b2e579d75675316ac8cacf8e3a318e4651c118060f576e25b46a11214b8b97b6109c2db8758036050311c153fc
data/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## Version 2.3.0 (2024-08-23)
10
+
11
+ ### Fixed
12
+
13
+ * Add support for Rails v7.2 and drop support for Rails < 6.1 (#70, thanks @mattmenefee)
14
+
15
+ ## Version 2.2.1 (2024-05-20)
16
+
17
+ ## Fixed
18
+
19
+ * Add UMD build of Coconned missing in 2.2.0
20
+
9
21
  ## Version 2.2.0 (2024-05-20)
10
22
 
11
23
  ## Added
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Cocooned makes it easier to handle nested forms in Rails.
7
7
 
8
- Cocooned is form builder-agnostic: it works with standard Rails (>= 6.0, < 7.1) form helpers, [Formtastic](https://github.com/justinfrench/formtastic) or [SimpleForm](https://github.com/plataformatec/simple_form).
8
+ Cocooned is form builder-agnostic: it works with standard Rails (>= 6.1, < 8.0) form helpers, [Formtastic](https://github.com/justinfrench/formtastic) or [SimpleForm](https://github.com/plataformatec/simple_form).
9
9
 
10
10
  1. [Background](#some-background)
11
11
  2. [Installation](#installation)
@@ -248,63 +248,10 @@
248
248
  }
249
249
  }
250
250
 
251
- /**
252
- * Borrowed from Lodash
253
- * See https://lodash.com/docs/#escapeRegExp
254
- */
255
- const reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
256
- const reHasRegExpChar = RegExp(reRegExpChar.source);
257
-
258
- class Replacement {
259
- attribute
260
-
261
- constructor (attribute, name, startDelimiter, endDelimiter = null) {
262
- this.attribute = attribute;
263
-
264
- this.#name = name;
265
- this.#startDelimiter = startDelimiter;
266
- this.#endDelimiter = endDelimiter || startDelimiter;
267
- }
268
-
269
- apply (node, id) {
270
- const value = node.getAttribute(this.attribute);
271
- if (!this.#regexp.test(value)) {
272
- return
273
- }
274
-
275
- node.setAttribute(this.attribute, value.replace(this.#regexp, this.#replacement(id)));
276
- }
277
-
278
- /* Protected and private attributes and methods */
279
- #name
280
- #startDelimiter
281
- #endDelimiter
282
-
283
- #replacement (id) {
284
- return `${this.#startDelimiter}${id}${this.#endDelimiter}$1`
285
- }
286
-
287
- get #regexp () {
288
- const escaped = this.#escape(`${this.#startDelimiter}${this.#name}${this.#endDelimiter}`);
289
- return new RegExp(`${escaped}(.*?)`, 'g')
290
- }
291
-
292
- #escape (string) {
293
- return (string && reHasRegExpChar.test(string))
294
- ? string.replace(reRegExpChar, '\\$&')
295
- : (string || '')
296
- }
297
- }
298
-
299
251
  class Builder {
300
- constructor (documentFragment, association) {
252
+ constructor (documentFragment, replacements) {
301
253
  this.#documentFragment = documentFragment;
302
- this.#association = association;
303
- this.#replacements = [
304
- new Replacement('for', association, '_'),
305
- new Replacement('id', association, '_'),
306
- new Replacement('name', association, '[', ']')
307
- ];
254
+ this.#replacements = replacements;
308
255
  }
309
256
 
310
257
  build (id) {
@@ -314,13 +261,14 @@
314
261
  }
315
262
 
316
263
  /* Protected and private attributes and methods */
317
- #association
318
264
  #documentFragment
319
265
  #replacements
320
266
 
321
267
  #applyReplacements (node, id) {
322
268
  this.#replacements.forEach(replacement => {
323
- node.querySelectorAll(`*[${replacement.attribute}]`).forEach(node => replacement.apply(node, id));
269
+ node.querySelectorAll(`${replacement.tag}[${replacement.attribute}]`).forEach(node => {
270
+ return replacement.apply(node, id)
271
+ });
324
272
  });
325
273
 
326
274
  node.querySelectorAll('template').forEach(template => {
@@ -478,7 +426,10 @@
478
426
  return null
479
427
  }
480
428
 
481
- return new Builder(template.content, `new_${this.#dataset.association}`)
429
+ return new Builder(
430
+ template.content,
431
+ this.#cocooned.replacementsFor(`new_${this.#dataset.association}`)
432
+ )
482
433
  }
483
434
 
484
435
  _extractCount () {
@@ -675,6 +626,56 @@
675
626
  }
676
627
  }
677
628
 
629
+ /**
630
+ * Borrowed from Lodash
631
+ * See https://lodash.com/docs/#escapeRegExp
632
+ */
633
+ const reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
634
+ const reHasRegExpChar = RegExp(reRegExpChar.source);
635
+
636
+ class Replacement {
637
+ attribute
638
+ tag
639
+
640
+ constructor ({ tag = '*', attribute, association, delimiters }) {
641
+ this.attribute = attribute;
642
+ this.tag = tag;
643
+
644
+ this.#association = association;
645
+ this.#startDelimiter = delimiters[0];
646
+ this.#endDelimiter = delimiters[delimiters.length - 1];
647
+ }
648
+
649
+ apply (node, id) {
650
+ const value = node.getAttribute(this.attribute);
651
+ if (!this.#regexp.test(value)) {
652
+ return
653
+ }
654
+
655
+ node.setAttribute(this.attribute, value.replace(this.#regexp, this.#replacement(id)));
656
+ }
657
+
658
+ /* Protected and private attributes and methods */
659
+ #association
660
+ #startDelimiter
661
+ #endDelimiter
662
+
663
+ #replacement (id) {
664
+ return `${this.#startDelimiter}${id}${this.#endDelimiter}$1`
665
+ }
666
+
667
+ get #regexp () {
668
+ const escaped = this.#escape(`${this.#startDelimiter}${this.#association}${this.#endDelimiter}`);
669
+ return new RegExp(`${escaped}(.*?)`, 'g')
670
+ }
671
+
672
+ #escape (string) {
673
+ return (string && reHasRegExpChar.test(string))
674
+ ? string.replace(reRegExpChar, '\\$&')
675
+ : (string || '')
676
+ }
677
+ }
678
+
678
679
  function clickHandler$1 (callback) {
679
680
  return e => {
680
681
  e.preventDefault();
@@ -708,6 +709,18 @@
708
709
  }
709
710
 
710
711
  const coreMixin = (Base) => class extends Base {
712
+ static registerReplacement ({ tag = '*', attribute, delimiters }) {
713
+ this.__replacements.push({ tag, attribute, delimiters });
714
+ }
715
+
716
+ static get replacements () {
717
+ return this.__replacements
718
+ }
719
+
720
+ static replacementsFor (association) {
721
+ return this.replacements.map(r => new Replacement({ association, ...r }))
722
+ }
723
+
711
724
  static get selectors () {
712
725
  return {
713
726
  ...super.selectors,
@@ -736,6 +749,21 @@
736
749
  })
737
750
  );
738
751
  }
752
+
753
+ replacementsFor (association) {
754
+ return this.constructor.replacementsFor(association)
755
+ }
756
+
757
+ /* Protected and private attributes and methods */
758
+ static __replacements = [
759
+ // Default attributes
760
+ { tag: 'label', attribute: 'for', delimiters: ['_'] },
761
+ { tag: '*', attribute: 'id', delimiters: ['_'] },
762
+ { tag: '*', attribute: 'name', delimiters: ['[', ']'] },
763
+
764
+ // Compatibility with Trix. See #65 on Github.
765
+ { tag: 'trix-editor', attribute: 'input', delimiters: ['_'] }
766
+ ]
739
767
  };
740
768
 
741
769
  let Cocooned$1 = class Cocooned extends coreMixin(Base) {
data/cocooned.gemspec CHANGED
@@ -40,7 +40,7 @@ Gem::Specification.new do |spec|
40
40
  end
41
41
  spec.required_ruby_version = '>= 2.6'
42
42
 
43
- spec.add_dependency 'rails', '>= 6.0', '<= 7.2'
43
+ spec.add_dependency 'rails', '>= 6.1', '<= 8.0'
44
44
 
45
45
  spec.add_development_dependency 'bundler', '~> 2.1'
46
46
  spec.add_development_dependency 'rake', '~> 13.0'
@@ -13,7 +13,7 @@ module Cocooned
13
13
 
14
14
  def initialize(deprecation_horizon = nil, gem_name = 'Cocooned')
15
15
  deprecation_horizon ||= format('%<major>d.0', major: Gem::Version.new(Cocooned::VERSION).segments.first + 1)
16
- super(deprecation_horizon, gem_name)
16
+ super
17
17
  end
18
18
  end
19
19
 
@@ -64,8 +64,7 @@ module Cocooned
64
64
  protected
65
65
 
66
66
  def cocooned_wrapper_defaults(options, additional_classes, mark)
67
- # TODO: Replace with compact_blank when dropping support for Rails 6.0
68
- classes = Array.wrap(options.delete(:class)).flat_map { |k| k.to_s.split }.reject(&:blank?)
67
+ classes = Array.wrap(options.delete(:class)).flat_map { |k| k.to_s.split }.compact_blank
69
68
 
70
69
  { class: (classes + additional_classes), data: { mark => true } }
71
70
  end
@@ -7,7 +7,6 @@ module Cocooned
7
7
  protected
8
8
 
9
9
  def association_options
10
- # TODO: Replace with compact_blank when dropping support for Rails 6.0
11
10
  {
12
11
  association: association,
13
12
  template: html_template_name,
@@ -15,7 +14,7 @@ module Cocooned
15
14
  association_insertion_node: options.delete(:insertion_node),
16
15
  association_insertion_method: options.delete(:insertion_method),
17
16
  association_insertion_traversal: options.delete(:insertion_traversal)
18
- }.reject { |_, value| value.blank? }
17
+ }.compact_blank
19
18
  end
20
19
  end
21
20
 
@@ -32,7 +31,7 @@ module Cocooned
32
31
  end
33
32
 
34
33
  def render(as: :link)
35
- template.safe_join([super(as: as), html_template])
34
+ template.safe_join([super, html_template])
36
35
  end
37
36
 
38
37
  protected
@@ -47,14 +47,12 @@ module Cocooned
47
47
  @html_options ||= begin
48
48
  options[:class] = html_classes
49
49
  options[:data] = html_data
50
- # TODO: Replace with compact_blank when dropping support for Rails 6.0
51
- options.reject { |_, value| value.blank? }
50
+ options.compact_blank
52
51
  end
53
52
  end
54
53
 
55
54
  def html_classes
56
- # TODO: Replace with compact_blank when dropping support for Rails 6.0
57
- Array.wrap(options.delete(:class)).flat_map { |k| k.to_s.split }.reject(&:blank?)
55
+ Array.wrap(options.delete(:class)).flat_map { |k| k.to_s.split }.compact_blank
58
56
  end
59
57
  end
60
58
  end
@@ -6,7 +6,7 @@ module Cocooned
6
6
  include Cocooned::TagsHelper::AssociationLabel
7
7
 
8
8
  def render(as: :link)
9
- template.safe_join([hidden_field, super(as: as)])
9
+ template.safe_join([hidden_field, super])
10
10
  end
11
11
 
12
12
  protected
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cocooned
4
- VERSION = '2.2.0'
4
+ VERSION = '2.3.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocooned
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gaël-Ian Havard
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-05-20 00:00:00.000000000 Z
12
+ date: 2024-08-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -17,20 +17,20 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '6.0'
20
+ version: '6.1'
21
21
  - - "<="
22
22
  - !ruby/object:Gem::Version
23
- version: '7.2'
23
+ version: '8.0'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
28
  - - ">="
29
29
  - !ruby/object:Gem::Version
30
- version: '6.0'
30
+ version: '6.1'
31
31
  - - "<="
32
32
  - !ruby/object:Gem::Version
33
- version: '7.2'
33
+ version: '8.0'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: bundler
36
36
  requirement: !ruby/object:Gem::Requirement