Create a Comark Content Parser
Turn new file types into documents with content.addParser().
By default the Content instance only parses Markdown. But content.addParser() has been designed to handle any extension.
content.addParser(extensions, parse)
Registers a Parser that runs every time the Content instance sees a file with one of the given extensions.
Parameters:
extensions: an array of dotted file extensions, e.g.['.csv'].parse: aParsercallback that turns a raw file into aParserResult.
Returns: void
Parser
The callback content.addParser runs: (ctx: ParserContext) => ParserResult | null. It receives a ParserContext describing the file and returns a ParserResult, or null to skip the file.
Parameters:
ctx: aParserContext.
| Field | Type | Description |
|---|---|---|
read | () => string | Promise<string> | Fetch the raw file contents. |
extension | string | The file's extension, e.g. .csv. |
filepath | string | The path of the file being parsed. |
partial | boolean | true on lightweight scans (manifest build): parse only metadata and skip the body. |
Returns: a ParserResult (or null to skip). Every field is optional.
| Field | Type | Description |
|---|---|---|
kind | 'document' | 'media' | How to track the file. Defaults to 'document'. |
type | string | The file's MIME type. |
data | ContentFile['data'] | The parsed data (frontmatter for documents). |
meta | Record<string, any> | Extra metadata merged onto the entry. |
nodes | ContentFile['nodes'] | The parsed AST, empty for data-only files. |
partial | boolean | Whether only metadata was parsed. Defaults to the context's partial. |
To trim which
data fields listings keep, pair the parser with content.addListingFields().Usage
Write a parser plugin, register it on comarkContent(), then read the new files like any other document.
Define the parser
Call content.addParser from the plugin's setup. This CSV parser reads the raw file and returns each row as data, with empty nodes:
csv-plugin.ts
import { defineContentPlugin } from 'comark-content'
export default defineContentPlugin(() => ({
setup(content) {
content.addParser(['.csv'], async ({ read }) => {
const body = await read()
const [header, ...rows] = body.trim().split('\n').map(line => line.split(','))
const data = rows.map(row => Object.fromEntries(header!.map((h, i) => [h, row[i]])))
return { kind: 'document', data: { rows: data }, meta: {}, nodes: [] }
})
},
}))Register the parser
content.ts
import { comarkContent } from 'comark-content'
import fs from 'comark-content/sources/fs'
import csv from './csv-plugin'
const content = comarkContent({ source: fs('./content'), plugins: [csv()] })Read the result
read.ts
const team = await content.get('/teams/roster')
team?.data.rows // parsed CSV rows, queryable and listableReturn
data with empty nodes for any data-only format (TOML, CSV, INI): entries stay queryable and listable but carry no rendered body