UNPKG

python2igcse

Version:

Convert Python code to IGCSE Pseudocode format

254 lines 8.69 kB
"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(`![${altText}](${url}${titleAttr})`, 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