contentbase 0.0.2 → 0.0.4
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/.mcp.json +9 -0
- package/CLI.md +593 -0
- package/MCP-DESCRIPTIONS-REVIEW.md +122 -0
- package/MCP-SERVER-SPEC.md +453 -0
- package/PRIMER.md +540 -0
- package/README.md +289 -13
- package/bun.lock +43 -4
- package/dist/cnotes +0 -0
- package/docs/README.md +110 -0
- package/docs/TABLE-OF-CONTENTS.md +7 -0
- package/docs/models.ts +38 -0
- package/models.ts +38 -0
- package/package.json +12 -3
- package/public/web-demo/index.html +813 -0
- package/showcases/node_modules/.cache/.repl_history +3 -0
- package/showcases/vinyl-collection/artists/nina-simone.mdx +1 -1
- package/src/__tests__/semantic-search.integration.test.ts +284 -0
- package/src/api/endpoints/actions.ts +34 -0
- package/src/api/endpoints/doc.ts +187 -0
- package/src/api/endpoints/docs-index.ts +26 -0
- package/src/api/endpoints/document.ts +171 -0
- package/src/api/endpoints/documents.ts +71 -0
- package/src/api/endpoints/inspect.ts +16 -0
- package/src/api/endpoints/models.ts +10 -0
- package/src/api/endpoints/query.ts +88 -0
- package/src/api/endpoints/root.ts +7 -0
- package/src/api/endpoints/search-reindex.ts +65 -0
- package/src/api/endpoints/search-status.ts +55 -0
- package/src/api/endpoints/search.ts +104 -0
- package/src/api/endpoints/semantic-search.ts +120 -0
- package/src/api/endpoints/text-search.ts +63 -0
- package/src/api/endpoints/validate.ts +34 -0
- package/src/api/helpers.ts +97 -0
- package/src/base-model.ts +12 -0
- package/src/cli/commands/action.ts +82 -44
- package/src/cli/commands/console.ts +124 -0
- package/src/cli/commands/create.ts +179 -53
- package/src/cli/commands/embed.ts +323 -0
- package/src/cli/commands/export.ts +58 -24
- package/src/cli/commands/extract.ts +174 -0
- package/src/cli/commands/help.ts +81 -0
- package/src/cli/commands/index.ts +17 -0
- package/src/cli/commands/init.ts +72 -48
- package/src/cli/commands/inspect.ts +56 -46
- package/src/cli/commands/mcp.ts +1219 -0
- package/src/cli/commands/search.ts +285 -0
- package/src/cli/commands/serve.ts +348 -0
- package/src/cli/commands/summary.ts +60 -0
- package/src/cli/commands/teach.ts +86 -0
- package/src/cli/commands/text-search.ts +134 -0
- package/src/cli/commands/validate.ts +126 -64
- package/src/cli/index.ts +88 -19
- package/src/cli/load-collection.ts +144 -17
- package/src/cli/registry.ts +28 -0
- package/src/collection.ts +361 -10
- package/src/define-model.ts +101 -4
- package/src/document.ts +47 -1
- package/src/extract-sections.ts +1 -1
- package/src/index.ts +14 -2
- package/src/model-instance.ts +35 -5
- package/src/node-shortcuts.ts +1 -1
- package/src/query/collection-query.ts +96 -9
- package/src/query/index.ts +7 -0
- package/src/query/query-dsl.ts +259 -0
- package/src/relationships/has-many.ts +39 -0
- package/src/relationships/index.ts +7 -2
- package/src/section.ts +2 -0
- package/src/types.ts +23 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/match-pattern.ts +65 -0
- package/src/validator.ts +18 -1
- package/test/collection.test.ts +118 -2
- package/test/fixtures/sdlc/MODELS.md +106 -0
- package/test/fixtures/sdlc/SKILL.md +404 -0
- package/test/fixtures/sdlc/index.ts +9 -0
- package/test/fixtures/sdlc/models.ts +8 -6
- package/test/fixtures/sdlc/stories/authentication/a-user-should-be-able-to-login.mdx +20 -0
- package/test/fixtures/sdlc/templates/epic.md +23 -0
- package/test/fixtures/sdlc/templates/story.md +19 -0
- package/test/pattern.test.ts +191 -0
- package/test/query-dsl.test.ts +431 -0
- package/test/query.test.ts +29 -0
- package/test/relationships.test.ts +130 -0
- package/test/section.test.ts +61 -0
- package/test/table-of-contents.test.ts +49 -5
package/README.md
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
Contentbase treats a folder of Markdown and MDX files as a typed, queryable database. Define models with Zod schemas, extract structured data from headings and lists, traverse parent/child relationships across documents, validate everything, and query it all with a fluent API.
|
|
6
6
|
|
|
7
7
|
```ts
|
|
8
|
-
import { Collection, defineModel, section, hasMany, z } from "contentbase";
|
|
9
|
-
import { toString } from "mdast-util-to-string";
|
|
8
|
+
import { Collection, defineModel, section, hasMany, z, toString } from "contentbase";
|
|
10
9
|
|
|
11
10
|
const Story = defineModel("Story", {
|
|
12
11
|
meta: z.object({
|
|
@@ -79,14 +78,18 @@ content/
|
|
|
79
78
|
|
|
80
79
|
A model is a config object that describes one type of document. It declares:
|
|
81
80
|
|
|
81
|
+
- **description** -- human-readable summary (auto-generated from schema if omitted)
|
|
82
82
|
- **meta** -- a Zod schema for frontmatter
|
|
83
83
|
- **sections** -- named extractions from heading-based sections
|
|
84
84
|
- **relationships** -- `hasMany` / `belongsTo` links between models
|
|
85
85
|
- **computed** -- derived values calculated from instance data
|
|
86
|
+
- **defaults** -- static default values for frontmatter fields
|
|
87
|
+
- **pattern** -- Express-style path patterns for inferring meta from file paths
|
|
86
88
|
|
|
87
89
|
```ts
|
|
88
90
|
const Epic = defineModel("Epic", {
|
|
89
91
|
prefix: "epics",
|
|
92
|
+
description: "A project epic that groups related user stories.",
|
|
90
93
|
meta: z.object({
|
|
91
94
|
priority: z.enum(["low", "medium", "high"]).optional(),
|
|
92
95
|
status: z.enum(["created", "in-progress", "complete"]).default("created"),
|
|
@@ -103,14 +106,71 @@ const Epic = defineModel("Epic", {
|
|
|
103
106
|
});
|
|
104
107
|
```
|
|
105
108
|
|
|
109
|
+
If `description` is omitted, one is generated on first access from the model's schema: *"An Epic has metadata (priority, status), relationship (stories → Story), and computed property (isComplete)."*
|
|
110
|
+
|
|
106
111
|
The `prefix` determines which files match this model. Files whose path starts with `"epics"` are Epics. If omitted, the prefix is auto-pluralized from the name (`"Epic"` -> `"epics"`).
|
|
107
112
|
|
|
113
|
+
#### Explicit Model Assignment with `_model`
|
|
114
|
+
|
|
115
|
+
Documents at the root of a collection (not in a subfolder) can't be matched by prefix. You can explicitly assign a model by adding `_model` to the frontmatter:
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
---
|
|
119
|
+
_model: Epic
|
|
120
|
+
title: Platform Migration
|
|
121
|
+
status: created
|
|
122
|
+
---
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The `_model` key takes priority over prefix matching, so this works even if the file lives outside the model's prefix folder.
|
|
126
|
+
|
|
127
|
+
#### The Base Model
|
|
128
|
+
|
|
129
|
+
Every collection automatically registers a built-in `Base` model as a catch-all. Documents that don't match any other model (by `_model` or prefix) are assigned to Base. You can query these unmatched documents:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { Base } from "contentbase";
|
|
133
|
+
|
|
134
|
+
const misc = await collection.query(Base).fetchAll();
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
If you want to customize the Base model (e.g. add a meta schema), register your own before calling `load()`:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const MyBase = defineModel("Base", {
|
|
141
|
+
meta: z.object({ tags: z.array(z.string()).optional() }),
|
|
142
|
+
});
|
|
143
|
+
collection.register(MyBase);
|
|
144
|
+
await collection.load(); // won't auto-register the built-in Base
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Path Patterns
|
|
148
|
+
|
|
149
|
+
Models can declare Express-style path patterns to automatically infer meta values from the document's file path:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
const Story = defineModel("Story", {
|
|
153
|
+
prefix: "stories",
|
|
154
|
+
pattern: "stories/:epic/:slug",
|
|
155
|
+
meta: z.object({
|
|
156
|
+
epic: z.string(),
|
|
157
|
+
slug: z.string(),
|
|
158
|
+
}),
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
A file at `stories/authentication/user-can-register.mdx` will automatically have `{ epic: "authentication", slug: "user-can-register" }` inferred into its meta. Explicit frontmatter values always take precedence over pattern-inferred values. You can also supply an array of patterns -- the first match wins.
|
|
163
|
+
|
|
108
164
|
### Collections
|
|
109
165
|
|
|
110
166
|
A `Collection` loads a directory tree and gives you access to documents and typed model instances.
|
|
111
167
|
|
|
112
168
|
```ts
|
|
113
|
-
const collection = new Collection({
|
|
169
|
+
const collection = new Collection({
|
|
170
|
+
rootPath: "./content",
|
|
171
|
+
extensions: ["mdx", "md"], // default
|
|
172
|
+
autoDiscover: true, // auto-load models.ts if no models registered
|
|
173
|
+
});
|
|
114
174
|
await collection.load();
|
|
115
175
|
|
|
116
176
|
// Register models for prefix-based matching
|
|
@@ -141,8 +201,7 @@ Given this Markdown:
|
|
|
141
201
|
Define a section to extract the list items:
|
|
142
202
|
|
|
143
203
|
```ts
|
|
144
|
-
import { section } from "contentbase";
|
|
145
|
-
import { toString } from "mdast-util-to-string";
|
|
204
|
+
import { section, toString } from "contentbase";
|
|
146
205
|
|
|
147
206
|
const Story = defineModel("Story", {
|
|
148
207
|
sections: {
|
|
@@ -150,12 +209,13 @@ const Story = defineModel("Story", {
|
|
|
150
209
|
extract: (query) =>
|
|
151
210
|
query.selectAll("listItem").map((node) => toString(node)),
|
|
152
211
|
schema: z.array(z.string()),
|
|
212
|
+
alternatives: ["Requirements"], // fallback heading names
|
|
153
213
|
}),
|
|
154
214
|
},
|
|
155
215
|
});
|
|
156
216
|
```
|
|
157
217
|
|
|
158
|
-
The `extract` function receives an `AstQuery` scoped to the content under that heading. The `schema` is optional and used during validation.
|
|
218
|
+
The `extract` function receives an `AstQuery` scoped to the content under that heading. The `schema` is optional and used during validation. The `alternatives` array provides fallback heading names -- if "Acceptance Criteria" isn't found, it tries "Requirements" next.
|
|
159
219
|
|
|
160
220
|
Section data is **lazily computed and cached** -- the extract function only runs the first time you access the property.
|
|
161
221
|
|
|
@@ -272,6 +332,9 @@ const results = await collection
|
|
|
272
332
|
.query(Story)
|
|
273
333
|
.whereIn("meta.status", ["created", "in-progress"])
|
|
274
334
|
.whereExists("meta.epic")
|
|
335
|
+
.sort("meta.status", "asc")
|
|
336
|
+
.limit(10)
|
|
337
|
+
.offset(0)
|
|
275
338
|
.fetchAll();
|
|
276
339
|
|
|
277
340
|
// Convenience accessors
|
|
@@ -283,6 +346,60 @@ Available operators: `eq`, `neq`, `in`, `notIn`, `gt`, `lt`, `gte`, `lte`, `cont
|
|
|
283
346
|
|
|
284
347
|
Queries filter by model type **before** creating instances, so you only pay the parsing cost for matching documents.
|
|
285
348
|
|
|
349
|
+
### JSON Query DSL
|
|
350
|
+
|
|
351
|
+
For querying over the wire (REST API, MCP server) without executing arbitrary code, Contentbase provides a MongoDB-style JSON query DSL:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"model": "Epic",
|
|
356
|
+
"where": {
|
|
357
|
+
"meta.status": "created",
|
|
358
|
+
"meta.priority": { "$gt": 3 }
|
|
359
|
+
},
|
|
360
|
+
"sort": { "meta.priority": "desc" },
|
|
361
|
+
"select": ["id", "title", "meta.status"],
|
|
362
|
+
"limit": 10,
|
|
363
|
+
"offset": 0
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**Where value shortcuts:**
|
|
368
|
+
|
|
369
|
+
| Value type | Interpretation | Example |
|
|
370
|
+
|------------|---------------|---------|
|
|
371
|
+
| Literal (string, number, boolean, null) | Implicit `$eq` | `"meta.status": "active"` |
|
|
372
|
+
| Array | Implicit `$in` | `"meta.tags": ["a", "b"]` |
|
|
373
|
+
| Operator object | Explicit operator | `"meta.priority": { "$gt": 5 }` |
|
|
374
|
+
| Multiple operators | AND on same field | `"meta.priority": { "$gte": 3, "$lte": 8 }` |
|
|
375
|
+
|
|
376
|
+
**Available operators:** `$eq`, `$neq`, `$in`, `$notIn`, `$gt`, `$lt`, `$gte`, `$lte`, `$contains`, `$startsWith`, `$endsWith`, `$regex`, `$exists`
|
|
377
|
+
|
|
378
|
+
**Options:**
|
|
379
|
+
|
|
380
|
+
| Field | Type | Default | Description |
|
|
381
|
+
|-------|------|---------|-------------|
|
|
382
|
+
| `model` | string | *(required)* | Model name or prefix |
|
|
383
|
+
| `where` | object | -- | MongoDB-style filter conditions |
|
|
384
|
+
| `sort` | object or array | -- | `{ "field": "asc"\|"desc" }` or `[{ "path": "...", "direction": "asc" }]` |
|
|
385
|
+
| `select` | string[] | -- | Fields to include in output |
|
|
386
|
+
| `limit` | number | -- | Maximum results to return |
|
|
387
|
+
| `offset` | number | -- | Number of results to skip |
|
|
388
|
+
| `method` | string | `"fetchAll"` | `"fetchAll"`, `"first"`, `"last"`, or `"count"` |
|
|
389
|
+
|
|
390
|
+
Use via `POST /api/query` with a JSON body, or through the MCP `query` tool. The DSL parser is also available programmatically:
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
import { executeQueryDSL, queryDSLSchema } from "contentbase";
|
|
394
|
+
|
|
395
|
+
const result = await executeQueryDSL(collection, {
|
|
396
|
+
model: "Epic",
|
|
397
|
+
where: { "meta.status": "created" },
|
|
398
|
+
sort: { title: "asc" },
|
|
399
|
+
limit: 5,
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
286
403
|
---
|
|
287
404
|
|
|
288
405
|
## Validation
|
|
@@ -489,6 +606,32 @@ collection.tableOfContents({ basePath: "./content" });
|
|
|
489
606
|
// links become: ./content/epics/authentication.mdx
|
|
490
607
|
```
|
|
491
608
|
|
|
609
|
+
### File Tree
|
|
610
|
+
|
|
611
|
+
Render an ASCII file tree of all documents in the collection:
|
|
612
|
+
|
|
613
|
+
```ts
|
|
614
|
+
const tree = collection.renderFileTree();
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
```
|
|
618
|
+
epics/
|
|
619
|
+
├── authentication.mdx
|
|
620
|
+
└── searching-and-browsing.mdx
|
|
621
|
+
stories/
|
|
622
|
+
└── authentication/
|
|
623
|
+
└── a-user-should-be-able-to-register.mdx
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
### Model Summary
|
|
627
|
+
|
|
628
|
+
Generate comprehensive documentation of all registered models, including schema fields, sections, relationships, and defaults:
|
|
629
|
+
|
|
630
|
+
```ts
|
|
631
|
+
const summary = await collection.generateModelSummary();
|
|
632
|
+
// Returns markdown documenting each model's schema, sections, relationships
|
|
633
|
+
```
|
|
634
|
+
|
|
492
635
|
---
|
|
493
636
|
|
|
494
637
|
## Computed Properties
|
|
@@ -537,16 +680,141 @@ collection.use(timestampPlugin, { format: "iso" });
|
|
|
537
680
|
|
|
538
681
|
## CLI
|
|
539
682
|
|
|
540
|
-
Contentbase ships with a CLI for
|
|
683
|
+
Contentbase ships with a CLI available as both `cnotes` and `contentbase`. See [CLI.md](./CLI.md) for the full reference with examples for every command.
|
|
684
|
+
|
|
685
|
+
```bash
|
|
686
|
+
bun add contentbase
|
|
687
|
+
|
|
688
|
+
# Then use it via bunx, or in package.json scripts
|
|
689
|
+
bunx cnotes inspect
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### Commands
|
|
693
|
+
|
|
694
|
+
```bash
|
|
695
|
+
cnotes init [name] # scaffold a new project
|
|
696
|
+
cnotes create <Model> --title "..." # scaffold a new document (uses templates if available)
|
|
697
|
+
cnotes inspect # show models, sections, relationships, doc counts
|
|
698
|
+
cnotes validate [target] # validate documents ('all', a model name, or a path ID)
|
|
699
|
+
cnotes export # export collection as JSON
|
|
700
|
+
cnotes extract <glob> --sections "A, B" # extract specific sections from matching documents
|
|
701
|
+
cnotes summary # generate MODELS.md and TABLE-OF-CONTENTS.md
|
|
702
|
+
cnotes teach # output combined documentation for LLM context
|
|
703
|
+
cnotes action <name> # run a named action
|
|
704
|
+
cnotes text-search <pattern> # search file contents with pattern matching
|
|
705
|
+
cnotes serve # start HTTP server with REST API and doc serving
|
|
706
|
+
cnotes mcp # start MCP server for AI agent integration
|
|
707
|
+
cnotes console # interactive REPL with collection in scope
|
|
708
|
+
cnotes help # list available commands
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
All commands accept `--contentFolder` to specify which folder contains your content. Defaults to `./docs`. You can also set it in `package.json`:
|
|
712
|
+
|
|
713
|
+
```json
|
|
714
|
+
{
|
|
715
|
+
"contentbase": {
|
|
716
|
+
"contentFolder": "content"
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### serve
|
|
722
|
+
|
|
723
|
+
Start an HTTP server that exposes a full REST API for the collection. Documents are available as JSON, rendered HTML, or raw markdown.
|
|
724
|
+
|
|
725
|
+
```bash
|
|
726
|
+
# Start on default port 8000
|
|
727
|
+
cnotes serve
|
|
728
|
+
|
|
729
|
+
# Custom port, specific content folder
|
|
730
|
+
cnotes serve --port 9000 --contentFolder ./sdlc
|
|
731
|
+
|
|
732
|
+
# Read-only mode: disables all write endpoints (POST/PUT/PATCH/DELETE)
|
|
733
|
+
cnotes serve --read-only
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
**Built-in endpoints:**
|
|
737
|
+
|
|
738
|
+
| Path | Description |
|
|
739
|
+
|------|-------------|
|
|
740
|
+
| `GET /api/inspect` | Collection overview |
|
|
741
|
+
| `GET /api/models` | All model definitions |
|
|
742
|
+
| `GET /api/documents` | List documents (filter with `?model=`) |
|
|
743
|
+
| `GET/POST/PUT/PATCH/DELETE /api/documents/:pathId` | Document CRUD |
|
|
744
|
+
| `GET /api/query?model=&where=&select=` | Query model instances (flat condition format) |
|
|
745
|
+
| `POST /api/query` | Query with JSON DSL body (MongoDB-style) |
|
|
746
|
+
| `GET /api/search?pattern=` | Full-text regex search across documents |
|
|
747
|
+
| `GET /api/text-search?pattern=` | File-level text search (`expanded=true` for line detail) |
|
|
748
|
+
| `GET /api/validate?pathId=` | Validate against schema |
|
|
749
|
+
| `GET/POST /api/actions` | List or execute actions |
|
|
750
|
+
| `GET /docs/:path.json\|.md\|.html` | Content-negotiated doc serving |
|
|
751
|
+
| `GET /openapi.json` | Auto-generated OpenAPI 3.1 spec |
|
|
752
|
+
|
|
753
|
+
When `--read-only` is passed, all mutating endpoints return `403 Forbidden`. This includes `POST /api/documents`, `PUT/PATCH/DELETE /api/documents/:pathId`, and `POST /api/actions`. Read endpoints are unaffected.
|
|
754
|
+
|
|
755
|
+
You can also add your own endpoints by placing files in an `endpoints/` directory. See [CLI.md](./CLI.md#user-defined-endpoints) for details.
|
|
756
|
+
|
|
757
|
+
### mcp
|
|
758
|
+
|
|
759
|
+
Start a Model Context Protocol server for AI agent integration. Exposes tools, resources, and prompts for the collection.
|
|
541
760
|
|
|
542
761
|
```bash
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
contentbase export # export collection as JSON
|
|
546
|
-
contentbase create Story # scaffold a new document
|
|
547
|
-
contentbase action publish # run a named action
|
|
762
|
+
cnotes mcp # stdio transport (for Claude Desktop, etc.)
|
|
763
|
+
cnotes mcp --transport http --port 3003 # HTTP transport
|
|
548
764
|
```
|
|
549
765
|
|
|
766
|
+
### extract
|
|
767
|
+
|
|
768
|
+
The `extract` command outputs document titles, leading content, and only the requested sections -- combined into a single document suitable for creating new content:
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
# Extract Acceptance Criteria from all stories
|
|
772
|
+
cnotes extract "stories/**/*" --sections "Acceptance Criteria"
|
|
773
|
+
|
|
774
|
+
# Combine epics into a single document with a title
|
|
775
|
+
cnotes extract "epics/*" -s "Stories" --title "All Stories"
|
|
776
|
+
|
|
777
|
+
# Multiple sections, include frontmatter, raw heading depths
|
|
778
|
+
cnotes extract "epics/*" -s "Stories, Notes" --frontmatter --no-normalize-headings
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
Glob patterns are matched against document path IDs using [picomatch](https://github.com/micromatch/picomatch). Sections that don't exist in a document are silently skipped.
|
|
782
|
+
|
|
783
|
+
By default, heading depths are normalized so each document's content nests properly in the combined output. When `--title` is provided, it becomes the h1 and document titles shift to h2. Use `--no-normalize-headings` to preserve original heading depths.
|
|
784
|
+
|
|
785
|
+
### create
|
|
786
|
+
|
|
787
|
+
The `create` command scaffolds new documents with smart defaults:
|
|
788
|
+
|
|
789
|
+
```bash
|
|
790
|
+
cnotes create Story --title "User can logout"
|
|
791
|
+
cnotes create Epic --title "Payments" --meta.priority high
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
If a template exists at `templates/<model>.md` (or `.mdx`) in your content directory, it's used as the base. Meta values are merged with this priority: Zod defaults < model defaults < template frontmatter < CLI `--meta.*` flags.
|
|
795
|
+
|
|
796
|
+
### Model Discovery
|
|
797
|
+
|
|
798
|
+
The CLI uses a 3-tier system to find your models:
|
|
799
|
+
|
|
800
|
+
**Tier 1 — `index.ts`** (recommended): If your content directory has an `index.ts` that exports a `Collection` with models registered, the CLI uses it directly. This is what `contentbase init` scaffolds.
|
|
801
|
+
|
|
802
|
+
```ts
|
|
803
|
+
// docs/index.ts
|
|
804
|
+
import { Collection, defineModel, z } from "contentbase";
|
|
805
|
+
|
|
806
|
+
const Post = defineModel("Post", {
|
|
807
|
+
meta: z.object({ draft: z.boolean().default(false) }),
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
export const collection = new Collection({ rootPath: import.meta.dir });
|
|
811
|
+
collection.register(Post);
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
**Tier 2 — `models.ts`**: If no `index.ts` exists but a `models.ts` is found, the CLI imports it, detects model definitions from exports, and auto-registers them on a new Collection.
|
|
815
|
+
|
|
816
|
+
**Tier 3 — Auto-discovery**: If neither file exists, the CLI scans top-level subdirectories for markdown files and generates bare models from folder names (`epics/` → `Epic`). These models have no schema validation — useful for quick inspection, but you'll want a `models.ts` or `index.ts` for real use.
|
|
817
|
+
|
|
550
818
|
---
|
|
551
819
|
|
|
552
820
|
## API Reference
|
|
@@ -557,18 +825,26 @@ contentbase action publish # run a named action
|
|
|
557
825
|
| --- | --- |
|
|
558
826
|
| `Collection` | Loads and manages a directory of documents |
|
|
559
827
|
| `Document` | A single Markdown/MDX file with AST operations |
|
|
560
|
-
| `defineModel()` | Create a typed model definition |
|
|
828
|
+
| `defineModel()` | Create a typed model definition (accepts optional `description`, auto-generated if omitted) |
|
|
829
|
+
| `generateDescription()` | Generate a human-readable model description from its schema |
|
|
561
830
|
| `section()` | Declare a section extraction |
|
|
562
831
|
| `hasMany()` | Declare a one-to-many relationship |
|
|
563
832
|
| `belongsTo()` | Declare a many-to-one relationship |
|
|
564
833
|
| `parse()` | Parse a file path or markdown string into a queryable `ParsedDocument` |
|
|
565
834
|
| `extractSections()` | Combine sections from multiple documents into one |
|
|
566
835
|
| `CollectionQuery` | Fluent query builder for model instances |
|
|
836
|
+
| `queryDSLSchema` | Zod schema for validating JSON query DSL input |
|
|
837
|
+
| `parseWhereClause()` | Parse MongoDB-style where object into internal conditions |
|
|
838
|
+
| `executeQueryDSL()` | Execute a JSON query DSL against a collection |
|
|
567
839
|
| `AstQuery` | MDAST query wrapper (select, visit, find) |
|
|
568
840
|
| `NodeShortcuts` | Convenience getters for common AST nodes |
|
|
569
841
|
| `createModelInstance()` | Low-level factory for model instances |
|
|
570
842
|
| `validateDocument()` | Standalone validation function |
|
|
843
|
+
| `matchPattern()` | Express-style path pattern matching (`:param` syntax) |
|
|
844
|
+
| `matchPatterns()` | Try multiple patterns against a path, first match wins |
|
|
845
|
+
| `introspectMetaSchema()` | Extract field info (name, type, required, default) from a Zod schema |
|
|
571
846
|
| `z` | Re-exported from Zod (no extra dependency needed) |
|
|
847
|
+
| `toString` | Re-exported from `mdast-util-to-string` |
|
|
572
848
|
|
|
573
849
|
---
|
|
574
850
|
|
package/bun.lock
CHANGED
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
"": {
|
|
5
5
|
"name": "contentbase",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"citty": "^0.1.6",
|
|
8
7
|
"gray-matter": "^4.0.3",
|
|
9
8
|
"js-yaml": "^4.1.0",
|
|
10
9
|
"mdast-util-mdxjs-esm": "^2.0.1",
|
|
11
10
|
"mdast-util-to-markdown": "^2.1.2",
|
|
12
11
|
"mdast-util-to-string": "^4.0.0",
|
|
12
|
+
"picomatch": "^4.0.3",
|
|
13
|
+
"rehype-stringify": "^10.0.1",
|
|
13
14
|
"remark-gfm": "^4.0.0",
|
|
14
15
|
"remark-parse": "^11.0.0",
|
|
16
|
+
"remark-rehype": "^11.1.2",
|
|
15
17
|
"remark-stringify": "^11.0.0",
|
|
16
18
|
"unified": "^11.0.5",
|
|
17
19
|
"unist-util-find-after": "^5.0.0",
|
|
@@ -25,10 +27,17 @@
|
|
|
25
27
|
"devDependencies": {
|
|
26
28
|
"@types/js-yaml": "^4.0.9",
|
|
27
29
|
"@types/mdast": "^4.0.4",
|
|
30
|
+
"@types/picomatch": "^4.0.2",
|
|
28
31
|
"bun-types": "^1.1.0",
|
|
29
32
|
"typescript": "^5.4.0",
|
|
30
33
|
"vitest": "^1.6.0",
|
|
31
34
|
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@soederpop/luca": ">=0.0.1",
|
|
37
|
+
},
|
|
38
|
+
"optionalPeers": [
|
|
39
|
+
"@soederpop/luca",
|
|
40
|
+
],
|
|
32
41
|
},
|
|
33
42
|
},
|
|
34
43
|
"packages": {
|
|
@@ -150,8 +159,12 @@
|
|
|
150
159
|
|
|
151
160
|
"@types/node": ["@types/node@25.2.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ=="],
|
|
152
161
|
|
|
162
|
+
"@types/picomatch": ["@types/picomatch@4.0.2", "", {}, "sha512-qHHxQ+P9PysNEGbALT8f8YOSHW0KJu6l2xU8DYY0fu/EmGxXdVnuTLvFUvBgPJMSqXq29SYHveejeAha+4AYgA=="],
|
|
163
|
+
|
|
153
164
|
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
|
154
165
|
|
|
166
|
+
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
|
167
|
+
|
|
155
168
|
"@vitest/expect": ["@vitest/expect@1.6.1", "", { "dependencies": { "@vitest/spy": "1.6.1", "@vitest/utils": "1.6.1", "chai": "^4.3.10" } }, "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog=="],
|
|
156
169
|
|
|
157
170
|
"@vitest/runner": ["@vitest/runner@1.6.1", "", { "dependencies": { "@vitest/utils": "1.6.1", "p-limit": "^5.0.0", "pathe": "^1.1.1" } }, "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA=="],
|
|
@@ -186,14 +199,16 @@
|
|
|
186
199
|
|
|
187
200
|
"character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
|
|
188
201
|
|
|
202
|
+
"character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
|
|
203
|
+
|
|
204
|
+
"character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
|
|
205
|
+
|
|
189
206
|
"check-error": ["check-error@1.0.3", "", { "dependencies": { "get-func-name": "^2.0.2" } }, "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg=="],
|
|
190
207
|
|
|
191
|
-
"
|
|
208
|
+
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
|
192
209
|
|
|
193
210
|
"confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
|
194
211
|
|
|
195
|
-
"consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
|
|
196
|
-
|
|
197
212
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
198
213
|
|
|
199
214
|
"css-selector-parser": ["css-selector-parser@3.3.0", "", {}, "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g=="],
|
|
@@ -232,6 +247,12 @@
|
|
|
232
247
|
|
|
233
248
|
"gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="],
|
|
234
249
|
|
|
250
|
+
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
|
|
251
|
+
|
|
252
|
+
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
|
|
253
|
+
|
|
254
|
+
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
|
|
255
|
+
|
|
235
256
|
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
|
236
257
|
|
|
237
258
|
"is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
|
|
@@ -278,6 +299,8 @@
|
|
|
278
299
|
|
|
279
300
|
"mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="],
|
|
280
301
|
|
|
302
|
+
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="],
|
|
303
|
+
|
|
281
304
|
"mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="],
|
|
282
305
|
|
|
283
306
|
"mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="],
|
|
@@ -364,18 +387,26 @@
|
|
|
364
387
|
|
|
365
388
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
366
389
|
|
|
390
|
+
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
|
391
|
+
|
|
367
392
|
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
|
368
393
|
|
|
369
394
|
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
|
370
395
|
|
|
371
396
|
"pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
|
|
372
397
|
|
|
398
|
+
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
|
399
|
+
|
|
373
400
|
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
|
374
401
|
|
|
402
|
+
"rehype-stringify": ["rehype-stringify@10.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-html": "^9.0.0", "unified": "^11.0.0" } }, "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA=="],
|
|
403
|
+
|
|
375
404
|
"remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="],
|
|
376
405
|
|
|
377
406
|
"remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="],
|
|
378
407
|
|
|
408
|
+
"remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="],
|
|
409
|
+
|
|
379
410
|
"remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="],
|
|
380
411
|
|
|
381
412
|
"rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="],
|
|
@@ -392,12 +423,16 @@
|
|
|
392
423
|
|
|
393
424
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
394
425
|
|
|
426
|
+
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
|
|
427
|
+
|
|
395
428
|
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
|
|
396
429
|
|
|
397
430
|
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
|
398
431
|
|
|
399
432
|
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
|
|
400
433
|
|
|
434
|
+
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
|
|
435
|
+
|
|
401
436
|
"strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="],
|
|
402
437
|
|
|
403
438
|
"strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
|
@@ -410,6 +445,8 @@
|
|
|
410
445
|
|
|
411
446
|
"tinyspy": ["tinyspy@2.2.1", "", {}, "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A=="],
|
|
412
447
|
|
|
448
|
+
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
|
|
449
|
+
|
|
413
450
|
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
|
|
414
451
|
|
|
415
452
|
"type-detect": ["type-detect@4.1.0", "", {}, "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw=="],
|
|
@@ -432,6 +469,8 @@
|
|
|
432
469
|
|
|
433
470
|
"unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
|
|
434
471
|
|
|
472
|
+
"unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
|
|
473
|
+
|
|
435
474
|
"unist-util-select": ["unist-util-select@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "css-selector-parser": "^3.0.0", "devlop": "^1.1.0", "nth-check": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-4A5mfokSHG/rNQ4g7gSbdEs+H586xyd24sdJqF1IWamqrLHvYb+DH48fzxowyOhOfK7YSqX+XlCojAyuuyyT2A=="],
|
|
436
475
|
|
|
437
476
|
"unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
|
package/dist/cnotes
ADDED
|
Binary file
|