JSON Plugin
The json plugin lets your sources serve plain JSON files alongside Markdown. Each .json file becomes a ContentFile whose data is the parsed JSON object and whose nodes are empty.
Usage
import { comarkContent } from 'comark-content'
import json from 'comark-content/plugins/json'
const content = comarkContent({
source: fs('./content'),
plugins: [json()],
})Given content/teams/engineering.json:
{
"name": "Engineering",
"lead": "Ada Lovelace",
"members": 42
}const team = await content.get('/teams/engineering')
// ^? ContentFile
team.data // { name: 'Engineering', lead: 'Ada Lovelace', members: 42 }API
json(options?)
Returns a ContentPlugin that registers a parser for .json files. Each file becomes a kind: 'document' ContentFile whose data is the parsed JSON object and whose nodes are empty. Files that fail to parse, or that parse to an array (rather than an object), are handled according to onError — by default they are dropped with a warning.
Parameters:
options?: see Options.
Returns: ContentPlugin
Options
| Option | Type | Default | Description |
|---|---|---|---|
listingFields | string[] | undefined | data fields kept in listings for .json entries. |
onError | 'throw' | 'warn' | 'ignore' | Content onError | How to react to a malformed or non-object .json file. |
listingFields
By default a listing keeps a document's whole data object. Pass listingFields to limit which data keys are retained in content.list() results for .json entries, forwarded to content.addListingFields():
import json from 'comark-content/plugins/json'
json({
listingFields: ['name', 'members'],
})Default: undefined
onError
How the parser reacts when a .json file can't be parsed or isn't an object: 'warn' logs and drops it, 'ignore' drops it silently, 'throw' aborts. Defaults to the Content-level onError (which defaults to 'warn').
json({ onError: 'throw' }) // fail fast on malformed JSONDefault: the Content instance onError option
Read data
Each .json file resolves to a regular kind: 'document' ContentFile whose data is the parsed object, so the core content methods (content.get(), content.list(), content.stat(), and content.navigation()) treat them like any other document, and content.query() indexes their flattened data.
await content.list(['default'])
// → includes engineering.json alongside .md files
await content.query('default').where('data.members', '>', 10).all()
// → SQL queries against JSON data work toocontent.search() is the only method that skips JSON files. It only indexes parsed nodes, which data files don't have.ContentFile so navigation, queries, and snapshots include them uniformly.Trim listing payloads
When a source serves large JSON records, restrict listings to the fields you actually render:
const content = comarkContent({
source: fs('./content'),
plugins: [json({ listingFields: ['name', 'members'] })],
})
await content.list(['default'])
// → each JSON entry's data is trimmed to { name, members }