react_on_rails_pro 17.0.0.rc.10 → 17.0.0.rc.11
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.lock +3 -3
- data/LICENSE +145 -49
- data/LICENSE_SETUP.md +2 -2
- data/app/helpers/react_on_rails_pro_helper.rb +86 -5
- data/lib/react_on_rails_pro/engine.rb +3 -3
- data/lib/react_on_rails_pro/license_validator.rb +8 -36
- data/lib/react_on_rails_pro/utils.rb +4 -9
- data/lib/react_on_rails_pro/version.rb +1 -1
- data/react_on_rails_pro.gemspec +1 -1
- data/sig/react_on_rails_pro/license_validator.rbs +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 355e4b67d6e24dfdf3303aa6de3d422a78d15f52c77fd8c330269d20df684364
|
|
4
|
+
data.tar.gz: 43821f77ed457678324aedd29ef9ea8f8c1b1eeae1633122ce79a11b82c2a8bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 374a52f15b4167b4d081cd548dc1d257280cc3014919419c7ca1fdf66fb3d580b47be291727fe034417b883de488205630ba3935f0dcaf07622ceebd7edf0484
|
|
7
|
+
data.tar.gz: 88cac8f1d67b6fce6bee50f2ff4fab294cc338afa3ac30c579c1e724527ba39a2d090171b6678eaf287b455d7f3fc76a7ec0e4cfa8128c6648c3502a9996bb7a
|
data/Gemfile.lock
CHANGED
|
@@ -9,7 +9,7 @@ GIT
|
|
|
9
9
|
PATH
|
|
10
10
|
remote: ..
|
|
11
11
|
specs:
|
|
12
|
-
react_on_rails (17.0.0.rc.
|
|
12
|
+
react_on_rails (17.0.0.rc.11)
|
|
13
13
|
addressable
|
|
14
14
|
connection_pool
|
|
15
15
|
execjs (~> 2.5)
|
|
@@ -20,14 +20,14 @@ PATH
|
|
|
20
20
|
PATH
|
|
21
21
|
remote: .
|
|
22
22
|
specs:
|
|
23
|
-
react_on_rails_pro (17.0.0.rc.
|
|
23
|
+
react_on_rails_pro (17.0.0.rc.11)
|
|
24
24
|
async (>= 2.29)
|
|
25
25
|
async-http (~> 0.95)
|
|
26
26
|
execjs (~> 2.9)
|
|
27
27
|
io-endpoint (~> 0.17.0)
|
|
28
28
|
jwt (>= 2.5, < 4)
|
|
29
29
|
nokogiri (>= 1.12, < 2)
|
|
30
|
-
react_on_rails (= 17.0.0.rc.
|
|
30
|
+
react_on_rails (= 17.0.0.rc.11)
|
|
31
31
|
|
|
32
32
|
GEM
|
|
33
33
|
remote: https://rubygems.org/
|
data/LICENSE
CHANGED
|
@@ -1,98 +1,194 @@
|
|
|
1
|
-
|
|
1
|
+
# ShakaCode React on Rails Pro – End User License Agreement (EULA)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
_Version 2.3 — 2026-07-14_\
|
|
4
|
+
© 2015–2026 ShakaCode, LLC. All rights reserved.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
---
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
## 1. Definitions
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
- **Organization** – the single legal entity identified in the order (e.g., GitHub Sponsors, invoice).
|
|
11
|
+
- **Licensee** – the Organization or any other person or entity exercising royalty-free rights under Section 4.
|
|
12
|
+
- **Production Use** – any use of the Software in connection with a live application, website, or service accessed by end users **other than**:
|
|
13
|
+
- evaluation or testing
|
|
14
|
+
- classroom instruction, tutorials, workshops, coursework
|
|
15
|
+
- recorded demos, livestreams, or videos
|
|
16
|
+
- personal/hobby experiments not offered as a service
|
|
17
|
+
- **Complimentary OSS License** – a license issued under Section 4.1 at no charge to a qualifying open-source Organization.
|
|
18
|
+
- **Covered HTML Document** – an HTML document containing output rendered by the integrated React on Rails Pro product.
|
|
19
|
+
- **Attribution Provider** – the part of the integrated React on Rails Pro product that generates and inserts the Generated Attribution on behalf of the product as a whole.
|
|
20
|
+
- **Generated Attribution** – the complete, non-visual HTML comment emitted by the Attribution Provider, including its license-status suffix.
|
|
10
21
|
|
|
22
|
+
---
|
|
11
23
|
|
|
12
|
-
|
|
24
|
+
## 2. Grant of License (Per-Organization)
|
|
13
25
|
|
|
14
|
-
|
|
26
|
+
Subject to this Agreement, ShakaCode grants the subscribing Organization a **non-exclusive, non-transferable** license, during the applicable license term, to install, internally modify, and use React on Rails Pro (“Software”) in the Organization’s own applications, websites, and services, whether accessed internally or by public end users.
|
|
15
27
|
|
|
16
|
-
|
|
28
|
+
This grant does not permit redistribution or sublicensing of the Software, offering the Software itself to third parties, or using one Organization’s license for another Organization or consulting client.
|
|
17
29
|
|
|
18
|
-
|
|
30
|
+
---
|
|
19
31
|
|
|
20
|
-
|
|
32
|
+
## 3. Consulting Firms and Individual Consultants
|
|
21
33
|
|
|
22
|
-
|
|
34
|
+
- **Consulting Firms** – this license covers only the firm’s own applications, websites, and services, whether accessed internally or by public end users. Each client Organization requires its own license for any Production Use.
|
|
35
|
+
- **Individual Consultants** – this license covers only the consultant’s own applications, websites, and services personally operated by them, not client Organizations. Each client Organization must obtain its own license.
|
|
23
36
|
|
|
24
|
-
|
|
37
|
+
---
|
|
25
38
|
|
|
26
|
-
|
|
39
|
+
## 4. Non-Commercial / Educational / Demo Use (Free)
|
|
27
40
|
|
|
28
|
-
|
|
41
|
+
Free, royalty-free use is permitted for:
|
|
29
42
|
|
|
30
|
-
|
|
43
|
+
- classroom instruction, training, workshops, coursework;
|
|
44
|
+
- tutorials, blog posts, livestreams, or videos;
|
|
45
|
+
- personal/hobby projects not used in production;
|
|
46
|
+
- demo apps showcasing coding techniques.
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
**Note:** This clause does **not** permit any Production Use by any entity (commercial, non-profit, or individual). All Production Use requires a paid subscription under this Agreement, except as provided in Section 4.1.
|
|
33
49
|
|
|
34
|
-
|
|
50
|
+
**4.1 Open-Source Project License (Complimentary)**
|
|
35
51
|
|
|
36
|
-
|
|
52
|
+
ShakaCode may, at its sole discretion, issue a complimentary "oss" license to an Organization that meets **all** of the following criteria:
|
|
37
53
|
|
|
38
|
-
|
|
54
|
+
1. The Organization deploys the Software as part of a project whose source code is publicly available under an [OSI-approved license](https://opensource.org/licenses).
|
|
55
|
+
2. The Organization's annual revenue (or total funding received, if pre-revenue) does not exceed USD $1,000,000.
|
|
56
|
+
3. The Organization applies by emailing [justin@shakacode.com](mailto:justin@shakacode.com) and provides truthful information about the project and Organization.
|
|
39
57
|
|
|
40
|
-
|
|
58
|
+
**Terms of Complimentary OSS Licenses:**
|
|
41
59
|
|
|
42
|
-
|
|
60
|
+
- The attribution requirement in Section 6 applies and may not be waived.
|
|
61
|
+
- Complimentary OSS Licenses are granted for a fixed term of one (1) year from the date of issuance and may be renewed upon request.
|
|
62
|
+
- ShakaCode may revoke a Complimentary OSS License (i) immediately upon written notice if the Organization violates this Agreement, or (ii) on thirty (30) days' written notice if the Organization no longer meets the eligibility criteria.
|
|
63
|
+
- All other terms of this Agreement apply (including Sections 5, 7, 9, and 12), subject to the modifications for Complimentary OSS Licenses in Section 7.
|
|
43
64
|
|
|
44
|
-
|
|
65
|
+
---
|
|
45
66
|
|
|
46
|
-
|
|
67
|
+
## 5. Restrictions
|
|
47
68
|
|
|
48
|
-
|
|
69
|
+
The Organization shall not:
|
|
49
70
|
|
|
50
|
-
|
|
71
|
+
1. redistribute or resell the Software or derivatives;
|
|
72
|
+
2. remove, obfuscate, or disable required attribution;
|
|
73
|
+
3. use the Software to build a directly competing product exposing substantially similar functionality;
|
|
74
|
+
4. **circumvent, bypass, modify, disable, or tamper with any license validation mechanisms, license checks, or authentication systems;**
|
|
75
|
+
5. **reverse engineer, decompile, or disassemble the Software for the purpose of circumventing license restrictions;**
|
|
76
|
+
6. **create, use, or distribute any tools, scripts, patches, or modifications designed to enable unauthorized use of Pro features;**
|
|
77
|
+
7. **access or use the Software outside the rights granted by this Agreement, including any Production Use without a valid, active paid or Complimentary OSS License.**
|
|
51
78
|
|
|
52
|
-
|
|
79
|
+
---
|
|
53
80
|
|
|
54
|
-
|
|
81
|
+
## 6. Product-Level Attribution (HTML Source)
|
|
55
82
|
|
|
56
|
-
|
|
83
|
+
Every Covered HTML Document must retain exactly one complete, unmodified Generated Attribution in its HTML source. The Attribution Provider emits this comment once on behalf of the integrated React on Rails Pro product. A related component, including `react-on-rails-rsc`, has no independent obligation to insert another attribution comment when it does not control the HTML document or generate or insert the Generated Attribution.
|
|
57
84
|
|
|
58
|
-
|
|
85
|
+
This requirement applies to paid Production Use, Production Use under a Complimentary OSS License, and every royalty-free use permitted by Section 4.
|
|
59
86
|
|
|
60
|
-
|
|
87
|
+
The Generated Attribution uses the following form, where the status suffix is generated by the Software:
|
|
61
88
|
|
|
62
|
-
|
|
89
|
+
```html
|
|
90
|
+
<!-- Powered by React on Rails Pro (c) ShakaCode | STATUS -->
|
|
91
|
+
```
|
|
63
92
|
|
|
64
|
-
|
|
93
|
+
For a valid license credential, the status suffix is `Licensed` and does not identify the Organization. Expired, invalid, and missing license credentials use `LICENSE EXPIRED`, `INVALID LICENSE`, and `UNLICENSED`, respectively. `UNLICENSED` indicates that no license credential was present; that status alone does not establish a violation because the use may be permitted by Section 4.
|
|
65
94
|
|
|
66
|
-
|
|
95
|
+
The Licensee may not remove, modify, obfuscate, or disable the Generated Attribution.
|
|
67
96
|
|
|
68
|
-
|
|
97
|
+
---
|
|
69
98
|
|
|
70
|
-
|
|
99
|
+
## 7. Fees; Term; Termination
|
|
71
100
|
|
|
72
|
-
|
|
101
|
+
Paid subscriptions may be purchased or renewed at [pro.reactonrails.com](https://pro.reactonrails.com/) or through another ShakaCode-approved order channel.
|
|
73
102
|
|
|
74
|
-
|
|
103
|
+
Fees and billing terms are as agreed in the applicable order (e.g., GitHub Sponsors subscription or annual invoice).\
|
|
104
|
+
For paid subscriptions, the license remains active only while fees are paid. ShakaCode may suspend or terminate for non-payment or material breach. Complimentary OSS Licenses remain active for the term specified in the grant, subject to the revocation terms in Section 4.1.\
|
|
105
|
+
Upon termination, lapse, or revocation, the Organization must immediately cease use and remove the Software (including derivatives) from all Production systems and repositories, except for (a) non-commercial uses explicitly permitted in Section 4, or (b) Complimentary OSS Licenses revoked under Section 4.1(ii) for eligibility changes, in which case the Organization has thirty (30) days from written notice to comply.
|
|
75
106
|
|
|
76
|
-
|
|
107
|
+
---
|
|
77
108
|
|
|
78
|
-
|
|
109
|
+
## 8. Updates & Support
|
|
79
110
|
|
|
80
|
-
|
|
111
|
+
While subscribed, the Organization receives software updates and reasonable support (email or issue tracker, business hours). No specific response or resolution times are guaranteed unless set out in an order or separate SLA.
|
|
81
112
|
|
|
82
|
-
|
|
113
|
+
---
|
|
83
114
|
|
|
84
|
-
|
|
115
|
+
## 9. Verification / Audit
|
|
85
116
|
|
|
86
|
-
|
|
117
|
+
If ShakaCode reasonably suspects non-compliance, the Organization will cooperate in good faith to verify compliance, including enabling inspection for attribution presence and providing a usage statement. ShakaCode will use commercially reasonable efforts to minimize disruption.
|
|
87
118
|
|
|
88
|
-
|
|
119
|
+
**9.1 Detailed Audits**\
|
|
120
|
+
ShakaCode or a certified auditor acting on its behalf may, upon reasonable request and at ShakaCode’s expense, audit the Organization’s use of the Software to verify compliance with this Agreement. Audits may be conducted by mail, electronically, or by in-person visits during regular business hours and shall minimize disruption to the Organization’s business. If the audit reveals a material unauthorized use, the Organization shall reimburse ShakaCode for reasonable audit costs.
|
|
89
121
|
|
|
90
|
-
|
|
122
|
+
---
|
|
91
123
|
|
|
92
|
-
|
|
124
|
+
## 10. Feedback & Contributions
|
|
93
125
|
|
|
94
|
-
|
|
126
|
+
By submitting feedback or improvements, the Organization grants ShakaCode a worldwide, royalty-free, irrevocable license to use and incorporate them.
|
|
95
127
|
|
|
96
|
-
|
|
128
|
+
---
|
|
97
129
|
|
|
98
|
-
|
|
130
|
+
## 11. Intellectual Property
|
|
131
|
+
|
|
132
|
+
The Software is **licensed, not sold**. ShakaCode retains all rights, title, and interest, including all intellectual property rights.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 12. Confidentiality
|
|
137
|
+
|
|
138
|
+
License keys and any non-public materials are ShakaCode confidential information. The Organization will protect them with at least reasonable care.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 13. Warranty Disclaimer
|
|
143
|
+
|
|
144
|
+
> EXCEPT AS EXPRESSLY PROVIDED IN §8, THE SOFTWARE IS PROVIDED “AS IS,” WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 14. Limitation of Liability
|
|
149
|
+
|
|
150
|
+
To the maximum extent permitted by law, ShakaCode is not liable for indirect, incidental, special, consequential, or punitive damages.\
|
|
151
|
+
Direct damages are limited to amounts paid in the 12 months preceding the claim.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 15. Indemnification
|
|
156
|
+
|
|
157
|
+
The Organization agrees to defend, indemnify, and hold harmless ShakaCode and its affiliates from any claims, losses, damages, liabilities, costs, or expenses (including legal fees) arising out of the Organization’s use of the Software or breach of this Agreement.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 16. Export Compliance
|
|
162
|
+
|
|
163
|
+
The Organization agrees to comply with all applicable export laws and regulations, including restrictions on export, re-export, or redistribution of the Software.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 17. Attorneys’ Fees and Costs
|
|
168
|
+
|
|
169
|
+
In any enforcement or legal action arising under this Agreement, the prevailing party shall be entitled to recover reasonable attorneys’ fees and costs.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 18. Governing Law; Venue
|
|
174
|
+
|
|
175
|
+
This Agreement is governed by the laws of the **State of Hawaii**, USA. Exclusive jurisdiction and venue lie in the courts located therein.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 19. Miscellaneous
|
|
180
|
+
|
|
181
|
+
- **19.1 Severability**\
|
|
182
|
+
If any provision is held invalid or unenforceable, the remainder shall continue in full force.
|
|
183
|
+
|
|
184
|
+
- **19.2 Waiver**\
|
|
185
|
+
Failure to enforce any provision is not a waiver of rights.
|
|
186
|
+
|
|
187
|
+
- **19.3 Assignment**\
|
|
188
|
+
The Organization may not assign this Agreement without prior written consent.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 20. Entire Agreement; Order of Precedence
|
|
193
|
+
|
|
194
|
+
This EULA and any order (pricing/term) are the entire agreement. If there is a conflict, the order controls.
|
data/LICENSE_SETUP.md
CHANGED
|
@@ -127,7 +127,7 @@ Organization: Acme Corp
|
|
|
127
127
|
Plan: paid
|
|
128
128
|
Expiration: 2025-12-31
|
|
129
129
|
Days left: 180
|
|
130
|
-
Attribution:
|
|
130
|
+
Attribution: required
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
**Example JSON output:**
|
|
@@ -138,7 +138,7 @@ Attribution: not required
|
|
|
138
138
|
"organization": "Acme Corp",
|
|
139
139
|
"plan": "paid",
|
|
140
140
|
"expiration": "2025-12-31T00:00:00Z",
|
|
141
|
-
"attribution_required":
|
|
141
|
+
"attribution_required": true,
|
|
142
142
|
"days_remaining": 180,
|
|
143
143
|
"renewal_required": false
|
|
144
144
|
}
|
|
@@ -34,6 +34,11 @@ module ReactOnRailsProHelper
|
|
|
34
34
|
SCRIPT_CLOSE_TAG_LENGTH = 8
|
|
35
35
|
STATIC_RSC_PAYLOAD_SCRIPT_MARKER_ATTRIBUTE = "data-react-on-rails-rsc-payload"
|
|
36
36
|
STATIC_RSC_ASSET_DIAGNOSTIC_CACHE_MUTEX = Mutex.new
|
|
37
|
+
HTML_COMMENT_OPEN = "<!--"
|
|
38
|
+
HTML_COMMENT_CLOSE = "-->"
|
|
39
|
+
PRO_ATTRIBUTION_MARKER = "Powered by React on Rails Pro"
|
|
40
|
+
PRO_ATTRIBUTION_COMMENT_PREFIX = "Powered by React on Rails Pro (c) ShakaCode"
|
|
41
|
+
RAILS_CONTEXT_MARKER = "js-react-on-rails-context"
|
|
37
42
|
@static_rsc_asset_diagnostic_cache = {}
|
|
38
43
|
|
|
39
44
|
class << self
|
|
@@ -452,10 +457,81 @@ module ReactOnRailsProHelper
|
|
|
452
457
|
end
|
|
453
458
|
ReactOnRailsPro::Cache.register_normalized_tags(normalized_cache_tags, cache_key, cache_options) unless cache_hit
|
|
454
459
|
load_pack_for_cached_react_component(component_name, options) if cache_hit
|
|
460
|
+
result = normalize_cached_pro_attribution(result) if cache_hit
|
|
455
461
|
|
|
456
462
|
add_component_cache_metadata(result, cache_key, cache_hit)
|
|
457
463
|
end
|
|
458
464
|
|
|
465
|
+
def normalize_cached_pro_attribution(result)
|
|
466
|
+
return normalize_cached_pro_attribution_html(result) if result.is_a?(String)
|
|
467
|
+
|
|
468
|
+
return result unless result.is_a?(Hash) && result.key?(ReactOnRails::Helper::COMPONENT_HTML_KEY)
|
|
469
|
+
|
|
470
|
+
result.merge(
|
|
471
|
+
ReactOnRails::Helper::COMPONENT_HTML_KEY =>
|
|
472
|
+
normalize_cached_pro_attribution_html(result[ReactOnRails::Helper::COMPONENT_HTML_KEY])
|
|
473
|
+
)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def normalize_cached_pro_attribution_html(html)
|
|
477
|
+
return html if @rendered_rails_context && !html.include?(PRO_ATTRIBUTION_MARKER) &&
|
|
478
|
+
!html.include?(RAILS_CONTEXT_MARKER)
|
|
479
|
+
|
|
480
|
+
was_html_safe = html.html_safe?
|
|
481
|
+
normalized_html = strip_leading_pro_attribution_comments(html)
|
|
482
|
+
normalized_html = strip_leading_rails_context_script(normalized_html)
|
|
483
|
+
normalized_html = prepend_render_rails_context(normalized_html)
|
|
484
|
+
|
|
485
|
+
was_html_safe ? normalized_html : String.new(normalized_html)
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def strip_leading_pro_attribution_comments(html)
|
|
489
|
+
cursor = 0
|
|
490
|
+
stripped_comment = false
|
|
491
|
+
|
|
492
|
+
loop do
|
|
493
|
+
comment_start = html_space_end_index(html, cursor)
|
|
494
|
+
break unless html[comment_start, HTML_COMMENT_OPEN.length] == HTML_COMMENT_OPEN
|
|
495
|
+
|
|
496
|
+
content_start = html_space_end_index(html, comment_start + HTML_COMMENT_OPEN.length)
|
|
497
|
+
prefix_end = content_start + PRO_ATTRIBUTION_COMMENT_PREFIX.length
|
|
498
|
+
break unless html[content_start, PRO_ATTRIBUTION_COMMENT_PREFIX.length] == PRO_ATTRIBUTION_COMMENT_PREFIX
|
|
499
|
+
|
|
500
|
+
comment_end = html.index(HTML_COMMENT_CLOSE, prefix_end)
|
|
501
|
+
break unless comment_end
|
|
502
|
+
|
|
503
|
+
separator_index = html_space_end_index(html, prefix_end)
|
|
504
|
+
break unless separator_index == comment_end || html[separator_index] == "|"
|
|
505
|
+
|
|
506
|
+
cursor = html_space_end_index(html, comment_end + HTML_COMMENT_CLOSE.length)
|
|
507
|
+
stripped_comment = true
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
stripped_comment ? (html[cursor..] || "") : html
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def strip_leading_rails_context_script(html)
|
|
514
|
+
script_start = html_space_end_index(html, 0)
|
|
515
|
+
return html unless html_ascii_case_insensitive_match?(html, SCRIPT_OPEN_TAG, script_start)
|
|
516
|
+
return html unless html_tag_name_boundary?(html, script_start + SCRIPT_OPEN_TAG_LENGTH)
|
|
517
|
+
|
|
518
|
+
opening_tag_end = html_tag_end_index(html, script_start + SCRIPT_OPEN_TAG_LENGTH)
|
|
519
|
+
return html unless opening_tag_end
|
|
520
|
+
|
|
521
|
+
closing_tag_range = html_script_closing_tag_range(html, opening_tag_end + 1)
|
|
522
|
+
return html unless closing_tag_range
|
|
523
|
+
|
|
524
|
+
script_node = Nokogiri::HTML5.fragment(html[script_start..closing_tag_range.end]).at_css("script")
|
|
525
|
+
return html unless script_node && script_node["id"] == RAILS_CONTEXT_MARKER
|
|
526
|
+
|
|
527
|
+
html[html_space_end_index(html, closing_tag_range.end + 1)..] || ""
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def html_space_end_index(html, cursor)
|
|
531
|
+
cursor += 1 while cursor < html.length && HTML_SPACE_CHARACTERS.include?(html[cursor])
|
|
532
|
+
cursor
|
|
533
|
+
end
|
|
534
|
+
|
|
459
535
|
def add_component_cache_metadata(result, cache_key, cache_hit)
|
|
460
536
|
return result unless result.is_a?(Hash)
|
|
461
537
|
|
|
@@ -596,6 +672,7 @@ module ReactOnRailsProHelper
|
|
|
596
672
|
load_pack_for_cached_react_component(component_name, render_options) if cache_hit
|
|
597
673
|
|
|
598
674
|
cache_diagnostics[:hit] = cache_hit
|
|
675
|
+
result = normalize_cached_pro_attribution(result) if cache_hit
|
|
599
676
|
result
|
|
600
677
|
end
|
|
601
678
|
|
|
@@ -1026,14 +1103,17 @@ module ReactOnRailsProHelper
|
|
|
1026
1103
|
def handle_stream_cache_hit(component_name, raw_options, auto_load_bundle, cached_chunks)
|
|
1027
1104
|
load_pack_for_cached_react_component(component_name, raw_options.merge(auto_load_bundle:))
|
|
1028
1105
|
|
|
1029
|
-
initial_result
|
|
1106
|
+
initial_result = normalize_cached_pro_attribution(cached_chunks.first)
|
|
1030
1107
|
|
|
1031
1108
|
# Enqueue remaining chunks asynchronously
|
|
1032
|
-
@async_barrier.async do
|
|
1033
|
-
|
|
1109
|
+
@async_barrier.async do |task|
|
|
1110
|
+
task.yield
|
|
1111
|
+
|
|
1112
|
+
cached_chunks.each_with_index do |chunk, index|
|
|
1113
|
+
next if index.zero?
|
|
1034
1114
|
break if response.stream.closed?
|
|
1035
1115
|
|
|
1036
|
-
@main_output_queue.enqueue(chunk)
|
|
1116
|
+
@main_output_queue.enqueue(normalize_cached_pro_attribution(chunk))
|
|
1037
1117
|
end
|
|
1038
1118
|
rescue Async::Queue::ClosedError
|
|
1039
1119
|
# Queue closed due to error/disconnect in another component — stop enqueuing
|
|
@@ -1122,7 +1202,8 @@ module ReactOnRailsProHelper
|
|
|
1122
1202
|
if cached_result
|
|
1123
1203
|
Rails.logger.debug { "React on Rails Pro async cache HIT for #{cache_key.inspect}" }
|
|
1124
1204
|
load_pack_for_cached_react_component(component_name, cache_options)
|
|
1125
|
-
|
|
1205
|
+
normalized_result = normalize_cached_pro_attribution(cached_result)
|
|
1206
|
+
return ReactOnRailsPro::ImmediateAsyncValue.new(normalized_result)
|
|
1126
1207
|
end
|
|
1127
1208
|
|
|
1128
1209
|
Rails.logger.debug { "React on Rails Pro async cache MISS for #{cache_key.inspect}" }
|
|
@@ -130,9 +130,9 @@ module ReactOnRailsPro
|
|
|
130
130
|
prefix = "[React on Rails Pro] #{issue}."
|
|
131
131
|
|
|
132
132
|
if Rails.env.production?
|
|
133
|
-
warning = "
|
|
134
|
-
"
|
|
135
|
-
Rails.logger.warn "#{prefix} #{warning}
|
|
133
|
+
warning = "Production Use of React on Rails Pro requires a valid license. " \
|
|
134
|
+
"If this deployment is Production Use, #{action}"
|
|
135
|
+
Rails.logger.warn "#{prefix} #{warning}"
|
|
136
136
|
else
|
|
137
137
|
Rails.logger.info "#{prefix} No license required for development/test environments."
|
|
138
138
|
end
|
|
@@ -33,20 +33,8 @@ module ReactOnRailsPro
|
|
|
33
33
|
VALID_PLANS = %w[paid startup nonprofit education oss partner].freeze
|
|
34
34
|
# MIRROR VALUES END
|
|
35
35
|
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
# Attribution defaults by plan:
|
|
39
|
-
# Plan | Attribution Required?
|
|
40
|
-
# -----------|----------------------
|
|
41
|
-
# paid | No
|
|
42
|
-
# partner | No
|
|
43
|
-
# startup | Yes
|
|
44
|
-
# oss | Yes
|
|
45
|
-
# nonprofit | No (default)
|
|
46
|
-
# education | No (default)
|
|
47
|
-
#
|
|
48
|
-
# These defaults can be overridden by explicit "attribution" field in the license JWT.
|
|
49
|
-
ATTRIBUTION_REQUIRED_PLANS = %w[startup oss].freeze
|
|
36
|
+
# Public compatibility alias: product-level attribution is required for every recognized plan.
|
|
37
|
+
ATTRIBUTION_REQUIRED_PLANS = VALID_PLANS
|
|
50
38
|
|
|
51
39
|
# Mutex for thread-safe license status initialization.
|
|
52
40
|
# Using a constant eliminates the race condition that would exist with @mutex ||= Mutex.new
|
|
@@ -104,11 +92,9 @@ module ReactOnRailsPro
|
|
|
104
92
|
end
|
|
105
93
|
end
|
|
106
94
|
|
|
107
|
-
# Returns whether attribution is required
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
# - startup, oss: Attribution required
|
|
111
|
-
# - nonprofit, education: Attribution optional (default: no)
|
|
95
|
+
# Returns whether the product-level attribution is required.
|
|
96
|
+
# Attribution applies to every recognized plan and to free uses permitted by the EULA.
|
|
97
|
+
# A license JWT cannot waive the requirement.
|
|
112
98
|
# @return [Boolean] True if attribution is required
|
|
113
99
|
def attribution_required?
|
|
114
100
|
return @attribution_required if defined?(@attribution_required)
|
|
@@ -226,25 +212,11 @@ module ReactOnRailsPro
|
|
|
226
212
|
yield decoded_data
|
|
227
213
|
end
|
|
228
214
|
|
|
229
|
-
#
|
|
230
|
-
#
|
|
215
|
+
# Attribution is required for every use permitted by the EULA, including
|
|
216
|
+
# paid, complimentary, educational, demo, and personal/hobby use.
|
|
231
217
|
# @return [Boolean] True if attribution is required
|
|
232
218
|
def determine_attribution_required
|
|
233
|
-
|
|
234
|
-
return false unless license_string
|
|
235
|
-
|
|
236
|
-
decoded_data = decode_license(license_string)
|
|
237
|
-
return false unless decoded_data
|
|
238
|
-
|
|
239
|
-
# Check explicit attribution field first
|
|
240
|
-
attribution = decoded_data["attribution"]
|
|
241
|
-
return attribution if [true, false].include?(attribution)
|
|
242
|
-
|
|
243
|
-
# Infer from plan type
|
|
244
|
-
plan = decoded_data["plan"]
|
|
245
|
-
return false unless plan.is_a?(String)
|
|
246
|
-
|
|
247
|
-
ATTRIBUTION_REQUIRED_PLANS.include?(plan.strip)
|
|
219
|
+
true
|
|
248
220
|
end
|
|
249
221
|
|
|
250
222
|
# Loads license string from environment variable
|
|
@@ -210,20 +210,15 @@ module ReactOnRailsPro
|
|
|
210
210
|
end.join("_").underscore
|
|
211
211
|
end
|
|
212
212
|
|
|
213
|
-
# Generates the Pro-specific HTML attribution comment based on license status
|
|
214
|
-
# Called by React on Rails helper
|
|
215
|
-
#
|
|
213
|
+
# Generates the Pro-specific HTML attribution comment based on license status.
|
|
214
|
+
# Called by the React on Rails helper as the product-level attribution provider.
|
|
215
|
+
# Organization and plan details remain available only in private server diagnostics.
|
|
216
216
|
def self.pro_attribution_comment
|
|
217
217
|
base = "Powered by React on Rails Pro (c) ShakaCode"
|
|
218
|
-
org = ReactOnRailsPro::LicenseValidator.license_organization
|
|
219
218
|
|
|
220
219
|
comment = case ReactOnRailsPro::LicenseValidator.license_status
|
|
221
220
|
when :valid
|
|
222
|
-
|
|
223
|
-
"#{base} | Licensed to #{org}"
|
|
224
|
-
else
|
|
225
|
-
"#{base} | Licensed"
|
|
226
|
-
end
|
|
221
|
+
"#{base} | Licensed"
|
|
227
222
|
when :expired
|
|
228
223
|
"#{base} | LICENSE EXPIRED"
|
|
229
224
|
when :invalid
|
data/react_on_rails_pro.gemspec
CHANGED
|
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
|
|
|
30
30
|
s.summary = "Rails with react server rendering with webpack. Performance helpers"
|
|
31
31
|
s.description = "See README.md"
|
|
32
32
|
s.homepage = "https://reactonrails.com/docs/pro/"
|
|
33
|
-
s.license = "
|
|
33
|
+
s.license = "LicenseRef-LICENSE"
|
|
34
34
|
s.metadata["rubygems_mfa_required"] = "true"
|
|
35
35
|
s.metadata["bug_tracker_uri"] = "https://github.com/shakacode/react_on_rails/issues"
|
|
36
36
|
s.metadata["changelog_uri"] = "https://github.com/shakacode/react_on_rails/blob/main/CHANGELOG.md"
|
|
@@ -28,7 +28,7 @@ module ReactOnRailsPro
|
|
|
28
28
|
# Valid license plan types
|
|
29
29
|
VALID_PLANS: Array[String]
|
|
30
30
|
|
|
31
|
-
#
|
|
31
|
+
# Recognized plans, all of which require product-level attribution
|
|
32
32
|
ATTRIBUTION_REQUIRED_PLANS: Array[String]
|
|
33
33
|
|
|
34
34
|
# Returns the current license status (never raises, never logs)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: react_on_rails_pro
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 17.0.0.rc.
|
|
4
|
+
version: 17.0.0.rc.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Gordon
|
|
@@ -111,14 +111,14 @@ dependencies:
|
|
|
111
111
|
requirements:
|
|
112
112
|
- - '='
|
|
113
113
|
- !ruby/object:Gem::Version
|
|
114
|
-
version: 17.0.0.rc.
|
|
114
|
+
version: 17.0.0.rc.11
|
|
115
115
|
type: :runtime
|
|
116
116
|
prerelease: false
|
|
117
117
|
version_requirements: !ruby/object:Gem::Requirement
|
|
118
118
|
requirements:
|
|
119
119
|
- - '='
|
|
120
120
|
- !ruby/object:Gem::Version
|
|
121
|
-
version: 17.0.0.rc.
|
|
121
|
+
version: 17.0.0.rc.11
|
|
122
122
|
- !ruby/object:Gem::Dependency
|
|
123
123
|
name: bundler
|
|
124
124
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -293,7 +293,7 @@ files:
|
|
|
293
293
|
- sig/react_on_rails_pro/utils.rbs
|
|
294
294
|
homepage: https://reactonrails.com/docs/pro/
|
|
295
295
|
licenses:
|
|
296
|
-
-
|
|
296
|
+
- LicenseRef-LICENSE
|
|
297
297
|
metadata:
|
|
298
298
|
rubygems_mfa_required: 'true'
|
|
299
299
|
bug_tracker_uri: https://github.com/shakacode/react_on_rails/issues
|