python2igcse
Version:
Convert Python code to IGCSE Pseudocode format
254 lines • 8.69 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarkdownEmitter = void 0;
const text_emitter_1 = require("./text-emitter");
/**
* Emitter that outputs IGCSE Pseudocode in Markdown format
*/
class MarkdownEmitter extends text_emitter_1.TextEmitter {
constructor(options = {}, markdownConfig = {}) {
super({ ...options, format: 'markdown' });
this.markdownConfig = {
codeBlockLanguage: 'pseudocode',
headingLevel: 2,
includeDescription: true,
generateToc: false,
...markdownConfig,
};
}
/**
* Convert IR to Markdown format
*/
emit(ir) {
this.startEmitting();
this.resetContext();
this.debug('Starting Markdown emission...');
try {
// Output Markdown header
this.emitMarkdownHeader();
// Generate table of contents (optional)
if (this.markdownConfig.generateToc) {
this.emitTableOfContents(ir);
}
// Add description (optional)
if (this.markdownConfig.includeDescription) {
this.emitDescription();
}
// Start code block
this.emitCodeBlockStart();
// Process IR
this.emitNode(ir);
// End code block
this.emitCodeBlockEnd();
// Add footer
this.emitMarkdownFooter();
const result = this.createEmitResult();
this.debug(`Markdown emission completed. Lines: ${result.stats.linesGenerated}`);
return result;
}
catch (error) {
this.addError(`Markdown emit failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'output_error');
return this.createEmitResult();
}
}
/**
* Output Markdown header
*/
emitMarkdownHeader() {
const headingPrefix = '#'.repeat(this.markdownConfig.headingLevel);
this.emitLine(`${headingPrefix} IGCSE Pseudocode`, false);
this.emitBlankLine();
if (this.options.includeComments) {
this.emitLine('*Generated by python2igcse converter*', false);
this.emitLine(`*Date: ${new Date().toLocaleDateString()}*`, false);
this.emitBlankLine();
}
}
/**
* Generate table of contents
*/
emitTableOfContents(ir) {
const headingPrefix = '#'.repeat(this.markdownConfig.headingLevel + 1);
this.emitLine(`${headingPrefix} Table of Contents`, false);
this.emitBlankLine();
const toc = this.generateTocEntries(ir);
for (const entry of toc) {
this.emitLine(entry, false);
}
this.emitBlankLine();
}
/**
* Generate table of contents entries
*/
generateTocEntries(ir, level = 0) {
const entries = [];
const indent = ' '.repeat(level);
if (ir.kind === 'procedure' || ir.kind === 'function') {
const name = ir.meta?.name || 'Unknown';
const link = name.toLowerCase().replace(/\s+/g, '-');
entries.push(`${indent}- [${name}](#${link})`);
}
for (const child of ir.children) {
entries.push(...this.generateTocEntries(child, level + 1));
}
return entries;
}
/**
* Output description
*/
emitDescription() {
const headingPrefix = '#'.repeat(this.markdownConfig.headingLevel + 1);
this.emitLine(`${headingPrefix} Description`, false);
this.emitBlankLine();
this.emitLine('This pseudocode follows the IGCSE Computer Science specification.', false);
this.emitLine('It has been automatically converted from Python source code.', false);
this.emitBlankLine();
this.emitLine('**Key Features:**', false);
this.emitLine('- Uses IGCSE-compliant syntax and keywords', false);
this.emitLine('- Proper indentation and structure', false);
this.emitLine('- Clear variable assignments using ←', false);
this.emitLine('- Standard control structures (IF/THEN/ELSE, FOR/NEXT, WHILE/ENDWHILE)', false);
this.emitBlankLine();
}
/**
* Start code block
*/
emitCodeBlockStart() {
const headingPrefix = '#'.repeat(this.markdownConfig.headingLevel + 1);
this.emitLine(`${headingPrefix} Pseudocode`, false);
this.emitBlankLine();
this.emitLine(`\`\`\`${this.markdownConfig.codeBlockLanguage}`, false);
}
/**
* End code block
*/
emitCodeBlockEnd() {
this.emitLine('```', false);
this.emitBlankLine();
}
/**
* Output Markdown footer
*/
emitMarkdownFooter() {
if (!this.options.includeComments)
return;
const headingPrefix = '#'.repeat(this.markdownConfig.headingLevel + 1);
this.emitLine(`${headingPrefix} Notes`, false);
this.emitBlankLine();
this.emitLine('- This pseudocode is designed for IGCSE Computer Science examinations', false);
this.emitLine('- All syntax follows the official IGCSE specification', false);
this.emitLine('- Variable assignments use the ← symbol as required', false);
this.emitLine('- Control structures use proper IGCSE keywords', false);
this.emitBlankLine();
this.emitLine('---', false);
this.emitLine('*Generated by [python2igcse](https://github.com/your-repo/python2igcse)*', false);
}
/**
* Function/procedure header with anchor link
*/
emitProcedure(node) {
const name = node.meta?.name || 'Unknown';
const anchor = name.toLowerCase().replace(/\s+/g, '-');
const headingPrefix = '#'.repeat(this.markdownConfig.headingLevel + 2);
// Function/procedure header
this.emitLine(`${headingPrefix} ${name} {#${anchor}}`, false);
this.emitBlankLine();
// Parameter information
if (node.meta?.params && node.meta.params.length > 0) {
this.emitLine('**Parameters:**', false);
for (const param of node.meta.params) {
this.emitLine(`- \`${param}\``, false);
}
this.emitBlankLine();
}
// Return value information
if (node.meta?.returnType) {
this.emitLine(`**Returns:** ${node.meta.returnType}`, false);
this.emitBlankLine();
}
// Code block
this.emitLine(`\`\`\`${this.markdownConfig.codeBlockLanguage}`, false);
// Actual procedure code
super.emitProcedure(node);
this.emitLine('```', false);
this.emitBlankLine();
}
/**
* Output function (same as procedure)
*/
emitFunction(node) {
this.emitProcedure(node);
}
/**
* Format for inline code
*/
formatInlineCode(text) {
return `\`${text}\``;
}
/**
* Add emphasized text
*/
emitEmphasis(text, type = 'bold') {
const marker = type === 'bold' ? '**' : '*';
this.emitLine(`${marker}${text}${marker}`, false);
}
/**
* Output list item
*/
emitListItem(text, level = 0) {
const indent = ' '.repeat(level);
this.emitLine(`${indent}- ${text}`, false);
}
/**
* Output horizontal rule
*/
emitHorizontalRule() {
this.emitLine('---', false);
}
/**
* Output link
*/
emitLink(text, url) {
this.emitLine(`[${text}](${url})`, false);
}
/**
* Output image
*/
emitImage(altText, url, title) {
const titleAttr = title ? ` "${title}"` : '';
this.emitLine(``, false);
}
/**
* Output table
*/
emitTable(headers, rows) {
// Header row
this.emitLine(`| ${headers.join(' | ')} |`, false);
// Separator line
const separator = headers.map(() => '---').join(' | ');
this.emitLine(`| ${separator} |`, false);
// Data row
for (const row of rows) {
this.emitLine(`| ${row.join(' | ')} |`, false);
}
this.emitBlankLine();
}
/**
* Output blockquote
*/
emitBlockquote(text) {
const lines = text.split('\n');
for (const line of lines) {
this.emitLine(`> ${line}`, false);
}
this.emitBlankLine();
}
/**
* Update Markdown configuration
*/
updateMarkdownConfig(config) {
this.markdownConfig = { ...this.markdownConfig, ...config };
}
}
exports.MarkdownEmitter = MarkdownEmitter;
//# sourceMappingURL=markdown-emitter.js.map