Skip to content

Commit ec812c5

Browse files
committed
Removing inline styles and improving CSP
1 parent c6cf138 commit ec812c5

22 files changed

Lines changed: 410 additions & 51 deletions

apps/proxy/prod.Caddyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
# Production CSP
3232
# Using hash for inline script instead of 'unsafe-inline'
33-
Content-Security-Policy "default-src 'none'; script-src 'self' 'wasm-unsafe-eval' 'sha256-HlD9D/WlEaVKKAvDnldsXkj/nllO8aCRBvtofUTEnGQ='; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss://*.zxcoder.org https://*.zxcoder.org; worker-src 'self' blob:; child-src 'self' blob:; frame-src 'none'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; manifest-src 'self'; media-src 'self'; upgrade-insecure-requests; block-all-mixed-content"
33+
Content-Security-Policy "default-src 'none'; script-src 'self' 'wasm-unsafe-eval' 'sha256-HlD9D/WlEaVKKAvDnldsXkj/nllO8aCRBvtofUTEnGQ='; style-src 'self'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss://*.zxcoder.org https://*.zxcoder.org; worker-src 'self' blob:; child-src 'self' blob:; frame-src 'none'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; manifest-src 'self'; media-src 'self'; upgrade-insecure-requests; block-all-mixed-content"
3434

3535
# CSP Report endpoint (optional - set up monitoring)
3636
# Report-To "{\"group\":\"csp-endpoint\",\"max_age\":10886400,\"endpoints\":[{\"url\":\"https://your-report-collector.example.com/csp-reports\"}]}"

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"html-webpack-plugin": "^5.6.4",
7878
"jest": "^30.2.0",
7979
"jest-transform-stub": "^2.0.0",
80+
"mini-css-extract-plugin": "^2.9.4",
8081
"npm-run-all": "^4.1.5",
8182
"npm-watch": "^0.13.0",
8283
"process": "^0.11.10",

apps/web/public/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
<meta name="twitter:title" content="Code . ZX Play">
2424
<meta name="twitter:description" content="A ZX Spectrum emulator & programming environment for the browser.">
2525
<meta name="twitter:image" content="/assets/images/embed-preview.png">
26-
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'wasm-unsafe-eval' 'sha256-HlD9D/WlEaVKKAvDnldsXkj/nllO8aCRBvtofUTEnGQ='; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss://*.zxcoder.org https://*.zxcoder.org; worker-src 'self' blob:; child-src 'self' blob:; frame-src 'none'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; manifest-src 'self'; media-src 'self'">
2726
<link rel="stylesheet" type="text/css" href="/style.css?ver=<%= buildVersion %>">
27+
<link rel="stylesheet" type="text/css" href="/dist/main.css?ver=<%= buildVersion %>">
2828
</head>
2929
<body>
3030
<div id="root"></div>

apps/web/public/style.css

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,227 @@ code {
138138
.mobile .p-tabview-panels {
139139
padding: 0 !important;
140140
}
141+
142+
/* Utility classes for inline style replacements */
143+
.text-center {
144+
text-align: center;
145+
}
146+
147+
.full-width-grid {
148+
width: 100%;
149+
padding: 0;
150+
margin: 0;
151+
}
152+
153+
.col-no-padding {
154+
padding: 0;
155+
}
156+
157+
.height-53 {
158+
height: 53px;
159+
}
160+
161+
.max-width-1024 {
162+
max-width: 1024px;
163+
margin: auto;
164+
}
165+
166+
.margin-top-8 {
167+
margin-top: 8px;
168+
}
169+
170+
.dialog-width-450 {
171+
width: 450px;
172+
}
173+
174+
.min-height-400 {
175+
min-height: 400px;
176+
}
177+
178+
.text-nowrap-min-160 {
179+
white-space: nowrap;
180+
min-width: 160px;
181+
}
182+
183+
.user-select-none {
184+
user-select: none;
185+
}
186+
187+
.col-width-34-mobile-70 {
188+
width: 34%;
189+
}
190+
191+
.col-width-22-mobile-30 {
192+
width: 22%;
193+
}
194+
195+
.col-width-22 {
196+
width: 22%;
197+
}
198+
199+
.card-bg-dark {
200+
background-color: #2c2c2c;
201+
}
202+
203+
.avatar-editor-container {
204+
display: grid;
205+
grid-template-columns: auto auto;
206+
gap: 20px;
207+
justify-content: center;
208+
align-items: start;
209+
}
210+
211+
.avatar-canvas-container {
212+
display: flex;
213+
flex-direction: column;
214+
align-items: center;
215+
gap: 10px;
216+
}
217+
218+
.avatar-controls {
219+
width: 200px;
220+
}
221+
222+
.color-picker {
223+
display: flex;
224+
flex-wrap: wrap;
225+
gap: 5px;
226+
margin-top: 10px;
227+
}
228+
229+
.color-swatch {
230+
width: 30px;
231+
height: 30px;
232+
cursor: pointer;
233+
border: 2px solid transparent;
234+
}
235+
236+
.color-swatch:hover {
237+
border-color: #fff;
238+
}
239+
240+
.avatar-selector-dialog {
241+
width: 600px;
242+
}
243+
244+
.avatar-option {
245+
cursor: pointer;
246+
border: 2px solid transparent;
247+
padding: 5px;
248+
}
249+
250+
.avatar-option:hover {
251+
border-color: #fff;
252+
}
253+
254+
.avatar-button-min-80 {
255+
min-width: 80px;
256+
text-align: center;
257+
}
258+
259+
.avatar-preview-centered {
260+
padding-top: 10px;
261+
}
262+
263+
.tag-user-icon {
264+
background-color: #2c2c2c;
265+
color: #ffffff;
266+
}
267+
268+
.editor-dialog-50vw {
269+
width: 50vw;
270+
}
271+
272+
.profile-header {
273+
display: flex;
274+
gap: 20px;
275+
align-items: center;
276+
}
277+
278+
.profile-avatar {
279+
flex-shrink: 0;
280+
}
281+
282+
.profile-info {
283+
flex: 1;
284+
}
285+
286+
.profile-username {
287+
font-size: 12px;
288+
color: #aaa;
289+
}
290+
291+
.profile-bio {
292+
margin-top: 10px;
293+
padding: 10px;
294+
background-color: #2c2c2c;
295+
border-radius: 4px;
296+
}
297+
298+
.profile-stats {
299+
display: flex;
300+
gap: 20px;
301+
margin-top: 10px;
302+
}
303+
304+
.profile-stat-item {
305+
cursor: pointer;
306+
}
307+
308+
.profile-stat-item:hover {
309+
text-decoration: underline;
310+
}
311+
312+
.activity-card-bg {
313+
background-color: #2c2c2c;
314+
margin-bottom: 15px;
315+
cursor: pointer;
316+
}
317+
318+
.activity-card-bg:hover {
319+
background-color: #333;
320+
}
321+
322+
.activity-item-header {
323+
display: flex;
324+
justify-content: space-between;
325+
align-items: center;
326+
margin-bottom: 10px;
327+
}
328+
329+
.activity-item-user {
330+
display: flex;
331+
align-items: center;
332+
gap: 10px;
333+
}
334+
335+
.activity-item-content {
336+
padding-left: 40px;
337+
}
338+
339+
.activity-timestamp {
340+
font-size: 12px;
341+
color: #aaa;
342+
}
343+
344+
.follow-list-dialog {
345+
background-color: #2c2c2c;
346+
}
347+
348+
.follow-list-header {
349+
display: flex;
350+
justify-content: space-between;
351+
align-items: center;
352+
padding: 15px;
353+
border-bottom: 1px solid #444;
354+
}
355+
356+
@media (max-width: 768px) {
357+
.col-width-34-mobile-70 {
358+
width: 70%;
359+
}
360+
361+
.col-width-22-mobile-30 {
362+
width: 30%;
363+
}
364+
}

apps/web/src/components/ActivityFeed.jsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ export default function ActivityFeed() {
6161
if (feedLoading) {
6262
return (
6363
<div
64-
className="flex justify-content-center align-items-center"
65-
style={{ minHeight: "400px" }}
64+
className="flex justify-content-center align-items-center min-height-400"
6665
>
6766
<ProgressSpinner />
6867
</div>
@@ -105,10 +104,9 @@ export default function ActivityFeed() {
105104
>
106105
<Link to={projectUrl} className="no-underline">
107106
<Card
108-
className="h-full hover:shadow-5 transition-all transition-duration-200 cursor-pointer overflow-hidden"
107+
className="h-full hover:shadow-5 transition-all transition-duration-200 cursor-pointer overflow-hidden card-bg-dark"
109108
style={{
110109
border: "none",
111-
backgroundColor: "#2c2c2c",
112110
}}
113111
>
114112
<div className="flex flex-column h-full relative">

apps/web/src/components/AvatarPixelEditor.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export default function AvatarPixelEditor({ identifier, onSave, onCancel }) {
147147
</div>
148148

149149
<div
150-
className="pixel-canvas"
150+
className="pixel-canvas user-select-none"
151151
onMouseUp={handleMouseUp}
152152
onMouseLeave={handleMouseUp}
153153
style={{
@@ -156,7 +156,6 @@ export default function AvatarPixelEditor({ identifier, onSave, onCancel }) {
156156
borderRadius: "4px",
157157
backgroundColor: "#1a1a1a",
158158
padding: "8px",
159-
userSelect: "none",
160159
}}
161160
>
162161
<div

apps/web/src/components/AvatarSelector.jsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ export default function AvatarSelector({
8787
disabled={currentPage === 0}
8888
/>
8989
<span
90-
className="text-sm px-1"
91-
style={{ minWidth: "80px", textAlign: "center" }}
90+
className="text-sm px-1 avatar-button-min-80"
9291
>
9392
Page {currentPage + 1}/{totalPages}
9493
</span>
@@ -129,7 +128,6 @@ export default function AvatarSelector({
129128
visible={visible}
130129
onHide={onHide}
131130
footer={footer}
132-
style={{ width: "600px" }}
133131
className="avatar-selector-dialog"
134132
>
135133
<TabView
@@ -178,7 +176,7 @@ export default function AvatarSelector({
178176
))}
179177
</div>
180178

181-
<div className="text-center mt-2" style={{ paddingTop: "10px" }}>
179+
<div className="text-center mt-2 avatar-preview-centered">
182180
<small className="text-500">
183181
Tip: Use arrow buttons to browse more patterns, or click Randomize
184182
for a surprise!

apps/web/src/components/DemoAssemblyEditor.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function DemoAssemblyEditor() {
3838
<Button
3939
label="Play"
4040
icon="pi pi-play"
41-
style={{ marginTop: "8px" }}
41+
className="margin-top-8"
4242
onClick={() => {
4343
dashboardLock();
4444
dispatch(runAssembly());

apps/web/src/components/DemoSinclairBasicEditor.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function DemoSinclairBasicEditor() {
3838
<Button
3939
label="Play"
4040
icon="pi pi-play"
41-
style={{marginTop: "8px"}}
41+
className="margin-top-8"
4242
onClick={() => {
4343
dashboardLock();
4444
dispatch(runSinclairBasic());

apps/web/src/components/ErrorPage.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default function ErrorPage({msg}) {
2525

2626
return (
2727
<Titled title={(s) => `Error ${sep} ${s}`}>
28-
<Card className="m-2" style={{textAlign: 'center'}}>
28+
<Card className="m-2 text-center">
2929
<div className="m-4">
3030
<p>Sorry, an unexpected error occurred.</p>
3131
<p>Error message is:</p>

0 commit comments

Comments
 (0)