comarkContent()
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:
options: aContentOptionsobject. See Options.
Returns: ComarkContent & <plugin methods>, a typed handle. Base methods are always present; plugins like sqlQuery add content.query, sqliteFullTextSearch adds content.search.
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 sqlQueryOptions
| Option | Type | Default | Description |
|---|---|---|---|
source | Source | undefined | A single source mounted as default. |
sources | Record<string, Source> | undefined | Multiple named sources. |
cache | CacheOptions | false | {} | Where parsed entries are stored and kept fresh. In-memory by default; false disables it. |
plugins | ContentPlugin[] | [] | Plugins to install at construction. |
markdown | ParserOptions | undefined | Forwarded to the Comark parser (markdown plugins, options). |
basePath | string | '/api/content' | Path handler() is mounted at. |
logger | Logger | false | console | Where 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.mdsourceorsources, 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.
| Field | Type | Default | Description |
|---|---|---|---|
driver | Driver | in-memory | unstorage driver backing the cache. |
ttl | number | undefined | Milliseconds 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> | undefined | Hydrate the manifest from a pre-built manifest artifact on init(). |
loadSnapshot | (source) => Promise<CacheArtifact | null> | undefined | Hydrate 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.
| Value | Behaviour |
|---|---|
'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:
content.get(path, options?): read one document by its public path.content.list(sources?): list lightweight entries from the manifest.content.navigation(sources?): build a navigation tree.content.stat(key): look up a single manifest entry.content.getSource(name): get a configured source by name.content.init(options?): initialize the instance.content.loadSnapshot(source): hydrate a source's bodies from a snapshot.content.update(source, file): upsert a single parsed file.content.remove(source, key): drop a single entry.content.watch(): keep the manifest and cache in sync with file changes.content.handler(request): handle a web-standard request.content.addParser(extensions, parse): register a parser for file extensions.content.addListingFields(extensions, fields): limit which fields listings keep.content.addServeHandler(section, handler): register a custom handler section.
And these properties:
content.cache: the resolvedCachebacking the instance.content.logger: the resolvedLoggerused across the pipeline.content.manifest: the read-only in-memoryManifestthe read methods index from.content.hooks: aHookablebus for content-change events.content.status: the lifecycle status ('created','initializing','initialized-partial', or'initialized-full').
Usage
import { comarkContent } from 'comark-content'
import fs from 'comark-content/sources/fs'
export const content = comarkContent({ source: fs('./content') })