@deepnote/convert 2.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +219 -0
- package/dist/bin.d.cts +1 -0
- package/dist/index.cjs +33 -0
- package/dist/index.d.cts +633 -0
- package/dist/index.d.ts +2 -12143
- package/dist/src-DI6mrd_2.cjs +1716 -0
- package/package.json +7 -5
package/dist/bin.cjs
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_src = require('./src-DI6mrd_2.cjs');
|
|
3
|
+
let cleye = require("cleye");
|
|
4
|
+
cleye = require_src.__toESM(cleye);
|
|
5
|
+
let node_fs_promises = require("node:fs/promises");
|
|
6
|
+
node_fs_promises = require_src.__toESM(node_fs_promises);
|
|
7
|
+
let node_path = require("node:path");
|
|
8
|
+
node_path = require_src.__toESM(node_path);
|
|
9
|
+
let chalk = require("chalk");
|
|
10
|
+
chalk = require_src.__toESM(chalk);
|
|
11
|
+
let ora = require("ora");
|
|
12
|
+
ora = require_src.__toESM(ora);
|
|
13
|
+
|
|
14
|
+
//#region src/cli.ts
|
|
15
|
+
async function convert(options) {
|
|
16
|
+
const { inputPath, projectName: customProjectName, outputPath: customOutputPath, cwd = process.cwd(), outputFormat = "jupyter" } = options;
|
|
17
|
+
const resolveProjectName = (possibleName) => {
|
|
18
|
+
if (customProjectName) return customProjectName;
|
|
19
|
+
if (possibleName) return possibleName;
|
|
20
|
+
return "Untitled project";
|
|
21
|
+
};
|
|
22
|
+
const resolveOutputPath = async (outputFilename) => {
|
|
23
|
+
if (customOutputPath) {
|
|
24
|
+
const absoluteOutputPath = (0, node_path.resolve)(cwd, customOutputPath);
|
|
25
|
+
if ((await node_fs_promises.default.stat(absoluteOutputPath).catch(() => null))?.isDirectory()) return (0, node_path.resolve)(absoluteOutputPath, outputFilename);
|
|
26
|
+
return absoluteOutputPath;
|
|
27
|
+
}
|
|
28
|
+
return (0, node_path.resolve)(cwd, outputFilename);
|
|
29
|
+
};
|
|
30
|
+
const absolutePath = (0, node_path.resolve)(cwd, inputPath);
|
|
31
|
+
if ((await node_fs_promises.default.stat(absolutePath)).isDirectory()) {
|
|
32
|
+
const entries = await node_fs_promises.default.readdir(absolutePath, { withFileTypes: true });
|
|
33
|
+
const ipynbFiles = entries.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".ipynb")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
34
|
+
const quartoFiles = entries.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".qmd")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
35
|
+
const pyFiles = entries.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".py")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
36
|
+
const classifyPyFile = async (pyFile) => {
|
|
37
|
+
const content = await node_fs_promises.default.readFile((0, node_path.resolve)(absolutePath, pyFile), "utf-8");
|
|
38
|
+
if (require_src.isMarimoContent(content)) return {
|
|
39
|
+
file: pyFile,
|
|
40
|
+
type: "marimo"
|
|
41
|
+
};
|
|
42
|
+
if (require_src.isPercentContent(content)) return {
|
|
43
|
+
file: pyFile,
|
|
44
|
+
type: "percent"
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
file: pyFile,
|
|
48
|
+
type: "unknown"
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
const CONCURRENCY_LIMIT = 10;
|
|
52
|
+
const results = [];
|
|
53
|
+
for (let i = 0; i < pyFiles.length; i += CONCURRENCY_LIMIT) {
|
|
54
|
+
const batch = pyFiles.slice(i, i + CONCURRENCY_LIMIT);
|
|
55
|
+
const batchResults = await Promise.all(batch.map(classifyPyFile));
|
|
56
|
+
results.push(...batchResults);
|
|
57
|
+
}
|
|
58
|
+
const marimoFiles = results.filter((r) => r.type === "marimo").map((r) => r.file);
|
|
59
|
+
const percentFiles = results.filter((r) => r.type === "percent").map((r) => r.file);
|
|
60
|
+
if (ipynbFiles.length > 0) return convertDirectory(absolutePath, ipynbFiles, "jupyter", resolveProjectName, resolveOutputPath);
|
|
61
|
+
if (quartoFiles.length > 0) return convertDirectory(absolutePath, quartoFiles, "quarto", resolveProjectName, resolveOutputPath);
|
|
62
|
+
if (marimoFiles.length > 0) return convertDirectory(absolutePath, marimoFiles, "marimo", resolveProjectName, resolveOutputPath);
|
|
63
|
+
if (percentFiles.length > 0) return convertDirectory(absolutePath, percentFiles, "percent", resolveProjectName, resolveOutputPath);
|
|
64
|
+
throw new Error("No supported notebook files found in the specified directory (.ipynb, .qmd, .py)");
|
|
65
|
+
}
|
|
66
|
+
const ext = (0, node_path.extname)(absolutePath).toLowerCase();
|
|
67
|
+
if (ext === ".ipynb") return convertJupyterToDeepnote(absolutePath, resolveProjectName, resolveOutputPath);
|
|
68
|
+
if (ext === ".qmd") return convertQuartoToDeepnote(absolutePath, resolveProjectName, resolveOutputPath);
|
|
69
|
+
if (ext === ".py") {
|
|
70
|
+
const content = await node_fs_promises.default.readFile(absolutePath, "utf-8");
|
|
71
|
+
if (require_src.isMarimoContent(content)) return convertMarimoToDeepnote(absolutePath, resolveProjectName, resolveOutputPath);
|
|
72
|
+
if (require_src.isPercentContent(content)) return convertPercentToDeepnote(absolutePath, resolveProjectName, resolveOutputPath);
|
|
73
|
+
throw new Error("Unsupported Python file format. File must be a percent format (# %% markers) or Marimo notebook (@app.cell decorators).");
|
|
74
|
+
}
|
|
75
|
+
if (ext === ".deepnote") return convertDeepnoteToFormat(absolutePath, outputFormat, customOutputPath, cwd);
|
|
76
|
+
throw new Error("Unsupported file type. Please provide a .ipynb, .qmd, .py (percent/marimo), or .deepnote file.");
|
|
77
|
+
}
|
|
78
|
+
async function convertDirectory(dirPath, files, format, resolveProjectName, resolveOutputPath) {
|
|
79
|
+
const spinner = (0, ora.default)(`Converting ${{
|
|
80
|
+
jupyter: "Jupyter Notebooks",
|
|
81
|
+
quarto: "Quarto documents",
|
|
82
|
+
percent: "percent format notebooks",
|
|
83
|
+
marimo: "Marimo notebooks"
|
|
84
|
+
}[format]} to a Deepnote project...`).start();
|
|
85
|
+
try {
|
|
86
|
+
const filenameWithoutExtension = (0, node_path.basename)(dirPath);
|
|
87
|
+
const projectName = resolveProjectName(filenameWithoutExtension);
|
|
88
|
+
const outputPath = await resolveOutputPath(`${filenameWithoutExtension}.deepnote`);
|
|
89
|
+
const inputFilePaths = files.map((file) => (0, node_path.resolve)(dirPath, file));
|
|
90
|
+
switch (format) {
|
|
91
|
+
case "jupyter":
|
|
92
|
+
await require_src.convertIpynbFilesToDeepnoteFile(inputFilePaths, {
|
|
93
|
+
projectName,
|
|
94
|
+
outputPath
|
|
95
|
+
});
|
|
96
|
+
break;
|
|
97
|
+
case "quarto":
|
|
98
|
+
await require_src.convertQuartoFilesToDeepnoteFile(inputFilePaths, {
|
|
99
|
+
projectName,
|
|
100
|
+
outputPath
|
|
101
|
+
});
|
|
102
|
+
break;
|
|
103
|
+
case "percent":
|
|
104
|
+
await require_src.convertPercentFilesToDeepnoteFile(inputFilePaths, {
|
|
105
|
+
projectName,
|
|
106
|
+
outputPath
|
|
107
|
+
});
|
|
108
|
+
break;
|
|
109
|
+
case "marimo":
|
|
110
|
+
await require_src.convertMarimoFilesToDeepnoteFile(inputFilePaths, {
|
|
111
|
+
projectName,
|
|
112
|
+
outputPath
|
|
113
|
+
});
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
spinner.succeed(`The Deepnote project has been saved to ${chalk.default.bold(outputPath)}`);
|
|
117
|
+
return outputPath;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
spinner.fail("Conversion failed");
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function convertSingleFileToDeepnote(absolutePath, formatName, converter, resolveProjectName, resolveOutputPath) {
|
|
124
|
+
const spinner = (0, ora.default)(`Converting the ${formatName} to a Deepnote project...`).start();
|
|
125
|
+
try {
|
|
126
|
+
const filenameWithoutExtension = (0, node_path.basename)(absolutePath, (0, node_path.extname)(absolutePath));
|
|
127
|
+
const projectName = resolveProjectName(filenameWithoutExtension);
|
|
128
|
+
const outputPath = await resolveOutputPath(`${filenameWithoutExtension}.deepnote`);
|
|
129
|
+
await converter([absolutePath], {
|
|
130
|
+
projectName,
|
|
131
|
+
outputPath
|
|
132
|
+
});
|
|
133
|
+
spinner.succeed(`The Deepnote project has been saved to ${chalk.default.bold(outputPath)}`);
|
|
134
|
+
return outputPath;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
spinner.fail("Conversion failed");
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function convertJupyterToDeepnote(absolutePath, resolveProjectName, resolveOutputPath) {
|
|
141
|
+
return convertSingleFileToDeepnote(absolutePath, "Jupyter Notebook", require_src.convertIpynbFilesToDeepnoteFile, resolveProjectName, resolveOutputPath);
|
|
142
|
+
}
|
|
143
|
+
function convertQuartoToDeepnote(absolutePath, resolveProjectName, resolveOutputPath) {
|
|
144
|
+
return convertSingleFileToDeepnote(absolutePath, "Quarto document", require_src.convertQuartoFilesToDeepnoteFile, resolveProjectName, resolveOutputPath);
|
|
145
|
+
}
|
|
146
|
+
function convertPercentToDeepnote(absolutePath, resolveProjectName, resolveOutputPath) {
|
|
147
|
+
return convertSingleFileToDeepnote(absolutePath, "percent format notebook", require_src.convertPercentFilesToDeepnoteFile, resolveProjectName, resolveOutputPath);
|
|
148
|
+
}
|
|
149
|
+
function convertMarimoToDeepnote(absolutePath, resolveProjectName, resolveOutputPath) {
|
|
150
|
+
return convertSingleFileToDeepnote(absolutePath, "Marimo notebook", require_src.convertMarimoFilesToDeepnoteFile, resolveProjectName, resolveOutputPath);
|
|
151
|
+
}
|
|
152
|
+
async function convertDeepnoteToFormat(absolutePath, outputFormat, customOutputPath, cwd) {
|
|
153
|
+
const formatNames = {
|
|
154
|
+
jupyter: "Jupyter Notebooks",
|
|
155
|
+
percent: "percent format files",
|
|
156
|
+
quarto: "Quarto documents",
|
|
157
|
+
marimo: "Marimo notebooks"
|
|
158
|
+
};
|
|
159
|
+
const spinner = (0, ora.default)(`Converting Deepnote project to ${formatNames[outputFormat]}...`).start();
|
|
160
|
+
try {
|
|
161
|
+
const outputDirName = (0, node_path.basename)(absolutePath, (0, node_path.extname)(absolutePath));
|
|
162
|
+
const outputDir = customOutputPath ? (0, node_path.resolve)(cwd, customOutputPath) : (0, node_path.resolve)(cwd, outputDirName);
|
|
163
|
+
switch (outputFormat) {
|
|
164
|
+
case "jupyter":
|
|
165
|
+
await require_src.convertDeepnoteFileToJupyterFiles(absolutePath, { outputDir });
|
|
166
|
+
break;
|
|
167
|
+
case "percent":
|
|
168
|
+
await require_src.convertDeepnoteFileToPercentFiles(absolutePath, { outputDir });
|
|
169
|
+
break;
|
|
170
|
+
case "quarto":
|
|
171
|
+
await require_src.convertDeepnoteFileToQuartoFiles(absolutePath, { outputDir });
|
|
172
|
+
break;
|
|
173
|
+
case "marimo":
|
|
174
|
+
await require_src.convertDeepnoteFileToMarimoFiles(absolutePath, { outputDir });
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
spinner.succeed(`${formatNames[outputFormat]} have been saved to ${chalk.default.bold(outputDir)}`);
|
|
178
|
+
return outputDir;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
spinner.fail("Conversion failed");
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/bin.ts
|
|
187
|
+
async function main() {
|
|
188
|
+
const argv = (0, cleye.cli)({
|
|
189
|
+
name: "deepnote-convert",
|
|
190
|
+
parameters: ["<path>"],
|
|
191
|
+
flags: {
|
|
192
|
+
projectName: {
|
|
193
|
+
description: "The name of the Deepnote project.",
|
|
194
|
+
type: String
|
|
195
|
+
},
|
|
196
|
+
outputPath: {
|
|
197
|
+
alias: "o",
|
|
198
|
+
description: "The path where the .deepnote file will be saved.",
|
|
199
|
+
type: String
|
|
200
|
+
},
|
|
201
|
+
cwd: {
|
|
202
|
+
description: "The working directory to resolve paths relative to.",
|
|
203
|
+
type: String
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
await convert({
|
|
208
|
+
inputPath: argv._.path,
|
|
209
|
+
projectName: argv.flags.projectName,
|
|
210
|
+
outputPath: argv.flags.outputPath,
|
|
211
|
+
cwd: argv.flags.cwd ?? process.cwd()
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (process.env.NODE_ENV !== "test" && process.env.VITEST !== "true") main().catch((error) => {
|
|
215
|
+
console.error(error);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
//#endregion
|
package/dist/bin.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const require_src = require('./src-DI6mrd_2.cjs');
|
|
2
|
+
|
|
3
|
+
exports.convertBlocksToJupyterNotebook = require_src.convertBlocksToJupyterNotebook;
|
|
4
|
+
exports.convertBlocksToMarimoApp = require_src.convertBlocksToMarimoApp;
|
|
5
|
+
exports.convertBlocksToPercentNotebook = require_src.convertBlocksToPercentNotebook;
|
|
6
|
+
exports.convertBlocksToQuartoDocument = require_src.convertBlocksToQuartoDocument;
|
|
7
|
+
exports.convertDeepnoteFileToJupyter = require_src.convertDeepnoteFileToJupyterFiles;
|
|
8
|
+
exports.convertDeepnoteFileToMarimoFiles = require_src.convertDeepnoteFileToMarimoFiles;
|
|
9
|
+
exports.convertDeepnoteFileToPercentFiles = require_src.convertDeepnoteFileToPercentFiles;
|
|
10
|
+
exports.convertDeepnoteFileToQuartoFiles = require_src.convertDeepnoteFileToQuartoFiles;
|
|
11
|
+
exports.convertDeepnoteToJupyterNotebooks = require_src.convertDeepnoteToJupyterNotebooks;
|
|
12
|
+
exports.convertDeepnoteToMarimoApps = require_src.convertDeepnoteToMarimoApps;
|
|
13
|
+
exports.convertDeepnoteToPercentNotebooks = require_src.convertDeepnoteToPercentNotebooks;
|
|
14
|
+
exports.convertDeepnoteToQuartoDocuments = require_src.convertDeepnoteToQuartoDocuments;
|
|
15
|
+
exports.convertIpynbFilesToDeepnoteFile = require_src.convertIpynbFilesToDeepnoteFile;
|
|
16
|
+
exports.convertJupyterNotebookToBlocks = require_src.convertJupyterNotebookToBlocks;
|
|
17
|
+
exports.convertJupyterNotebooksToDeepnote = require_src.convertJupyterNotebooksToDeepnote;
|
|
18
|
+
exports.convertMarimoAppToBlocks = require_src.convertMarimoAppToBlocks;
|
|
19
|
+
exports.convertMarimoAppsToDeepnote = require_src.convertMarimoAppsToDeepnote;
|
|
20
|
+
exports.convertMarimoFilesToDeepnoteFile = require_src.convertMarimoFilesToDeepnoteFile;
|
|
21
|
+
exports.convertPercentFilesToDeepnoteFile = require_src.convertPercentFilesToDeepnoteFile;
|
|
22
|
+
exports.convertPercentNotebookToBlocks = require_src.convertPercentNotebookToBlocks;
|
|
23
|
+
exports.convertPercentNotebooksToDeepnote = require_src.convertPercentNotebooksToDeepnote;
|
|
24
|
+
exports.convertQuartoDocumentToBlocks = require_src.convertQuartoDocumentToBlocks;
|
|
25
|
+
exports.convertQuartoDocumentsToDeepnote = require_src.convertQuartoDocumentsToDeepnote;
|
|
26
|
+
exports.convertQuartoFilesToDeepnoteFile = require_src.convertQuartoFilesToDeepnoteFile;
|
|
27
|
+
exports.detectFormat = require_src.detectFormat;
|
|
28
|
+
exports.parseMarimoFormat = require_src.parseMarimoFormat;
|
|
29
|
+
exports.parsePercentFormat = require_src.parsePercentFormat;
|
|
30
|
+
exports.parseQuartoFormat = require_src.parseQuartoFormat;
|
|
31
|
+
exports.serializeMarimoFormat = require_src.serializeMarimoFormat;
|
|
32
|
+
exports.serializePercentFormat = require_src.serializePercentFormat;
|
|
33
|
+
exports.serializeQuartoFormat = require_src.serializeQuartoFormat;
|