@usezanin/blog 0.1.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/LICENSE +21 -0
- package/README.md +68 -0
- package/dist/BlogIndex.d.ts +9 -0
- package/dist/BlogIndex.d.ts.map +1 -0
- package/dist/BlogIndex.js +21 -0
- package/dist/BlogIndex.js.map +1 -0
- package/dist/BlogPost.d.ts +14 -0
- package/dist/BlogPost.d.ts.map +1 -0
- package/dist/BlogPost.js +53 -0
- package/dist/BlogPost.js.map +1 -0
- package/dist/components/CTA.d.ts +7 -0
- package/dist/components/CTA.d.ts.map +1 -0
- package/dist/components/CTA.js +5 -0
- package/dist/components/CTA.js.map +1 -0
- package/dist/components/Callout.d.ts +8 -0
- package/dist/components/Callout.d.ts.map +1 -0
- package/dist/components/Callout.js +11 -0
- package/dist/components/Callout.js.map +1 -0
- package/dist/components/Chart.d.ts +16 -0
- package/dist/components/Chart.d.ts.map +1 -0
- package/dist/components/Chart.js +28 -0
- package/dist/components/Chart.js.map +1 -0
- package/dist/components/CodeBlock.d.ts +9 -0
- package/dist/components/CodeBlock.d.ts.map +1 -0
- package/dist/components/CodeBlock.js +13 -0
- package/dist/components/CodeBlock.js.map +1 -0
- package/dist/components/ComparisonTable.d.ts +9 -0
- package/dist/components/ComparisonTable.d.ts.map +1 -0
- package/dist/components/ComparisonTable.js +12 -0
- package/dist/components/ComparisonTable.js.map +1 -0
- package/dist/components/Embeds.d.ts +15 -0
- package/dist/components/Embeds.d.ts.map +1 -0
- package/dist/components/Embeds.js +13 -0
- package/dist/components/Embeds.js.map +1 -0
- package/dist/components/FAQ.d.ts +9 -0
- package/dist/components/FAQ.d.ts.map +1 -0
- package/dist/components/FAQ.js +15 -0
- package/dist/components/FAQ.js.map +1 -0
- package/dist/components/Figure.d.ts +8 -0
- package/dist/components/Figure.d.ts.map +1 -0
- package/dist/components/Figure.js +5 -0
- package/dist/components/Figure.js.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +27 -0
- package/dist/config.js.map +1 -0
- package/dist/custom-components.d.ts +9 -0
- package/dist/custom-components.d.ts.map +1 -0
- package/dist/custom-components.js +58 -0
- package/dist/custom-components.js.map +1 -0
- package/dist/data.d.ts +9 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +36 -0
- package/dist/data.js.map +1 -0
- package/dist/handlers.d.ts +21 -0
- package/dist/handlers.d.ts.map +1 -0
- package/dist/handlers.js +89 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/mdx.d.ts +8 -0
- package/dist/mdx.d.ts.map +1 -0
- package/dist/mdx.js +35 -0
- package/dist/mdx.js.map +1 -0
- package/dist/seo.d.ts +19 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +49 -0
- package/dist/seo.js.map +1 -0
- package/package.json +61 -0
- package/styles.css +484 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as jsxRuntime from "react/jsx-runtime";
|
|
3
|
+
import { createClient } from "./data.js";
|
|
4
|
+
/**
|
|
5
|
+
* Modules a compiled component may require. Mirrors the CMS-side upload
|
|
6
|
+
* allowlist; anything else throws at evaluation time as defense in depth.
|
|
7
|
+
*/
|
|
8
|
+
const MODULE_MAP = {
|
|
9
|
+
react: React,
|
|
10
|
+
"react/jsx-runtime": jsxRuntime,
|
|
11
|
+
};
|
|
12
|
+
function evaluateComponent(name, compiledJs) {
|
|
13
|
+
const module = { exports: {} };
|
|
14
|
+
const requireShim = (specifier) => {
|
|
15
|
+
const resolved = MODULE_MAP[specifier];
|
|
16
|
+
if (!resolved) {
|
|
17
|
+
throw new Error(`Custom component "${name}" tried to require disallowed module "${specifier}"`);
|
|
18
|
+
}
|
|
19
|
+
return resolved;
|
|
20
|
+
};
|
|
21
|
+
try {
|
|
22
|
+
const factory = new Function("exports", "require", "module", compiledJs);
|
|
23
|
+
factory(module.exports, requireShim, module);
|
|
24
|
+
const exported = (module.exports.default ?? module.exports[name]);
|
|
25
|
+
return typeof exported === "function" ? exported : null;
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
console.error(`[@usezanin/blog] Failed to evaluate custom component "${name}":`, err);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Fetches the site's custom components and evaluates their compiled modules
|
|
34
|
+
* into React components, keyed by MDX tag name. Failures are skipped (with a
|
|
35
|
+
* server-side log) rather than breaking the whole post.
|
|
36
|
+
*/
|
|
37
|
+
export async function fetchCustomComponents(config) {
|
|
38
|
+
let list;
|
|
39
|
+
try {
|
|
40
|
+
list = await createClient(config).listComponents(config.siteId, {
|
|
41
|
+
includeCompiled: true,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error("[@usezanin/blog] Failed to fetch custom components:", err);
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
const map = {};
|
|
49
|
+
for (const component of list) {
|
|
50
|
+
if (!component.compiledJs)
|
|
51
|
+
continue;
|
|
52
|
+
const evaluated = evaluateComponent(component.name, component.compiledJs);
|
|
53
|
+
if (evaluated)
|
|
54
|
+
map[component.name] = evaluated;
|
|
55
|
+
}
|
|
56
|
+
return map;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=custom-components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-components.js","sourceRoot":"","sources":["../src/custom-components.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAIzC;;;GAGG;AACH,MAAM,UAAU,GAA4B;IAC1C,KAAK,EAAE,KAAK;IACZ,mBAAmB,EAAE,UAAU;CAChC,CAAC;AAEF,SAAS,iBAAiB,CAAC,IAAY,EAAE,UAAkB;IACzD,MAAM,MAAM,GAAc,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1C,MAAM,WAAW,GAAG,CAAC,SAAiB,EAAE,EAAE;QACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACb,qBAAqB,IAAI,yCAAyC,SAAS,GAAG,CAC/E,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACzE,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAEnD,CAAC;QACd,OAAO,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,yDAAyD,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;QACtF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAA+B;IAE/B,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE;YAC9D,eAAe,EAAE,IAAI;SACtB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,qDAAqD,EAAE,GAAG,CAAC,CAAC;QAC1E,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,SAAS,CAAC,UAAU;YAAE,SAAS;QACpC,MAAM,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QAC1E,IAAI,SAAS;YAAE,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACjD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/data.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ZaninClient, type Post } from "@usezanin/client";
|
|
2
|
+
import type { ResolvedZaninBlogConfig } from "./config.js";
|
|
3
|
+
/** Cache tag used for all SDK content fetches; the revalidation webhook busts it. */
|
|
4
|
+
export declare const ZANIN_CACHE_TAG = "zanin-blog";
|
|
5
|
+
export declare function createClient(config: ResolvedZaninBlogConfig): ZaninClient;
|
|
6
|
+
export declare function fetchPublishedPosts(config: ResolvedZaninBlogConfig): Promise<Post[]>;
|
|
7
|
+
export declare function fetchPublishedPost(config: ResolvedZaninBlogConfig, slug: string): Promise<Post | null>;
|
|
8
|
+
export declare function postUrl(config: ResolvedZaninBlogConfig, slug: string): string;
|
|
9
|
+
//# sourceMappingURL=data.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/data.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ZaninClient } from "@usezanin/client";
|
|
2
|
+
/** Cache tag used for all SDK content fetches; the revalidation webhook busts it. */
|
|
3
|
+
export const ZANIN_CACHE_TAG = "zanin-blog";
|
|
4
|
+
function createFetch(config) {
|
|
5
|
+
// Next.js patches global fetch; passing revalidate + tags opts the SDK's
|
|
6
|
+
// requests into ISR caching that the publish webhook can invalidate.
|
|
7
|
+
return (input, init) => fetch(input, {
|
|
8
|
+
...init,
|
|
9
|
+
next: { revalidate: config.revalidate, tags: [ZANIN_CACHE_TAG] },
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export function createClient(config) {
|
|
13
|
+
return new ZaninClient({
|
|
14
|
+
baseUrl: config.baseUrl,
|
|
15
|
+
apiKey: config.apiKey,
|
|
16
|
+
fetch: createFetch(config),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export async function fetchPublishedPosts(config) {
|
|
20
|
+
const posts = await createClient(config).listPosts(config.siteId, {
|
|
21
|
+
status: "published",
|
|
22
|
+
limit: 100,
|
|
23
|
+
});
|
|
24
|
+
return [...posts].sort((a, b) => new Date(b.publishedAt ?? b.createdAt).getTime() -
|
|
25
|
+
new Date(a.publishedAt ?? a.createdAt).getTime());
|
|
26
|
+
}
|
|
27
|
+
export async function fetchPublishedPost(config, slug) {
|
|
28
|
+
return createClient(config).getPostBySlug(config.siteId, slug, {
|
|
29
|
+
status: "published",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export function postUrl(config, slug) {
|
|
33
|
+
const path = `${config.basePath}/${slug}`.replace(/\/{2,}/g, "/");
|
|
34
|
+
return config.siteUrl ? `${config.siteUrl}${path}` : path;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=data.js.map
|
package/dist/data.js.map
ADDED
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ZaninBlogConfig } from "./config.js";
|
|
2
|
+
/**
|
|
3
|
+
* RSS 2.0 route handler. Usage — app/blog/rss.xml/route.ts:
|
|
4
|
+
* export const GET = createRssHandler(config);
|
|
5
|
+
*/
|
|
6
|
+
export declare function createRssHandler(config?: ZaninBlogConfig): () => Promise<Response>;
|
|
7
|
+
/**
|
|
8
|
+
* Sitemap route handler for the blog section. Usage — app/blog/sitemap.xml/route.ts:
|
|
9
|
+
* export const GET = createSitemapHandler(config);
|
|
10
|
+
*/
|
|
11
|
+
export declare function createSitemapHandler(config?: ZaninBlogConfig): () => Promise<Response>;
|
|
12
|
+
/**
|
|
13
|
+
* Revalidation webhook handler. Point the site's "revalidate webhook URL" in
|
|
14
|
+
* the Zanin dashboard at this route; the CMS calls it on publish/unpublish/
|
|
15
|
+
* update and the handler busts the SDK's ISR cache immediately.
|
|
16
|
+
*
|
|
17
|
+
* Usage — app/api/zanin/revalidate/route.ts:
|
|
18
|
+
* export const POST = createRevalidateHandler(config);
|
|
19
|
+
*/
|
|
20
|
+
export declare function createRevalidateHandler(config?: ZaninBlogConfig): (req: Request) => Promise<Response>;
|
|
21
|
+
//# sourceMappingURL=handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAWlE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAmClF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAuBtF;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,CAAC,EAAE,eAAe,GACvB,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAcrC"}
|
package/dist/handlers.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { revalidateTag } from "next/cache";
|
|
2
|
+
import { resolveConfig } from "./config.js";
|
|
3
|
+
import { fetchPublishedPosts, postUrl, ZANIN_CACHE_TAG } from "./data.js";
|
|
4
|
+
function xmlEscape(value) {
|
|
5
|
+
return value
|
|
6
|
+
.replaceAll("&", "&")
|
|
7
|
+
.replaceAll("<", "<")
|
|
8
|
+
.replaceAll(">", ">")
|
|
9
|
+
.replaceAll('"', """);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* RSS 2.0 route handler. Usage — app/blog/rss.xml/route.ts:
|
|
13
|
+
* export const GET = createRssHandler(config);
|
|
14
|
+
*/
|
|
15
|
+
export function createRssHandler(config) {
|
|
16
|
+
return async () => {
|
|
17
|
+
const resolved = resolveConfig(config);
|
|
18
|
+
const posts = await fetchPublishedPosts(resolved);
|
|
19
|
+
const channelTitle = resolved.siteName ? `${resolved.siteName} Blog` : "Blog";
|
|
20
|
+
const channelLink = resolved.siteUrl
|
|
21
|
+
? `${resolved.siteUrl}${resolved.basePath}`
|
|
22
|
+
: resolved.basePath;
|
|
23
|
+
const items = posts
|
|
24
|
+
.map((post) => ` <item>
|
|
25
|
+
<title>${xmlEscape(post.title)}</title>
|
|
26
|
+
<link>${xmlEscape(postUrl(resolved, post.slug))}</link>
|
|
27
|
+
<guid isPermaLink="true">${xmlEscape(postUrl(resolved, post.slug))}</guid>
|
|
28
|
+
${post.description ? `<description>${xmlEscape(post.description)}</description>` : ""}
|
|
29
|
+
<pubDate>${new Date(post.publishedAt ?? post.createdAt).toUTCString()}</pubDate>
|
|
30
|
+
</item>`)
|
|
31
|
+
.join("\n");
|
|
32
|
+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
33
|
+
<rss version="2.0">
|
|
34
|
+
<channel>
|
|
35
|
+
<title>${xmlEscape(channelTitle)}</title>
|
|
36
|
+
<link>${xmlEscape(channelLink)}</link>
|
|
37
|
+
<description>${xmlEscape(`Latest posts from ${channelTitle}`)}</description>
|
|
38
|
+
${items}
|
|
39
|
+
</channel>
|
|
40
|
+
</rss>`;
|
|
41
|
+
return new Response(xml, {
|
|
42
|
+
headers: { "content-type": "application/rss+xml; charset=utf-8" },
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sitemap route handler for the blog section. Usage — app/blog/sitemap.xml/route.ts:
|
|
48
|
+
* export const GET = createSitemapHandler(config);
|
|
49
|
+
*/
|
|
50
|
+
export function createSitemapHandler(config) {
|
|
51
|
+
return async () => {
|
|
52
|
+
const resolved = resolveConfig(config);
|
|
53
|
+
const posts = await fetchPublishedPosts(resolved);
|
|
54
|
+
const urls = posts
|
|
55
|
+
.map((post) => ` <url>
|
|
56
|
+
<loc>${xmlEscape(postUrl(resolved, post.slug))}</loc>
|
|
57
|
+
<lastmod>${new Date(post.updatedAt).toISOString()}</lastmod>
|
|
58
|
+
</url>`)
|
|
59
|
+
.join("\n");
|
|
60
|
+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
61
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
62
|
+
${urls}
|
|
63
|
+
</urlset>`;
|
|
64
|
+
return new Response(xml, {
|
|
65
|
+
headers: { "content-type": "application/xml; charset=utf-8" },
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Revalidation webhook handler. Point the site's "revalidate webhook URL" in
|
|
71
|
+
* the Zanin dashboard at this route; the CMS calls it on publish/unpublish/
|
|
72
|
+
* update and the handler busts the SDK's ISR cache immediately.
|
|
73
|
+
*
|
|
74
|
+
* Usage — app/api/zanin/revalidate/route.ts:
|
|
75
|
+
* export const POST = createRevalidateHandler(config);
|
|
76
|
+
*/
|
|
77
|
+
export function createRevalidateHandler(config) {
|
|
78
|
+
return async (req) => {
|
|
79
|
+
const resolved = resolveConfig(config);
|
|
80
|
+
if (resolved.revalidateSecret &&
|
|
81
|
+
req.headers.get("x-zanin-secret") !== resolved.revalidateSecret) {
|
|
82
|
+
return Response.json({ error: "Invalid secret" }, { status: 401 });
|
|
83
|
+
}
|
|
84
|
+
revalidateTag(ZANIN_CACHE_TAG);
|
|
85
|
+
const payload = await req.json().catch(() => ({}));
|
|
86
|
+
return Response.json({ revalidated: true, received: payload });
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { BlogIndex, type BlogIndexProps } from "./BlogIndex.js";
|
|
2
|
+
export { BlogPost, type BlogPostProps } from "./BlogPost.js";
|
|
3
|
+
export { resolveConfig, type ZaninBlogConfig } from "./config.js";
|
|
4
|
+
export { ZANIN_CACHE_TAG } from "./data.js";
|
|
5
|
+
export { createRevalidateHandler, createRssHandler, createSitemapHandler, } from "./handlers.js";
|
|
6
|
+
export { fetchCustomComponents } from "./custom-components.js";
|
|
7
|
+
export { builtinComponents, renderMdx } from "./mdx.js";
|
|
8
|
+
export { generateBlogMetadata, generateBlogStaticParams } from "./seo.js";
|
|
9
|
+
export { Callout } from "./components/Callout.js";
|
|
10
|
+
export { Chart, type ChartProps } from "./components/Chart.js";
|
|
11
|
+
export { CodeBlock } from "./components/CodeBlock.js";
|
|
12
|
+
export { ComparisonTable } from "./components/ComparisonTable.js";
|
|
13
|
+
export { CTA } from "./components/CTA.js";
|
|
14
|
+
export { Tweet, YouTube } from "./components/Embeds.js";
|
|
15
|
+
export { FAQ, type FaqItem } from "./components/FAQ.js";
|
|
16
|
+
export { Figure } from "./components/Figure.js";
|
|
17
|
+
export type { Post, Site } from "@usezanin/client";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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;AAChE,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,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
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { BlogIndex } from "./BlogIndex.js";
|
|
2
|
+
export { BlogPost } from "./BlogPost.js";
|
|
3
|
+
export { resolveConfig } from "./config.js";
|
|
4
|
+
export { ZANIN_CACHE_TAG } from "./data.js";
|
|
5
|
+
export { createRevalidateHandler, createRssHandler, createSitemapHandler, } from "./handlers.js";
|
|
6
|
+
export { fetchCustomComponents } from "./custom-components.js";
|
|
7
|
+
export { builtinComponents, renderMdx } from "./mdx.js";
|
|
8
|
+
export { generateBlogMetadata, generateBlogStaticParams } from "./seo.js";
|
|
9
|
+
export { Callout } from "./components/Callout.js";
|
|
10
|
+
export { Chart } from "./components/Chart.js";
|
|
11
|
+
export { CodeBlock } from "./components/CodeBlock.js";
|
|
12
|
+
export { ComparisonTable } from "./components/ComparisonTable.js";
|
|
13
|
+
export { CTA } from "./components/CTA.js";
|
|
14
|
+
export { Tweet, YouTube } from "./components/Embeds.js";
|
|
15
|
+
export { FAQ } from "./components/FAQ.js";
|
|
16
|
+
export { Figure } from "./components/Figure.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuB,MAAM,gBAAgB,CAAC;AAChE,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,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/mdx.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MDXComponents } from "mdx/types";
|
|
2
|
+
export declare const builtinComponents: MDXComponents;
|
|
3
|
+
/**
|
|
4
|
+
* Compiles and renders a post's MDX body on the server. Custom per-site
|
|
5
|
+
* components (milestone 5) and host overrides merge over the built-ins.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderMdx(source: string, components?: MDXComponents): Promise<React.ReactElement>;
|
|
8
|
+
//# sourceMappingURL=mdx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdx.d.ts","sourceRoot":"","sources":["../src/mdx.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAY/C,eAAO,MAAM,iBAAiB,EAAE,aAU/B,CAAC;AAEF;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,UAAU,GAAE,aAAkB,GAC7B,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAM7B"}
|
package/dist/mdx.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { evaluate } from "@mdx-js/mdx";
|
|
3
|
+
import * as runtime from "react/jsx-runtime";
|
|
4
|
+
import remarkGfm from "remark-gfm";
|
|
5
|
+
import { Callout } from "./components/Callout.js";
|
|
6
|
+
import { Chart } from "./components/Chart.js";
|
|
7
|
+
import { CodeBlock } from "./components/CodeBlock.js";
|
|
8
|
+
import { ComparisonTable } from "./components/ComparisonTable.js";
|
|
9
|
+
import { CTA } from "./components/CTA.js";
|
|
10
|
+
import { Tweet, YouTube } from "./components/Embeds.js";
|
|
11
|
+
import { FAQ } from "./components/FAQ.js";
|
|
12
|
+
import { Figure } from "./components/Figure.js";
|
|
13
|
+
export const builtinComponents = {
|
|
14
|
+
Callout,
|
|
15
|
+
Chart,
|
|
16
|
+
ComparisonTable,
|
|
17
|
+
CTA,
|
|
18
|
+
FAQ,
|
|
19
|
+
Figure,
|
|
20
|
+
Tweet,
|
|
21
|
+
YouTube,
|
|
22
|
+
pre: CodeBlock,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Compiles and renders a post's MDX body on the server. Custom per-site
|
|
26
|
+
* components (milestone 5) and host overrides merge over the built-ins.
|
|
27
|
+
*/
|
|
28
|
+
export async function renderMdx(source, components = {}) {
|
|
29
|
+
const { default: MDXContent } = await evaluate(source, {
|
|
30
|
+
...runtime,
|
|
31
|
+
remarkPlugins: [remarkGfm],
|
|
32
|
+
});
|
|
33
|
+
return _jsx(MDXContent, { components: { ...builtinComponents, ...components } });
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=mdx.js.map
|
package/dist/mdx.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdx.js","sourceRoot":"","sources":["../src/mdx.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAC7C,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,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,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,MAAM,CAAC,MAAM,iBAAiB,GAAkB;IAC9C,OAAO;IACP,KAAK;IACL,eAAe;IACf,GAAG;IACH,GAAG;IACH,MAAM;IACN,KAAK;IACL,OAAO;IACP,GAAG,EAAE,SAAS;CACf,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAc,EACd,aAA4B,EAAE;IAE9B,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE;QACrD,GAAG,OAAO;QACV,aAAa,EAAE,CAAC,SAAS,CAAC;KAC3B,CAAC,CAAC;IACH,OAAO,KAAC,UAAU,IAAC,UAAU,EAAE,EAAE,GAAG,iBAAiB,EAAE,GAAG,UAAU,EAAE,GAAI,CAAC;AAC7E,CAAC"}
|
package/dist/seo.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import { type ZaninBlogConfig } from "./config.js";
|
|
3
|
+
/**
|
|
4
|
+
* Next.js generateMetadata helper for the post page. Usage:
|
|
5
|
+
*
|
|
6
|
+
* export async function generateMetadata({ params }) {
|
|
7
|
+
* const { slug } = await params;
|
|
8
|
+
* return generateBlogMetadata(slug, config);
|
|
9
|
+
* }
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateBlogMetadata(slug: string, config?: ZaninBlogConfig): Promise<Metadata>;
|
|
12
|
+
/**
|
|
13
|
+
* Next.js generateStaticParams helper for the [slug] segment: returns all
|
|
14
|
+
* published slugs so posts are statically generated at build time.
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateBlogStaticParams(config?: ZaninBlogConfig): Promise<{
|
|
17
|
+
slug: string;
|
|
18
|
+
}[]>;
|
|
19
|
+
//# sourceMappingURL=seo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../src/seo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAGlE;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,QAAQ,CAAC,CA6BnB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAI7B"}
|
package/dist/seo.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { resolveConfig } from "./config.js";
|
|
2
|
+
import { fetchPublishedPost, fetchPublishedPosts, postUrl } from "./data.js";
|
|
3
|
+
/**
|
|
4
|
+
* Next.js generateMetadata helper for the post page. Usage:
|
|
5
|
+
*
|
|
6
|
+
* export async function generateMetadata({ params }) {
|
|
7
|
+
* const { slug } = await params;
|
|
8
|
+
* return generateBlogMetadata(slug, config);
|
|
9
|
+
* }
|
|
10
|
+
*/
|
|
11
|
+
export async function generateBlogMetadata(slug, config) {
|
|
12
|
+
const resolved = resolveConfig(config);
|
|
13
|
+
const post = await fetchPublishedPost(resolved, slug);
|
|
14
|
+
if (!post)
|
|
15
|
+
return {};
|
|
16
|
+
const canonical = resolved.siteUrl ? postUrl(resolved, post.slug) : undefined;
|
|
17
|
+
const title = resolved.siteName ? `${post.title} — ${resolved.siteName}` : post.title;
|
|
18
|
+
return {
|
|
19
|
+
title,
|
|
20
|
+
description: post.description ?? undefined,
|
|
21
|
+
alternates: canonical ? { canonical } : undefined,
|
|
22
|
+
openGraph: {
|
|
23
|
+
title: post.title,
|
|
24
|
+
description: post.description ?? undefined,
|
|
25
|
+
type: "article",
|
|
26
|
+
publishedTime: post.publishedAt ?? undefined,
|
|
27
|
+
modifiedTime: post.updatedAt,
|
|
28
|
+
url: canonical,
|
|
29
|
+
tags: post.tags,
|
|
30
|
+
...(post.ogImageUrl ? { images: [{ url: post.ogImageUrl }] } : {}),
|
|
31
|
+
},
|
|
32
|
+
twitter: {
|
|
33
|
+
card: post.ogImageUrl ? "summary_large_image" : "summary",
|
|
34
|
+
title: post.title,
|
|
35
|
+
description: post.description ?? undefined,
|
|
36
|
+
...(post.ogImageUrl ? { images: [post.ogImageUrl] } : {}),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Next.js generateStaticParams helper for the [slug] segment: returns all
|
|
42
|
+
* published slugs so posts are statically generated at build time.
|
|
43
|
+
*/
|
|
44
|
+
export async function generateBlogStaticParams(config) {
|
|
45
|
+
const resolved = resolveConfig(config);
|
|
46
|
+
const posts = await fetchPublishedPosts(resolved);
|
|
47
|
+
return posts.map((post) => ({ slug: post.slug }));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=seo.js.map
|
package/dist/seo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo.js","sourceRoot":"","sources":["../src/seo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7E;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAY,EACZ,MAAwB;IAExB,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAErB,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IAEtF,OAAO;QACL,KAAK;QACL,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;QAC1C,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS;QACjD,SAAS,EAAE;YACT,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;YAC1C,IAAI,EAAE,SAAS;YACf,aAAa,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;YAC5C,YAAY,EAAE,IAAI,CAAC,SAAS;YAC5B,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnE;QACD,OAAO,EAAE;YACP,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS;YACzD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;YAC1C,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1D;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAwB;IAExB,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@usezanin/blog",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React SDK for rendering Zanin blogs in Next.js sites — index/post components, built-in MDX components, SEO, RSS and sitemap",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./styles.css": "./styles.css"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"styles.css"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"zanin",
|
|
22
|
+
"blog",
|
|
23
|
+
"cms",
|
|
24
|
+
"nextjs",
|
|
25
|
+
"mdx",
|
|
26
|
+
"react"
|
|
27
|
+
],
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/siyabendoezdemir/zanin.git",
|
|
31
|
+
"directory": "packages/blog"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc -p tsconfig.json",
|
|
38
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
39
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
40
|
+
"prepublishOnly": "npm run build"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@mdx-js/mdx": "^3.1.0",
|
|
44
|
+
"@usezanin/client": "^0.1.0",
|
|
45
|
+
"recharts": "^2.15.0",
|
|
46
|
+
"remark-gfm": "^4.0.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"next": ">=15",
|
|
50
|
+
"react": ">=19",
|
|
51
|
+
"react-dom": ">=19"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^22.15.0",
|
|
55
|
+
"@types/react": "^19.1.0",
|
|
56
|
+
"next": "^15.4.0",
|
|
57
|
+
"react": "^19.1.0",
|
|
58
|
+
"react-dom": "^19.1.0",
|
|
59
|
+
"typescript": "^5.8.0"
|
|
60
|
+
}
|
|
61
|
+
}
|