@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 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 { T as convertDeepnoteFileToMarimoFiles, _ as convertDeepnoteFileToQuartoFiles, a as convertPercentFilesToDeepnoteFile, d as convertMarimoFilesToDeepnoteFile, k as convertDeepnoteFileToJupyterFiles, p as convertIpynbFilesToDeepnoteFile, r as convertQuartoFilesToDeepnoteFile, x as convertDeepnoteFileToPercentFiles } from "./src-CUESP0m8.js";
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;