tandem-editor 0.2.6 → 0.2.7

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/cli/index.js CHANGED
@@ -337,7 +337,7 @@ var init_start = __esm({
337
337
 
338
338
  // src/cli/index.ts
339
339
  import updateNotifier from "update-notifier";
340
- var version = true ? "0.2.6" : "0.0.0-dev";
340
+ var version = true ? "0.2.7" : "0.0.0-dev";
341
341
  updateNotifier({ pkg: { name: "tandem-editor", version } }).notify();
342
342
  var args = process.argv.slice(2);
343
343
  if (args.includes("--help") || args.includes("-h")) {
@@ -60,9 +60,6 @@ function getOrCreateDocument(name) {
60
60
  }
61
61
  return doc;
62
62
  }
63
- function removeDocument(name) {
64
- return documents.delete(name);
65
- }
66
63
  async function startHocuspocus(port) {
67
64
  hocuspocusInstance = new Hocuspocus({
68
65
  port,
@@ -119,9 +116,6 @@ async function startHocuspocus(port) {
119
116
  }
120
117
  return hocuspocusInstance;
121
118
  }
122
- function getHocuspocus() {
123
- return hocuspocusInstance;
124
- }
125
119
  var hocuspocusInstance, documents, shouldKeepDocument, onDocSwapped, onDocUnloaded;
126
120
  var init_provider = __esm({
127
121
  "src/server/yjs/provider.ts"() {
@@ -2827,7 +2821,25 @@ async function openFileByPath(filePath, options) {
2827
2821
  };
2828
2822
  }
2829
2823
  if (forceReload) {
2830
- await forceCloseDocument(id, existing);
2824
+ const doc2 = getDocument(id) ?? getOrCreateDocument(id);
2825
+ const fileName2 = path5.basename(resolved);
2826
+ await clearAndReload(id, doc2, resolved, format, existing);
2827
+ addDoc(id, { id, filePath: resolved, format, readOnly, source: "file" });
2828
+ setActiveDocId(id);
2829
+ broadcastOpenDocs();
2830
+ ensureAutoSave();
2831
+ return {
2832
+ ...buildResult(doc2, {
2833
+ documentId: id,
2834
+ filePath: resolved,
2835
+ fileName: fileName2,
2836
+ format,
2837
+ readOnly,
2838
+ source: "file",
2839
+ restoredFromSession: false
2840
+ }),
2841
+ forceReloaded: true
2842
+ };
2831
2843
  }
2832
2844
  const doc = getOrCreateDocument(id);
2833
2845
  const fileName = path5.basename(resolved);
@@ -2868,7 +2880,7 @@ async function openFileByPath(filePath, options) {
2868
2880
  source: "file",
2869
2881
  restoredFromSession
2870
2882
  }),
2871
- forceReloaded: forceReload === true
2883
+ forceReloaded: false
2872
2884
  };
2873
2885
  }
2874
2886
  async function openFileFromContent(fileName, content) {
@@ -2908,57 +2920,64 @@ async function openFileFromContent(fileName, content) {
2908
2920
  restoredFromSession: false
2909
2921
  });
2910
2922
  }
2911
- async function forceCloseDocument(id, existing) {
2912
- console.error(`[Tandem] forceCloseDocument: tearing down ${id}`);
2913
- let errors = 0;
2914
- try {
2915
- detachObservers(id);
2916
- } catch (err) {
2917
- errors++;
2918
- console.error(`[Tandem] forceCloseDocument: detachObservers failed for ${id}:`, err);
2919
- }
2920
- try {
2921
- removeDoc(id);
2922
- broadcastOpenDocs();
2923
- } catch (err) {
2924
- errors++;
2925
- console.error(`[Tandem] forceCloseDocument: removeDoc/broadcast failed for ${id}:`, err);
2926
- }
2927
- try {
2928
- const hp = getHocuspocus();
2929
- if (hp) {
2930
- hp.closeConnections(id);
2931
- const hpDoc = hp.documents.get(id);
2932
- if (hpDoc) {
2933
- hp.documents.delete(id);
2934
- hpDoc.destroy();
2935
- }
2936
- hp.loadingDocuments.delete(id);
2937
- }
2938
- } catch (err) {
2939
- errors++;
2940
- console.error(`[Tandem] forceCloseDocument: Hocuspocus cleanup failed for ${id}:`, err);
2941
- }
2942
- try {
2943
- const oldDoc = getDocument(id);
2944
- if (oldDoc) {
2945
- oldDoc.destroy();
2946
- removeDocument(id);
2947
- }
2948
- } catch (err) {
2949
- errors++;
2950
- console.error(`[Tandem] forceCloseDocument: Y.Doc removal failed for ${id}:`, err);
2923
+ async function clearAndReload(id, doc, filePath, format, existing) {
2924
+ console.error(`[Tandem] clearAndReload: reloading ${id} from disk`);
2925
+ const isDocx = format === "docx";
2926
+ let preparedHtml;
2927
+ let preparedComments;
2928
+ let preparedContent;
2929
+ if (isDocx) {
2930
+ const buffer3 = await fs3.readFile(filePath);
2931
+ [preparedHtml, preparedComments] = await Promise.all([
2932
+ loadDocx(buffer3),
2933
+ extractDocxComments(buffer3).catch((err) => {
2934
+ console.error(
2935
+ "[docx-comments] Comment extraction failed; document will reload without imported comments:",
2936
+ err
2937
+ );
2938
+ return [];
2939
+ })
2940
+ ]);
2941
+ } else {
2942
+ preparedContent = await fs3.readFile(filePath, "utf-8");
2951
2943
  }
2952
2944
  try {
2953
- await deleteSession(existing.filePath);
2945
+ doc.transact(() => {
2946
+ const annotations = doc.getMap(Y_MAP_ANNOTATIONS);
2947
+ annotations.forEach((_, k) => annotations.delete(k));
2948
+ const awareness = doc.getMap(Y_MAP_AWARENESS);
2949
+ awareness.forEach((_, k) => awareness.delete(k));
2950
+ const userAwareness = doc.getMap(Y_MAP_USER_AWARENESS);
2951
+ userAwareness.forEach((_, k) => userAwareness.delete(k));
2952
+ if (isDocx && preparedHtml !== void 0) {
2953
+ htmlToYDoc(doc, preparedHtml);
2954
+ if (preparedComments && preparedComments.length > 0) {
2955
+ injectCommentsAsAnnotations(doc, preparedComments);
2956
+ }
2957
+ } else if (format === "md" && preparedContent !== void 0) {
2958
+ loadMarkdown(doc, preparedContent);
2959
+ } else if (preparedContent !== void 0) {
2960
+ populateYDoc(doc, preparedContent);
2961
+ }
2962
+ const meta = doc.getMap(Y_MAP_DOCUMENT_META);
2963
+ meta.set("readOnly", isDocx);
2964
+ meta.set("format", format);
2965
+ meta.set("documentId", id);
2966
+ meta.set("fileName", path5.basename(filePath));
2967
+ meta.set(Y_MAP_SAVED_AT_VERSION, Date.now());
2968
+ }, MCP_ORIGIN);
2969
+ attachObservers(id, doc);
2954
2970
  } catch (err) {
2955
- errors++;
2956
- console.error(`[Tandem] forceCloseDocument: deleteSession failed for ${id}:`, err);
2971
+ console.error(
2972
+ `[Tandem] clearAndReload: failed for ${id} (format=${format}). Y.Doc may be in a partially cleared state:`,
2973
+ err
2974
+ );
2975
+ throw err;
2957
2976
  }
2958
- await new Promise((resolve) => setTimeout(resolve, 100));
2959
- console.error(
2960
- `[Tandem] forceCloseDocument: teardown complete for ${id}${errors > 0 ? ` with ${errors} error(s)` : ""}`
2961
- );
2977
+ await deleteSession(existing.filePath).catch((err) => {
2978
+ console.error(`[Tandem] clearAndReload: deleteSession failed for ${id}:`, err);
2979
+ });
2980
+ console.error(`[Tandem] clearAndReload: complete for ${id}`);
2962
2981
  }
2963
2982
  function initSavedBaseline(doc) {
2964
2983
  const meta = doc.getMap(Y_MAP_DOCUMENT_META);
@@ -3010,6 +3029,10 @@ var init_file_opener = __esm({
3010
3029
  init_constants();
3011
3030
  init_queue();
3012
3031
  init_file_io();
3032
+ init_markdown();
3033
+ init_docx();
3034
+ init_docx_html();
3035
+ init_docx_comments();
3013
3036
  init_manager();
3014
3037
  init_document_model();
3015
3038
  init_document_service();