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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +1 -1
- data/app/assets/javascripts/cocooned.js +86 -58
- data/cocooned.gemspec +1 -1
- data/lib/cocooned/deprecation.rb +1 -1
- data/lib/cocooned/helpers/containers.rb +1 -2
- data/lib/cocooned/tags/add.rb +2 -3
- data/lib/cocooned/tags/base.rb +2 -4
- data/lib/cocooned/tags/remove.rb +1 -1
- data/lib/cocooned/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09dea153d60f4775a1971687cd1559ee09ef878f97ce865088ab76189db919e7'
|
4
|
+
data.tar.gz: dea0da54a7111ac9723faec4ea74f3f058e3db2884aecd14233b0e13c74881e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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,
|
252
|
+
constructor (documentFragment, replacements) {
|
301
253
|
this.#documentFragment = documentFragment;
|
302
|
-
this.#
|
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(
|
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(
|
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.
|
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'
|
data/lib/cocooned/deprecation.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
data/lib/cocooned/tags/add.rb
CHANGED
@@ -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
|
-
}.
|
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
|
34
|
+
template.safe_join([super, html_template])
|
36
35
|
end
|
37
36
|
|
38
37
|
protected
|
data/lib/cocooned/tags/base.rb
CHANGED
@@ -47,14 +47,12 @@ module Cocooned
|
|
47
47
|
@html_options ||= begin
|
48
48
|
options[:class] = html_classes
|
49
49
|
options[:data] = html_data
|
50
|
-
|
51
|
-
options.reject { |_, value| value.blank? }
|
50
|
+
options.compact_blank
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
54
|
def html_classes
|
56
|
-
|
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
|
data/lib/cocooned/tags/remove.rb
CHANGED
data/lib/cocooned/version.rb
CHANGED
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.
|
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-
|
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.
|
20
|
+
version: '6.1'
|
21
21
|
- - "<="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: '
|
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.
|
30
|
+
version: '6.1'
|
31
31
|
- - "<="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '8.0'
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: bundler
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|