pmx-canvas 0.1.11 โ†’ 0.1.13

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.
@@ -135,8 +135,6 @@ function normalizeExcalidrawBoundText(elements: Array<Record<string, unknown>>):
135
135
 
136
136
  let changed = false;
137
137
  const boundElementIdsByContainer = new Map<string, Set<string>>();
138
- const labelByContainer = new Map<string, Record<string, unknown>>();
139
- const textIdsConvertedToLabels = new Set<string>();
140
138
 
141
139
  for (const element of elements) {
142
140
  if (element.type !== 'text' || typeof element.id !== 'string' || typeof element.containerId !== 'string') continue;
@@ -145,48 +143,28 @@ function normalizeExcalidrawBoundText(elements: Array<Record<string, unknown>>):
145
143
  const ids = boundElementIdsByContainer.get(element.containerId) ?? new Set<string>();
146
144
  ids.add(element.id);
147
145
  boundElementIdsByContainer.set(element.containerId, ids);
148
- const text = typeof element.text === 'string' ? element.text.trim() : '';
149
- if (!isRecord(container.label) && text.length > 0) {
150
- labelByContainer.set(element.containerId, {
151
- text,
152
- ...(typeof element.fontSize === 'number' && Number.isFinite(element.fontSize) ? { fontSize: element.fontSize } : {}),
153
- });
154
- textIdsConvertedToLabels.add(element.id);
155
- }
156
146
  }
157
147
 
158
- const normalized = elements.flatMap<Record<string, unknown>>((element) => {
159
- if (typeof element.id === 'string' && textIdsConvertedToLabels.has(element.id)) {
160
- changed = true;
161
- return [];
162
- }
148
+ const normalized = elements.map((element) => {
163
149
  if (typeof element.id !== 'string') return element;
164
150
  const boundTextIds = boundElementIdsByContainer.get(element.id);
165
- const label = labelByContainer.get(element.id);
166
- if ((!boundTextIds || boundTextIds.size === 0) && !label) return element;
151
+ if (!boundTextIds || boundTextIds.size === 0) return element;
167
152
 
168
153
  const existing = Array.isArray(element.boundElements)
169
154
  ? element.boundElements.filter(isRecord)
170
155
  : [];
171
- const remainingExisting = existing.filter((boundElement) => {
172
- return !(boundElement.type === 'text' && typeof boundElement.id === 'string' && textIdsConvertedToLabels.has(boundElement.id));
173
- });
174
156
  const existingTextIds = new Set(
175
- remainingExisting
157
+ existing
176
158
  .filter((boundElement) => boundElement.type === 'text' && typeof boundElement.id === 'string')
177
159
  .map((boundElement) => boundElement.id as string),
178
160
  );
179
- const missing = [...(boundTextIds ?? [])]
180
- .filter((id) => !textIdsConvertedToLabels.has(id) && !existingTextIds.has(id));
181
- if (missing.length === 0 && !label && remainingExisting.length === existing.length) return element;
161
+ const missing = [...boundTextIds].filter((id) => !existingTextIds.has(id));
162
+ if (missing.length === 0) return element;
182
163
 
183
164
  changed = true;
184
165
  return {
185
166
  ...element,
186
- ...(label ? { label } : {}),
187
- ...(remainingExisting.length > 0 || missing.length > 0
188
- ? { boundElements: [...remainingExisting, ...missing.map((id) => ({ type: 'text', id }))] }
189
- : {}),
167
+ boundElements: [...existing, ...missing.map((id) => ({ type: 'text', id }))],
190
168
  };
191
169
  });
192
170
 
@@ -97,7 +97,7 @@ export class PmxCanvas extends EventEmitter {
97
97
  open?: boolean;
98
98
  automationWebView?: boolean | CanvasAutomationWebViewOptions;
99
99
  }): Promise<void> {
100
- const base = startCanvasServer({ port: this._port });
100
+ const base = startCanvasServer({ port: this._port, allowPortFallback: false });
101
101
  if (!base) {
102
102
  throw new Error(`Failed to start canvas server on port ${this._port}`);
103
103
  }
@@ -605,7 +605,7 @@ export class PmxCanvas extends EventEmitter {
605
605
  async startAutomationWebView(
606
606
  options: CanvasAutomationWebViewOptions = {},
607
607
  ): Promise<CanvasAutomationWebViewStatus> {
608
- const base = this._server ?? startCanvasServer({ port: this._port });
608
+ const base = this._server ?? startCanvasServer({ port: this._port, allowPortFallback: false });
609
609
  if (!base) {
610
610
  throw new Error(`Failed to start canvas server on port ${this._port}`);
611
611
  }
@@ -1639,6 +1639,7 @@ async function handleCanvasBuildWebArtifact(req: Request): Promise<Response> {
1639
1639
  bytes: result.fileSize,
1640
1640
  projectPath: result.projectPath,
1641
1641
  openedInCanvas: result.openedInCanvas,
1642
+ completedAt: result.completedAt,
1642
1643
  // `id` is the canvas node id alias used by every other add-style
1643
1644
  // response. It is only present when a canvas node was actually
1644
1645
  // created (i.e. openInCanvas was not explicitly disabled). When
@@ -3727,6 +3728,7 @@ export interface CanvasServerOptions {
3727
3728
  port?: number;
3728
3729
  workspaceRoot?: string;
3729
3730
  autoOpenBrowser?: boolean;
3731
+ allowPortFallback?: boolean;
3730
3732
  }
3731
3733
 
3732
3734
  export function startCanvasServer(options: CanvasServerOptions = {}): string | null {
@@ -3764,7 +3766,9 @@ export function startCanvasServer(options: CanvasServerOptions = {}): string | n
3764
3766
  rotatePrimaryWorkbenchSessionIfNeeded();
3765
3767
 
3766
3768
  const preferredPort = options.port ?? Number(process.env.PMX_WEB_CANVAS_PORT ?? DEFAULT_PORT);
3767
- const portCandidates = buildPortCandidates(preferredPort);
3769
+ const portCandidates = options.allowPortFallback === false
3770
+ ? [preferredPort > 0 ? Math.floor(preferredPort) : DEFAULT_PORT]
3771
+ : buildPortCandidates(preferredPort);
3768
3772
 
3769
3773
  for (const portCandidate of portCandidates) {
3770
3774
  try {
@@ -116,12 +116,13 @@ else
116
116
  echo "โœ… Using Vite $VITE_VERSION (Node 18 compatible)"
117
117
  fi
118
118
 
119
- # Detect OS and set sed syntax
120
- if [[ "$OSTYPE" == "darwin"* ]]; then
121
- SED_INPLACE="sed -i ''"
122
- else
123
- SED_INPLACE="sed -i"
124
- fi
119
+ function sed_in_place() {
120
+ if [[ "$OSTYPE" == "darwin"* ]]; then
121
+ sed -i '' "$@"
122
+ else
123
+ sed -i "$@"
124
+ fi
125
+ }
125
126
 
126
127
  declare -a PNPM_CMD
127
128
  configure_pnpm
@@ -159,8 +160,8 @@ fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
159
160
  "
160
161
 
161
162
  echo "๐Ÿงน Cleaning up Vite template..."
162
- $SED_INPLACE '/<link rel="icon".*/d' index.html
163
- $SED_INPLACE 's/<title>.*<\/title>/<title>'"$PROJECT_NAME"'<\/title>/' index.html
163
+ sed_in_place '/<link rel="icon".*/d' index.html
164
+ sed_in_place 's/<title>.*<\/title>/<title>'"$PROJECT_NAME"'<\/title>/' index.html
164
165
 
165
166
  echo "๐Ÿ“ฆ Installing base dependencies..."
166
167
  run_pnpm_quiet install
@@ -2,9 +2,11 @@ import { spawn } from 'node:child_process';
2
2
  import {
3
3
  copyFileSync,
4
4
  existsSync,
5
+ readdirSync,
5
6
  mkdirSync,
6
7
  readFileSync,
7
8
  statSync,
9
+ unlinkSync,
8
10
  writeFileSync,
9
11
  } from 'node:fs';
10
12
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from 'node:path';
@@ -71,6 +73,7 @@ export interface WebArtifactCanvasBuildResult extends WebArtifactBuildOutput {
71
73
  openedInCanvas: boolean;
72
74
  nodeId?: string;
73
75
  url?: string;
76
+ completedAt: string;
74
77
  }
75
78
 
76
79
  function currentWorkspaceRoot(): string {
@@ -300,6 +303,14 @@ function writeProjectFiles(
300
303
  }
301
304
  }
302
305
 
306
+ function removeLiteralSedBackupFiles(projectPath: string): void {
307
+ for (const entry of readdirSync(projectPath, { withFileTypes: true })) {
308
+ if (entry.isFile() && entry.name.endsWith("''")) {
309
+ unlinkSync(join(projectPath, entry.name));
310
+ }
311
+ }
312
+ }
313
+
303
314
  function ensurePackageManagerBoundary(dirPath: string): void {
304
315
  const packageJsonPath = join(dirPath, 'package.json');
305
316
  mkdirSync(dirPath, { recursive: true });
@@ -401,6 +412,7 @@ export async function executeWebArtifactBuild(
401
412
  });
402
413
  stdout = [stdout, initResult.stdout].filter(Boolean).join('\n');
403
414
  stderr = [stderr, initResult.stderr].filter(Boolean).join('\n');
415
+ removeLiteralSedBackupFiles(projectPath);
404
416
  }
405
417
 
406
418
  writeProjectFiles(projectPath, input);
@@ -508,7 +520,7 @@ export async function buildWebArtifactOnCanvas(input: WebArtifactBuildInput & {
508
520
  }): Promise<WebArtifactCanvasBuildResult> {
509
521
  const build = await executeWebArtifactBuild(input);
510
522
  if (input.openInCanvas === false) {
511
- return { ...build, openedInCanvas: false };
523
+ return { ...build, openedInCanvas: false, completedAt: new Date().toISOString() };
512
524
  }
513
525
  const opened = openWebArtifactInCanvas({
514
526
  title: input.title,
@@ -519,5 +531,6 @@ export async function buildWebArtifactOnCanvas(input: WebArtifactBuildInput & {
519
531
  openedInCanvas: true,
520
532
  nodeId: opened.nodeId,
521
533
  url: opened.url,
534
+ completedAt: new Date().toISOString(),
522
535
  };
523
536
  }