Skip to content

Commit 38ee478

Browse files
committed
feat: enhance theme switcher and add atom-dark Prism theme support
1 parent 622ae47 commit 38ee478

4 files changed

Lines changed: 207 additions & 17 deletions

File tree

Web/Extensions/EndpointExtensions.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -278,51 +278,51 @@ public static void MapArticleImagesEndpoint(this WebApplication app)
278278

279279
// Sanitize the path to prevent any potential issues
280280
imagePath = imagePath.Replace("..", "").TrimStart('/');
281-
281+
282282
try
283283
{
284284
// Get the container client (using "images" as the default container name)
285285
var containerClient = blobServiceClient.GetBlobContainerClient("content-images");
286-
286+
287287
// Check if the container exists
288288
if (!await containerClient.ExistsAsync())
289289
{
290290
logger.LogError("Images container not found in blob storage");
291291
return Results.Problem("Image container not available", statusCode: 500);
292292
}
293-
293+
294294
// Get the blob client for the requested image
295295
var blobClient = containerClient.GetBlobClient(imagePath);
296-
296+
297297
// Check if the blob exists
298298
if (!await blobClient.ExistsAsync())
299299
{
300300
logger.LogWarning("Article image not found in blob storage: {ImagePath}", imagePath);
301301
return Results.NotFound();
302302
}
303-
303+
304304
// Get the blob properties to determine content type
305305
var properties = await blobClient.GetPropertiesAsync();
306306
var contentType = properties.Value.ContentType;
307-
307+
308308
// If content type is not set in blob properties, determine it from file extension
309309
if (string.IsNullOrEmpty(contentType))
310310
{
311311
contentType = GetContentType(Path.GetExtension(imagePath));
312312
}
313-
313+
314314
// Set cache control headers for better performance
315315
context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
316316
{
317317
Public = true,
318318
MaxAge = TimeSpan.FromDays(30)
319319
};
320-
320+
321321
// Download the blob content
322322
var memoryStream = new MemoryStream();
323323
await blobClient.DownloadToAsync(memoryStream);
324324
memoryStream.Position = 0;
325-
325+
326326
// Return the file content with the appropriate content type
327327
return Results.File(memoryStream.ToArray(), contentType);
328328
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/**
2+
* atom-dark theme for `prism.js`
3+
* Based on Atom's `atom-dark` theme: https://github.com/atom/atom-dark-syntax
4+
* @author Joe Gibson (@gibsjose)
5+
*/
6+
7+
code[class*="language-"],
8+
pre[class*="language-"] {
9+
color: #c5c8c6;
10+
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
11+
font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier, monospace;
12+
direction: ltr;
13+
text-align: left;
14+
white-space: pre;
15+
word-spacing: normal;
16+
word-break: normal;
17+
line-height: 1.5;
18+
19+
-moz-tab-size: 4;
20+
-o-tab-size: 4;
21+
tab-size: 4;
22+
23+
-webkit-hyphens: none;
24+
-moz-hyphens: none;
25+
-ms-hyphens: none;
26+
hyphens: none;
27+
}
28+
29+
/* Code blocks */
30+
pre[class*="language-"] {
31+
padding: 1em;
32+
margin: .5em 0;
33+
overflow: auto;
34+
border-radius: 0.3em;
35+
}
36+
37+
:not(pre) > code[class*="language-"],
38+
pre[class*="language-"] {
39+
background: #1d1f21;
40+
}
41+
42+
/* Inline code */
43+
:not(pre) > code[class*="language-"] {
44+
padding: .1em;
45+
border-radius: .3em;
46+
}
47+
48+
.token.comment,
49+
.token.prolog,
50+
.token.doctype,
51+
.token.cdata {
52+
color: #7C7C7C;
53+
}
54+
55+
.token.punctuation {
56+
color: #c5c8c6;
57+
}
58+
59+
.namespace {
60+
opacity: .7;
61+
}
62+
63+
.token.property,
64+
.token.keyword,
65+
.token.tag {
66+
color: #96CBFE;
67+
}
68+
69+
.token.class-name {
70+
color: #FFFFB6;
71+
text-decoration: underline;
72+
}
73+
74+
.token.boolean,
75+
.token.constant {
76+
color: #99CC99;
77+
}
78+
79+
.token.symbol,
80+
.token.deleted {
81+
color: #f92672;
82+
}
83+
84+
.token.number {
85+
color: #FF73FD;
86+
}
87+
88+
.token.selector,
89+
.token.attr-name,
90+
.token.string,
91+
.token.char,
92+
.token.builtin,
93+
.token.inserted {
94+
color: #A8FF60;
95+
}
96+
97+
.token.variable {
98+
color: #C6C5FE;
99+
}
100+
101+
.token.operator {
102+
color: #EDEDED;
103+
}
104+
105+
.token.entity {
106+
color: #FFFFB6;
107+
cursor: help;
108+
}
109+
110+
.token.url {
111+
color: #96CBFE;
112+
}
113+
114+
.language-css .token.string,
115+
.style .token.string {
116+
color: #87C38A;
117+
}
118+
119+
.token.atrule,
120+
.token.attr-value {
121+
color: #F9EE98;
122+
}
123+
124+
.token.function {
125+
color: #DAD085;
126+
}
127+
128+
.token.regex {
129+
color: #E9C062;
130+
}
131+
132+
.token.important {
133+
color: #fd971f;
134+
}
135+
136+
.token.important,
137+
.token.bold {
138+
font-weight: bold;
139+
}
140+
141+
.token.italic {
142+
font-style: italic;
143+
}

Web/wwwroot/css/site.css

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ body {
402402

403403
/* Basic code block styling with theme support */
404404
pre[class*="language-"] {
405+
color: var(--text-primary);
405406
position: relative;
406407
margin: 1.5rem 0;
407408
border-radius: 0.5rem;
@@ -721,4 +722,37 @@ html[data-theme-resolved="dark"] .tip-content table.comparison-table tbody td:la
721722
background-color: var(--primary-dark);
722723
border-color: var(--primary-dark);
723724
box-shadow: 0 0 0 0.25rem rgba(98, 0, 238, 0.25);
725+
}
726+
727+
/* Code block styling with word wrapping */
728+
pre {
729+
white-space: pre-wrap; /* CSS3 */
730+
word-wrap: break-word; /* IE */
731+
word-break: break-word;
732+
overflow-wrap: break-word;
733+
max-width: 100%;
734+
overflow-x: hidden !important;
735+
padding: 1rem;
736+
border-radius: 0.5rem;
737+
margin: 1.5rem 0;
738+
}
739+
740+
pre code {
741+
white-space: pre-wrap !important;
742+
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
743+
}
744+
745+
/* Adjust the code block styling for different screen sizes */
746+
@media (max-width: 768px) {
747+
pre {
748+
padding: 0.75rem;
749+
font-size: 0.85rem;
750+
}
751+
}
752+
753+
/* Ensure code blocks have proper background in dark mode */
754+
html[data-theme="dark"] pre,
755+
html[data-theme-resolved="dark"] pre {
756+
background-color: var(--code-bg);
757+
border: 1px solid var(--border-color);
724758
}

Web/wwwroot/js/theme-switcher.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,34 @@ class ThemeSwitcher {
135135
}));
136136
} // Load the appropriate Prism theme based on current theme
137137
updatePrismTheme(resolvedTheme) {
138-
const prismThemeLink = document.getElementById('prism-theme');
139-
if (prismThemeLink) {
140-
const themeUrl = resolvedTheme === 'dark'
141-
? 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css'
142-
: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css';
143-
144-
// Update theme URL and trigger rehighlight
138+
// Look for the existing Prism theme link
139+
let prismThemeLink = document.getElementById('prism-theme');
140+
141+
// If it doesn't exist, create it
142+
if (!prismThemeLink) {
143+
prismThemeLink = document.createElement('link');
144+
prismThemeLink.id = 'prism-theme';
145+
prismThemeLink.rel = 'stylesheet';
146+
document.head.appendChild(prismThemeLink);
147+
}
148+
149+
const themeUrl = resolvedTheme === 'dark'
150+
? '/css/prism-atom-dark.css'
151+
: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css';
152+
153+
// Only update if the theme URL has changed
154+
if (prismThemeLink.href !== themeUrl) {
155+
// Update theme URL
145156
prismThemeLink.href = themeUrl;
146157

147158
// Re-highlight code if Prism is available
148159
if (window.Prism) {
149160
setTimeout(() => {
150161
Prism.highlightAll();
151-
}, 100); // Small delay to ensure theme is loaded
162+
}, 200); // Slightly longer delay to ensure theme is loaded
152163
}
164+
165+
console.log(`Prism theme updated to: ${resolvedTheme === 'dark' ? 'dark' : 'light'}`);
153166
}
154167
}
155168
updateNavbarStyling() {

0 commit comments

Comments
 (0)