@deepnote/convert 2.0.0 → 2.1.0

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/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { A as convertDeepnoteToJupyterNotebooks, C as serializePercentFormat, D as serializeMarimoFormat, E as convertDeepnoteToMarimoApps, O as convertBlocksToJupyterNotebook, S as convertDeepnoteToPercentNotebooks, T as convertDeepnoteFileToMarimoFiles, _ as convertDeepnoteFileToQuartoFiles, a as convertPercentFilesToDeepnoteFile, b as convertBlocksToPercentNotebook, c as parsePercentFormat, d as convertMarimoFilesToDeepnoteFile, f as parseMarimoFormat, g as convertBlocksToQuartoDocument, h as convertJupyterNotebooksToDeepnote, i as parseQuartoFormat, k as convertDeepnoteFileToJupyterFiles, l as convertMarimoAppToBlocks, m as convertJupyterNotebookToBlocks, n as convertQuartoDocumentsToDeepnote, o as convertPercentNotebookToBlocks, p as convertIpynbFilesToDeepnoteFile, r as convertQuartoFilesToDeepnoteFile, s as convertPercentNotebooksToDeepnote, t as convertQuartoDocumentToBlocks, u as convertMarimoAppsToDeepnote, v as convertDeepnoteToQuartoDocuments, w as convertBlocksToMarimoApp, x as convertDeepnoteFileToPercentFiles, y as serializeQuartoFormat } from "./src-CUESP0m8.js";
1
+ import { A as serializeMarimoFormat, C as convertBlocksToPercentNotebook, D as convertBlocksToMarimoApp, E as serializePercentFormat, M as convertDeepnoteFileToJupyterFiles, N as convertDeepnoteToJupyterNotebooks, O as convertDeepnoteFileToMarimoFiles, S as serializeQuartoFormat, T as convertDeepnoteToPercentNotebooks, a as convertPercentFilesToDeepnoteFile, b as convertDeepnoteFileToQuartoFiles, c as parsePercentFormat, d as convertMarimoFilesToDeepnoteFile, f as parseMarimoFormat, g as detectFormat, h as convertJupyterNotebooksToDeepnote, i as parseQuartoFormat, j as convertBlocksToJupyterNotebook, k as convertDeepnoteToMarimoApps, l as convertMarimoAppToBlocks, m as convertJupyterNotebookToBlocks, n as convertQuartoDocumentsToDeepnote, o as convertPercentNotebookToBlocks, p as convertIpynbFilesToDeepnoteFile, r as convertQuartoFilesToDeepnoteFile, s as convertPercentNotebooksToDeepnote, t as convertQuartoDocumentToBlocks, u as convertMarimoAppsToDeepnote, w as convertDeepnoteFileToPercentFiles, x as convertDeepnoteToQuartoDocuments, y as convertBlocksToQuartoDocument } from "./src-oALQkXiP.js";
2
2
 
3
- export { convertBlocksToJupyterNotebook, convertBlocksToMarimoApp, convertBlocksToPercentNotebook, convertBlocksToQuartoDocument, convertDeepnoteFileToJupyterFiles as convertDeepnoteFileToJupyter, convertDeepnoteFileToMarimoFiles, convertDeepnoteFileToPercentFiles, convertDeepnoteFileToQuartoFiles, convertDeepnoteToJupyterNotebooks, convertDeepnoteToMarimoApps, convertDeepnoteToPercentNotebooks, convertDeepnoteToQuartoDocuments, convertIpynbFilesToDeepnoteFile, convertJupyterNotebookToBlocks, convertJupyterNotebooksToDeepnote, convertMarimoAppToBlocks, convertMarimoAppsToDeepnote, convertMarimoFilesToDeepnoteFile, convertPercentFilesToDeepnoteFile, convertPercentNotebookToBlocks, convertPercentNotebooksToDeepnote, convertQuartoDocumentToBlocks, convertQuartoDocumentsToDeepnote, convertQuartoFilesToDeepnoteFile, parseMarimoFormat, parsePercentFormat, parseQuartoFormat, serializeMarimoFormat, serializePercentFormat, serializeQuartoFormat };
3
+ export { convertBlocksToJupyterNotebook, convertBlocksToMarimoApp, convertBlocksToPercentNotebook, convertBlocksToQuartoDocument, convertDeepnoteFileToJupyterFiles as convertDeepnoteFileToJupyter, convertDeepnoteFileToMarimoFiles, convertDeepnoteFileToPercentFiles, convertDeepnoteFileToQuartoFiles, convertDeepnoteToJupyterNotebooks, convertDeepnoteToMarimoApps, convertDeepnoteToPercentNotebooks, convertDeepnoteToQuartoDocuments, convertIpynbFilesToDeepnoteFile, convertJupyterNotebookToBlocks, convertJupyterNotebooksToDeepnote, convertMarimoAppToBlocks, convertMarimoAppsToDeepnote, convertMarimoFilesToDeepnoteFile, convertPercentFilesToDeepnoteFile, convertPercentNotebookToBlocks, convertPercentNotebooksToDeepnote, convertQuartoDocumentToBlocks, convertQuartoDocumentsToDeepnote, convertQuartoFilesToDeepnoteFile, detectFormat, parseMarimoFormat, parsePercentFormat, parseQuartoFormat, serializeMarimoFormat, serializePercentFormat, serializeQuartoFormat };
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs/promises";
2
2
  import { basename, dirname, extname, join } from "node:path";
3
- import { createMarkdown, createPythonCode, deserializeDeepnoteFile, environmentSchema, executionSchema } from "@deepnote/blocks";
3
+ import { createMarkdown, createPythonCode, deepnoteBlockSchema, deserializeDeepnoteFile, environmentSchema, executionSchema } from "@deepnote/blocks";
4
4
  import { v4 } from "uuid";
5
5
  import { parse, stringify } from "yaml";
6
6
 
@@ -62,6 +62,18 @@ function isMarkdownBlockType(blockType) {
62
62
  if (CODE_BLOCK_TYPES.includes(blockType)) return false;
63
63
  return true;
64
64
  }
65
+ /**
66
+ * Sorts object keys alphabetically while preserving the type.
67
+ * Useful for producing stable, predictable output in serialized formats like YAML.
68
+ *
69
+ * @param obj - The object whose keys should be sorted
70
+ * @returns A new object with the same values but keys in alphabetical order
71
+ */
72
+ function sortKeysAlphabetically(obj) {
73
+ const sorted = {};
74
+ for (const key of Object.keys(obj).sort()) sorted[key] = obj[key];
75
+ return sorted;
76
+ }
65
77
 
66
78
  //#endregion
67
79
  //#region src/deepnote-to-jupyter.ts
@@ -146,23 +158,27 @@ async function convertDeepnoteFileToJupyterFiles(deepnoteFilePath, options) {
146
158
  function convertBlockToCell$3(block) {
147
159
  const content = block.content || "";
148
160
  const jupyterCellType = convertBlockTypeToJupyter(block.type);
161
+ const executionStartedAt = "executionStartedAt" in block ? block.executionStartedAt : void 0;
162
+ const executionFinishedAt = "executionFinishedAt" in block ? block.executionFinishedAt : void 0;
163
+ const executionCount = "executionCount" in block ? block.executionCount : null;
164
+ const outputs = "outputs" in block ? block.outputs : void 0;
149
165
  const metadata = {
166
+ ...block.metadata || {},
150
167
  cell_id: block.id,
151
168
  deepnote_block_group: block.blockGroup,
152
169
  deepnote_cell_type: block.type,
153
170
  deepnote_sorting_key: block.sortingKey,
154
171
  deepnote_content_hash: block.contentHash,
155
- deepnote_execution_started_at: block.executionStartedAt,
156
- deepnote_execution_finished_at: block.executionFinishedAt,
157
- ...block.metadata || {}
172
+ deepnote_execution_started_at: executionStartedAt,
173
+ deepnote_execution_finished_at: executionFinishedAt
158
174
  };
159
175
  metadata.deepnote_source = content;
160
176
  return {
161
177
  block_group: block.blockGroup,
162
178
  cell_type: jupyterCellType,
163
- execution_count: block.executionCount ?? null,
179
+ execution_count: executionCount ?? null,
164
180
  metadata,
165
- outputs: block.outputs,
181
+ outputs,
166
182
  source: getSourceForBlock(block, jupyterCellType, content)
167
183
  };
168
184
  }
@@ -603,6 +619,34 @@ function convertBlockToCell(block) {
603
619
  return cell;
604
620
  }
605
621
 
622
+ //#endregion
623
+ //#region src/format-detection.ts
624
+ /** Check if file content is Marimo format */
625
+ function isMarimoContent(content) {
626
+ return /^import marimo\b/m.test(content) && /@app\.cell\b/.test(content) && !/^\s*['"]{3}[\s\S]*?import marimo/m.test(content);
627
+ }
628
+ /** Check if file content is percent format */
629
+ function isPercentContent(content) {
630
+ return /^# %%/m.test(content) && !/^\s*['"]{3}[\s\S]*?# %%/m.test(content);
631
+ }
632
+ /**
633
+ * Detects the notebook format from filename and optionally content.
634
+ * For .py files, content is required to distinguish between Marimo and Percent formats.
635
+ */
636
+ function detectFormat(filename, content) {
637
+ const lowercaseFilename = filename.toLowerCase();
638
+ if (lowercaseFilename.endsWith(".ipynb")) return "jupyter";
639
+ if (lowercaseFilename.endsWith(".deepnote")) return "deepnote";
640
+ if (lowercaseFilename.endsWith(".qmd")) return "quarto";
641
+ if (lowercaseFilename.endsWith(".py")) {
642
+ if (!content) throw new Error("Content is required to detect format for .py files");
643
+ if (isMarimoContent(content)) return "marimo";
644
+ if (isPercentContent(content)) return "percent";
645
+ throw new Error("Unsupported Python file format. File must be percent format (# %%) or Marimo (@app.cell).");
646
+ }
647
+ throw new Error(`Unsupported file format: ${filename}`);
648
+ }
649
+
606
650
  //#endregion
607
651
  //#region src/jupyter-to-deepnote.ts
608
652
  /**
@@ -741,7 +785,7 @@ function convertCellToBlock$3(cell, index, idGenerator) {
741
785
  const executionCount = cell.execution_count ?? void 0;
742
786
  const hasExecutionCount = executionCount !== void 0;
743
787
  const hasOutputs = cell.cell_type === "code" && cell.outputs !== void 0;
744
- return {
788
+ return sortKeysAlphabetically(deepnoteBlockSchema.parse({
745
789
  blockGroup,
746
790
  content: source,
747
791
  ...contentHash ? { contentHash } : {},
@@ -753,7 +797,7 @@ function convertCellToBlock$3(cell, index, idGenerator) {
753
797
  ...hasOutputs ? { outputs: cell.outputs } : {},
754
798
  sortingKey: sortingKey ?? createSortingKey(index),
755
799
  type: blockType
756
- };
800
+ }));
757
801
  }
758
802
 
759
803
  //#endregion
@@ -1438,4 +1482,4 @@ function convertCellToBlock(cell, index, idGenerator) {
1438
1482
  }
1439
1483
 
1440
1484
  //#endregion
1441
- export { convertDeepnoteToJupyterNotebooks as A, serializePercentFormat as C, serializeMarimoFormat as D, convertDeepnoteToMarimoApps as E, convertBlocksToJupyterNotebook as O, convertDeepnoteToPercentNotebooks as S, convertDeepnoteFileToMarimoFiles as T, convertDeepnoteFileToQuartoFiles as _, convertPercentFilesToDeepnoteFile as a, convertBlocksToPercentNotebook as b, parsePercentFormat as c, convertMarimoFilesToDeepnoteFile as d, parseMarimoFormat as f, convertBlocksToQuartoDocument as g, convertJupyterNotebooksToDeepnote as h, parseQuartoFormat as i, convertDeepnoteFileToJupyterFiles as k, convertMarimoAppToBlocks as l, convertJupyterNotebookToBlocks as m, convertQuartoDocumentsToDeepnote as n, convertPercentNotebookToBlocks as o, convertIpynbFilesToDeepnoteFile as p, convertQuartoFilesToDeepnoteFile as r, convertPercentNotebooksToDeepnote as s, convertQuartoDocumentToBlocks as t, convertMarimoAppsToDeepnote as u, convertDeepnoteToQuartoDocuments as v, convertBlocksToMarimoApp as w, convertDeepnoteFileToPercentFiles as x, serializeQuartoFormat as y };
1485
+ export { serializeMarimoFormat as A, convertBlocksToPercentNotebook as C, convertBlocksToMarimoApp as D, serializePercentFormat as E, convertDeepnoteFileToJupyterFiles as M, convertDeepnoteToJupyterNotebooks as N, convertDeepnoteFileToMarimoFiles as O, serializeQuartoFormat as S, convertDeepnoteToPercentNotebooks as T, isMarimoContent as _, convertPercentFilesToDeepnoteFile as a, convertDeepnoteFileToQuartoFiles as b, parsePercentFormat as c, convertMarimoFilesToDeepnoteFile as d, parseMarimoFormat as f, detectFormat as g, convertJupyterNotebooksToDeepnote as h, parseQuartoFormat as i, convertBlocksToJupyterNotebook as j, convertDeepnoteToMarimoApps as k, convertMarimoAppToBlocks as l, convertJupyterNotebookToBlocks as m, convertQuartoDocumentsToDeepnote as n, convertPercentNotebookToBlocks as o, convertIpynbFilesToDeepnoteFile as p, convertQuartoFilesToDeepnoteFile as r, convertPercentNotebooksToDeepnote as s, convertQuartoDocumentToBlocks as t, convertMarimoAppsToDeepnote as u, isPercentContent as v, convertDeepnoteFileToPercentFiles as w, convertDeepnoteToQuartoDocuments as x, convertBlocksToQuartoDocument as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepnote/convert",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "ora": "^9.0.0",
34
34
  "uuid": "^13.0.0",
35
35
  "yaml": "^2.8.1",
36
- "@deepnote/blocks": "2.0.0"
36
+ "@deepnote/blocks": "3.0.1"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^22.0.0",