@hwp-editor/react 1.4.0 → 1.4.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/index.cjs CHANGED
@@ -58,7 +58,7 @@ module.exports = __toCommonJS(index_exports);
58
58
 
59
59
  // src/HwpEditor.tsx
60
60
  var import_react13 = require("react");
61
- var import_core19 = require("@hwp-editor/core");
61
+ var import_core20 = require("@hwp-editor/core");
62
62
 
63
63
  // src/context.ts
64
64
  var import_react = require("react");
@@ -75,7 +75,7 @@ function useHwpEditorContext() {
75
75
 
76
76
  // src/PageCanvas.tsx
77
77
  var import_react2 = require("react");
78
- var import_core2 = require("@hwp-editor/core");
78
+ var import_core3 = require("@hwp-editor/core");
79
79
 
80
80
  // src/geometry.ts
81
81
  var import_core = require("@hwp-editor/core");
@@ -130,21 +130,46 @@ function idIndex(envelope) {
130
130
  idIndexes.set(envelope, index);
131
131
  return index;
132
132
  }
133
+ var pathIndexes = /* @__PURE__ */ new WeakMap();
134
+ function pathIndex(envelope) {
135
+ const cached = pathIndexes.get(envelope);
136
+ if (cached !== void 0) return cached;
137
+ const index = /* @__PURE__ */ new Map();
138
+ for (const segment of envelope.segments) {
139
+ if (segment.id !== void 0 || segment.kind !== "para") continue;
140
+ const key = [segment.section, ...segment.indices ?? [segment.para]].join(".");
141
+ if (!index.has(key)) index.set(key, segment);
142
+ }
143
+ pathIndexes.set(envelope, index);
144
+ return index;
145
+ }
146
+ function rowSegment(envelope, rowId) {
147
+ const byId = idIndex(envelope).get(rowId);
148
+ if (byId !== void 0) return byId;
149
+ const path = (0, import_core.segmentIdPath)(rowId);
150
+ return path.length === 0 ? void 0 : pathIndex(envelope).get(path.join("."));
151
+ }
152
+ function hasIds(envelope) {
153
+ return envelope.segments.some((segment) => segment.id !== void 0);
154
+ }
155
+ function rowDraws(envelope, rowId, segment) {
156
+ if (segment.id !== void 0) return rowId === segment.id;
157
+ return rowSegment(envelope, rowId) === segment;
158
+ }
133
159
  function segmentOnPage(envelope, page, xFraction, yFraction, pageIndex, pageCount) {
134
- if (page.layout === void 0 || !envelope.segments.some((segment) => segment.id !== void 0)) {
160
+ if (page.layout === void 0 || !hasIds(envelope) && page.layout.rows.every((row) => rowSegment(envelope, row.id) === void 0)) {
135
161
  return nearestSegment(envelope, pageIndex, yFraction, pageCount);
136
162
  }
137
163
  const { width_pt, height_pt, rows } = page.layout;
138
164
  const x = clamp(xFraction, 0, 1) * width_pt;
139
165
  const y = clamp(yFraction, 0, 1) * height_pt;
140
- const byId = idIndex(envelope);
141
166
  let best;
142
167
  let bestVertical = Infinity;
143
168
  let bestHorizontal = Infinity;
144
169
  let bestArea = Infinity;
145
170
  for (const row of rows) {
146
171
  const box = row.box;
147
- const segment = byId.get(row.id);
172
+ const segment = rowSegment(envelope, row.id);
148
173
  if (box === null || segment === void 0) continue;
149
174
  const dx = Math.max(box.x0 - x, 0, x - box.x1);
150
175
  const dy = Math.max(box.y0 - y, 0, y - box.y1);
@@ -161,13 +186,13 @@ function segmentOnPage(envelope, page, xFraction, yFraction, pageIndex, pageCoun
161
186
  return best;
162
187
  }
163
188
  function bandsOnPage(envelope, segment, page, pageIndex, pageCount) {
164
- if (page.layout === void 0 || segment.id === void 0) {
189
+ if (page.layout === void 0) {
165
190
  const band = segmentBand(envelope, segment, pageCount);
166
- return band?.pageIndex === pageIndex ? [{ left: 0, top: band.top, width: 100, height: band.height }] : [];
191
+ return band?.pageIndex === pageIndex ? [{ left: 0, top: band.top, width: 100, height: band.height, approximate: true }] : [];
167
192
  }
168
193
  const target = ["run", "image", "field"].includes(segment.kind) && segment.indices !== void 0 ? envelope.segments.find((candidate) => candidate.kind === "para" && candidate.section === segment.section && candidate.indices !== void 0 && candidate.indices.length === segment.indices.length - 1 && candidate.indices.every((value, index) => value === segment.indices[index])) ?? segment : segment;
169
194
  const { width_pt, height_pt, rows } = page.layout;
170
- return rows.filter((row) => row.id === target.id && row.box !== null).map((row) => {
195
+ return rows.filter((row) => row.box !== null && rowDraws(envelope, row.id, target)).map((row) => {
171
196
  const box = row.box;
172
197
  return {
173
198
  left: box.x0 / width_pt * 100,
@@ -179,6 +204,7 @@ function bandsOnPage(envelope, segment, page, pageIndex, pageCount) {
179
204
  }
180
205
 
181
206
  // src/text.ts
207
+ var import_core2 = require("@hwp-editor/core");
182
208
  function plainSegmentText(markdownSlice) {
183
209
  return markdownSlice.split("\n").map(stripLine).join("\n").trim();
184
210
  }
@@ -192,6 +218,41 @@ function stripLine(line) {
192
218
  out = out.replace(/`([^`]*)`/g, "$1");
193
219
  return out;
194
220
  }
221
+ var LIST_MARKER = /^[ \t]*(?:\d{1,9}[.)]|[-*+])[ \t]+/;
222
+ function paragraphSourceText(envelope, para, pages = []) {
223
+ const plain = plainSegmentText((0, import_core2.segmentText)(envelope, para));
224
+ const marker = LIST_MARKER.exec(plain);
225
+ if (marker === null) return plain;
226
+ const stripped = plain.slice(marker[0].length);
227
+ if (para.indices !== void 0) {
228
+ const first = envelope.segments.find((candidate) => candidate.kind === "run" && candidate.section === para.section && candidate.indices !== void 0 && candidate.indices.length === para.indices.length + 1 && para.indices.every((value, index) => candidate.indices[index] === value));
229
+ if (first !== void 0) {
230
+ const lead = [...(0, import_core2.segmentText)(envelope, para)].slice(0, Math.max(0, first.start - para.start)).join("");
231
+ return LIST_MARKER.test(lead) && lead.trim() === marker[0].trim() ? stripped : plain;
232
+ }
233
+ }
234
+ const length = sourceLength(para, pages);
235
+ if (length === void 0) return plain;
236
+ return stripped.length === length && plain.length !== length ? stripped : plain;
237
+ }
238
+ function sourceLength(para, pages) {
239
+ let start = Infinity;
240
+ let end = -Infinity;
241
+ for (const page of pages) {
242
+ for (const row of page.layout?.rows ?? []) {
243
+ if (row.kind !== "para" || row.source_chars === null || !rowMatches(row.id, para)) continue;
244
+ start = Math.min(start, row.source_chars.start);
245
+ end = Math.max(end, row.source_chars.end);
246
+ }
247
+ }
248
+ return end >= start ? end - start : void 0;
249
+ }
250
+ function rowMatches(rowId, segment) {
251
+ if (segment.id !== void 0) return rowId === segment.id;
252
+ const path = (0, import_core2.segmentIdPath)(rowId);
253
+ const own = [segment.section, ...segment.indices ?? [segment.para]];
254
+ return path.length === own.length && path.every((value, index) => value === own[index]);
255
+ }
195
256
 
196
257
  // src/PageCanvas.tsx
197
258
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -206,11 +267,11 @@ function PageCanvas() {
206
267
  if (envelope !== null) {
207
268
  const refs = state.selections?.length ? state.selections : selection === null ? [] : [selection];
208
269
  for (const ref of refs) {
209
- const segment = (0, import_core2.segmentAtRef)(envelope, ref);
270
+ const segment = (0, import_core3.segmentAtRef)(envelope, ref);
210
271
  if (segment !== void 0) selectedSegments.add(segment);
211
272
  }
212
273
  }
213
- if (pages.length === 0) {
274
+ if (pages.length === 0 || envelope === null) {
214
275
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hwped-canvas", role: "main", "aria-label": t("canvas.aria"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hwped-empty", children: t("canvas.emptyPages") }) });
215
276
  }
216
277
  const selectAt = (pageIndex, xFraction, yFraction, modifiers) => {
@@ -218,7 +279,7 @@ function PageCanvas() {
218
279
  const segment = segmentOnPage(envelope, pages[pageIndex], xFraction, yFraction, pageIndex, pages.length);
219
280
  if (segment !== void 0) {
220
281
  const mode = modifiers?.shiftKey ? "extend" : modifiers?.metaKey || modifiers?.ctrlKey ? "toggle" : "single";
221
- store.dispatch((0, import_core2.selectionAction)(envelope, store.getState(), segment, mode));
282
+ store.dispatch((0, import_core3.selectionAction)(envelope, store.getState(), segment, mode));
222
283
  }
223
284
  };
224
285
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hwped-canvas", role: "main", "aria-label": t("canvas.aria"), children: pages.map((page, pageIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -264,7 +325,7 @@ function bandsForPage(envelope, page, pageIndex, pageCount, selected, pendingKey
264
325
  bands.push({
265
326
  ...band,
266
327
  key: `${isSelected ? "sel" : "pend"}-${key}-${bandIdentity(segment)}-${index}`,
267
- className: isSelected ? "hwped-band hwped-band-selected" : "hwped-band hwped-band-pending"
328
+ className: (isSelected ? "hwped-band hwped-band-selected" : "hwped-band hwped-band-pending") + (band.approximate ? " hwped-band-approximate" : "")
268
329
  });
269
330
  }
270
331
  }
@@ -276,7 +337,7 @@ function PageView(props) {
276
337
  const label = t("page.label", { page: page.page });
277
338
  const imgSrc = (0, import_react2.useMemo)(() => {
278
339
  const mime = page.format === "jpeg" ? "image/jpeg" : page.format === "svg" ? "image/svg+xml" : `image/${page.format}`;
279
- return `data:${mime};base64,${import_core2.base64.encode(page.data)}`;
340
+ return `data:${mime};base64,${import_core3.base64.encode(page.data)}`;
280
341
  }, [page]);
281
342
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
282
343
  "div",
@@ -308,6 +369,7 @@ function PageView(props) {
308
369
  "div",
309
370
  {
310
371
  className: band.className,
372
+ "data-approximate": band.className.includes("hwped-band-approximate") ? "true" : void 0,
311
373
  style: { top: `${band.top}%`, height: `${band.height}%`, left: `${band.left}%`, width: `${band.width}%` }
312
374
  },
313
375
  band.key
@@ -340,7 +402,7 @@ function targetsSegment(op, envelope, segment) {
340
402
  return "run" in at ? segment.kind === "run" && segment.indices?.length === 2 && segment.indices[1] === at.run : segment.kind === "para" && (segment.indices === void 0 || segment.indices.length === 1);
341
403
  }
342
404
  const target = opSearchText(op);
343
- return target !== null && target !== "" && plainSegmentText((0, import_core2.segmentText)(envelope, segment)).includes(target);
405
+ return target !== null && target !== "" && plainSegmentText((0, import_core3.segmentText)(envelope, segment)).includes(target);
344
406
  }
345
407
 
346
408
  // src/unit-input.ts
@@ -351,7 +413,7 @@ function isPlainDecimal(value) {
351
413
 
352
414
  // src/SegmentInspector.tsx
353
415
  var import_react3 = require("react");
354
- var import_core3 = require("@hwp-editor/core");
416
+ var import_core4 = require("@hwp-editor/core");
355
417
  var import_jsx_runtime2 = require("react/jsx-runtime");
356
418
  var ALIGNMENTS = [
357
419
  { value: "left", key: "segment.alignLeft" },
@@ -381,15 +443,15 @@ function SegmentInspector() {
381
443
  const paragraphKeys = /* @__PURE__ */ new Set();
382
444
  const paragraphs = (envelope?.segments.filter((candidate) => {
383
445
  if (candidate.kind !== "para") return false;
384
- if (!(0, import_core3.hasOwnRef)(candidate)) return false;
446
+ if (!(0, import_core4.hasOwnRef)(candidate)) return false;
385
447
  const key = candidate.id ?? `${candidate.section}:${candidate.para}`;
386
448
  if (paragraphKeys.has(key)) return false;
387
449
  paragraphKeys.add(key);
388
450
  return true;
389
- }) ?? []).sort(import_core3.compareSegments);
390
- const selected = envelope === null ? [] : (0, import_core3.selectedParagraphs)(envelope, state);
391
- const segment = envelope !== null && selection !== null ? (0, import_core3.segmentAtRef)(envelope, selection) : void 0;
392
- const targets = envelope !== null && segment !== void 0 ? (0, import_core3.resolveSelection)(envelope, segment) : void 0;
451
+ }) ?? []).sort(import_core4.compareSegments);
452
+ const selected = envelope === null ? [] : (0, import_core4.selectedParagraphs)(envelope, state);
453
+ const segment = envelope !== null && selection !== null ? (0, import_core4.segmentAtRef)(envelope, selection) : void 0;
454
+ const targets = envelope !== null && segment !== void 0 ? (0, import_core4.resolveSelection)(envelope, segment) : void 0;
393
455
  const paragraphTargets = targets?.paragraphs ?? [];
394
456
  const singleParagraph = targets?.paragraph;
395
457
  const directStyleRow = (() => {
@@ -397,13 +459,13 @@ function SegmentInspector() {
397
459
  if (id === void 0 || styles === null) return void 0;
398
460
  return styles.styles.find((item) => item.kind === "paragraph" && item.used_by.includes(id));
399
461
  })();
400
- const directStyleWhy = directStyleRow !== void 0 ? null : stylesStatus === "loading" ? "segment.directStyleLoading" : stylesStatus === "failed" ? "segment.directStyleFailed" : stylesStatus === "unsupported" ? "styles.unavailableHost" : capabilities === null ? "styles.checkingHost" : capabilities.styles !== "v1" ? (0, import_core3.stylesVersionSupported)(capabilities.version) ? "styles.unavailableHost" : "segment.directStyleUnavailable" : "segment.directStyleUnknown";
462
+ const directStyleWhy = directStyleRow !== void 0 ? null : stylesStatus === "loading" ? "segment.directStyleLoading" : stylesStatus === "failed" ? "segment.directStyleFailed" : stylesStatus === "unsupported" ? "styles.unavailableHost" : capabilities === null ? "styles.checkingHost" : capabilities.styles !== "v1" ? (0, import_core4.stylesVersionSupported)(capabilities.version) ? "styles.unavailableHost" : "segment.directStyleUnavailable" : "segment.directStyleUnknown";
401
463
  const refusalText = (reason) => reason === null || reason === void 0 ? null : reason === "cell" ? t("segment.cellSelectionRefused") : reason === "table" ? t("segment.tableSelectionRefused") : reason === "container" ? t("segment.containerSelectionRefused") : t("segment.noParagraphSelection");
402
464
  const clickRefusedText = (reason) => reason === null || reason === void 0 ? null : t(CLICK_REFUSAL_MESSAGE[reason]);
403
465
  const refusalReason2 = refusalText(targets?.refusal);
404
- const targetLabel = segment === void 0 ? "" : segment.kind === "cell" ? t("segment.selectedCell", { path: (0, import_core3.segmentPath)(segment), count: paragraphTargets.length }) : singleParagraph === void 0 ? "" : t("segment.selectedPara", { path: (0, import_core3.segmentPath)(singleParagraph) });
405
- const currentText = envelope !== null && paragraphTargets.length > 0 ? plainSegmentText(paragraphTargets.map((candidate) => (0, import_core3.segmentText)(envelope, candidate)).join("\n")) : "";
406
- const markdownText = envelope !== null && singleParagraph !== void 0 ? (0, import_core3.segmentText)(envelope, singleParagraph) : "";
466
+ const targetLabel = segment === void 0 ? "" : segment.kind === "cell" ? t("segment.selectedCell", { path: (0, import_core4.segmentPath)(segment), count: paragraphTargets.length }) : singleParagraph === void 0 ? "" : t("segment.selectedPara", { path: (0, import_core4.segmentPath)(singleParagraph) });
467
+ const currentText = envelope !== null && paragraphTargets.length > 0 ? paragraphTargets.map((candidate) => paragraphSourceText(envelope, candidate, state.pages)).join("\n").trim() : "";
468
+ const markdownText = envelope !== null && singleParagraph !== void 0 ? (0, import_core4.segmentText)(envelope, singleParagraph) : "";
407
469
  const supplementaryStarts = (0, import_react3.useMemo)(() => {
408
470
  const positions = [];
409
471
  let offset = 0;
@@ -439,19 +501,19 @@ function SegmentInspector() {
439
501
  setPlaceholderName("");
440
502
  }, [selection]);
441
503
  const find = currentText;
442
- const address = singleParagraph === void 0 ? void 0 : (0, import_core3.paragraphAddress)(singleParagraph);
504
+ const address = singleParagraph === void 0 ? void 0 : (0, import_core4.paragraphAddress)(singleParagraph);
443
505
  const siblings = singleParagraph?.indices === void 0 ? [] : paragraphs.filter((candidate) => candidate.section === singleParagraph.section && candidate.id !== void 0 && candidate.indices !== void 0 && candidate.indices.length === singleParagraph.indices.length && singleParagraph.indices.slice(0, -1).every((index, at) => candidate.indices[at] === index));
444
506
  const siblingAt = siblings.findIndex((candidate) => candidate.id === singleParagraph?.id);
445
507
  const addressedUnavailable = capabilities?.editOps !== "v1";
446
508
  const disabled = !editable || addressedUnavailable || state.status === "applying";
447
509
  const selectedRefs = state.selections?.length ? state.selections : selection === null ? [] : [selection];
448
510
  const explicitSegments = envelope === null ? [] : selectedRefs.flatMap((ref) => {
449
- const item = (0, import_core3.segmentAtRef)(envelope, ref);
511
+ const item = (0, import_core4.segmentAtRef)(envelope, ref);
450
512
  return item === void 0 ? [] : [item];
451
513
  });
452
514
  const hasRunSelection = explicitSegments.some((item) => item.kind === "run");
453
515
  const multiSelection = explicitSegments.length > 1;
454
- const paragraphRun = multiSelection && explicitSegments.every((item) => item.kind === "para") ? [...explicitSegments].sort(import_core3.compareSegments) : null;
516
+ const paragraphRun = multiSelection && explicitSegments.every((item) => item.kind === "para") ? [...explicitSegments].sort(import_core4.compareSegments) : null;
455
517
  const runStart = paragraphRun === null ? -1 : siblings.findIndex((candidate) => candidate.id === paragraphRun[0]?.id);
456
518
  const runContiguous = paragraphRun !== null && runStart >= 0 && paragraphRun.every((item, at) => siblings[runStart + at]?.id === item.id);
457
519
  const runEnd = runContiguous ? runStart + paragraphRun.length - 1 : -1;
@@ -462,7 +524,7 @@ function SegmentInspector() {
462
524
  if (insertionRun === null || !insertionCurrent || runParent === void 0) return [];
463
525
  const section = insertionRun[0].section;
464
526
  return insertedHidden.ids.flatMap((id) => {
465
- const [idSection, ...indices] = (0, import_core3.segmentIdPath)(id);
527
+ const [idSection, ...indices] = (0, import_core4.segmentIdPath)(id);
466
528
  if (idSection !== section || indices.length !== runParent.length + 1) return [];
467
529
  if (!runParent.every((index, at) => indices[at] === index)) return [];
468
530
  return [{ id, index: indices[indices.length - 1] }];
@@ -473,16 +535,16 @@ function SegmentInspector() {
473
535
  if (published === void 0) return void 0;
474
536
  const publishedIndex = published.indices?.[published.indices.length - 1];
475
537
  const beyond = hiddenInRun.filter((hidden) => publishedIndex === void 0 || (edge === "first" ? hidden.index < publishedIndex : hidden.index > publishedIndex));
476
- if (beyond.length === 0) return (0, import_core3.paragraphAddress)(published);
538
+ if (beyond.length === 0) return (0, import_core4.paragraphAddress)(published);
477
539
  const pick = beyond.reduce((best, hidden) => (edge === "first" ? hidden.index < best.index : hidden.index > best.index) ? hidden : best);
478
540
  return { id: pick.id };
479
541
  };
480
542
  const textSelectionRestricted = multiSelection || hasRunSelection || state.range != null;
481
543
  const singleTargetDisabled = disabled || textSelectionRestricted || address === void 0;
482
544
  const reorderRefused = multiSelection && !runContiguous;
483
- const definitionLocked = paragraphRun === null ? singleParagraph !== void 0 && (0, import_core3.isSectionDefinitionParagraph)(singleParagraph) : paragraphRun.some(import_core3.isSectionDefinitionParagraph);
545
+ const definitionLocked = paragraphRun === null ? singleParagraph !== void 0 && (0, import_core4.isSectionDefinitionParagraph)(singleParagraph) : paragraphRun.some(import_core4.isSectionDefinitionParagraph);
484
546
  const moveUpNeighbour = siblings[(paragraphRun === null ? siblingAt : runStart) - 1];
485
- const definitionAbove = moveUpNeighbour !== void 0 && (0, import_core3.isSectionDefinitionParagraph)(moveUpNeighbour);
547
+ const definitionAbove = moveUpNeighbour !== void 0 && (0, import_core4.isSectionDefinitionParagraph)(moveUpNeighbour);
486
548
  const deleteDisabled = disabled || definitionLocked || (paragraphRun === null ? textSelectionRestricted || address === void 0 : !runContiguous);
487
549
  const moveUpDisabled = deleteDisabled || definitionAbove || (paragraphRun === null ? siblingAt <= 0 : runStart <= 0);
488
550
  const moveDownDisabled = deleteDisabled || (paragraphRun === null ? siblingAt < 0 || siblingAt >= siblings.length - 1 : runEnd >= siblings.length - 1);
@@ -490,12 +552,12 @@ function SegmentInspector() {
490
552
  const legacyLinkSeparator = capabilities?.editOps !== "v1" && [currentText, linkText, linkUrl].some((value) => value.includes("=>"));
491
553
  const validShape = isPlainDecimal(shapeValue) && (shapeKey !== "line-spacing" || Number(shapeValue) > 0);
492
554
  const validFontSize = fontSize.trim() === "" || isPlainDecimal(fontSize) && Number(fontSize) > 0;
493
- const formatInputs = envelope === null ? [] : explicitSegments.flatMap((item) => item.kind === "run" ? [item] : (0, import_core3.resolveSelection)(envelope, item).paragraphs).sort(import_core3.compareSegments);
494
- const formatTargets = envelope === null ? [] : (0, import_core3.formatTargets)(envelope, formatInputs, state.range, (0, import_core3.documentFormat)(state.document?.name, state.document?.data));
495
- const runs = envelope === null || singleParagraph === void 0 ? [] : (0, import_core3.paragraphRuns)(envelope, singleParagraph);
555
+ const formatInputs = envelope === null ? [] : explicitSegments.flatMap((item) => item.kind === "run" ? [item] : (0, import_core4.resolveSelection)(envelope, item).paragraphs).sort(import_core4.compareSegments);
556
+ const formatTargets = envelope === null ? [] : (0, import_core4.formatTargets)(envelope, formatInputs, state.range, (0, import_core4.documentFormat)(state.document?.name, state.document?.data));
557
+ const runs = envelope === null || singleParagraph === void 0 ? [] : (0, import_core4.paragraphRuns)(envelope, singleParagraph);
496
558
  const formatNoRuns = state.range == null && singleParagraph !== void 0 && singleParagraph.start !== singleParagraph.end && singleParagraph.indices === void 0 && runs.length === 0;
497
559
  const rangeAvailable = !multiSelection && runs.some((run) => run.id !== void 0 || singleParagraph?.indices?.length === 1 && run.indices?.length === 2);
498
- const charPrimary = segment?.kind === "run" ? segment : envelope !== null && state.range != null && formatTargets[0]?.address.id !== void 0 ? (0, import_core3.segmentAtRef)(envelope, { id: formatTargets[0].address.id, section: 0, para: 0 }) ?? singleParagraph : singleParagraph;
560
+ const charPrimary = segment?.kind === "run" ? segment : envelope !== null && state.range != null && formatTargets[0]?.address.id !== void 0 ? (0, import_core4.segmentAtRef)(envelope, { id: formatTargets[0].address.id, section: 0, para: 0 }) ?? singleParagraph : singleParagraph;
499
561
  const plainParagraph = (() => {
500
562
  if (envelope === null || singleParagraph === void 0) return void 0;
501
563
  const depth = singleParagraph.indices?.length;
@@ -506,7 +568,7 @@ function SegmentInspector() {
506
568
  const contentEnd = singleParagraph.start + points.length;
507
569
  const holdsControl = envelope.segments.some((item) => (item.kind === "field" || item.kind === "image" || item.kind === "bookmark") && item.start < contentEnd && item.end > singleParagraph.start);
508
570
  if (holdsControl) return void 0;
509
- const ordered = (0, import_core3.paragraphRuns)(envelope, singleParagraph);
571
+ const ordered = (0, import_core4.paragraphRuns)(envelope, singleParagraph);
510
572
  let cursor = singleParagraph.start;
511
573
  for (const run of ordered) {
512
574
  if (run.start !== cursor || run.end < run.start || run.end > contentEnd) return void 0;
@@ -522,7 +584,7 @@ function SegmentInspector() {
522
584
  if (/^(?:[-+]|\d{1,3}[.)])\s/u.test(text)) return void 0;
523
585
  return { runs: ordered, texts, text };
524
586
  })();
525
- const rangeRuns = envelope !== null && singleParagraph !== void 0 && state.range != null ? (0, import_core3.paragraphRuns)(envelope, singleParagraph, state.range) : [];
587
+ const rangeRuns = envelope !== null && singleParagraph !== void 0 && state.range != null ? (0, import_core4.paragraphRuns)(envelope, singleParagraph, state.range) : [];
526
588
  const rangeFrom = rangeRuns.length === 0 ? -1 : Math.min(...rangeRuns.map((item) => item.start));
527
589
  const rangeTo = rangeRuns.length === 0 ? -1 : Math.max(...rangeRuns.map((item) => item.end));
528
590
  const wholeRuns = state.range != null && rangeRuns.length > 0 && rangeFrom === state.range.start && rangeTo === state.range.end;
@@ -555,7 +617,7 @@ function SegmentInspector() {
555
617
  };
556
618
  const activateSelection = (target, mode) => {
557
619
  if (envelope === null) return;
558
- store.dispatch((0, import_core3.selectionAction)(envelope, store.getState(), target, mode));
620
+ store.dispatch((0, import_core4.selectionAction)(envelope, store.getState(), target, mode));
559
621
  };
560
622
  const handleOptionKeyDown = (event, target) => {
561
623
  if (event.key !== "Enter" && event.key !== " ") return;
@@ -566,11 +628,11 @@ function SegmentInspector() {
566
628
  if (envelope === null || singleParagraph === void 0) return;
567
629
  const match = level === "char" ? charPrimary : singleParagraph;
568
630
  if (match === void 0) return;
569
- const refs = (0, import_core3.selectSimilar)(envelope, match, level);
631
+ const refs = (0, import_core4.selectSimilar)(envelope, match, level);
570
632
  if (refs.length === 0) return;
571
633
  const activeMatch = refs.find((ref) => {
572
- const item = (0, import_core3.segmentAtRef)(envelope, ref);
573
- const parent = item === void 0 ? void 0 : (0, import_core3.resolveSelection)(envelope, item).paragraph;
634
+ const item = (0, import_core4.segmentAtRef)(envelope, ref);
635
+ const parent = item === void 0 ? void 0 : (0, import_core4.resolveSelection)(envelope, item).paragraph;
574
636
  return parent === singleParagraph || parent?.id !== void 0 && parent.id === singleParagraph.id || parent !== void 0 && parent.id === void 0 && singleParagraph.id === void 0 && parent.section === singleParagraph.section && parent.para === singleParagraph.para;
575
637
  });
576
638
  const primary = activeMatch ?? refs[0];
@@ -593,7 +655,7 @@ function SegmentInspector() {
593
655
  type: "queueOp",
594
656
  op: {
595
657
  kind: "move-para",
596
- address: (0, import_core3.paragraphAddress)(neighbour2),
658
+ address: (0, import_core4.paragraphAddress)(neighbour2),
597
659
  to: { address: anchor2, position: direction === -1 ? "after" : "before" }
598
660
  }
599
661
  });
@@ -607,7 +669,7 @@ function SegmentInspector() {
607
669
  op: {
608
670
  kind: "move-para",
609
671
  address,
610
- to: { address: (0, import_core3.paragraphAddress)(neighbour2), position: direction === -1 ? "before" : "after" }
672
+ to: { address: (0, import_core4.paragraphAddress)(neighbour2), position: direction === -1 ? "before" : "after" }
611
673
  }
612
674
  });
613
675
  return;
@@ -620,7 +682,7 @@ function SegmentInspector() {
620
682
  type: "queueOp",
621
683
  op: {
622
684
  kind: "move-para",
623
- address: (0, import_core3.paragraphAddress)(neighbour),
685
+ address: (0, import_core4.paragraphAddress)(neighbour),
624
686
  to: { address: anchor, position: direction === -1 ? "after" : "before" }
625
687
  }
626
688
  });
@@ -645,7 +707,7 @@ function SegmentInspector() {
645
707
  store.dispatch({
646
708
  type: "queueOps",
647
709
  ops: [
648
- ...paragraphRun.map((item) => ({ kind: "delete-para", address: (0, import_core3.paragraphAddress)(item) })),
710
+ ...paragraphRun.map((item) => ({ kind: "delete-para", address: (0, import_core4.paragraphAddress)(item) })),
649
711
  // The insertion's unpublished paragraphs go with it (#521).
650
712
  ...hiddenInRun.map((hidden) => ({ kind: "delete-para", address: { id: hidden.id } }))
651
713
  ]
@@ -669,7 +731,7 @@ function SegmentInspector() {
669
731
  style: { maxHeight: "12rem", overflowY: "auto" },
670
732
  children: paragraphs.map((candidate, index) => {
671
733
  const isSelected = selected.some((item) => item === candidate || item.id !== void 0 && item.id === candidate.id || item.id === void 0 && candidate.id === void 0 && item.section === candidate.section && item.para === candidate.para);
672
- const snippet = plainSegmentText((0, import_core3.segmentText)(envelope, candidate)).trim().replace(/\s+/g, " ");
734
+ const snippet = plainSegmentText((0, import_core4.segmentText)(envelope, candidate)).trim().replace(/\s+/g, " ");
673
735
  const text = snippet.length > 96 ? `${snippet.slice(0, 93)}...` : snippet || t("segment.emptyPara");
674
736
  const label = t("segment.choiceLabel", { index: index + 1, text });
675
737
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -845,7 +907,7 @@ function SegmentInspector() {
845
907
  disabled: disabled || selected.length === 0,
846
908
  onClick: () => store.dispatch({
847
909
  type: "queueOps",
848
- ops: selected.map((target) => ({ kind: "set-align", address: (0, import_core3.paragraphAddress)(target), alignment: align.value }))
910
+ ops: selected.map((target) => ({ kind: "set-align", address: (0, import_core4.paragraphAddress)(target), alignment: align.value }))
849
911
  }),
850
912
  children: t(align.key)
851
913
  },
@@ -891,7 +953,7 @@ function SegmentInspector() {
891
953
  type: "button",
892
954
  className: "hwped-btn",
893
955
  disabled: disabled || selected.length === 0 || !validShape,
894
- onClick: () => store.dispatch({ type: "queueOps", ops: selected.map((target) => ({ kind: "set-para", address: (0, import_core3.paragraphAddress)(target), key: shapeKey, value: `${shapeValue.trim()}${shapeKey === "line-spacing" ? lineSpacingUnit : "mm"}` })) }),
956
+ onClick: () => store.dispatch({ type: "queueOps", ops: selected.map((target) => ({ kind: "set-para", address: (0, import_core4.paragraphAddress)(target), key: shapeKey, value: `${shapeValue.trim()}${shapeKey === "line-spacing" ? lineSpacingUnit : "mm"}` })) }),
895
957
  children: t("segment.setPara")
896
958
  }
897
959
  )
@@ -907,7 +969,7 @@ function SegmentInspector() {
907
969
  charPrimary?.directChar === void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", children: t("segment.similarCharUnavailable") }),
908
970
  singleParagraph.directPara === void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", children: t("segment.similarParaUnavailable") })
909
971
  ] }),
910
- singleParagraph !== void 0 && (0, import_core3.hasDirectFormatting)(singleParagraph) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "hwped-field", children: [
972
+ singleParagraph !== void 0 && (0, import_core4.hasDirectFormatting)(singleParagraph) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "hwped-field", children: [
911
973
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "hwped-label", children: t("segment.directFormatting") }),
912
974
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", children: t("segment.directFormattingHint") }),
913
975
  directStyleRow === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", children: t(directStyleWhy ?? "segment.directStyleUnknown") }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -916,7 +978,7 @@ function SegmentInspector() {
916
978
  type: "button",
917
979
  className: "hwped-btn",
918
980
  disabled,
919
- onClick: () => store.dispatch({ type: "queueOp", op: { kind: "apply-style", address: (0, import_core3.paragraphAddress)(singleParagraph), style: directStyleRow.id, clearDirect: true } }),
981
+ onClick: () => store.dispatch({ type: "queueOp", op: { kind: "apply-style", address: (0, import_core4.paragraphAddress)(singleParagraph), style: directStyleRow.id, clearDirect: true } }),
920
982
  children: t("segment.clearDirect")
921
983
  }
922
984
  )
@@ -990,7 +1052,7 @@ function SegmentInspector() {
990
1052
  }
991
1053
  setRangeSplit(false);
992
1054
  store.dispatch({ type: "setRange", range: start === end ? null : {
993
- paragraph: (0, import_core3.segmentRef)(singleParagraph),
1055
+ paragraph: (0, import_core4.segmentRef)(singleParagraph),
994
1056
  start: singleParagraph.start + start,
995
1057
  end: singleParagraph.start + end
996
1058
  } });
@@ -1008,7 +1070,7 @@ function SegmentInspector() {
1008
1070
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "hwped-btn", onClick: () => {
1009
1071
  setRangeSplit(false);
1010
1072
  rangeInput.current?.setSelectionRange(0, 0);
1011
- if (hasRunSelection) store.dispatch({ type: "select", selection: (0, import_core3.segmentRef)(singleParagraph) });
1073
+ if (hasRunSelection) store.dispatch({ type: "select", selection: (0, import_core4.segmentRef)(singleParagraph) });
1012
1074
  else store.dispatch({ type: "setRange", range: null });
1013
1075
  }, children: t("segment.rangeClear") })
1014
1076
  ] })
@@ -1168,7 +1230,7 @@ function wholeRunText(run, markdown) {
1168
1230
 
1169
1231
  // src/StylesPanel.tsx
1170
1232
  var import_react4 = require("react");
1171
- var import_core4 = require("@hwp-editor/core");
1233
+ var import_core5 = require("@hwp-editor/core");
1172
1234
  var import_jsx_runtime3 = require("react/jsx-runtime");
1173
1235
  var ALIGNMENTS2 = ["justify", "left", "right", "center", "distribute"];
1174
1236
  var ALIGN_LABEL = {
@@ -1241,7 +1303,7 @@ function DefinitionForm(props) {
1241
1303
  type: "queueOps",
1242
1304
  ops: paragraphs.map((paragraph) => ({
1243
1305
  kind: "apply-style",
1244
- address: (0, import_core4.paragraphAddress)(paragraph),
1306
+ address: (0, import_core5.paragraphAddress)(paragraph),
1245
1307
  style: row.id
1246
1308
  }))
1247
1309
  });
@@ -1365,12 +1427,12 @@ function StylesPanel() {
1365
1427
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "hwped-panel", role: "region", "aria-label": t("tabs.styles"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "hwped-hint", role: "status", children: t("styles.checkingHost") }) });
1366
1428
  }
1367
1429
  if (capabilities.styles !== "v1") {
1368
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "hwped-panel", role: "region", "aria-label": t("tabs.styles"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "hwped-hint", role: "status", children: (0, import_core4.stylesVersionSupported)(capabilities.version) ? t("styles.unavailableHost") : t("styles.unavailable", { version: capabilities.version }) }) });
1430
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "hwped-panel", role: "region", "aria-label": t("tabs.styles"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "hwped-hint", role: "status", children: (0, import_core5.stylesVersionSupported)(capabilities.version) ? t("styles.unavailableHost") : t("styles.unavailable", { version: capabilities.version }) }) });
1369
1431
  }
1370
1432
  if (engine.styles === void 0) {
1371
1433
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "hwped-panel", role: "region", "aria-label": t("tabs.styles"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "hwped-hint", role: "status", children: t("styles.unavailableHost") }) });
1372
1434
  }
1373
- const paragraphs = envelope === null ? [] : (0, import_core4.selectedParagraphs)(envelope, state);
1435
+ const paragraphs = envelope === null ? [] : (0, import_core5.selectedParagraphs)(envelope, state);
1374
1436
  const rows = styles?.styles ?? [];
1375
1437
  const row = rows.find((item) => item.id === selectedId) ?? null;
1376
1438
  const paragraphRow = row !== null && row.kind === "paragraph" ? row : null;
@@ -1380,8 +1442,8 @@ function StylesPanel() {
1380
1442
  setSelectedId(item.id);
1381
1443
  if (envelope === null || item.used_by.length === 0) return;
1382
1444
  const refs = item.used_by.flatMap((id) => {
1383
- const segment = (0, import_core4.segmentAtRef)(envelope, { id, section: 0, para: 0 });
1384
- return segment === void 0 ? [] : [(0, import_core4.segmentRef)(segment)];
1445
+ const segment = (0, import_core5.segmentAtRef)(envelope, { id, section: 0, para: 0 });
1446
+ return segment === void 0 ? [] : [(0, import_core5.segmentRef)(segment)];
1385
1447
  });
1386
1448
  if (refs.length === 0) return;
1387
1449
  store.dispatch({ type: "selectMany", selections: refs, primary: refs[0], anchor: refs[0] });
@@ -1392,12 +1454,12 @@ function StylesPanel() {
1392
1454
  const shape = base === void 0 ? void 0 : base.direct ?? base.style;
1393
1455
  if (name === "" || base === void 0 || shape === void 0 || envelope === null) return;
1394
1456
  const face = firstFace(shape);
1395
- const paragraph = (0, import_core4.resolveSelection)(envelope, base).paragraph ?? base;
1457
+ const paragraph = (0, import_core5.resolveSelection)(envelope, base).paragraph ?? base;
1396
1458
  const id = paragraph.id;
1397
1459
  const own = id === void 0 ? void 0 : rows.find((item) => item.kind === "paragraph" && item.used_by.includes(id));
1398
- const targets = (0, import_core4.selectSimilar)(envelope, paragraph, "para").flatMap((ref) => {
1399
- const segment = (0, import_core4.segmentAtRef)(envelope, ref);
1400
- return segment === void 0 ? [] : [(0, import_core4.paragraphAddress)(segment)];
1460
+ const targets = (0, import_core5.selectSimilar)(envelope, paragraph, "para").flatMap((ref) => {
1461
+ const segment = (0, import_core5.segmentAtRef)(envelope, ref);
1462
+ return segment === void 0 ? [] : [(0, import_core5.paragraphAddress)(segment)];
1401
1463
  });
1402
1464
  const align = shape.para === void 0 ? void 0 : writableAlignment(shape.para.alignment);
1403
1465
  store.dispatch({
@@ -1433,7 +1495,7 @@ function StylesPanel() {
1433
1495
  const switchPreset = () => {
1434
1496
  if (styles === null || envelope === null) return;
1435
1497
  const epoch = loadEpoch();
1436
- const styleOps = (0, import_core4.presetStyleOps)(styles, preset, envelope);
1498
+ const styleOps = (0, import_core5.presetStyleOps)(styles, preset, envelope);
1437
1499
  const carriedStyleOp = styleOps.length > 0;
1438
1500
  const batch = [
1439
1501
  ...styleOps,
@@ -1443,10 +1505,10 @@ function StylesPanel() {
1443
1505
  let unstyled = false;
1444
1506
  let changed = false;
1445
1507
  void replaceDocument(async (current) => {
1446
- const styled = await engine.edit(current, batch, (0, import_core4.presetBatchOptions)(batch, { verify: true }));
1447
- const reading = (0, import_core4.readPresetBatch)(styled.report);
1508
+ const styled = await engine.edit(current, batch, (0, import_core5.presetBatchOptions)(batch, { verify: true }));
1509
+ const reading = (0, import_core5.readPresetBatch)(styled.report);
1448
1510
  if (reading.refusal !== null) {
1449
- throw new import_core4.HwpEngineError(reading.refusal.code, reading.refusal.message);
1511
+ throw new import_core5.HwpEngineError(reading.refusal.code, reading.refusal.message);
1450
1512
  }
1451
1513
  unstyled = reading.unstyledTable;
1452
1514
  changed = !reading.unchanged;
@@ -1529,7 +1591,7 @@ function StylesPanel() {
1529
1591
  disabled,
1530
1592
  "aria-label": t("styles.presetLabel"),
1531
1593
  onChange: (e) => setPreset(e.target.value),
1532
- children: import_core4.STYLE_TABLE_PRESETS.map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value, children: t(PRESET_LABEL[value]) }, value))
1594
+ children: import_core5.STYLE_TABLE_PRESETS.map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value, children: t(PRESET_LABEL[value]) }, value))
1533
1595
  }
1534
1596
  ),
1535
1597
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -1550,10 +1612,10 @@ function StylesPanel() {
1550
1612
 
1551
1613
  // src/TableGrid.tsx
1552
1614
  var import_react5 = require("react");
1553
- var import_core6 = require("@hwp-editor/core");
1615
+ var import_core7 = require("@hwp-editor/core");
1554
1616
 
1555
1617
  // src/tables.ts
1556
- var import_core5 = require("@hwp-editor/core");
1618
+ var import_core6 = require("@hwp-editor/core");
1557
1619
  var GFM_DELIMITER_CELL = /^:?-{2,}:?$/;
1558
1620
  function endsWithCellDelimiter(row) {
1559
1621
  if (!row.endsWith("|")) return false;
@@ -1620,7 +1682,7 @@ function findTables(envelope) {
1620
1682
  tables.push({
1621
1683
  tableIndex: tables.length,
1622
1684
  segment,
1623
- rows: parseMarkdownTable((0, import_core5.segmentText)(envelope, segment))
1685
+ rows: parseMarkdownTable((0, import_core6.segmentText)(envelope, segment))
1624
1686
  });
1625
1687
  }
1626
1688
  return tables;
@@ -1690,7 +1752,7 @@ function TableGrid() {
1690
1752
  }
1691
1753
  )
1692
1754
  ] });
1693
- const mismatch = envelope === null ? null : (0, import_core6.tableCountMismatch)(envelope);
1755
+ const mismatch = envelope === null ? null : (0, import_core7.tableCountMismatch)(envelope);
1694
1756
  if (mismatch !== null) {
1695
1757
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "hwped-panel", role: "region", "aria-label": t("table.panelAria"), children: [
1696
1758
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "hwped-hint", children: t("table.indexMismatch", mismatch) }),
@@ -1925,10 +1987,10 @@ function TableGrid() {
1925
1987
 
1926
1988
  // src/FieldsPanel.tsx
1927
1989
  var import_react6 = require("react");
1928
- var import_core8 = require("@hwp-editor/core");
1990
+ var import_core9 = require("@hwp-editor/core");
1929
1991
 
1930
1992
  // src/fields.ts
1931
- var import_core7 = require("@hwp-editor/core");
1993
+ var import_core8 = require("@hwp-editor/core");
1932
1994
  var SLOT_PATTERN = /\{\{\s*([^{}]+?)\s*\}\}/g;
1933
1995
  var CONTROL_KINDS = /* @__PURE__ */ new Set(["field", "image", "bookmark"]);
1934
1996
  function innermostAt(envelope, offset) {
@@ -1956,10 +2018,10 @@ function extractFieldSlots(envelope) {
1956
2018
  const offset = [...envelope.markdown.slice(0, match.index ?? 0)].length;
1957
2019
  const hit = innermostAt(envelope, offset);
1958
2020
  if (hit === void 0 || seen.has(name)) continue;
1959
- const paragraph = (0, import_core7.resolveSelection)(envelope, hit).paragraph;
2021
+ const paragraph = (0, import_core8.resolveSelection)(envelope, hit).paragraph;
1960
2022
  if (paragraph === void 0) continue;
1961
2023
  seen.add(name);
1962
- slots.push({ name, segment: (0, import_core7.segmentRef)(paragraph) });
2024
+ slots.push({ name, segment: (0, import_core8.segmentRef)(paragraph) });
1963
2025
  }
1964
2026
  return slots;
1965
2027
  }
@@ -1993,8 +2055,8 @@ function FieldsPanel() {
1993
2055
  children: [
1994
2056
  legacy && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "hwped-hint", children: t("fields.legacySeparatorHint") }),
1995
2057
  slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "hwped-hint", children: t("fields.hint") }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "hwped-fields", children: slots.map((slot) => {
1996
- const segment = envelope === null ? void 0 : (0, import_core8.segmentAtRef)(envelope, slot.segment);
1997
- const snippet = envelope === null || segment === void 0 ? "" : (0, import_core8.segmentText)(envelope, segment).trim().slice(0, 40);
2058
+ const segment = envelope === null ? void 0 : (0, import_core9.segmentAtRef)(envelope, slot.segment);
2059
+ const snippet = envelope === null || segment === void 0 ? "" : (0, import_core9.segmentText)(envelope, segment).trim().slice(0, 40);
1998
2060
  const draft = drafts[slot.name] ?? "";
1999
2061
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { className: "hwped-field-item", children: [
2000
2062
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hwped-row", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
@@ -2063,19 +2125,19 @@ function FieldsPanel() {
2063
2125
 
2064
2126
  // src/TemplatePanel.tsx
2065
2127
  var import_react7 = require("react");
2066
- var import_core12 = require("@hwp-editor/core");
2128
+ var import_core13 = require("@hwp-editor/core");
2067
2129
 
2068
2130
  // src/errors.ts
2069
- var import_core9 = require("@hwp-editor/core");
2131
+ var import_core10 = require("@hwp-editor/core");
2070
2132
  function toEditorError(e) {
2071
2133
  const refusal = engineRefusalKind(e);
2072
- const base = (0, import_core9.isHwpEngineError)(e) && (0, import_core9.isHwpErrorCode)(e.code) ? { code: e.code, message: e.message } : { message: e instanceof Error ? e.message : String(e) };
2134
+ const base = (0, import_core10.isHwpEngineError)(e) && (0, import_core10.isHwpErrorCode)(e.code) ? { code: e.code, message: e.message } : { message: e instanceof Error ? e.message : String(e) };
2073
2135
  return refusal === void 0 ? base : { ...base, refusal };
2074
2136
  }
2075
2137
  function engineRefusalKind(e) {
2076
2138
  if (typeof e !== "object" || e === null) return void 0;
2077
2139
  const refusal = e.refusal;
2078
- return (0, import_core9.isEditRefusalKind)(refusal) ? refusal : void 0;
2140
+ return (0, import_core10.isEditRefusalKind)(refusal) ? refusal : void 0;
2079
2141
  }
2080
2142
  function engineStoppedWithoutDiagnostic(e) {
2081
2143
  return typeof e === "object" && e !== null && e.stopped === true;
@@ -2145,8 +2207,8 @@ function ErrorLine(props) {
2145
2207
  }
2146
2208
 
2147
2209
  // src/template-support.ts
2148
- var import_core10 = require("@hwp-editor/core");
2149
2210
  var import_core11 = require("@hwp-editor/core");
2211
+ var import_core12 = require("@hwp-editor/core");
2150
2212
  var METHOD_LABEL_KEYS = {
2151
2213
  slots: "templates.methodSlots",
2152
2214
  fill: "templates.methodFill",
@@ -2156,7 +2218,7 @@ var METHOD_LABEL_KEYS = {
2156
2218
  create: "templates.methodCreate"
2157
2219
  };
2158
2220
  function templateMethodStatus(engine, capabilities, method) {
2159
- if (!(0, import_core10.templateVersionSupported)(capabilities?.version ?? "")) {
2221
+ if (!(0, import_core11.templateVersionSupported)(capabilities?.version ?? "")) {
2160
2222
  return { supported: false, reason: "version" };
2161
2223
  }
2162
2224
  if (typeof engine[method] !== "function") {
@@ -2168,7 +2230,7 @@ function templateMethodStatus(engine, capabilities, method) {
2168
2230
  return { supported: true, reason: null };
2169
2231
  }
2170
2232
  function templateStatusReason(t, status, method) {
2171
- if (status.reason === "version") return t("templates.versionRequired", { version: import_core11.TEMPLATE_MIN_VERSION });
2233
+ if (status.reason === "version") return t("templates.versionRequired", { version: import_core12.TEMPLATE_MIN_VERSION });
2172
2234
  const label = t(METHOD_LABEL_KEYS[method]);
2173
2235
  if (status.reason === "missing") return t("templates.methodMissing", { method: label });
2174
2236
  if (status.reason === "unadvertised") return t("templates.methodUnadvertised", { method: label });
@@ -2190,7 +2252,7 @@ function initialListRow(fields, supplied = {}) {
2190
2252
  }
2191
2253
  function pageData(page) {
2192
2254
  const mime = page.format === "svg" ? "image/svg+xml" : `image/${page.format}`;
2193
- return `data:${mime};base64,${import_core12.base64.encode(page.data)}`;
2255
+ return `data:${mime};base64,${import_core13.base64.encode(page.data)}`;
2194
2256
  }
2195
2257
  function kindLabel(input, t) {
2196
2258
  if (input.kind === "slot") return t("templates.kindSlot");
@@ -2681,7 +2743,7 @@ function DocumentPanel() {
2681
2743
 
2682
2744
  // src/ImagePanel.tsx
2683
2745
  var import_react10 = require("react");
2684
- var import_core13 = require("@hwp-editor/core");
2746
+ var import_core14 = require("@hwp-editor/core");
2685
2747
  var import_jsx_runtime10 = require("react/jsx-runtime");
2686
2748
  function ImagePanel() {
2687
2749
  const { state, store, envelope, capabilities, editable, queueImage, onError, t } = useHwpEditorContext();
@@ -2719,14 +2781,14 @@ function ImagePanel() {
2719
2781
  if (file === void 0) return;
2720
2782
  setReading(true);
2721
2783
  try {
2722
- if (file.size === 0 || file.size > import_core13.MAX_IMAGE_ASSET_BYTES) throw new Error(t("image.invalidSize"));
2784
+ if (file.size === 0 || file.size > import_core14.MAX_IMAGE_ASSET_BYTES) throw new Error(t("image.invalidSize"));
2723
2785
  let bytes;
2724
2786
  try {
2725
2787
  bytes = await file.arrayBuffer();
2726
2788
  } catch {
2727
2789
  throw new Error(t("image.readError"));
2728
2790
  }
2729
- const data = new Uint8Array(bytes), mediaType = (0, import_core13.imageAssetMediaType)(data);
2791
+ const data = new Uint8Array(bytes), mediaType = (0, import_core14.imageAssetMediaType)(data);
2730
2792
  if (mediaType === null) throw new Error(t("image.invalidType"));
2731
2793
  if (generation.current === version && store.getState().document === source) {
2732
2794
  setChosen({ name: file.name, data, extension: mediaType === "image/png" ? "png" : "jpg" });
@@ -2784,12 +2846,12 @@ function ImagePanel() {
2784
2846
 
2785
2847
  // src/ComposePanel.tsx
2786
2848
  var import_react11 = require("react");
2787
- var import_core16 = require("@hwp-editor/core");
2849
+ var import_core17 = require("@hwp-editor/core");
2788
2850
 
2789
2851
  // src/presets.ts
2790
- var import_core14 = require("@hwp-editor/core");
2791
- var COMPOSE_PRESETS = [...import_core14.DOCUMENT_PROFILE_NAMES];
2792
- var PRESET_PROFILES = import_core14.DOCUMENT_PROFILES;
2852
+ var import_core15 = require("@hwp-editor/core");
2853
+ var COMPOSE_PRESETS = [...import_core15.DOCUMENT_PROFILE_NAMES];
2854
+ var PRESET_PROFILES = import_core15.DOCUMENT_PROFILES;
2793
2855
  function bodyToBlocks(body) {
2794
2856
  const blocks = [];
2795
2857
  for (const chunk of body.split(/\n\s*\n/)) {
@@ -2850,17 +2912,17 @@ function buildDocumentSpec(preset, input) {
2850
2912
  },
2851
2913
  heading: {
2852
2914
  font_family: profile.fontFamily,
2853
- font_size_pt: profile.bodySizePt + import_core14.COMPOSE_STYLE_ROWS.heading.sizeDeltaPt,
2915
+ font_size_pt: profile.bodySizePt + import_core15.COMPOSE_STYLE_ROWS.heading.sizeDeltaPt,
2854
2916
  bold: true,
2855
- spacing_before_pt: import_core14.COMPOSE_STYLE_ROWS.heading.spacingBeforePt,
2856
- spacing_after_pt: import_core14.COMPOSE_STYLE_ROWS.heading.spacingAfterPt
2917
+ spacing_before_pt: import_core15.COMPOSE_STYLE_ROWS.heading.spacingBeforePt,
2918
+ spacing_after_pt: import_core15.COMPOSE_STYLE_ROWS.heading.spacingAfterPt
2857
2919
  },
2858
2920
  title: {
2859
2921
  font_family: profile.fontFamily,
2860
- font_size_pt: profile.bodySizePt + import_core14.COMPOSE_STYLE_ROWS.title.sizeDeltaPt,
2922
+ font_size_pt: profile.bodySizePt + import_core15.COMPOSE_STYLE_ROWS.title.sizeDeltaPt,
2861
2923
  bold: true,
2862
2924
  align: "center",
2863
- spacing_after_pt: import_core14.COMPOSE_STYLE_ROWS.title.spacingAfterPt
2925
+ spacing_after_pt: import_core15.COMPOSE_STYLE_ROWS.title.spacingAfterPt
2864
2926
  }
2865
2927
  },
2866
2928
  sections: [section]
@@ -2869,7 +2931,7 @@ function buildDocumentSpec(preset, input) {
2869
2931
  }
2870
2932
 
2871
2933
  // src/components-support.ts
2872
- var import_core15 = require("@hwp-editor/core");
2934
+ var import_core16 = require("@hwp-editor/core");
2873
2935
  function millimetres(value) {
2874
2936
  return `${Math.round(value * 10) / 10} mm`;
2875
2937
  }
@@ -2925,7 +2987,7 @@ function insertionPreflight(blocks, documentName, t) {
2925
2987
  function insertionOf(error) {
2926
2988
  if (typeof error !== "object" || error === null) return void 0;
2927
2989
  const value = error.insertion;
2928
- return (0, import_core15.isInsertionRefusal)(value) ? value : void 0;
2990
+ return (0, import_core16.isInsertionRefusal)(value) ? value : void 0;
2929
2991
  }
2930
2992
  function overflowingBodyMm(error) {
2931
2993
  const insertion = insertionOf(error);
@@ -2935,10 +2997,10 @@ function isLayoutOverflow(error) {
2935
2997
  return insertionOf(error)?.kind === "layout_overflow";
2936
2998
  }
2937
2999
  function wrapped(error, text, detail) {
2938
- if ((0, import_core15.isHwpEngineError)(error)) {
3000
+ if ((0, import_core16.isHwpEngineError)(error)) {
2939
3001
  const insertion = insertionOf(error);
2940
3002
  return Object.assign(
2941
- new import_core15.HwpEngineError(error.code, text, {
3003
+ new import_core16.HwpEngineError(error.code, text, {
2942
3004
  ...error.status === void 0 ? {} : { status: error.status },
2943
3005
  cause: error,
2944
3006
  ...insertion === void 0 ? {} : { insertion },
@@ -2959,7 +3021,7 @@ function refusalReason(message) {
2959
3021
  }
2960
3022
  function isRefusedInsertion(error) {
2961
3023
  if (insertionOf(error) !== void 0) return true;
2962
- return (0, import_core15.isHwpEngineError)(error) && (error.code === "failed" || error.code === "bad_request");
3024
+ return (0, import_core16.isHwpEngineError)(error) && (error.code === "failed" || error.code === "bad_request");
2963
3025
  }
2964
3026
  function insertionFailure(error, blocks, t) {
2965
3027
  const message = error instanceof Error ? error.message : String(error);
@@ -2987,7 +3049,7 @@ var STEP_KEYS = {
2987
3049
  component_load: "components.step.load"
2988
3050
  };
2989
3051
  function componentRefusalText(error, t) {
2990
- if (!(0, import_core15.isComponentError)(error)) return null;
3052
+ if (!(0, import_core16.isComponentError)(error)) return null;
2991
3053
  return t("components.refused", {
2992
3054
  code: error.code,
2993
3055
  source: error.source,
@@ -3016,7 +3078,7 @@ var PRESET_LABEL_KEYS = {
3016
3078
  };
3017
3079
  function ComposePanel(props) {
3018
3080
  const { engine, t, onError, store, state, loadEpoch, loadSettled, loadInFlight } = useHwpEditorContext();
3019
- const components = props.components ?? import_core16.STARTER_COMPONENTS;
3081
+ const components = props.components ?? import_core17.STARTER_COMPONENTS;
3020
3082
  const [preset, setPreset] = (0, import_react11.useState)("official");
3021
3083
  const [title, setTitle] = (0, import_react11.useState)("");
3022
3084
  const [author, setAuthor] = (0, import_react11.useState)("");
@@ -3138,7 +3200,7 @@ function ComposePanel(props) {
3138
3200
  const source = store.getState().document;
3139
3201
  try {
3140
3202
  const written = title.trim();
3141
- const spec = assembling ? (0, import_core16.documentSpecFromComponents)(
3203
+ const spec = assembling ? (0, import_core17.documentSpecFromComponents)(
3142
3204
  assembly.map((row) => ({ component: row.component, values: row.values })),
3143
3205
  written === "" ? {} : { title: written }
3144
3206
  ) : buildDocumentSpec(preset, { title, author, body });
@@ -3383,18 +3445,18 @@ function ComposePanel(props) {
3383
3445
 
3384
3446
  // src/ComponentsPanel.tsx
3385
3447
  var import_react12 = require("react");
3386
- var import_core17 = require("@hwp-editor/core");
3448
+ var import_core18 = require("@hwp-editor/core");
3387
3449
  var import_jsx_runtime12 = require("react/jsx-runtime");
3388
3450
  function componentsSupportReason(capabilities, t) {
3389
3451
  if (capabilities === null) return "";
3390
3452
  if (capabilities.editOps !== "v1") return t("components.disabledChannel");
3391
- if (!(0, import_core17.editReportSupported)(capabilities.version)) {
3392
- return t("components.disabledVersion", { version: import_core17.EDIT_REPORT_MIN_VERSION });
3453
+ if (!(0, import_core18.editReportSupported)(capabilities.version)) {
3454
+ return t("components.disabledVersion", { version: import_core18.EDIT_REPORT_MIN_VERSION });
3393
3455
  }
3394
3456
  return "";
3395
3457
  }
3396
3458
  function ComponentsPanel({
3397
- components = import_core17.STARTER_COMPONENTS,
3459
+ components = import_core18.STARTER_COMPONENTS,
3398
3460
  disabledReason = "",
3399
3461
  beforeDisabledReason = "",
3400
3462
  refusalFor,
@@ -3618,7 +3680,7 @@ function pendingTargetLabel(op, t, resolvers = {}, envelope = null) {
3618
3680
  }
3619
3681
 
3620
3682
  // src/messages.ts
3621
- var import_core18 = require("@hwp-editor/core");
3683
+ var import_core19 = require("@hwp-editor/core");
3622
3684
  var en = {
3623
3685
  // Toolbar
3624
3686
  "toolbar.toolsAria": "Editing tools",
@@ -3992,9 +4054,9 @@ var en = {
3992
4054
  "error.unresolvableAddress": "The engine could not address the edit's paragraph or run. Runs inside some nested paragraphs cannot be addressed. Format text in a top-level paragraph or a table cell, or edit this target in a word processor.",
3993
4055
  "error.runRangeConflict": "A run format change was refused because an earlier pending change in that paragraph (text, a link, a field, a bookmark, an image or a cell) may change its text, so the run might no longer name the same characters. Nothing was applied. Remove the format change from the pending list, apply the rest, then format the run again; or queue the format change before the others.",
3994
4056
  "error.rangeTagRefused": "This HWP document holds a range mark the engine cannot move, so a pending edit was refused and nothing was applied. Edits that move text around the mark are refused: changing a paragraph's text length, changing a field's value to one of a different length, inserting or deleting a link, field, bookmark or image, or deleting a table. A table cell that holds a mark refuses any change to its content. The engine does not say which edit. Remove those pending edits from the pending list (a same-length text replacement in a paragraph, or a same-length field value, is accepted) and apply the rest. To make those edits, convert the document to HWPX, which drops the range marks, or remove the mark in Hangul, then reopen it; reopening drops the pending list.",
3995
- "error.stoppedWithoutDiagnostic": import_core18.STOPPED_WITHOUT_DIAGNOSTIC,
4057
+ "error.stoppedWithoutDiagnostic": import_core19.STOPPED_WITHOUT_DIAGNOSTIC,
3996
4058
  // The same rule for a failure with stderr but no Error: line (#140).
3997
- "error.noEngineCause": import_core18.NO_ENGINE_CAUSE,
4059
+ "error.noEngineCause": import_core19.NO_ENGINE_CAUSE,
3998
4060
  "error.badEnvelope": (p) => `The host returned a document read this editor cannot use: ${p.detail}. Have the host emit segment-envelope-v2 data, then reload.`,
3999
4061
  "error.readOnlyReplacement": "The editor became read-only before the template could be applied; switch to an editable document and retry.",
4000
4062
  "error.pendingReplacement": "Pending edits would be lost; apply or clear them before replacing this document.",
@@ -4070,14 +4132,14 @@ var en = {
4070
4132
  "image.insert": "Insert image",
4071
4133
  "image.delete": "Delete image",
4072
4134
  "image.file": "PNG/JPEG image file",
4073
- "image.fileHint": `Choose a PNG or JPEG image up to ${import_core18.MAX_IMAGE_ASSET_MIB} MiB.`,
4135
+ "image.fileHint": `Choose a PNG or JPEG image up to ${import_core19.MAX_IMAGE_ASSET_MIB} MiB.`,
4074
4136
  "image.unsupported": "Image upload needs a host with an upload command. With the agent-hwp engine, use 1.4.0 or newer, the version this editor verifies uploads against. A supplied engine has to advertise image-asset uploads. The desktop app has no upload command, and this editor cannot insert a picture from a local file, so insert the picture in a word processor and reopen the document here.",
4075
4137
  "image.anchor": "Insert after paragraph text",
4076
4138
  "image.deleteAnchor": "Image anchor text to delete",
4077
4139
  "image.width": "Width (mm)",
4078
4140
  "image.height": "Height (mm)",
4079
4141
  "image.reading": "Reading image...",
4080
- "image.invalidSize": `The image is empty or exceeds ${import_core18.MAX_IMAGE_ASSET_MIB} MiB; choose a smaller PNG/JPEG file.`,
4142
+ "image.invalidSize": `The image is empty or exceeds ${import_core19.MAX_IMAGE_ASSET_MIB} MiB; choose a smaller PNG/JPEG file.`,
4081
4143
  "image.invalidType": "The file is not PNG/JPEG image data; choose a supported image.",
4082
4144
  "image.readError": "The image could not be read; select the file again.",
4083
4145
  "error.prefix.image": "Image operation failed",
@@ -4527,14 +4589,14 @@ var ko = {
4527
4589
  "image.insert": "\uC774\uBBF8\uC9C0 \uC0BD\uC785",
4528
4590
  "image.delete": "\uC774\uBBF8\uC9C0 \uC0AD\uC81C",
4529
4591
  "image.file": "PNG/JPEG \uC774\uBBF8\uC9C0 \uD30C\uC77C",
4530
- "image.fileHint": `${import_core18.MAX_IMAGE_ASSET_MIB} MiB \uC774\uD558\uC758 PNG \uB610\uB294 JPEG \uC774\uBBF8\uC9C0\uB97C \uC120\uD0DD\uD558\uC138\uC694.`,
4592
+ "image.fileHint": `${import_core19.MAX_IMAGE_ASSET_MIB} MiB \uC774\uD558\uC758 PNG \uB610\uB294 JPEG \uC774\uBBF8\uC9C0\uB97C \uC120\uD0DD\uD558\uC138\uC694.`,
4531
4593
  "image.unsupported": "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC\uB294 \uC5C5\uB85C\uB4DC \uBA85\uB839\uC774 \uC788\uB294 \uD638\uC2A4\uD2B8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. agent-hwp \uC5D4\uC9C4\uC774\uB77C\uBA74 \uC774 \uD3B8\uC9D1\uAE30\uAC00 \uC5C5\uB85C\uB4DC\uB97C \uAC80\uC99D\uD55C 1.4.0 \uC774\uC0C1\uC744 \uC0AC\uC6A9\uD558\uC138\uC694. \uC5D4\uC9C4\uC744 \uC9C1\uC811 \uACF5\uAE09\uD558\uB294 \uD638\uC2A4\uD2B8\uB294 \uC774\uBBF8\uC9C0 \uC790\uC0B0 \uC5C5\uB85C\uB4DC\uB97C \uC9C0\uC6D0\uD55C\uB2E4\uACE0 \uC54C\uB824\uC57C \uD569\uB2C8\uB2E4. \uB370\uC2A4\uD06C\uD1B1 \uC571\uC5D0\uB294 \uC5C5\uB85C\uB4DC \uBA85\uB839\uC774 \uC5C6\uACE0 \uC774 \uD3B8\uC9D1\uAE30\uB294 \uB85C\uCEEC \uD30C\uC77C\uC5D0\uC11C \uADF8\uB9BC\uC744 \uB123\uC744 \uC218 \uC5C6\uC73C\uBBC0\uB85C, \uC6CC\uB4DC\uD504\uB85C\uC138\uC11C\uC5D0\uC11C \uADF8\uB9BC\uC744 \uB123\uC740 \uB4A4 \uC774 \uD3B8\uC9D1\uAE30\uC5D0\uC11C \uBB38\uC11C\uB97C \uB2E4\uC2DC \uC5EC\uC138\uC694.",
4532
4594
  "image.anchor": "\uC774 \uBB38\uB2E8 \uBB38\uC790\uC5F4 \uB4A4\uC5D0 \uC0BD\uC785",
4533
4595
  "image.deleteAnchor": "\uC0AD\uC81C\uD560 \uC774\uBBF8\uC9C0\uC758 \uC704\uCE58 \uBB38\uC790\uC5F4",
4534
4596
  "image.width": "\uB108\uBE44 (mm)",
4535
4597
  "image.height": "\uB192\uC774 (mm)",
4536
4598
  "image.reading": "\uC774\uBBF8\uC9C0 \uC77D\uB294 \uC911...",
4537
- "image.invalidSize": `\uC774\uBBF8\uC9C0\uAC00 \uBE44\uC5B4 \uC788\uAC70\uB098 ${import_core18.MAX_IMAGE_ASSET_MIB} MiB\uB97C \uCD08\uACFC\uD569\uB2C8\uB2E4. \uB354 \uC791\uC740 PNG/JPEG \uD30C\uC77C\uC744 \uC120\uD0DD\uD558\uC138\uC694.`,
4599
+ "image.invalidSize": `\uC774\uBBF8\uC9C0\uAC00 \uBE44\uC5B4 \uC788\uAC70\uB098 ${import_core19.MAX_IMAGE_ASSET_MIB} MiB\uB97C \uCD08\uACFC\uD569\uB2C8\uB2E4. \uB354 \uC791\uC740 PNG/JPEG \uD30C\uC77C\uC744 \uC120\uD0DD\uD558\uC138\uC694.`,
4538
4600
  "image.invalidType": "PNG/JPEG \uC774\uBBF8\uC9C0 \uB370\uC774\uD130\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uC9C0\uC6D0\uD558\uB294 \uC774\uBBF8\uC9C0 \uD30C\uC77C\uC744 \uC120\uD0DD\uD558\uC138\uC694.",
4539
4601
  "image.readError": "\uC774\uBBF8\uC9C0\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD30C\uC77C\uC744 \uB2E4\uC2DC \uC120\uD0DD\uD558\uC138\uC694.",
4540
4602
  "error.prefix.image": "\uC774\uBBF8\uC9C0 \uC791\uC5C5 \uC2E4\uD328",
@@ -4597,16 +4659,16 @@ function selectionParagraphs(envelope, state) {
4597
4659
  const seen = /* @__PURE__ */ new Set();
4598
4660
  const paragraphs = [];
4599
4661
  for (const ref of refs) {
4600
- const segment = (0, import_core19.segmentAtRef)(envelope, ref);
4662
+ const segment = (0, import_core20.segmentAtRef)(envelope, ref);
4601
4663
  if (segment === void 0) continue;
4602
- for (const paragraph of (0, import_core19.resolveSelection)(envelope, segment).paragraphs) {
4664
+ for (const paragraph of (0, import_core20.resolveSelection)(envelope, segment).paragraphs) {
4603
4665
  const key = paragraph.id ?? `${paragraph.section}:${paragraph.para}:${paragraph.start}`;
4604
4666
  if (seen.has(key)) continue;
4605
4667
  seen.add(key);
4606
4668
  paragraphs.push(paragraph);
4607
4669
  }
4608
4670
  }
4609
- return paragraphs.sort(import_core19.compareSegments);
4671
+ return paragraphs.sort(import_core20.compareSegments);
4610
4672
  }
4611
4673
  function insertAnchor(covered, position) {
4612
4674
  const paragraph = position === "before" ? covered[0] : covered[covered.length - 1];
@@ -4644,7 +4706,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
4644
4706
  className,
4645
4707
  style
4646
4708
  } = props;
4647
- const catalogue = components ?? import_core19.STARTER_COMPONENTS;
4709
+ const catalogue = components ?? import_core20.STARTER_COMPONENTS;
4648
4710
  const cbRef = (0, import_react13.useRef)({ onReady, onError, onChange, onDirtyChange });
4649
4711
  (0, import_react13.useEffect)(() => {
4650
4712
  cbRef.current = { onReady, onError, onChange, onDirtyChange };
@@ -4662,7 +4724,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
4662
4724
  cbRef.current.onDirtyChange?.(dirty2);
4663
4725
  }, []);
4664
4726
  const t = (0, import_react13.useMemo)(() => createT(locale, messages), [locale, messages]);
4665
- const [store] = (0, import_react13.useState)(() => (0, import_core19.createStore)());
4727
+ const [store] = (0, import_react13.useState)(() => (0, import_core20.createStore)());
4666
4728
  const state = (0, import_react13.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
4667
4729
  const [envelope, setEnvelope] = (0, import_react13.useState)(null);
4668
4730
  const [capabilities, setCapabilities] = (0, import_react13.useState)(null);
@@ -4715,9 +4777,9 @@ var HwpEditor = (0, import_react13.forwardRef)(
4715
4777
  const readEnvelope = (0, import_react13.useCallback)(async (target) => {
4716
4778
  const read = await engine.read(target);
4717
4779
  try {
4718
- return (0, import_core19.validateCatEnvelope)(read);
4780
+ return (0, import_core20.validateCatEnvelope)(read);
4719
4781
  } catch (e) {
4720
- throw new import_core19.HwpEngineError(
4782
+ throw new import_core20.HwpEngineError(
4721
4783
  "failed",
4722
4784
  latestT.current("error.badEnvelope", { detail: envelopeProblem(e instanceof Error ? e.message : String(e)) }),
4723
4785
  { cause: e }
@@ -4736,7 +4798,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
4736
4798
  insertedTriedFor.current = envelope;
4737
4799
  const hidden = [];
4738
4800
  const paragraphs = pendingInserted.flatMap((id) => {
4739
- const segment = (0, import_core19.segmentAtRef)(envelope, { id, section: 0, para: 0 });
4801
+ const segment = (0, import_core20.segmentAtRef)(envelope, { id, section: 0, para: 0 });
4740
4802
  if (segment === void 0) hidden.push(id);
4741
4803
  return segment === void 0 || segment.kind !== "para" ? [] : [segment];
4742
4804
  });
@@ -4744,9 +4806,9 @@ var HwpEditor = (0, import_react13.forwardRef)(
4744
4806
  if (paragraphs.length === 0) return;
4745
4807
  store.dispatch({
4746
4808
  type: "selectMany",
4747
- selections: paragraphs.map(import_core19.segmentRef),
4748
- primary: (0, import_core19.segmentRef)(paragraphs[0]),
4749
- anchor: (0, import_core19.segmentRef)(paragraphs[0])
4809
+ selections: paragraphs.map(import_core20.segmentRef),
4810
+ primary: (0, import_core20.segmentRef)(paragraphs[0]),
4811
+ anchor: (0, import_core20.segmentRef)(paragraphs[0])
4750
4812
  });
4751
4813
  setInsertedHidden(hidden.length === 0 ? null : { envelope, selections: store.getState().selections, ids: hidden });
4752
4814
  }, [envelope, pendingInserted, store]);
@@ -4827,22 +4889,22 @@ var HwpEditor = (0, import_react13.forwardRef)(
4827
4889
  const queueImage = (0, import_react13.useCallback)((op, asset) => {
4828
4890
  const snapshot = store.getState();
4829
4891
  if (!editable || envelope === null || snapshot.document === null || snapshot.status === "applying") return;
4830
- if (capabilities?.imageAssets !== "v1") throw new import_core19.HwpEngineError("unavailable", t("image.unsupported"));
4831
- if (op.path !== asset.name) throw new import_core19.HwpEngineError("bad_request", t("image.referenceMismatch"));
4892
+ if (capabilities?.imageAssets !== "v1") throw new import_core20.HwpEngineError("unavailable", t("image.unsupported"));
4893
+ if (op.path !== asset.name) throw new import_core20.HwpEngineError("bad_request", t("image.referenceMismatch"));
4832
4894
  const active = snapshot.pendingOps.flatMap((pending) => {
4833
4895
  const stored = imageAssets.current.get(pending);
4834
4896
  return stored === void 0 ? [] : [stored];
4835
4897
  });
4836
- if (active.length + 1 > import_core19.MAX_IMAGE_ASSETS || active.reduce((bytes, image) => bytes + image.data.length, asset.data.length) > import_core19.MAX_IMAGE_ASSETS_TOTAL_BYTES) {
4837
- throw new import_core19.HwpEngineError("bad_request", t("image.queueLimit", { count: import_core19.MAX_IMAGE_ASSETS, miB: import_core19.MAX_IMAGE_ASSETS_TOTAL_BYTES / (1024 * 1024) }));
4898
+ if (active.length + 1 > import_core20.MAX_IMAGE_ASSETS || active.reduce((bytes, image) => bytes + image.data.length, asset.data.length) > import_core20.MAX_IMAGE_ASSETS_TOTAL_BYTES) {
4899
+ throw new import_core20.HwpEngineError("bad_request", t("image.queueLimit", { count: import_core20.MAX_IMAGE_ASSETS, miB: import_core20.MAX_IMAGE_ASSETS_TOTAL_BYTES / (1024 * 1024) }));
4838
4900
  }
4839
- (0, import_core19.validateImageAssets)([...active, asset]);
4901
+ (0, import_core20.validateImageAssets)([...active, asset]);
4840
4902
  imageAssets.current.set(op, { name: asset.name, data: asset.data.slice() });
4841
4903
  store.dispatch({ type: "queueOp", op });
4842
4904
  }, [editable, envelope, capabilities, store, t]);
4843
4905
  (0, import_react13.useEffect)(() => {
4844
4906
  if (envelope === null || state.selection === null) return;
4845
- const segment = (0, import_core19.segmentAtRef)(envelope, state.selection);
4907
+ const segment = (0, import_core20.segmentAtRef)(envelope, state.selection);
4846
4908
  if (segment === void 0) return;
4847
4909
  const next = hostsTable(envelope, segment) ? "table" : "para";
4848
4910
  setTab((current) => current === "components" || current === "styles" ? current : next);
@@ -4989,17 +5051,17 @@ var HwpEditor = (0, import_react13.forwardRef)(
4989
5051
  noteRefusal(t("error.loadingReplacement"));
4990
5052
  return;
4991
5053
  }
4992
- const segment = snapshot.selection === null ? void 0 : (0, import_core19.segmentAtRef)(envelope, snapshot.selection);
5054
+ const segment = snapshot.selection === null ? void 0 : (0, import_core20.segmentAtRef)(envelope, snapshot.selection);
4993
5055
  const covered = selectionParagraphs(envelope, snapshot);
4994
5056
  const address = segment === void 0 ? null : insertAnchor(covered, position);
4995
5057
  if (address === null) return;
4996
- if (position === "before" && covered[0] !== void 0 && (0, import_core19.isSectionDefinitionParagraph)(covered[0])) return;
5058
+ if (position === "before" && covered[0] !== void 0 && (0, import_core20.isSectionDefinitionParagraph)(covered[0])) return;
4997
5059
  let blocks;
4998
5060
  let styles2;
4999
5061
  try {
5000
- const filled = (0, import_core19.substituteParams)(component, values, component.name);
5062
+ const filled = (0, import_core20.substituteParams)(component, values, component.name);
5001
5063
  blocks = filled.blocks;
5002
- styles2 = (0, import_core19.componentStyleMap)([filled]);
5064
+ styles2 = (0, import_core20.componentStyleMap)([filled]);
5003
5065
  } catch (error) {
5004
5066
  const shown = toError(componentFailure(error, t));
5005
5067
  noteNotice(shown.message, shown);
@@ -5052,7 +5114,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
5052
5114
  }
5053
5115
  let ids;
5054
5116
  try {
5055
- ids = (0, import_core19.insertedParagraphIds)(outcome);
5117
+ ids = (0, import_core20.insertedParagraphIds)(outcome);
5056
5118
  } catch (error) {
5057
5119
  noteNotice(toError(error).message, error);
5058
5120
  return;
@@ -5063,12 +5125,12 @@ var HwpEditor = (0, import_react13.forwardRef)(
5063
5125
  [emitError, engine, envelope, noteRefusal, replaceDocument, store, t]
5064
5126
  );
5065
5127
  const selectedTargets = envelope === null || state.selection === null ? void 0 : (() => {
5066
- const segment = (0, import_core19.segmentAtRef)(envelope, state.selection);
5067
- return segment === void 0 ? void 0 : (0, import_core19.resolveSelection)(envelope, segment);
5128
+ const segment = (0, import_core20.segmentAtRef)(envelope, state.selection);
5129
+ return segment === void 0 ? void 0 : (0, import_core20.resolveSelection)(envelope, segment);
5068
5130
  })();
5069
5131
  const componentAnchor = envelope === null || state.selection === null ? [] : selectionParagraphs(envelope, state);
5070
5132
  const selectedAddress = insertAnchor(componentAnchor, "after");
5071
- const beforeDisabledReason = componentAnchor[0] !== void 0 && (0, import_core19.isSectionDefinitionParagraph)(componentAnchor[0]) ? t("components.positionBeforeLocked") : "";
5133
+ const beforeDisabledReason = componentAnchor[0] !== void 0 && (0, import_core20.isSectionDefinitionParagraph)(componentAnchor[0]) ? t("components.positionBeforeLocked") : "";
5072
5134
  const componentDisabled = componentsSupportReason(capabilities, t) || (state.pendingOps.length > 0 ? t("components.pendingEdits") : "") || (state.selection === null ? t("components.noSelection") : selectedAddress !== null ? "" : selectedTargets?.refusal === "cell" ? t("segment.cellSelectionRefused") : selectedTargets?.refusal === "table" ? t("segment.tableSelectionRefused") : selectedTargets?.refusal === "container" ? t("segment.containerSelectionRefused") : t("components.noAddress"));
5073
5135
  const componentRefusal = (0, import_react13.useCallback)(
5074
5136
  (component) => insertionPreflight(component.blocks, state.document?.name ?? "", t),