blume 0.6.2 → 0.6.3
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/package.json
CHANGED
|
@@ -28,7 +28,7 @@ const { prev, next, strings } = Astro.props;
|
|
|
28
28
|
>
|
|
29
29
|
<Icon class="rtl:-scale-x-100" name="arrow-left" size={16} />
|
|
30
30
|
<span>
|
|
31
|
-
<span class="block text-muted-foreground text-xs">
|
|
31
|
+
<span class="block text-muted-foreground text-xs max-md:hidden">
|
|
32
32
|
{strings.previous}
|
|
33
33
|
</span>
|
|
34
34
|
<span class="block font-medium">{prev.label}</span>
|
|
@@ -43,7 +43,7 @@ const { prev, next, strings } = Astro.props;
|
|
|
43
43
|
href={next.route}
|
|
44
44
|
>
|
|
45
45
|
<span>
|
|
46
|
-
<span class="block text-muted-foreground text-xs">
|
|
46
|
+
<span class="block text-muted-foreground text-xs max-md:hidden">
|
|
47
47
|
{strings.next}
|
|
48
48
|
</span>
|
|
49
49
|
<span class="block font-medium">{next.label}</span>
|
|
@@ -367,11 +367,15 @@ const bannerScript = banner?.dismissible
|
|
|
367
367
|
class:list={["mx-auto grid grid-cols-1 items-start", gridClass]}
|
|
368
368
|
data-blume-doc-grid
|
|
369
369
|
>
|
|
370
|
-
{
|
|
371
|
-
showSidebar && (
|
|
372
370
|
<aside
|
|
373
371
|
aria-label="Primary"
|
|
374
|
-
class=
|
|
372
|
+
class:list={[
|
|
373
|
+
"fixed top-[var(--blume-drawer-top,4rem)] start-0 z-[35] h-[calc(100dvh-var(--blume-drawer-top,4rem))] w-64 max-w-[80vw] -translate-x-[105%] overflow-y-auto border-border border-e bg-background px-5 pt-4 pb-6 transition-transform rtl:translate-x-[105%] [:where([data-blume-nav-open])_&]:translate-x-0! lg:sticky lg:top-16 lg:z-auto lg:h-[calc(100dvh-4rem)] lg:w-auto lg:max-w-none lg:translate-x-0! lg:border-e-0 lg:bg-transparent lg:px-4",
|
|
374
|
+
// A "bare" landing (the changelog index) has no sidebar column on
|
|
375
|
+
// desktop, but the header hamburger still needs a drawer to open on
|
|
376
|
+
// mobile — without it the toggle only locked page scroll.
|
|
377
|
+
!showSidebar && "lg:hidden",
|
|
378
|
+
]}
|
|
375
379
|
>
|
|
376
380
|
{
|
|
377
381
|
// Pinned links (blog, changelog, contact…) sit above every section on
|
|
@@ -419,9 +423,17 @@ const bannerScript = banner?.dismissible
|
|
|
419
423
|
// The header's tab bar is hidden below `md`, so the drawer is the only
|
|
420
424
|
// way to move between sections on mobile: list the tabs above the
|
|
421
425
|
// page tree, separated by a divider. Hidden from `md` up, where the
|
|
422
|
-
// header tabs take over
|
|
426
|
+
// header tabs take over — unless the page tree is empty (a tab-scoped
|
|
427
|
+
// standalone page like the changelog), where they keep the drawer
|
|
428
|
+
// from opening blank.
|
|
423
429
|
navigation.tabs.length > 0 && (
|
|
424
|
-
<nav
|
|
430
|
+
<nav
|
|
431
|
+
aria-label="Sections"
|
|
432
|
+
class:list={[
|
|
433
|
+
"mb-4 border-border border-b pb-4",
|
|
434
|
+
sidebar.length > 0 && "md:hidden",
|
|
435
|
+
]}
|
|
436
|
+
>
|
|
425
437
|
<ul class="m-0 list-none p-0">
|
|
426
438
|
{navigation.tabs.map((tab) => (
|
|
427
439
|
<li>
|
|
@@ -460,8 +472,6 @@ const bannerScript = banner?.dismissible
|
|
|
460
472
|
}
|
|
461
473
|
</nav>
|
|
462
474
|
</aside>
|
|
463
|
-
)
|
|
464
|
-
}
|
|
465
475
|
<main class="px-6 pt-6 pb-10 lg:px-8 xl:px-10" id="blume-content">
|
|
466
476
|
<BreadcrumbsSlot crumbs={crumbs} wide={isApiOperation} />
|
|
467
477
|
<TableOfContentsSlot
|
package/src/og/card.ts
CHANGED
|
@@ -80,27 +80,34 @@ export const truncate = (value: string, max: number): string => {
|
|
|
80
80
|
: value;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
// Brand mark sizing: target this height, but scale down so
|
|
84
|
-
// stays within the lockup.
|
|
83
|
+
// Brand mark sizing: target this height, but scale down so an extremely wide
|
|
84
|
+
// logo stays within the lockup. The cap leaves room for a wordmark to render
|
|
85
|
+
// at full height — it stands alone as the brand (no text label beside it).
|
|
85
86
|
const MARK_HEIGHT = 32;
|
|
86
|
-
const MARK_MAX_WIDTH =
|
|
87
|
+
const MARK_MAX_WIDTH = 240;
|
|
87
88
|
// Accept either quote style and a non-zero min-x/min-y; only width/height
|
|
88
89
|
// matter for the aspect ratio. A miss falls back to a square mark.
|
|
89
90
|
const VIEW_BOX =
|
|
90
91
|
/viewBox=(?<q>["'])[\d.-]+[\s,]+[\d.-]+[\s,]+(?<w>[\d.]+)[\s,]+(?<h>[\d.]+)\k<q>/u;
|
|
91
92
|
|
|
93
|
+
/** The SVG's viewBox aspect ratio (w/h), or null without a usable viewBox. */
|
|
94
|
+
const logoAspect = (svg: string): number | null => {
|
|
95
|
+
const box = svg.match(VIEW_BOX);
|
|
96
|
+
const w = Number(box?.groups?.w);
|
|
97
|
+
const h = Number(box?.groups?.h);
|
|
98
|
+
return w && h ? w / h : null;
|
|
99
|
+
};
|
|
100
|
+
|
|
92
101
|
// Render the configured logo as the brand mark. A `currentColor` logo carries
|
|
93
102
|
// no intrinsic color, so it is painted in the foreground to read on the light
|
|
94
103
|
// card, then handed to Takumi as a data URI sized from the SVG's aspect ratio.
|
|
95
104
|
const logoMark = (svg: string): Node => {
|
|
96
105
|
const painted = svg.replaceAll("currentColor", FOREGROUND);
|
|
97
|
-
const
|
|
98
|
-
const w = Number(box?.groups?.w);
|
|
99
|
-
const h = Number(box?.groups?.h);
|
|
106
|
+
const aspect = logoAspect(painted);
|
|
100
107
|
let height = MARK_HEIGHT;
|
|
101
|
-
let width =
|
|
108
|
+
let width = aspect ? MARK_HEIGHT * aspect : MARK_HEIGHT;
|
|
102
109
|
if (width > MARK_MAX_WIDTH) {
|
|
103
|
-
height =
|
|
110
|
+
height = aspect ? MARK_MAX_WIDTH / aspect : MARK_HEIGHT;
|
|
104
111
|
width = MARK_MAX_WIDTH;
|
|
105
112
|
}
|
|
106
113
|
return image({
|
|
@@ -152,19 +159,13 @@ export const renderOgImage = (options: OgCardOptions): Promise<Buffer> => {
|
|
|
152
159
|
const repo = options.repo?.trim();
|
|
153
160
|
const site = options.site?.trim();
|
|
154
161
|
|
|
162
|
+
// Logo only — no brand-name label beside it. A wordmark logo already spells
|
|
163
|
+
// the name, and rendering the site title next to it duplicated the brand
|
|
164
|
+
// ("Ultracite Ultracite"). Without a logo, the accent tile with the brand
|
|
165
|
+
// initial stands in.
|
|
155
166
|
const header = container({
|
|
156
|
-
children: [
|
|
157
|
-
|
|
158
|
-
brand
|
|
159
|
-
? text(brand, {
|
|
160
|
-
color: FOREGROUND,
|
|
161
|
-
fontSize: 30,
|
|
162
|
-
fontWeight: 500,
|
|
163
|
-
letterSpacing: "-0.01em",
|
|
164
|
-
})
|
|
165
|
-
: container({}),
|
|
166
|
-
],
|
|
167
|
-
style: { alignItems: "center", display: "flex", gap: 18 },
|
|
167
|
+
children: [logo ? logoMark(logo) : initialMark(accent, initial)],
|
|
168
|
+
style: { alignItems: "center", display: "flex" },
|
|
168
169
|
});
|
|
169
170
|
|
|
170
171
|
const body = container({
|