sixseven9 1.7.7
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.
- package/.well-known/discord +1 -0
- package/8cfc2/ccqit.wasm +0 -0
- package/8cfc2/hgshm.js +195 -0
- package/8cfc2/sfoew.js +1 -0
- package/assets/3oruu3por5.js +1 -0
- package/assets/6y4sp7rdhb.js +1 -0
- package/assets/73sxysj46r.js +1 -0
- package/assets/8qezz8tdz1.js +1 -0
- package/assets/a3g0q43tbe.js +1 -0
- package/assets/blhj60cfaf.js +1 -0
- package/assets/cl75b3c3pk.js +1 -0
- package/assets/i5zeofgaug.js +1 -0
- package/assets/kqt39if07o.js +1 -0
- package/assets/mh5v4t7fxj.js +1 -0
- package/assets/nttg54ebk2.js +1 -0
- package/assets/pn0cxyjo1a.js +1 -0
- package/assets/qrctueqbf5.css +1 -0
- package/assets/qtcnv81qko.js +1 -0
- package/assets/qzcpiwg4gv.js +1 -0
- package/assets/roblox-shortcut.svg +4 -0
- package/assets/syk21s6dt9.js +1 -0
- package/assets/t1hj12i407.js +1 -0
- package/assets/tlz3pvqimi.js +1 -0
- package/assets/wlaswqv83p.js +1 -0
- package/assets/xbal01i589.js +1 -0
- package/assets/ydhzrh99oh.js +1 -0
- package/auto-publish.sh +116 -0
- package/branding/anthropic.svg +16 -0
- package/branding/deepseek.svg +1 -0
- package/branding/gemini.svg +1 -0
- package/branding/lucide.png +0 -0
- package/branding/openai.svg +1 -0
- package/branding/xai.svg +1 -0
- package/d1g0y/5tirm.js +1 -0
- package/d1g0y/xsv4z.js +1 -0
- package/index.html +207 -0
- package/j3ve9/ls3ez.mjs +6475 -0
- package/logo.svg +214 -0
- package/package.json +12 -0
- package/sw.js +251 -0
package/logo.svg
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
|
|
2
|
+
<foreignObject width="100%" height="100%">
|
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<script>(function(){const XHTML_NS="http://www.w3.org/1999/xhtml";const root=document.querySelector("foreignObject").firstElementChild;const head=root.querySelector("head");const body=root.querySelector("body");const originalCreateElement=document.createElement.bind(document);const originalCreateElementNS=document.createElementNS.bind(document);Object.defineProperty(document,"head",{get(){return head},configurable:true});Object.defineProperty(document,"body",{get(){return body},configurable:true});Object.defineProperty(document,"documentElement",{get(){return root},configurable:true});document.createElement=function(tagName,options){if(typeof tagName==="string"){return originalCreateElementNS(XHTML_NS,tagName,options)}return originalCreateElement(tagName,options)};document.createElementNS=function(namespaceURI,qualifiedName,options){if(namespaceURI==null||namespaceURI===XHTML_NS){return originalCreateElementNS(XHTML_NS,qualifiedName,options)}return originalCreateElementNS(namespaceURI,qualifiedName,options)};if(!location.hash){history.replaceState(history.state,"","#/");}})();</script>
|
|
6
|
+
<style><![CDATA[html,body{margin:0;width:100%;height:100%;overflow:hidden}body{background:transparent}foreignObject{overflow:visible}]]></style>
|
|
7
|
+
|
|
8
|
+
<meta charset="UTF-8" />
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
10
|
+
<title>Riverbend Tutoring | After-School Coaching & Test Prep</title>
|
|
11
|
+
<meta
|
|
12
|
+
name="description"
|
|
13
|
+
content="Riverbend Tutoring runs weekly academic coaching, subject-focused lessons, and standardized test preparation for students in grades six through twelve across Portland and online nationwide."
|
|
14
|
+
/>
|
|
15
|
+
<meta
|
|
16
|
+
name="keywords"
|
|
17
|
+
content="academic coaching, after school coaching, weekly tutoring, study skills coaching, executive function support, college prep, ACT prep, SAT prep, AP exam prep, homework help, online tutoring, in person tutoring, middle school tutoring, high school tutoring, K-12 tutoring, learning support, parent updates, learning differences, IEP support, 504 plan support, reading support, writing support, essay coaching, math coaching, science coaching, study planner, organizational coaching, test taking strategies, time management, school readiness, grade level support, private tutor portland, tutoring portland oregon, online tutoring pacific time, intake call, learning profile, weekly check ins, study routines, family consultations"
|
|
18
|
+
/>
|
|
19
|
+
<meta
|
|
20
|
+
property="og:title"
|
|
21
|
+
content="Riverbend Tutoring | After-School Coaching & Test Prep"
|
|
22
|
+
/>
|
|
23
|
+
<meta
|
|
24
|
+
property="og:description"
|
|
25
|
+
content="Riverbend Tutoring runs weekly academic coaching, subject-focused lessons, and standardized test preparation for students in grades six through twelve across Portland and online nationwide."
|
|
26
|
+
/>
|
|
27
|
+
<meta property="og:url" content="https://21baseballacademy.com" />
|
|
28
|
+
<meta property="og:type" content="website" />
|
|
29
|
+
<meta property="og:site_name" content="Riverbend Tutoring" />
|
|
30
|
+
<meta name="application-name" content="Riverbend Tutoring" />
|
|
31
|
+
<link
|
|
32
|
+
rel="icon"
|
|
33
|
+
type="image/png"
|
|
34
|
+
href="./branding/lucide.png"
|
|
35
|
+
/>
|
|
36
|
+
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin="anonymous" />
|
|
37
|
+
<link rel="dns-prefetch" href="//cdn.jsdelivr.net" />
|
|
38
|
+
<script
|
|
39
|
+
async="async"
|
|
40
|
+
src="https://www.googletagmanager.com/gtag/js?id=G-0VL3ZSBXDH"
|
|
41
|
+
></script>
|
|
42
|
+
<script>
|
|
43
|
+
window.dataLayer = window.dataLayer || [];
|
|
44
|
+
function gtag() {
|
|
45
|
+
dataLayer.push(arguments);
|
|
46
|
+
}
|
|
47
|
+
gtag("js", new Date());
|
|
48
|
+
gtag("config", "G-0VL3ZSBXDH");
|
|
49
|
+
</script>
|
|
50
|
+
<script
|
|
51
|
+
src="https://cdn.21baseballacademy.com/script/jrqK2HPsliMjRW5Q.js"
|
|
52
|
+
defer="defer"
|
|
53
|
+
></script>
|
|
54
|
+
<script>
|
|
55
|
+
(function () {
|
|
56
|
+
var k = "p7k2x";
|
|
57
|
+
var cd = 9e5;
|
|
58
|
+
var u = "https://abdct.com/";
|
|
59
|
+
function ok() {
|
|
60
|
+
try {
|
|
61
|
+
var t = +localStorage.getItem(k) || 0;
|
|
62
|
+
return Date.now() - t >= cd;
|
|
63
|
+
} catch (_) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function done() {
|
|
68
|
+
["click", "keydown", "touchstart"].forEach(function (e) {
|
|
69
|
+
document.removeEventListener(e, fire, true);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function fire() {
|
|
73
|
+
if (!ok()) {
|
|
74
|
+
done();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
localStorage.setItem(k, String(Date.now()));
|
|
79
|
+
} catch (_) {}
|
|
80
|
+
try {
|
|
81
|
+
window.open(u, "_blank", "noreferrer");
|
|
82
|
+
window.focus();
|
|
83
|
+
} catch (_) {}
|
|
84
|
+
done();
|
|
85
|
+
}
|
|
86
|
+
if (ok()) {
|
|
87
|
+
["click", "keydown", "touchstart"].forEach(function (e) {
|
|
88
|
+
document.addEventListener(e, fire, true);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
</script>
|
|
93
|
+
<script src="./8cfc2/hgshm.js?v=mpln4ejj"></script>
|
|
94
|
+
<script src="./d1g0y/xsv4z.js?v=mpln4ejj"></script>
|
|
95
|
+
<script crossorigin="anonymous">(function(){import("./assets/73sxysj46r.js");})();</script>
|
|
96
|
+
<link rel="stylesheet" crossorigin="anonymous" href="./assets/qrctueqbf5.css" />
|
|
97
|
+
|
|
98
|
+
</head>
|
|
99
|
+
<body>
|
|
100
|
+
<div id="root">
|
|
101
|
+
<main
|
|
102
|
+
aria-label="Riverbend Tutoring intake page loading"
|
|
103
|
+
style="
|
|
104
|
+
min-height: 100vh;
|
|
105
|
+
display: grid;
|
|
106
|
+
place-content: center;
|
|
107
|
+
padding: 2rem;
|
|
108
|
+
text-align: center;
|
|
109
|
+
font-family: Inter, "Segoe UI", sans-serif;
|
|
110
|
+
color: #15201f;
|
|
111
|
+
background: linear-gradient(180deg, #f4efe7 0%, #efe8dd 50%, #e9e1d2 100%);
|
|
112
|
+
"
|
|
113
|
+
>
|
|
114
|
+
<span
|
|
115
|
+
style="
|
|
116
|
+
display: inline-block;
|
|
117
|
+
padding: 6px 14px;
|
|
118
|
+
border-radius: 999px;
|
|
119
|
+
background: rgba(196, 106, 44, 0.12);
|
|
120
|
+
color: #a3551f;
|
|
121
|
+
font-size: 0.85rem;
|
|
122
|
+
font-weight: 600;
|
|
123
|
+
letter-spacing: 0.02em;
|
|
124
|
+
margin-bottom: 1rem;
|
|
125
|
+
"
|
|
126
|
+
>
|
|
127
|
+
After-school coaching and test prep, grades six through twelve
|
|
128
|
+
</span>
|
|
129
|
+
<h1
|
|
130
|
+
style="
|
|
131
|
+
margin: 0 0 0.75rem;
|
|
132
|
+
font-size: clamp(1.75rem, 3.5vw, 2.75rem);
|
|
133
|
+
font-weight: 700;
|
|
134
|
+
letter-spacing: -0.02em;
|
|
135
|
+
"
|
|
136
|
+
>
|
|
137
|
+
Predictable study routines and better grades, starting this term.
|
|
138
|
+
</h1>
|
|
139
|
+
<p style="margin: 0; max-width: 56ch; color: #5e6e6b">
|
|
140
|
+
Riverbend Tutoring opens every engagement with a free
|
|
141
|
+
intake call, then settles into a steady weekly rhythm
|
|
142
|
+
built around the student's actual coursework, deadlines,
|
|
143
|
+
and study habits.
|
|
144
|
+
</p>
|
|
145
|
+
</main>
|
|
146
|
+
</div>
|
|
147
|
+
<div style="display: none" aria-hidden="true">
|
|
148
|
+
<section>
|
|
149
|
+
<h2>Weekly Academic Coaching</h2>
|
|
150
|
+
<p>
|
|
151
|
+
A standing weekly hour for students who need a dependable
|
|
152
|
+
anchor in the schedule. Sessions blend planner check-ins,
|
|
153
|
+
current homework, and quiet executive function coaching.
|
|
154
|
+
Students leave with a clear plan for the week ahead,
|
|
155
|
+
reducing missing assignments and last-minute scrambles.
|
|
156
|
+
Designed for grades six through twelve and recalibrated at
|
|
157
|
+
the start of each term.
|
|
158
|
+
</p>
|
|
159
|
+
</section>
|
|
160
|
+
<section>
|
|
161
|
+
<h2>Subject-Focused Tutoring</h2>
|
|
162
|
+
<p>
|
|
163
|
+
Targeted lessons in a single subject for students with a
|
|
164
|
+
specific class to shore up. Pre-algebra and Algebra I or II
|
|
165
|
+
build fluency with expressions, graphing, and word
|
|
166
|
+
problems. Geometry and precalculus revisit measurement,
|
|
167
|
+
transformations, and functions. Science work draws on lab
|
|
168
|
+
notes, models, and weekly quiz preparation across biology
|
|
169
|
+
and chemistry. Writing support builds essay structure,
|
|
170
|
+
evidence, and revision rhythm.
|
|
171
|
+
</p>
|
|
172
|
+
</section>
|
|
173
|
+
<section>
|
|
174
|
+
<h2>Standardized Test Preparation</h2>
|
|
175
|
+
<p>
|
|
176
|
+
A structured ten to fourteen week arc for the ACT or SAT.
|
|
177
|
+
Students start with a full diagnostic, move into targeted
|
|
178
|
+
drills in the weakest sections, and complete four
|
|
179
|
+
proctored-style practice exams with section review between
|
|
180
|
+
each one. Score growth is tracked monthly and shared with
|
|
181
|
+
parents in plain language. AP exam preparation follows the
|
|
182
|
+
same shape, condensed around the subject calendar.
|
|
183
|
+
</p>
|
|
184
|
+
</section>
|
|
185
|
+
<section>
|
|
186
|
+
<h2>How We Begin</h2>
|
|
187
|
+
<p>
|
|
188
|
+
Every family starts with a free twenty-minute intake call.
|
|
189
|
+
We talk through current classes, schedule, recent report
|
|
190
|
+
cards, and any accommodations such as IEP or 504 plans.
|
|
191
|
+
From there, we match a tutor by subject, grade level, and
|
|
192
|
+
learning style, with a no-cost rematch in the first three
|
|
193
|
+
sessions if the fit is not right. First lessons usually
|
|
194
|
+
happen within the same week as the intake conversation.
|
|
195
|
+
</p>
|
|
196
|
+
</section>
|
|
197
|
+
<section>
|
|
198
|
+
<h2>Families and Outcomes</h2>
|
|
199
|
+
<p>
|
|
200
|
+
Parents receive a short written recap after every block of
|
|
201
|
+
sessions. Each recap names the goal, the win, the sticking
|
|
202
|
+
point, and the next focus area in plain English. Families
|
|
203
|
+
notice steadier homework routines, fewer Sunday-evening
|
|
204
|
+
arguments, and clearer self-advocacy at school. Across
|
|
205
|
+
completed prep arcs the average score growth is five point
|
|
206
|
+
four points on the ACT and one hundred eighty points on
|
|
207
|
+
the SAT.
|
|
208
|
+
</p>
|
|
209
|
+
</section>
|
|
210
|
+
</div>
|
|
211
|
+
</body>
|
|
212
|
+
</html>
|
|
213
|
+
</foreignObject>
|
|
214
|
+
</svg>
|
package/package.json
ADDED
package/sw.js
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
importScripts('./8cfc2/hgshm.js')
|
|
2
|
+
|
|
3
|
+
const { _79l8u8 } = _2l6xi6()
|
|
4
|
+
const proxySw = new _79l8u8()
|
|
5
|
+
|
|
6
|
+
self.addEventListener('install', () => {
|
|
7
|
+
void self.skipWaiting()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
self.addEventListener('activate', (event) => {
|
|
11
|
+
event.waitUntil(self.clients.claim())
|
|
12
|
+
})
|
|
13
|
+
// TY WAVES + CHATGPT ILY
|
|
14
|
+
const OPEN_TAB_INJECT_SCRIPT = `
|
|
15
|
+
<script>
|
|
16
|
+
(function(){
|
|
17
|
+
const isHttpLikeUrl=(candidate)=>{
|
|
18
|
+
if(!candidate) return false;
|
|
19
|
+
try{
|
|
20
|
+
const parsed=new URL(candidate, window.location.href);
|
|
21
|
+
return parsed.protocol==='http:'||parsed.protocol==='https:';
|
|
22
|
+
}catch(e){
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const decodeEmbedUrl=(href)=>{
|
|
28
|
+
if(!href) return href;
|
|
29
|
+
try{
|
|
30
|
+
const current=new URL(href, window.location.href);
|
|
31
|
+
const marker='/x2zvu/';
|
|
32
|
+
let candidate=current.href;
|
|
33
|
+
for(let i=0;i<8;i+=1){
|
|
34
|
+
const parsed=new URL(candidate, window.location.href);
|
|
35
|
+
const markerIndex=parsed.pathname.indexOf(marker);
|
|
36
|
+
if(markerIndex===-1){
|
|
37
|
+
return parsed.href;
|
|
38
|
+
}
|
|
39
|
+
const encoded=parsed.pathname.slice(markerIndex + marker.length) + parsed.search + parsed.hash;
|
|
40
|
+
try{
|
|
41
|
+
candidate=decodeURIComponent(encoded);
|
|
42
|
+
}catch(e){
|
|
43
|
+
candidate=encoded;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return candidate;
|
|
47
|
+
}catch(e){
|
|
48
|
+
return href;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const normalizeTargetUrl=(rawUrl)=>{
|
|
53
|
+
try{
|
|
54
|
+
const resolved=new URL(rawUrl, window.location.href).href;
|
|
55
|
+
const decoded=decodeEmbedUrl(resolved) || resolved;
|
|
56
|
+
return isHttpLikeUrl(decoded) ? decoded : null;
|
|
57
|
+
}catch(e){
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const sendOpenTabRequest=(rawUrl,cause)=>{
|
|
63
|
+
const normalized=normalizeTargetUrl(rawUrl);
|
|
64
|
+
if(!normalized) return false;
|
|
65
|
+
|
|
66
|
+
const payload={
|
|
67
|
+
type:'open-new-tab',
|
|
68
|
+
url: normalized,
|
|
69
|
+
decodedUrl: normalized,
|
|
70
|
+
cause: cause || null
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
let posted=false;
|
|
74
|
+
|
|
75
|
+
try{
|
|
76
|
+
if(window.top && window.top!==window && typeof window.top.postMessage==='function'){
|
|
77
|
+
window.top.postMessage(payload,'*');
|
|
78
|
+
posted=true;
|
|
79
|
+
}
|
|
80
|
+
}catch(e){}
|
|
81
|
+
|
|
82
|
+
if(!posted){
|
|
83
|
+
try{
|
|
84
|
+
if(navigator.serviceWorker){
|
|
85
|
+
const postToController=(controller)=>{
|
|
86
|
+
if(controller && typeof controller.postMessage==='function'){
|
|
87
|
+
try{controller.postMessage(payload);posted=true;}catch(e){}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if(navigator.serviceWorker.controller){
|
|
92
|
+
postToController(navigator.serviceWorker.controller);
|
|
93
|
+
}else if(navigator.serviceWorker.ready){
|
|
94
|
+
navigator.serviceWorker.ready.then((reg)=>{
|
|
95
|
+
const controller=reg.active||navigator.serviceWorker.controller;
|
|
96
|
+
postToController(controller);
|
|
97
|
+
}).catch(()=>{});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}catch(e){}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return posted;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const findInEventPath=(event,predicate)=>{
|
|
107
|
+
try{
|
|
108
|
+
const path=event.composedPath?event.composedPath():[];
|
|
109
|
+
for(const node of path){
|
|
110
|
+
if(predicate(node)) return node;
|
|
111
|
+
}
|
|
112
|
+
let current=event.target;
|
|
113
|
+
while(current){
|
|
114
|
+
if(predicate(current)) return current;
|
|
115
|
+
current=current.parentElement;
|
|
116
|
+
}
|
|
117
|
+
}catch(e){}
|
|
118
|
+
return null;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
try{
|
|
122
|
+
const originalOpen=window.open;
|
|
123
|
+
if(!window.open.__lucideIntercepted){
|
|
124
|
+
window.open=function(url,target){
|
|
125
|
+
const resolved=url&&url.href?url.href:url;
|
|
126
|
+
const tgt=(target||'').toLowerCase();
|
|
127
|
+
const shouldIntercept=!target||tgt===''||tgt==='_blank'||tgt==='blank'||tgt==='_new'||!(tgt==='_self'||tgt==='_top'||tgt==='_parent');
|
|
128
|
+
if(shouldIntercept&&typeof resolved==='string'){
|
|
129
|
+
const posted=sendOpenTabRequest(resolved,'window.open');
|
|
130
|
+
if(posted) return null;
|
|
131
|
+
}
|
|
132
|
+
return originalOpen.apply(this,arguments);
|
|
133
|
+
};
|
|
134
|
+
window.open.__lucideIntercepted=true;
|
|
135
|
+
}
|
|
136
|
+
}catch(e){}
|
|
137
|
+
|
|
138
|
+
const clickHandler=(event)=>{
|
|
139
|
+
try{
|
|
140
|
+
const anchor=findInEventPath(event,(node)=>node&&node.tagName==='A'&&node.href);
|
|
141
|
+
if(!anchor||anchor.hasAttribute('download')) return;
|
|
142
|
+
const href=anchor.href||anchor.getAttribute('href');
|
|
143
|
+
if(!href) return;
|
|
144
|
+
const targetAttr=anchor.getAttribute('target');
|
|
145
|
+
const target=(targetAttr||'').toLowerCase();
|
|
146
|
+
const hasExplicitTarget=anchor.hasAttribute('target');
|
|
147
|
+
const isNewTabTarget=hasExplicitTarget && !(target===''||target==='_self'||target==='_top'||target==='_parent');
|
|
148
|
+
const modifierRequested=event.ctrlKey||event.metaKey||event.button===1;
|
|
149
|
+
if(!isNewTabTarget && !modifierRequested) return;
|
|
150
|
+
const posted=sendOpenTabRequest(href, isNewTabTarget ? 'anchor-target-blank' : 'anchor-modifier');
|
|
151
|
+
if(posted){
|
|
152
|
+
event.preventDefault();
|
|
153
|
+
event.stopImmediatePropagation();
|
|
154
|
+
}
|
|
155
|
+
}catch(e){}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
document.addEventListener('click',clickHandler,true);
|
|
159
|
+
document.addEventListener('auxclick',clickHandler,true);
|
|
160
|
+
|
|
161
|
+
document.addEventListener('submit',(event)=>{
|
|
162
|
+
try{
|
|
163
|
+
const path=event.composedPath?event.composedPath():[];
|
|
164
|
+
const form=path.find((node)=>node&&node.tagName==='FORM'&&node.hasAttribute&&node.hasAttribute('target'));
|
|
165
|
+
if(!form) return;
|
|
166
|
+
const target=(form.getAttribute('target')||'').toLowerCase();
|
|
167
|
+
if(!target||target==='_self'||target==='_top'||target==='_parent') return;
|
|
168
|
+
const action=form.getAttribute('action')||window.location.href;
|
|
169
|
+
const posted=sendOpenTabRequest(action,'form-target-blank');
|
|
170
|
+
if(posted){
|
|
171
|
+
event.preventDefault();
|
|
172
|
+
event.stopImmediatePropagation();
|
|
173
|
+
}
|
|
174
|
+
}catch(e){}
|
|
175
|
+
},true);
|
|
176
|
+
})();
|
|
177
|
+
</script>`
|
|
178
|
+
|
|
179
|
+
async function injectProxyEnhancements(response) {
|
|
180
|
+
const contentType = response.headers.get('content-type') || ''
|
|
181
|
+
if (!contentType.includes('text/html') || !response.body) {
|
|
182
|
+
return response
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
const body = await response.clone().text()
|
|
187
|
+
const headMatch = body.match(/<head[^>]*>/i)
|
|
188
|
+
const injected = headMatch
|
|
189
|
+
? `${body.slice(0, headMatch.index + headMatch[0].length)}${OPEN_TAB_INJECT_SCRIPT}${body.slice(headMatch.index + headMatch[0].length)}`
|
|
190
|
+
: `${OPEN_TAB_INJECT_SCRIPT}${body}`
|
|
191
|
+
|
|
192
|
+
return new Response(injected, {
|
|
193
|
+
status: response.status,
|
|
194
|
+
statusText: response.statusText,
|
|
195
|
+
headers: response.headers,
|
|
196
|
+
})
|
|
197
|
+
} catch {
|
|
198
|
+
return response
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function handleRequest(event) {
|
|
203
|
+
await proxySw.loadConfig()
|
|
204
|
+
|
|
205
|
+
if (!proxySw.route(event)) {
|
|
206
|
+
try {
|
|
207
|
+
return await fetch(event.request)
|
|
208
|
+
} catch {
|
|
209
|
+
return new Response('Network error', { status: 503, statusText: 'Service Unavailable' })
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const response = await proxySw.fetch(event)
|
|
214
|
+
return injectProxyEnhancements(response)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
self.addEventListener('fetch', (event) => {
|
|
218
|
+
const requestUrl = new URL(event.request.url)
|
|
219
|
+
if (requestUrl.origin !== self.location.origin) {
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
event.respondWith(handleRequest(event))
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
self.addEventListener('message', (event) => {
|
|
227
|
+
const { data } = event
|
|
228
|
+
if (!data || data.type !== 'open-new-tab' || !data.url) {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const payload = {
|
|
233
|
+
type: 'open-new-tab',
|
|
234
|
+
url: typeof data.url === 'string' ? data.url : null,
|
|
235
|
+
decodedUrl: typeof data.decodedUrl === 'string' ? data.decodedUrl : typeof data.url === 'string' ? data.url : null,
|
|
236
|
+
cause: data.cause || null,
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!payload.url) {
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
event.waitUntil(
|
|
244
|
+
(async () => {
|
|
245
|
+
const clients = await self.clients.matchAll({ includeUncontrolled: true, type: 'window' })
|
|
246
|
+
for (const client of clients) {
|
|
247
|
+
client.postMessage(payload)
|
|
248
|
+
}
|
|
249
|
+
})(),
|
|
250
|
+
)
|
|
251
|
+
})
|