@ingram-tech/nk-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/README.md +78 -0
- package/dist/blog.d.ts +54 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +99 -0
- package/dist/blog.js.map +1 -0
- package/dist/contract.d.ts +102 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +57 -0
- package/dist/contract.js.map +1 -0
- package/dist/date.d.ts +6 -0
- package/dist/date.d.ts.map +1 -0
- package/dist/date.js +12 -0
- package/dist/date.js.map +1 -0
- package/dist/http.d.ts +3 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +10 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +8 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +11 -0
- package/dist/keys.js.map +1 -0
- package/dist/limited-mdx.d.ts +33 -0
- package/dist/limited-mdx.d.ts.map +1 -0
- package/dist/limited-mdx.js +151 -0
- package/dist/limited-mdx.js.map +1 -0
- package/dist/reading-time.d.ts +10 -0
- package/dist/reading-time.d.ts.map +1 -0
- package/dist/reading-time.js +11 -0
- package/dist/reading-time.js.map +1 -0
- package/dist/render.d.ts +38 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +39 -0
- package/dist/render.js.map +1 -0
- package/dist/rss.d.ts +18 -0
- package/dist/rss.d.ts.map +1 -0
- package/dist/rss.js +49 -0
- package/dist/rss.js.map +1 -0
- package/dist/schema.d.ts +61 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +48 -0
- package/dist/schema.js.map +1 -0
- package/dist/seo.d.ts +18 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +30 -0
- package/dist/seo.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +10 -0
- package/dist/server.js.map +1 -0
- package/dist/sources/fs.d.ts +12 -0
- package/dist/sources/fs.d.ts.map +1 -0
- package/dist/sources/fs.js +54 -0
- package/dist/sources/fs.js.map +1 -0
- package/dist/sources/github.d.ts +20 -0
- package/dist/sources/github.d.ts.map +1 -0
- package/dist/sources/github.js +62 -0
- package/dist/sources/github.js.map +1 -0
- package/dist/sources/publish.d.ts +36 -0
- package/dist/sources/publish.d.ts.map +1 -0
- package/dist/sources/publish.js +55 -0
- package/dist/sources/publish.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/unstyled/callout.d.ts +8 -0
- package/dist/unstyled/callout.d.ts.map +1 -0
- package/dist/unstyled/callout.js +8 -0
- package/dist/unstyled/callout.js.map +1 -0
- package/dist/unstyled/figure.d.ts +8 -0
- package/dist/unstyled/figure.d.ts.map +1 -0
- package/dist/unstyled/figure.js +9 -0
- package/dist/unstyled/figure.js.map +1 -0
- package/dist/unstyled/index.d.ts +16 -0
- package/dist/unstyled/index.d.ts.map +1 -0
- package/dist/unstyled/index.js +23 -0
- package/dist/unstyled/index.js.map +1 -0
- package/dist/unstyled/newsletter-subscribe.d.ts +7 -0
- package/dist/unstyled/newsletter-subscribe.d.ts.map +1 -0
- package/dist/unstyled/newsletter-subscribe.js +7 -0
- package/dist/unstyled/newsletter-subscribe.js.map +1 -0
- package/dist/unstyled/tweet.d.ts +8 -0
- package/dist/unstyled/tweet.d.ts.map +1 -0
- package/dist/unstyled/tweet.js +8 -0
- package/dist/unstyled/tweet.js.map +1 -0
- package/dist/unstyled/youtube.d.ts +7 -0
- package/dist/unstyled/youtube.d.ts.map +1 -0
- package/dist/unstyled/youtube.js +11 -0
- package/dist/unstyled/youtube.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/sources/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;IAExE,OAAO;QACN,KAAK,CAAC,IAAI;YACT,IAAI,OAAO,CAAC;YACZ,IAAI,CAAC;gBACJ,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,IACC,KAAK,YAAY,KAAK;oBACtB,MAAM,IAAI,KAAK;oBACf,KAAK,CAAC,IAAI,KAAK,QAAQ,EACtB,CAAC;oBACF,OAAO,EAAE,CAAC;gBACX,CAAC;gBACD,MAAM,KAAK,CAAC;YACb,CAAC;YAED,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAClD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACxB,CAAC;qBAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBAChC,8DAA8D;oBAC9D,KAAK,MAAM,KAAK,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC;wBAC/C,IAAI,CAAC;4BACJ,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;4BACpD,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;4BACrC,MAAM;wBACP,CAAC;wBAAC,MAAM,CAAC;4BACR,eAAe;wBAChB,CAAC;oBACF,CAAC;gBACF,CAAC;YACF,CAAC;YAED,OAAO,OAAO,CAAC,GAAG,CACjB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC1B,IAAI;gBACJ,OAAO,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC;aACzD,CAAC,CAAC,CACH,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BlogSource } from "../blog.js";
|
|
2
|
+
export interface GitHubRepoConfig {
|
|
3
|
+
owner: string;
|
|
4
|
+
repo: string;
|
|
5
|
+
/** Branch, tag, or commit; defaults to the repo's default branch. */
|
|
6
|
+
ref?: string;
|
|
7
|
+
/** Content directory inside the repo, e.g. "content/blog". */
|
|
8
|
+
dir: string;
|
|
9
|
+
/** Falls back to the GITHUB_TOKEN env var. */
|
|
10
|
+
token?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function githubHeaders(token: string | undefined): Record<string, string>;
|
|
13
|
+
/**
|
|
14
|
+
* Read a repo's posts over the GitHub API — the admin publisher's read path
|
|
15
|
+
* (list a target's real posts; reconcile instead of blind-append). One Trees
|
|
16
|
+
* call for the listing, then batched blob fetches: never per-file `contents`
|
|
17
|
+
* round-trips.
|
|
18
|
+
*/
|
|
19
|
+
export declare function githubSource(config: GitHubRepoConfig): BlogSource;
|
|
20
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/sources/github.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,YAAY,CAAC;AAI1D,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ/E;AAkBD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAgDjE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { assertResponseOk } from "../http.js";
|
|
3
|
+
import { keys } from "../keys.js";
|
|
4
|
+
const API = "https://api.github.com";
|
|
5
|
+
export function githubHeaders(token) {
|
|
6
|
+
const resolved = token ?? keys().GITHUB_TOKEN;
|
|
7
|
+
return {
|
|
8
|
+
accept: "application/vnd.github+json",
|
|
9
|
+
"x-github-api-version": "2022-11-28",
|
|
10
|
+
"user-agent": "nk-blog",
|
|
11
|
+
...(resolved ? { authorization: `Bearer ${resolved}` } : {}),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const treeSchema = z.object({
|
|
15
|
+
truncated: z.boolean(),
|
|
16
|
+
tree: z.array(z.object({
|
|
17
|
+
path: z.string(),
|
|
18
|
+
type: z.string(),
|
|
19
|
+
sha: z.string(),
|
|
20
|
+
})),
|
|
21
|
+
});
|
|
22
|
+
const blobSchema = z.object({
|
|
23
|
+
content: z.string(),
|
|
24
|
+
encoding: z.literal("base64"),
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Read a repo's posts over the GitHub API — the admin publisher's read path
|
|
28
|
+
* (list a target's real posts; reconcile instead of blind-append). One Trees
|
|
29
|
+
* call for the listing, then batched blob fetches: never per-file `contents`
|
|
30
|
+
* round-trips.
|
|
31
|
+
*/
|
|
32
|
+
export function githubSource(config) {
|
|
33
|
+
return {
|
|
34
|
+
async load() {
|
|
35
|
+
const headers = githubHeaders(config.token);
|
|
36
|
+
const base = `${API}/repos/${config.owner}/${config.repo}`;
|
|
37
|
+
const ref = config.ref ?? "HEAD";
|
|
38
|
+
const treeResponse = await fetch(`${base}/git/trees/${encodeURIComponent(ref)}?recursive=1`, { headers });
|
|
39
|
+
await assertResponseOk(treeResponse, `nk-blog: listing ${config.owner}/${config.repo}@${ref}`);
|
|
40
|
+
const { tree, truncated } = treeSchema.parse(await treeResponse.json());
|
|
41
|
+
if (truncated) {
|
|
42
|
+
throw new Error(`nk-blog: git tree for ${config.owner}/${config.repo} is truncated; narrow \`dir\``);
|
|
43
|
+
}
|
|
44
|
+
const prefix = `${config.dir.replace(/\/$/, "")}/`;
|
|
45
|
+
const files = tree.filter((entry) => entry.type === "blob" &&
|
|
46
|
+
entry.path.startsWith(prefix) &&
|
|
47
|
+
/\.mdx?$/.test(entry.path));
|
|
48
|
+
return Promise.all(files.map(async (entry) => {
|
|
49
|
+
const blobResponse = await fetch(`${base}/git/blobs/${entry.sha}`, {
|
|
50
|
+
headers,
|
|
51
|
+
});
|
|
52
|
+
await assertResponseOk(blobResponse, `nk-blog: reading ${entry.path}`);
|
|
53
|
+
const blob = blobSchema.parse(await blobResponse.json());
|
|
54
|
+
return {
|
|
55
|
+
name: entry.path.slice(prefix.length),
|
|
56
|
+
content: Buffer.from(blob.content, "base64").toString("utf8"),
|
|
57
|
+
};
|
|
58
|
+
}));
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/sources/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type BlogFrontmatterInput } from "../schema.js";
|
|
3
|
+
import type { PostFormat } from "../types.js";
|
|
4
|
+
import { type GitHubRepoConfig } from "./github.js";
|
|
5
|
+
/** Canonical on-disk form of a post: YAML frontmatter + body, one trailing \n. */
|
|
6
|
+
export declare function serializePost(frontmatter: BlogFrontmatterInput, body: string): string;
|
|
7
|
+
export interface PublishPostInput {
|
|
8
|
+
slug: string;
|
|
9
|
+
frontmatter: BlogFrontmatterInput;
|
|
10
|
+
body: string;
|
|
11
|
+
/** Admin's automated path emits "md" (data, never code) — the default. */
|
|
12
|
+
format?: PostFormat;
|
|
13
|
+
message?: string;
|
|
14
|
+
/** Commit to this branch (e.g. for a draft/preview PR) instead of the ref. */
|
|
15
|
+
branch?: string;
|
|
16
|
+
/** Update an existing post instead of failing the slug-collision check. */
|
|
17
|
+
overwrite?: boolean;
|
|
18
|
+
}
|
|
19
|
+
declare const putResponseSchema: z.ZodObject<{
|
|
20
|
+
content: z.ZodObject<{
|
|
21
|
+
path: z.ZodString;
|
|
22
|
+
sha: z.ZodString;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
commit: z.ZodObject<{
|
|
25
|
+
sha: z.ZodString;
|
|
26
|
+
html_url: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export type PublishedPost = z.infer<typeof putResponseSchema>;
|
|
30
|
+
/**
|
|
31
|
+
* Publish a post by committing one content file to the target repo — the
|
|
32
|
+
* entire replacement for admin's buildPostsJson/buildMdx machinery.
|
|
33
|
+
*/
|
|
34
|
+
export declare function publishPost(target: GitHubRepoConfig, input: PublishPostInput): Promise<PublishedPost>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/sources/publish.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAyB,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAInE,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,WAAW,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,oBAAoB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,iBAAiB;;;;;;;;;iBAGrB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE9D;;;GAGG;AACH,wBAAsB,WAAW,CAChC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,gBAAgB,GACrB,OAAO,CAAC,aAAa,CAAC,CAwCxB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import matter from "gray-matter";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { blogFrontmatterSchema } from "../schema.js";
|
|
4
|
+
import { assertResponseOk } from "../http.js";
|
|
5
|
+
import { githubHeaders } from "./github.js";
|
|
6
|
+
const API = "https://api.github.com";
|
|
7
|
+
/** Canonical on-disk form of a post: YAML frontmatter + body, one trailing \n. */
|
|
8
|
+
export function serializePost(frontmatter, body) {
|
|
9
|
+
// Validate before serializing so admin can never commit a file the sites'
|
|
10
|
+
// readers would reject at build time.
|
|
11
|
+
blogFrontmatterSchema.parse(frontmatter);
|
|
12
|
+
return `${matter.stringify(`\n${body.trim()}\n`, frontmatter).trim()}\n`;
|
|
13
|
+
}
|
|
14
|
+
const putResponseSchema = z.object({
|
|
15
|
+
content: z.object({ path: z.string(), sha: z.string() }),
|
|
16
|
+
commit: z.object({ sha: z.string(), html_url: z.string().optional() }),
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Publish a post by committing one content file to the target repo — the
|
|
20
|
+
* entire replacement for admin's buildPostsJson/buildMdx machinery.
|
|
21
|
+
*/
|
|
22
|
+
export async function publishPost(target, input) {
|
|
23
|
+
const headers = githubHeaders(target.token);
|
|
24
|
+
const base = `${API}/repos/${target.owner}/${target.repo}`;
|
|
25
|
+
const filePath = `${target.dir.replace(/\/$/, "")}/${input.slug}.${input.format ?? "md"}`;
|
|
26
|
+
const branch = input.branch ?? target.ref;
|
|
27
|
+
const refQuery = branch ? `?ref=${encodeURIComponent(branch)}` : "";
|
|
28
|
+
// Slug-collision check (and the sha needed when overwriting).
|
|
29
|
+
const existing = await fetch(`${base}/contents/${filePath}${refQuery}`, {
|
|
30
|
+
headers,
|
|
31
|
+
});
|
|
32
|
+
let existingSha;
|
|
33
|
+
if (existing.ok) {
|
|
34
|
+
if (!input.overwrite) {
|
|
35
|
+
throw new Error(`nk-blog: ${filePath} already exists in ${target.owner}/${target.repo}`);
|
|
36
|
+
}
|
|
37
|
+
existingSha = z.object({ sha: z.string() }).parse(await existing.json()).sha;
|
|
38
|
+
}
|
|
39
|
+
else if (existing.status !== 404) {
|
|
40
|
+
await assertResponseOk(existing, `nk-blog: checking ${filePath}`);
|
|
41
|
+
}
|
|
42
|
+
const response = await fetch(`${base}/contents/${filePath}`, {
|
|
43
|
+
method: "PUT",
|
|
44
|
+
headers: { ...headers, "content-type": "application/json" },
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
message: input.message ?? `content: publish ${input.slug}`,
|
|
47
|
+
content: Buffer.from(serializePost(input.frontmatter, input.body), "utf8").toString("base64"),
|
|
48
|
+
...(branch ? { branch } : {}),
|
|
49
|
+
...(existingSha ? { sha: existingSha } : {}),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
await assertResponseOk(response, `nk-blog: publishing ${filePath}`);
|
|
53
|
+
return putResponseSchema.parse(await response.json());
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/sources/publish.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type PostFormat = "md" | "mdx";
|
|
2
|
+
/** Everything a listing page needs — no body. */
|
|
3
|
+
export interface BlogPostPreview {
|
|
4
|
+
slug: string;
|
|
5
|
+
title: string;
|
|
6
|
+
seoTitle?: string;
|
|
7
|
+
description: string;
|
|
8
|
+
/** ISO 8601. */
|
|
9
|
+
date: string;
|
|
10
|
+
/** ISO 8601; set when the post declares an `updated` date. */
|
|
11
|
+
updated?: string;
|
|
12
|
+
authors: string[];
|
|
13
|
+
/** First author — convenience for single-byline layouts. */
|
|
14
|
+
author: string;
|
|
15
|
+
category?: string;
|
|
16
|
+
tags: string[];
|
|
17
|
+
image?: string;
|
|
18
|
+
draft: boolean;
|
|
19
|
+
featured: boolean;
|
|
20
|
+
/** Reserved for i18n'd blogs; not interpreted by the reader yet. */
|
|
21
|
+
lang?: string;
|
|
22
|
+
/** Reserved canonical-URL override for syndicated posts. */
|
|
23
|
+
canonical?: string;
|
|
24
|
+
format: PostFormat;
|
|
25
|
+
readingTimeMinutes: number;
|
|
26
|
+
/** e.g. "5 min read" — derived from the body, never authored. */
|
|
27
|
+
readTime: string;
|
|
28
|
+
}
|
|
29
|
+
/** A full post: the preview fields plus the body (frontmatter stripped). */
|
|
30
|
+
export interface BlogPost extends BlogPostPreview {
|
|
31
|
+
content: string;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,KAAK,CAAC;AAEtC,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,4EAA4E;AAC5E,MAAM,WAAW,QAAS,SAAQ,eAAe;IAChD,OAAO,EAAE,MAAM,CAAC;CAChB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CalloutProps } from "../contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* Unstyled default. Semantic structure only — style it from the site via the
|
|
4
|
+
* data attributes, or replace it wholesale. No visual props beyond className,
|
|
5
|
+
* ever (the bright line that keeps "unstyled" from eroding into a theme).
|
|
6
|
+
*/
|
|
7
|
+
export declare const Callout: React.FC<CalloutProps>;
|
|
8
|
+
//# sourceMappingURL=callout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callout.d.ts","sourceRoot":"","sources":["../../src/unstyled/callout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAU1C,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Unstyled default. Semantic structure only — style it from the site via the
|
|
4
|
+
* data attributes, or replace it wholesale. No visual props beyond className,
|
|
5
|
+
* ever (the bright line that keeps "unstyled" from eroding into a theme).
|
|
6
|
+
*/
|
|
7
|
+
export const Callout = ({ variant = "note", title, className, children, }) => (_jsxs("aside", { "data-callout": variant, className: className, children: [title ? _jsx("p", { "data-callout-title": true, children: title }) : null, _jsx("div", { "data-callout-body": true, children: children })] }));
|
|
8
|
+
//# sourceMappingURL=callout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callout.js","sourceRoot":"","sources":["../../src/unstyled/callout.tsx"],"names":[],"mappings":";AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,EAC/C,OAAO,GAAG,MAAM,EAChB,KAAK,EACL,SAAS,EACT,QAAQ,GACR,EAAE,EAAE,CAAC,CACL,iCAAqB,OAAO,EAAE,SAAS,EAAE,SAAS,aAChD,KAAK,CAAC,CAAC,CAAC,kDAAuB,KAAK,GAAK,CAAC,CAAC,CAAC,IAAI,EACjD,mDAAwB,QAAQ,GAAO,IAChC,CACR,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FigureProps } from "../contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* Unstyled captioned image: correct semantics (figure/figcaption), lazy
|
|
4
|
+
* loading, and explicit dimensions when given (CLS). Sites wanting
|
|
5
|
+
* next/image replace this wholesale.
|
|
6
|
+
*/
|
|
7
|
+
export declare const Figure: React.FC<FigureProps>;
|
|
8
|
+
//# sourceMappingURL=figure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figure.d.ts","sourceRoot":"","sources":["../../src/unstyled/figure.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAKlD;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAmBxC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const toDimension = (value) => typeof value === "string" ? Number(value) : value;
|
|
3
|
+
/**
|
|
4
|
+
* Unstyled captioned image: correct semantics (figure/figcaption), lazy
|
|
5
|
+
* loading, and explicit dimensions when given (CLS). Sites wanting
|
|
6
|
+
* next/image replace this wholesale.
|
|
7
|
+
*/
|
|
8
|
+
export const Figure = ({ src, alt, caption, width, height, className, }) => (_jsxs("figure", { className: className, children: [_jsx("img", { src: src, alt: alt, width: toDimension(width), height: toDimension(height), loading: "lazy", decoding: "async" }), caption ? _jsx("figcaption", { children: caption }) : null] }));
|
|
9
|
+
//# sourceMappingURL=figure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figure.js","sourceRoot":"","sources":["../../src/unstyled/figure.tsx"],"names":[],"mappings":";AAEA,MAAM,WAAW,GAAG,CAAC,KAAkC,EAAsB,EAAE,CAC9E,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAEnD;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAA0B,CAAC,EAC7C,GAAG,EACH,GAAG,EACH,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,GACT,EAAE,EAAE,CAAC,CACL,kBAAQ,SAAS,EAAE,SAAS,aAC3B,cACC,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EACzB,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAC3B,OAAO,EAAC,MAAM,EACd,QAAQ,EAAC,OAAO,GACf,EACD,OAAO,CAAC,CAAC,CAAC,+BAAa,OAAO,GAAc,CAAC,CAAC,CAAC,IAAI,IAC5C,CACT,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Callout } from "./callout.js";
|
|
2
|
+
import { Figure } from "./figure.js";
|
|
3
|
+
import { NewsletterSubscribe } from "./newsletter-subscribe.js";
|
|
4
|
+
import { Tweet } from "./tweet.js";
|
|
5
|
+
import { YouTube } from "./youtube.js";
|
|
6
|
+
export { Callout, Figure, NewsletterSubscribe, Tweet, YouTube };
|
|
7
|
+
/**
|
|
8
|
+
* The complete default registry. A site's whole obligation is:
|
|
9
|
+
*
|
|
10
|
+
* export const blogComponents = defineBlogComponents({
|
|
11
|
+
* ...unstyled,
|
|
12
|
+
* Callout: BrandCallout, // replaced wholesale where the brand cares
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
export declare const unstyled: import("../contract.js").BlogComponents;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/unstyled/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAEhE;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,yCAMnB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineBlogComponents } from "../contract.js";
|
|
2
|
+
import { Callout } from "./callout.js";
|
|
3
|
+
import { Figure } from "./figure.js";
|
|
4
|
+
import { NewsletterSubscribe } from "./newsletter-subscribe.js";
|
|
5
|
+
import { Tweet } from "./tweet.js";
|
|
6
|
+
import { YouTube } from "./youtube.js";
|
|
7
|
+
export { Callout, Figure, NewsletterSubscribe, Tweet, YouTube };
|
|
8
|
+
/**
|
|
9
|
+
* The complete default registry. A site's whole obligation is:
|
|
10
|
+
*
|
|
11
|
+
* export const blogComponents = defineBlogComponents({
|
|
12
|
+
* ...unstyled,
|
|
13
|
+
* Callout: BrandCallout, // replaced wholesale where the brand cares
|
|
14
|
+
* });
|
|
15
|
+
*/
|
|
16
|
+
export const unstyled = defineBlogComponents({
|
|
17
|
+
Callout,
|
|
18
|
+
Figure,
|
|
19
|
+
YouTube,
|
|
20
|
+
Tweet,
|
|
21
|
+
NewsletterSubscribe,
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/unstyled/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAEhE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,oBAAoB,CAAC;IAC5C,OAAO;IACP,MAAM;IACN,OAAO;IACP,KAAK;IACL,mBAAmB;CACnB,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NewsletterSubscribeProps } from "../contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* Plain HTML form POSTing to the injected endpoint — works with zero client
|
|
4
|
+
* JS. The package never bakes in a newsletter backend.
|
|
5
|
+
*/
|
|
6
|
+
export declare const NewsletterSubscribe: React.FC<NewsletterSubscribeProps>;
|
|
7
|
+
//# sourceMappingURL=newsletter-subscribe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"newsletter-subscribe.d.ts","sourceRoot":"","sources":["../../src/unstyled/newsletter-subscribe.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAgBlE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Plain HTML form POSTing to the injected endpoint — works with zero client
|
|
4
|
+
* JS. The package never bakes in a newsletter backend.
|
|
5
|
+
*/
|
|
6
|
+
export const NewsletterSubscribe = ({ action, placeholder, buttonLabel, className, }) => (_jsxs("form", { action: action, method: "post", className: className, children: [_jsx("input", { type: "email", name: "email", required: true, placeholder: placeholder ?? "you@example.com", "aria-label": "Email address" }), _jsx("button", { type: "submit", children: buttonLabel ?? "Subscribe" })] }));
|
|
7
|
+
//# sourceMappingURL=newsletter-subscribe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"newsletter-subscribe.js","sourceRoot":"","sources":["../../src/unstyled/newsletter-subscribe.tsx"],"names":[],"mappings":";AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAuC,CAAC,EACvE,MAAM,EACN,WAAW,EACX,WAAW,EACX,SAAS,GACT,EAAE,EAAE,CAAC,CACL,gBAAM,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,MAAM,EAAC,SAAS,EAAE,SAAS,aACvD,gBACC,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,OAAO,EACZ,QAAQ,QACR,WAAW,EAAE,WAAW,IAAI,iBAAiB,gBAClC,eAAe,GACzB,EACF,iBAAQ,IAAI,EAAC,QAAQ,YAAE,WAAW,IAAI,WAAW,GAAU,IACrD,CACP,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TweetProps } from "../contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* Zero-JS default: the standard `twitter-tweet` blockquote, progressively
|
|
4
|
+
* enhanced if the site loads the platform widget script — otherwise it
|
|
5
|
+
* degrades to a plain link. No data fetching in the package.
|
|
6
|
+
*/
|
|
7
|
+
export declare const Tweet: React.FC<TweetProps>;
|
|
8
|
+
//# sourceMappingURL=tweet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tweet.d.ts","sourceRoot":"","sources":["../../src/unstyled/tweet.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAItC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Zero-JS default: the standard `twitter-tweet` blockquote, progressively
|
|
4
|
+
* enhanced if the site loads the platform widget script — otherwise it
|
|
5
|
+
* degrades to a plain link. No data fetching in the package.
|
|
6
|
+
*/
|
|
7
|
+
export const Tweet = ({ id, className }) => (_jsx("blockquote", { className: ["twitter-tweet", className].filter(Boolean).join(" "), children: _jsx("a", { href: `https://twitter.com/i/status/${encodeURIComponent(id)}`, children: "View post" }) }));
|
|
8
|
+
//# sourceMappingURL=tweet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tweet.js","sourceRoot":"","sources":["../../src/unstyled/tweet.tsx"],"names":[],"mappings":";AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAyB,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CACjE,qBAAY,SAAS,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAC5E,YAAG,IAAI,EAAE,gCAAgC,kBAAkB,CAAC,EAAE,CAAC,EAAE,0BAAe,GACpE,CACb,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { YouTubeProps } from "../contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* Privacy-enhanced (youtube-nocookie), lazy-loaded embed with a stable 16:9
|
|
4
|
+
* box (CLS). The inline aspect-ratio is behavior, not styling.
|
|
5
|
+
*/
|
|
6
|
+
export declare const YouTube: React.FC<YouTubeProps>;
|
|
7
|
+
//# sourceMappingURL=youtube.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../../src/unstyled/youtube.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAiB1C,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Privacy-enhanced (youtube-nocookie), lazy-loaded embed with a stable 16:9
|
|
4
|
+
* box (CLS). The inline aspect-ratio is behavior, not styling.
|
|
5
|
+
*/
|
|
6
|
+
export const YouTube = ({ id, title, start, className }) => {
|
|
7
|
+
const startSeconds = typeof start === "string" ? Number(start) : start;
|
|
8
|
+
const src = `https://www.youtube-nocookie.com/embed/${encodeURIComponent(id)}${startSeconds ? `?start=${startSeconds}` : ""}`;
|
|
9
|
+
return (_jsx("iframe", { src: src, title: title ?? "YouTube video", loading: "lazy", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: true, referrerPolicy: "strict-origin-when-cross-origin", className: className, style: { aspectRatio: "16 / 9", width: "100%", border: 0 } }));
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=youtube.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../src/unstyled/youtube.tsx"],"names":[],"mappings":";AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAA2B,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE;IAClF,MAAM,YAAY,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACvE,MAAM,GAAG,GAAG,0CAA0C,kBAAkB,CAAC,EAAE,CAAC,GAC3E,YAAY,CAAC,CAAC,CAAC,UAAU,YAAY,EAAE,CAAC,CAAC,CAAC,EAC3C,EAAE,CAAC;IACH,OAAO,CACN,iBACC,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,IAAI,eAAe,EAC/B,OAAO,EAAC,MAAM,EACd,KAAK,EAAC,0FAA0F,EAChG,eAAe,QACf,cAAc,EAAC,iCAAiC,EAChD,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,GACzD,CACF,CAAC;AACH,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ingram-tech/nk-blog",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "File-based blog foundation for Next.js sites: frontmatter schema, build-time reader, limited-MDX rendering, a typed component contract with unstyled defaults, GitHub read/publish, and RSS.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ingram-technologies/nextkit.git",
|
|
10
|
+
"directory": "packages/nk-blog"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./server": {
|
|
25
|
+
"types": "./dist/server.d.ts",
|
|
26
|
+
"import": "./dist/server.js"
|
|
27
|
+
},
|
|
28
|
+
"./render": {
|
|
29
|
+
"types": "./dist/render.d.ts",
|
|
30
|
+
"import": "./dist/render.js"
|
|
31
|
+
},
|
|
32
|
+
"./unstyled": {
|
|
33
|
+
"types": "./dist/unstyled/index.d.ts",
|
|
34
|
+
"import": "./dist/unstyled/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc -p tsconfig.json",
|
|
39
|
+
"type-check": "tsc -p tsconfig.json --noEmit",
|
|
40
|
+
"test": "vitest run"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@ingram-tech/nk-seo": "^0.5.0",
|
|
44
|
+
"@mdx-js/mdx": "^3.1.1",
|
|
45
|
+
"gray-matter": "^4.0.3",
|
|
46
|
+
"react-markdown": "^10.1.0",
|
|
47
|
+
"remark-gfm": "^4.0.1",
|
|
48
|
+
"unist-util-visit": "^5.0.0",
|
|
49
|
+
"zod": "^4.4.3"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"next": ">=14.0.0",
|
|
53
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"next": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"react": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@ingram-tech/nk-dev": "0.2.4",
|
|
65
|
+
"@types/mdast": "^4.0.4",
|
|
66
|
+
"@types/node": "^26.0.1",
|
|
67
|
+
"@types/react": "^19.2.17",
|
|
68
|
+
"@types/react-dom": "^19.2.3",
|
|
69
|
+
"mdast-util-mdx-jsx": "^3.2.0",
|
|
70
|
+
"next": "^16.2.9",
|
|
71
|
+
"react": "^19.2.7",
|
|
72
|
+
"react-dom": "^19.2.7",
|
|
73
|
+
"typescript": "^6.0.3",
|
|
74
|
+
"unified": "^11.0.5",
|
|
75
|
+
"vfile": "^6.0.3",
|
|
76
|
+
"vitest": "^4.1.9"
|
|
77
|
+
}
|
|
78
|
+
}
|