roxxie-proxy-u-prod 0.1.0 → 0.2.2
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/README.md +62 -74
- package/dist/assets/{index-DcvPYWS3.js → index-CttvagWK.js} +164 -172
- package/dist/assets/index-EeRhLAof.css +1 -0
- package/dist/assets/{inject-BnVzMVpl.js → inject-xtH4w5z9.js} +8 -5
- package/dist/favicon.png +0 -0
- package/embed.js +2 -1
- package/examples/single-page.html +3 -1
- package/package.json +43 -41
- package/runtime/index.html +5 -4
- package/scripts/build.mjs +11 -5
- package/scripts/smoke.mjs +264 -73
- package/scripts/verify.mjs +100 -1
- package/source/packages/chrome/index.html +3 -2
- package/source/packages/chrome/public/favicon.png +0 -0
- package/source/packages/chrome/src/Tab/Tab.tsx +1 -1
- package/source/packages/chrome/src/assets/favicon.ts +1 -1
- package/source/packages/chrome/src/components/Button.tsx +11 -22
- package/source/packages/chrome/src/components/Checkbox.tsx +8 -12
- package/source/packages/chrome/src/components/Input.tsx +3 -4
- package/source/packages/chrome/src/components/StartScreen.tsx +34 -49
- package/source/packages/chrome/src/components/TopSiteButton.tsx +2 -2
- package/source/packages/chrome/src/pages/NewTabPage.tsx +42 -10
- package/source/packages/chrome/src/pages/SettingsPage.tsx +10 -11
- package/source/packages/chrome/src/runtime-base.ts +1 -1
- package/source/packages/chrome/src/services/SettingsService.ts +1 -1
- package/source/packages/chrome/src/style.css +7 -7
- package/source/packages/chrome/src/themes.ts +21 -21
- package/source/packages/inject/src/errorpage/errorpage.css +22 -35
- package/source/packages/inject/src/errorpage/errorpage.ts +6 -3
- package/source/packages/roxxie-transport/package.json +1 -1
- package/source/packages/roxxie-transport/src/connection.ts +1 -1
- package/source/packages/roxxie-transport/src/transport.ts +2 -2
- package/source/packages/scramjet/packages/core/dist/scramjet.js +1 -1
- package/source/packages/scramjet/packages/core/dist/scramjet.mjs +1 -1
- package/source/packages/scramjet/packages/core/dist/scramjet_bundled.js +1 -1
- package/source/packages/scramjet/packages/core/dist/scramjet_bundled.mjs +1 -1
- package/source/packages/tracker-protocol/package.json +1 -1
- package/source/packages/tracker-protocol/src/index.ts +34 -10
- package/source/pnpm-lock.yaml +4 -1
- package/standalone.html +27 -0
- package/dist/assets/index-BdRlQ7d_.css +0 -1
- package/dist/icon.png +0 -0
- package/dist/roxxie-icon.svg +0 -12
- package/source/packages/chrome/public/icon.png +0 -0
- package/source/packages/chrome/public/roxxie-icon.svg +0 -12
- package/source/packages/scramjet/packages/core/dist/temp-types-build/index.js +0 -23
- package/source/packages/scramjet/packages/core/dist/temp-types-build/index.js.map +0 -1
package/scripts/verify.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* SPDX-License-Identifier: AGPL-3.0-only */
|
|
2
2
|
|
|
3
3
|
import { access, readFile, readdir, stat } from "node:fs/promises";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
4
5
|
import { dirname, join, resolve } from "node:path";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
7
|
|
|
@@ -8,14 +9,22 @@ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
8
9
|
const manifest = JSON.parse(
|
|
9
10
|
await readFile(join(packageRoot, "package.json"), "utf8")
|
|
10
11
|
);
|
|
11
|
-
const
|
|
12
|
+
const packageSpec = `${manifest.name}@${manifest.version}`;
|
|
13
|
+
const expectedCdnRoot = `https://cdn.jsdelivr.net/npm/${packageSpec}/`;
|
|
14
|
+
const expectedCdn = `${expectedCdnRoot}dist/`;
|
|
15
|
+
const expectedRuntimeBase = `/${packageSpec}/runtime/`;
|
|
16
|
+
const expectedShell = `https://unpkg.com${expectedRuntimeBase}index.html`;
|
|
12
17
|
const required = [
|
|
13
18
|
"embed.js",
|
|
19
|
+
"standalone.html",
|
|
20
|
+
"examples/single-page.html",
|
|
14
21
|
"LICENSE",
|
|
15
22
|
"SOURCE.md",
|
|
16
23
|
"THIRD_PARTY_NOTICES.md",
|
|
17
24
|
"dist",
|
|
25
|
+
"dist/favicon.png",
|
|
18
26
|
"source/packages/chrome/src",
|
|
27
|
+
"source/packages/chrome/public/favicon.png",
|
|
19
28
|
"source/packages/chrome/src/adblock/assets/filters.bin",
|
|
20
29
|
"source/packages/cdp/dist/chobitsu.js",
|
|
21
30
|
"source/packages/cdp/src",
|
|
@@ -67,10 +76,93 @@ async function* walkFiles(root, relativeRoot = "") {
|
|
|
67
76
|
|
|
68
77
|
for (const path of required) await access(join(packageRoot, path));
|
|
69
78
|
|
|
79
|
+
const expectedLogoSha256 =
|
|
80
|
+
"fda3eb53c94eb3ef61e24e2724b4a87e863e0ce4135767f0041beb86e7107472";
|
|
81
|
+
for (const path of [
|
|
82
|
+
"dist/favicon.png",
|
|
83
|
+
"source/packages/chrome/public/favicon.png",
|
|
84
|
+
]) {
|
|
85
|
+
const digest = createHash("sha256")
|
|
86
|
+
.update(await readFile(join(packageRoot, path)))
|
|
87
|
+
.digest("hex");
|
|
88
|
+
if (digest !== expectedLogoSha256) {
|
|
89
|
+
throw new Error(`${path} does not contain the approved Roxxie logo`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const themeSource = await readFile(
|
|
94
|
+
join(packageRoot, "source/packages/chrome/src/themes.ts"),
|
|
95
|
+
"utf8"
|
|
96
|
+
);
|
|
97
|
+
for (const requiredThemeValue of [
|
|
98
|
+
' name: "EDUrocks Dark"',
|
|
99
|
+
' toolbar: "#222230"',
|
|
100
|
+
' field: "#11111b"',
|
|
101
|
+
' accent: "#eb458b"',
|
|
102
|
+
]) {
|
|
103
|
+
if (!themeSource.includes(requiredThemeValue.trimStart())) {
|
|
104
|
+
throw new Error(`Branded theme is missing ${requiredThemeValue.trim()}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const startScreenSource = await readFile(
|
|
109
|
+
join(packageRoot, "source/packages/chrome/src/components/StartScreen.tsx"),
|
|
110
|
+
"utf8"
|
|
111
|
+
);
|
|
112
|
+
if (!startScreenSource.includes("--start-action: #eb458b")) {
|
|
113
|
+
throw new Error("Start screen does not use the EDUrocks accent color");
|
|
114
|
+
}
|
|
115
|
+
if (
|
|
116
|
+
/\b(?:linear|radial)-gradient\s*\(|text-shadow\s*:/iu.test(startScreenSource)
|
|
117
|
+
) {
|
|
118
|
+
throw new Error("Start screen must remain flat and glow-free");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (manifest.version !== "0.2.2") {
|
|
122
|
+
throw new Error("This production release must be version 0.2.2");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const embedBytes = await readFile(join(packageRoot, "embed.js"));
|
|
126
|
+
const embed = embedBytes.toString("utf8");
|
|
127
|
+
const expectedEmbedIntegrity = `sha384-${createHash("sha384")
|
|
128
|
+
.update(embedBytes)
|
|
129
|
+
.digest("base64")}`;
|
|
130
|
+
if (!embed.includes(expectedShell)) {
|
|
131
|
+
throw new Error(`embed.js must default to ${expectedShell}`);
|
|
132
|
+
}
|
|
133
|
+
if (/100\.58\.76\.81\/browser/iu.test(embed)) {
|
|
134
|
+
throw new Error("embed.js must not depend on tracker-hosted browser files");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
for (const path of ["standalone.html", "examples/single-page.html"]) {
|
|
138
|
+
const document = await readFile(join(packageRoot, path), "utf8");
|
|
139
|
+
if (!document.includes(`${expectedCdnRoot}embed.js`)) {
|
|
140
|
+
throw new Error(`${path} must load the exact pinned jsDelivr embed`);
|
|
141
|
+
}
|
|
142
|
+
if (!document.includes(`integrity="${expectedEmbedIntegrity}"`)) {
|
|
143
|
+
throw new Error(`${path} must pin embed.js with ${expectedEmbedIntegrity}`);
|
|
144
|
+
}
|
|
145
|
+
if (!document.includes('crossorigin="anonymous"')) {
|
|
146
|
+
throw new Error(`${path} must request the SRI-protected embed anonymously`);
|
|
147
|
+
}
|
|
148
|
+
if (/data-roxxie-src=/iu.test(document)) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
`${path} must exercise embed.js's production default shell`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
70
155
|
const shell = await readFile(join(packageRoot, "runtime/index.html"), "utf8");
|
|
71
156
|
if (!shell.includes(expectedCdn)) {
|
|
72
157
|
throw new Error(`runtime/index.html must reference ${expectedCdn}`);
|
|
73
158
|
}
|
|
159
|
+
if (
|
|
160
|
+
!shell.includes('rel="icon"') ||
|
|
161
|
+
!shell.includes('type="image/png"') ||
|
|
162
|
+
!shell.includes(`${expectedCdn}favicon.png`)
|
|
163
|
+
) {
|
|
164
|
+
throw new Error("Runtime shell does not reference the pinned branded PNG");
|
|
165
|
+
}
|
|
74
166
|
if (/127\.0\.0\.1|localhost/.test(shell)) {
|
|
75
167
|
throw new Error("Production shell contains a loopback address");
|
|
76
168
|
}
|
|
@@ -95,9 +187,16 @@ if (outputFiles.some((path) => path.endsWith(".map"))) {
|
|
|
95
187
|
if (outputFiles.includes("index.html")) {
|
|
96
188
|
throw new Error("CDN dist must not claim that jsDelivr can execute HTML");
|
|
97
189
|
}
|
|
190
|
+
let hasVersionedRuntimeBase = false;
|
|
98
191
|
for (const path of JavaScriptFiles) {
|
|
99
192
|
const source = await readFile(join(packageRoot, "dist", path), "utf8");
|
|
100
193
|
assertNoLocalPath(`dist/${path}`, source);
|
|
194
|
+
if (source.includes(expectedRuntimeBase)) hasVersionedRuntimeBase = true;
|
|
195
|
+
}
|
|
196
|
+
if (!hasVersionedRuntimeBase) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
`Production JavaScript must use the unpkg runtime base ${expectedRuntimeBase}`
|
|
199
|
+
);
|
|
101
200
|
}
|
|
102
201
|
for await (const path of walkFiles(packageRoot)) {
|
|
103
202
|
const contents = await readFile(join(packageRoot, path));
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/
|
|
5
|
+
<link rel="icon" type="image/png" sizes="any" href="/favicon.png" />
|
|
6
|
+
<meta name="theme-color" content="#222230" />
|
|
6
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
8
|
<title>Roxxie Proxy U</title>
|
|
8
9
|
|
|
9
10
|
<!--ssr-head-->
|
|
10
11
|
</head>
|
|
11
12
|
|
|
12
|
-
<body
|
|
13
|
+
<body>
|
|
13
14
|
<!--ssr-body-->
|
|
14
15
|
<div id="app"></div>
|
|
15
16
|
<script type="module" src="/src/index.ts"></script>
|
|
Binary file
|
|
@@ -138,7 +138,7 @@ export class Tab extends StatefulClass {
|
|
|
138
138
|
this.url = url;
|
|
139
139
|
this.icon = defaultFaviconUrl;
|
|
140
140
|
if (url.protocol == INTERNAL_URL_PROTOCOL) {
|
|
141
|
-
this.icon =
|
|
141
|
+
this.icon = roxxieIconUrl;
|
|
142
142
|
this.history.current().favicon = roxxieIconUrl;
|
|
143
143
|
switch (url.host) {
|
|
144
144
|
case "newtab":
|
|
@@ -34,34 +34,23 @@ Button.style = css`
|
|
|
34
34
|
}
|
|
35
35
|
:scope:not(.icon):hover {
|
|
36
36
|
background: var(--text-10);
|
|
37
|
-
|
|
38
|
-
70% 80% at 50% 100%,
|
|
39
|
-
var(--text-8),
|
|
40
|
-
var(--text-5)
|
|
41
|
-
);
|
|
37
|
+
border-color: var(--text-30);
|
|
42
38
|
}
|
|
43
39
|
:scope.primary {
|
|
44
|
-
background
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
var(--tab_line),
|
|
48
|
-
var(--accent-shade-20)
|
|
49
|
-
);
|
|
50
|
-
box-shadow: inset 0px 0.05em 0.025em rgb(255 255 255 / 30%);
|
|
51
|
-
text-shadow: 0 0.055em 0.05em var(--accent-shade-20);
|
|
52
|
-
color: white;
|
|
53
|
-
font-weight: 500;
|
|
40
|
+
background: var(--tab_line);
|
|
41
|
+
color: #11111b;
|
|
42
|
+
font-weight: 650;
|
|
54
43
|
border-color: var(--tab_line);
|
|
55
44
|
}
|
|
56
45
|
|
|
57
46
|
:scope.primary:hover {
|
|
58
|
-
background
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
);
|
|
64
|
-
|
|
47
|
+
background: var(--accent-shade-10);
|
|
48
|
+
border-color: var(--accent-shade-10);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
:scope:not(.icon):focus-visible {
|
|
52
|
+
outline: 2px solid var(--tab_line);
|
|
53
|
+
outline-offset: 2px;
|
|
65
54
|
}
|
|
66
55
|
|
|
67
56
|
:scope:disabled,
|
|
@@ -47,8 +47,7 @@ Checkbox.style = css`
|
|
|
47
47
|
display: flex;
|
|
48
48
|
align-items: center;
|
|
49
49
|
justify-content: center;
|
|
50
|
-
color:
|
|
51
|
-
text-shadow: 0 0.055em 0.05em var(--accent-shade-20);
|
|
50
|
+
color: #11111b;
|
|
52
51
|
font-size: 0.8em;
|
|
53
52
|
transform: scale(0);
|
|
54
53
|
transition: transform 120ms cubic-bezier(0.43, 0.91, 0.34, 1.3);
|
|
@@ -56,16 +55,13 @@ Checkbox.style = css`
|
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
:scope:has(input:checked) {
|
|
59
|
-
background
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
inset 0px 0.05em 0.025em rgb(255 255 255 / 40%),
|
|
67
|
-
inset 0px -0.05em 0.04em rgb(0 0 0 / 20%);
|
|
68
|
-
border: none;
|
|
58
|
+
background: var(--tab_line);
|
|
59
|
+
border-color: var(--tab_line);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
:scope:has(input:focus-visible) {
|
|
63
|
+
outline: 2px solid var(--tab_line);
|
|
64
|
+
outline-offset: 2px;
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
:scope:has(input:checked)::after {
|
|
@@ -61,14 +61,13 @@ Input.style = css`
|
|
|
61
61
|
font-size: 0.9em;
|
|
62
62
|
color: var(--toolbar_field_text);
|
|
63
63
|
outline: none;
|
|
64
|
-
transition:
|
|
65
|
-
border-color 0.2s ease,
|
|
66
|
-
box-shadow 0.2s ease;
|
|
64
|
+
transition: border-color 0.2s ease;
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
input:focus {
|
|
70
68
|
border-color: var(--tab_line);
|
|
71
|
-
|
|
69
|
+
outline: 2px solid var(--tab_line);
|
|
70
|
+
outline-offset: 2px;
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
input:disabled {
|
|
@@ -61,9 +61,14 @@ export function StartScreen(this: FC<StartScreenProps, StartScreenState>) {
|
|
|
61
61
|
<div class="start-screen">
|
|
62
62
|
<main class="start-panel" aria-labelledby="start-title">
|
|
63
63
|
<header class="product-name">
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
<img
|
|
65
|
+
class="product-mark"
|
|
66
|
+
src={`${import.meta.env.BASE_URL}favicon.png`}
|
|
67
|
+
alt=""
|
|
68
|
+
aria-hidden="true"
|
|
69
|
+
width="56"
|
|
70
|
+
height="56"
|
|
71
|
+
/>
|
|
67
72
|
<span>Roxxie Proxy U</span>
|
|
68
73
|
</header>
|
|
69
74
|
|
|
@@ -164,17 +169,18 @@ export function mountStartScreen(props: StartScreenProps): HTMLElement {
|
|
|
164
169
|
|
|
165
170
|
StartScreen.style = css`
|
|
166
171
|
:scope {
|
|
167
|
-
--start-background: #
|
|
168
|
-
--start-panel: #
|
|
169
|
-
--start-text: #
|
|
170
|
-
--start-muted: #
|
|
171
|
-
--start-border: #
|
|
172
|
-
--start-subtle: #
|
|
173
|
-
--start-action: #
|
|
174
|
-
--start-action-hover: #
|
|
175
|
-
--start-
|
|
176
|
-
--start-error-
|
|
177
|
-
--start-error-
|
|
172
|
+
--start-background: #11111b;
|
|
173
|
+
--start-panel: #222230;
|
|
174
|
+
--start-text: #ebeff5;
|
|
175
|
+
--start-muted: #b2bdcb;
|
|
176
|
+
--start-border: #4f526b;
|
|
177
|
+
--start-subtle: #191925;
|
|
178
|
+
--start-action: #eb458b;
|
|
179
|
+
--start-action-hover: #d6387a;
|
|
180
|
+
--start-action-text: #11111b;
|
|
181
|
+
--start-error-background: #2d1d26;
|
|
182
|
+
--start-error-border: #a85173;
|
|
183
|
+
--start-error-text: #f3afcb;
|
|
178
184
|
|
|
179
185
|
width: 100%;
|
|
180
186
|
height: 100%;
|
|
@@ -201,29 +207,23 @@ StartScreen.style = css`
|
|
|
201
207
|
padding: 2rem;
|
|
202
208
|
background: var(--start-panel);
|
|
203
209
|
border: 1px solid var(--start-border);
|
|
204
|
-
border-radius:
|
|
210
|
+
border-radius: 16px;
|
|
205
211
|
}
|
|
206
212
|
|
|
207
213
|
.product-name {
|
|
208
214
|
display: flex;
|
|
209
215
|
align-items: center;
|
|
210
|
-
gap: 0.
|
|
216
|
+
gap: 0.8rem;
|
|
211
217
|
font-size: 0.9rem;
|
|
212
218
|
font-weight: 650;
|
|
213
219
|
letter-spacing: 0.01em;
|
|
214
220
|
}
|
|
215
221
|
|
|
216
222
|
.product-mark {
|
|
217
|
-
width:
|
|
218
|
-
height:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
justify-content: center;
|
|
222
|
-
border-radius: 4px;
|
|
223
|
-
background: var(--start-action);
|
|
224
|
-
color: #ffffff;
|
|
225
|
-
font-size: 0.95rem;
|
|
226
|
-
font-weight: 750;
|
|
223
|
+
width: 3.5rem;
|
|
224
|
+
height: 3.5rem;
|
|
225
|
+
object-fit: contain;
|
|
226
|
+
flex: 0 0 auto;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
.introduction {
|
|
@@ -266,7 +266,7 @@ StartScreen.style = css`
|
|
|
266
266
|
padding: 0.9rem 1rem;
|
|
267
267
|
background: var(--start-subtle);
|
|
268
268
|
border: 1px solid var(--start-border);
|
|
269
|
-
border-radius:
|
|
269
|
+
border-radius: 10px;
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
.status-label {
|
|
@@ -288,7 +288,7 @@ StartScreen.style = css`
|
|
|
288
288
|
padding: 1rem;
|
|
289
289
|
background: var(--start-error-background);
|
|
290
290
|
border: 1px solid var(--start-error-border);
|
|
291
|
-
border-radius:
|
|
291
|
+
border-radius: 10px;
|
|
292
292
|
color: var(--start-error-text);
|
|
293
293
|
font-size: 0.85rem;
|
|
294
294
|
}
|
|
@@ -323,8 +323,8 @@ StartScreen.style = css`
|
|
|
323
323
|
padding: 0.7rem 1rem;
|
|
324
324
|
background: var(--start-action);
|
|
325
325
|
border: 1px solid var(--start-action);
|
|
326
|
-
border-radius:
|
|
327
|
-
color:
|
|
326
|
+
border-radius: 10px;
|
|
327
|
+
color: var(--start-action-text);
|
|
328
328
|
font: inherit;
|
|
329
329
|
font-size: 0.95rem;
|
|
330
330
|
font-weight: 650;
|
|
@@ -337,13 +337,14 @@ StartScreen.style = css`
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
.start-button:focus-visible {
|
|
340
|
-
outline: 3px solid #
|
|
340
|
+
outline: 3px solid #f3afcb;
|
|
341
341
|
outline-offset: 2px;
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
.start-button:disabled {
|
|
345
|
-
background: #
|
|
346
|
-
border-color: #
|
|
345
|
+
background: #6b4056;
|
|
346
|
+
border-color: #6b4056;
|
|
347
|
+
color: var(--start-muted);
|
|
347
348
|
cursor: wait;
|
|
348
349
|
}
|
|
349
350
|
|
|
@@ -352,22 +353,6 @@ StartScreen.style = css`
|
|
|
352
353
|
font-size: 0.78rem;
|
|
353
354
|
}
|
|
354
355
|
|
|
355
|
-
@media (prefers-color-scheme: dark) {
|
|
356
|
-
:scope {
|
|
357
|
-
--start-background: #181a1b;
|
|
358
|
-
--start-panel: #222526;
|
|
359
|
-
--start-text: #f1f2ef;
|
|
360
|
-
--start-muted: #b4b8b5;
|
|
361
|
-
--start-border: #444846;
|
|
362
|
-
--start-subtle: #292c2d;
|
|
363
|
-
--start-action: #3d8068;
|
|
364
|
-
--start-action-hover: #4a9278;
|
|
365
|
-
--start-error-background: #322321;
|
|
366
|
-
--start-error-border: #875c55;
|
|
367
|
-
--start-error-text: #f0c1b9;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
356
|
@media (max-width: 34rem) {
|
|
372
357
|
:scope {
|
|
373
358
|
align-items: flex-start;
|
|
@@ -132,8 +132,8 @@ TopSiteButton.style = css`
|
|
|
132
132
|
|
|
133
133
|
.top-site-button:focus-visible .tile {
|
|
134
134
|
border-color: var(--tab_line);
|
|
135
|
-
|
|
136
|
-
outline:
|
|
135
|
+
outline: 2px solid var(--tab_line);
|
|
136
|
+
outline-offset: 2px;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
.icon-wrapper {
|
|
@@ -74,12 +74,15 @@ export function NewTabPage(this: FC<{ tab: Tab }>) {
|
|
|
74
74
|
<div>
|
|
75
75
|
<div class="logo">
|
|
76
76
|
<img
|
|
77
|
-
src={`${import.meta.env.BASE_URL}
|
|
77
|
+
src={`${import.meta.env.BASE_URL}favicon.png`}
|
|
78
78
|
alt="Roxxie Proxy U logo"
|
|
79
|
-
width="
|
|
80
|
-
height="
|
|
79
|
+
width="80"
|
|
80
|
+
height="80"
|
|
81
81
|
/>
|
|
82
|
-
<
|
|
82
|
+
<div class="logo-copy">
|
|
83
|
+
<span>EDUrocks network</span>
|
|
84
|
+
<h1>Roxxie Proxy U</h1>
|
|
85
|
+
</div>
|
|
83
86
|
</div>
|
|
84
87
|
<div class="topbar">
|
|
85
88
|
<div class="inputcontainercontainer">
|
|
@@ -153,16 +156,32 @@ NewTabPage.style = css`
|
|
|
153
156
|
.logo {
|
|
154
157
|
display: flex;
|
|
155
158
|
align-items: center;
|
|
156
|
-
gap: 1rem;
|
|
159
|
+
gap: 1.1rem;
|
|
157
160
|
margin-bottom: 2rem;
|
|
158
161
|
}
|
|
162
|
+
.logo-copy {
|
|
163
|
+
display: flex;
|
|
164
|
+
flex-direction: column;
|
|
165
|
+
gap: 0.2rem;
|
|
166
|
+
}
|
|
167
|
+
.logo-copy span {
|
|
168
|
+
color: var(--ntp-text-60);
|
|
169
|
+
font-size: 0.74rem;
|
|
170
|
+
font-weight: 700;
|
|
171
|
+
letter-spacing: 0.08em;
|
|
172
|
+
text-transform: uppercase;
|
|
173
|
+
}
|
|
159
174
|
.logo h1 {
|
|
160
|
-
font-size: 2.
|
|
161
|
-
font-weight:
|
|
175
|
+
font-size: 2.1rem;
|
|
176
|
+
font-weight: 650;
|
|
177
|
+
letter-spacing: -0.025em;
|
|
162
178
|
user-select: none;
|
|
163
179
|
}
|
|
164
180
|
.logo img {
|
|
165
181
|
display: inline-block;
|
|
182
|
+
width: 5rem;
|
|
183
|
+
height: 5rem;
|
|
184
|
+
object-fit: contain;
|
|
166
185
|
user-select: none;
|
|
167
186
|
}
|
|
168
187
|
.clock {
|
|
@@ -187,7 +206,6 @@ NewTabPage.style = css`
|
|
|
187
206
|
align-items: center;
|
|
188
207
|
transition:
|
|
189
208
|
border-color 0.15s ease-out,
|
|
190
|
-
box-shadow 0.15s ease-out,
|
|
191
209
|
background-color 0.15s ease-out;
|
|
192
210
|
}
|
|
193
211
|
|
|
@@ -199,8 +217,8 @@ NewTabPage.style = css`
|
|
|
199
217
|
|
|
200
218
|
.inputcontainer:focus-within {
|
|
201
219
|
border-color: var(--tab_line);
|
|
202
|
-
|
|
203
|
-
outline:
|
|
220
|
+
outline: 2px solid var(--tab_line);
|
|
221
|
+
outline-offset: 2px;
|
|
204
222
|
}
|
|
205
223
|
input {
|
|
206
224
|
font-size: 1.05rem;
|
|
@@ -260,5 +278,19 @@ NewTabPage.style = css`
|
|
|
260
278
|
.top-sites-list {
|
|
261
279
|
grid-template-columns: repeat(auto-fit, minmax(6.25rem, 6.25rem));
|
|
262
280
|
}
|
|
281
|
+
|
|
282
|
+
.logo {
|
|
283
|
+
align-items: flex-start;
|
|
284
|
+
gap: 0.8rem;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.logo img {
|
|
288
|
+
width: 4rem;
|
|
289
|
+
height: 4rem;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.logo h1 {
|
|
293
|
+
font-size: 1.65rem;
|
|
294
|
+
}
|
|
263
295
|
}
|
|
264
296
|
`;
|
|
@@ -1313,7 +1313,7 @@ export function SettingsPage(
|
|
|
1313
1313
|
<div class="about-info">
|
|
1314
1314
|
<img
|
|
1315
1315
|
class="browser-logo"
|
|
1316
|
-
src={`${import.meta.env.BASE_URL}
|
|
1316
|
+
src={`${import.meta.env.BASE_URL}favicon.png`}
|
|
1317
1317
|
alt="Roxxie Proxy U logo"
|
|
1318
1318
|
/>
|
|
1319
1319
|
<div class="browser-info">
|
|
@@ -1505,7 +1505,8 @@ SettingsPage.style = css`
|
|
|
1505
1505
|
|
|
1506
1506
|
.search-input input:focus {
|
|
1507
1507
|
border-color: var(--tab_line);
|
|
1508
|
-
|
|
1508
|
+
outline: 2px solid var(--tab_line);
|
|
1509
|
+
outline-offset: 2px;
|
|
1509
1510
|
}
|
|
1510
1511
|
|
|
1511
1512
|
.search-input .icon {
|
|
@@ -1653,16 +1654,11 @@ SettingsPage.style = css`
|
|
|
1653
1654
|
cursor: pointer;
|
|
1654
1655
|
display: flex;
|
|
1655
1656
|
flex-direction: column;
|
|
1656
|
-
transition:
|
|
1657
|
-
border-color 0.15s ease,
|
|
1658
|
-
box-shadow 0.15s ease,
|
|
1659
|
-
transform 0.15s ease;
|
|
1657
|
+
transition: border-color 0.15s ease;
|
|
1660
1658
|
}
|
|
1661
1659
|
|
|
1662
1660
|
.layout-card:hover {
|
|
1663
1661
|
border-color: var(--tab_line);
|
|
1664
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
1665
|
-
transform: translateY(-1px);
|
|
1666
1662
|
}
|
|
1667
1663
|
|
|
1668
1664
|
.layout-card:focus-within {
|
|
@@ -1672,7 +1668,8 @@ SettingsPage.style = css`
|
|
|
1672
1668
|
|
|
1673
1669
|
.layout-card.selected {
|
|
1674
1670
|
border-color: var(--tab_line);
|
|
1675
|
-
|
|
1671
|
+
outline: 2px solid var(--tab_line);
|
|
1672
|
+
outline-offset: 2px;
|
|
1676
1673
|
}
|
|
1677
1674
|
|
|
1678
1675
|
.layout-radio {
|
|
@@ -1833,6 +1830,7 @@ SettingsPage.style = css`
|
|
|
1833
1830
|
.browser-logo {
|
|
1834
1831
|
width: 5rem;
|
|
1835
1832
|
height: 5rem;
|
|
1833
|
+
object-fit: contain;
|
|
1836
1834
|
}
|
|
1837
1835
|
|
|
1838
1836
|
.browser-info h3 {
|
|
@@ -1894,6 +1892,7 @@ SettingsPage.style = css`
|
|
|
1894
1892
|
}
|
|
1895
1893
|
|
|
1896
1894
|
.theme-card {
|
|
1895
|
+
border: 1px solid var(--ntp-text-15);
|
|
1897
1896
|
border-radius: var(--radius-md);
|
|
1898
1897
|
overflow: hidden;
|
|
1899
1898
|
cursor: pointer;
|
|
@@ -1903,12 +1902,12 @@ SettingsPage.style = css`
|
|
|
1903
1902
|
|
|
1904
1903
|
.theme-card:hover {
|
|
1905
1904
|
border-color: var(--tab_line);
|
|
1906
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
1907
1905
|
}
|
|
1908
1906
|
|
|
1909
1907
|
.theme-card.selected {
|
|
1910
1908
|
border-color: var(--tab_line);
|
|
1911
|
-
|
|
1909
|
+
outline: 2px solid var(--tab_line);
|
|
1910
|
+
outline-offset: 2px;
|
|
1912
1911
|
}
|
|
1913
1912
|
|
|
1914
1913
|
.theme-info {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Static assets may be delivered by a CDN while configuration and service
|
|
5
5
|
* workers must remain on the application's own origin. Development and the
|
|
6
6
|
* standalone build use Vite's ordinary base URL; the production npm build
|
|
7
|
-
* supplies
|
|
7
|
+
* supplies its versioned, same-origin unpkg runtime directory explicitly.
|
|
8
8
|
*/
|
|
9
9
|
export function runtimeBaseUrl(): URL {
|
|
10
10
|
const configuredBase = import.meta.env.VITE_RUNTIME_BASE?.trim();
|
|
@@ -33,8 +33,8 @@ iframe {
|
|
|
33
33
|
html,
|
|
34
34
|
body {
|
|
35
35
|
font-family: var(--font);
|
|
36
|
-
color: var(--toolbar_text);
|
|
37
|
-
background: var(--toolbar);
|
|
36
|
+
color: var(--toolbar_text, #ebeff5);
|
|
37
|
+
background: var(--toolbar, #222230);
|
|
38
38
|
accent-color: var(--tab_line);
|
|
39
39
|
color-scheme: dark;
|
|
40
40
|
|
|
@@ -93,11 +93,11 @@ body {
|
|
|
93
93
|
--accent-shade-40: color-mix(in oklab, black 40%, var(--tab_line));
|
|
94
94
|
--accent-shade-50: color-mix(in oklab, black 50%, var(--tab_line));
|
|
95
95
|
|
|
96
|
-
--radius-xs:
|
|
97
|
-
--radius-sm:
|
|
98
|
-
--radius-md:
|
|
99
|
-
--radius-lg:
|
|
100
|
-
--radius-xl:
|
|
96
|
+
--radius-xs: 4px;
|
|
97
|
+
--radius-sm: 6px;
|
|
98
|
+
--radius-md: 8px;
|
|
99
|
+
--radius-lg: 12px;
|
|
100
|
+
--radius-xl: 16px;
|
|
101
101
|
|
|
102
102
|
--space-xxs: 0.15rem;
|
|
103
103
|
--space-xs: 0.225rem;
|