@deepnote/convert 2.0.0 → 2.1.1
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/bin.js +1 -9
- package/dist/index.cjs +33 -0
- package/dist/index.d.cts +12774 -0
- package/dist/index.d.ts +11924 -402
- package/dist/index.js +2 -2
- package/dist/src-DI6mrd_2.cjs +1716 -0
- package/dist/{src-CUESP0m8.js → src-oALQkXiP.js} +53 -9
- package/package.json +8 -6
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/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { M as convertDeepnoteFileToJupyterFiles, O as convertDeepnoteFileToMarimoFiles, _ as isMarimoContent, a as convertPercentFilesToDeepnoteFile, b as convertDeepnoteFileToQuartoFiles, d as convertMarimoFilesToDeepnoteFile, p as convertIpynbFilesToDeepnoteFile, r as convertQuartoFilesToDeepnoteFile, v as isPercentContent, w as convertDeepnoteFileToPercentFiles } from "./src-oALQkXiP.js";
|
|
3
3
|
import { cli } from "cleye";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
5
|
import { basename, extname, resolve } from "node:path";
|
|
@@ -176,14 +176,6 @@ async function convertDeepnoteToFormat(absolutePath, outputFormat, customOutputP
|
|
|
176
176
|
throw error;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
-
/** Check if file content is Marimo format */
|
|
180
|
-
function isMarimoContent(content) {
|
|
181
|
-
return /^import marimo\b/m.test(content) && /@app\.cell\b/.test(content) && !/^\s*['"]{3}[\s\S]*?import marimo/m.test(content);
|
|
182
|
-
}
|
|
183
|
-
/** Check if file content is percent format */
|
|
184
|
-
function isPercentContent(content) {
|
|
185
|
-
return /^# %%/m.test(content) && !/^\s*['"]{3}[\s\S]*?# %%/m.test(content);
|
|
186
|
-
}
|
|
187
179
|
|
|
188
180
|
//#endregion
|
|
189
181
|
//#region src/bin.ts
|
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;
|