Skip to content

Commit 61d2d7d

Browse files
committed
Enhance Screenshot component: add aspect ratio handling for SVGs and prioritize loading.
1 parent 57541d2 commit 61d2d7d

1 file changed

Lines changed: 75 additions & 3 deletions

File tree

Spectre.Docs/Components/Shared/Screenshot.razor

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
<div class="not-prose bg-base-950/80 dark:bg-base-800 border-1 dark:border-base-500/10 border-base-500/50 rounded-lg lg:rounded-xl p-1 lg:p-2 mt-4 -mx-3 lg:mx-0 shadow-sm lg:shadow-xl">
1+
@inject IWebHostEnvironment Environment
2+
3+
<div class="not-prose bg-base-950/80 dark:bg-base-800 border-1 dark:border-base-500/10 border-base-500/50 rounded-lg lg:rounded-xl p-1 lg:p-2 mt-4 -mx-3 lg:mx-0 shadow-sm lg:shadow-xl">
24
<div class="not-prose flex flex-col rounded-lg lg:rounded-xl">
35
<!-- Terminal buttons -->
46
<div class="flex justify-end-safe gap-2 py-2 px-4">
@@ -7,7 +9,12 @@
79
<div class="w-2 h-2 lg:w-3 lg:h-3 rounded-sm bg-accent-200/90 dark:bg-accent-500/60 border border-accent-900/50 dark:border-accent-600"></div>
810
</div>
911
<div class="rounded-lg inner-shadow py-2 px-2 lg:px-6 bg-base-950/40 dark:bg-base-900 [background-image:repeating-linear-gradient(0deg,transparent,transparent_2px,rgba(255,255,255,0.01)_2px,rgba(255,255,255,0.01)_4px)]">
10-
<img defer src="@Src" alt="@Alt" loading="lazy" style="width: 100%;" />
12+
@{
13+
var imgStyle = _aspectRatio != null
14+
? $"width: 100%; aspect-ratio: {_aspectRatio};"
15+
: "width: 100%;";
16+
}
17+
<img fetchpriority="high" src="@Src" alt="@Alt" style="@imgStyle" />
1118
</div>
1219
</div>
1320
</div>
@@ -18,4 +25,69 @@
1825

1926
[Parameter]
2027
public string Alt { get; set; } = "Screenshot";
21-
}
28+
29+
private string? _aspectRatio;
30+
31+
protected override void OnParametersSet()
32+
{
33+
_aspectRatio = null;
34+
35+
// Only process SVG files from /assets/
36+
if (!string.IsNullOrEmpty(Src) &&
37+
Src.StartsWith("/assets/", StringComparison.OrdinalIgnoreCase) &&
38+
Src.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
39+
{
40+
_aspectRatio = TryGetAspectRatio(Src);
41+
}
42+
}
43+
44+
private string? TryGetAspectRatio(string srcUrl)
45+
{
46+
try
47+
{
48+
// Map URL /assets/file.svg to Content/assets/file.svg
49+
var relativePath = srcUrl.TrimStart('/');
50+
51+
// Handle both Windows and Unix path separators
52+
if (Path.DirectorySeparatorChar != '/')
53+
{
54+
relativePath = relativePath.Replace('/', Path.DirectorySeparatorChar);
55+
}
56+
57+
var contentPath = Path.Combine(Environment.ContentRootPath, "Content", relativePath);
58+
59+
if (!File.Exists(contentPath))
60+
{
61+
return null;
62+
}
63+
64+
// Read only first 1KB - viewBox should be in opening <svg> tag
65+
using var stream = new FileStream(contentPath, FileMode.Open, FileAccess.Read, FileShare.Read);
66+
using var reader = new StreamReader(stream);
67+
var buffer = new char[1024];
68+
var charsRead = reader.Read(buffer, 0, buffer.Length);
69+
var content = new string(buffer, 0, charsRead);
70+
71+
// Parse viewBox="minX minY width height" - captures the last two numbers (width and height)
72+
var match = System.Text.RegularExpressions.Regex.Match(
73+
content,
74+
@"viewBox\s*=\s*[""'][\d.\-]+\s+[\d.\-]+\s+([\d.]+)\s+([\d.]+)[""']");
75+
76+
if (match.Success &&
77+
double.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Float,
78+
System.Globalization.CultureInfo.InvariantCulture, out var width) &&
79+
double.TryParse(match.Groups[2].Value, System.Globalization.NumberStyles.Float,
80+
System.Globalization.CultureInfo.InvariantCulture, out var height) &&
81+
height > 0 && width > 0)
82+
{
83+
return FormattableString.Invariant($"{width} / {height}");
84+
}
85+
}
86+
catch
87+
{
88+
// Any error - fall back to no aspect ratio
89+
}
90+
91+
return null;
92+
}
93+
}

0 commit comments

Comments
 (0)