astro-awesomeness 1.2.0 → 1.2.2

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.
@@ -0,0 +1,3 @@
1
+ import { cn } from "cn";
2
+
3
+ export { cn as t };
@@ -1,4 +1,4 @@
1
- import { t as cn } from "../cn-DmzdyV07.js";
1
+ import { t as cn } from "../cn-B2A3VjBM.js";
2
2
  import { Button as Button$1 } from "@base-ui/react/button";
3
3
  import { useSyncExternalStore } from "react";
4
4
  import { cva } from "class-variance-authority";
@@ -1,4 +1,4 @@
1
- import { cn } from "cnfast";
1
+ import { cn } from "cn";
2
2
  //#region src/lib/category-label.d.ts
3
3
  declare const categoryLabel: (name: string) => string;
4
4
  //#endregion
@@ -54,4 +54,4 @@ declare namespace index_d_exports {
54
54
  }
55
55
  //#endregion
56
56
  export { requireEnv as a, PostParams as c, getRelatedPosts as d, formatDate as f, slugify as i, PostUrlBuilder as l, cn as m, DEFAULT_TAG_BASE as n, readingTime as o, categoryLabel as p, tagUrl as r, PostLike as s, index_d_exports as t, createPostUrl as u };
57
- //# sourceMappingURL=index-CrcndL2W.d.ts.map
57
+ //# sourceMappingURL=index-iwkIePdz.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { Author, Post, Tag, t as index_d_exports } from "./content/index.js";
2
- import { t as index_d_exports$1 } from "./index-CrcndL2W.js";
2
+ import { t as index_d_exports$1 } from "./index-iwkIePdz.js";
3
3
  export { type Author, type Post, type Tag, index_d_exports as content, index_d_exports$1 as lib };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { t as content_exports } from "./content/index.js";
2
- import { t as lib_exports } from "./lib-BqEjsOJx.js";
2
+ import { t as lib_exports } from "./lib-D7HdNeEs.js";
3
3
 
4
4
  export { content_exports as content, lib_exports as lib };
@@ -1,2 +1,2 @@
1
- import { a as requireEnv, c as PostParams, d as getRelatedPosts, f as formatDate, i as slugify, l as PostUrlBuilder, m as cn, n as DEFAULT_TAG_BASE, o as readingTime, p as categoryLabel, r as tagUrl, s as PostLike, u as createPostUrl } from "../index-CrcndL2W.js";
1
+ import { a as requireEnv, c as PostParams, d as getRelatedPosts, f as formatDate, i as slugify, l as PostUrlBuilder, m as cn, n as DEFAULT_TAG_BASE, o as readingTime, p as categoryLabel, r as tagUrl, s as PostLike, u as createPostUrl } from "../index-iwkIePdz.js";
2
2
  export { DEFAULT_TAG_BASE, type PostLike, type PostParams, type PostUrlBuilder, categoryLabel, cn, createPostUrl, formatDate, getRelatedPosts, readingTime, requireEnv, slugify, tagUrl };
package/dist/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as cn } from "../cn-DmzdyV07.js";
2
- import { a as readingTime, c as getRelatedPosts, i as requireEnv, l as formatDate, n as DEFAULT_TAG_BASE, o as createPostUrl, r as tagUrl, s as slugify, u as categoryLabel } from "../lib-BqEjsOJx.js";
1
+ import { t as cn } from "../cn-B2A3VjBM.js";
2
+ import { a as readingTime, c as getRelatedPosts, i as requireEnv, l as formatDate, n as DEFAULT_TAG_BASE, o as createPostUrl, r as tagUrl, s as slugify, u as categoryLabel } from "../lib-D7HdNeEs.js";
3
3
 
4
4
  export { DEFAULT_TAG_BASE, categoryLabel, cn, createPostUrl, formatDate, getRelatedPosts, readingTime, requireEnv, slugify, tagUrl };
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-w6R9maHv.js";
2
- import { t as cn } from "./cn-DmzdyV07.js";
2
+ import { t as cn } from "./cn-B2A3VjBM.js";
3
3
 
4
4
  //#region src/lib/category-label.ts
5
5
  const NAMED_ENTITIES = {
@@ -151,4 +151,4 @@ var lib_exports = /* @__PURE__ */ __exportAll({
151
151
 
152
152
  //#endregion
153
153
  export { readingTime as a, getRelatedPosts as c, requireEnv as i, formatDate as l, DEFAULT_TAG_BASE as n, createPostUrl as o, tagUrl as r, slugify as s, lib_exports as t, categoryLabel as u };
154
- //# sourceMappingURL=lib-BqEjsOJx.js.map
154
+ //# sourceMappingURL=lib-D7HdNeEs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lib-BqEjsOJx.js","names":[],"sources":["../src/lib/category-label.ts","../src/lib/format-date.ts","../src/lib/get-related-posts.ts","../src/lib/slugify.ts","../src/lib/post-url.ts","../src/lib/reading-time.ts","../src/lib/require-env.ts","../src/lib/tag-url.ts","../src/lib/index.ts"],"sourcesContent":["const NAMED_ENTITIES = {\n amp: \"&\",\n apos: \"'\",\n gt: \">\",\n hellip: \"\\u2026\",\n ldquo: \"\\u201c\",\n lsquo: \"\\u2018\",\n lt: \"<\",\n nbsp: \"\\u00a0\",\n ndash: \"\\u2013\",\n quot: '\"',\n rdquo: \"\\u201d\",\n rsquo: \"\\u2019\",\n} as const;\n\nconst MAX_CODE_POINT = 1_114_111;\nconst EM_DASH = 8212;\nconst HEX_RADIX = 16;\nconst ENTITY_PATTERN = /&(?:#(?<decimal>\\d+)|#x(?<hex>[\\dA-F]+)|(?<named>[A-Z]+));/giv;\n\nconst isNamedEntity = (key: string): key is keyof typeof NAMED_ENTITIES =>\n Object.hasOwn(NAMED_ENTITIES, key);\n\nconst fromCodePoint = (codePoint: number, entity: string): string =>\n Number.isInteger(codePoint) && codePoint <= MAX_CODE_POINT && codePoint !== EM_DASH\n ? String.fromCodePoint(codePoint)\n : entity;\n\nconst decodeEntity = (entity: string, decimal?: string, hex?: string, named?: string): string => {\n if (decimal !== undefined) {\n return fromCodePoint(Number(decimal), entity);\n }\n if (hex !== undefined) {\n return fromCodePoint(Number.parseInt(hex, HEX_RADIX), entity);\n }\n if (named === undefined) {\n return entity;\n }\n const key = named.toLowerCase();\n if (!isNamedEntity(key)) {\n return entity;\n }\n return NAMED_ENTITIES[key];\n};\n\nconst categoryLabel = (name: string): string => name.replaceAll(ENTITY_PATTERN, decodeEntity);\n\nexport { categoryLabel };\n","const defaultOptions: Intl.DateTimeFormatOptions = {\n day: \"numeric\",\n month: \"long\",\n timeZone: \"UTC\",\n year: \"numeric\",\n};\n\nconst formatterCache = new Map<string, Intl.DateTimeFormat>();\n\nconst getFormatter = (key: string, locale: string, options: Intl.DateTimeFormatOptions) => {\n let formatter = formatterCache.get(key);\n if (!formatter) {\n formatter = new Intl.DateTimeFormat(locale, options);\n formatterCache.set(key, formatter);\n }\n return formatter;\n};\n\nconst formatDate = (date: Date, locale: string = \"en-US\", options?: Intl.DateTimeFormatOptions) => {\n if (!options) {\n return getFormatter(locale, locale, defaultOptions).format(date);\n }\n const merged = { ...defaultOptions, ...options };\n return getFormatter(`${locale}:${JSON.stringify(merged)}`, locale, merged).format(date);\n};\n\nexport { formatDate };\n","type HasTags = { data: { tags: Array<string> }; id: string };\n\nconst getRelatedPosts = <T extends HasTags>(current: T, all: Array<T>, n: number) => {\n const currentTagSet = new Set(current.data.tags);\n const scored: Array<{ post: T; score: number }> = [];\n\n for (const post of all) {\n if (post.id === current.id) {\n continue;\n }\n let score = 0;\n for (const tag of post.data.tags) {\n if (currentTagSet.has(tag)) {\n score++;\n }\n }\n scored.push({ post, score });\n }\n\n return scored\n .toSorted((x, y) => y.score - x.score)\n .slice(0, n)\n .map(({ post }) => post);\n};\n\nexport { getRelatedPosts };\n","const slugify = (input: string) =>\n input\n .normalize(\"NFD\")\n .replaceAll(/[̀-ͯ]/gv, \"\")\n .toLowerCase()\n .replaceAll(/[^a-z0-9\\s\\-]/gv, \"\")\n .trim()\n .replaceAll(/[\\s\\-]+/gv, \"-\")\n .replaceAll(/^-+|-+$/gv, \"\");\n\nexport { slugify };\n","import { slugify } from \"./slugify\";\n\ntype PostLike = {\n data: {\n categories?: Array<string>;\n seo?: { canonical_url?: string };\n };\n id: string;\n};\n\ntype PostParams = { category: string; slug: string };\n\ntype PostUrlBuilder = {\n postParams: (post: PostLike) => PostParams;\n postUrl: (post: PostLike) => string;\n};\n\nconst createPostUrl = (\n categorySlugMap: Record<string, string>,\n defaultCategory: string,\n): PostUrlBuilder => {\n const postParams = (post: PostLike): PostParams => {\n const canonical = post.data.seo?.canonical_url;\n if (canonical !== undefined && canonical !== \"\") {\n try {\n const segments = new URL(canonical).pathname.split(\"/\").filter(Boolean);\n const category = segments.at(-2);\n const slug = segments.at(-1);\n if (category !== undefined && slug !== undefined) {\n return { category, slug };\n }\n } catch {\n // Malformed canonical_url; fall through to category-derived logic.\n }\n }\n const first = post.data.categories?.at(0);\n const category =\n first !== undefined && first !== \"\"\n ? (categorySlugMap[first] ?? slugify(first))\n : defaultCategory;\n return { category, slug: post.id };\n };\n\n const postUrl = (post: PostLike): string => {\n const { category, slug } = postParams(post);\n return `/${category}/${slug}/`;\n };\n\n return { postParams, postUrl };\n};\n\nexport type { PostLike, PostParams, PostUrlBuilder };\nexport { createPostUrl };\n","const WORDS_PER_MINUTE = 200;\n\nconst readingTime = (input: string) => {\n const stripped = input\n .replaceAll(/<[^>]*>/gv, \"\")\n .replaceAll(/[#*_`>\\-]/gv, \" \")\n .replaceAll(/\\s+/gv, \" \")\n .trim();\n const words = stripped.length === 0 ? 0 : stripped.split(\" \").length;\n const minutes = Math.max(1, Math.ceil(words / WORDS_PER_MINUTE));\n return { minutes, words };\n};\n\nexport { readingTime };\n","const requireEnv = (name: string): string => {\n const value = process.env[name];\n if (value === undefined || value === \"\") {\n throw new Error(`Missing required env var: ${name}`);\n }\n return value;\n};\n\nexport { requireEnv };\n","import { slugify } from \"./slugify\";\n\nconst DEFAULT_TAG_BASE = \"/tag\";\n\nconst tagUrl = (tag: string, base: string = DEFAULT_TAG_BASE): string =>\n `${base.replace(/\\/+$/v, \"\")}/${slugify(tag)}/`;\n\nexport { DEFAULT_TAG_BASE, tagUrl };\n","export { cn } from \"./cn\";\nexport { categoryLabel } from \"./category-label\";\nexport { formatDate } from \"./format-date\";\nexport { getRelatedPosts } from \"./get-related-posts\";\nexport type { PostLike, PostParams, PostUrlBuilder } from \"./post-url\";\nexport { createPostUrl } from \"./post-url\";\nexport { readingTime } from \"./reading-time\";\nexport { requireEnv } from \"./require-env\";\nexport { slugify } from \"./slugify\";\nexport { DEFAULT_TAG_BASE, tagUrl } from \"./tag-url\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"lib-D7HdNeEs.js","names":[],"sources":["../src/lib/category-label.ts","../src/lib/format-date.ts","../src/lib/get-related-posts.ts","../src/lib/slugify.ts","../src/lib/post-url.ts","../src/lib/reading-time.ts","../src/lib/require-env.ts","../src/lib/tag-url.ts","../src/lib/index.ts"],"sourcesContent":["const NAMED_ENTITIES = {\n amp: \"&\",\n apos: \"'\",\n gt: \">\",\n hellip: \"\\u2026\",\n ldquo: \"\\u201c\",\n lsquo: \"\\u2018\",\n lt: \"<\",\n nbsp: \"\\u00a0\",\n ndash: \"\\u2013\",\n quot: '\"',\n rdquo: \"\\u201d\",\n rsquo: \"\\u2019\",\n} as const;\n\nconst MAX_CODE_POINT = 1_114_111;\nconst EM_DASH = 8212;\nconst HEX_RADIX = 16;\nconst ENTITY_PATTERN = /&(?:#(?<decimal>\\d+)|#x(?<hex>[\\dA-F]+)|(?<named>[A-Z]+));/giv;\n\nconst isNamedEntity = (key: string): key is keyof typeof NAMED_ENTITIES =>\n Object.hasOwn(NAMED_ENTITIES, key);\n\nconst fromCodePoint = (codePoint: number, entity: string): string =>\n Number.isInteger(codePoint) && codePoint <= MAX_CODE_POINT && codePoint !== EM_DASH\n ? String.fromCodePoint(codePoint)\n : entity;\n\nconst decodeEntity = (entity: string, decimal?: string, hex?: string, named?: string): string => {\n if (decimal !== undefined) {\n return fromCodePoint(Number(decimal), entity);\n }\n if (hex !== undefined) {\n return fromCodePoint(Number.parseInt(hex, HEX_RADIX), entity);\n }\n if (named === undefined) {\n return entity;\n }\n const key = named.toLowerCase();\n if (!isNamedEntity(key)) {\n return entity;\n }\n return NAMED_ENTITIES[key];\n};\n\nconst categoryLabel = (name: string): string => name.replaceAll(ENTITY_PATTERN, decodeEntity);\n\nexport { categoryLabel };\n","const defaultOptions: Intl.DateTimeFormatOptions = {\n day: \"numeric\",\n month: \"long\",\n timeZone: \"UTC\",\n year: \"numeric\",\n};\n\nconst formatterCache = new Map<string, Intl.DateTimeFormat>();\n\nconst getFormatter = (key: string, locale: string, options: Intl.DateTimeFormatOptions) => {\n let formatter = formatterCache.get(key);\n if (!formatter) {\n formatter = new Intl.DateTimeFormat(locale, options);\n formatterCache.set(key, formatter);\n }\n return formatter;\n};\n\nconst formatDate = (date: Date, locale: string = \"en-US\", options?: Intl.DateTimeFormatOptions) => {\n if (!options) {\n return getFormatter(locale, locale, defaultOptions).format(date);\n }\n const merged = { ...defaultOptions, ...options };\n return getFormatter(`${locale}:${JSON.stringify(merged)}`, locale, merged).format(date);\n};\n\nexport { formatDate };\n","type HasTags = { data: { tags: Array<string> }; id: string };\n\nconst getRelatedPosts = <T extends HasTags>(current: T, all: Array<T>, n: number) => {\n const currentTagSet = new Set(current.data.tags);\n const scored: Array<{ post: T; score: number }> = [];\n\n for (const post of all) {\n if (post.id === current.id) {\n continue;\n }\n let score = 0;\n for (const tag of post.data.tags) {\n if (currentTagSet.has(tag)) {\n score++;\n }\n }\n scored.push({ post, score });\n }\n\n return scored\n .toSorted((x, y) => y.score - x.score)\n .slice(0, n)\n .map(({ post }) => post);\n};\n\nexport { getRelatedPosts };\n","const slugify = (input: string) =>\n input\n .normalize(\"NFD\")\n .replaceAll(/[̀-ͯ]/gv, \"\")\n .toLowerCase()\n .replaceAll(/[^a-z0-9\\s\\-]/gv, \"\")\n .trim()\n .replaceAll(/[\\s\\-]+/gv, \"-\")\n .replaceAll(/^-+|-+$/gv, \"\");\n\nexport { slugify };\n","import { slugify } from \"./slugify\";\n\ntype PostLike = {\n data: {\n categories?: Array<string>;\n seo?: { canonical_url?: string };\n };\n id: string;\n};\n\ntype PostParams = { category: string; slug: string };\n\ntype PostUrlBuilder = {\n postParams: (post: PostLike) => PostParams;\n postUrl: (post: PostLike) => string;\n};\n\nconst createPostUrl = (\n categorySlugMap: Record<string, string>,\n defaultCategory: string,\n): PostUrlBuilder => {\n const postParams = (post: PostLike): PostParams => {\n const canonical = post.data.seo?.canonical_url;\n if (canonical !== undefined && canonical !== \"\") {\n try {\n const segments = new URL(canonical).pathname.split(\"/\").filter(Boolean);\n const category = segments.at(-2);\n const slug = segments.at(-1);\n if (category !== undefined && slug !== undefined) {\n return { category, slug };\n }\n } catch {\n // Malformed canonical_url; fall through to category-derived logic.\n }\n }\n const first = post.data.categories?.at(0);\n const category =\n first !== undefined && first !== \"\"\n ? (categorySlugMap[first] ?? slugify(first))\n : defaultCategory;\n return { category, slug: post.id };\n };\n\n const postUrl = (post: PostLike): string => {\n const { category, slug } = postParams(post);\n return `/${category}/${slug}/`;\n };\n\n return { postParams, postUrl };\n};\n\nexport type { PostLike, PostParams, PostUrlBuilder };\nexport { createPostUrl };\n","const WORDS_PER_MINUTE = 200;\n\nconst readingTime = (input: string) => {\n const stripped = input\n .replaceAll(/<[^>]*>/gv, \"\")\n .replaceAll(/[#*_`>\\-]/gv, \" \")\n .replaceAll(/\\s+/gv, \" \")\n .trim();\n const words = stripped.length === 0 ? 0 : stripped.split(\" \").length;\n const minutes = Math.max(1, Math.ceil(words / WORDS_PER_MINUTE));\n return { minutes, words };\n};\n\nexport { readingTime };\n","const requireEnv = (name: string): string => {\n const value = process.env[name];\n if (value === undefined || value === \"\") {\n throw new Error(`Missing required env var: ${name}`);\n }\n return value;\n};\n\nexport { requireEnv };\n","import { slugify } from \"./slugify\";\n\nconst DEFAULT_TAG_BASE = \"/tag\";\n\nconst tagUrl = (tag: string, base: string = DEFAULT_TAG_BASE): string =>\n `${base.replace(/\\/+$/v, \"\")}/${slugify(tag)}/`;\n\nexport { DEFAULT_TAG_BASE, tagUrl };\n","export { cn } from \"./cn\";\nexport { categoryLabel } from \"./category-label\";\nexport { formatDate } from \"./format-date\";\nexport { getRelatedPosts } from \"./get-related-posts\";\nexport type { PostLike, PostParams, PostUrlBuilder } from \"./post-url\";\nexport { createPostUrl } from \"./post-url\";\nexport { readingTime } from \"./reading-time\";\nexport { requireEnv } from \"./require-env\";\nexport { slugify } from \"./slugify\";\nexport { DEFAULT_TAG_BASE, tagUrl } from \"./tag-url\";\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-awesomeness",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Astro 6/7 blog theme with shadcn primitives and a Tailwind v4 preset.",
5
5
  "keywords": [
6
6
  "astro",
@@ -54,22 +54,22 @@
54
54
  "dependencies": {
55
55
  "@base-ui/react": "^1.6.0",
56
56
  "class-variance-authority": "^0.7.1",
57
- "cnfast": "^0.1.0",
58
- "lucide-react": "^1.31.0",
57
+ "cn": "^0.2.4",
58
+ "lucide-react": "^1.40.0",
59
59
  "tw-animate-css": "^1.4.0",
60
- "zod": "^4.4.3"
60
+ "zod": "^4.5.4"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@tailwindcss/postcss": "^4.3.2",
64
- "@types/node": "^26.2.0",
64
+ "@types/node": "^26.4.1",
65
65
  "@types/react": "^19.2.17",
66
- "@types/react-dom": "^19.2.3",
67
- "@vitest/coverage-v8": "^4.1.10",
66
+ "@types/react-dom": "^19.2.5",
67
+ "@vitest/coverage-v8": "^4.1.11",
68
68
  "tailwindcss": "^4.3.2",
69
69
  "typescript": "^7.0.2",
70
- "vitest": "^4.1.10",
71
- "@repo/typescript-config": "0.0.0",
72
- "@repo/config-vitest": "0.0.0"
70
+ "vitest": "^4.1.11",
71
+ "@repo/config-vitest": "0.0.0",
72
+ "@repo/typescript-config": "0.0.0"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "astro": "^6.0.0 || ^7.0.0",
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import type { Author } from "../content";
3
+ import { cn } from "../lib/cn";
3
4
 
4
5
  type Props = {
5
6
  author: Author;
@@ -8,7 +9,7 @@ type Props = {
8
9
 
9
10
  const { author, class: className = "" } = Astro.props;
10
11
  ---
11
- <div class:list={["flex items-center gap-2", className]}>
12
+ <div class={cn("flex items-center gap-2", className)}>
12
13
  {author.photoUrl && (
13
14
  <img
14
15
  src={author.photoUrl}
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import type { Author } from "../content";
3
+ import { cn } from "../lib/cn";
3
4
 
4
5
  type Props = {
5
6
  author: Author;
@@ -8,7 +9,7 @@ type Props = {
8
9
 
9
10
  const { author, class: className = "" } = Astro.props;
10
11
  ---
11
- <aside class:list={["border-border bg-muted/50 flex gap-4 rounded-lg border p-4", className]}>
12
+ <aside class={cn("border-border bg-muted/50 flex gap-4 rounded-lg border p-4", className)}>
12
13
  {author.photoUrl && (
13
14
  <img
14
15
  src={author.photoUrl}
@@ -1,14 +1,15 @@
1
1
  ---
2
2
  import { Code } from "astro:components";
3
+ import { cn } from "../lib/cn";
3
4
 
4
5
  type Props = {
6
+ class?: string;
5
7
  code: string;
6
8
  lang?: string;
7
- class?: string;
8
9
  };
9
10
 
10
- const { code, lang = "ts", class: className = "" } = Astro.props;
11
+ const { class: className = "", code, lang = "ts" } = Astro.props;
11
12
  ---
12
- <div class:list={["bg-muted border-border overflow-hidden rounded-md border", className]}>
13
+ <div class={cn("bg-muted border-border overflow-hidden rounded-md border", className)}>
13
14
  <Code code={code} lang={lang} theme="github-dark" />
14
15
  </div>
@@ -1,13 +1,15 @@
1
1
  ---
2
+ import { cn } from "../lib/cn";
3
+
2
4
  type Props = {
3
- siteTitle: string;
4
5
  class?: string;
6
+ siteTitle: string;
5
7
  };
6
8
 
7
- const { siteTitle, class: className = "" } = Astro.props;
9
+ const { class: className = "", siteTitle } = Astro.props;
8
10
  const year = new Date().getFullYear();
9
11
  ---
10
- <footer class:list={["border-border text-muted-foreground mt-16 border-t py-6 text-sm", className]}>
12
+ <footer class={cn("border-border text-muted-foreground mt-16 border-t py-6 text-sm", className)}>
11
13
  <div class="mx-auto flex max-w-5xl flex-col items-center justify-between gap-2 px-5 sm:flex-row sm:px-8">
12
14
  <p>© {year} {siteTitle}</p>
13
15
  <slot name="links" />
@@ -2,12 +2,12 @@
2
2
  import { formatDate } from "../lib/format-date";
3
3
 
4
4
  type Props = {
5
+ class?: string;
5
6
  date: Date;
6
7
  locale?: string;
7
- class?: string;
8
8
  };
9
9
 
10
- const { date, locale = "en-US", class: className = "" } = Astro.props;
10
+ const { class: className = "", date, locale = "en-US" } = Astro.props;
11
11
  const iso = date.toISOString();
12
12
  const formatted = formatDate(date, locale);
13
13
  ---
@@ -1,23 +1,24 @@
1
1
  ---
2
2
  import { ThemeToggle } from "../components/theme-toggle";
3
+ import { cn } from "../lib/cn";
3
4
 
4
5
  type Props = {
5
- siteTitle: string;
6
- homeHref?: string;
7
6
  class?: string;
8
- themeToggleLabel?: string;
7
+ homeHref?: string;
9
8
  showThemeToggle?: boolean;
9
+ siteTitle: string;
10
+ themeToggleLabel?: string;
10
11
  };
11
12
 
12
13
  const {
13
- siteTitle,
14
- homeHref = "/",
15
14
  class: className = "",
16
- themeToggleLabel = "Toggle theme",
15
+ homeHref = "/",
17
16
  showThemeToggle = true,
17
+ siteTitle,
18
+ themeToggleLabel = "Toggle theme",
18
19
  } = Astro.props;
19
20
  ---
20
- <header class:list={["border-border bg-background/80 sticky top-0 z-40 border-b backdrop-blur", className]}>
21
+ <header class={cn("border-border bg-background/80 sticky top-0 z-40 border-b backdrop-blur", className)}>
21
22
  <div class="mx-auto flex max-w-5xl items-center justify-between px-5 py-4 sm:px-8">
22
23
  <a href={homeHref} class="text-foreground font-serif text-lg font-semibold tracking-tight">
23
24
  <slot name="brand">{siteTitle}</slot>
@@ -1,29 +1,31 @@
1
1
  ---
2
+ import { cn } from "../lib/cn";
3
+
2
4
  type Props = {
5
+ class?: string;
3
6
  currentPage: number;
4
7
  lastPage: number;
5
- urlForPage: (page: number) => string;
6
- class?: string;
7
- prevLabel?: string;
8
8
  nextLabel?: string;
9
- pageLabel?: string;
10
9
  ofLabel?: string;
10
+ pageLabel?: string;
11
+ prevLabel?: string;
12
+ urlForPage: (page: number) => string;
11
13
  };
12
14
 
13
15
  const {
16
+ class: className = "",
14
17
  currentPage,
15
18
  lastPage,
16
- urlForPage,
17
- class: className = "",
18
- prevLabel = "← Previous",
19
19
  nextLabel = "Next →",
20
- pageLabel = "Page",
21
20
  ofLabel = "of",
21
+ pageLabel = "Page",
22
+ prevLabel = "← Previous",
23
+ urlForPage,
22
24
  } = Astro.props;
23
25
  const hasPrev = currentPage > 1;
24
26
  const hasNext = currentPage < lastPage;
25
27
  ---
26
- <nav class:list={["mt-8 flex items-center justify-between", className]} aria-label="Pagination">
28
+ <nav class={cn("mt-8 flex items-center justify-between", className)} aria-label="Pagination">
27
29
  {hasPrev ? (
28
30
  <a
29
31
  href={urlForPage(currentPage - 1)}
@@ -4,15 +4,15 @@ import type { Post } from "../content/index";
4
4
  import FormattedDate from "./formatted-date.astro";
5
5
  import TagList from "./tag-list.astro";
6
6
 
7
- type PostEntry = { id: string; data: Post };
7
+ type PostEntry = { data: Post; id: string };
8
8
  type Props = {
9
- post: PostEntry;
10
9
  locale?: string;
10
+ post: PostEntry;
11
11
  postHref?: (post: PostEntry) => string;
12
12
  };
13
13
 
14
- const { post, locale, postHref } = Astro.props;
15
- const { title, description, pubDate, tags } = post.data;
14
+ const { locale, post, postHref } = Astro.props;
15
+ const { description, pubDate, tags, title } = post.data;
16
16
  const href = postHref ? postHref(post) : `/blog/${post.id}`;
17
17
  ---
18
18
  <article class="post-card border-border group border-b py-6 last:border-0">
@@ -1,10 +1,12 @@
1
1
  ---
2
+ import { cn } from "../lib/cn";
3
+
2
4
  type Props = {
3
5
  class?: string;
4
6
  };
5
7
 
6
8
  const { class: className = "" } = Astro.props;
7
9
  ---
8
- <div class:list={["prose", className]}>
10
+ <div class={cn("prose", className)}>
9
11
  <slot />
10
12
  </div>
@@ -2,12 +2,12 @@
2
2
  import { readingTime } from "../lib/reading-time";
3
3
 
4
4
  type Props = {
5
- text: string;
6
- label?: string;
7
5
  class?: string;
6
+ label?: string;
7
+ text: string;
8
8
  };
9
9
 
10
- const { text, label = "min read", class: className = "" } = Astro.props;
10
+ const { class: className = "", label = "min read", text } = Astro.props;
11
11
  const { minutes } = readingTime(text);
12
12
  ---
13
13
  <span class={className}>{minutes} {label}</span>
@@ -1,28 +1,28 @@
1
1
  ---
2
2
  type Props = {
3
- title: string;
4
- description: string;
3
+ authorName?: string;
5
4
  canonical?: string;
5
+ description: string;
6
6
  image?: string;
7
- type?: "website" | "article";
8
- siteName?: string;
9
7
  locale?: string;
10
- publishedTime?: Date;
11
8
  modifiedTime?: Date;
12
- authorName?: string;
9
+ publishedTime?: Date;
10
+ siteName?: string;
11
+ title: string;
12
+ type?: "website" | "article";
13
13
  };
14
14
 
15
15
  const {
16
- title,
17
- description,
16
+ authorName,
18
17
  canonical,
18
+ description,
19
19
  image,
20
- type = "website",
21
- siteName,
22
20
  locale = "en_US",
23
- publishedTime,
24
21
  modifiedTime,
25
- authorName,
22
+ publishedTime,
23
+ siteName,
24
+ title,
25
+ type = "website",
26
26
  } = Astro.props;
27
27
  const url = canonical ?? new URL(Astro.url.pathname, Astro.site ?? Astro.url.origin).toString();
28
28
  ---
@@ -1,34 +1,37 @@
1
1
  ---
2
2
  import { slugify } from "../lib/slugify";
3
+ import { cn } from "../lib/cn";
3
4
 
4
- type Heading = { depth: number; text: string; slug: string };
5
+ type Heading = { depth: number; slug: string; text: string };
5
6
 
6
7
  type Props = {
7
- headings: Array<{ depth: number; text: string; slug?: string }>;
8
- minDepth?: number;
9
- maxDepth?: number;
10
8
  class?: string;
11
9
  heading?: string;
10
+ headings: Array<{ depth: number; slug?: string; text: string }>;
11
+ maxDepth?: number;
12
+ minDepth?: number;
12
13
  };
13
14
 
14
15
  const {
15
- headings,
16
- minDepth = 2,
17
- maxDepth = 3,
18
16
  class: className = "",
19
17
  heading = "On this page",
18
+ headings,
19
+ maxDepth = 3,
20
+ minDepth = 2,
20
21
  } = Astro.props;
21
22
 
22
- const visible: Array<Heading> = headings
23
- .filter((h) => h.depth >= minDepth && h.depth <= maxDepth)
24
- .map((h) => ({ depth: h.depth, text: h.text, slug: h.slug ?? slugify(h.text) }));
23
+ const visible: Array<Heading> = headings.flatMap((h) =>
24
+ h.depth >= minDepth && h.depth <= maxDepth
25
+ ? [{ depth: h.depth, slug: h.slug ?? slugify(h.text), text: h.text }]
26
+ : [],
27
+ );
25
28
  ---
26
29
  {visible.length > 0 && (
27
- <nav class:list={["text-sm", className]} aria-label="Table of contents">
30
+ <nav class={cn("text-sm", className)} aria-label="Table of contents">
28
31
  <p class="text-muted-foreground mb-2 font-medium tracking-wide uppercase">{heading}</p>
29
32
  <ul class="space-y-1">
30
33
  {visible.map((item) => (
31
- <li class:list={["leading-snug", item.depth === 3 && "pl-4"]}>
34
+ <li class={cn("leading-snug", item.depth === 3 && "pl-4")}>
32
35
  <a
33
36
  href={`#${item.slug}`}
34
37
  class="text-muted-foreground hover:text-foreground block transition-colors"
@@ -1,15 +1,16 @@
1
1
  ---
2
2
  import { DEFAULT_TAG_BASE, tagUrl } from "../lib/tag-url";
3
+ import { cn } from "../lib/cn";
3
4
 
4
5
  type Props = {
5
- tags: Array<string>;
6
6
  base?: string;
7
7
  class?: string;
8
+ tags: Array<string>;
8
9
  };
9
10
 
10
- const { tags, base = DEFAULT_TAG_BASE, class: className = "" } = Astro.props;
11
+ const { base = DEFAULT_TAG_BASE, class: className = "", tags } = Astro.props;
11
12
  ---
12
- <ul class:list={["flex flex-wrap gap-2", className]}>
13
+ <ul class={cn("flex flex-wrap gap-2", className)}>
13
14
  {tags.map((tag) => (
14
15
  <li>
15
16
  <a
@@ -2,47 +2,48 @@
2
2
  import Seo from "../astro/seo.astro";
3
3
 
4
4
  type Props = {
5
- title: string;
6
- description: string;
5
+ authorName?: string;
7
6
  canonical?: string;
7
+ colorScheme?: "auto" | "light" | "dark";
8
+ description: string;
8
9
  image?: string;
9
- type?: "website" | "article";
10
10
  lang?: string;
11
- siteTitle?: string;
12
- rssHref?: string;
13
- siteName?: string;
14
11
  locale?: string;
15
- publishedTime?: Date;
16
12
  modifiedTime?: Date;
17
- authorName?: string;
18
- colorScheme?: "auto" | "light" | "dark";
13
+ publishedTime?: Date;
14
+ rssHref?: string;
15
+ siteName?: string;
16
+ siteTitle?: string;
17
+ title: string;
18
+ type?: "website" | "article";
19
19
  };
20
20
 
21
21
  const {
22
- title,
23
- description,
22
+ authorName,
24
23
  canonical,
24
+ colorScheme = "auto",
25
+ description,
25
26
  image,
26
- type = "website",
27
27
  lang = "en",
28
- siteTitle,
29
- rssHref,
30
- siteName,
31
28
  locale,
32
- publishedTime,
33
29
  modifiedTime,
34
- authorName,
35
- colorScheme = "auto",
30
+ publishedTime,
31
+ rssHref,
32
+ siteName,
33
+ siteTitle,
34
+ title,
35
+ type = "website",
36
36
  } = Astro.props;
37
37
 
38
- const colorSchemeScript = colorScheme === "auto"
39
- ? `(() => {
38
+ const colorSchemeScript =
39
+ colorScheme === "auto"
40
+ ? `(() => {
40
41
  const stored = localStorage.getItem("theme");
41
42
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
42
43
  const theme = stored === "dark" || stored === "light" ? stored : prefersDark ? "dark" : "light";
43
44
  document.documentElement.classList.toggle("dark", theme === "dark");
44
45
  })();`
45
- : `document.documentElement.classList.toggle("dark", ${colorScheme === "dark"});`;
46
+ : `document.documentElement.classList.toggle("dark", ${colorScheme === "dark"});`;
46
47
  ---
47
48
  <!doctype html>
48
49
  <html lang={lang}>
@@ -7,22 +7,32 @@ import Header from "../astro/header.astro";
7
7
  import PostCard from "../astro/post-card.astro";
8
8
  import Pagination from "../astro/pagination.astro";
9
9
 
10
- type PostEntry = { id: string; data: Post };
10
+ type PostEntry = { data: Post; id: string };
11
11
  type Props = {
12
- title: string;
13
12
  description: string;
14
13
  eyebrow?: string;
15
- posts: Array<PostEntry>;
16
- page?: { currentPage: number; lastPage: number; url: { prev?: string; next?: string } };
17
- urlForPage?: (page: number) => string;
18
14
  locale?: string;
19
- siteTitle?: string;
20
- rssHref?: string;
15
+ page?: { currentPage: number; lastPage: number; url: { next?: string; prev?: string } };
21
16
  postHref?: (post: PostEntry) => string;
17
+ posts: Array<PostEntry>;
18
+ rssHref?: string;
19
+ siteTitle?: string;
20
+ title: string;
21
+ urlForPage?: (page: number) => string;
22
22
  };
23
23
 
24
- const { title, description, eyebrow, posts, page, urlForPage, locale, siteTitle, rssHref, postHref } =
25
- Astro.props;
24
+ const {
25
+ description,
26
+ eyebrow,
27
+ locale,
28
+ page,
29
+ postHref,
30
+ posts,
31
+ rssHref,
32
+ siteTitle,
33
+ title,
34
+ urlForPage,
35
+ } = Astro.props;
26
36
  ---
27
37
  <BaseLayout title={title} description={description} siteTitle={siteTitle} rssHref={rssHref}>
28
38
  <Fragment slot="header">{siteTitle && <Header siteTitle={siteTitle} />}</Fragment>
@@ -11,31 +11,31 @@ import Prose from "../astro/prose.astro";
11
11
  import TableOfContents from "../astro/table-of-contents.astro";
12
12
  import PostCard from "../astro/post-card.astro";
13
13
 
14
- type PostEntry = { id: string; data: Post };
14
+ type PostEntry = { data: Post; id: string };
15
15
  type Props = {
16
- post: { id: string; data: Post; body?: string };
16
+ headings?: Array<{ depth: number; slug?: string; text: string }>;
17
17
  locale?: string;
18
+ post: { body?: string; data: Post; id: string };
19
+ postHref?: (post: PostEntry) => string;
20
+ relatedHeading?: string;
21
+ relatedPosts?: Array<PostEntry>;
22
+ rssHref?: string;
18
23
  siteTitle?: string;
19
24
  updatedLabel?: string;
20
- rssHref?: string;
21
- headings?: Array<{ depth: number; text: string; slug?: string }>;
22
- relatedPosts?: Array<PostEntry>;
23
- relatedHeading?: string;
24
- postHref?: (post: PostEntry) => string;
25
25
  };
26
26
 
27
27
  const {
28
- post,
28
+ headings,
29
29
  locale,
30
+ post,
31
+ postHref,
32
+ relatedHeading = "Related posts",
33
+ relatedPosts,
34
+ rssHref,
30
35
  siteTitle,
31
36
  updatedLabel = "Updated",
32
- rssHref,
33
- headings,
34
- relatedPosts,
35
- relatedHeading = "Related posts",
36
- postHref,
37
37
  } = Astro.props;
38
- const { title, description, pubDate, updatedDate, tags } = post.data;
38
+ const { description, pubDate, tags, title, updatedDate } = post.data;
39
39
  ---
40
40
  <BaseLayout
41
41
  title={title}
package/src/lib/cn.ts CHANGED
@@ -1 +1 @@
1
- export { cn } from "cnfast";
1
+ export { cn } from "cn";
@@ -1,3 +0,0 @@
1
- import { cn } from "cnfast";
2
-
3
- export { cn as t };