drafted 1.11.36 → 1.11.37

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/mcp/server.mjs CHANGED
@@ -19,7 +19,7 @@ import { z } from 'zod';
19
19
  import { registerAppResource, RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server';
20
20
  import WebSocket from 'ws';
21
21
  import { LAYERS } from '../src/shared/constants.mjs';
22
- import { emptyExcalidrawScene, excalidrawSceneFromMermaid, stringifyExcalidrawScene } from '../src/shared/excalidraw.mjs';
22
+ import { emptyExcalidrawScene, stringifyExcalidrawScene } from '../src/shared/excalidraw.mjs';
23
23
  import { createGateState, markSearched, g1Block, g2Block, g3Block, selectWithinBudget, wouldExceedBudget, budgetError, formatWikiIndex, PROJECT_CONTEXT_BUDGET_CHARS } from './gates.mjs';
24
24
  import { loadPersistedProject, savePersistedProject } from './active-project-store.mjs';
25
25
 
@@ -2046,7 +2046,6 @@ tool('frame', 'Frame CRUD in the ACTIVE PROJECT. Dispatch by `action`: read (by
2046
2046
  content: z.string().optional().describe('[write] HTML/markdown/text for Drafted inline frames. [write_doc_content|append_doc_content] native Google Doc body text. Do not use action=write content to populate Google Doc/Slide frames.'),
2047
2047
  excalidraw_data: z.any().optional().describe('[write_excalidraw] Excalidraw scene JSON object or JSON string. Defaults to an empty scene.'),
2048
2048
  state: z.any().optional().describe('[set_state] App-frame state object (JSON) to persist for a deployed windowType:"app" frame — e.g. {specText:"..."} for the AS/NZS electrical app. The canvas hydrates the app from this on load (the host posts a "hydrate" message with it when the frame mounts), so you can deploy a generic app frame once and drive it with data afterwards. Max 64KB. Frame must be an app frame.'),
2049
- mermaid: z.string().optional().describe('[write_excalidraw] Mermaid source to convert into an editable Excalidraw scene.'),
2050
2049
  file_path: z.string().optional().describe('[write] absolute path to a local file to upload. Mutually exclusive with content/base64/googleType.'),
2051
2050
  base64: z.string().optional().describe('[write] base64-encoded binary content. Mutually exclusive with content/file_path/googleType. Use with content_type when known.'),
2052
2051
  content_type: z.string().optional().describe('[write + base64] MIME type for base64 binary content, e.g. image/png, application/pdf. Defaults from the path extension or application/octet-stream.'),
@@ -2438,13 +2437,12 @@ tool('frame', 'Frame CRUD in the ACTIVE PROJECT. Dispatch by `action`: read (by
2438
2437
  });
2439
2438
  }
2440
2439
  case 'write_excalidraw': {
2441
- const { path, excalidraw_data, mermaid, width, height, color } = args;
2440
+ const { path, excalidraw_data, width, height, color } = args;
2442
2441
  if (!path) throw new Error('path required for action=write_excalidraw');
2443
- if (excalidraw_data != null && mermaid) throw new Error('Provide only one of excalidraw_data or mermaid');
2444
2442
  const parts = path.replace(/^\/+/, '').split('/');
2445
2443
  if (parts.length !== 3) throw new Error('Path must be /{layer}/{lane}/{filename}');
2446
2444
  const filename = parts[2].toLowerCase().endsWith('.excalidraw') ? parts[2] : parts[2] + '.excalidraw';
2447
- const scene = mermaid ? await excalidrawSceneFromMermaid(mermaid) : (excalidraw_data ?? emptyExcalidrawScene());
2445
+ const scene = excalidraw_data ?? emptyExcalidrawScene();
2448
2446
  const body = { content: stringifyExcalidrawScene(scene) };
2449
2447
  if (width) body.width = width;
2450
2448
  if (height) body.height = height;
@@ -3462,13 +3460,12 @@ tool('wiki', 'Per-org wiki. Markdown pages with paths as hierarchy. You and othe
3462
3460
  // `LINE+ID|content`). The server applies the ops via the same
3463
3461
  // hashline algorithm — no client-side re-hashing, no algorithm drift.
3464
3462
  case 'write_excalidraw': {
3465
- const { path, excalidraw_data, mermaid, width, height, color } = args;
3463
+ const { path, excalidraw_data, width, height, color } = args;
3466
3464
  if (!path) throw new Error('path required for action=write_excalidraw');
3467
- if (excalidraw_data != null && mermaid) throw new Error('Provide only one of excalidraw_data or mermaid');
3468
3465
  const parts = path.replace(/^\/+/, '').split('/');
3469
3466
  if (parts.length !== 3) throw new Error('Path must be /{layer}/{lane}/{filename}');
3470
3467
  const filename = parts[2].toLowerCase().endsWith('.excalidraw') ? parts[2] : parts[2] + '.excalidraw';
3471
- const scene = mermaid ? await excalidrawSceneFromMermaid(mermaid) : (excalidraw_data ?? emptyExcalidrawScene());
3468
+ const scene = excalidraw_data ?? emptyExcalidrawScene();
3472
3469
  const body = { content: stringifyExcalidrawScene(scene) };
3473
3470
  if (width) body.width = width;
3474
3471
  if (height) body.height = height;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.11.36",
3
+ "version": "1.11.37",
4
4
  "description": "Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.",
5
5
  "type": "module",
6
6
  "files": [
@@ -45,7 +45,6 @@
45
45
  "@clerk/express": "^2.1.4",
46
46
  "@clerk/mcp-tools": "^0.3.1",
47
47
  "@excalidraw/excalidraw": "^0.18.1",
48
- "@excalidraw/mermaid-to-excalidraw": "^2.2.2",
49
48
  "@modelcontextprotocol/ext-apps": "^1.6.0",
50
49
  "@modelcontextprotocol/sdk": "^1.27.1",
51
50
  "@sentry/browser": "^10.53.1",
@@ -59,7 +58,6 @@
59
58
  "esbuild": "^0.28.0",
60
59
  "exceljs": "^4.4.0",
61
60
  "express": "^4.18.2",
62
- "jsdom": "^27.0.1",
63
61
  "jszip": "^3.10.1",
64
62
  "lucide": "^1.16.0",
65
63
  "mdast-util-from-markdown": "^2.0.3",
@@ -38,64 +38,3 @@ export function normalizeExcalidrawScene(input) {
38
38
  export function stringifyExcalidrawScene(input) {
39
39
  return JSON.stringify(normalizeExcalidrawScene(input), null, 2);
40
40
  }
41
-
42
- function restoreMermaidDom(previous, dom) {
43
- for (const [key, value] of Object.entries(previous)) {
44
- if (value === undefined) {
45
- try { delete globalThis[key]; } catch {}
46
- } else if (key === 'navigator') {
47
- Object.defineProperty(globalThis, 'navigator', { value, configurable: true });
48
- } else {
49
- globalThis[key] = value;
50
- }
51
- }
52
- if (dom) dom.window.close();
53
- }
54
-
55
- export async function excalidrawSceneFromMermaid(mermaid) {
56
- let dom;
57
- const previous = {
58
- window: globalThis.window,
59
- document: globalThis.document,
60
- DOMParser: globalThis.DOMParser,
61
- XMLSerializer: globalThis.XMLSerializer,
62
- Element: globalThis.Element,
63
- SVGElement: globalThis.SVGElement,
64
- navigator: globalThis.navigator,
65
- CSSStyleSheet: globalThis.CSSStyleSheet,
66
- };
67
- try {
68
- if (typeof document === 'undefined') {
69
- const { JSDOM } = await import('jsdom');
70
- dom = new JSDOM('<!doctype html><html><body></body></html>');
71
- globalThis.window = dom.window;
72
- globalThis.document = dom.window.document;
73
- globalThis.DOMParser = dom.window.DOMParser;
74
- globalThis.XMLSerializer = dom.window.XMLSerializer;
75
- globalThis.Element = dom.window.Element;
76
- globalThis.SVGElement = dom.window.SVGElement;
77
- if (globalThis.SVGElement && !globalThis.SVGElement.prototype.getBBox) {
78
- globalThis.SVGElement.prototype.getBBox = function () {
79
- const text = this.textContent || '';
80
- return { x: 0, y: 0, width: Math.max(24, text.length * 8), height: 20 };
81
- };
82
- }
83
- Object.defineProperty(globalThis, 'navigator', { value: dom.window.navigator, configurable: true });
84
- globalThis.CSSStyleSheet = class {
85
- constructor() { this.cssRules = []; }
86
- replaceSync() { this.cssRules = []; }
87
- insertRule(rule) { this.cssRules.push({ cssText: rule }); }
88
- };
89
- }
90
- const { parseMermaidToExcalidraw } = await import('@excalidraw/mermaid-to-excalidraw');
91
- const result = await parseMermaidToExcalidraw(mermaid);
92
- return {
93
- ...emptyExcalidrawScene(),
94
- elements: result.elements || [],
95
- files: result.files || {},
96
- appState: { viewBackgroundColor: '#ffffff' },
97
- };
98
- } finally {
99
- if (dom) restoreMermaidDom(previous, dom);
100
- }
101
- }