@nifrajs/content 2.1.0 → 2.3.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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # @nifrajs/content
2
2
 
3
- Typed, schema-validated content collections for nifra — Markdown + frontmatter, framework-agnostic.
3
+ Typed, schema-validated content collections for nifra - Markdown + frontmatter, framework-agnostic.
4
4
 
5
- Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework — one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
5
+ Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework - one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
6
6
 
7
7
  ## Install
8
8
 
@@ -19,7 +19,7 @@ MIT
19
19
 
20
20
  ## For AI agents
21
21
 
22
- Start with [`LLM.md`](./LLM.md) — this package's contract card (the exports you call + its footguns),
22
+ Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
23
23
  one cheap read instead of the whole corpus. For the wider framework: the repo's
24
24
  [`AGENTS.md`](../../AGENTS.md) is the copy-paste quick reference, and
25
25
  [`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nifrajs/content",
3
- "version": "2.1.0",
4
- "description": "Typed, schema-validated content collections for nifra — Markdown + frontmatter, framework-agnostic.",
3
+ "version": "2.3.0",
4
+ "description": "Typed, schema-validated content collections for nifra - Markdown + frontmatter, framework-agnostic.",
5
5
  "keywords": [
6
6
  "bun",
7
7
  "typescript",
package/src/fs.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Filesystem-backed content collections — `defineCollection` reads a directory of Markdown files and
2
+ * Filesystem-backed content collections - `defineCollection` reads a directory of Markdown files and
3
3
  * gives you a typed, validated API over them. Build/server-time (Bun/Node/Deno); for the edge, bake the
4
- * entries at build (the manifest approach `@nifrajs/web/fs` uses for routes) — tracked as a follow-up.
4
+ * entries at build (the manifest approach `@nifrajs/web/fs` uses for routes) - tracked as a follow-up.
5
5
  */
6
6
  import { readdirSync, readFileSync, statSync } from "node:fs"
7
7
  import { resolve, sep } from "node:path"
@@ -18,7 +18,7 @@ export interface CollectionConfig<S extends StandardSchemaV1> {
18
18
 
19
19
  /** A typed collection over a content directory. */
20
20
  export interface Collection<Frontmatter> {
21
- /** Every entry in the directory (unordered — sort/filter in your loader). Throws if any file's
21
+ /** Every entry in the directory (unordered - sort/filter in your loader). Throws if any file's
22
22
  * frontmatter is invalid. */
23
23
  all(): Promise<Array<Entry<Frontmatter>>>
24
24
  /** One entry by slug (filename without extension), or `null` if not found. */
@@ -66,7 +66,7 @@ interface CollectionSnapshot<Frontmatter> {
66
66
  /**
67
67
  * Define a content collection backed by a directory. `all()` discovers + parses every matching file;
68
68
  * `get(slug)` loads one. Frontmatter is validated against `schema`, so entries are fully typed and a
69
- * malformed file fails loudly. Reads the filesystem — use it at build time (SSG/prerender) or on a
69
+ * malformed file fails loudly. Reads the filesystem - use it at build time (SSG/prerender) or on a
70
70
  * long-lived server (Bun/Node/Deno).
71
71
  */
72
72
  export function defineCollection<S extends StandardSchemaV1>(
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Typed content collections for nifra — the **framework-agnostic core**. Parse a Markdown file's
2
+ * Typed content collections for nifra - the **framework-agnostic core**. Parse a Markdown file's
3
3
  * frontmatter + body, validate the frontmatter against a Standard Schema (`@nifrajs/schema`'s `t`, zod,
4
- * valibot), and render the body to HTML. Pure (no filesystem, no DOM) so it runs anywhere — pair it
4
+ * valibot), and render the body to HTML. Pure (no filesystem, no DOM) so it runs anywhere - pair it
5
5
  * with `@nifrajs/content/fs`'s `defineCollection` for fs-backed discovery on Bun/Node/Deno + at build.
6
6
  *
7
7
  * import { t } from "@nifrajs/schema"
@@ -12,7 +12,7 @@
12
12
  * schema: t.object({ title: t.string(), date: t.string(), draft: t.boolean() }),
13
13
  * })
14
14
  *
15
- * // in a loader — typed + validated entries, no manual fs/frontmatter parsing:
15
+ * // in a loader - typed + validated entries, no manual fs/frontmatter parsing:
16
16
  * const posts = (await blog.all()).filter((p) => !p.frontmatter.draft)
17
17
  * // posts[0].frontmatter is { title: string; date: string; draft: boolean }
18
18
  * // posts[0].html is the rendered Markdown
@@ -26,7 +26,7 @@ interface StandardIssue {
26
26
  }
27
27
 
28
28
  /**
29
- * Minimal [Standard Schema](https://standardschema.dev) shape — lets frontmatter validate against any
29
+ * Minimal [Standard Schema](https://standardschema.dev) shape - lets frontmatter validate against any
30
30
  * compliant validator (`@nifrajs/schema`'s `t`, zod, valibot, …) without coupling `@nifrajs/content` to one.
31
31
  */
32
32
  export interface StandardSchemaV1<Output = unknown> {
@@ -73,14 +73,14 @@ export function parseFrontmatter(raw: string): { data: unknown; body: string } {
73
73
  export interface ParseEntryOptions<S extends StandardSchemaV1> {
74
74
  readonly raw: string
75
75
  readonly slug: string
76
- /** Standard Schema validating the frontmatter — a typo'd/missing field throws (a build-time failure,
76
+ /** Standard Schema validating the frontmatter - a typo'd/missing field throws (a build-time failure,
77
77
  * never a broken page). */
78
78
  readonly schema: S
79
79
  }
80
80
 
81
81
  /**
82
82
  * Parse one content file: split + validate its frontmatter against `schema`, render its Markdown body
83
- * to HTML. Throws a descriptive error (naming the slug + the issues) when the frontmatter is invalid —
83
+ * to HTML. Throws a descriptive error (naming the slug + the issues) when the frontmatter is invalid -
84
84
  * surface it at build/load time rather than shipping a malformed entry. Pure + edge-safe.
85
85
  */
86
86
  export async function parseEntry<S extends StandardSchemaV1>(
@@ -92,7 +92,7 @@ export async function parseEntry<S extends StandardSchemaV1>(
92
92
  const detail = result.issues.map((issue) => issue.message).join("; ")
93
93
  throw new Error(`@nifrajs/content: invalid frontmatter in "${options.slug}": ${detail}`)
94
94
  }
95
- // `marked.parse` is sync by default but may be async with extensions — await covers both. Content is
95
+ // `marked.parse` is sync by default but may be async with extensions - await covers both. Content is
96
96
  // author-controlled (your own files), so raw HTML in Markdown is passed through (standard SSG
97
97
  // behavior); sanitize yourself if a collection ever holds untrusted input.
98
98
  const html = await marked.parse(body)
@@ -100,7 +100,7 @@ export async function parseEntry<S extends StandardSchemaV1>(
100
100
  }
101
101
 
102
102
  /**
103
- * A content collection baked to plain data — fs-free, so it works at the **edge** (Workers
103
+ * A content collection baked to plain data - fs-free, so it works at the **edge** (Workers
104
104
  * request-time) where `defineCollection`'s `node:fs` reader can't run. Produce one at build/server time
105
105
  * with `bakeCollection`, JSON-serialize + ship it in the bundle, then rehydrate with `fromBaked`.
106
106
  */
@@ -108,7 +108,7 @@ export interface BakedCollection<Frontmatter> {
108
108
  readonly entries: ReadonlyArray<Entry<Frontmatter>>
109
109
  }
110
110
 
111
- /** Read-only collection surface (`all()`/`get()`) — structurally compatible with `defineCollection`'s
111
+ /** Read-only collection surface (`all()`/`get()`) - structurally compatible with `defineCollection`'s
112
112
  * `Collection`, but with no filesystem access. */
113
113
  export interface StaticCollection<Frontmatter> {
114
114
  all(): Promise<ReadonlyArray<Entry<Frontmatter>>>
@@ -118,7 +118,7 @@ export interface StaticCollection<Frontmatter> {
118
118
  /**
119
119
  * Bake a collection's entries to serializable data at build/server time. The collection does the
120
120
  * filesystem read + validation (via `all()`); this just collects the already-parsed result so it can be
121
- * JSON-serialized into the edge bundle. Pure — safe to import anywhere.
121
+ * JSON-serialized into the edge bundle. Pure - safe to import anywhere.
122
122
  */
123
123
  export async function bakeCollection<Frontmatter>(collection: {
124
124
  all(): Promise<ReadonlyArray<Entry<Frontmatter>>>
@@ -127,7 +127,7 @@ export async function bakeCollection<Frontmatter>(collection: {
127
127
  }
128
128
 
129
129
  /**
130
- * Rehydrate a baked collection into a read-only `all()`/`get()` collection — fs-free, edge-safe. The
130
+ * Rehydrate a baked collection into a read-only `all()`/`get()` collection - fs-free, edge-safe. The
131
131
  * entries were validated when baked (build output, trusted), so they're served as-is. `get` is O(1).
132
132
  */
133
133
  export function fromBaked<Frontmatter>(
package/src/mdx.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `mdxBunPlugin` — a `Bun.build` plugin that compiles `.mdx` files (Markdown + JSX components) into
2
+ * `mdxBunPlugin` - a `Bun.build` plugin that compiles `.mdx` files (Markdown + JSX components) into
3
3
  * components for your UI framework, so an `.mdx` file can be a nifra route or be imported like a module.
4
4
  * Pass it to `buildClient`/`buildServer`'s `plugins`, and add `.mdx` to your route discovery.
5
5
  *
@@ -13,22 +13,22 @@
13
13
  * })
14
14
  *
15
15
  * MDX is JSX-oriented, so this targets the JSX family (React/Preact/Solid) via `jsxImportSource`. Needs
16
- * `@mdx-js/mdx` installed (an optional peer — lazy-loaded at build time only).
16
+ * `@mdx-js/mdx` installed (an optional peer - lazy-loaded at build time only).
17
17
  */
18
18
  import type { BunPlugin } from "bun"
19
19
 
20
20
  export interface MdxPluginOptions {
21
- /** JSX runtime source the compiled MDX imports from — `"react"` (default), `"preact"`, `"solid-js"`. */
21
+ /** JSX runtime source the compiled MDX imports from - `"react"` (default), `"preact"`, `"solid-js"`. */
22
22
  readonly jsxImportSource?: string
23
23
  /** Emit development JSX (line numbers, `jsxDEV`). Default `false`. */
24
24
  readonly development?: boolean
25
- /** Extra `@mdx-js/mdx` `compile` options — e.g. `remarkPlugins`/`rehypePlugins` (GFM, slugs, …). */
25
+ /** Extra `@mdx-js/mdx` `compile` options - e.g. `remarkPlugins`/`rehypePlugins` (GFM, slugs, …). */
26
26
  readonly compileOptions?: Record<string, unknown>
27
- /** Advanced: override the compiler module specifier (default `"@mdx-js/mdx"`) — e.g. to use a fork. */
27
+ /** Advanced: override the compiler module specifier (default `"@mdx-js/mdx"`) - e.g. to use a fork. */
28
28
  readonly moduleName?: string
29
29
  }
30
30
 
31
- // Non-literal specifier so tsc/consumers don't need `@mdx-js/mdx`'s types to typecheck this file — it's
31
+ // Non-literal specifier so tsc/consumers don't need `@mdx-js/mdx`'s types to typecheck this file - it's
32
32
  // an optional peer, imported only when the plugin actually runs (mirrors `@nifrajs/node`'s lazy `ws`).
33
33
  const MDX_MODULE = "@mdx-js/mdx"
34
34
 
@@ -53,10 +53,10 @@ export function mdxBunPlugin(options: MdxPluginOptions = {}): BunPlugin {
53
53
  compile = mod.compile
54
54
  } catch {
55
55
  throw new Error(
56
- "@nifrajs/content/mdx: compiling `.mdx` needs the `@mdx-js/mdx` package — install it (`bun add @mdx-js/mdx`).",
56
+ "@nifrajs/content/mdx: compiling `.mdx` needs the `@mdx-js/mdx` package - install it (`bun add @mdx-js/mdx`).",
57
57
  )
58
58
  }
59
- // Tolerate a `?query` suffix — `nifra dev` (Vite) appends an import-cache-busting query so edited
59
+ // Tolerate a `?query` suffix - `nifra dev` (Vite) appends an import-cache-busting query so edited
60
60
  // `.mdx` re-SSR; strip it before reading off disk.
61
61
  build.onLoad({ filter: /\.mdx(\?|$)/ }, async (args) => {
62
62
  const path = args.path.split("?")[0] ?? args.path
@@ -66,7 +66,7 @@ export function mdxBunPlugin(options: MdxPluginOptions = {}): BunPlugin {
66
66
  development,
67
67
  ...options.compileOptions,
68
68
  })
69
- // `loader: "jsx"` — the compiled output still contains JSX; Bun applies the JSX transform with
69
+ // `loader: "jsx"` - the compiled output still contains JSX; Bun applies the JSX transform with
70
70
  // the active `jsxImportSource`. Markup is hydration-equivalent to a hand-written component.
71
71
  return { contents: String(compiled), loader: "jsx" }
72
72
  })