@contedra/md-importer
v0.2.2
Published
CLI tool to import YAML-frontmatter Markdown files + images into Firestore using model definition JSON
Downloads
158
Maintainers
Readme
@contedra/md-importer
CLI tool and library to import YAML-frontmatter Markdown files (with images) into Firestore, using Conteditor model definition JSON for schema validation.
Installation
pnpm add @contedra/md-importerCLI Usage
npx @contedra/md-importer \
--md-dir ./content \
--model ./models/blog_posts.json \
--project-id your-project-id \
--credential ./service-account.json \
--storage-bucket your-project-id.firebasestorage.appCLI Options
| Option | Required | Description |
|--------|----------|-------------|
| --md-dir <path> | Yes | Directory containing .md files |
| --model <path> | Yes | Path to model definition JSON |
| --project-id <id> | Yes | Firebase project ID |
| --credential <path> | No | Path to service account JSON (uses ADC if omitted) |
| --collection <name> | No | Firestore collection name (defaults to modelName) |
| --storage-bucket <name> | No* | Firebase Storage bucket name (e.g. your-project.firebasestorage.app) |
| --no-images | No | Skip image extraction, upload, and URL replacement |
| --image-base-dir <path> | No | Directory for resolving absolute image paths (e.g. ./public) |
| --image-fields <fields> | No | Comma-separated frontmatter field names containing image paths (e.g. heroImage,cover) |
| --field-mapping <json> | No | JSON mapping frontmatter keys to model properties |
*
--storage-bucketis required unless--no-imagesis set.
Field Mapping
When your Markdown frontmatter keys don't match the model property names, use --field-mapping:
npx @contedra/md-importer \
--md-dir ./content \
--model ./models/blog_posts.json \
--project-id your-project-id \
--field-mapping '{"article_title":"title","article_date":"publishedAt"}'Unmapped frontmatter keys that match model property names are auto-matched.
Programmatic API
mdImporter(config): Promise<ImportResult>
import { mdImporter } from "@contedra/md-importer";
const result = await mdImporter({
mdDir: "./content",
modelFile: "./models/blog_posts.json",
firebaseConfig: {
projectId: "your-project-id",
credential: "./service-account.json",
storageBucket: "your-project-id.firebasestorage.app",
},
fieldMapping: {
article_title: "title",
article_date: "publishedAt",
},
imageFields: ["heroImage", "cover"], // frontmatter fields containing image paths
// noImages: true, // set to skip all image processing
});
console.log(`Imported: ${result.imported.length}`);
console.log(`Errors: ${result.errors.length}`);Custom Image Resolver
By default, local images referenced in Markdown are read from the filesystem and uploaded to Firebase Storage (assets/{modelName}/{contentId}/{fileName}). Provide a custom resolver to change this behavior:
const result = await mdImporter({
mdDir: "./content",
modelFile: "./models/blog_posts.json",
firebaseConfig: { projectId: "your-project-id" },
resolveImage: async (imagePath, mdFilePath) => {
const response = await fetch(`https://cdn.example.com/${imagePath}`);
return Buffer.from(await response.arrayBuffer());
},
});Helper Functions
generateDocId(filePath)— Converts a filename to a slugified Firestore document IDparseMarkdownFile(filePath)— Parses a.mdfile into{ frontmatter, body }parseMarkdownString(content)— Parses a markdown string (uses gray-matter)mapFields(frontmatter, model, fieldMapping?)— Maps frontmatter fields to model properties, returns{ data, unmapped }
Image Handling
Images referenced in Markdown (e.g., ) are:
- Extracted from the markdown body
- Resolved via the local filesystem (or custom
resolveImage) - Uploaded to Firebase Storage at
assets/{modelName}/{contentId}/{fileName} - Replaced in the markdown body with
asset://URIs
External URLs (http://, https://) and asset:// URIs are skipped.
License
MIT
