@usezanin/blog 0.1.0 → 0.2.0
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 +26 -0
- package/dist/BlogIndex.d.ts +9 -1
- package/dist/BlogIndex.d.ts.map +1 -1
- package/dist/BlogIndex.js +14 -6
- package/dist/BlogIndex.js.map +1 -1
- package/dist/BlogPost.d.ts.map +1 -1
- package/dist/BlogPost.js +6 -3
- package/dist/BlogPost.js.map +1 -1
- package/dist/components/Chart.js +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/data.d.ts +2 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +10 -0
- package/dist/data.js.map +1 -1
- package/dist/headless.d.ts +14 -0
- package/dist/headless.d.ts.map +1 -0
- package/dist/headless.js +20 -0
- package/dist/headless.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/theme.d.ts +12 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +48 -0
- package/dist/theme.js.map +1 -0
- package/package.json +3 -3
- package/styles.css +245 -172
package/README.md
CHANGED
|
@@ -57,6 +57,32 @@ import { createRevalidateHandler } from "@usezanin/blog";
|
|
|
57
57
|
export const POST = createRevalidateHandler();
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
## Theming — fully customizable
|
|
61
|
+
|
|
62
|
+
Blogs are themable end to end: colors, fonts, sizes, spacing, radius, content width, and index layout.
|
|
63
|
+
|
|
64
|
+
1. **Dashboard / agents (recommended)** — set the theme per site in the Zanin dashboard ("Customize theme") or let agents call the `update_site_theme` MCP tool. The SDK fetches it with the content and re-renders instantly via the revalidation webhook. No deploy.
|
|
65
|
+
2. **Host code overrides** — pass `theme` in the config (wins over the dashboard theme):
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const config = {
|
|
69
|
+
theme: {
|
|
70
|
+
accent: "#0a7d54",
|
|
71
|
+
fontHeading: "'Playfair Display', Georgia, serif", // load the font in your layout
|
|
72
|
+
fontBody: "Inter, sans-serif",
|
|
73
|
+
measure: "680px",
|
|
74
|
+
radius: "16px",
|
|
75
|
+
spacing: "relaxed", // compact | comfortable | relaxed
|
|
76
|
+
indexLayout: "grid", // list | grid
|
|
77
|
+
},
|
|
78
|
+
} satisfies ZaninBlogConfig;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
3. **Plain CSS** — every value is a `--zanin-*` CSS variable on `.zanin-blog`; override any of them (or restyle `.zanin-*` component classes) in your own stylesheet.
|
|
82
|
+
4. **Fully headless** — build your own layouts with the exported data helpers and pieces: `getBlogPosts()`, `getBlogPost(slug)`, `getBlogSite()` (includes the theme), `PostCard`, `renderMdx`, `builtinComponents`, `themeToStyle`.
|
|
83
|
+
|
|
84
|
+
Custom fonts: load them however you like (`next/font`, `<link>` tags) and reference the family name in `fontHeading` / `fontBody` / `fontMono`.
|
|
85
|
+
|
|
60
86
|
## What you get
|
|
61
87
|
|
|
62
88
|
- Server-rendered MDX with built-in components: `Callout`, `Figure`, `Chart` (bar/line/area/pie from inline data), `CTA`, `YouTube`, `Tweet`, `ComparisonTable`, `FAQ` (with FAQPage JSON-LD), styled code blocks
|
package/dist/BlogIndex.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
import type { Post } from "@usezanin/client";
|
|
1
2
|
import { type ZaninBlogConfig } from "./config.js";
|
|
3
|
+
/** One entry in the blog index; exported for fully custom index layouts. */
|
|
4
|
+
export declare function PostCard({ post, basePath }: {
|
|
5
|
+
post: Post;
|
|
6
|
+
basePath?: string;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
2
8
|
export interface BlogIndexProps {
|
|
3
9
|
config?: ZaninBlogConfig;
|
|
4
10
|
title?: string;
|
|
5
11
|
description?: string;
|
|
12
|
+
/** Overrides the themed index layout for this page only. */
|
|
13
|
+
layout?: "list" | "grid";
|
|
6
14
|
}
|
|
7
15
|
/** Server component: renders the list of published posts. */
|
|
8
|
-
export declare function BlogIndex({ config, title, description }: BlogIndexProps): Promise<import("react").JSX.Element>;
|
|
16
|
+
export declare function BlogIndex({ config, title, description, layout }: BlogIndexProps): Promise<import("react").JSX.Element>;
|
|
9
17
|
//# sourceMappingURL=BlogIndex.d.ts.map
|
package/dist/BlogIndex.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlogIndex.d.ts","sourceRoot":"","sources":["../src/BlogIndex.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BlogIndex.d.ts","sourceRoot":"","sources":["../src/BlogIndex.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAYlE,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAkB,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,+BAuBvF;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED,6DAA6D;AAC7D,wBAAsB,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,cAAc,wCA2BrF"}
|
package/dist/BlogIndex.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { resolveConfig } from "./config.js";
|
|
3
|
-
import { fetchPublishedPosts } from "./data.js";
|
|
3
|
+
import { fetchPublishedPosts, fetchSite } from "./data.js";
|
|
4
|
+
import { indexLayoutClass, mergeThemes, themeToStyle } from "./theme.js";
|
|
4
5
|
function formatDate(iso) {
|
|
5
6
|
return new Date(iso).toLocaleDateString("en-US", {
|
|
6
7
|
year: "numeric",
|
|
@@ -8,14 +9,21 @@ function formatDate(iso) {
|
|
|
8
9
|
day: "numeric",
|
|
9
10
|
});
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
+
/** One entry in the blog index; exported for fully custom index layouts. */
|
|
13
|
+
export function PostCard({ post, basePath = "/blog" }) {
|
|
12
14
|
const href = `${basePath}/${post.slug}`.replace(/\/{2,}/g, "/");
|
|
13
|
-
return (_jsx("article", { className: "zanin-index-item", children: _jsxs("a", { href: href, children: [_jsxs("div", { className: "zanin-index-meta", children: [_jsx("time", { dateTime: post.publishedAt ?? undefined, children: formatDate(post.publishedAt ?? post.createdAt) }), post.tags.slice(0, 3).map((tag) => (_jsx("span", { className: "zanin-tag", children: tag }, tag)))] }), _jsx("h2", { children: post.title }), post.description && _jsx("p", { children: post.description })] }) }));
|
|
15
|
+
return (_jsx("article", { className: "zanin-index-item", children: _jsxs("a", { href: href, children: [_jsxs("div", { className: "zanin-index-meta", children: [_jsx("time", { dateTime: post.publishedAt ?? undefined, children: formatDate(post.publishedAt ?? post.createdAt) }), post.tags.slice(0, 3).map((tag) => (_jsx("span", { className: "zanin-tag", children: tag }, tag)))] }), _jsx("h2", { children: post.title }), post.description && _jsx("p", { children: post.description }), _jsx("span", { className: "zanin-index-more", "aria-hidden": true, children: "Read more \u2192" })] }) }));
|
|
14
16
|
}
|
|
15
17
|
/** Server component: renders the list of published posts. */
|
|
16
|
-
export async function BlogIndex({ config, title, description }) {
|
|
18
|
+
export async function BlogIndex({ config, title, description, layout }) {
|
|
17
19
|
const resolved = resolveConfig(config);
|
|
18
|
-
const posts = await
|
|
19
|
-
|
|
20
|
+
const [posts, site] = await Promise.all([
|
|
21
|
+
fetchPublishedPosts(resolved),
|
|
22
|
+
fetchSite(resolved),
|
|
23
|
+
]);
|
|
24
|
+
const theme = mergeThemes(site?.theme, resolved.theme);
|
|
25
|
+
if (layout)
|
|
26
|
+
theme.indexLayout = layout;
|
|
27
|
+
return (_jsxs("div", { className: `zanin-blog zanin-index ${indexLayoutClass(theme)}`, style: themeToStyle(theme), children: [_jsxs("header", { className: "zanin-index-header", children: [_jsx("h1", { children: title ?? "Blog" }), description && _jsx("p", { children: description })] }), posts.length === 0 ? (_jsx("p", { className: "zanin-index-empty", children: "No posts yet." })) : (_jsx("div", { className: "zanin-index-list", children: posts.map((post) => (_jsx(PostCard, { post: post, basePath: resolved.basePath }, post.id))) }))] }));
|
|
20
28
|
}
|
|
21
29
|
//# sourceMappingURL=BlogIndex.js.map
|
package/dist/BlogIndex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlogIndex.js","sourceRoot":"","sources":["../src/BlogIndex.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"BlogIndex.js","sourceRoot":"","sources":["../src/BlogIndex.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEzE,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;QAC/C,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,GAAG,EAAE,SAAS;KACf,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,EAAqC;IACtF,MAAM,IAAI,GAAG,GAAG,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAChE,OAAO,CACL,kBAAS,SAAS,EAAC,kBAAkB,YACnC,aAAG,IAAI,EAAE,IAAI,aACX,eAAK,SAAS,EAAC,kBAAkB,aAC/B,eAAM,QAAQ,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS,YAC1C,UAAU,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,GAC1C,EACN,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAClC,eAAgB,SAAS,EAAC,WAAW,YAClC,GAAG,IADK,GAAG,CAEP,CACR,CAAC,IACE,EACN,uBAAK,IAAI,CAAC,KAAK,GAAM,EACpB,IAAI,CAAC,WAAW,IAAI,sBAAI,IAAI,CAAC,WAAW,GAAK,EAC9C,eAAM,SAAS,EAAC,kBAAkB,sDAE3B,IACL,GACI,CACX,CAAC;AACJ,CAAC;AAUD,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAkB;IACpF,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACtC,mBAAmB,CAAC,QAAQ,CAAC;QAC7B,SAAS,CAAC,QAAQ,CAAC;KACpB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,MAAM;QAAE,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;IAEvC,OAAO,CACL,eAAK,SAAS,EAAE,0BAA0B,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,aAC7F,kBAAQ,SAAS,EAAC,oBAAoB,aACpC,uBAAK,KAAK,IAAI,MAAM,GAAM,EACzB,WAAW,IAAI,sBAAI,WAAW,GAAK,IAC7B,EACR,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACpB,YAAG,SAAS,EAAC,mBAAmB,8BAAkB,CACnD,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAC,kBAAkB,YAC9B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,KAAC,QAAQ,IAAe,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAhD,IAAI,CAAC,EAAE,CAA6C,CACpE,CAAC,GACE,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
|
package/dist/BlogPost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlogPost.d.ts","sourceRoot":"","sources":["../src/BlogPost.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"BlogPost.d.ts","sourceRoot":"","sources":["../src/BlogPost.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAkBlE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,aAAa,wCA4DzE"}
|
package/dist/BlogPost.js
CHANGED
|
@@ -2,8 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { notFound } from "next/navigation";
|
|
3
3
|
import { resolveConfig } from "./config.js";
|
|
4
4
|
import { fetchCustomComponents } from "./custom-components.js";
|
|
5
|
-
import { fetchPublishedPost, postUrl } from "./data.js";
|
|
5
|
+
import { fetchPublishedPost, fetchSite, postUrl } from "./data.js";
|
|
6
6
|
import { renderMdx } from "./mdx.js";
|
|
7
|
+
import { mergeThemes, themeToStyle } from "./theme.js";
|
|
7
8
|
function formatDate(iso) {
|
|
8
9
|
return new Date(iso).toLocaleDateString("en-US", {
|
|
9
10
|
year: "numeric",
|
|
@@ -20,12 +21,14 @@ function readingTime(body) {
|
|
|
20
21
|
*/
|
|
21
22
|
export async function BlogPost({ slug, config, components }) {
|
|
22
23
|
const resolved = resolveConfig(config);
|
|
23
|
-
const [post, customComponents] = await Promise.all([
|
|
24
|
+
const [post, customComponents, site] = await Promise.all([
|
|
24
25
|
fetchPublishedPost(resolved, slug),
|
|
25
26
|
fetchCustomComponents(resolved),
|
|
27
|
+
fetchSite(resolved),
|
|
26
28
|
]);
|
|
27
29
|
if (!post)
|
|
28
30
|
notFound();
|
|
31
|
+
const theme = mergeThemes(site?.theme, resolved.theme);
|
|
29
32
|
// Precedence: built-ins < site custom components < host overrides.
|
|
30
33
|
const content = await renderMdx(post.body ?? "", {
|
|
31
34
|
...customComponents,
|
|
@@ -48,6 +51,6 @@ export async function BlogPost({ slug, config, components }) {
|
|
|
48
51
|
}
|
|
49
52
|
: {}),
|
|
50
53
|
};
|
|
51
|
-
return (_jsxs("article", { className: "zanin-blog zanin-post", children: [_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify(jsonLd) } }), _jsxs("header", { className: "zanin-post-header", children: [_jsxs("div", { className: "zanin-post-meta", children: [_jsx("time", { dateTime: post.publishedAt ?? undefined, children: formatDate(post.publishedAt ?? post.createdAt) }), _jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsxs("span", { children: [readingTime(post.body ?? ""), " min read"] }), post.tags.slice(0, 3).map((tag) => (_jsx("span", { className: "zanin-tag", children: tag }, tag)))] }), _jsx("h1", { children: post.title }), post.description && _jsx("p", { className: "zanin-post-lede", children: post.description })] }), _jsx("div", { className: "zanin-prose", children: content })] }));
|
|
54
|
+
return (_jsxs("article", { className: "zanin-blog zanin-post", style: themeToStyle(theme), children: [_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify(jsonLd) } }), _jsxs("header", { className: "zanin-post-header", children: [_jsxs("div", { className: "zanin-post-meta", children: [_jsx("time", { dateTime: post.publishedAt ?? undefined, children: formatDate(post.publishedAt ?? post.createdAt) }), _jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsxs("span", { children: [readingTime(post.body ?? ""), " min read"] }), post.tags.slice(0, 3).map((tag) => (_jsx("span", { className: "zanin-tag", children: tag }, tag)))] }), _jsx("h1", { children: post.title }), post.description && _jsx("p", { className: "zanin-post-lede", children: post.description })] }), _jsx("div", { className: "zanin-prose", children: content })] }));
|
|
52
55
|
}
|
|
53
56
|
//# sourceMappingURL=BlogPost.js.map
|
package/dist/BlogPost.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlogPost.js","sourceRoot":"","sources":["../src/BlogPost.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"BlogPost.js","sourceRoot":"","sources":["../src/BlogPost.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEvD,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;QAC/C,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,GAAG,EAAE,SAAS;KACf,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC;AACjE,CAAC;AASD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAiB;IACxE,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACvD,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC;QAClC,qBAAqB,CAAC,QAAQ,CAAC;QAC/B,SAAS,CAAC,QAAQ,CAAC;KACpB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI;QAAE,QAAQ,EAAE,CAAC;IAEtB,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEvD,mEAAmE;IACnE,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE;QAC/C,GAAG,gBAAgB;QACnB,GAAG,UAAU;KACd,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG;QACb,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,SAAS;QAClB,QAAQ,EAAE,IAAI,CAAC,KAAK;QACpB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;QAC1C,aAAa,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;QAC5C,YAAY,EAAE,IAAI,CAAC,SAAS;QAC5B,KAAK,EAAE,IAAI,CAAC,UAAU,IAAI,SAAS;QACnC,GAAG,CAAC,QAAQ,CAAC,OAAO;YAClB,CAAC,CAAC;gBACE,gBAAgB,EAAE;oBAChB,OAAO,EAAE,SAAS;oBAClB,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC;iBACpC;aACF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IAEF,OAAO,CACL,mBAAS,SAAS,EAAC,uBAAuB,EAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,aACnE,iBACE,IAAI,EAAC,qBAAqB,EAC1B,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,GAC3D,EACF,kBAAQ,SAAS,EAAC,mBAAmB,aACnC,eAAK,SAAS,EAAC,iBAAiB,aAC9B,eAAM,QAAQ,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS,YAC1C,UAAU,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,GAC1C,EACP,yDAA0B,EAC1B,2BAAO,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,iBAAiB,EACnD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAClC,eAAgB,SAAS,EAAC,WAAW,YAClC,GAAG,IADK,GAAG,CAEP,CACR,CAAC,IACE,EACN,uBAAK,IAAI,CAAC,KAAK,GAAM,EACpB,IAAI,CAAC,WAAW,IAAI,YAAG,SAAS,EAAC,iBAAiB,YAAE,IAAI,CAAC,WAAW,GAAK,IACnE,EACT,cAAK,SAAS,EAAC,aAAa,YAAE,OAAO,GAAO,IACpC,CACX,CAAC;AACJ,CAAC"}
|
package/dist/components/Chart.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Legend, Line, LineChart, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts";
|
|
4
4
|
const DEFAULT_COLORS = [
|
|
5
|
-
"var(--zanin-accent, #
|
|
5
|
+
"var(--zanin-accent, #005bd3)",
|
|
6
6
|
"#0ea5e9",
|
|
7
7
|
"#8b5cf6",
|
|
8
8
|
"#f59e0b",
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import type { ZaninTheme } from "@usezanin/client";
|
|
1
2
|
export interface ZaninBlogConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Theme overrides applied on top of the theme configured in the Zanin
|
|
5
|
+
* dashboard (colors, fonts, layout). Highest precedence.
|
|
6
|
+
*/
|
|
7
|
+
theme?: ZaninTheme;
|
|
2
8
|
/** Base URL of the Zanin CMS deployment. Falls back to ZANIN_BASE_URL. */
|
|
3
9
|
baseUrl?: string;
|
|
4
10
|
/** Site id from the Zanin dashboard. Falls back to ZANIN_SITE_ID. */
|
|
@@ -25,6 +31,7 @@ export interface ResolvedZaninBlogConfig {
|
|
|
25
31
|
siteName?: string;
|
|
26
32
|
revalidate: number | false;
|
|
27
33
|
revalidateSecret?: string;
|
|
34
|
+
theme?: ZaninTheme;
|
|
28
35
|
}
|
|
29
36
|
export declare function resolveConfig(config?: ZaninBlogConfig): ResolvedZaninBlogConfig;
|
|
30
37
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wIAAwI;IACxI,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5B,kHAAkH;IAClH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wIAAwI;IACxI,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5B,kHAAkH;IAClH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,MAAM,GAAE,eAAoB,GAAG,uBAAuB,CAuBnF"}
|
package/dist/config.js
CHANGED
|
@@ -18,6 +18,7 @@ export function resolveConfig(config = {}) {
|
|
|
18
18
|
siteName: config.siteName,
|
|
19
19
|
revalidate: config.revalidate ?? 300,
|
|
20
20
|
revalidateSecret: config.revalidateSecret ?? process.env.ZANIN_REVALIDATE_SECRET,
|
|
21
|
+
theme: config.theme,
|
|
21
22
|
};
|
|
22
23
|
}
|
|
23
24
|
function normalizeBasePath(path) {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAsCA,MAAM,UAAU,aAAa,CAAC,SAA0B,EAAE;IACxD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC7D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC1D,MAAM,MAAM,GACV,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAE3E,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACzF,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IACtF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,MAAM;QACN,MAAM;QACN,QAAQ,EAAE,iBAAiB,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC;QACvD,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC5E,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,GAAG;QACpC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB;QAChF,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IAC7D,OAAO,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;AAChD,CAAC"}
|
package/dist/data.d.ts
CHANGED
|
@@ -5,5 +5,7 @@ export declare const ZANIN_CACHE_TAG = "zanin-blog";
|
|
|
5
5
|
export declare function createClient(config: ResolvedZaninBlogConfig): ZaninClient;
|
|
6
6
|
export declare function fetchPublishedPosts(config: ResolvedZaninBlogConfig): Promise<Post[]>;
|
|
7
7
|
export declare function fetchPublishedPost(config: ResolvedZaninBlogConfig, slug: string): Promise<Post | null>;
|
|
8
|
+
/** The site record carries the dashboard-configured theme. */
|
|
9
|
+
export declare function fetchSite(config: ResolvedZaninBlogConfig): Promise<import("@usezanin/client").Site | null>;
|
|
8
10
|
export declare function postUrl(config: ResolvedZaninBlogConfig, slug: string): string;
|
|
9
11
|
//# sourceMappingURL=data.d.ts.map
|
package/dist/data.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,qFAAqF;AACrF,eAAO,MAAM,eAAe,eAAe,CAAC;AAY5C,wBAAgB,YAAY,CAAC,MAAM,EAAE,uBAAuB,GAAG,WAAW,CAMzE;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,IAAI,EAAE,CAAC,CAUjB;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,uBAAuB,EAC/B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAItB;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7E"}
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,qFAAqF;AACrF,eAAO,MAAM,eAAe,eAAe,CAAC;AAY5C,wBAAgB,YAAY,CAAC,MAAM,EAAE,uBAAuB,GAAG,WAAW,CAMzE;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,IAAI,EAAE,CAAC,CAUjB;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,uBAAuB,EAC/B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAItB;AAED,8DAA8D;AAC9D,wBAAsB,SAAS,CAAC,MAAM,EAAE,uBAAuB,mDAO9D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7E"}
|
package/dist/data.js
CHANGED
|
@@ -29,6 +29,16 @@ export async function fetchPublishedPost(config, slug) {
|
|
|
29
29
|
status: "published",
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
/** The site record carries the dashboard-configured theme. */
|
|
33
|
+
export async function fetchSite(config) {
|
|
34
|
+
try {
|
|
35
|
+
return await createClient(config).getSite(config.siteId);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.error("[@usezanin/blog] Failed to fetch site (theme falls back to defaults):", err);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
32
42
|
export function postUrl(config, slug) {
|
|
33
43
|
const path = `${config.basePath}/${slug}`.replace(/\/{2,}/g, "/");
|
|
34
44
|
return config.siteUrl ? `${config.siteUrl}${path}` : path;
|
package/dist/data.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAa,MAAM,kBAAkB,CAAC;AAG1D,qFAAqF;AACrF,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAE5C,SAAS,WAAW,CAAC,MAA+B;IAClD,yEAAyE;IACzE,qEAAqE;IACrE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACrB,KAAK,CAAC,KAAK,EAAE;QACX,GAAG,IAAI;QACP,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE;KAClD,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAA+B;IAC1D,OAAO,IAAI,WAAW,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC;KAC3B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAA+B;IAE/B,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE;QAChE,MAAM,EAAE,WAAW;QACnB,KAAK,EAAE,GAAG;KACX,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CACpB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;QAChD,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACnD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAA+B,EAC/B,IAAY;IAEZ,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE;QAC7D,MAAM,EAAE,WAAW;KACpB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,MAA+B,EAAE,IAAY;IACnE,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC"}
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAa,MAAM,kBAAkB,CAAC;AAG1D,qFAAqF;AACrF,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAE5C,SAAS,WAAW,CAAC,MAA+B;IAClD,yEAAyE;IACzE,qEAAqE;IACrE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACrB,KAAK,CAAC,KAAK,EAAE;QACX,GAAG,IAAI;QACP,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE;KAClD,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAA+B;IAC1D,OAAO,IAAI,WAAW,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC;KAC3B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAA+B;IAE/B,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE;QAChE,MAAM,EAAE,WAAW;QACnB,KAAK,EAAE,GAAG;KACX,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CACpB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;QAChD,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACnD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAA+B,EAC/B,IAAY;IAEZ,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE;QAC7D,MAAM,EAAE,WAAW;KACpB,CAAC,CAAC;AACL,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAA+B;IAC7D,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,uEAAuE,EAAE,GAAG,CAAC,CAAC;QAC5F,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,MAA+B,EAAE,IAAY;IACnE,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Post, Site } from "@usezanin/client";
|
|
2
|
+
import { type ZaninBlogConfig } from "./config.js";
|
|
3
|
+
/**
|
|
4
|
+
* Headless data helpers for fully custom blog UIs: fetch the content with
|
|
5
|
+
* these, render however you like (renderMdx + builtinComponents are exported
|
|
6
|
+
* too). All requests share the SDK's ISR caching and revalidation webhook.
|
|
7
|
+
*/
|
|
8
|
+
/** All published posts (sorted newest first, bodies excluded). */
|
|
9
|
+
export declare function getBlogPosts(config?: ZaninBlogConfig): Promise<Post[]>;
|
|
10
|
+
/** One published post by slug, including its MDX body; null when not found. */
|
|
11
|
+
export declare function getBlogPost(slug: string, config?: ZaninBlogConfig): Promise<Post | null>;
|
|
12
|
+
/** The site record, including the dashboard-configured theme. */
|
|
13
|
+
export declare function getBlogSite(config?: ZaninBlogConfig): Promise<Site | null>;
|
|
14
|
+
//# sourceMappingURL=headless.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless.d.ts","sourceRoot":"","sources":["../src/headless.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAGlE;;;;GAIG;AAEH,kEAAkE;AAClE,wBAAsB,YAAY,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAE5E;AAED,+EAA+E;AAC/E,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAEtB;AAED,iEAAiE;AACjE,wBAAsB,WAAW,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAEhF"}
|
package/dist/headless.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { resolveConfig } from "./config.js";
|
|
2
|
+
import { fetchPublishedPost, fetchPublishedPosts, fetchSite } from "./data.js";
|
|
3
|
+
/**
|
|
4
|
+
* Headless data helpers for fully custom blog UIs: fetch the content with
|
|
5
|
+
* these, render however you like (renderMdx + builtinComponents are exported
|
|
6
|
+
* too). All requests share the SDK's ISR caching and revalidation webhook.
|
|
7
|
+
*/
|
|
8
|
+
/** All published posts (sorted newest first, bodies excluded). */
|
|
9
|
+
export async function getBlogPosts(config) {
|
|
10
|
+
return fetchPublishedPosts(resolveConfig(config));
|
|
11
|
+
}
|
|
12
|
+
/** One published post by slug, including its MDX body; null when not found. */
|
|
13
|
+
export async function getBlogPost(slug, config) {
|
|
14
|
+
return fetchPublishedPost(resolveConfig(config), slug);
|
|
15
|
+
}
|
|
16
|
+
/** The site record, including the dashboard-configured theme. */
|
|
17
|
+
export async function getBlogSite(config) {
|
|
18
|
+
return fetchSite(resolveConfig(config));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=headless.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless.js","sourceRoot":"","sources":["../src/headless.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE/E;;;;GAIG;AAEH,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAwB;IACzD,OAAO,mBAAmB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,MAAwB;IAExB,OAAO,kBAAkB,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AACzD,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAwB;IACxD,OAAO,SAAS,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AAC1C,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export { BlogIndex, type BlogIndexProps } from "./BlogIndex.js";
|
|
1
|
+
export { BlogIndex, PostCard, type BlogIndexProps } from "./BlogIndex.js";
|
|
2
2
|
export { BlogPost, type BlogPostProps } from "./BlogPost.js";
|
|
3
3
|
export { resolveConfig, type ZaninBlogConfig } from "./config.js";
|
|
4
4
|
export { ZANIN_CACHE_TAG } from "./data.js";
|
|
5
|
+
export { getBlogPost, getBlogPosts, getBlogSite } from "./headless.js";
|
|
6
|
+
export { indexLayoutClass, mergeThemes, themeToStyle, type ZaninTheme } from "./theme.js";
|
|
5
7
|
export { createRevalidateHandler, createRssHandler, createSitemapHandler, } from "./handlers.js";
|
|
6
8
|
export { fetchCustomComponents } from "./custom-components.js";
|
|
7
9
|
export { builtinComponents, renderMdx } from "./mdx.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export { BlogIndex } from "./BlogIndex.js";
|
|
1
|
+
export { BlogIndex, PostCard } from "./BlogIndex.js";
|
|
2
2
|
export { BlogPost } from "./BlogPost.js";
|
|
3
3
|
export { resolveConfig } from "./config.js";
|
|
4
4
|
export { ZANIN_CACHE_TAG } from "./data.js";
|
|
5
|
+
export { getBlogPost, getBlogPosts, getBlogSite } from "./headless.js";
|
|
6
|
+
export { indexLayoutClass, mergeThemes, themeToStyle } from "./theme.js";
|
|
5
7
|
export { createRevalidateHandler, createRssHandler, createSitemapHandler, } from "./handlers.js";
|
|
6
8
|
export { fetchCustomComponents } from "./custom-components.js";
|
|
7
9
|
export { builtinComponents, renderMdx } from "./mdx.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAuB,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAsB,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAC;AAC1F,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAmB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,GAAG,EAAgB,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ZaninTheme } from "@usezanin/client";
|
|
2
|
+
export type { ZaninTheme };
|
|
3
|
+
/** Host theme wins over the CMS theme; both win over stylesheet defaults. */
|
|
4
|
+
export declare function mergeThemes(cmsTheme: ZaninTheme | null | undefined, hostTheme: ZaninTheme | undefined): ZaninTheme;
|
|
5
|
+
/**
|
|
6
|
+
* Converts a theme to inline CSS-variable overrides for the .zanin-blog
|
|
7
|
+
* wrapper. Every value lands in a CSS custom property (never a property),
|
|
8
|
+
* so arbitrary values cannot escape the declaration.
|
|
9
|
+
*/
|
|
10
|
+
export declare function themeToStyle(theme: ZaninTheme): Record<string, string>;
|
|
11
|
+
export declare function indexLayoutClass(theme: ZaninTheme): string;
|
|
12
|
+
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,YAAY,EAAE,UAAU,EAAE,CAAC;AA0B3B,6EAA6E;AAC7E,wBAAgB,WAAW,CACzB,QAAQ,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACvC,SAAS,EAAE,UAAU,GAAG,SAAS,GAChC,UAAU,CAEZ;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYtE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE1D"}
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Direct theme-field → CSS-variable mappings. */
|
|
2
|
+
const VAR_MAP = {
|
|
3
|
+
"--zanin-accent": "accent",
|
|
4
|
+
"--zanin-canvas": "background",
|
|
5
|
+
"--zanin-surface": "surface",
|
|
6
|
+
"--zanin-ink": "text",
|
|
7
|
+
"--zanin-ink-muted": "textMuted",
|
|
8
|
+
"--zanin-ink-faint": "textFaint",
|
|
9
|
+
"--zanin-hairline": "border",
|
|
10
|
+
"--zanin-font-body": "fontBody",
|
|
11
|
+
"--zanin-font-heading": "fontHeading",
|
|
12
|
+
"--zanin-font-mono": "fontMono",
|
|
13
|
+
"--zanin-base-size": "baseFontSize",
|
|
14
|
+
"--zanin-heading-weight": "headingWeight",
|
|
15
|
+
"--zanin-measure": "measure",
|
|
16
|
+
"--zanin-radius": "radius",
|
|
17
|
+
};
|
|
18
|
+
const SPACING_SCALE = {
|
|
19
|
+
compact: "0.8",
|
|
20
|
+
comfortable: "1",
|
|
21
|
+
relaxed: "1.3",
|
|
22
|
+
};
|
|
23
|
+
/** Host theme wins over the CMS theme; both win over stylesheet defaults. */
|
|
24
|
+
export function mergeThemes(cmsTheme, hostTheme) {
|
|
25
|
+
return { ...(cmsTheme ?? {}), ...(hostTheme ?? {}) };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Converts a theme to inline CSS-variable overrides for the .zanin-blog
|
|
29
|
+
* wrapper. Every value lands in a CSS custom property (never a property),
|
|
30
|
+
* so arbitrary values cannot escape the declaration.
|
|
31
|
+
*/
|
|
32
|
+
export function themeToStyle(theme) {
|
|
33
|
+
const style = {};
|
|
34
|
+
for (const [cssVar, field] of Object.entries(VAR_MAP)) {
|
|
35
|
+
const value = theme[field];
|
|
36
|
+
if (typeof value === "string" && value.trim()) {
|
|
37
|
+
style[cssVar] = value.trim().replace(/[{};]/g, "");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (theme.spacing) {
|
|
41
|
+
style["--zanin-space"] = SPACING_SCALE[theme.spacing];
|
|
42
|
+
}
|
|
43
|
+
return style;
|
|
44
|
+
}
|
|
45
|
+
export function indexLayoutClass(theme) {
|
|
46
|
+
return theme.indexLayout === "grid" ? "zanin-index--grid" : "zanin-index--list";
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAIA,kDAAkD;AAClD,MAAM,OAAO,GAAqC;IAChD,gBAAgB,EAAE,QAAQ;IAC1B,gBAAgB,EAAE,YAAY;IAC9B,iBAAiB,EAAE,SAAS;IAC5B,aAAa,EAAE,MAAM;IACrB,mBAAmB,EAAE,WAAW;IAChC,mBAAmB,EAAE,WAAW;IAChC,kBAAkB,EAAE,QAAQ;IAC5B,mBAAmB,EAAE,UAAU;IAC/B,sBAAsB,EAAE,aAAa;IACrC,mBAAmB,EAAE,UAAU;IAC/B,mBAAmB,EAAE,cAAc;IACnC,wBAAwB,EAAE,eAAe;IACzC,iBAAiB,EAAE,SAAS;IAC5B,gBAAgB,EAAE,QAAQ;CAC3B,CAAC;AAEF,MAAM,aAAa,GAAuD;IACxE,OAAO,EAAE,KAAK;IACd,WAAW,EAAE,GAAG;IAChB,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CACzB,QAAuC,EACvC,SAAiC;IAEjC,OAAO,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9C,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,KAAK,CAAC,eAAe,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,OAAO,KAAK,CAAC,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CAAC;AAClF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usezanin/blog",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "React SDK for rendering Zanin blogs in Next.js sites
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "React SDK for rendering Zanin blogs in Next.js sites \u2014 index/post components, built-in MDX components, SEO, RSS and sitemap",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@mdx-js/mdx": "^3.1.0",
|
|
44
|
-
"@usezanin/client": "^0.
|
|
44
|
+
"@usezanin/client": "^0.2.0",
|
|
45
45
|
"recharts": "^2.15.0",
|
|
46
46
|
"remark-gfm": "^4.0.0"
|
|
47
47
|
},
|
package/styles.css
CHANGED
|
@@ -1,33 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @usezanin/blog — themable reading styles.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Design language matches the Zanin admin: clean neutral surfaces, hairline
|
|
5
|
+
* borders, subtle shadows, one accent color. Every value routes through a
|
|
6
|
+
* --zanin-* CSS variable; override them via the site theme in the Zanin
|
|
7
|
+
* dashboard, the SDK `theme` config, or plain CSS.
|
|
8
8
|
*/
|
|
9
9
|
.zanin-blog {
|
|
10
|
-
--zanin-accent: #
|
|
11
|
-
--zanin-
|
|
12
|
-
--zanin-
|
|
13
|
-
--zanin-
|
|
14
|
-
--zanin-ink: #
|
|
15
|
-
--zanin-ink-
|
|
16
|
-
--zanin-
|
|
17
|
-
--zanin-
|
|
18
|
-
--zanin-font-
|
|
19
|
-
--zanin-font-serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
|
|
10
|
+
--zanin-accent: #005bd3;
|
|
11
|
+
--zanin-canvas: #ffffff;
|
|
12
|
+
--zanin-surface: #fafafa;
|
|
13
|
+
--zanin-ink: #1a1a1a;
|
|
14
|
+
--zanin-ink-muted: #616161;
|
|
15
|
+
--zanin-ink-faint: #8a8a8a;
|
|
16
|
+
--zanin-hairline: #e3e3e3;
|
|
17
|
+
--zanin-font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
18
|
+
--zanin-font-heading: var(--zanin-font-body);
|
|
20
19
|
--zanin-font-mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace;
|
|
20
|
+
--zanin-base-size: 16.5px;
|
|
21
|
+
--zanin-heading-weight: 650;
|
|
21
22
|
--zanin-measure: 720px;
|
|
22
|
-
--zanin-radius
|
|
23
|
+
--zanin-radius: 12px;
|
|
24
|
+
/* Vertical rhythm multiplier (theme spacing: compact 0.8 / relaxed 1.3) */
|
|
25
|
+
--zanin-space: 1;
|
|
26
|
+
|
|
27
|
+
/* Derived */
|
|
28
|
+
--zanin-accent-strong: color-mix(in srgb, var(--zanin-accent) 82%, var(--zanin-ink));
|
|
29
|
+
--zanin-shadow: 0 1px 2px color-mix(in srgb, var(--zanin-ink) 7%, transparent);
|
|
23
30
|
|
|
24
31
|
margin: 0 auto;
|
|
25
32
|
max-width: var(--zanin-measure);
|
|
26
|
-
padding: 48px 24px 96px;
|
|
33
|
+
padding: calc(48px * var(--zanin-space)) 24px calc(96px * var(--zanin-space));
|
|
34
|
+
background: var(--zanin-canvas);
|
|
27
35
|
color: var(--zanin-ink);
|
|
28
|
-
font-family: var(--zanin-font-
|
|
29
|
-
font-size:
|
|
30
|
-
line-height: 1.
|
|
36
|
+
font-family: var(--zanin-font-body);
|
|
37
|
+
font-size: var(--zanin-base-size);
|
|
38
|
+
line-height: 1.65;
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
.zanin-blog a {
|
|
@@ -35,119 +43,164 @@
|
|
|
35
43
|
text-decoration: none;
|
|
36
44
|
}
|
|
37
45
|
.zanin-blog a:hover {
|
|
38
|
-
color: var(--zanin-accent-
|
|
46
|
+
color: var(--zanin-accent-strong);
|
|
47
|
+
text-decoration: underline;
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
.zanin-tag {
|
|
42
51
|
display: inline-block;
|
|
43
|
-
border
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
font-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
border: 1px solid var(--zanin-hairline);
|
|
53
|
+
border-radius: calc(var(--zanin-radius) / 1.5);
|
|
54
|
+
background: var(--zanin-surface);
|
|
55
|
+
color: var(--zanin-ink-muted);
|
|
56
|
+
font-size: 0.72em;
|
|
57
|
+
font-weight: 550;
|
|
58
|
+
letter-spacing: 0.01em;
|
|
59
|
+
padding: 2px 9px;
|
|
50
60
|
}
|
|
51
61
|
|
|
52
62
|
/* ---- Index ---------------------------------------------------------- */
|
|
53
63
|
|
|
54
64
|
.zanin-index-header {
|
|
55
|
-
margin-bottom:
|
|
65
|
+
margin-bottom: calc(40px * var(--zanin-space));
|
|
56
66
|
}
|
|
57
67
|
.zanin-index-header h1 {
|
|
58
|
-
font-family: var(--zanin-font-
|
|
59
|
-
font-size:
|
|
60
|
-
font-weight:
|
|
61
|
-
letter-spacing: -0.
|
|
62
|
-
line-height: 1.
|
|
68
|
+
font-family: var(--zanin-font-heading);
|
|
69
|
+
font-size: 2.5em;
|
|
70
|
+
font-weight: var(--zanin-heading-weight);
|
|
71
|
+
letter-spacing: -0.02em;
|
|
72
|
+
line-height: 1.12;
|
|
63
73
|
margin: 0 0 8px;
|
|
64
74
|
text-wrap: balance;
|
|
65
75
|
}
|
|
66
76
|
.zanin-index-header p {
|
|
67
77
|
color: var(--zanin-ink-muted);
|
|
68
|
-
font-size:
|
|
78
|
+
font-size: 1.06em;
|
|
69
79
|
margin: 0;
|
|
70
80
|
max-width: 52ch;
|
|
71
81
|
}
|
|
72
82
|
|
|
73
|
-
.zanin-index-list {
|
|
74
|
-
display: flex;
|
|
75
|
-
flex-direction: column;
|
|
76
|
-
}
|
|
77
|
-
.zanin-index-item {
|
|
78
|
-
border-top: 1px solid var(--zanin-hairline);
|
|
79
|
-
}
|
|
80
|
-
.zanin-index-item:last-child {
|
|
81
|
-
border-bottom: 1px solid var(--zanin-hairline);
|
|
82
|
-
}
|
|
83
83
|
.zanin-index-item > a {
|
|
84
84
|
color: inherit;
|
|
85
85
|
display: block;
|
|
86
|
-
|
|
87
|
-
transition: opacity 0.15s ease;
|
|
88
|
-
}
|
|
89
|
-
.zanin-index-item > a:hover {
|
|
90
|
-
color: inherit;
|
|
91
|
-
opacity: 0.72;
|
|
86
|
+
text-decoration: none;
|
|
92
87
|
}
|
|
93
88
|
.zanin-index-item h2 {
|
|
94
|
-
font-family: var(--zanin-font-
|
|
95
|
-
font-size:
|
|
96
|
-
font-weight:
|
|
97
|
-
letter-spacing: -0.
|
|
98
|
-
line-height: 1.
|
|
89
|
+
font-family: var(--zanin-font-heading);
|
|
90
|
+
font-size: 1.45em;
|
|
91
|
+
font-weight: var(--zanin-heading-weight);
|
|
92
|
+
letter-spacing: -0.012em;
|
|
93
|
+
line-height: 1.28;
|
|
99
94
|
margin: 0 0 6px;
|
|
100
95
|
text-wrap: balance;
|
|
101
96
|
}
|
|
97
|
+
.zanin-index-item > a:hover h2 {
|
|
98
|
+
color: var(--zanin-accent);
|
|
99
|
+
}
|
|
100
|
+
.zanin-index-item > a:hover {
|
|
101
|
+
text-decoration: none;
|
|
102
|
+
color: inherit;
|
|
103
|
+
}
|
|
102
104
|
.zanin-index-item p {
|
|
103
105
|
color: var(--zanin-ink-muted);
|
|
106
|
+
font-size: 0.94em;
|
|
104
107
|
margin: 0;
|
|
105
|
-
max-width:
|
|
108
|
+
max-width: 66ch;
|
|
106
109
|
}
|
|
107
110
|
.zanin-index-meta {
|
|
108
111
|
align-items: center;
|
|
109
112
|
color: var(--zanin-ink-faint);
|
|
110
113
|
display: flex;
|
|
111
|
-
|
|
112
|
-
font-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
flex-wrap: wrap;
|
|
115
|
+
font-size: 0.78em;
|
|
116
|
+
font-weight: 500;
|
|
117
|
+
gap: 8px;
|
|
115
118
|
margin-bottom: 10px;
|
|
116
|
-
|
|
119
|
+
}
|
|
120
|
+
.zanin-index-more {
|
|
121
|
+
color: var(--zanin-accent);
|
|
122
|
+
display: inline-block;
|
|
123
|
+
font-size: 0.85em;
|
|
124
|
+
font-weight: 550;
|
|
125
|
+
margin-top: 12px;
|
|
117
126
|
}
|
|
118
127
|
.zanin-index-empty {
|
|
119
128
|
color: var(--zanin-ink-faint);
|
|
120
129
|
}
|
|
121
130
|
|
|
131
|
+
/* List layout (default): divided rows */
|
|
132
|
+
.zanin-index--list .zanin-index-list {
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-direction: column;
|
|
135
|
+
}
|
|
136
|
+
.zanin-index--list .zanin-index-item {
|
|
137
|
+
border-top: 1px solid var(--zanin-hairline);
|
|
138
|
+
}
|
|
139
|
+
.zanin-index--list .zanin-index-item:last-child {
|
|
140
|
+
border-bottom: 1px solid var(--zanin-hairline);
|
|
141
|
+
}
|
|
142
|
+
.zanin-index--list .zanin-index-item > a {
|
|
143
|
+
padding: calc(26px * var(--zanin-space)) 2px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Grid layout: cards */
|
|
147
|
+
.zanin-index--grid {
|
|
148
|
+
max-width: calc(var(--zanin-measure) * 1.5);
|
|
149
|
+
}
|
|
150
|
+
.zanin-index--grid .zanin-index-list {
|
|
151
|
+
display: grid;
|
|
152
|
+
gap: calc(20px * var(--zanin-space));
|
|
153
|
+
grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
|
|
154
|
+
}
|
|
155
|
+
.zanin-index--grid .zanin-index-item {
|
|
156
|
+
background: var(--zanin-surface);
|
|
157
|
+
border: 1px solid var(--zanin-hairline);
|
|
158
|
+
border-radius: var(--zanin-radius);
|
|
159
|
+
box-shadow: var(--zanin-shadow);
|
|
160
|
+
transition: box-shadow 0.15s ease, transform 0.15s ease;
|
|
161
|
+
}
|
|
162
|
+
.zanin-index--grid .zanin-index-item:hover {
|
|
163
|
+
box-shadow: 0 4px 14px color-mix(in srgb, var(--zanin-ink) 10%, transparent);
|
|
164
|
+
transform: translateY(-1px);
|
|
165
|
+
}
|
|
166
|
+
.zanin-index--grid .zanin-index-item > a {
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
height: 100%;
|
|
170
|
+
padding: calc(22px * var(--zanin-space));
|
|
171
|
+
}
|
|
172
|
+
.zanin-index--grid .zanin-index-more {
|
|
173
|
+
margin-top: auto;
|
|
174
|
+
padding-top: 14px;
|
|
175
|
+
}
|
|
176
|
+
|
|
122
177
|
/* ---- Post header ----------------------------------------------------- */
|
|
123
178
|
|
|
124
179
|
.zanin-post-header {
|
|
125
|
-
margin-bottom:
|
|
180
|
+
margin-bottom: calc(40px * var(--zanin-space));
|
|
126
181
|
}
|
|
127
182
|
.zanin-post-meta {
|
|
128
183
|
align-items: center;
|
|
129
184
|
color: var(--zanin-ink-faint);
|
|
130
185
|
display: flex;
|
|
131
186
|
flex-wrap: wrap;
|
|
132
|
-
font-size:
|
|
133
|
-
font-weight:
|
|
134
|
-
gap:
|
|
135
|
-
|
|
136
|
-
margin-bottom: 16px;
|
|
137
|
-
text-transform: uppercase;
|
|
187
|
+
font-size: 0.8em;
|
|
188
|
+
font-weight: 500;
|
|
189
|
+
gap: 8px;
|
|
190
|
+
margin-bottom: 14px;
|
|
138
191
|
}
|
|
139
192
|
.zanin-post-header h1 {
|
|
140
|
-
font-family: var(--zanin-font-
|
|
141
|
-
font-size:
|
|
142
|
-
font-weight:
|
|
143
|
-
letter-spacing: -0.
|
|
193
|
+
font-family: var(--zanin-font-heading);
|
|
194
|
+
font-size: 2.5em;
|
|
195
|
+
font-weight: var(--zanin-heading-weight);
|
|
196
|
+
letter-spacing: -0.02em;
|
|
144
197
|
line-height: 1.12;
|
|
145
|
-
margin: 0 0
|
|
198
|
+
margin: 0 0 12px;
|
|
146
199
|
text-wrap: balance;
|
|
147
200
|
}
|
|
148
201
|
.zanin-post-lede {
|
|
149
202
|
color: var(--zanin-ink-muted);
|
|
150
|
-
font-size:
|
|
203
|
+
font-size: 1.12em;
|
|
151
204
|
line-height: 1.55;
|
|
152
205
|
margin: 0;
|
|
153
206
|
text-wrap: pretty;
|
|
@@ -156,92 +209,90 @@
|
|
|
156
209
|
/* ---- Prose ----------------------------------------------------------- */
|
|
157
210
|
|
|
158
211
|
.zanin-prose {
|
|
159
|
-
|
|
160
|
-
line-height: 1.65;
|
|
212
|
+
line-height: 1.68;
|
|
161
213
|
}
|
|
162
214
|
.zanin-prose > * + * {
|
|
163
|
-
margin-top: 1.
|
|
215
|
+
margin-top: calc(1.1em * var(--zanin-space));
|
|
164
216
|
}
|
|
165
217
|
.zanin-prose p {
|
|
166
218
|
margin: 0;
|
|
167
219
|
text-wrap: pretty;
|
|
168
220
|
}
|
|
169
221
|
.zanin-prose h2 {
|
|
170
|
-
font-family: var(--zanin-font-
|
|
171
|
-
font-size:
|
|
172
|
-
font-weight:
|
|
173
|
-
letter-spacing: -0.
|
|
222
|
+
font-family: var(--zanin-font-heading);
|
|
223
|
+
font-size: 1.6em;
|
|
224
|
+
font-weight: var(--zanin-heading-weight);
|
|
225
|
+
letter-spacing: -0.015em;
|
|
174
226
|
line-height: 1.25;
|
|
175
|
-
margin-top:
|
|
176
|
-
text-wrap: balance;
|
|
227
|
+
margin-top: calc(1.9em * var(--zanin-space));
|
|
177
228
|
}
|
|
178
229
|
.zanin-prose h3 {
|
|
179
|
-
font-
|
|
180
|
-
font-
|
|
230
|
+
font-family: var(--zanin-font-heading);
|
|
231
|
+
font-size: 1.2em;
|
|
232
|
+
font-weight: var(--zanin-heading-weight);
|
|
181
233
|
line-height: 1.3;
|
|
182
|
-
margin-top: 1.
|
|
234
|
+
margin-top: calc(1.7em * var(--zanin-space));
|
|
183
235
|
}
|
|
184
236
|
.zanin-prose ul,
|
|
185
237
|
.zanin-prose ol {
|
|
186
238
|
padding-left: 1.4em;
|
|
187
239
|
}
|
|
188
240
|
.zanin-prose li + li {
|
|
189
|
-
margin-top: 0.4em;
|
|
241
|
+
margin-top: calc(0.4em * var(--zanin-space));
|
|
190
242
|
}
|
|
191
243
|
.zanin-prose blockquote {
|
|
192
244
|
border-left: 3px solid var(--zanin-accent);
|
|
193
245
|
color: var(--zanin-ink-muted);
|
|
194
|
-
font-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
margin: 1.6em 0;
|
|
198
|
-
padding: 0.2em 0 0.2em 1.2em;
|
|
246
|
+
font-size: 1.05em;
|
|
247
|
+
margin: calc(1.5em * var(--zanin-space)) 0;
|
|
248
|
+
padding: 0.15em 0 0.15em 1.2em;
|
|
199
249
|
}
|
|
200
250
|
.zanin-prose code {
|
|
201
|
-
background:
|
|
251
|
+
background: var(--zanin-surface);
|
|
252
|
+
border: 1px solid var(--zanin-hairline);
|
|
202
253
|
border-radius: 6px;
|
|
203
254
|
font-family: var(--zanin-font-mono);
|
|
204
|
-
font-size: 0.
|
|
205
|
-
padding: 0.
|
|
255
|
+
font-size: 0.86em;
|
|
256
|
+
padding: 0.1em 0.35em;
|
|
206
257
|
}
|
|
207
258
|
.zanin-prose img {
|
|
208
|
-
border
|
|
259
|
+
border: 1px solid var(--zanin-hairline);
|
|
260
|
+
border-radius: var(--zanin-radius);
|
|
209
261
|
height: auto;
|
|
210
262
|
max-width: 100%;
|
|
211
263
|
}
|
|
212
264
|
.zanin-prose hr {
|
|
213
265
|
border: none;
|
|
214
266
|
border-top: 1px solid var(--zanin-hairline);
|
|
215
|
-
margin: 2.
|
|
267
|
+
margin: calc(2.4em * var(--zanin-space)) 0;
|
|
216
268
|
}
|
|
217
269
|
.zanin-prose table {
|
|
218
270
|
border-collapse: collapse;
|
|
219
|
-
font-size:
|
|
271
|
+
font-size: 0.9em;
|
|
220
272
|
width: 100%;
|
|
221
273
|
}
|
|
222
274
|
.zanin-prose th,
|
|
223
275
|
.zanin-prose td {
|
|
224
276
|
border-bottom: 1px solid var(--zanin-hairline);
|
|
225
|
-
padding:
|
|
277
|
+
padding: 9px 12px;
|
|
226
278
|
text-align: left;
|
|
227
279
|
}
|
|
228
280
|
.zanin-prose th {
|
|
229
|
-
color: var(--zanin-ink-
|
|
230
|
-
font-size:
|
|
231
|
-
font-weight:
|
|
232
|
-
letter-spacing: 0.09em;
|
|
233
|
-
text-transform: uppercase;
|
|
281
|
+
color: var(--zanin-ink-muted);
|
|
282
|
+
font-size: 0.82em;
|
|
283
|
+
font-weight: 600;
|
|
234
284
|
}
|
|
235
285
|
|
|
236
286
|
/* ---- Built-in components --------------------------------------------- */
|
|
237
287
|
|
|
238
288
|
.zanin-callout {
|
|
239
289
|
background: var(--zanin-surface);
|
|
240
|
-
border
|
|
241
|
-
|
|
290
|
+
border: 1px solid var(--zanin-hairline);
|
|
291
|
+
border-radius: var(--zanin-radius);
|
|
292
|
+
box-shadow: var(--zanin-shadow);
|
|
242
293
|
display: flex;
|
|
243
|
-
gap:
|
|
244
|
-
padding: 18px
|
|
294
|
+
gap: 12px;
|
|
295
|
+
padding: calc(16px * var(--zanin-space)) 18px;
|
|
245
296
|
}
|
|
246
297
|
.zanin-callout-icon {
|
|
247
298
|
align-items: center;
|
|
@@ -250,23 +301,23 @@
|
|
|
250
301
|
color: var(--zanin-accent);
|
|
251
302
|
display: flex;
|
|
252
303
|
flex-shrink: 0;
|
|
253
|
-
font-size:
|
|
304
|
+
font-size: 0.78em;
|
|
254
305
|
font-weight: 700;
|
|
255
|
-
height:
|
|
306
|
+
height: 24px;
|
|
256
307
|
justify-content: center;
|
|
257
308
|
margin-top: 2px;
|
|
258
|
-
width:
|
|
309
|
+
width: 24px;
|
|
259
310
|
}
|
|
260
311
|
.zanin-callout-warning .zanin-callout-icon {
|
|
261
|
-
background:
|
|
262
|
-
color: #
|
|
312
|
+
background: #ffef9d;
|
|
313
|
+
color: #4f4700;
|
|
263
314
|
}
|
|
264
315
|
.zanin-callout-success .zanin-callout-icon {
|
|
265
|
-
background:
|
|
266
|
-
color: #
|
|
316
|
+
background: #cdfee1;
|
|
317
|
+
color: #0c5132;
|
|
267
318
|
}
|
|
268
319
|
.zanin-callout-body {
|
|
269
|
-
font-size:
|
|
320
|
+
font-size: 0.94em;
|
|
270
321
|
}
|
|
271
322
|
.zanin-callout-body > * + * {
|
|
272
323
|
margin-top: 0.5em;
|
|
@@ -282,31 +333,31 @@
|
|
|
282
333
|
margin: 0;
|
|
283
334
|
}
|
|
284
335
|
.zanin-figure img {
|
|
285
|
-
border
|
|
336
|
+
border: 1px solid var(--zanin-hairline);
|
|
337
|
+
border-radius: var(--zanin-radius);
|
|
286
338
|
height: auto;
|
|
287
339
|
max-width: 100%;
|
|
288
340
|
width: 100%;
|
|
289
341
|
}
|
|
290
342
|
.zanin-figure figcaption {
|
|
291
343
|
color: var(--zanin-ink-faint);
|
|
292
|
-
font-size:
|
|
344
|
+
font-size: 0.82em;
|
|
293
345
|
margin-top: 10px;
|
|
294
346
|
text-align: center;
|
|
295
347
|
}
|
|
296
348
|
|
|
297
349
|
.zanin-chart {
|
|
298
350
|
background: var(--zanin-surface);
|
|
299
|
-
border
|
|
300
|
-
|
|
301
|
-
|
|
351
|
+
border: 1px solid var(--zanin-hairline);
|
|
352
|
+
border-radius: var(--zanin-radius);
|
|
353
|
+
box-shadow: var(--zanin-shadow);
|
|
354
|
+
padding: calc(18px * var(--zanin-space));
|
|
302
355
|
}
|
|
303
356
|
.zanin-chart-title {
|
|
304
|
-
color: var(--zanin-ink-
|
|
305
|
-
font-size:
|
|
306
|
-
font-weight:
|
|
307
|
-
letter-spacing: 0.09em;
|
|
357
|
+
color: var(--zanin-ink-muted);
|
|
358
|
+
font-size: 0.82em;
|
|
359
|
+
font-weight: 600;
|
|
308
360
|
margin: 0 0 14px;
|
|
309
|
-
text-transform: uppercase;
|
|
310
361
|
}
|
|
311
362
|
.zanin-chart .recharts-text {
|
|
312
363
|
fill: var(--zanin-ink-faint);
|
|
@@ -314,47 +365,50 @@
|
|
|
314
365
|
|
|
315
366
|
.zanin-cta {
|
|
316
367
|
align-items: center;
|
|
317
|
-
background:
|
|
318
|
-
border
|
|
368
|
+
background: var(--zanin-surface);
|
|
369
|
+
border: 1px solid var(--zanin-hairline);
|
|
370
|
+
border-radius: var(--zanin-radius);
|
|
371
|
+
box-shadow: var(--zanin-shadow);
|
|
319
372
|
display: flex;
|
|
320
373
|
flex-wrap: wrap;
|
|
321
|
-
gap:
|
|
374
|
+
gap: 16px;
|
|
322
375
|
justify-content: space-between;
|
|
323
|
-
padding:
|
|
376
|
+
padding: calc(22px * var(--zanin-space)) 24px;
|
|
324
377
|
}
|
|
325
378
|
.zanin-cta-title {
|
|
326
|
-
font-family: var(--zanin-font-
|
|
327
|
-
font-size:
|
|
328
|
-
font-weight:
|
|
379
|
+
font-family: var(--zanin-font-heading);
|
|
380
|
+
font-size: 1.15em;
|
|
381
|
+
font-weight: var(--zanin-heading-weight);
|
|
329
382
|
margin: 0;
|
|
330
383
|
}
|
|
331
384
|
.zanin-cta-description {
|
|
332
385
|
color: var(--zanin-ink-muted);
|
|
333
|
-
font-size:
|
|
386
|
+
font-size: 0.9em;
|
|
334
387
|
margin: 4px 0 0;
|
|
335
388
|
}
|
|
336
389
|
.zanin-cta-button {
|
|
337
390
|
background: var(--zanin-accent);
|
|
338
|
-
border-radius:
|
|
339
|
-
box-shadow: 0 4px 14px color-mix(in srgb, var(--zanin-accent) 35%, transparent);
|
|
391
|
+
border-radius: calc(var(--zanin-radius) / 1.5);
|
|
340
392
|
color: #fff !important;
|
|
341
393
|
display: inline-block;
|
|
342
|
-
font-size:
|
|
343
|
-
font-weight:
|
|
344
|
-
padding:
|
|
345
|
-
|
|
394
|
+
font-size: 0.9em;
|
|
395
|
+
font-weight: 600;
|
|
396
|
+
padding: 10px 20px;
|
|
397
|
+
text-decoration: none !important;
|
|
398
|
+
transition: background 0.15s ease, transform 0.1s ease;
|
|
346
399
|
white-space: nowrap;
|
|
347
400
|
}
|
|
348
401
|
.zanin-cta-button:hover {
|
|
349
|
-
background: var(--zanin-accent-
|
|
402
|
+
background: var(--zanin-accent-strong);
|
|
350
403
|
}
|
|
351
404
|
.zanin-cta-button:active {
|
|
352
|
-
transform: scale(0.
|
|
405
|
+
transform: scale(0.98);
|
|
353
406
|
}
|
|
354
407
|
|
|
355
408
|
.zanin-embed-youtube {
|
|
356
409
|
aspect-ratio: 16 / 9;
|
|
357
|
-
border
|
|
410
|
+
border: 1px solid var(--zanin-hairline);
|
|
411
|
+
border-radius: var(--zanin-radius);
|
|
358
412
|
overflow: hidden;
|
|
359
413
|
}
|
|
360
414
|
.zanin-embed-youtube iframe {
|
|
@@ -365,84 +419,101 @@
|
|
|
365
419
|
|
|
366
420
|
.zanin-tweet {
|
|
367
421
|
background: var(--zanin-surface);
|
|
368
|
-
border
|
|
369
|
-
|
|
422
|
+
border: 1px solid var(--zanin-hairline);
|
|
423
|
+
border-radius: var(--zanin-radius);
|
|
424
|
+
box-shadow: var(--zanin-shadow);
|
|
370
425
|
margin: 0;
|
|
371
|
-
padding: 22px
|
|
426
|
+
padding: calc(18px * var(--zanin-space)) 22px;
|
|
372
427
|
}
|
|
373
428
|
.zanin-tweet-text {
|
|
374
|
-
font-
|
|
375
|
-
|
|
376
|
-
font-style: italic;
|
|
377
|
-
line-height: 1.5;
|
|
429
|
+
font-size: 1.02em;
|
|
430
|
+
line-height: 1.55;
|
|
378
431
|
}
|
|
379
432
|
.zanin-tweet footer {
|
|
380
433
|
align-items: center;
|
|
381
434
|
color: var(--zanin-ink-faint);
|
|
382
435
|
display: flex;
|
|
383
|
-
font-size:
|
|
436
|
+
font-size: 0.82em;
|
|
384
437
|
gap: 8px;
|
|
385
|
-
margin-top:
|
|
438
|
+
margin-top: 12px;
|
|
386
439
|
}
|
|
387
440
|
.zanin-tweet-author {
|
|
388
441
|
color: var(--zanin-ink);
|
|
389
|
-
font-weight:
|
|
442
|
+
font-weight: 600;
|
|
390
443
|
}
|
|
391
444
|
|
|
392
445
|
.zanin-codeblock {
|
|
393
|
-
background: #
|
|
394
|
-
border-radius: var(--zanin-radius
|
|
395
|
-
color: #
|
|
446
|
+
background: #1a1a1a;
|
|
447
|
+
border-radius: var(--zanin-radius);
|
|
448
|
+
color: #e3e3e3;
|
|
396
449
|
overflow: hidden;
|
|
397
450
|
position: relative;
|
|
398
451
|
}
|
|
399
452
|
.zanin-codeblock-lang {
|
|
400
|
-
color: #
|
|
453
|
+
color: #8a8a8a;
|
|
401
454
|
font-family: var(--zanin-font-mono);
|
|
402
|
-
font-size:
|
|
403
|
-
letter-spacing: 0.
|
|
455
|
+
font-size: 0.68em;
|
|
456
|
+
letter-spacing: 0.08em;
|
|
404
457
|
position: absolute;
|
|
405
|
-
right:
|
|
458
|
+
right: 14px;
|
|
406
459
|
text-transform: uppercase;
|
|
407
|
-
top:
|
|
460
|
+
top: 11px;
|
|
408
461
|
}
|
|
409
462
|
.zanin-codeblock pre {
|
|
410
463
|
font-family: var(--zanin-font-mono);
|
|
411
|
-
font-size:
|
|
464
|
+
font-size: 0.82em;
|
|
412
465
|
line-height: 1.6;
|
|
413
466
|
margin: 0;
|
|
414
467
|
overflow-x: auto;
|
|
415
|
-
padding: 20px
|
|
468
|
+
padding: calc(18px * var(--zanin-space)) 20px;
|
|
416
469
|
}
|
|
417
470
|
.zanin-codeblock code {
|
|
418
471
|
background: none;
|
|
472
|
+
border: none;
|
|
419
473
|
padding: 0;
|
|
420
474
|
}
|
|
421
475
|
|
|
422
476
|
.zanin-comparison {
|
|
477
|
+
border: 1px solid var(--zanin-hairline);
|
|
478
|
+
border-radius: var(--zanin-radius);
|
|
423
479
|
overflow-x: auto;
|
|
424
480
|
}
|
|
481
|
+
.zanin-comparison table {
|
|
482
|
+
margin: 0;
|
|
483
|
+
}
|
|
484
|
+
.zanin-comparison th,
|
|
485
|
+
.zanin-comparison td {
|
|
486
|
+
padding: 10px 14px;
|
|
487
|
+
}
|
|
488
|
+
.zanin-comparison tr:last-child td {
|
|
489
|
+
border-bottom: none;
|
|
490
|
+
}
|
|
425
491
|
.zanin-comparison .zanin-highlight {
|
|
426
|
-
background: color-mix(in srgb, var(--zanin-accent)
|
|
492
|
+
background: color-mix(in srgb, var(--zanin-accent) 6%, transparent);
|
|
427
493
|
}
|
|
428
494
|
.zanin-check {
|
|
429
|
-
color: #
|
|
495
|
+
color: #0c5132;
|
|
430
496
|
font-weight: 700;
|
|
431
497
|
}
|
|
432
498
|
.zanin-cross {
|
|
433
499
|
color: var(--zanin-ink-faint);
|
|
434
500
|
}
|
|
435
501
|
|
|
502
|
+
.zanin-faq {
|
|
503
|
+
border: 1px solid var(--zanin-hairline);
|
|
504
|
+
border-radius: var(--zanin-radius);
|
|
505
|
+
overflow: hidden;
|
|
506
|
+
}
|
|
436
507
|
.zanin-faq details {
|
|
437
|
-
border-
|
|
438
|
-
padding:
|
|
508
|
+
border-bottom: 1px solid var(--zanin-hairline);
|
|
509
|
+
padding: calc(14px * var(--zanin-space)) 18px;
|
|
439
510
|
}
|
|
440
511
|
.zanin-faq details:last-child {
|
|
441
|
-
border-bottom:
|
|
512
|
+
border-bottom: none;
|
|
442
513
|
}
|
|
443
514
|
.zanin-faq summary {
|
|
444
515
|
cursor: pointer;
|
|
445
|
-
font-weight:
|
|
516
|
+
font-weight: 600;
|
|
446
517
|
list-style: none;
|
|
447
518
|
}
|
|
448
519
|
.zanin-faq summary::-webkit-details-marker {
|
|
@@ -452,13 +523,15 @@
|
|
|
452
523
|
color: var(--zanin-ink-faint);
|
|
453
524
|
content: "+";
|
|
454
525
|
float: right;
|
|
455
|
-
font-size:
|
|
526
|
+
font-size: 1.1em;
|
|
527
|
+
line-height: 1;
|
|
456
528
|
}
|
|
457
529
|
.zanin-faq details[open] summary::after {
|
|
458
530
|
content: "–";
|
|
459
531
|
}
|
|
460
532
|
.zanin-faq details p {
|
|
461
533
|
color: var(--zanin-ink-muted);
|
|
534
|
+
font-size: 0.94em;
|
|
462
535
|
margin: 10px 0 0;
|
|
463
536
|
}
|
|
464
537
|
|
|
@@ -466,11 +539,11 @@
|
|
|
466
539
|
|
|
467
540
|
@media (max-width: 640px) {
|
|
468
541
|
.zanin-blog {
|
|
469
|
-
padding: 32px 18px 64px;
|
|
542
|
+
padding: calc(32px * var(--zanin-space)) 18px calc(64px * var(--zanin-space));
|
|
470
543
|
}
|
|
471
544
|
.zanin-index-header h1,
|
|
472
545
|
.zanin-post-header h1 {
|
|
473
|
-
font-size:
|
|
546
|
+
font-size: 1.9em;
|
|
474
547
|
}
|
|
475
548
|
}
|
|
476
549
|
|