@hwp-editor/react 1.3.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 +257 -188
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +3 -6
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.js +136 -67
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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
|
|
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
|
|
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.
|
|
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 =
|
|
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
|
|
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.
|
|
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,
|
|
@@ -178,32 +203,8 @@ function bandsOnPage(envelope, segment, page, pageIndex, pageCount) {
|
|
|
178
203
|
});
|
|
179
204
|
}
|
|
180
205
|
|
|
181
|
-
// src/sanitize.ts
|
|
182
|
-
function sanitizeSvg(svgText) {
|
|
183
|
-
const doc = new DOMParser().parseFromString(svgText, "image/svg+xml");
|
|
184
|
-
const root = doc.documentElement;
|
|
185
|
-
if (root === null || root.nodeName === "parsererror" || doc.getElementsByTagName("parsererror").length > 0) {
|
|
186
|
-
return "";
|
|
187
|
-
}
|
|
188
|
-
const dangerous = root.querySelectorAll("script, foreignObject");
|
|
189
|
-
for (const node of Array.from(dangerous)) node.remove();
|
|
190
|
-
scrubElement(root);
|
|
191
|
-
return root.outerHTML;
|
|
192
|
-
}
|
|
193
|
-
function scrubElement(el) {
|
|
194
|
-
for (const attr of Array.from(el.attributes)) {
|
|
195
|
-
const name = attr.name.toLowerCase();
|
|
196
|
-
const value = attr.value.trim().toLowerCase();
|
|
197
|
-
if (name.startsWith("on")) {
|
|
198
|
-
el.removeAttribute(attr.name);
|
|
199
|
-
} else if ((name === "href" || name === "xlink:href") && value.startsWith("javascript:")) {
|
|
200
|
-
el.removeAttribute(attr.name);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
for (const child of Array.from(el.children)) scrubElement(child);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
206
|
// src/text.ts
|
|
207
|
+
var import_core2 = require("@hwp-editor/core");
|
|
207
208
|
function plainSegmentText(markdownSlice) {
|
|
208
209
|
return markdownSlice.split("\n").map(stripLine).join("\n").trim();
|
|
209
210
|
}
|
|
@@ -217,6 +218,41 @@ function stripLine(line) {
|
|
|
217
218
|
out = out.replace(/`([^`]*)`/g, "$1");
|
|
218
219
|
return out;
|
|
219
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
|
+
}
|
|
220
256
|
|
|
221
257
|
// src/PageCanvas.tsx
|
|
222
258
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -231,11 +267,11 @@ function PageCanvas() {
|
|
|
231
267
|
if (envelope !== null) {
|
|
232
268
|
const refs = state.selections?.length ? state.selections : selection === null ? [] : [selection];
|
|
233
269
|
for (const ref of refs) {
|
|
234
|
-
const segment = (0,
|
|
270
|
+
const segment = (0, import_core3.segmentAtRef)(envelope, ref);
|
|
235
271
|
if (segment !== void 0) selectedSegments.add(segment);
|
|
236
272
|
}
|
|
237
273
|
}
|
|
238
|
-
if (pages.length === 0) {
|
|
274
|
+
if (pages.length === 0 || envelope === null) {
|
|
239
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") }) });
|
|
240
276
|
}
|
|
241
277
|
const selectAt = (pageIndex, xFraction, yFraction, modifiers) => {
|
|
@@ -243,7 +279,7 @@ function PageCanvas() {
|
|
|
243
279
|
const segment = segmentOnPage(envelope, pages[pageIndex], xFraction, yFraction, pageIndex, pages.length);
|
|
244
280
|
if (segment !== void 0) {
|
|
245
281
|
const mode = modifiers?.shiftKey ? "extend" : modifiers?.metaKey || modifiers?.ctrlKey ? "toggle" : "single";
|
|
246
|
-
store.dispatch((0,
|
|
282
|
+
store.dispatch((0, import_core3.selectionAction)(envelope, store.getState(), segment, mode));
|
|
247
283
|
}
|
|
248
284
|
};
|
|
249
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)(
|
|
@@ -289,7 +325,7 @@ function bandsForPage(envelope, page, pageIndex, pageCount, selected, pendingKey
|
|
|
289
325
|
bands.push({
|
|
290
326
|
...band,
|
|
291
327
|
key: `${isSelected ? "sel" : "pend"}-${key}-${bandIdentity(segment)}-${index}`,
|
|
292
|
-
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" : "")
|
|
293
329
|
});
|
|
294
330
|
}
|
|
295
331
|
}
|
|
@@ -299,14 +335,9 @@ function PageView(props) {
|
|
|
299
335
|
const { page, onClick, onActivate, bands } = props;
|
|
300
336
|
const { t } = useHwpEditorContext();
|
|
301
337
|
const label = t("page.label", { page: page.page });
|
|
302
|
-
const svgHtml = (0, import_react2.useMemo)(
|
|
303
|
-
() => page.format === "svg" ? sanitizeSvg(new TextDecoder().decode(page.data)) : null,
|
|
304
|
-
[page]
|
|
305
|
-
);
|
|
306
338
|
const imgSrc = (0, import_react2.useMemo)(() => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
return `data:${mime};base64,${import_core2.base64.encode(page.data)}`;
|
|
339
|
+
const mime = page.format === "jpeg" ? "image/jpeg" : page.format === "svg" ? "image/svg+xml" : `image/${page.format}`;
|
|
340
|
+
return `data:${mime};base64,${import_core3.base64.encode(page.data)}`;
|
|
310
341
|
}, [page]);
|
|
311
342
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
312
343
|
"div",
|
|
@@ -324,17 +355,11 @@ function PageView(props) {
|
|
|
324
355
|
}
|
|
325
356
|
},
|
|
326
357
|
children: [
|
|
327
|
-
|
|
328
|
-
"div",
|
|
329
|
-
{
|
|
330
|
-
className: "hwped-page-svg",
|
|
331
|
-
dangerouslySetInnerHTML: { __html: svgHtml }
|
|
332
|
-
}
|
|
333
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
358
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
334
359
|
"img",
|
|
335
360
|
{
|
|
336
361
|
className: "hwped-page-img",
|
|
337
|
-
src: imgSrc
|
|
362
|
+
src: imgSrc,
|
|
338
363
|
alt: label,
|
|
339
364
|
width: page.width,
|
|
340
365
|
height: page.height
|
|
@@ -344,6 +369,7 @@ function PageView(props) {
|
|
|
344
369
|
"div",
|
|
345
370
|
{
|
|
346
371
|
className: band.className,
|
|
372
|
+
"data-approximate": band.className.includes("hwped-band-approximate") ? "true" : void 0,
|
|
347
373
|
style: { top: `${band.top}%`, height: `${band.height}%`, left: `${band.left}%`, width: `${band.width}%` }
|
|
348
374
|
},
|
|
349
375
|
band.key
|
|
@@ -376,7 +402,7 @@ function targetsSegment(op, envelope, segment) {
|
|
|
376
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);
|
|
377
403
|
}
|
|
378
404
|
const target = opSearchText(op);
|
|
379
|
-
return target !== null && target !== "" && plainSegmentText((0,
|
|
405
|
+
return target !== null && target !== "" && plainSegmentText((0, import_core3.segmentText)(envelope, segment)).includes(target);
|
|
380
406
|
}
|
|
381
407
|
|
|
382
408
|
// src/unit-input.ts
|
|
@@ -387,7 +413,7 @@ function isPlainDecimal(value) {
|
|
|
387
413
|
|
|
388
414
|
// src/SegmentInspector.tsx
|
|
389
415
|
var import_react3 = require("react");
|
|
390
|
-
var
|
|
416
|
+
var import_core4 = require("@hwp-editor/core");
|
|
391
417
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
392
418
|
var ALIGNMENTS = [
|
|
393
419
|
{ value: "left", key: "segment.alignLeft" },
|
|
@@ -403,21 +429,29 @@ var SHAPE_KEYS = [
|
|
|
403
429
|
{ value: "top", key: "segment.shape.top" },
|
|
404
430
|
{ value: "bottom", key: "segment.shape.bottom" }
|
|
405
431
|
];
|
|
432
|
+
var CLICK_REFUSAL_MESSAGE = {
|
|
433
|
+
cell: "segment.clickRefusedCell",
|
|
434
|
+
table: "segment.clickRefusedTable",
|
|
435
|
+
container: "segment.clickRefusedContainer",
|
|
436
|
+
unaddressable: "segment.clickRefusedUnaddressable",
|
|
437
|
+
unaddressableRuns: "segment.clickRefusedUnaddressableRuns",
|
|
438
|
+
noRuns: "segment.clickRefusedNoRuns"
|
|
439
|
+
};
|
|
406
440
|
function SegmentInspector() {
|
|
407
441
|
const { state, store, envelope, editable, capabilities, styles, stylesStatus, t, insertedHidden } = useHwpEditorContext();
|
|
408
442
|
const { selection } = state;
|
|
409
443
|
const paragraphKeys = /* @__PURE__ */ new Set();
|
|
410
444
|
const paragraphs = (envelope?.segments.filter((candidate) => {
|
|
411
445
|
if (candidate.kind !== "para") return false;
|
|
412
|
-
if (!(0,
|
|
446
|
+
if (!(0, import_core4.hasOwnRef)(candidate)) return false;
|
|
413
447
|
const key = candidate.id ?? `${candidate.section}:${candidate.para}`;
|
|
414
448
|
if (paragraphKeys.has(key)) return false;
|
|
415
449
|
paragraphKeys.add(key);
|
|
416
450
|
return true;
|
|
417
|
-
}) ?? []).sort(
|
|
418
|
-
const selected = envelope === null ? [] : (0,
|
|
419
|
-
const segment = envelope !== null && selection !== null ? (0,
|
|
420
|
-
const targets = envelope !== null && segment !== void 0 ? (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;
|
|
421
455
|
const paragraphTargets = targets?.paragraphs ?? [];
|
|
422
456
|
const singleParagraph = targets?.paragraph;
|
|
423
457
|
const directStyleRow = (() => {
|
|
@@ -425,13 +459,13 @@ function SegmentInspector() {
|
|
|
425
459
|
if (id === void 0 || styles === null) return void 0;
|
|
426
460
|
return styles.styles.find((item) => item.kind === "paragraph" && item.used_by.includes(id));
|
|
427
461
|
})();
|
|
428
|
-
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,
|
|
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";
|
|
429
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");
|
|
430
|
-
const clickRefusedText = (reason) => reason === null || reason === void 0 ? null :
|
|
464
|
+
const clickRefusedText = (reason) => reason === null || reason === void 0 ? null : t(CLICK_REFUSAL_MESSAGE[reason]);
|
|
431
465
|
const refusalReason2 = refusalText(targets?.refusal);
|
|
432
|
-
const targetLabel = segment === void 0 ? "" : segment.kind === "cell" ? t("segment.selectedCell", { path: (0,
|
|
433
|
-
const currentText = envelope !== null && paragraphTargets.length > 0 ?
|
|
434
|
-
const markdownText = envelope !== null && singleParagraph !== void 0 ? (0,
|
|
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) : "";
|
|
435
469
|
const supplementaryStarts = (0, import_react3.useMemo)(() => {
|
|
436
470
|
const positions = [];
|
|
437
471
|
let offset = 0;
|
|
@@ -467,19 +501,19 @@ function SegmentInspector() {
|
|
|
467
501
|
setPlaceholderName("");
|
|
468
502
|
}, [selection]);
|
|
469
503
|
const find = currentText;
|
|
470
|
-
const address = singleParagraph === void 0 ? void 0 : (0,
|
|
504
|
+
const address = singleParagraph === void 0 ? void 0 : (0, import_core4.paragraphAddress)(singleParagraph);
|
|
471
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));
|
|
472
506
|
const siblingAt = siblings.findIndex((candidate) => candidate.id === singleParagraph?.id);
|
|
473
507
|
const addressedUnavailable = capabilities?.editOps !== "v1";
|
|
474
508
|
const disabled = !editable || addressedUnavailable || state.status === "applying";
|
|
475
509
|
const selectedRefs = state.selections?.length ? state.selections : selection === null ? [] : [selection];
|
|
476
510
|
const explicitSegments = envelope === null ? [] : selectedRefs.flatMap((ref) => {
|
|
477
|
-
const item = (0,
|
|
511
|
+
const item = (0, import_core4.segmentAtRef)(envelope, ref);
|
|
478
512
|
return item === void 0 ? [] : [item];
|
|
479
513
|
});
|
|
480
514
|
const hasRunSelection = explicitSegments.some((item) => item.kind === "run");
|
|
481
515
|
const multiSelection = explicitSegments.length > 1;
|
|
482
|
-
const paragraphRun = multiSelection && explicitSegments.every((item) => item.kind === "para") ? [...explicitSegments].sort(
|
|
516
|
+
const paragraphRun = multiSelection && explicitSegments.every((item) => item.kind === "para") ? [...explicitSegments].sort(import_core4.compareSegments) : null;
|
|
483
517
|
const runStart = paragraphRun === null ? -1 : siblings.findIndex((candidate) => candidate.id === paragraphRun[0]?.id);
|
|
484
518
|
const runContiguous = paragraphRun !== null && runStart >= 0 && paragraphRun.every((item, at) => siblings[runStart + at]?.id === item.id);
|
|
485
519
|
const runEnd = runContiguous ? runStart + paragraphRun.length - 1 : -1;
|
|
@@ -490,7 +524,7 @@ function SegmentInspector() {
|
|
|
490
524
|
if (insertionRun === null || !insertionCurrent || runParent === void 0) return [];
|
|
491
525
|
const section = insertionRun[0].section;
|
|
492
526
|
return insertedHidden.ids.flatMap((id) => {
|
|
493
|
-
const [idSection, ...indices] = (0,
|
|
527
|
+
const [idSection, ...indices] = (0, import_core4.segmentIdPath)(id);
|
|
494
528
|
if (idSection !== section || indices.length !== runParent.length + 1) return [];
|
|
495
529
|
if (!runParent.every((index, at) => indices[at] === index)) return [];
|
|
496
530
|
return [{ id, index: indices[indices.length - 1] }];
|
|
@@ -501,16 +535,16 @@ function SegmentInspector() {
|
|
|
501
535
|
if (published === void 0) return void 0;
|
|
502
536
|
const publishedIndex = published.indices?.[published.indices.length - 1];
|
|
503
537
|
const beyond = hiddenInRun.filter((hidden) => publishedIndex === void 0 || (edge === "first" ? hidden.index < publishedIndex : hidden.index > publishedIndex));
|
|
504
|
-
if (beyond.length === 0) return (0,
|
|
538
|
+
if (beyond.length === 0) return (0, import_core4.paragraphAddress)(published);
|
|
505
539
|
const pick = beyond.reduce((best, hidden) => (edge === "first" ? hidden.index < best.index : hidden.index > best.index) ? hidden : best);
|
|
506
540
|
return { id: pick.id };
|
|
507
541
|
};
|
|
508
542
|
const textSelectionRestricted = multiSelection || hasRunSelection || state.range != null;
|
|
509
543
|
const singleTargetDisabled = disabled || textSelectionRestricted || address === void 0;
|
|
510
544
|
const reorderRefused = multiSelection && !runContiguous;
|
|
511
|
-
const definitionLocked = paragraphRun === null ? singleParagraph !== void 0 && (0,
|
|
545
|
+
const definitionLocked = paragraphRun === null ? singleParagraph !== void 0 && (0, import_core4.isSectionDefinitionParagraph)(singleParagraph) : paragraphRun.some(import_core4.isSectionDefinitionParagraph);
|
|
512
546
|
const moveUpNeighbour = siblings[(paragraphRun === null ? siblingAt : runStart) - 1];
|
|
513
|
-
const definitionAbove = moveUpNeighbour !== void 0 && (0,
|
|
547
|
+
const definitionAbove = moveUpNeighbour !== void 0 && (0, import_core4.isSectionDefinitionParagraph)(moveUpNeighbour);
|
|
514
548
|
const deleteDisabled = disabled || definitionLocked || (paragraphRun === null ? textSelectionRestricted || address === void 0 : !runContiguous);
|
|
515
549
|
const moveUpDisabled = deleteDisabled || definitionAbove || (paragraphRun === null ? siblingAt <= 0 : runStart <= 0);
|
|
516
550
|
const moveDownDisabled = deleteDisabled || (paragraphRun === null ? siblingAt < 0 || siblingAt >= siblings.length - 1 : runEnd >= siblings.length - 1);
|
|
@@ -518,12 +552,12 @@ function SegmentInspector() {
|
|
|
518
552
|
const legacyLinkSeparator = capabilities?.editOps !== "v1" && [currentText, linkText, linkUrl].some((value) => value.includes("=>"));
|
|
519
553
|
const validShape = isPlainDecimal(shapeValue) && (shapeKey !== "line-spacing" || Number(shapeValue) > 0);
|
|
520
554
|
const validFontSize = fontSize.trim() === "" || isPlainDecimal(fontSize) && Number(fontSize) > 0;
|
|
521
|
-
const formatInputs = envelope === null ? [] : explicitSegments.flatMap((item) => item.kind === "run" ? [item] : (0,
|
|
522
|
-
const formatTargets = envelope === null ? [] : (0,
|
|
523
|
-
const runs = envelope === null || singleParagraph === void 0 ? [] : (0,
|
|
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);
|
|
524
558
|
const formatNoRuns = state.range == null && singleParagraph !== void 0 && singleParagraph.start !== singleParagraph.end && singleParagraph.indices === void 0 && runs.length === 0;
|
|
525
559
|
const rangeAvailable = !multiSelection && runs.some((run) => run.id !== void 0 || singleParagraph?.indices?.length === 1 && run.indices?.length === 2);
|
|
526
|
-
const charPrimary = segment?.kind === "run" ? segment : envelope !== null && state.range != null && formatTargets[0]?.address.id !== void 0 ? (0,
|
|
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;
|
|
527
561
|
const plainParagraph = (() => {
|
|
528
562
|
if (envelope === null || singleParagraph === void 0) return void 0;
|
|
529
563
|
const depth = singleParagraph.indices?.length;
|
|
@@ -534,7 +568,7 @@ function SegmentInspector() {
|
|
|
534
568
|
const contentEnd = singleParagraph.start + points.length;
|
|
535
569
|
const holdsControl = envelope.segments.some((item) => (item.kind === "field" || item.kind === "image" || item.kind === "bookmark") && item.start < contentEnd && item.end > singleParagraph.start);
|
|
536
570
|
if (holdsControl) return void 0;
|
|
537
|
-
const ordered = (0,
|
|
571
|
+
const ordered = (0, import_core4.paragraphRuns)(envelope, singleParagraph);
|
|
538
572
|
let cursor = singleParagraph.start;
|
|
539
573
|
for (const run of ordered) {
|
|
540
574
|
if (run.start !== cursor || run.end < run.start || run.end > contentEnd) return void 0;
|
|
@@ -550,7 +584,7 @@ function SegmentInspector() {
|
|
|
550
584
|
if (/^(?:[-+]|\d{1,3}[.)])\s/u.test(text)) return void 0;
|
|
551
585
|
return { runs: ordered, texts, text };
|
|
552
586
|
})();
|
|
553
|
-
const rangeRuns = envelope !== null && singleParagraph !== void 0 && state.range != null ? (0,
|
|
587
|
+
const rangeRuns = envelope !== null && singleParagraph !== void 0 && state.range != null ? (0, import_core4.paragraphRuns)(envelope, singleParagraph, state.range) : [];
|
|
554
588
|
const rangeFrom = rangeRuns.length === 0 ? -1 : Math.min(...rangeRuns.map((item) => item.start));
|
|
555
589
|
const rangeTo = rangeRuns.length === 0 ? -1 : Math.max(...rangeRuns.map((item) => item.end));
|
|
556
590
|
const wholeRuns = state.range != null && rangeRuns.length > 0 && rangeFrom === state.range.start && rangeTo === state.range.end;
|
|
@@ -583,7 +617,7 @@ function SegmentInspector() {
|
|
|
583
617
|
};
|
|
584
618
|
const activateSelection = (target, mode) => {
|
|
585
619
|
if (envelope === null) return;
|
|
586
|
-
store.dispatch((0,
|
|
620
|
+
store.dispatch((0, import_core4.selectionAction)(envelope, store.getState(), target, mode));
|
|
587
621
|
};
|
|
588
622
|
const handleOptionKeyDown = (event, target) => {
|
|
589
623
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
@@ -594,11 +628,11 @@ function SegmentInspector() {
|
|
|
594
628
|
if (envelope === null || singleParagraph === void 0) return;
|
|
595
629
|
const match = level === "char" ? charPrimary : singleParagraph;
|
|
596
630
|
if (match === void 0) return;
|
|
597
|
-
const refs = (0,
|
|
631
|
+
const refs = (0, import_core4.selectSimilar)(envelope, match, level);
|
|
598
632
|
if (refs.length === 0) return;
|
|
599
633
|
const activeMatch = refs.find((ref) => {
|
|
600
|
-
const item = (0,
|
|
601
|
-
const parent = item === void 0 ? void 0 : (0,
|
|
634
|
+
const item = (0, import_core4.segmentAtRef)(envelope, ref);
|
|
635
|
+
const parent = item === void 0 ? void 0 : (0, import_core4.resolveSelection)(envelope, item).paragraph;
|
|
602
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;
|
|
603
637
|
});
|
|
604
638
|
const primary = activeMatch ?? refs[0];
|
|
@@ -606,7 +640,10 @@ function SegmentInspector() {
|
|
|
606
640
|
type: "selectMany",
|
|
607
641
|
selections: refs,
|
|
608
642
|
primary,
|
|
609
|
-
|
|
643
|
+
// A matching-character-format selection is a new run selection, so its
|
|
644
|
+
// anchor is its own primary (#71 rule 7), never a run left over from an
|
|
645
|
+
// earlier one. The paragraph level keeps an existing anchor as before.
|
|
646
|
+
...level === "char" || state.selectionAnchor === null || state.selectionAnchor === void 0 ? { anchor: primary } : { anchor: state.selectionAnchor }
|
|
610
647
|
});
|
|
611
648
|
};
|
|
612
649
|
const moveParagraph = (direction) => {
|
|
@@ -618,7 +655,7 @@ function SegmentInspector() {
|
|
|
618
655
|
type: "queueOp",
|
|
619
656
|
op: {
|
|
620
657
|
kind: "move-para",
|
|
621
|
-
address: (0,
|
|
658
|
+
address: (0, import_core4.paragraphAddress)(neighbour2),
|
|
622
659
|
to: { address: anchor2, position: direction === -1 ? "after" : "before" }
|
|
623
660
|
}
|
|
624
661
|
});
|
|
@@ -632,7 +669,7 @@ function SegmentInspector() {
|
|
|
632
669
|
op: {
|
|
633
670
|
kind: "move-para",
|
|
634
671
|
address,
|
|
635
|
-
to: { address: (0,
|
|
672
|
+
to: { address: (0, import_core4.paragraphAddress)(neighbour2), position: direction === -1 ? "before" : "after" }
|
|
636
673
|
}
|
|
637
674
|
});
|
|
638
675
|
return;
|
|
@@ -645,7 +682,7 @@ function SegmentInspector() {
|
|
|
645
682
|
type: "queueOp",
|
|
646
683
|
op: {
|
|
647
684
|
kind: "move-para",
|
|
648
|
-
address: (0,
|
|
685
|
+
address: (0, import_core4.paragraphAddress)(neighbour),
|
|
649
686
|
to: { address: anchor, position: direction === -1 ? "after" : "before" }
|
|
650
687
|
}
|
|
651
688
|
});
|
|
@@ -670,7 +707,7 @@ function SegmentInspector() {
|
|
|
670
707
|
store.dispatch({
|
|
671
708
|
type: "queueOps",
|
|
672
709
|
ops: [
|
|
673
|
-
...paragraphRun.map((item) => ({ kind: "delete-para", address: (0,
|
|
710
|
+
...paragraphRun.map((item) => ({ kind: "delete-para", address: (0, import_core4.paragraphAddress)(item) })),
|
|
674
711
|
// The insertion's unpublished paragraphs go with it (#521).
|
|
675
712
|
...hiddenInRun.map((hidden) => ({ kind: "delete-para", address: { id: hidden.id } }))
|
|
676
713
|
]
|
|
@@ -694,7 +731,7 @@ function SegmentInspector() {
|
|
|
694
731
|
style: { maxHeight: "12rem", overflowY: "auto" },
|
|
695
732
|
children: paragraphs.map((candidate, index) => {
|
|
696
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);
|
|
697
|
-
const snippet = plainSegmentText((0,
|
|
734
|
+
const snippet = plainSegmentText((0, import_core4.segmentText)(envelope, candidate)).trim().replace(/\s+/g, " ");
|
|
698
735
|
const text = snippet.length > 96 ? `${snippet.slice(0, 93)}...` : snippet || t("segment.emptyPara");
|
|
699
736
|
const label = t("segment.choiceLabel", { index: index + 1, text });
|
|
700
737
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -720,9 +757,9 @@ function SegmentInspector() {
|
|
|
720
757
|
// state holds and the targets the format op will address.
|
|
721
758
|
children: hasRunSelection ? t("segment.selectedRunCount", { count: explicitSegments.length }) : t("segment.selectedCount", { count: selected.length })
|
|
722
759
|
}),
|
|
723
|
-
// A run-level selection formats runs, and a modifier click
|
|
724
|
-
//
|
|
725
|
-
hasRunSelection && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", role: "status", children: t("segment.
|
|
760
|
+
// A run-level selection formats runs, and a modifier click keeps it at
|
|
761
|
+
// run level: Ctrl toggles a unit's runs, Shift extends by run (#71).
|
|
762
|
+
hasRunSelection && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", role: "status", children: t("segment.runSelectionGestures") }),
|
|
726
763
|
// A modifier click that had no paragraph to add left the selection
|
|
727
764
|
// alone, and reports the click here whatever the selection's own
|
|
728
765
|
// reason is: the reader's action is what was refused, and a click
|
|
@@ -870,7 +907,7 @@ function SegmentInspector() {
|
|
|
870
907
|
disabled: disabled || selected.length === 0,
|
|
871
908
|
onClick: () => store.dispatch({
|
|
872
909
|
type: "queueOps",
|
|
873
|
-
ops: selected.map((target) => ({ kind: "set-align", address: (0,
|
|
910
|
+
ops: selected.map((target) => ({ kind: "set-align", address: (0, import_core4.paragraphAddress)(target), alignment: align.value }))
|
|
874
911
|
}),
|
|
875
912
|
children: t(align.key)
|
|
876
913
|
},
|
|
@@ -916,7 +953,7 @@ function SegmentInspector() {
|
|
|
916
953
|
type: "button",
|
|
917
954
|
className: "hwped-btn",
|
|
918
955
|
disabled: disabled || selected.length === 0 || !validShape,
|
|
919
|
-
onClick: () => store.dispatch({ type: "queueOps", ops: selected.map((target) => ({ kind: "set-para", address: (0,
|
|
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"}` })) }),
|
|
920
957
|
children: t("segment.setPara")
|
|
921
958
|
}
|
|
922
959
|
)
|
|
@@ -932,7 +969,7 @@ function SegmentInspector() {
|
|
|
932
969
|
charPrimary?.directChar === void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", children: t("segment.similarCharUnavailable") }),
|
|
933
970
|
singleParagraph.directPara === void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", children: t("segment.similarParaUnavailable") })
|
|
934
971
|
] }),
|
|
935
|
-
singleParagraph !== void 0 && (0,
|
|
972
|
+
singleParagraph !== void 0 && (0, import_core4.hasDirectFormatting)(singleParagraph) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "hwped-field", children: [
|
|
936
973
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "hwped-label", children: t("segment.directFormatting") }),
|
|
937
974
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "hwped-hint", children: t("segment.directFormattingHint") }),
|
|
938
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)(
|
|
@@ -941,7 +978,7 @@ function SegmentInspector() {
|
|
|
941
978
|
type: "button",
|
|
942
979
|
className: "hwped-btn",
|
|
943
980
|
disabled,
|
|
944
|
-
onClick: () => store.dispatch({ type: "queueOp", op: { kind: "apply-style", address: (0,
|
|
981
|
+
onClick: () => store.dispatch({ type: "queueOp", op: { kind: "apply-style", address: (0, import_core4.paragraphAddress)(singleParagraph), style: directStyleRow.id, clearDirect: true } }),
|
|
945
982
|
children: t("segment.clearDirect")
|
|
946
983
|
}
|
|
947
984
|
)
|
|
@@ -1015,7 +1052,7 @@ function SegmentInspector() {
|
|
|
1015
1052
|
}
|
|
1016
1053
|
setRangeSplit(false);
|
|
1017
1054
|
store.dispatch({ type: "setRange", range: start === end ? null : {
|
|
1018
|
-
paragraph: (0,
|
|
1055
|
+
paragraph: (0, import_core4.segmentRef)(singleParagraph),
|
|
1019
1056
|
start: singleParagraph.start + start,
|
|
1020
1057
|
end: singleParagraph.start + end
|
|
1021
1058
|
} });
|
|
@@ -1033,7 +1070,7 @@ function SegmentInspector() {
|
|
|
1033
1070
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "hwped-btn", onClick: () => {
|
|
1034
1071
|
setRangeSplit(false);
|
|
1035
1072
|
rangeInput.current?.setSelectionRange(0, 0);
|
|
1036
|
-
if (hasRunSelection) store.dispatch({ type: "select", selection: (0,
|
|
1073
|
+
if (hasRunSelection) store.dispatch({ type: "select", selection: (0, import_core4.segmentRef)(singleParagraph) });
|
|
1037
1074
|
else store.dispatch({ type: "setRange", range: null });
|
|
1038
1075
|
}, children: t("segment.rangeClear") })
|
|
1039
1076
|
] })
|
|
@@ -1193,7 +1230,7 @@ function wholeRunText(run, markdown) {
|
|
|
1193
1230
|
|
|
1194
1231
|
// src/StylesPanel.tsx
|
|
1195
1232
|
var import_react4 = require("react");
|
|
1196
|
-
var
|
|
1233
|
+
var import_core5 = require("@hwp-editor/core");
|
|
1197
1234
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1198
1235
|
var ALIGNMENTS2 = ["justify", "left", "right", "center", "distribute"];
|
|
1199
1236
|
var ALIGN_LABEL = {
|
|
@@ -1266,7 +1303,7 @@ function DefinitionForm(props) {
|
|
|
1266
1303
|
type: "queueOps",
|
|
1267
1304
|
ops: paragraphs.map((paragraph) => ({
|
|
1268
1305
|
kind: "apply-style",
|
|
1269
|
-
address: (0,
|
|
1306
|
+
address: (0, import_core5.paragraphAddress)(paragraph),
|
|
1270
1307
|
style: row.id
|
|
1271
1308
|
}))
|
|
1272
1309
|
});
|
|
@@ -1390,12 +1427,12 @@ function StylesPanel() {
|
|
|
1390
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") }) });
|
|
1391
1428
|
}
|
|
1392
1429
|
if (capabilities.styles !== "v1") {
|
|
1393
|
-
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,
|
|
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 }) }) });
|
|
1394
1431
|
}
|
|
1395
1432
|
if (engine.styles === void 0) {
|
|
1396
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") }) });
|
|
1397
1434
|
}
|
|
1398
|
-
const paragraphs = envelope === null ? [] : (0,
|
|
1435
|
+
const paragraphs = envelope === null ? [] : (0, import_core5.selectedParagraphs)(envelope, state);
|
|
1399
1436
|
const rows = styles?.styles ?? [];
|
|
1400
1437
|
const row = rows.find((item) => item.id === selectedId) ?? null;
|
|
1401
1438
|
const paragraphRow = row !== null && row.kind === "paragraph" ? row : null;
|
|
@@ -1405,8 +1442,8 @@ function StylesPanel() {
|
|
|
1405
1442
|
setSelectedId(item.id);
|
|
1406
1443
|
if (envelope === null || item.used_by.length === 0) return;
|
|
1407
1444
|
const refs = item.used_by.flatMap((id) => {
|
|
1408
|
-
const segment = (0,
|
|
1409
|
-
return segment === void 0 ? [] : [(0,
|
|
1445
|
+
const segment = (0, import_core5.segmentAtRef)(envelope, { id, section: 0, para: 0 });
|
|
1446
|
+
return segment === void 0 ? [] : [(0, import_core5.segmentRef)(segment)];
|
|
1410
1447
|
});
|
|
1411
1448
|
if (refs.length === 0) return;
|
|
1412
1449
|
store.dispatch({ type: "selectMany", selections: refs, primary: refs[0], anchor: refs[0] });
|
|
@@ -1417,12 +1454,12 @@ function StylesPanel() {
|
|
|
1417
1454
|
const shape = base === void 0 ? void 0 : base.direct ?? base.style;
|
|
1418
1455
|
if (name === "" || base === void 0 || shape === void 0 || envelope === null) return;
|
|
1419
1456
|
const face = firstFace(shape);
|
|
1420
|
-
const paragraph = (0,
|
|
1457
|
+
const paragraph = (0, import_core5.resolveSelection)(envelope, base).paragraph ?? base;
|
|
1421
1458
|
const id = paragraph.id;
|
|
1422
1459
|
const own = id === void 0 ? void 0 : rows.find((item) => item.kind === "paragraph" && item.used_by.includes(id));
|
|
1423
|
-
const targets = (0,
|
|
1424
|
-
const segment = (0,
|
|
1425
|
-
return segment === void 0 ? [] : [(0,
|
|
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)];
|
|
1426
1463
|
});
|
|
1427
1464
|
const align = shape.para === void 0 ? void 0 : writableAlignment(shape.para.alignment);
|
|
1428
1465
|
store.dispatch({
|
|
@@ -1458,7 +1495,7 @@ function StylesPanel() {
|
|
|
1458
1495
|
const switchPreset = () => {
|
|
1459
1496
|
if (styles === null || envelope === null) return;
|
|
1460
1497
|
const epoch = loadEpoch();
|
|
1461
|
-
const styleOps = (0,
|
|
1498
|
+
const styleOps = (0, import_core5.presetStyleOps)(styles, preset, envelope);
|
|
1462
1499
|
const carriedStyleOp = styleOps.length > 0;
|
|
1463
1500
|
const batch = [
|
|
1464
1501
|
...styleOps,
|
|
@@ -1468,10 +1505,10 @@ function StylesPanel() {
|
|
|
1468
1505
|
let unstyled = false;
|
|
1469
1506
|
let changed = false;
|
|
1470
1507
|
void replaceDocument(async (current) => {
|
|
1471
|
-
const styled = await engine.edit(current, batch, (0,
|
|
1472
|
-
const reading = (0,
|
|
1508
|
+
const styled = await engine.edit(current, batch, (0, import_core5.presetBatchOptions)(batch, { verify: true }));
|
|
1509
|
+
const reading = (0, import_core5.readPresetBatch)(styled.report);
|
|
1473
1510
|
if (reading.refusal !== null) {
|
|
1474
|
-
throw new
|
|
1511
|
+
throw new import_core5.HwpEngineError(reading.refusal.code, reading.refusal.message);
|
|
1475
1512
|
}
|
|
1476
1513
|
unstyled = reading.unstyledTable;
|
|
1477
1514
|
changed = !reading.unchanged;
|
|
@@ -1554,7 +1591,7 @@ function StylesPanel() {
|
|
|
1554
1591
|
disabled,
|
|
1555
1592
|
"aria-label": t("styles.presetLabel"),
|
|
1556
1593
|
onChange: (e) => setPreset(e.target.value),
|
|
1557
|
-
children:
|
|
1594
|
+
children: import_core5.STYLE_TABLE_PRESETS.map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value, children: t(PRESET_LABEL[value]) }, value))
|
|
1558
1595
|
}
|
|
1559
1596
|
),
|
|
1560
1597
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -1575,10 +1612,10 @@ function StylesPanel() {
|
|
|
1575
1612
|
|
|
1576
1613
|
// src/TableGrid.tsx
|
|
1577
1614
|
var import_react5 = require("react");
|
|
1578
|
-
var
|
|
1615
|
+
var import_core7 = require("@hwp-editor/core");
|
|
1579
1616
|
|
|
1580
1617
|
// src/tables.ts
|
|
1581
|
-
var
|
|
1618
|
+
var import_core6 = require("@hwp-editor/core");
|
|
1582
1619
|
var GFM_DELIMITER_CELL = /^:?-{2,}:?$/;
|
|
1583
1620
|
function endsWithCellDelimiter(row) {
|
|
1584
1621
|
if (!row.endsWith("|")) return false;
|
|
@@ -1645,7 +1682,7 @@ function findTables(envelope) {
|
|
|
1645
1682
|
tables.push({
|
|
1646
1683
|
tableIndex: tables.length,
|
|
1647
1684
|
segment,
|
|
1648
|
-
rows: parseMarkdownTable((0,
|
|
1685
|
+
rows: parseMarkdownTable((0, import_core6.segmentText)(envelope, segment))
|
|
1649
1686
|
});
|
|
1650
1687
|
}
|
|
1651
1688
|
return tables;
|
|
@@ -1715,7 +1752,7 @@ function TableGrid() {
|
|
|
1715
1752
|
}
|
|
1716
1753
|
)
|
|
1717
1754
|
] });
|
|
1718
|
-
const mismatch = envelope === null ? null : (0,
|
|
1755
|
+
const mismatch = envelope === null ? null : (0, import_core7.tableCountMismatch)(envelope);
|
|
1719
1756
|
if (mismatch !== null) {
|
|
1720
1757
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "hwped-panel", role: "region", "aria-label": t("table.panelAria"), children: [
|
|
1721
1758
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "hwped-hint", children: t("table.indexMismatch", mismatch) }),
|
|
@@ -1950,10 +1987,10 @@ function TableGrid() {
|
|
|
1950
1987
|
|
|
1951
1988
|
// src/FieldsPanel.tsx
|
|
1952
1989
|
var import_react6 = require("react");
|
|
1953
|
-
var
|
|
1990
|
+
var import_core9 = require("@hwp-editor/core");
|
|
1954
1991
|
|
|
1955
1992
|
// src/fields.ts
|
|
1956
|
-
var
|
|
1993
|
+
var import_core8 = require("@hwp-editor/core");
|
|
1957
1994
|
var SLOT_PATTERN = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
1958
1995
|
var CONTROL_KINDS = /* @__PURE__ */ new Set(["field", "image", "bookmark"]);
|
|
1959
1996
|
function innermostAt(envelope, offset) {
|
|
@@ -1981,10 +2018,10 @@ function extractFieldSlots(envelope) {
|
|
|
1981
2018
|
const offset = [...envelope.markdown.slice(0, match.index ?? 0)].length;
|
|
1982
2019
|
const hit = innermostAt(envelope, offset);
|
|
1983
2020
|
if (hit === void 0 || seen.has(name)) continue;
|
|
1984
|
-
const paragraph = (0,
|
|
2021
|
+
const paragraph = (0, import_core8.resolveSelection)(envelope, hit).paragraph;
|
|
1985
2022
|
if (paragraph === void 0) continue;
|
|
1986
2023
|
seen.add(name);
|
|
1987
|
-
slots.push({ name, segment: (0,
|
|
2024
|
+
slots.push({ name, segment: (0, import_core8.segmentRef)(paragraph) });
|
|
1988
2025
|
}
|
|
1989
2026
|
return slots;
|
|
1990
2027
|
}
|
|
@@ -2018,8 +2055,8 @@ function FieldsPanel() {
|
|
|
2018
2055
|
children: [
|
|
2019
2056
|
legacy && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "hwped-hint", children: t("fields.legacySeparatorHint") }),
|
|
2020
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) => {
|
|
2021
|
-
const segment = envelope === null ? void 0 : (0,
|
|
2022
|
-
const snippet = envelope === null || segment === void 0 ? "" : (0,
|
|
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);
|
|
2023
2060
|
const draft = drafts[slot.name] ?? "";
|
|
2024
2061
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { className: "hwped-field-item", children: [
|
|
2025
2062
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hwped-row", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
@@ -2088,19 +2125,19 @@ function FieldsPanel() {
|
|
|
2088
2125
|
|
|
2089
2126
|
// src/TemplatePanel.tsx
|
|
2090
2127
|
var import_react7 = require("react");
|
|
2091
|
-
var
|
|
2128
|
+
var import_core13 = require("@hwp-editor/core");
|
|
2092
2129
|
|
|
2093
2130
|
// src/errors.ts
|
|
2094
|
-
var
|
|
2131
|
+
var import_core10 = require("@hwp-editor/core");
|
|
2095
2132
|
function toEditorError(e) {
|
|
2096
2133
|
const refusal = engineRefusalKind(e);
|
|
2097
|
-
const base = (0,
|
|
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) };
|
|
2098
2135
|
return refusal === void 0 ? base : { ...base, refusal };
|
|
2099
2136
|
}
|
|
2100
2137
|
function engineRefusalKind(e) {
|
|
2101
2138
|
if (typeof e !== "object" || e === null) return void 0;
|
|
2102
2139
|
const refusal = e.refusal;
|
|
2103
|
-
return (0,
|
|
2140
|
+
return (0, import_core10.isEditRefusalKind)(refusal) ? refusal : void 0;
|
|
2104
2141
|
}
|
|
2105
2142
|
function engineStoppedWithoutDiagnostic(e) {
|
|
2106
2143
|
return typeof e === "object" && e !== null && e.stopped === true;
|
|
@@ -2170,8 +2207,8 @@ function ErrorLine(props) {
|
|
|
2170
2207
|
}
|
|
2171
2208
|
|
|
2172
2209
|
// src/template-support.ts
|
|
2173
|
-
var import_core10 = require("@hwp-editor/core");
|
|
2174
2210
|
var import_core11 = require("@hwp-editor/core");
|
|
2211
|
+
var import_core12 = require("@hwp-editor/core");
|
|
2175
2212
|
var METHOD_LABEL_KEYS = {
|
|
2176
2213
|
slots: "templates.methodSlots",
|
|
2177
2214
|
fill: "templates.methodFill",
|
|
@@ -2181,7 +2218,7 @@ var METHOD_LABEL_KEYS = {
|
|
|
2181
2218
|
create: "templates.methodCreate"
|
|
2182
2219
|
};
|
|
2183
2220
|
function templateMethodStatus(engine, capabilities, method) {
|
|
2184
|
-
if (!(0,
|
|
2221
|
+
if (!(0, import_core11.templateVersionSupported)(capabilities?.version ?? "")) {
|
|
2185
2222
|
return { supported: false, reason: "version" };
|
|
2186
2223
|
}
|
|
2187
2224
|
if (typeof engine[method] !== "function") {
|
|
@@ -2193,7 +2230,7 @@ function templateMethodStatus(engine, capabilities, method) {
|
|
|
2193
2230
|
return { supported: true, reason: null };
|
|
2194
2231
|
}
|
|
2195
2232
|
function templateStatusReason(t, status, method) {
|
|
2196
|
-
if (status.reason === "version") return t("templates.versionRequired", { version:
|
|
2233
|
+
if (status.reason === "version") return t("templates.versionRequired", { version: import_core12.TEMPLATE_MIN_VERSION });
|
|
2197
2234
|
const label = t(METHOD_LABEL_KEYS[method]);
|
|
2198
2235
|
if (status.reason === "missing") return t("templates.methodMissing", { method: label });
|
|
2199
2236
|
if (status.reason === "unadvertised") return t("templates.methodUnadvertised", { method: label });
|
|
@@ -2215,7 +2252,7 @@ function initialListRow(fields, supplied = {}) {
|
|
|
2215
2252
|
}
|
|
2216
2253
|
function pageData(page) {
|
|
2217
2254
|
const mime = page.format === "svg" ? "image/svg+xml" : `image/${page.format}`;
|
|
2218
|
-
return `data:${mime};base64,${
|
|
2255
|
+
return `data:${mime};base64,${import_core13.base64.encode(page.data)}`;
|
|
2219
2256
|
}
|
|
2220
2257
|
function kindLabel(input, t) {
|
|
2221
2258
|
if (input.kind === "slot") return t("templates.kindSlot");
|
|
@@ -2706,7 +2743,7 @@ function DocumentPanel() {
|
|
|
2706
2743
|
|
|
2707
2744
|
// src/ImagePanel.tsx
|
|
2708
2745
|
var import_react10 = require("react");
|
|
2709
|
-
var
|
|
2746
|
+
var import_core14 = require("@hwp-editor/core");
|
|
2710
2747
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2711
2748
|
function ImagePanel() {
|
|
2712
2749
|
const { state, store, envelope, capabilities, editable, queueImage, onError, t } = useHwpEditorContext();
|
|
@@ -2744,14 +2781,14 @@ function ImagePanel() {
|
|
|
2744
2781
|
if (file === void 0) return;
|
|
2745
2782
|
setReading(true);
|
|
2746
2783
|
try {
|
|
2747
|
-
if (file.size === 0 || file.size >
|
|
2784
|
+
if (file.size === 0 || file.size > import_core14.MAX_IMAGE_ASSET_BYTES) throw new Error(t("image.invalidSize"));
|
|
2748
2785
|
let bytes;
|
|
2749
2786
|
try {
|
|
2750
2787
|
bytes = await file.arrayBuffer();
|
|
2751
2788
|
} catch {
|
|
2752
2789
|
throw new Error(t("image.readError"));
|
|
2753
2790
|
}
|
|
2754
|
-
const data = new Uint8Array(bytes), mediaType = (0,
|
|
2791
|
+
const data = new Uint8Array(bytes), mediaType = (0, import_core14.imageAssetMediaType)(data);
|
|
2755
2792
|
if (mediaType === null) throw new Error(t("image.invalidType"));
|
|
2756
2793
|
if (generation.current === version && store.getState().document === source) {
|
|
2757
2794
|
setChosen({ name: file.name, data, extension: mediaType === "image/png" ? "png" : "jpg" });
|
|
@@ -2809,12 +2846,12 @@ function ImagePanel() {
|
|
|
2809
2846
|
|
|
2810
2847
|
// src/ComposePanel.tsx
|
|
2811
2848
|
var import_react11 = require("react");
|
|
2812
|
-
var
|
|
2849
|
+
var import_core17 = require("@hwp-editor/core");
|
|
2813
2850
|
|
|
2814
2851
|
// src/presets.ts
|
|
2815
|
-
var
|
|
2816
|
-
var COMPOSE_PRESETS = [...
|
|
2817
|
-
var PRESET_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;
|
|
2818
2855
|
function bodyToBlocks(body) {
|
|
2819
2856
|
const blocks = [];
|
|
2820
2857
|
for (const chunk of body.split(/\n\s*\n/)) {
|
|
@@ -2875,17 +2912,17 @@ function buildDocumentSpec(preset, input) {
|
|
|
2875
2912
|
},
|
|
2876
2913
|
heading: {
|
|
2877
2914
|
font_family: profile.fontFamily,
|
|
2878
|
-
font_size_pt: profile.bodySizePt +
|
|
2915
|
+
font_size_pt: profile.bodySizePt + import_core15.COMPOSE_STYLE_ROWS.heading.sizeDeltaPt,
|
|
2879
2916
|
bold: true,
|
|
2880
|
-
spacing_before_pt:
|
|
2881
|
-
spacing_after_pt:
|
|
2917
|
+
spacing_before_pt: import_core15.COMPOSE_STYLE_ROWS.heading.spacingBeforePt,
|
|
2918
|
+
spacing_after_pt: import_core15.COMPOSE_STYLE_ROWS.heading.spacingAfterPt
|
|
2882
2919
|
},
|
|
2883
2920
|
title: {
|
|
2884
2921
|
font_family: profile.fontFamily,
|
|
2885
|
-
font_size_pt: profile.bodySizePt +
|
|
2922
|
+
font_size_pt: profile.bodySizePt + import_core15.COMPOSE_STYLE_ROWS.title.sizeDeltaPt,
|
|
2886
2923
|
bold: true,
|
|
2887
2924
|
align: "center",
|
|
2888
|
-
spacing_after_pt:
|
|
2925
|
+
spacing_after_pt: import_core15.COMPOSE_STYLE_ROWS.title.spacingAfterPt
|
|
2889
2926
|
}
|
|
2890
2927
|
},
|
|
2891
2928
|
sections: [section]
|
|
@@ -2894,7 +2931,7 @@ function buildDocumentSpec(preset, input) {
|
|
|
2894
2931
|
}
|
|
2895
2932
|
|
|
2896
2933
|
// src/components-support.ts
|
|
2897
|
-
var
|
|
2934
|
+
var import_core16 = require("@hwp-editor/core");
|
|
2898
2935
|
function millimetres(value) {
|
|
2899
2936
|
return `${Math.round(value * 10) / 10} mm`;
|
|
2900
2937
|
}
|
|
@@ -2950,7 +2987,7 @@ function insertionPreflight(blocks, documentName, t) {
|
|
|
2950
2987
|
function insertionOf(error) {
|
|
2951
2988
|
if (typeof error !== "object" || error === null) return void 0;
|
|
2952
2989
|
const value = error.insertion;
|
|
2953
|
-
return (0,
|
|
2990
|
+
return (0, import_core16.isInsertionRefusal)(value) ? value : void 0;
|
|
2954
2991
|
}
|
|
2955
2992
|
function overflowingBodyMm(error) {
|
|
2956
2993
|
const insertion = insertionOf(error);
|
|
@@ -2960,10 +2997,10 @@ function isLayoutOverflow(error) {
|
|
|
2960
2997
|
return insertionOf(error)?.kind === "layout_overflow";
|
|
2961
2998
|
}
|
|
2962
2999
|
function wrapped(error, text, detail) {
|
|
2963
|
-
if ((0,
|
|
3000
|
+
if ((0, import_core16.isHwpEngineError)(error)) {
|
|
2964
3001
|
const insertion = insertionOf(error);
|
|
2965
3002
|
return Object.assign(
|
|
2966
|
-
new
|
|
3003
|
+
new import_core16.HwpEngineError(error.code, text, {
|
|
2967
3004
|
...error.status === void 0 ? {} : { status: error.status },
|
|
2968
3005
|
cause: error,
|
|
2969
3006
|
...insertion === void 0 ? {} : { insertion },
|
|
@@ -2984,7 +3021,7 @@ function refusalReason(message) {
|
|
|
2984
3021
|
}
|
|
2985
3022
|
function isRefusedInsertion(error) {
|
|
2986
3023
|
if (insertionOf(error) !== void 0) return true;
|
|
2987
|
-
return (0,
|
|
3024
|
+
return (0, import_core16.isHwpEngineError)(error) && (error.code === "failed" || error.code === "bad_request");
|
|
2988
3025
|
}
|
|
2989
3026
|
function insertionFailure(error, blocks, t) {
|
|
2990
3027
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -3012,7 +3049,7 @@ var STEP_KEYS = {
|
|
|
3012
3049
|
component_load: "components.step.load"
|
|
3013
3050
|
};
|
|
3014
3051
|
function componentRefusalText(error, t) {
|
|
3015
|
-
if (!(0,
|
|
3052
|
+
if (!(0, import_core16.isComponentError)(error)) return null;
|
|
3016
3053
|
return t("components.refused", {
|
|
3017
3054
|
code: error.code,
|
|
3018
3055
|
source: error.source,
|
|
@@ -3041,7 +3078,7 @@ var PRESET_LABEL_KEYS = {
|
|
|
3041
3078
|
};
|
|
3042
3079
|
function ComposePanel(props) {
|
|
3043
3080
|
const { engine, t, onError, store, state, loadEpoch, loadSettled, loadInFlight } = useHwpEditorContext();
|
|
3044
|
-
const components = props.components ??
|
|
3081
|
+
const components = props.components ?? import_core17.STARTER_COMPONENTS;
|
|
3045
3082
|
const [preset, setPreset] = (0, import_react11.useState)("official");
|
|
3046
3083
|
const [title, setTitle] = (0, import_react11.useState)("");
|
|
3047
3084
|
const [author, setAuthor] = (0, import_react11.useState)("");
|
|
@@ -3163,7 +3200,7 @@ function ComposePanel(props) {
|
|
|
3163
3200
|
const source = store.getState().document;
|
|
3164
3201
|
try {
|
|
3165
3202
|
const written = title.trim();
|
|
3166
|
-
const spec = assembling ? (0,
|
|
3203
|
+
const spec = assembling ? (0, import_core17.documentSpecFromComponents)(
|
|
3167
3204
|
assembly.map((row) => ({ component: row.component, values: row.values })),
|
|
3168
3205
|
written === "" ? {} : { title: written }
|
|
3169
3206
|
) : buildDocumentSpec(preset, { title, author, body });
|
|
@@ -3408,18 +3445,18 @@ function ComposePanel(props) {
|
|
|
3408
3445
|
|
|
3409
3446
|
// src/ComponentsPanel.tsx
|
|
3410
3447
|
var import_react12 = require("react");
|
|
3411
|
-
var
|
|
3448
|
+
var import_core18 = require("@hwp-editor/core");
|
|
3412
3449
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
3413
3450
|
function componentsSupportReason(capabilities, t) {
|
|
3414
3451
|
if (capabilities === null) return "";
|
|
3415
3452
|
if (capabilities.editOps !== "v1") return t("components.disabledChannel");
|
|
3416
|
-
if (!(0,
|
|
3417
|
-
return t("components.disabledVersion", { version:
|
|
3453
|
+
if (!(0, import_core18.editReportSupported)(capabilities.version)) {
|
|
3454
|
+
return t("components.disabledVersion", { version: import_core18.EDIT_REPORT_MIN_VERSION });
|
|
3418
3455
|
}
|
|
3419
3456
|
return "";
|
|
3420
3457
|
}
|
|
3421
3458
|
function ComponentsPanel({
|
|
3422
|
-
components =
|
|
3459
|
+
components = import_core18.STARTER_COMPONENTS,
|
|
3423
3460
|
disabledReason = "",
|
|
3424
3461
|
beforeDisabledReason = "",
|
|
3425
3462
|
refusalFor,
|
|
@@ -3643,7 +3680,7 @@ function pendingTargetLabel(op, t, resolvers = {}, envelope = null) {
|
|
|
3643
3680
|
}
|
|
3644
3681
|
|
|
3645
3682
|
// src/messages.ts
|
|
3646
|
-
var
|
|
3683
|
+
var import_core19 = require("@hwp-editor/core");
|
|
3647
3684
|
var en = {
|
|
3648
3685
|
// Toolbar
|
|
3649
3686
|
"toolbar.toolsAria": "Editing tools",
|
|
@@ -3870,7 +3907,7 @@ var en = {
|
|
|
3870
3907
|
"segment.rangeTextEditHint": "A character range formats text but cannot rewrite it. Use whole paragraph to edit its text.",
|
|
3871
3908
|
"segment.runTextEditHint": "A run selection formats runs only, so the text controls are off. Select a paragraph to edit its text.",
|
|
3872
3909
|
"segment.runSelectionParagraphs": (p) => p.count === 1 ? "Alignment and spacing apply to the 1 paragraph containing a selected run." : `Alignment and spacing apply to all ${p.count} paragraphs containing a selected run.`,
|
|
3873
|
-
"segment.
|
|
3910
|
+
"segment.runSelectionGestures": "Ctrl adds or removes a paragraph's runs; Shift extends by run.",
|
|
3874
3911
|
"segment.noParagraphSelection": "This selection carries no paragraph the engine can address, so paragraph edits are off. Pick a paragraph from the list above.",
|
|
3875
3912
|
"segment.cellSelectionRefused": "This selection is a table cell. Alignment and spacing apply to every paragraph in the cell, but replace, insert and delete address exactly one paragraph, and the engine refuses to delete a cell's last one. Pick a paragraph from the list above.",
|
|
3876
3913
|
"segment.tableSelectionRefused": "This selection is a table, not a paragraph. The paragraph that holds the table also holds its own text, so editing or deleting it would take the table with it. Pick a paragraph from the list above.",
|
|
@@ -3886,6 +3923,8 @@ var en = {
|
|
|
3886
3923
|
"segment.clickRefusedTable": "The click added nothing: a table has no paragraph of its own, so there is none to add. Click a paragraph or a cell.",
|
|
3887
3924
|
"segment.clickRefusedContainer": "The click added nothing: an image, a field or a bookmark has no text of its own, so there is no paragraph to add. Click a paragraph or a cell.",
|
|
3888
3925
|
"segment.clickRefusedUnaddressable": "That unit does not name a paragraph the engine can address, so the click selected nothing. Click a paragraph or a cell.",
|
|
3926
|
+
"segment.clickRefusedUnaddressableRuns": "The clicked paragraph or cell has runs, but the engine published no address for them, so the click selected nothing. Click without Ctrl or Shift to select the whole paragraph, or click a paragraph or cell whose runs have addresses.",
|
|
3927
|
+
"segment.clickRefusedNoRuns": "The clicked paragraph or cell has no runs to add. Click a paragraph or cell that has text.",
|
|
3889
3928
|
"segment.selectSimilar": "Select content with matching direct formatting",
|
|
3890
3929
|
"segment.similarChar": "Matching character format",
|
|
3891
3930
|
"segment.similarPara": "Matching paragraph format",
|
|
@@ -4012,11 +4051,12 @@ var en = {
|
|
|
4012
4051
|
"error.staleCompose": "The open document changed while the new document was being composed; compose again.",
|
|
4013
4052
|
"error.stalePreview": "The document changed while this preview was being made; preview again on the open document.",
|
|
4014
4053
|
"error.unmatchedReplace": "The engine found no text to replace in that paragraph, so nothing was applied. Select the text again and retry.",
|
|
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.",
|
|
4015
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.",
|
|
4016
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.",
|
|
4017
|
-
"error.stoppedWithoutDiagnostic":
|
|
4057
|
+
"error.stoppedWithoutDiagnostic": import_core19.STOPPED_WITHOUT_DIAGNOSTIC,
|
|
4018
4058
|
// The same rule for a failure with stderr but no Error: line (#140).
|
|
4019
|
-
"error.noEngineCause":
|
|
4059
|
+
"error.noEngineCause": import_core19.NO_ENGINE_CAUSE,
|
|
4020
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.`,
|
|
4021
4061
|
"error.readOnlyReplacement": "The editor became read-only before the template could be applied; switch to an editable document and retry.",
|
|
4022
4062
|
"error.pendingReplacement": "Pending edits would be lost; apply or clear them before replacing this document.",
|
|
@@ -4092,14 +4132,14 @@ var en = {
|
|
|
4092
4132
|
"image.insert": "Insert image",
|
|
4093
4133
|
"image.delete": "Delete image",
|
|
4094
4134
|
"image.file": "PNG/JPEG image file",
|
|
4095
|
-
"image.fileHint": `Choose a PNG or JPEG image up to ${
|
|
4135
|
+
"image.fileHint": `Choose a PNG or JPEG image up to ${import_core19.MAX_IMAGE_ASSET_MIB} MiB.`,
|
|
4096
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.",
|
|
4097
4137
|
"image.anchor": "Insert after paragraph text",
|
|
4098
4138
|
"image.deleteAnchor": "Image anchor text to delete",
|
|
4099
4139
|
"image.width": "Width (mm)",
|
|
4100
4140
|
"image.height": "Height (mm)",
|
|
4101
4141
|
"image.reading": "Reading image...",
|
|
4102
|
-
"image.invalidSize": `The image is empty or exceeds ${
|
|
4142
|
+
"image.invalidSize": `The image is empty or exceeds ${import_core19.MAX_IMAGE_ASSET_MIB} MiB; choose a smaller PNG/JPEG file.`,
|
|
4103
4143
|
"image.invalidType": "The file is not PNG/JPEG image data; choose a supported image.",
|
|
4104
4144
|
"image.readError": "The image could not be read; select the file again.",
|
|
4105
4145
|
"error.prefix.image": "Image operation failed",
|
|
@@ -4341,7 +4381,7 @@ var ko = {
|
|
|
4341
4381
|
"segment.rangeTextEditHint": "\uAE00\uC790 \uBC94\uC704 \uC120\uD0DD\uC740 \uC11C\uC2DD\uB9CC \uBC14\uAFC0 \uC218 \uC788\uACE0 \uD14D\uC2A4\uD2B8\uB294 \uBC14\uAFC0 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD14D\uC2A4\uD2B8\uB97C \uD3B8\uC9D1\uD558\uB824\uBA74 \uBB38\uB2E8 \uC804\uCCB4\uB97C \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
4342
4382
|
"segment.runTextEditHint": "run \uC120\uD0DD\uC740 \uC11C\uC2DD\uB9CC \uBC14\uAFC0 \uC218 \uC788\uC5B4 \uD14D\uC2A4\uD2B8 \uC785\uB825\uB780\uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD14D\uC2A4\uD2B8\uB97C \uD3B8\uC9D1\uD558\uB824\uBA74 \uBB38\uB2E8\uC744 \uC120\uD0DD\uD558\uC138\uC694.",
|
|
4343
4383
|
"segment.runSelectionParagraphs": (p) => `\uBB38\uB2E8 \uC815\uB82C\uACFC \uAC04\uACA9\uC740 \uC120\uD0DD\uD55C run\uC774 \uC788\uB294 \uBB38\uB2E8 ${p.count}\uAC1C \uC804\uCCB4\uC5D0 \uC801\uC6A9\uB429\uB2C8\uB2E4.`,
|
|
4344
|
-
"segment.
|
|
4384
|
+
"segment.runSelectionGestures": "Ctrl\uB85C \uBB38\uB2E8\uC758 run\uC744 \uB354\uD558\uAC70\uB098 \uBE7C\uACE0, Shift\uB85C run \uB2E8\uC704\uB85C \uB113\uD799\uB2C8\uB2E4.",
|
|
4345
4385
|
"segment.noParagraphSelection": "\uC774 \uC120\uD0DD\uC5D0\uB294 \uC5D4\uC9C4\uC774 \uC8FC\uC18C\uB85C \uC9C0\uC815\uD560 \uC218 \uC788\uB294 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uBB38\uB2E8 \uD3B8\uC9D1\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC704 \uBAA9\uB85D\uC5D0\uC11C \uBB38\uB2E8\uC744 \uC120\uD0DD\uD558\uC138\uC694.",
|
|
4346
4386
|
"segment.cellSelectionRefused": "\uC774 \uC120\uD0DD\uC740 \uD45C\uC758 \uC140\uC785\uB2C8\uB2E4. \uC815\uB82C\uACFC \uBB38\uB2E8 \uBAA8\uC591\uC740 \uC140 \uC548\uC758 \uBAA8\uB4E0 \uBB38\uB2E8\uC5D0 \uC801\uC6A9\uB418\uC9C0\uB9CC, \uAD50\uCCB4, \uC0BD\uC785, \uC0AD\uC81C\uB294 \uBB38\uB2E8 \uD558\uB098\uB9CC \uB300\uC0C1\uC73C\uB85C \uD558\uBA70, \uC5D4\uC9C4\uC740 \uC140\uC758 \uB9C8\uC9C0\uB9C9 \uBB38\uB2E8 \uC0AD\uC81C\uB3C4 \uAC70\uBD80\uD569\uB2C8\uB2E4. \uC704 \uBAA9\uB85D\uC5D0\uC11C \uBB38\uB2E8\uC744 \uC120\uD0DD\uD558\uC138\uC694.",
|
|
4347
4387
|
"segment.tableSelectionRefused": "\uC774 \uC120\uD0DD\uC740 \uBB38\uB2E8\uC774 \uC544\uB2C8\uB77C \uD45C\uC785\uB2C8\uB2E4. \uD45C\uB97C \uB2F4\uACE0 \uC788\uB294 \uBB38\uB2E8\uC740 \uC790\uAE30 \uD14D\uC2A4\uD2B8\uB3C4 \uD568\uAED8 \uB2F4\uACE0 \uC788\uC5B4, \uADF8 \uBB38\uB2E8\uC744 \uD3B8\uC9D1\uD558\uAC70\uB098 \uC0AD\uC81C\uD558\uBA74 \uD45C\uAC00 \uC0AC\uB77C\uC9D1\uB2C8\uB2E4. \uC704 \uBAA9\uB85D\uC5D0\uC11C \uBB38\uB2E8\uC744 \uC120\uD0DD\uD558\uC138\uC694.",
|
|
@@ -4350,6 +4390,8 @@ var ko = {
|
|
|
4350
4390
|
"segment.clickRefusedTable": "\uD074\uB9AD\uC73C\uB85C \uCD94\uAC00\uB41C \uBB38\uB2E8\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uD45C\uB294 \uC790\uCCB4 \uBB38\uB2E8\uC774 \uC5C6\uC5B4 \uCD94\uAC00\uD560 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uBB38\uB2E8\uC774\uB098 \uC140\uC744 \uD074\uB9AD\uD558\uC138\uC694.",
|
|
4351
4391
|
"segment.clickRefusedContainer": "\uD074\uB9AD\uC73C\uB85C \uCD94\uAC00\uB41C \uBB38\uB2E8\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uADF8\uB9BC, \uD544\uB4DC \uB610\uB294 \uCC45\uAC08\uD53C\uB294 \uC790\uCCB4 \uD14D\uC2A4\uD2B8\uAC00 \uC5C6\uC5B4 \uCD94\uAC00\uD560 \uBB38\uB2E8\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uBB38\uB2E8\uC774\uB098 \uC140\uC744 \uD074\uB9AD\uD558\uC138\uC694.",
|
|
4352
4392
|
"segment.clickRefusedUnaddressable": "\uADF8 \uC694\uC18C\uB294 \uC5D4\uC9C4\uC774 \uC8FC\uC18C\uB85C \uC9C0\uC815\uD560 \uC218 \uC788\uB294 \uBB38\uB2E8\uC744 \uAC00\uB9AC\uD0A4\uC9C0 \uC54A\uC73C\uBBC0\uB85C \uD074\uB9AD\uC73C\uB85C \uC120\uD0DD\uB41C \uAC83\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uBB38\uB2E8\uC774\uB098 \uC140\uC744 \uD074\uB9AD\uD558\uC138\uC694.",
|
|
4393
|
+
"segment.clickRefusedUnaddressableRuns": "\uD074\uB9AD\uD55C \uBB38\uB2E8\uC774\uB098 \uC140\uC5D0 run\uC740 \uC788\uC9C0\uB9CC \uC5D4\uC9C4\uC774 \uADF8 run\uC758 \uC8FC\uC18C\uB97C \uC81C\uACF5\uD558\uC9C0 \uC54A\uC544 \uC120\uD0DD\uB41C \uAC83\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. Ctrl\uC774\uB098 Shift \uC5C6\uC774 \uD074\uB9AD\uD574 \uBB38\uB2E8 \uC804\uCCB4\uB97C \uC120\uD0DD\uD558\uAC70\uB098, \uC8FC\uC18C\uAC00 \uC788\uB294 run\uC744 \uAC00\uC9C4 \uBB38\uB2E8\uC774\uB098 \uC140\uC744 \uD074\uB9AD\uD558\uC138\uC694.",
|
|
4394
|
+
"segment.clickRefusedNoRuns": "\uD074\uB9AD\uD55C \uBB38\uB2E8\uC774\uB098 \uC140\uC5D0 \uCD94\uAC00\uD560 run\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uD14D\uC2A4\uD2B8\uAC00 \uC788\uB294 \uBB38\uB2E8\uC774\uB098 \uC140\uC744 \uD074\uB9AD\uD558\uC138\uC694.",
|
|
4353
4395
|
"segment.selectSimilar": "\uC9C1\uC811 \uC11C\uC2DD\uC774 \uAC19\uC740 \uB0B4\uC6A9 \uC120\uD0DD",
|
|
4354
4396
|
"segment.similarChar": "\uAC19\uC740 \uAE00\uC790 \uC11C\uC2DD",
|
|
4355
4397
|
"segment.similarPara": "\uAC19\uC740 \uBB38\uB2E8 \uC11C\uC2DD",
|
|
@@ -4467,6 +4509,7 @@ var ko = {
|
|
|
4467
4509
|
"error.staleCompose": "\uC0C8 \uBB38\uC11C\uB97C \uC791\uC131\uD558\uB294 \uB3D9\uC548 \uC5F4\uB9B0 \uBB38\uC11C\uAC00 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC791\uC131\uD558\uC138\uC694.",
|
|
4468
4510
|
"error.stalePreview": "\uBBF8\uB9AC\uBCF4\uAE30\uB97C \uB9CC\uB4DC\uB294 \uB3D9\uC548 \uBB38\uC11C\uAC00 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uC5F4\uB9B0 \uBB38\uC11C\uC5D0\uC11C \uB2E4\uC2DC \uBBF8\uB9AC\uBCF4\uAE30\uD558\uC138\uC694.",
|
|
4469
4511
|
"error.unmatchedReplace": "\uD574\uB2F9 \uBB38\uB2E8\uC5D0\uC11C \uBC14\uAFC0 \uD14D\uC2A4\uD2B8\uB97C \uC5D4\uC9C4\uC774 \uCC3E\uC9C0 \uBABB\uD574 \uC544\uBB34\uAC83\uB3C4 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uD14D\uC2A4\uD2B8\uB97C \uB2E4\uC2DC \uC120\uD0DD\uD55C \uB4A4 \uC7AC\uC2DC\uB3C4\uD558\uC138\uC694.",
|
|
4512
|
+
"error.unresolvableAddress": "\uC5D4\uC9C4\uC774 \uD3B8\uC9D1 \uB300\uC0C1 \uBB38\uB2E8\uC774\uB098 run\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC77C\uBD80 \uC911\uCCA9 \uBB38\uB2E8 \uC548\uC758 run\uC740 \uC5D4\uC9C4\uC774 \uC8FC\uC18C\uB85C \uC9C0\uC815\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uCD5C\uC0C1\uC704 \uBB38\uB2E8\uC774\uB098 \uD45C \uC140\uC758 \uD14D\uC2A4\uD2B8\uC5D0 \uC11C\uC2DD\uC744 \uC9C0\uC815\uD558\uAC70\uB098, \uC774 \uB300\uC0C1\uC740 \uC6CC\uB4DC\uD504\uB85C\uC138\uC11C\uC5D0\uC11C \uD3B8\uC9D1\uD558\uC138\uC694.",
|
|
4470
4513
|
"error.runRangeConflict": "\uAC19\uC740 \uBB38\uB2E8\uC5D0 \uB300\uAE30 \uC911\uC778 \uC55E\uC120 \uBCC0\uACBD(\uD14D\uC2A4\uD2B8, \uB9C1\uD06C, \uD544\uB4DC, \uCC45\uAC08\uD53C, \uC774\uBBF8\uC9C0, \uC140)\uC774 \uBB38\uB2E8 \uD14D\uC2A4\uD2B8\uB97C \uBC14\uAFC0 \uC218 \uC788\uC5B4 run\uC774 \uB354 \uC774\uC0C1 \uAC19\uC740 \uAE00\uC790\uB97C \uAC00\uB9AC\uD0A4\uC9C0 \uC54A\uC744 \uC218 \uC788\uC73C\uBBC0\uB85C run \uC11C\uC2DD \uBCC0\uACBD\uC774 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uB300\uAE30 \uBAA9\uB85D\uC5D0\uC11C \uC11C\uC2DD \uBCC0\uACBD\uC744 \uC81C\uAC70\uD558\uACE0 \uB098\uBA38\uC9C0\uB97C \uC801\uC6A9\uD55C \uB4A4 run \uC11C\uC2DD\uC744 \uB2E4\uC2DC \uC9C0\uC815\uD558\uAC70\uB098, \uC11C\uC2DD \uBCC0\uACBD\uC744 \uB2E4\uB978 \uBCC0\uACBD\uBCF4\uB2E4 \uBA3C\uC800 \uB300\uAE30\uC5F4\uC5D0 \uB123\uC73C\uC138\uC694.",
|
|
4471
4514
|
"error.rangeTagRefused": "\uC774 HWP \uBB38\uC11C\uC5D0\uB294 \uC5D4\uC9C4\uC774 \uC62E\uAE38 \uC218 \uC5C6\uB294 \uAD6C\uAC04 \uD45C\uC2DC\uAC00 \uC788\uC5B4 \uB300\uAE30 \uC911\uC778 \uD3B8\uC9D1\uC774 \uAC70\uBD80\uB418\uC5C8\uACE0, \uC544\uBB34\uAC83\uB3C4 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uAD6C\uAC04 \uD45C\uC2DC \uC8FC\uBCC0\uC758 \uAE00\uC790\uB97C \uC6C0\uC9C1\uC774\uB294 \uD3B8\uC9D1\uC740 \uAC70\uBD80\uB429\uB2C8\uB2E4: \uBB38\uB2E8 \uD14D\uC2A4\uD2B8 \uAE38\uC774 \uBCC0\uACBD, \uAE38\uC774\uAC00 \uB2E4\uB978 \uD544\uB4DC \uAC12\uC73C\uB85C\uC758 \uBCC0\uACBD, \uB9C1\uD06C\xB7\uD544\uB4DC\xB7\uCC45\uAC08\uD53C\xB7\uC774\uBBF8\uC9C0\uC758 \uC0BD\uC785\uC774\uB098 \uC0AD\uC81C, \uD45C \uC0AD\uC81C. \uAD6C\uAC04 \uD45C\uC2DC\uAC00 \uC788\uB294 \uD45C \uC140\uC740 \uB0B4\uC6A9\uC744 \uC5B4\uB5BB\uAC8C \uBC14\uAFB8\uB4E0 \uAC70\uBD80\uD569\uB2C8\uB2E4. \uC5D4\uC9C4\uC740 \uC5B4\uB290 \uD3B8\uC9D1\uC778\uC9C0 \uC54C\uB824 \uC8FC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB300\uAE30 \uBAA9\uB85D\uC5D0\uC11C \uD574\uB2F9 \uD3B8\uC9D1\uC744 \uC81C\uAC70\uD558\uACE0(\uBB38\uB2E8 \uC548\uC758 \uAC19\uC740 \uAE38\uC774 \uD14D\uC2A4\uD2B8 \uCE58\uD658\uACFC \uAC19\uC740 \uAE38\uC774\uC758 \uD544\uB4DC \uAC12\uC740 \uD5C8\uC6A9\uB429\uB2C8\uB2E4) \uB098\uBA38\uC9C0\uB97C \uC801\uC6A9\uD558\uC138\uC694. \uADF8\uB7F0 \uD3B8\uC9D1\uC774 \uD544\uC694\uD558\uBA74 \uBB38\uC11C\uB97C HWPX\uB85C \uBCC0\uD658\uD558\uAC70\uB098(\uBCC0\uD658\uD558\uBA74 \uAD6C\uAC04 \uD45C\uC2DC\uAC00 \uC0AC\uB77C\uC9D1\uB2C8\uB2E4) \uD55C\uAE00\uC5D0\uC11C \uAD6C\uAC04 \uD45C\uC2DC\uB97C \uC81C\uAC70\uD55C \uB4A4 \uB2E4\uC2DC \uC5EC\uC138\uC694. \uB2E4\uC2DC \uC5F4\uBA74 \uB300\uAE30 \uBAA9\uB85D\uC740 \uC0AC\uB77C\uC9D1\uB2C8\uB2E4.",
|
|
4472
4515
|
"error.noEngineCause": "\uC5D4\uC9C4\uC774 \uC6D0\uC778\uC744 \uBC1D\uD788\uC9C0 \uC54A\uACE0 \uC2E4\uD328\uD588\uC73C\uBBC0\uB85C(\uB300\uAC1C \uBE44\uC815\uC0C1 \uC885\uB8CC\uB41C \uACBD\uC6B0\uC785\uB2C8\uB2E4) \uC544\uBB34\uAC83\uB3C4 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC801\uC6A9\uD558\uACE0, \uAC19\uC740 \uBC29\uC2DD\uC73C\uB85C \uC2E4\uD328\uD558\uBA74 \uD638\uC2A4\uD2B8 \uB85C\uADF8\uC640 \uD568\uAED8 \uC54C\uB824 \uC8FC\uC138\uC694.",
|
|
@@ -4546,14 +4589,14 @@ var ko = {
|
|
|
4546
4589
|
"image.insert": "\uC774\uBBF8\uC9C0 \uC0BD\uC785",
|
|
4547
4590
|
"image.delete": "\uC774\uBBF8\uC9C0 \uC0AD\uC81C",
|
|
4548
4591
|
"image.file": "PNG/JPEG \uC774\uBBF8\uC9C0 \uD30C\uC77C",
|
|
4549
|
-
"image.fileHint": `${
|
|
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.`,
|
|
4550
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.",
|
|
4551
4594
|
"image.anchor": "\uC774 \uBB38\uB2E8 \uBB38\uC790\uC5F4 \uB4A4\uC5D0 \uC0BD\uC785",
|
|
4552
4595
|
"image.deleteAnchor": "\uC0AD\uC81C\uD560 \uC774\uBBF8\uC9C0\uC758 \uC704\uCE58 \uBB38\uC790\uC5F4",
|
|
4553
4596
|
"image.width": "\uB108\uBE44 (mm)",
|
|
4554
4597
|
"image.height": "\uB192\uC774 (mm)",
|
|
4555
4598
|
"image.reading": "\uC774\uBBF8\uC9C0 \uC77D\uB294 \uC911...",
|
|
4556
|
-
"image.invalidSize": `\uC774\uBBF8\uC9C0\uAC00 \uBE44\uC5B4 \uC788\uAC70\uB098 ${
|
|
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.`,
|
|
4557
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.",
|
|
4558
4601
|
"image.readError": "\uC774\uBBF8\uC9C0\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD30C\uC77C\uC744 \uB2E4\uC2DC \uC120\uD0DD\uD558\uC138\uC694.",
|
|
4559
4602
|
"error.prefix.image": "\uC774\uBBF8\uC9C0 \uC791\uC5C5 \uC2E4\uD328",
|
|
@@ -4616,16 +4659,16 @@ function selectionParagraphs(envelope, state) {
|
|
|
4616
4659
|
const seen = /* @__PURE__ */ new Set();
|
|
4617
4660
|
const paragraphs = [];
|
|
4618
4661
|
for (const ref of refs) {
|
|
4619
|
-
const segment = (0,
|
|
4662
|
+
const segment = (0, import_core20.segmentAtRef)(envelope, ref);
|
|
4620
4663
|
if (segment === void 0) continue;
|
|
4621
|
-
for (const paragraph of (0,
|
|
4664
|
+
for (const paragraph of (0, import_core20.resolveSelection)(envelope, segment).paragraphs) {
|
|
4622
4665
|
const key = paragraph.id ?? `${paragraph.section}:${paragraph.para}:${paragraph.start}`;
|
|
4623
4666
|
if (seen.has(key)) continue;
|
|
4624
4667
|
seen.add(key);
|
|
4625
4668
|
paragraphs.push(paragraph);
|
|
4626
4669
|
}
|
|
4627
4670
|
}
|
|
4628
|
-
return paragraphs.sort(
|
|
4671
|
+
return paragraphs.sort(import_core20.compareSegments);
|
|
4629
4672
|
}
|
|
4630
4673
|
function insertAnchor(covered, position) {
|
|
4631
4674
|
const paragraph = position === "before" ? covered[0] : covered[covered.length - 1];
|
|
@@ -4644,7 +4687,8 @@ var RENDER_SVG = { format: "svg" };
|
|
|
4644
4687
|
var REFUSAL_MESSAGE = {
|
|
4645
4688
|
unmatched_replace: "error.unmatchedReplace",
|
|
4646
4689
|
run_range_conflict: "error.runRangeConflict",
|
|
4647
|
-
range_tag: "error.rangeTagRefused"
|
|
4690
|
+
range_tag: "error.rangeTagRefused",
|
|
4691
|
+
unresolvable_address: "error.unresolvableAddress"
|
|
4648
4692
|
};
|
|
4649
4693
|
var HwpEditor = (0, import_react13.forwardRef)(
|
|
4650
4694
|
function HwpEditor2(props, ref) {
|
|
@@ -4662,7 +4706,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
4662
4706
|
className,
|
|
4663
4707
|
style
|
|
4664
4708
|
} = props;
|
|
4665
|
-
const catalogue = components ??
|
|
4709
|
+
const catalogue = components ?? import_core20.STARTER_COMPONENTS;
|
|
4666
4710
|
const cbRef = (0, import_react13.useRef)({ onReady, onError, onChange, onDirtyChange });
|
|
4667
4711
|
(0, import_react13.useEffect)(() => {
|
|
4668
4712
|
cbRef.current = { onReady, onError, onChange, onDirtyChange };
|
|
@@ -4680,7 +4724,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
4680
4724
|
cbRef.current.onDirtyChange?.(dirty2);
|
|
4681
4725
|
}, []);
|
|
4682
4726
|
const t = (0, import_react13.useMemo)(() => createT(locale, messages), [locale, messages]);
|
|
4683
|
-
const [store] = (0, import_react13.useState)(() => (0,
|
|
4727
|
+
const [store] = (0, import_react13.useState)(() => (0, import_core20.createStore)());
|
|
4684
4728
|
const state = (0, import_react13.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
|
|
4685
4729
|
const [envelope, setEnvelope] = (0, import_react13.useState)(null);
|
|
4686
4730
|
const [capabilities, setCapabilities] = (0, import_react13.useState)(null);
|
|
@@ -4733,9 +4777,9 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
4733
4777
|
const readEnvelope = (0, import_react13.useCallback)(async (target) => {
|
|
4734
4778
|
const read = await engine.read(target);
|
|
4735
4779
|
try {
|
|
4736
|
-
return (0,
|
|
4780
|
+
return (0, import_core20.validateCatEnvelope)(read);
|
|
4737
4781
|
} catch (e) {
|
|
4738
|
-
throw new
|
|
4782
|
+
throw new import_core20.HwpEngineError(
|
|
4739
4783
|
"failed",
|
|
4740
4784
|
latestT.current("error.badEnvelope", { detail: envelopeProblem(e instanceof Error ? e.message : String(e)) }),
|
|
4741
4785
|
{ cause: e }
|
|
@@ -4754,7 +4798,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
4754
4798
|
insertedTriedFor.current = envelope;
|
|
4755
4799
|
const hidden = [];
|
|
4756
4800
|
const paragraphs = pendingInserted.flatMap((id) => {
|
|
4757
|
-
const segment = (0,
|
|
4801
|
+
const segment = (0, import_core20.segmentAtRef)(envelope, { id, section: 0, para: 0 });
|
|
4758
4802
|
if (segment === void 0) hidden.push(id);
|
|
4759
4803
|
return segment === void 0 || segment.kind !== "para" ? [] : [segment];
|
|
4760
4804
|
});
|
|
@@ -4762,9 +4806,9 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
4762
4806
|
if (paragraphs.length === 0) return;
|
|
4763
4807
|
store.dispatch({
|
|
4764
4808
|
type: "selectMany",
|
|
4765
|
-
selections: paragraphs.map(
|
|
4766
|
-
primary: (0,
|
|
4767
|
-
anchor: (0,
|
|
4809
|
+
selections: paragraphs.map(import_core20.segmentRef),
|
|
4810
|
+
primary: (0, import_core20.segmentRef)(paragraphs[0]),
|
|
4811
|
+
anchor: (0, import_core20.segmentRef)(paragraphs[0])
|
|
4768
4812
|
});
|
|
4769
4813
|
setInsertedHidden(hidden.length === 0 ? null : { envelope, selections: store.getState().selections, ids: hidden });
|
|
4770
4814
|
}, [envelope, pendingInserted, store]);
|
|
@@ -4845,22 +4889,22 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
4845
4889
|
const queueImage = (0, import_react13.useCallback)((op, asset) => {
|
|
4846
4890
|
const snapshot = store.getState();
|
|
4847
4891
|
if (!editable || envelope === null || snapshot.document === null || snapshot.status === "applying") return;
|
|
4848
|
-
if (capabilities?.imageAssets !== "v1") throw new
|
|
4849
|
-
if (op.path !== asset.name) throw new
|
|
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"));
|
|
4850
4894
|
const active = snapshot.pendingOps.flatMap((pending) => {
|
|
4851
4895
|
const stored = imageAssets.current.get(pending);
|
|
4852
4896
|
return stored === void 0 ? [] : [stored];
|
|
4853
4897
|
});
|
|
4854
|
-
if (active.length + 1 >
|
|
4855
|
-
throw new
|
|
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) }));
|
|
4856
4900
|
}
|
|
4857
|
-
(0,
|
|
4901
|
+
(0, import_core20.validateImageAssets)([...active, asset]);
|
|
4858
4902
|
imageAssets.current.set(op, { name: asset.name, data: asset.data.slice() });
|
|
4859
4903
|
store.dispatch({ type: "queueOp", op });
|
|
4860
4904
|
}, [editable, envelope, capabilities, store, t]);
|
|
4861
4905
|
(0, import_react13.useEffect)(() => {
|
|
4862
4906
|
if (envelope === null || state.selection === null) return;
|
|
4863
|
-
const segment = (0,
|
|
4907
|
+
const segment = (0, import_core20.segmentAtRef)(envelope, state.selection);
|
|
4864
4908
|
if (segment === void 0) return;
|
|
4865
4909
|
const next = hostsTable(envelope, segment) ? "table" : "para";
|
|
4866
4910
|
setTab((current) => current === "components" || current === "styles" ? current : next);
|
|
@@ -5007,17 +5051,17 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
5007
5051
|
noteRefusal(t("error.loadingReplacement"));
|
|
5008
5052
|
return;
|
|
5009
5053
|
}
|
|
5010
|
-
const segment = snapshot.selection === null ? void 0 : (0,
|
|
5054
|
+
const segment = snapshot.selection === null ? void 0 : (0, import_core20.segmentAtRef)(envelope, snapshot.selection);
|
|
5011
5055
|
const covered = selectionParagraphs(envelope, snapshot);
|
|
5012
5056
|
const address = segment === void 0 ? null : insertAnchor(covered, position);
|
|
5013
5057
|
if (address === null) return;
|
|
5014
|
-
if (position === "before" && covered[0] !== void 0 && (0,
|
|
5058
|
+
if (position === "before" && covered[0] !== void 0 && (0, import_core20.isSectionDefinitionParagraph)(covered[0])) return;
|
|
5015
5059
|
let blocks;
|
|
5016
5060
|
let styles2;
|
|
5017
5061
|
try {
|
|
5018
|
-
const filled = (0,
|
|
5062
|
+
const filled = (0, import_core20.substituteParams)(component, values, component.name);
|
|
5019
5063
|
blocks = filled.blocks;
|
|
5020
|
-
styles2 = (0,
|
|
5064
|
+
styles2 = (0, import_core20.componentStyleMap)([filled]);
|
|
5021
5065
|
} catch (error) {
|
|
5022
5066
|
const shown = toError(componentFailure(error, t));
|
|
5023
5067
|
noteNotice(shown.message, shown);
|
|
@@ -5070,7 +5114,7 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
5070
5114
|
}
|
|
5071
5115
|
let ids;
|
|
5072
5116
|
try {
|
|
5073
|
-
ids = (0,
|
|
5117
|
+
ids = (0, import_core20.insertedParagraphIds)(outcome);
|
|
5074
5118
|
} catch (error) {
|
|
5075
5119
|
noteNotice(toError(error).message, error);
|
|
5076
5120
|
return;
|
|
@@ -5081,12 +5125,12 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
5081
5125
|
[emitError, engine, envelope, noteRefusal, replaceDocument, store, t]
|
|
5082
5126
|
);
|
|
5083
5127
|
const selectedTargets = envelope === null || state.selection === null ? void 0 : (() => {
|
|
5084
|
-
const segment = (0,
|
|
5085
|
-
return segment === void 0 ? void 0 : (0,
|
|
5128
|
+
const segment = (0, import_core20.segmentAtRef)(envelope, state.selection);
|
|
5129
|
+
return segment === void 0 ? void 0 : (0, import_core20.resolveSelection)(envelope, segment);
|
|
5086
5130
|
})();
|
|
5087
5131
|
const componentAnchor = envelope === null || state.selection === null ? [] : selectionParagraphs(envelope, state);
|
|
5088
5132
|
const selectedAddress = insertAnchor(componentAnchor, "after");
|
|
5089
|
-
const beforeDisabledReason = componentAnchor[0] !== void 0 && (0,
|
|
5133
|
+
const beforeDisabledReason = componentAnchor[0] !== void 0 && (0, import_core20.isSectionDefinitionParagraph)(componentAnchor[0]) ? t("components.positionBeforeLocked") : "";
|
|
5090
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"));
|
|
5091
5135
|
const componentRefusal = (0, import_react13.useCallback)(
|
|
5092
5136
|
(component) => insertionPreflight(component.blocks, state.document?.name ?? "", t),
|
|
@@ -5513,6 +5557,31 @@ var HwpEditor = (0, import_react13.forwardRef)(
|
|
|
5513
5557
|
) });
|
|
5514
5558
|
}
|
|
5515
5559
|
);
|
|
5560
|
+
|
|
5561
|
+
// src/sanitize.ts
|
|
5562
|
+
function sanitizeSvg(svgText) {
|
|
5563
|
+
const doc = new DOMParser().parseFromString(svgText, "image/svg+xml");
|
|
5564
|
+
const root = doc.documentElement;
|
|
5565
|
+
if (root === null || root.nodeName === "parsererror" || doc.getElementsByTagName("parsererror").length > 0) {
|
|
5566
|
+
return "";
|
|
5567
|
+
}
|
|
5568
|
+
const dangerous = root.querySelectorAll("script, foreignObject");
|
|
5569
|
+
for (const node of Array.from(dangerous)) node.remove();
|
|
5570
|
+
scrubElement(root);
|
|
5571
|
+
return root.outerHTML;
|
|
5572
|
+
}
|
|
5573
|
+
function scrubElement(el) {
|
|
5574
|
+
for (const attr of Array.from(el.attributes)) {
|
|
5575
|
+
const name = attr.name.toLowerCase();
|
|
5576
|
+
const value = attr.value.trim().toLowerCase();
|
|
5577
|
+
if (name.startsWith("on")) {
|
|
5578
|
+
el.removeAttribute(attr.name);
|
|
5579
|
+
} else if ((name === "href" || name === "xlink:href") && value.startsWith("javascript:")) {
|
|
5580
|
+
el.removeAttribute(attr.name);
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
for (const child of Array.from(el.children)) scrubElement(child);
|
|
5584
|
+
}
|
|
5516
5585
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5517
5586
|
0 && (module.exports = {
|
|
5518
5587
|
COMPOSE_PRESETS,
|