turbo_ready 0.0.3 → 0.0.6
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 +4 -4
- data/Gemfile +0 -3
- data/Gemfile.lock +55 -52
- data/README.md +261 -96
- data/README.md.orig +292 -0
- data/Rakefile +13 -1
- data/app/assets/builds/turbo_ready.js +1 -1
- data/app/assets/builds/turbo_ready.js.map +3 -3
- data/app/assets/images/turbo-ready-logo-dark.webp +0 -0
- data/app/assets/images/turbo-ready-logo-light.webp +0 -0
- data/app/javascript/turbo_ready.js +1 -1
- data/app/jobs/turbo_ready/broadcast_invoke_job.rb +9 -0
- data/bin/loc +1 -1
- data/lib/turbo_ready/engine.rb +13 -0
- data/lib/turbo_ready/patches/broadcastable.rb +21 -0
- data/lib/turbo_ready/patches/broadcasts.rb +18 -0
- data/lib/turbo_ready/patches/tag_builder.rb +15 -0
- data/lib/turbo_ready/patches.rb +8 -0
- data/lib/turbo_ready/string_wrapper.rb +32 -0
- data/lib/turbo_ready/tag_helper.rb +42 -0
- data/lib/turbo_ready/version.rb +1 -1
- data/lib/turbo_ready.rb +1 -10
- data/package.json +2 -2
- data/turbo_ready.gemspec +28 -19
- data/yarn.lock +155 -150
- metadata +141 -7
- data/lib/turbo_ready/railtie.rb +0 -6
- data/lib/turbo_ready/string.rb +0 -35
- data/lib/turbo_ready/tag_builder.rb +0 -33
data/README.md.orig
ADDED
@@ -0,0 +1,292 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<picture>
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://ik.imagekit.io/hopsoft/turbo-ready-logo-light_df4jcvbDL.webp?ik-sdk-version=javascript-1.4.3&updatedAt=1661615678275">
|
4
|
+
<img height="200" src="https://ik.imagekit.io/hopsoft/turbo-ready-logo-dark_VN4hA2ctc.webp?ik-sdk-version=javascript-1.4.3&updatedAt=1661615678278" />
|
5
|
+
</picture>
|
6
|
+
<h3 align="center">
|
7
|
+
Turbo Stream's Swiss Army Knife
|
8
|
+
</h3>
|
9
|
+
<h1 align="center">
|
10
|
+
Welcome to TurboReady 👋
|
11
|
+
</h1>
|
12
|
+
<p align="center">
|
13
|
+
<a href="http://blog.codinghorror.com/the-best-code-is-no-code-at-all/" target="_blank">
|
14
|
+
<img alt="Lines of Code" src="https://img.shields.io/badge/loc-278-47d299.svg" />
|
15
|
+
<<<<<<< HEAD
|
16
|
+
</a>
|
17
|
+
<a href="https://codeclimate.com/github/hopsoft/turbo_ready/maintainability" target="_blank">
|
18
|
+
<img src="https://api.codeclimate.com/v1/badges/a69b6f73abc3ccd49261/maintainability" />
|
19
|
+
</a>
|
20
|
+
<a href="https://rubygems.org/gems/turbo_ready" target="_blank">
|
21
|
+
<img alt="GEM" src="https://img.shields.io/gem/v/turbo_ready?color=168AFE&include_prereleases&logo=ruby&logoColor=FE1616">
|
22
|
+
</a>
|
23
|
+
<a href="https://www.npmjs.com/package/turbo_ready" target="_blank">
|
24
|
+
<img alt="NPM" src="https://img.shields.io/npm/v/turbo_ready?color=168AFE&logo=npm">
|
25
|
+
=======
|
26
|
+
</a>
|
27
|
+
<a href="https://codeclimate.com/github/hopsoft/turbo_ready/maintainability">
|
28
|
+
<img src="https://api.codeclimate.com/v1/badges/a69b6f73abc3ccd49261/maintainability" />
|
29
|
+
</a>
|
30
|
+
|
31
|
+
<a href="https://rubygems.org/gems/turbo_ready" target="_blank">
|
32
|
+
<img alt="Gem (including prereleases)" src="https://img.shields.io/gem/v/turbo_ready?color=168AFE&include_prereleases&logo=ruby&logoColor=FE1616">
|
33
|
+
</a>
|
34
|
+
<a href="https://github.com/testdouble/standard" target="_blank">
|
35
|
+
<img alt="Ruby Style" src="https://img.shields.io/badge/style-standard-999?logo=ruby&logoColor=FE1616" />
|
36
|
+
</a>
|
37
|
+
|
38
|
+
<br>
|
39
|
+
|
40
|
+
<a href="https://www.npmjs.com/package/turbo_ready" target="_blank">
|
41
|
+
<img alt="npm" src="https://img.shields.io/npm/v/turbo_ready?color=168AFE&logo=npm">
|
42
|
+
>>>>>>> 2ca627a (Badge updates)
|
43
|
+
</a>
|
44
|
+
<a href="https://bundlephobia.com/package/turbo_ready@" target="_blank">
|
45
|
+
<img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/turbo_ready?label=bundle%20size&logo=javascript&color=47d299">
|
46
|
+
</a>
|
47
|
+
<<<<<<< HEAD
|
48
|
+
<a href="https://github.com/testdouble/standard" target="_blank">
|
49
|
+
<img alt="Ruby Style" src="https://img.shields.io/badge/style-standard-168AFE?logo=ruby&logoColor=FE1616" />
|
50
|
+
</a>
|
51
|
+
<a href="https://github.com/sheerun/prettier-standard" target="_blank">
|
52
|
+
<img alt="JavaScript Style" src="https://img.shields.io/badge/style-prettier--standard-168AFE?logo=javascript&logoColor=f4e137" />
|
53
|
+
=======
|
54
|
+
<a href="https://github.com/sheerun/prettier-standard" target="_blank">
|
55
|
+
<img alt="JavaScript Style" src="https://img.shields.io/badge/style-prettier--standard-999?logo=javascript&logoColor=f4e137" />
|
56
|
+
>>>>>>> 2ca627a (Badge updates)
|
57
|
+
</a>
|
58
|
+
</p>
|
59
|
+
</p>
|
60
|
+
|
61
|
+
TurboReady extends [Turbo Streams](https://turbo.hotwired.dev/reference/streams) to give you full control of the
|
62
|
+
browser's [Document Object Model (DOM).](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)
|
63
|
+
|
64
|
+
**Thats right!**
|
65
|
+
You can `invoke` any DOM method on any DOM object *(including 3rd party libs)* using Turbo Streams.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
turbo_stream.invoke "console.log", "Hello World!"
|
69
|
+
```
|
70
|
+
|
71
|
+
<!-- Tocer[start]: Auto-generated, don't remove. -->
|
72
|
+
|
73
|
+
## Table of Contents
|
74
|
+
|
75
|
+
- [Why TurboReady?](#why-turboready)
|
76
|
+
- [Community](#community)
|
77
|
+
- [Sponsors](#sponsors)
|
78
|
+
- [Dependencies](#dependencies)
|
79
|
+
- [Installation](#installation)
|
80
|
+
- [Setup](#setup)
|
81
|
+
- [Usage](#usage)
|
82
|
+
- [Advanced Usage](#advanced-usage)
|
83
|
+
- [What Else Can I Do?](#what-else-can-i-do)
|
84
|
+
- [Extending Behavior](#extending-behavior)
|
85
|
+
- [Public API](#public-api)
|
86
|
+
- [A Word of Caution](#a-word-of-caution)
|
87
|
+
- [Releasing](#releasing)
|
88
|
+
- [License](#license)
|
89
|
+
|
90
|
+
<!-- Tocer[finish]: Auto-generated, don't remove. -->
|
91
|
+
|
92
|
+
## Why TurboReady?
|
93
|
+
|
94
|
+
Turbo Streams [intentionally restricts](https://turbo.hotwired.dev/handbook/streams#but-what-about-running-javascript%3F)
|
95
|
+
official actions to CRUD related activity.
|
96
|
+
The [official actions](https://turbo.hotwired.dev/reference/streams#the-seven-actions) work well for a
|
97
|
+
considerable number of use cases and you should push Streams as far as possible before reaching for TurboReady.
|
98
|
+
|
99
|
+
If you discover that CRUD isn't enough, TurboReady covers pretty much everything else.
|
100
|
+
|
101
|
+
## Community
|
102
|
+
|
103
|
+
Please join nearly 2000 of us on [Discord](https://discord.gg/stimulus-reflex) for support getting started,
|
104
|
+
as well as active discussions around Rails, Hotwire, Stimulus, Turbo (Drive, Frames, Streams), TurboReady, CableReady, StimulusReflex, ViewComponent, Phlex, and more.
|
105
|
+
|
106
|
+

|
107
|
+
|
108
|
+
Stop by #newcomers and introduce yourselves!
|
109
|
+
|
110
|
+
## Sponsors
|
111
|
+
|
112
|
+
<p align="center">
|
113
|
+
<em>Proudly sponsored by</em>
|
114
|
+
</p>
|
115
|
+
<p align="center">
|
116
|
+
<a href="https://www.clickfunnels.com?utm_source=hopsoft&utm_medium=open-source&utm_campaign=turbo_ready">
|
117
|
+
<img src="https://images.clickfunnel.com/uploads/digital_asset/file/176632/clickfunnels-dark-logo.svg" width="575" />
|
118
|
+
</a>
|
119
|
+
</p>
|
120
|
+
|
121
|
+
## Dependencies
|
122
|
+
|
123
|
+
- [rails](https://rubygems.org/gems/rails) `>=6.1`
|
124
|
+
- [turbo-rails](https://rubygems.org/gems/turbo-rails) `>=1.1`
|
125
|
+
- [@hotwired/turbo-rails](https://yarnpkg.com/package/@hotwired/turbo-rails) `>=7.2.0-beta.2`
|
126
|
+
|
127
|
+
## Installation
|
128
|
+
|
129
|
+
```sh
|
130
|
+
bundle add "turbo_ready --version VERSION"
|
131
|
+
yarn add "turbo_ready@VERSION --exact"
|
132
|
+
```
|
133
|
+
|
134
|
+
**IMPORTANT:** Be sure to use the same version for each libary.
|
135
|
+
|
136
|
+
## Setup
|
137
|
+
|
138
|
+
1. Import and intialize TurboReady in your application.
|
139
|
+
|
140
|
+
```diff
|
141
|
+
# Gemfile
|
142
|
+
+gem "turbo_ready", "~> 0.0.5"
|
143
|
+
```
|
144
|
+
|
145
|
+
```diff
|
146
|
+
# package.json
|
147
|
+
"dependencies": {
|
148
|
+
+ "@hotwired/turbo-rails": ">=7.2.0-beta.2",
|
149
|
+
+ "turbo_ready": "^0.0.5"
|
150
|
+
```
|
151
|
+
|
152
|
+
```diff
|
153
|
+
# app/javascript/application.js
|
154
|
+
import '@hotwired/turbo-rails'
|
155
|
+
+import TurboReady from 'turbo_ready'
|
156
|
+
|
157
|
+
+TurboReady.initialize(Turbo.StreamActions) // Adds TurboReady stream actions to Turbo
|
158
|
+
```
|
159
|
+
|
160
|
+
## Usage
|
161
|
+
|
162
|
+
Manipulate the DOM from anywhere you use [official Turbo Streams](https://turbo.hotwired.dev/handbook/streams#integration-with-server-side-frameworks).
|
163
|
+
Namely, [**M**odels](https://guides.rubyonrails.org/active_model_basics.html),
|
164
|
+
[**V**iews](https://guides.rubyonrails.org/action_view_overview.html),
|
165
|
+
[**C**ontrollers](https://guides.rubyonrails.org/action_controller_overview.html)
|
166
|
+
and [Jobs](https://guides.rubyonrails.org/active_job_basics.html).
|
167
|
+
|
168
|
+
You can **chain invocations.** ❤️
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
turbo_stream
|
172
|
+
.invoke("document.body.insertAdjacentHTML", "afterbegin", "<h1>Hello World!</h1>") # dot notation
|
173
|
+
.invoke("setAttribute", "data-turbo-ready", true, selector: ".button") # selector
|
174
|
+
.invoke("classList.add", "turbo-ready", selector: "a") # dot notation + selector
|
175
|
+
.flush # flush must be called when chaining invocations
|
176
|
+
```
|
177
|
+
|
178
|
+
You can use [dot notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#dot_notation)
|
179
|
+
or [selectors](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll)... **and can even combine them!** 🤯
|
180
|
+
|
181
|
+
Can I dispatch events? **You bet!** ⚡️
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
turbo_stream
|
185
|
+
.invoke("dispatchEvent", "turbo-ready:demo") # fires on window
|
186
|
+
.invoke("document.dispatchEvent", "turbo-ready:demo") # fires on document
|
187
|
+
.invoke("dispatchEvent", "turbo-ready:demo", selector: "#my-element") # fires on matching element(s)
|
188
|
+
.invoke("dispatchEvent", {bubbles: true, detail: {...}}) # set event options
|
189
|
+
.flush
|
190
|
+
```
|
191
|
+
|
192
|
+
## Advanced Usage
|
193
|
+
|
194
|
+
You can use symbols and [snake case](https://en.wikipedia.org/wiki/Snake_case) when invoking DOM functionality.
|
195
|
+
It'll implicitly convert to [camel case](https://en.wikipedia.org/wiki/Camel_case). 💎
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
turbo_stream
|
199
|
+
.invoke(:animate, [{opacity: 0}, {opacity: 1}], 2000, selector: "#example")
|
200
|
+
.invoke(:dispatch_event, {detail: {converts_to_camel_case: true}}, selector: "#example")
|
201
|
+
.flush
|
202
|
+
```
|
203
|
+
|
204
|
+
Need to opt out of camelize? No problem... just disable it.
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
turbo_stream.invoke :contrived_demo, camelize: false
|
208
|
+
```
|
209
|
+
|
210
|
+
## What Else Can I Do?
|
211
|
+
|
212
|
+
**The possibilities are endless**
|
213
|
+
and MDN has your back... [learn about the DOM and web APIs here.](https://developer.mozilla.org/en-US/docs/Web/API.)
|
214
|
+
|
215
|
+
### Extending Behavior
|
216
|
+
|
217
|
+
Want to extend things with custom functionality? **Let's do it.** 🔌
|
218
|
+
|
219
|
+
```js
|
220
|
+
// JavaScript
|
221
|
+
import morphdom from 'morphdom'
|
222
|
+
|
223
|
+
window.MyNamespace = {
|
224
|
+
morph: (from, to, options = {}) => {
|
225
|
+
morphdom(document.querySelector(from), to, options)
|
226
|
+
}
|
227
|
+
}
|
228
|
+
```
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
# Ruby
|
232
|
+
turbo_stream
|
233
|
+
.invoke "MyNamespace.morph", "#demo", "<div id='demo'><p>You've changed...</p></div>", {childrenOnly: true}
|
234
|
+
```
|
235
|
+
|
236
|
+
## Public API
|
237
|
+
|
238
|
+
There's only one method to consider, `invoke` defined in the
|
239
|
+
[tag builder](https://github.com/hopsoft/turbo_ready/blob/main/lib/turbo_ready/tag_builder.rb).
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
# Ruby
|
243
|
+
turbo_stream
|
244
|
+
.invoke(method, *args, selector: nil, camelize: true, id: nil)
|
245
|
+
# | | | | |
|
246
|
+
# | | | | |- Identifies this invocation (optional)
|
247
|
+
# | | | |
|
248
|
+
# | | | |- Should we camelize the JavaScript stuff? (optional)
|
249
|
+
# | | | (allows us to write snake_case Ruby)
|
250
|
+
# | | |
|
251
|
+
# | | |- An CSS selector for the element(s) to target (optional)
|
252
|
+
# | |
|
253
|
+
# | |- The arguments to pass to the JavaScript method being invoked (optional)
|
254
|
+
# |
|
255
|
+
# |- The JavaScript method to invoke (can use dot notation)
|
256
|
+
```
|
257
|
+
|
258
|
+
**NOTE:** The JavaScript method will be invoked on all matching elements when a `selector` is passed.
|
259
|
+
|
260
|
+
## A Word of Caution
|
261
|
+
|
262
|
+
Manually orchestrating DOM activity gets tedious fast.
|
263
|
+
**⚠️ Don't abuse this superpower!**
|
264
|
+
|
265
|
+
> With great power comes great responsibility. *-Uncle Ben*
|
266
|
+
|
267
|
+
This library is an extremely sharp tool. 🔪
|
268
|
+
Consider it a low-level building block that can be used to craft additional libraries with
|
269
|
+
great [DX](https://en.wikipedia.org/wiki/User_experience#Developer_experience)
|
270
|
+
like [CableReady](https://github.com/stimulusreflex/cable_ready)
|
271
|
+
and [StimulusReflex](https://github.com/stimulusreflex/stimulus_reflex).
|
272
|
+
|
273
|
+
Restrict your direct application usage to DOM manipulation that falls outside the purview of
|
274
|
+
[Turbo's official actions](https://turbo.hotwired.dev/reference/streams#the-seven-actions)...
|
275
|
+
*don't overdo it and find yourself maintaining spaghetti code reminiscent of the jQuery days.*
|
276
|
+
|
277
|
+
## Releasing
|
278
|
+
|
279
|
+
1. Run `yarn` and `bundle` to pick up the latest
|
280
|
+
1. Bump version number at `lib/turbo_ready/version.rb`. Pre-release versions use `.preN`
|
281
|
+
1. Run `rake build` and `yarn build`
|
282
|
+
1. Run `bin/standardize`
|
283
|
+
1. Commit and push changes to GitHub
|
284
|
+
1. Run `rake release`
|
285
|
+
1. Run `yarn publish --no-git-tag-version`
|
286
|
+
1. Yarn will prompt you for the new version. Pre-release versions use `-preN`
|
287
|
+
1. Commit and push changes to GitHub
|
288
|
+
1. Create a new release on GitHub ([here](https://github.com/hopsoft/turbo_ready/releases)) and generate the changelog for the stable release for it
|
289
|
+
|
290
|
+
## License
|
291
|
+
|
292
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
|
-
|
5
4
|
require "bundler/gem_tasks"
|
5
|
+
require "rake/testtask"
|
6
|
+
|
7
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
8
|
+
load "rails/tasks/engine.rake"
|
9
|
+
load "rails/tasks/statistics.rake"
|
10
|
+
|
11
|
+
Rake::TestTask.new do |test|
|
12
|
+
test.libs << "test"
|
13
|
+
test.test_files = FileList["test/**/*_test.rb"]
|
14
|
+
test.warning = false
|
15
|
+
end
|
16
|
+
|
17
|
+
task default: :test
|
@@ -1,2 +1,2 @@
|
|
1
|
-
function l(){let n=JSON.parse(this.templateContent.textContent),{id:h,
|
1
|
+
function l(){let n=JSON.parse(this.templateContent.textContent),{id:h,selector:c,receiver:a,method:r,args:i}=n,t=[self];switch(c&&(t=Array.from(document.querySelectorAll(c))),a&&(t=t.map(o=>{let e=o,s=a.split(".");for(;s.length>0;)e=e[s.shift()];return e})),r){case"dispatchEvent":let o=new CustomEvent(i[0],i[1]||{});t.forEach(e=>e.dispatchEvent(o));break;default:t.forEach(e=>e[r].apply(e,i))}}function f(n){n.invoke=l}var p={initialize:f};export{p as default};
|
2
2
|
//# sourceMappingURL=turbo_ready.js.map
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../javascript/turbo_ready.js"],
|
4
|
-
"sourcesContent": ["function invoke () {\n const payload = JSON.parse(this.templateContent.textContent)\n const { id,
|
5
|
-
"mappings": "AAAA,SAASA,GAAU,CACjB,IAAMC,EAAU,KAAK,MAAM,KAAK,gBAAgB,WAAW,EACrD,CAAE,GAAAC,EAAI,
|
6
|
-
"names": ["invoke", "payload", "id", "
|
4
|
+
"sourcesContent": ["function invoke () {\n const payload = JSON.parse(this.templateContent.textContent)\n const { id, selector, receiver, method, args } = payload\n let receivers = [self]\n if (selector) receivers = Array.from(document.querySelectorAll(selector))\n\n if (receiver) {\n receivers = receivers.map(r => {\n let context = r\n const chain = receiver.split('.')\n while (chain.length > 0) context = context[chain.shift()]\n return context\n })\n }\n\n switch (method) {\n case 'dispatchEvent':\n const evt = new CustomEvent(args[0], args[1] || {})\n receivers.forEach(r => r.dispatchEvent(evt))\n break\n default:\n receivers.forEach(r => r[method].apply(r, args))\n }\n}\n\nfunction initialize (streamActions) {\n streamActions.invoke = invoke\n}\n\nexport default { initialize }\n"],
|
5
|
+
"mappings": "AAAA,SAASA,GAAU,CACjB,IAAMC,EAAU,KAAK,MAAM,KAAK,gBAAgB,WAAW,EACrD,CAAE,GAAAC,EAAI,SAAAC,EAAU,SAAAC,EAAU,OAAAC,EAAQ,KAAAC,CAAK,EAAIL,EAC7CM,EAAY,CAAC,IAAI,EAYrB,OAXIJ,IAAUI,EAAY,MAAM,KAAK,SAAS,iBAAiBJ,CAAQ,CAAC,GAEpEC,IACFG,EAAYA,EAAU,IAAIC,GAAK,CAC7B,IAAIC,EAAUD,EACRE,EAAQN,EAAS,MAAM,GAAG,EAChC,KAAOM,EAAM,OAAS,GAAGD,EAAUA,EAAQC,EAAM,MAAM,GACvD,OAAOD,CACT,CAAC,GAGKJ,OACD,gBACH,IAAMM,EAAM,IAAI,YAAYL,EAAK,GAAIA,EAAK,IAAM,CAAC,CAAC,EAClDC,EAAU,QAAQC,GAAKA,EAAE,cAAcG,CAAG,CAAC,EAC3C,cAEAJ,EAAU,QAAQC,GAAKA,EAAEH,GAAQ,MAAMG,EAAGF,CAAI,CAAC,EAErD,CAEA,SAASM,EAAYC,EAAe,CAClCA,EAAc,OAASb,CACzB,CAEA,IAAOc,EAAQ,CAAE,WAAAF,CAAW",
|
6
|
+
"names": ["invoke", "payload", "id", "selector", "receiver", "method", "args", "receivers", "r", "context", "chain", "evt", "initialize", "streamActions", "turbo_ready_default"]
|
7
7
|
}
|
Binary file
|
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
function invoke () {
|
2
2
|
const payload = JSON.parse(this.templateContent.textContent)
|
3
|
-
const { id,
|
3
|
+
const { id, selector, receiver, method, args } = payload
|
4
4
|
let receivers = [self]
|
5
5
|
if (selector) receivers = Array.from(document.querySelectorAll(selector))
|
6
6
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TurboReady::BroadcastInvokeJob < ActiveJob::Base
|
4
|
+
include TurboReady::TagHelper
|
5
|
+
|
6
|
+
def perform(*streamables, method, **kwargs)
|
7
|
+
Turbo::StreamsChannel.broadcast_stream_to(*streamables, content: turbo_stream_invoke_tag(method, **kwargs))
|
8
|
+
end
|
9
|
+
end
|
data/bin/loc
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "turbo-rails"
|
4
|
+
require_relative "version"
|
5
|
+
require_relative "patches"
|
6
|
+
|
7
|
+
class TurboReady::Engine < ::Rails::Engine
|
8
|
+
config.after_initialize do
|
9
|
+
::Turbo::Streams::TagBuilder.send :include, TurboReady::Patches::TagBuilder
|
10
|
+
::Turbo::Streams::Broadcasts.send :include, TurboReady::Patches::Broadcasts
|
11
|
+
::Turbo::Broadcastable.send :include, TurboReady::Patches::Broadcastable
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Patch for Turbo::Broadcastable which is mixed into ActiveRecord
|
4
|
+
# SEE: https://github.com/hotwired/turbo-rails/blob/main/app/models/concerns/turbo/broadcastable.rb
|
5
|
+
module TurboReady::Patches::Broadcastable
|
6
|
+
def broadcast_invoke_to(*streamables, method, **kwargs)
|
7
|
+
Turbo::StreamsChannel.broadcast_invoke_to(*streamables, method, **kwargs)
|
8
|
+
end
|
9
|
+
|
10
|
+
def broadcast_invoke_later_to(*streamables, method, **kwargs)
|
11
|
+
Turbo::StreamsChannel.broadcast_invoke_later_to(*streamables, method, **kwargs)
|
12
|
+
end
|
13
|
+
|
14
|
+
def broadcast_invoke(method, **kwargs)
|
15
|
+
broadcast_invoke_to(self, method, **kwargs)
|
16
|
+
end
|
17
|
+
|
18
|
+
def broadcast_invoke_later(method, **kwargs)
|
19
|
+
broadcast_invoke_later_to(self, method, **kwargs)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../tag_helper"
|
4
|
+
require_relative "../../../app/jobs/turbo_ready/broadcast_invoke_job"
|
5
|
+
|
6
|
+
# Patch for Turbo::Streams::Broadcasts which is mixed into Turbo::StreamsChannel
|
7
|
+
# SEE: https://github.com/hotwired/turbo-rails/blob/main/app/channels/turbo/streams/broadcasts.rb
|
8
|
+
module TurboReady::Patches::Broadcasts
|
9
|
+
include TurboReady::TagHelper
|
10
|
+
|
11
|
+
def broadcast_invoke_to(*streamables, method, **kwargs)
|
12
|
+
broadcast_stream_to(*streamables, content: turbo_stream_invoke_tag(method, **kwargs))
|
13
|
+
end
|
14
|
+
|
15
|
+
def broadcast_invoke_later_to(*streamables, method, **kwargs)
|
16
|
+
TurboReady::BroadcastInvokeJob.perform_later(*streamables, method, **kwargs)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../string_wrapper"
|
4
|
+
require_relative "../tag_helper"
|
5
|
+
|
6
|
+
# Patch for Turbo::Streams::TagBuilder typically exposed as `turbo_stream`
|
7
|
+
# SEE: https://github.com/hotwired/turbo-rails/blob/main/app/models/turbo/streams/tag_builder.rb
|
8
|
+
module TurboReady::Patches::TagBuilder
|
9
|
+
include TurboReady::TagHelper
|
10
|
+
|
11
|
+
def invoke(method, args: [], selector: nil, camelize: true, id: nil)
|
12
|
+
tag = turbo_stream_invoke_tag(method, args: args, selector: selector, camelize: camelize, id: id)
|
13
|
+
TurboReady::StringWrapper.new tag
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TurboReady::StringWrapper
|
4
|
+
include TurboReady::TagHelper
|
5
|
+
attr_reader :turbo_stream_string
|
6
|
+
|
7
|
+
delegate_missing_to :turbo_stream_string
|
8
|
+
|
9
|
+
def initialize(turbo_stream_string, turbo_stream_strings: Set.new)
|
10
|
+
@turbo_stream_string = turbo_stream_string
|
11
|
+
@turbo_stream_strings = turbo_stream_strings
|
12
|
+
@turbo_stream_strings << turbo_stream_string
|
13
|
+
end
|
14
|
+
|
15
|
+
def invoke(...)
|
16
|
+
TurboReady::StringWrapper.new turbo_stream_invoke_tag(...), turbo_stream_strings: turbo_stream_strings
|
17
|
+
end
|
18
|
+
|
19
|
+
def flush
|
20
|
+
turbo_stream_strings.to_a.join("\n").html_safe
|
21
|
+
ensure
|
22
|
+
turbo_stream_strings.clear
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :to_s, :flush
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def turbo_stream_strings
|
30
|
+
@turbo_stream_strings ||= Set.new
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TurboReady::TagHelper
|
4
|
+
def turbo_stream_invoke_tag(method, args: [], selector: nil, camelize: true, id: nil)
|
5
|
+
id = SecureRandom.uuid if id.blank?
|
6
|
+
payload = HashWithIndifferentAccess.new(id: id.to_s, selector: selector)
|
7
|
+
payload.merge! method_details(method, args: args, camelize: camelize)
|
8
|
+
payload.select! { |_, v| v.present? }
|
9
|
+
%(<turbo-stream action="invoke" target="DOM"><template>#{payload.to_json}</template></turbo-stream>).html_safe
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def method_details(method, args: [], camelize: true)
|
15
|
+
if camelize
|
16
|
+
method = camelize_method(method)
|
17
|
+
args = camelize_args(args)
|
18
|
+
end
|
19
|
+
|
20
|
+
method_parts = method.to_s.split(".")
|
21
|
+
|
22
|
+
HashWithIndifferentAccess.new(
|
23
|
+
receiver: method_parts[0..-2].join("."),
|
24
|
+
method: method_parts.last,
|
25
|
+
args: args
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def camelize_method(method)
|
30
|
+
method.to_s.split(".").map { |s| s.camelize(:lower) }.join(".")
|
31
|
+
end
|
32
|
+
|
33
|
+
def camelize_args(args = [])
|
34
|
+
args.map do |param|
|
35
|
+
if param.is_a? Hash
|
36
|
+
param.deep_transform_keys { |key| key.to_s.camelize(:lower) }
|
37
|
+
else
|
38
|
+
param
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/turbo_ready/version.rb
CHANGED
data/lib/turbo_ready.rb
CHANGED
@@ -1,12 +1,3 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "turbo_ready/
|
4
|
-
require "turbo_ready/railtie"
|
5
|
-
require "turbo_ready/string"
|
6
|
-
require "turbo_ready/tag_builder"
|
7
|
-
|
8
|
-
module TurboReady
|
9
|
-
def self.patch!
|
10
|
-
Turbo::Streams::TagBuilder.send :include, TurboReady::TagBuilder
|
11
|
-
end
|
12
|
-
end
|
3
|
+
require "turbo_ready/engine"
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "turbo_ready",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.5",
|
4
4
|
"description": "Take full control of the DOM with Turbo Streams",
|
5
5
|
"main": "app/assets/builds/turbo_ready.js",
|
6
6
|
"repository": "https://github.com/hopsoft/turbo_ready",
|
@@ -10,7 +10,7 @@
|
|
10
10
|
"@hotwired/turbo-rails": ">= 7.1"
|
11
11
|
},
|
12
12
|
"devDependencies": {
|
13
|
-
"esbuild": "^0.
|
13
|
+
"esbuild": "^0.15.5",
|
14
14
|
"eslint": "^8.19.0",
|
15
15
|
"prettier-standard": "^16.4.1"
|
16
16
|
},
|
data/turbo_ready.gemspec
CHANGED
@@ -2,27 +2,36 @@
|
|
2
2
|
|
3
3
|
require_relative "lib/turbo_ready/version"
|
4
4
|
|
5
|
-
Gem::Specification.new do |
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "turbo_ready"
|
7
|
+
s.version = TurboReady::VERSION
|
8
|
+
s.authors = ["Nate Hopkins (hopsoft)"]
|
9
|
+
s.email = ["natehop@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/hopsoft/turbo_ready"
|
11
|
+
s.summary = "Take full control of the DOM with Turbo Streams"
|
12
|
+
s.description = s.summary
|
13
|
+
s.license = "MIT"
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
s.metadata["homepage_uri"] = s.homepage
|
16
|
+
s.metadata["source_code_uri"] = s.homepage
|
17
|
+
s.metadata["changelog_uri"] = s.homepage + "/blob/master/CHANGELOG.md"
|
18
18
|
|
19
|
-
|
19
|
+
s.files = Dir["lib/**/*.rb", "app/**/*", "bin/*", "[A-Z]*"]
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
s.add_dependency "rails", ">= 6.1"
|
22
|
+
s.add_dependency "turbo-rails", ">= 1.1"
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
s.add_development_dependency "capybara"
|
25
|
+
s.add_development_dependency "importmap-rails"
|
26
|
+
s.add_development_dependency "magic_frozen_string_literal"
|
27
|
+
s.add_development_dependency "net-smtp"
|
28
|
+
s.add_development_dependency "pry-byebug"
|
29
|
+
s.add_development_dependency "puma"
|
30
|
+
s.add_development_dependency "rake"
|
31
|
+
s.add_development_dependency "rexml"
|
32
|
+
s.add_development_dependency "selenium-webdriver"
|
33
|
+
s.add_development_dependency "sprockets-rails"
|
34
|
+
s.add_development_dependency "sqlite3"
|
35
|
+
s.add_development_dependency "standardrb"
|
36
|
+
s.add_development_dependency "webdrivers"
|
28
37
|
end
|