cocooned 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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