Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions cli/src/osf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,35 @@
return '';
}

// Helper to convert TextRun objects to Markdown
function textRunToMarkdown(run: TextRun): string {
if (typeof run === 'string') {
return run;
}
if ('type' in run) {
if (run.type === 'link') {
return `[${run.text}](${run.url})`;
}
if (run.type === 'image') {
return `![${run.alt}](${run.url})`;
}
}
if ('text' in run) {
let text = run.text;
if ((run as any).bold) {

Check warning on line 63 in cli/src/osf.ts

View workflow job for this annotation

GitHub Actions / Lint & Format

Unexpected any. Specify a different type

Check warning on line 63 in cli/src/osf.ts

View workflow job for this annotation

GitHub Actions / Lint & Format

Unexpected any. Specify a different type
text = `**${text}**`;
}
if ((run as any).italic) {

Check warning on line 66 in cli/src/osf.ts

View workflow job for this annotation

GitHub Actions / Lint & Format

Unexpected any. Specify a different type

Check warning on line 66 in cli/src/osf.ts

View workflow job for this annotation

GitHub Actions / Lint & Format

Unexpected any. Specify a different type
text = `*${text}*`;
}
if ((run as any).underline) {

Check warning on line 69 in cli/src/osf.ts

View workflow job for this annotation

GitHub Actions / Lint & Format

Unexpected any. Specify a different type

Check warning on line 69 in cli/src/osf.ts

View workflow job for this annotation

GitHub Actions / Lint & Format

Unexpected any. Specify a different type
text = `__${text}__`;
}
return text;
}
return '';
}

// Helper function to convert OSFValue to CellValue
function toSpreadsheetData(data: Record<string, OSFValue> | undefined): SpreadsheetData {
if (!data) return {};
Expand Down Expand Up @@ -600,12 +629,28 @@
for (const block of slide.content) {
if (block.type === 'unordered_list') {
for (const item of block.items) {
const itemText = item.content.map(extractText).join('');
const itemText = item.content.map(textRunToMarkdown).join('');
out.push(`- ${itemText}`);
}
} else if (block.type === 'ordered_list') {
block.items.forEach((item, idx) => {
const itemText = item.content.map(textRunToMarkdown).join('');
out.push(`${idx + 1}. ${itemText}`);
});
} else if (block.type === 'paragraph') {
const paragraphText = block.content.map(extractText).join('');
const paragraphText = block.content.map(textRunToMarkdown).join('');
out.push(paragraphText);
} else if (block.type === 'blockquote') {
for (const para of block.content) {
const quoteText = para.content.map(textRunToMarkdown).join('');
out.push(`> ${quoteText}`);
}
} else if (block.type === 'code') {
out.push(`\u0060\u0060\u0060${block.language || ''}`);
out.push(block.content);
out.push('\u0060\u0060\u0060');
} else if (block.type === 'image') {
out.push(`![${block.alt}](${block.url})`);
}
}
}
Expand Down
37 changes: 37 additions & 0 deletions cli/tests/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@ const FORMULA_TEST_OSF = `@meta {
formula (2,4): "=C1+C2";
}`;

const ADVANCED_OSF =
'@slide {\n' +
' title: "Comprehensive Slide";\n\n' +
' This is a paragraph with **bold**, *italic*, and __underlined__ text.\n\n' +
' - Unordered item 1\n' +
' - Unordered item 2\n\n' +
' 1. Ordered item 1\n' +
' 2. Ordered item 2\n\n' +
' > This is a blockquote.\n\n' +
' ```javascript\n' +
' console.log("Hello, World!");\n' +
' ```\n\n' +
' ![An image alt text](https://example.com/image.png)\n\n' +
' [A link to somewhere](https://example.com)\n' +
'}';

const INVALID_OSF = `@meta {
title: "Unclosed Block"
// Missing closing brace`;
Expand Down Expand Up @@ -294,6 +310,27 @@ describe('OSF CLI', () => {
expect(result).toContain('15 *(calc)*'); // (115-100)/100*100 = 15
});

it('should export advanced content to Markdown', () => {
const advancedFile = join(TEST_FIXTURES_DIR, 'advanced.osf');
writeFileSync(advancedFile, ADVANCED_OSF, 'utf8');
try {
const result = execSync(`node "${CLI_PATH}" export "${advancedFile}"`, {
encoding: 'utf8',
});

expect(result).toContain('1. Ordered item 1');
expect(result).toContain('> This is a blockquote.');
expect(result).toContain('```javascript');
expect(result).toContain('console.log("Hello, World!");');
expect(result).toContain('![An image alt text](https://example.com/image.png)');
expect(result).toContain('[A link to somewhere](https://example.com)');
} finally {
if (existsSync(advancedFile)) {
unlinkSync(advancedFile);
}
}
});

it('should export OSF with formulas to Markdown', () => {
const formulaFile = join(TEST_FIXTURES_DIR, 'formula_test.osf');
writeFileSync(formulaFile, FORMULA_TEST_OSF, 'utf8');
Expand Down
Loading