cable_ready 5.0.1 → 5.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -1
- data/app/assets/javascripts/cable_ready.js +86 -3
- data/app/assets/javascripts/cable_ready.umd.js +85 -3
- data/app/helpers/cable_ready/view_helper.rb +2 -1
- data/lib/cable_ready/channels.rb +2 -0
- data/lib/cable_ready/config.rb +2 -0
- data/lib/cable_ready/version.rb +1 -1
- data/package.json +1 -1
- data/yarn.lock +15 -10
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77c9ebacb73173f6208a3695b3f9305c70a87620216fc9441d92cc29fb2199af
|
4
|
+
data.tar.gz: c41f703f59647be24df6a357f91e0cb848da7a16d31701714f1a648ec1991f6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e741e3a8d4c500ed4ca9dc1a09590f373911f5bd87986e2a9de9fb8d461da06d65fb86d8b940a4007da79d38cb352907a2c09aefd642f2a808d9d511e7d6f230
|
7
|
+
data.tar.gz: 4a6b2d908138c58afb074642bf8e27c6f685eeace3ad2b43d182e31b61440fb251e059e7aa7cb508179e8c39c050f892e066f9c7d2c7516460284fda1d66bf87
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cable_ready (5.0.
|
4
|
+
cable_ready (5.0.2)
|
5
5
|
actionpack (>= 5.2)
|
6
6
|
actionview (>= 5.2)
|
7
7
|
activesupport (>= 5.2)
|
@@ -203,6 +203,7 @@ GEM
|
|
203
203
|
PLATFORMS
|
204
204
|
arm64-darwin-22
|
205
205
|
x86_64-darwin-19
|
206
|
+
x86_64-darwin-22
|
206
207
|
x86_64-linux
|
207
208
|
|
208
209
|
DEPENDENCIES
|
@@ -2,7 +2,7 @@ import morphdom from "morphdom";
|
|
2
2
|
|
3
3
|
var name = "cable_ready";
|
4
4
|
|
5
|
-
var version = "5.0.
|
5
|
+
var version = "5.0.3";
|
6
6
|
|
7
7
|
var description = "CableReady helps you create great real-time user experiences by making it simple to trigger client-side DOM changes from server-side Ruby.";
|
8
8
|
|
@@ -1061,6 +1061,56 @@ var Log = {
|
|
1061
1061
|
morphEnd: morphEnd
|
1062
1062
|
};
|
1063
1063
|
|
1064
|
+
class AppearanceObserver {
|
1065
|
+
constructor(delegate, element = null) {
|
1066
|
+
this.delegate = delegate;
|
1067
|
+
this.element = element || delegate;
|
1068
|
+
this.started = false;
|
1069
|
+
this.intersecting = false;
|
1070
|
+
this.intersectionObserver = new IntersectionObserver(this.intersect);
|
1071
|
+
}
|
1072
|
+
start() {
|
1073
|
+
if (!this.started) {
|
1074
|
+
this.started = true;
|
1075
|
+
this.intersectionObserver.observe(this.element);
|
1076
|
+
this.observeVisibility();
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
stop() {
|
1080
|
+
if (this.started) {
|
1081
|
+
this.started = false;
|
1082
|
+
this.intersectionObserver.unobserve(this.element);
|
1083
|
+
this.unobserveVisibility();
|
1084
|
+
}
|
1085
|
+
}
|
1086
|
+
observeVisibility=() => {
|
1087
|
+
document.addEventListener("visibilitychange", this.handleVisibilityChange);
|
1088
|
+
};
|
1089
|
+
unobserveVisibility=() => {
|
1090
|
+
document.removeEventListener("visibilitychange", this.handleVisibilityChange);
|
1091
|
+
};
|
1092
|
+
intersect=entries => {
|
1093
|
+
entries.forEach((entry => {
|
1094
|
+
if (entry.target === this.element) {
|
1095
|
+
if (entry.isIntersecting && document.visibilityState === "visible") {
|
1096
|
+
this.intersecting = true;
|
1097
|
+
this.delegate.appearedInViewport();
|
1098
|
+
} else {
|
1099
|
+
this.intersecting = false;
|
1100
|
+
this.delegate.disappearedFromViewport();
|
1101
|
+
}
|
1102
|
+
}
|
1103
|
+
}));
|
1104
|
+
};
|
1105
|
+
handleVisibilityChange=event => {
|
1106
|
+
if (document.visibilityState === "visible" && this.intersecting) {
|
1107
|
+
this.delegate.appearedInViewport();
|
1108
|
+
} else {
|
1109
|
+
this.delegate.disappearedFromViewport();
|
1110
|
+
}
|
1111
|
+
};
|
1112
|
+
}
|
1113
|
+
|
1064
1114
|
const template = `\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n`;
|
1065
1115
|
|
1066
1116
|
class UpdatesForElement extends SubscribingElement {
|
@@ -1075,6 +1125,9 @@ class UpdatesForElement extends SubscribingElement {
|
|
1075
1125
|
shadowRoot.innerHTML = template;
|
1076
1126
|
this.triggerElementLog = new BoundedQueue(10);
|
1077
1127
|
this.targetElementLog = new BoundedQueue(10);
|
1128
|
+
this.appearanceObserver = new AppearanceObserver(this);
|
1129
|
+
this.visible = false;
|
1130
|
+
this.didTransitionToVisible = false;
|
1078
1131
|
}
|
1079
1132
|
async connectedCallback() {
|
1080
1133
|
if (this.preview) return;
|
@@ -1085,6 +1138,14 @@ class UpdatesForElement extends SubscribingElement {
|
|
1085
1138
|
} else {
|
1086
1139
|
console.error("The `cable_ready_updates_for` helper cannot connect. You must initialize CableReady with an Action Cable consumer.");
|
1087
1140
|
}
|
1141
|
+
if (this.observeAppearance) {
|
1142
|
+
this.appearanceObserver.start();
|
1143
|
+
}
|
1144
|
+
}
|
1145
|
+
disconnectedCallback() {
|
1146
|
+
if (this.observeAppearance) {
|
1147
|
+
this.appearanceObserver.stop();
|
1148
|
+
}
|
1088
1149
|
}
|
1089
1150
|
async update(data) {
|
1090
1151
|
this.lastUpdateTimestamp = new Date;
|
@@ -1095,7 +1156,8 @@ class UpdatesForElement extends SubscribingElement {
|
|
1095
1156
|
return;
|
1096
1157
|
}
|
1097
1158
|
// first <cable-ready-updates-for> element in the DOM *at any given moment* updates all of the others
|
1098
|
-
|
1159
|
+
// if the element becomes visible though, we have to overrule and load it
|
1160
|
+
if (blocks[0].element !== this && !this.didTransitionToVisible) {
|
1099
1161
|
this.triggerElementLog.push(`${(new Date).toLocaleString()}: ${Log.cancel(this.lastUpdateTimestamp, "Update already requested")}`);
|
1100
1162
|
return;
|
1101
1163
|
}
|
@@ -1121,6 +1183,17 @@ class UpdatesForElement extends SubscribingElement {
|
|
1121
1183
|
block.process(data, this.html, this.index, this.lastUpdateTimestamp);
|
1122
1184
|
}));
|
1123
1185
|
}
|
1186
|
+
appearedInViewport() {
|
1187
|
+
if (!this.visible) {
|
1188
|
+
// transition from invisible to visible forces update
|
1189
|
+
this.didTransitionToVisible = true;
|
1190
|
+
this.update({});
|
1191
|
+
}
|
1192
|
+
this.visible = true;
|
1193
|
+
}
|
1194
|
+
disappearedFromViewport() {
|
1195
|
+
this.visible = false;
|
1196
|
+
}
|
1124
1197
|
get query() {
|
1125
1198
|
return `${this.tagName}[identifier="${this.identifier}"]`;
|
1126
1199
|
}
|
@@ -1130,6 +1203,9 @@ class UpdatesForElement extends SubscribingElement {
|
|
1130
1203
|
get debounce() {
|
1131
1204
|
return this.hasAttribute("debounce") ? parseInt(this.getAttribute("debounce")) : 20;
|
1132
1205
|
}
|
1206
|
+
get observeAppearance() {
|
1207
|
+
return this.hasAttribute("observe-appearance");
|
1208
|
+
}
|
1133
1209
|
}
|
1134
1210
|
|
1135
1211
|
class Block {
|
@@ -1159,6 +1235,7 @@ class Block {
|
|
1159
1235
|
onBeforeElUpdated: shouldMorph(operation),
|
1160
1236
|
onElUpdated: _ => {
|
1161
1237
|
this.element.removeAttribute("updating");
|
1238
|
+
this.element.didTransitionToVisible = false;
|
1162
1239
|
dispatch(this.element, "cable-ready:after-update", operation);
|
1163
1240
|
assignFocus(operation.focusSelector);
|
1164
1241
|
}
|
@@ -1185,7 +1262,7 @@ class Block {
|
|
1185
1262
|
}
|
1186
1263
|
shouldUpdate(data) {
|
1187
1264
|
// if everything that could prevent an update is false, update this block
|
1188
|
-
return !this.ignoresInnerUpdates && this.hasChangesSelectedForUpdate(data);
|
1265
|
+
return !this.ignoresInnerUpdates && this.hasChangesSelectedForUpdate(data) && (!this.observeAppearance || this.visible);
|
1189
1266
|
}
|
1190
1267
|
hasChangesSelectedForUpdate(data) {
|
1191
1268
|
// if there's an only attribute, only update if at least one of the attributes changed is in the allow list
|
@@ -1205,6 +1282,12 @@ class Block {
|
|
1205
1282
|
get query() {
|
1206
1283
|
return this.element.query;
|
1207
1284
|
}
|
1285
|
+
get visible() {
|
1286
|
+
return this.element.visible;
|
1287
|
+
}
|
1288
|
+
get observeAppearance() {
|
1289
|
+
return this.element.observeAppearance;
|
1290
|
+
}
|
1208
1291
|
}
|
1209
1292
|
|
1210
1293
|
const registerInnerUpdates = () => {
|
@@ -4,7 +4,7 @@
|
|
4
4
|
})(this, (function(exports, morphdom) {
|
5
5
|
"use strict";
|
6
6
|
var name = "cable_ready";
|
7
|
-
var version = "5.0.
|
7
|
+
var version = "5.0.3";
|
8
8
|
var description = "CableReady helps you create great real-time user experiences by making it simple to trigger client-side DOM changes from server-side Ruby.";
|
9
9
|
var keywords = [ "ruby", "rails", "websockets", "actioncable", "cable", "ssr", "stimulus_reflex", "client-side", "dom" ];
|
10
10
|
var homepage = "https://cableready.stimulusreflex.com";
|
@@ -982,6 +982,55 @@
|
|
982
982
|
morphStart: morphStart,
|
983
983
|
morphEnd: morphEnd
|
984
984
|
};
|
985
|
+
class AppearanceObserver {
|
986
|
+
constructor(delegate, element = null) {
|
987
|
+
this.delegate = delegate;
|
988
|
+
this.element = element || delegate;
|
989
|
+
this.started = false;
|
990
|
+
this.intersecting = false;
|
991
|
+
this.intersectionObserver = new IntersectionObserver(this.intersect);
|
992
|
+
}
|
993
|
+
start() {
|
994
|
+
if (!this.started) {
|
995
|
+
this.started = true;
|
996
|
+
this.intersectionObserver.observe(this.element);
|
997
|
+
this.observeVisibility();
|
998
|
+
}
|
999
|
+
}
|
1000
|
+
stop() {
|
1001
|
+
if (this.started) {
|
1002
|
+
this.started = false;
|
1003
|
+
this.intersectionObserver.unobserve(this.element);
|
1004
|
+
this.unobserveVisibility();
|
1005
|
+
}
|
1006
|
+
}
|
1007
|
+
observeVisibility=() => {
|
1008
|
+
document.addEventListener("visibilitychange", this.handleVisibilityChange);
|
1009
|
+
};
|
1010
|
+
unobserveVisibility=() => {
|
1011
|
+
document.removeEventListener("visibilitychange", this.handleVisibilityChange);
|
1012
|
+
};
|
1013
|
+
intersect=entries => {
|
1014
|
+
entries.forEach((entry => {
|
1015
|
+
if (entry.target === this.element) {
|
1016
|
+
if (entry.isIntersecting && document.visibilityState === "visible") {
|
1017
|
+
this.intersecting = true;
|
1018
|
+
this.delegate.appearedInViewport();
|
1019
|
+
} else {
|
1020
|
+
this.intersecting = false;
|
1021
|
+
this.delegate.disappearedFromViewport();
|
1022
|
+
}
|
1023
|
+
}
|
1024
|
+
}));
|
1025
|
+
};
|
1026
|
+
handleVisibilityChange=event => {
|
1027
|
+
if (document.visibilityState === "visible" && this.intersecting) {
|
1028
|
+
this.delegate.appearedInViewport();
|
1029
|
+
} else {
|
1030
|
+
this.delegate.disappearedFromViewport();
|
1031
|
+
}
|
1032
|
+
};
|
1033
|
+
}
|
985
1034
|
const template = `\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n`;
|
986
1035
|
class UpdatesForElement extends SubscribingElement {
|
987
1036
|
static get tagName() {
|
@@ -995,6 +1044,9 @@
|
|
995
1044
|
shadowRoot.innerHTML = template;
|
996
1045
|
this.triggerElementLog = new BoundedQueue(10);
|
997
1046
|
this.targetElementLog = new BoundedQueue(10);
|
1047
|
+
this.appearanceObserver = new AppearanceObserver(this);
|
1048
|
+
this.visible = false;
|
1049
|
+
this.didTransitionToVisible = false;
|
998
1050
|
}
|
999
1051
|
async connectedCallback() {
|
1000
1052
|
if (this.preview) return;
|
@@ -1005,6 +1057,14 @@
|
|
1005
1057
|
} else {
|
1006
1058
|
console.error("The `cable_ready_updates_for` helper cannot connect. You must initialize CableReady with an Action Cable consumer.");
|
1007
1059
|
}
|
1060
|
+
if (this.observeAppearance) {
|
1061
|
+
this.appearanceObserver.start();
|
1062
|
+
}
|
1063
|
+
}
|
1064
|
+
disconnectedCallback() {
|
1065
|
+
if (this.observeAppearance) {
|
1066
|
+
this.appearanceObserver.stop();
|
1067
|
+
}
|
1008
1068
|
}
|
1009
1069
|
async update(data) {
|
1010
1070
|
this.lastUpdateTimestamp = new Date;
|
@@ -1015,7 +1075,8 @@
|
|
1015
1075
|
return;
|
1016
1076
|
}
|
1017
1077
|
// first <cable-ready-updates-for> element in the DOM *at any given moment* updates all of the others
|
1018
|
-
|
1078
|
+
// if the element becomes visible though, we have to overrule and load it
|
1079
|
+
if (blocks[0].element !== this && !this.didTransitionToVisible) {
|
1019
1080
|
this.triggerElementLog.push(`${(new Date).toLocaleString()}: ${Log.cancel(this.lastUpdateTimestamp, "Update already requested")}`);
|
1020
1081
|
return;
|
1021
1082
|
}
|
@@ -1041,6 +1102,17 @@
|
|
1041
1102
|
block.process(data, this.html, this.index, this.lastUpdateTimestamp);
|
1042
1103
|
}));
|
1043
1104
|
}
|
1105
|
+
appearedInViewport() {
|
1106
|
+
if (!this.visible) {
|
1107
|
+
// transition from invisible to visible forces update
|
1108
|
+
this.didTransitionToVisible = true;
|
1109
|
+
this.update({});
|
1110
|
+
}
|
1111
|
+
this.visible = true;
|
1112
|
+
}
|
1113
|
+
disappearedFromViewport() {
|
1114
|
+
this.visible = false;
|
1115
|
+
}
|
1044
1116
|
get query() {
|
1045
1117
|
return `${this.tagName}[identifier="${this.identifier}"]`;
|
1046
1118
|
}
|
@@ -1050,6 +1122,9 @@
|
|
1050
1122
|
get debounce() {
|
1051
1123
|
return this.hasAttribute("debounce") ? parseInt(this.getAttribute("debounce")) : 20;
|
1052
1124
|
}
|
1125
|
+
get observeAppearance() {
|
1126
|
+
return this.hasAttribute("observe-appearance");
|
1127
|
+
}
|
1053
1128
|
}
|
1054
1129
|
class Block {
|
1055
1130
|
constructor(element) {
|
@@ -1078,6 +1153,7 @@
|
|
1078
1153
|
onBeforeElUpdated: shouldMorph(operation),
|
1079
1154
|
onElUpdated: _ => {
|
1080
1155
|
this.element.removeAttribute("updating");
|
1156
|
+
this.element.didTransitionToVisible = false;
|
1081
1157
|
dispatch(this.element, "cable-ready:after-update", operation);
|
1082
1158
|
assignFocus(operation.focusSelector);
|
1083
1159
|
}
|
@@ -1104,7 +1180,7 @@
|
|
1104
1180
|
}
|
1105
1181
|
shouldUpdate(data) {
|
1106
1182
|
// if everything that could prevent an update is false, update this block
|
1107
|
-
return !this.ignoresInnerUpdates && this.hasChangesSelectedForUpdate(data);
|
1183
|
+
return !this.ignoresInnerUpdates && this.hasChangesSelectedForUpdate(data) && (!this.observeAppearance || this.visible);
|
1108
1184
|
}
|
1109
1185
|
hasChangesSelectedForUpdate(data) {
|
1110
1186
|
// if there's an only attribute, only update if at least one of the attributes changed is in the allow list
|
@@ -1124,6 +1200,12 @@
|
|
1124
1200
|
get query() {
|
1125
1201
|
return this.element.query;
|
1126
1202
|
}
|
1203
|
+
get visible() {
|
1204
|
+
return this.element.visible;
|
1205
|
+
}
|
1206
|
+
get observeAppearance() {
|
1207
|
+
return this.element.observeAppearance;
|
1208
|
+
}
|
1127
1209
|
}
|
1128
1210
|
const registerInnerUpdates = () => {
|
1129
1211
|
document.addEventListener("stimulus-reflex:before", (event => {
|
@@ -27,12 +27,13 @@ module CableReady
|
|
27
27
|
tag.cable_ready_stream_from(**build_options(*keys, html_options))
|
28
28
|
end
|
29
29
|
|
30
|
-
def cable_ready_updates_for(*keys, url: nil, debounce: nil, only: nil, ignore_inner_updates: false, html_options: {}, &block)
|
30
|
+
def cable_ready_updates_for(*keys, url: nil, debounce: nil, only: nil, ignore_inner_updates: false, observe_appearance: false, html_options: {}, &block)
|
31
31
|
options = build_options(*keys, html_options)
|
32
32
|
options[:url] = url if url
|
33
33
|
options[:debounce] = debounce if debounce
|
34
34
|
options[:only] = only if only
|
35
35
|
options[:"ignore-inner-updates"] = "" if ignore_inner_updates
|
36
|
+
options[:"observe-appearance"] = "" if observe_appearance
|
36
37
|
tag.cable_ready_updates_for(**options) { capture(&block) }
|
37
38
|
end
|
38
39
|
|
data/lib/cable_ready/channels.rb
CHANGED
data/lib/cable_ready/config.rb
CHANGED
data/lib/cable_ready/version.rb
CHANGED
data/package.json
CHANGED
data/yarn.lock
CHANGED
@@ -4892,20 +4892,25 @@ semver-compare@^1.0.0:
|
|
4892
4892
|
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
4893
4893
|
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
|
4894
4894
|
|
4895
|
-
semver@6.3.0
|
4895
|
+
semver@6.3.0:
|
4896
4896
|
version "6.3.0"
|
4897
4897
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
4898
4898
|
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
4899
4899
|
|
4900
4900
|
semver@^5.5.0, semver@^5.6.0:
|
4901
|
-
version "5.7.
|
4902
|
-
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.
|
4903
|
-
integrity sha512-
|
4901
|
+
version "5.7.2"
|
4902
|
+
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
4903
|
+
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
4904
|
+
|
4905
|
+
semver@^6.0.0, semver@^6.1.2, semver@^6.3.0:
|
4906
|
+
version "6.3.1"
|
4907
|
+
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
4908
|
+
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
4904
4909
|
|
4905
4910
|
semver@^7.3.4:
|
4906
|
-
version "7.
|
4907
|
-
resolved "https://registry.yarnpkg.com/semver/-/semver-7.
|
4908
|
-
integrity sha512-
|
4911
|
+
version "7.5.4"
|
4912
|
+
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
4913
|
+
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
4909
4914
|
dependencies:
|
4910
4915
|
lru-cache "^6.0.0"
|
4911
4916
|
|
@@ -5728,9 +5733,9 @@ which@^2.0.1:
|
|
5728
5733
|
isexe "^2.0.0"
|
5729
5734
|
|
5730
5735
|
word-wrap@~1.2.3:
|
5731
|
-
version "1.2.
|
5732
|
-
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.
|
5733
|
-
integrity sha512-
|
5736
|
+
version "1.2.4"
|
5737
|
+
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
|
5738
|
+
integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==
|
5734
5739
|
|
5735
5740
|
wordwrap@^1.0.0:
|
5736
5741
|
version "1.0.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cable_ready
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Hopkins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -303,7 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
303
303
|
- !ruby/object:Gem::Version
|
304
304
|
version: '0'
|
305
305
|
requirements: []
|
306
|
-
rubygems_version: 3.4.
|
306
|
+
rubygems_version: 3.4.19
|
307
307
|
signing_key:
|
308
308
|
specification_version: 4
|
309
309
|
summary: Out-of-Band Server Triggered DOM Operations
|