(absolutePath: string, isDirectory: boolean, ext: string)
| 85 | } |
| 86 | |
| 87 | async function determineInputFormat(absolutePath: string, isDirectory: boolean, ext: string): Promise<NotebookFormat> { |
| 88 | if (ext === '.deepnote') { |
| 89 | return 'deepnote' |
| 90 | } |
| 91 | |
| 92 | if (ext === '.ipynb') { |
| 93 | return 'jupyter' |
| 94 | } |
| 95 | |
| 96 | if (ext === '.qmd') { |
| 97 | return 'quarto' |
| 98 | } |
| 99 | |
| 100 | if (ext === '.py') { |
| 101 | const content = await fs.readFile(absolutePath, 'utf-8') |
| 102 | const format = detectFormat(absolutePath, content) |
| 103 | if (format === 'marimo') return 'marimo' |
| 104 | if (format === 'percent') return 'percent' |
| 105 | throw new Error( |
| 106 | 'Unsupported Python file format. File must be a percent format (# %% markers) or Marimo notebook (@app.cell decorators).' |
| 107 | ) |
| 108 | } |
| 109 | |
| 110 | if (isDirectory) { |
| 111 | // Check directory contents to determine format |
| 112 | const entries = await fs.readdir(absolutePath, { withFileTypes: true }) |
| 113 | const files = entries.filter(e => e.isFile()).map(e => e.name) |
| 114 | |
| 115 | if (files.some(f => f.toLowerCase().endsWith('.ipynb'))) return 'jupyter' |
| 116 | if (files.some(f => f.toLowerCase().endsWith('.qmd'))) return 'quarto' |
| 117 | |
| 118 | // Check .py files for format |
| 119 | const pyFiles = files.filter(f => f.toLowerCase().endsWith('.py')) |
| 120 | for (const pyFile of pyFiles) { |
| 121 | const pyFilePath = resolve(absolutePath, pyFile) |
| 122 | const content = await fs.readFile(pyFilePath, 'utf-8') |
| 123 | const format = tryDetectFormat(pyFilePath, content) |
| 124 | if (format === 'marimo') return 'marimo' |
| 125 | if (format === 'percent') return 'percent' |
| 126 | } |
| 127 | |
| 128 | throw new Error('No supported notebook files found in the directory (.ipynb, .qmd, .py)') |
| 129 | } |
| 130 | |
| 131 | throw new Error('Unsupported file type. Please provide a .ipynb, .qmd, .py (percent/marimo), or .deepnote file.') |
| 132 | } |
| 133 | |
| 134 | async function convertFromDeepnote( |
| 135 | absolutePath: string, |
no test coverage detected