comarkContent()

Create a Comark Content instance from sources, an optional cache, and plugins.

comarkContent(options)

Creates a Comark Content instance from the supplied source(s), an optional cache, and optional plugins. The returned type is the base instance plus whatever methods the plugins contribute.

Parameters:

Returns: ComarkContent & <plugin methods>, a typed handle. Base methods are always present; plugins like sqlQuery add content.query, sqliteFullTextSearch adds content.search.

content.ts
import { comarkContent } from 'comark-content'
import fs from 'comark-content/sources/fs'
import sqlite from 'comark-content/database/sqlite-node'
import sqlQuery from 'comark-content/plugins/sql-query'

export const content = comarkContent({
  source: fs('./content'),
  plugins: [sqlQuery({ database: sqlite() })],
})

content.get    // base method
content.query  // contributed by sqlQuery

Options

OptionTypeDefaultDescription
sourceSourceundefinedA single source mounted as default.
sourcesRecord<string, Source>undefinedMultiple named sources.
cacheCacheOptions | false{}Where parsed entries are stored and kept fresh. In-memory by default; false disables it.
pluginsContentPlugin[][]Plugins to install at construction.
markdownParserOptionsundefinedForwarded to the Comark parser (markdown plugins, options).
basePathstring'/api/content'Path handler() is mounted at.
loggerLogger | falseconsoleWhere pipeline diagnostics go. Pass a custom logger, or false to silence output.
onError'throw' | 'warn' | 'ignore''warn'Default reaction when a file fails to parse.

source

Mounts a single source under the implicit name default. Use this for the common case.

comarkContent({ source: fs('./content') })
await content.get('/posts/hello')   // resolves to default/posts/hello.md
Pass sourceorsources, never both. The constructor throws otherwise.

sources

Mounts multiple named sources. Source names are part of every entry's meta.key and the values you pass to list([...]) / navigation([...]).

comarkContent({
  sources: {
    docs: github({ repo: 'comarkdown/comark', branch: 'main', path: 'docs/content' }),
    blog: fs('./content/blog'),
  },
})

See Sources for the full source API.

cache

Parsed entries are stored in a cache backed by an unstorage driver: in-memory by default, or any driver you provide. Pass false to disable caching entirely, so every get() re-parses from the source.

FieldTypeDefaultDescription
driverDriverin-memoryunstorage driver backing the cache.
ttlnumberundefinedMilliseconds before an entry is considered stale. Omit to never expire.
strategy'swr' | 'none''swr'swr serves a stale entry and refreshes in the background; none re-reads a stale entry on the next get().
loadManifest() => Promise<CacheArtifact | null>undefinedHydrate the manifest from a pre-built manifest artifact on init().
loadSnapshot(source) => Promise<CacheArtifact | null>undefinedHydrate a source's bodies from a snapshot on first get().

See Caching and Artifacts & hydration.

plugins

Plugins run synchronously at construction. They register parsers, hook into events, and add methods to the returned Content, fully typed.

comarkContent({
  source: fs('./content'),
  plugins: [sqlQuery({ database }), sqliteFullTextSearch({ database })],
})

See Plugins for the authoring API and Plugins for the built-ins.

markdown

Forwarded verbatim to the automatically installed markdown plugin. Use it to add Markdown-level plugins (highlight, toc, emoji, math, mermaid) and toggle parser options.

import highlight from 'comark/plugins/highlight'

comarkContent({
  source: fs('./content'),
  markdown: { plugins: [highlight()], autoClose: true },
})

If you add markdown() to plugins yourself—for example, to configure listingFields—pass these options to markdown({ comark }) instead. The top-level value only configures the automatic fallback plugin.

See Comark parse options for the full reference.

basePath

The path handler() is mounted at. The handler strips this prefix from the request pathname before dispatching. Defaults to /api/content.

logger

The logger used across the Content instance pipeline and its plugins. By default, diagnostics (such as a file that failed to parse, or a schema-validation warning) are written to console with a [comark-content] prefix.

Pass your own Logger to redirect output to your app's logging system, or pass false to silence it entirely — useful in environments that strip console from production builds, or in tests.

// Route through your own logger
comarkContent({
  source: fs('./content'),
  logger: {
    debug: (...a) => myLogger.debug(...a),
    info: (...a) => myLogger.info(...a),
    warn: (...a) => myLogger.warn(...a),
    error: (...a) => myLogger.error(...a),
  },
})

// Silence all pipeline output
comarkContent({ source: fs('./content'), logger: false })

The active logger is available as content.logger and is passed to plugins and parsers via their context.

onError

How the pipeline reacts when a file fails to parse — for example malformed JSON/YAML, or a markdown field that can't be parsed. Applies to the built-in json, yaml, and markdown-fields plugins.

ValueBehaviour
'warn' (default)Log a warning via logger and drop the offending file.
'ignore'Silently drop the offending file.
'throw'Surface the error and abort the operation (e.g. init() rejects).
// Fail fast on any bad content file
comarkContent({ source: fs('./content'), onError: 'throw' })

Individual plugins accept their own onError to override this default per file type:

comarkContent({
  source: fs('./content'),
  onError: 'warn',
  plugins: [json({ onError: 'throw' })], // stricter for JSON only
})

Schema-level validation is handled separately by the schema-validation plugin's mode option.

Instance

The returned instance exposes these methods:

And these properties:

Usage

server/utils/content.ts
import { comarkContent } from 'comark-content'
import fs from 'comark-content/sources/fs'

export const content = comarkContent({ source: fs('./content') })