diff --git a/test/test-codex-transform.js b/test/test-codex-transform.js index 63db245bf..b372bf084 100644 --- a/test/test-codex-transform.js +++ b/test/test-codex-transform.js @@ -38,7 +38,7 @@ function assert(condition, testName, detail) { * Validates the output is well-formed YAML that parses back correctly. */ function parseOutputDescription(output) { - const match = output.match(/^---\n([\s\S]*?)\n---/); + const match = output.match(/^---\r?\n([\s\S]*?)\r?\n---/); if (!match) return null; const parsed = yaml.parse(match[1]); return parsed?.description; @@ -103,6 +103,15 @@ console.log(`\n${colors.cyan}CodexSetup.transformToSkillFormat tests${colors.res assert(result.includes('Just some content without frontmatter.'), 'body preserved when no frontmatter'); } +// --- CRLF frontmatter is parsed correctly (Windows line endings) --- +{ + const input = '---\r\ndescription: windows line endings\r\n---\r\n\r\nBody.'; + const result = setup.transformToSkillFormat(input, 'crlf-skill'); + const desc = parseOutputDescription(result); + assert(desc === 'windows line endings', 'CRLF frontmatter parses correctly', `got description: ${JSON.stringify(desc)}`); + assert(result.includes('Body.'), 'body preserved for CRLF input'); +} + // --- Summary --- console.log(`\n${passed} passed, ${failed} failed\n`); process.exit(failed > 0 ? 1 : 0); diff --git a/tools/cli/installers/lib/ide/codex.js b/tools/cli/installers/lib/ide/codex.js index 07be97741..02447c398 100644 --- a/tools/cli/installers/lib/ide/codex.js +++ b/tools/cli/installers/lib/ide/codex.js @@ -197,7 +197,7 @@ class CodexSetup extends BaseIdeSetup { */ transformToSkillFormat(content, skillName) { // Parse frontmatter - const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/); + const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/); if (!fmMatch) { // No frontmatter -- wrap with minimal frontmatter return `---\nname: ${skillName}\ndescription: '${skillName}'\n---\n\n${content}`;