roocommander
Version:
Bridge Claude Code skills to Roo Code with intelligent orchestration. CLI tool + Custom Mode + 60+ production-tested skills for Cloudflare, AI, Frontend development.
84 lines • 3.17 kB
JavaScript
;
/**
* YAML Frontmatter Parser
*
* Wraps gray-matter library to extract YAML frontmatter from markdown files.
* Provides error handling and validation for skill files.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseFrontmatter = parseFrontmatter;
exports.extractKeywords = extractKeywords;
exports.extractUseWhen = extractUseWhen;
const gray_matter_1 = __importDefault(require("gray-matter"));
const fs_extra_1 = require("fs-extra");
const types_js_1 = require("./types.js");
/**
* Parse YAML frontmatter from a markdown file
*
* @param filePath - Absolute path to markdown file
* @returns Parsed frontmatter data and content
* @throws SkillParseError if file can't be read or YAML is malformed
*/
async function parseFrontmatter(filePath) {
try {
// Read file contents
const fileContent = await (0, fs_extra_1.readFile)(filePath, 'utf-8');
// Parse with gray-matter
const parsed = (0, gray_matter_1.default)(fileContent);
return {
data: parsed.data,
content: parsed.content,
};
}
catch (error) {
// Distinguish between file read errors and YAML parse errors
if (error.code === 'ENOENT') {
throw new types_js_1.SkillParseError(`SKILL.md file not found: ${filePath}`, filePath, error);
}
// Check if it's a YAML parsing error from gray-matter
if (error instanceof Error && error.message.includes('can not read')) {
throw new types_js_1.SkillParseError(`Malformed YAML frontmatter in ${filePath}: ${error.message}`, filePath, error);
}
// Generic error
throw new types_js_1.SkillParseError(`Failed to parse ${filePath}: ${error instanceof Error ? error.message : String(error)}`, filePath, error instanceof Error ? error : undefined);
}
}
/**
* Extract keywords from description text
*
* Looks for "Keywords:" line in description and extracts comma-separated values.
* Example: "Keywords: react, typescript, vite" → ["react", "typescript", "vite"]
*
* @param description - Full description text
* @returns Array of keywords (empty if not found)
*/
function extractKeywords(description) {
const keywordsMatch = description.match(/Keywords:\s*(.+)/i);
if (!keywordsMatch) {
return [];
}
// Split by comma and trim whitespace
return keywordsMatch[1]
.split(',')
.map((keyword) => keyword.trim())
.filter((keyword) => keyword.length > 0);
}
/**
* Extract "Use when:" section from description
*
* Extracts text after "Use when:" up to next section or end of paragraph.
*
* @param description - Full description text
* @returns "Use when" text, or undefined if not found
*/
function extractUseWhen(description) {
const useWhenMatch = description.match(/Use when:\s*(.+?)(?:\n\n|\nKeywords:|\n[A-Z]|$)/is);
if (!useWhenMatch) {
return undefined;
}
return useWhenMatch[1].trim();
}
//# sourceMappingURL=yaml-parser.js.map