@hyebook/vue3-adapter 2.3.2 → 2.3.3

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.
@@ -49,6 +49,14 @@ export declare class EBookPlayer implements EBookPlayerHandle {
49
49
  private renderTextBlock;
50
50
  private renderNonTextBlock;
51
51
  private getTextBlockContent;
52
+ private textBlockToHTML;
53
+ private paragraphTypeToTag;
54
+ private runToHTML;
55
+ private inlineElementToHTML;
56
+ private inlineImageAlignStyleParts;
57
+ private renderImageBlock;
58
+ private renderVideoBlock;
59
+ private renderTableBlock;
52
60
  private createAnnotationBuckets;
53
61
  private toBlockKey;
54
62
  private applyHighlightMarks;
@@ -60,6 +68,10 @@ export declare class EBookPlayer implements EBookPlayerHandle {
60
68
  private handleSelectionChange;
61
69
  private resolveTextContainer;
62
70
  private getSelectionOffsets;
71
+ private collectSelectionSegments;
72
+ private getContainerTextLength;
73
+ private getBoundaryOffsetInContainer;
74
+ private getRangeTextByOffsets;
63
75
  private hideSelectionToolbar;
64
76
  private clearSelection;
65
77
  private handleDocumentPointerDown;
@@ -1 +1 @@
1
- {"version":3,"file":"ebook-player.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/ebook-player.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ebook-player.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/ebook-player.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { PlayerEngine } from "./engine";
2
2
  const EBOOK_PLAYER_STYLE_ID = "hy-ebook-lite-player-style";
3
- const EBOOK_PLAYER_STYLE_VERSION = "0.1.0";
3
+ const EBOOK_PLAYER_STYLE_VERSION = "0.2.0";
4
4
  const HIGHLIGHT_ICON_SVG = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 22V12.5H6V8.5H18V12.5H21V22H3Z" stroke="#333333" stroke-width="2" stroke-linejoin="round"/><path d="M8.5 8.5V4L15.5 2V8.5" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
5
5
  const NOTE_ICON_SVG = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.4998 4.49951L19.4998 8.4995" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M3.99977 15.9995L17.9997 2L21.9998 5.9995L7.99975 19.9995L2.99976 20.9995L3.99977 15.9995Z" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M4.49976 15.9995L7.99975 19.4995" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.49976 17.4995L17.4998 6.4995" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
6
6
  const BOOKMARK_ICON_SVG = `<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3C0 1.34315 1.34315 0 3 0H27C28.6569 0 30 1.34315 30 3V38.1989C30 38.9837 29.1374 39.4627 28.4713 39.0477L15 30.6562L1.52873 39.0477C0.862627 39.4627 0 38.9837 0 38.1989L0 3Z" fill="#4FCEBB"/></svg>`;
@@ -9,15 +9,33 @@ const EBOOK_PLAYER_CSS = `
9
9
  .hyepl-content{position:relative}
10
10
  .hyepl-page{margin:0 0 16px}
11
11
  .hyepl-page:last-child{margin-bottom:0}
12
- .hyepl-block{margin:0 0 10px;white-space:pre-wrap;word-break:break-word}
12
+ .hyepl-block{margin:0 0 10px;word-break:break-word}
13
13
  .hyepl-block:last-child{margin-bottom:0}
14
- .hyepl-block-text{position:relative;padding-right:18px}
14
+ .hyepl-block-text{position:relative;padding-right:18px;white-space:normal}
15
+ .hyepl-block-text p,.hyepl-block-text h1,.hyepl-block-text h2,.hyepl-block-text h3,.hyepl-block-text h4,.hyepl-block-text blockquote{margin:0 0 .75em;line-height:1.7}
16
+ .hyepl-block-text p:last-child,.hyepl-block-text h1:last-child,.hyepl-block-text h2:last-child,.hyepl-block-text h3:last-child,.hyepl-block-text h4:last-child,.hyepl-block-text blockquote:last-child{margin-bottom:0}
17
+ .hyepl-block-text h1{font-size:24px;line-height:1.3}
18
+ .hyepl-block-text h2{font-size:20px;line-height:1.35}
19
+ .hyepl-block-text h3{font-size:16px;line-height:1.45}
20
+ .hyepl-block-text h4{font-size:14px;line-height:1.5}
21
+ .hyepl-block-text blockquote{padding-left:12px;border-left:3px solid #cbd5e1;color:#475569}
22
+ .hyepl-block-text sup,.hyepl-block-text sub{font-size:.6em;line-height:0;position:relative;vertical-align:baseline}
23
+ .hyepl-block-text sup{top:-.5em}
24
+ .hyepl-block-text sub{top:.5em}
25
+ .hyepl-inline-media{display:inline-block;vertical-align:middle;max-width:100%}
26
+ .hyepl-inline-image{height:auto;border-radius:6px}
27
+ .hyepl-inline-video{border-radius:8px;background:#000}
28
+ .hyepl-block-image img,.hyepl-block-video video{display:block;max-width:100%;width:100%;height:auto;border-radius:8px}
29
+ .hyepl-block-image figcaption,.hyepl-block-video figcaption{margin-top:6px;font-size:12px;color:#64748b}
30
+ .hyepl-block-table{overflow:auto}
31
+ .hyepl-block-table table{width:100%;border-collapse:collapse;table-layout:fixed}
32
+ .hyepl-block-table th,.hyepl-block-table td{border:1px solid #cbd5e1;padding:6px 8px;vertical-align:top;min-width:68px}
15
33
  .hyepl-block-muted{color:#64748b}
16
34
  .hyepl-highlight{background:var(--hyepl-highlight-color,#fff59d);color:inherit;padding:0 .08em;border-radius:.2em}
17
35
  .hyepl-note{background:rgba(14,116,144,.14);border-bottom:2px solid #0e7490;color:inherit;padding:0 .04em;border-radius:.2em}
18
36
  .hyepl-bookmark-flag{position:absolute;top:4px;right:0;display:inline-flex;align-items:center;justify-content:center;width:12px;height:16px;pointer-events:none;user-select:none}
19
37
  .hyepl-bookmark-flag svg{display:block;width:12px;height:16px}
20
- .hyepl-selection-toolbar{position:fixed;z-index:10060;display:none;align-items:stretch;gap:0;padding:8px 10px;border-radius:14px;border:1px solid #e5e7eb;background:#ffffff;box-shadow:0 10px 24px rgba(15,23,42,.14);transform:translate(-50%,-100%);overflow:visible}
38
+ .hyepl-selection-toolbar{position:fixed;z-index:10070;display:none;align-items:stretch;gap:0;padding:8px 10px;border-radius:14px;border:1px solid #e5e7eb;background:#ffffff;box-shadow:0 10px 24px rgba(15,23,42,.14);transform:translate(-50%,-100%);overflow:visible}
21
39
  .hyepl-selection-toolbar.show{display:flex}
22
40
  .hyepl-selection-toolbar:after{content:"";position:absolute;bottom:-10px;left:50%;transform:translateX(-50%);border-width:10px 10px 0 10px;border-style:solid;border-color:#ffffff transparent transparent transparent;filter:drop-shadow(0 1px 0 #e5e7eb);pointer-events:none}
23
41
 
@@ -248,7 +266,7 @@ export class EBookPlayer {
248
266
  blockTextNode.className = "hyepl-block hyepl-block-text";
249
267
  blockTextNode.dataset.pageId = pageId;
250
268
  blockTextNode.dataset.blockId = block.id;
251
- blockTextNode.textContent = this.getTextBlockContent(block);
269
+ blockTextNode.innerHTML = this.textBlockToHTML(block);
252
270
  const blockKey = this.toBlockKey(pageId, block.id);
253
271
  const highlights = buckets.highlightsByBlock.get(blockKey) || [];
254
272
  const notes = buckets.notesByBlock.get(blockKey) || [];
@@ -261,20 +279,17 @@ export class EBookPlayer {
261
279
  return blockTextNode;
262
280
  }
263
281
  renderNonTextBlock(block) {
264
- const node = document.createElement("div");
265
- node.className = "hyepl-block hyepl-block-muted";
266
282
  if (block.type === "image") {
267
- node.textContent = "[图片内容]";
268
- return node;
283
+ return this.renderImageBlock(block);
269
284
  }
270
285
  if (block.type === "video") {
271
- node.textContent = "[视频内容]";
272
- return node;
286
+ return this.renderVideoBlock(block);
273
287
  }
274
288
  if (block.type === "table") {
275
- node.textContent = "[表格内容]";
276
- return node;
289
+ return this.renderTableBlock(block);
277
290
  }
291
+ const node = document.createElement("div");
292
+ node.className = "hyepl-block hyepl-block-muted";
278
293
  node.textContent = "[内容块]";
279
294
  return node;
280
295
  }
@@ -285,6 +300,222 @@ export class EBookPlayer {
285
300
  })
286
301
  .join("\n");
287
302
  }
303
+ textBlockToHTML(block) {
304
+ const paragraphs = block.content?.paragraphs ?? [];
305
+ if (!paragraphs.length) {
306
+ return "<p><br></p>";
307
+ }
308
+ return paragraphs
309
+ .map((paragraph) => {
310
+ const tag = this.paragraphTypeToTag(paragraph.type);
311
+ const inlineById = Object.fromEntries((paragraph.inlineElements ?? []).map((item) => [item.id, item]));
312
+ const styleTokens = [
313
+ `text-align:${paragraph.align || "left"}`,
314
+ paragraph.lineHeight ? `line-height:${paragraph.lineHeight}` : "",
315
+ paragraph.spacingBefore !== undefined
316
+ ? `margin-top:${paragraph.spacingBefore}px`
317
+ : "",
318
+ paragraph.spacingAfter !== undefined
319
+ ? `margin-bottom:${paragraph.spacingAfter}px`
320
+ : "",
321
+ paragraph.indent !== undefined
322
+ ? `text-indent:${paragraph.indent}em`
323
+ : "",
324
+ ].filter(Boolean);
325
+ const body = paragraph.runs
326
+ ?.map((run) => this.runToHTML(run, inlineById))
327
+ .join("") || "<br>";
328
+ const styleAttr = styleTokens.length
329
+ ? ` style="${escapeAttribute(styleTokens.join(";"))}"`
330
+ : "";
331
+ return `<${tag}${styleAttr}>${body}</${tag}>`;
332
+ })
333
+ .join("");
334
+ }
335
+ paragraphTypeToTag(type) {
336
+ if (type === "h1" || type === "h2" || type === "h3" || type === "h4") {
337
+ return type;
338
+ }
339
+ if (type === "quote") {
340
+ return "blockquote";
341
+ }
342
+ return "p";
343
+ }
344
+ runToHTML(run, inlineById) {
345
+ const inlineElement = run.inlineRef
346
+ ? inlineById?.[run.inlineRef]
347
+ : undefined;
348
+ if (run.inlineRef && inlineElement) {
349
+ return this.inlineElementToHTML(inlineElement);
350
+ }
351
+ let text = escapeHtml(run.text || "").replace(/\n/g, "<br>");
352
+ const marks = run.marks || {};
353
+ const styleTokens = [];
354
+ if (marks.fontSize) {
355
+ styleTokens.push(`font-size:${marks.fontSize}px`);
356
+ }
357
+ if (marks.fontFamily) {
358
+ styleTokens.push(`font-family:${marks.fontFamily}`);
359
+ }
360
+ if (marks.color) {
361
+ styleTokens.push(`color:${marks.color}`);
362
+ }
363
+ if (marks.backgroundColor) {
364
+ styleTokens.push(`background-color:${marks.backgroundColor}`);
365
+ }
366
+ if (styleTokens.length) {
367
+ text = `<span style="${escapeAttribute(styleTokens.join(";"))}">${text}</span>`;
368
+ }
369
+ if (marks.bold) {
370
+ text = `<strong>${text}</strong>`;
371
+ }
372
+ if (marks.italic) {
373
+ text = `<em>${text}</em>`;
374
+ }
375
+ if (marks.underline) {
376
+ text = `<u>${text}</u>`;
377
+ }
378
+ if (marks.strike) {
379
+ text = `<s>${text}</s>`;
380
+ }
381
+ if (marks.sup) {
382
+ text = `<sup>${text}</sup>`;
383
+ }
384
+ if (marks.sub) {
385
+ text = `<sub>${text}</sub>`;
386
+ }
387
+ return text || "<br>";
388
+ }
389
+ inlineElementToHTML(element) {
390
+ if (element.type === "image") {
391
+ const sizeStyle = [
392
+ element.width !== undefined ? `width:${element.width}px` : "",
393
+ element.height !== undefined ? `height:${element.height}px` : "",
394
+ ...(element.align
395
+ ? this.inlineImageAlignStyleParts(element.align)
396
+ : []),
397
+ ]
398
+ .filter(Boolean)
399
+ .join(";");
400
+ return `<img class="hyepl-inline-media hyepl-inline-image" src="${escapeAttribute(element.src)}" alt="${escapeAttribute(element.alt || "")}" style="${escapeAttribute(sizeStyle)}" />`;
401
+ }
402
+ if (element.type === "video") {
403
+ const sizeStyle = [
404
+ element.width !== undefined ? `width:${element.width}px` : "",
405
+ element.height !== undefined ? `height:${element.height}px` : "",
406
+ ]
407
+ .filter(Boolean)
408
+ .join(";");
409
+ const posterAttr = element.poster
410
+ ? ` poster="${escapeAttribute(element.poster)}"`
411
+ : "";
412
+ return `<video class="hyepl-inline-media hyepl-inline-video" src="${escapeAttribute(element.src)}" controls${posterAttr} style="${escapeAttribute(sizeStyle)}"></video>`;
413
+ }
414
+ return "";
415
+ }
416
+ inlineImageAlignStyleParts(align) {
417
+ if (align === "center") {
418
+ return ["display:block", "margin-left:auto", "margin-right:auto"];
419
+ }
420
+ if (align === "right") {
421
+ return ["display:block", "margin-left:auto", "margin-right:0"];
422
+ }
423
+ if (align === "left") {
424
+ return ["display:block", "margin-left:0", "margin-right:auto"];
425
+ }
426
+ return [];
427
+ }
428
+ renderImageBlock(block) {
429
+ const figure = document.createElement("figure");
430
+ figure.className = "hyepl-block hyepl-block-image";
431
+ const image = document.createElement("img");
432
+ image.src = block.src;
433
+ image.alt = block.alt || "";
434
+ image.style.objectFit = block.fit || "contain";
435
+ figure.append(image);
436
+ if (block.caption) {
437
+ const caption = document.createElement("figcaption");
438
+ caption.textContent = block.caption;
439
+ figure.append(caption);
440
+ }
441
+ return figure;
442
+ }
443
+ renderVideoBlock(block) {
444
+ const figure = document.createElement("figure");
445
+ figure.className = "hyepl-block hyepl-block-video";
446
+ const video = document.createElement("video");
447
+ video.src = block.src;
448
+ video.controls = block.controls !== false;
449
+ video.autoplay = Boolean(block.autoplay);
450
+ video.muted = Boolean(block.muted);
451
+ video.loop = Boolean(block.loop);
452
+ if (block.poster) {
453
+ video.poster = block.poster;
454
+ }
455
+ figure.append(video);
456
+ return figure;
457
+ }
458
+ renderTableBlock(block) {
459
+ const wrapper = document.createElement("div");
460
+ wrapper.className = "hyepl-block hyepl-block-table";
461
+ const table = document.createElement("table");
462
+ if (block.style) {
463
+ table.setAttribute("style", block.style);
464
+ }
465
+ const tbody = document.createElement("tbody");
466
+ block.rows.forEach((row) => {
467
+ const tr = document.createElement("tr");
468
+ (row.cells || []).forEach((cell) => {
469
+ const node = document.createElement(cell.isHeader ? "th" : "td");
470
+ const rowSpan = Math.max(1, Math.round(cell.rowSpan || 1));
471
+ const colSpan = Math.max(1, Math.round(cell.colSpan || 1));
472
+ if (rowSpan > 1) {
473
+ node.rowSpan = rowSpan;
474
+ }
475
+ if (colSpan > 1) {
476
+ node.colSpan = colSpan;
477
+ }
478
+ if (cell.style) {
479
+ node.setAttribute("style", cell.style);
480
+ }
481
+ if (cell.textStyle?.color) {
482
+ node.style.color = cell.textStyle.color;
483
+ }
484
+ if (cell.textStyle?.fontFamily) {
485
+ node.style.fontFamily = cell.textStyle.fontFamily;
486
+ }
487
+ if (cell.textStyle?.fontSize !== undefined) {
488
+ node.style.fontSize = `${Math.round(cell.textStyle.fontSize)}px`;
489
+ }
490
+ if (cell.html) {
491
+ node.innerHTML = cell.html;
492
+ }
493
+ else {
494
+ node.textContent = cell.text || "";
495
+ }
496
+ if (!node.textContent && !node.children.length) {
497
+ node.innerHTML = "<br>";
498
+ }
499
+ tr.append(node);
500
+ });
501
+ if (!tr.children.length) {
502
+ const td = document.createElement("td");
503
+ td.innerHTML = "<br>";
504
+ tr.append(td);
505
+ }
506
+ tbody.append(tr);
507
+ });
508
+ if (!tbody.children.length) {
509
+ const tr = document.createElement("tr");
510
+ const td = document.createElement("td");
511
+ td.innerHTML = "<br>";
512
+ tr.append(td);
513
+ tbody.append(tr);
514
+ }
515
+ table.append(tbody);
516
+ wrapper.append(table);
517
+ return wrapper;
518
+ }
288
519
  createAnnotationBuckets(annotations) {
289
520
  const highlightsByBlock = new Map();
290
521
  const notesByBlock = new Map();
@@ -438,20 +669,13 @@ export class EBookPlayer {
438
669
  return;
439
670
  }
440
671
  const range = selection.getRangeAt(0);
441
- const startContainer = this.resolveTextContainer(range.startContainer);
442
- const endContainer = this.resolveTextContainer(range.endContainer);
443
- if (!startContainer || !endContainer || startContainer !== endContainer) {
672
+ const segments = this.collectSelectionSegments(selection, range);
673
+ if (!segments?.length) {
444
674
  this.hideSelectionToolbar();
445
675
  return;
446
676
  }
447
- const offsets = this.getSelectionOffsets(startContainer, selection);
448
- if (!offsets) {
449
- this.hideSelectionToolbar();
450
- return;
451
- }
452
- const pageId = startContainer.dataset.pageId;
453
- const blockId = startContainer.dataset.blockId;
454
- if (!pageId || !blockId) {
677
+ const firstSegment = segments[0];
678
+ if (!firstSegment) {
455
679
  this.hideSelectionToolbar();
456
680
  return;
457
681
  }
@@ -461,10 +685,11 @@ export class EBookPlayer {
461
685
  return;
462
686
  }
463
687
  this.selectionDraft = {
464
- pageId,
465
- blockId,
466
- range: offsets,
688
+ pageId: firstSegment.pageId,
689
+ blockId: firstSegment.blockId,
690
+ range: firstSegment.range,
467
691
  text: selection.toString().trim(),
692
+ segments,
468
693
  };
469
694
  this.selectionToolbar.style.left = `${Math.round(rect.left + rect.width / 2)}px`;
470
695
  this.selectionToolbar.style.top = `${Math.round(rect.top - 20)}px`;
@@ -501,6 +726,103 @@ export class EBookPlayer {
501
726
  const end = endRange.toString().length;
502
727
  return this.normalizeOffsetRange(start, end);
503
728
  }
729
+ collectSelectionSegments(selection, range) {
730
+ const startContainer = this.resolveTextContainer(range.startContainer);
731
+ const endContainer = this.resolveTextContainer(range.endContainer);
732
+ if (!startContainer || !endContainer) {
733
+ return null;
734
+ }
735
+ const textContainers = Array.from(this.content.querySelectorAll(".hyepl-block-text"));
736
+ const startIndex = textContainers.indexOf(startContainer);
737
+ const endIndex = textContainers.indexOf(endContainer);
738
+ if (startIndex < 0 || endIndex < 0) {
739
+ return null;
740
+ }
741
+ const from = Math.min(startIndex, endIndex);
742
+ const to = Math.max(startIndex, endIndex);
743
+ const segments = [];
744
+ for (let index = from; index <= to; index += 1) {
745
+ const container = textContainers[index];
746
+ if (!container) {
747
+ continue;
748
+ }
749
+ const pageId = container.dataset.pageId;
750
+ const blockId = container.dataset.blockId;
751
+ if (!pageId || !blockId) {
752
+ continue;
753
+ }
754
+ let start = 0;
755
+ let end = this.getContainerTextLength(container);
756
+ if (container === startContainer) {
757
+ const boundaryOffset = this.getBoundaryOffsetInContainer(container, range.startContainer, range.startOffset);
758
+ if (boundaryOffset === null) {
759
+ continue;
760
+ }
761
+ start = boundaryOffset;
762
+ }
763
+ if (container === endContainer) {
764
+ const boundaryOffset = this.getBoundaryOffsetInContainer(container, range.endContainer, range.endOffset);
765
+ if (boundaryOffset === null) {
766
+ continue;
767
+ }
768
+ end = boundaryOffset;
769
+ }
770
+ const normalized = this.normalizeOffsetRange(start, end);
771
+ if (!normalized) {
772
+ continue;
773
+ }
774
+ const text = this.getRangeTextByOffsets(container, normalized);
775
+ segments.push({
776
+ pageId,
777
+ blockId,
778
+ range: normalized,
779
+ text,
780
+ });
781
+ }
782
+ if (!segments.length) {
783
+ const fallback = this.getSelectionOffsets(startContainer, selection);
784
+ if (!fallback) {
785
+ return null;
786
+ }
787
+ const pageId = startContainer.dataset.pageId;
788
+ const blockId = startContainer.dataset.blockId;
789
+ if (!pageId || !blockId) {
790
+ return null;
791
+ }
792
+ return [
793
+ {
794
+ pageId,
795
+ blockId,
796
+ range: fallback,
797
+ text: selection.toString().trim(),
798
+ },
799
+ ];
800
+ }
801
+ return segments;
802
+ }
803
+ getContainerTextLength(container) {
804
+ const range = document.createRange();
805
+ range.selectNodeContents(container);
806
+ return range.toString().length;
807
+ }
808
+ getBoundaryOffsetInContainer(container, boundaryNode, boundaryOffset) {
809
+ if (!container.contains(boundaryNode) && container !== boundaryNode) {
810
+ return null;
811
+ }
812
+ const range = document.createRange();
813
+ range.selectNodeContents(container);
814
+ try {
815
+ range.setEnd(boundaryNode, boundaryOffset);
816
+ }
817
+ catch {
818
+ return null;
819
+ }
820
+ return range.toString().length;
821
+ }
822
+ getRangeTextByOffsets(container, offsets) {
823
+ const range = this.createRangeFromOffsets(container, offsets.start, offsets.end);
824
+ return range ? range.toString().trim() : "";
825
+ }
504
826
  hideSelectionToolbar() {
505
827
  this.selectionToolbar.classList.remove("show");
506
828
  this.selectionDraft = null;
@@ -529,18 +851,28 @@ export class EBookPlayer {
529
851
  if (!this.selectionDraft) {
530
852
  return;
531
853
  }
532
- const payload = {
533
- pageId: this.selectionDraft.pageId,
534
- blockId: this.selectionDraft.blockId,
535
- range: this.selectionDraft.range,
536
- ...(this.selectionDraft.text
537
- ? { selectedText: this.selectionDraft.text }
538
- : {}),
539
- ...(this.selectionOptions.highlightColor
540
- ? { color: this.selectionOptions.highlightColor }
541
- : {}),
542
- };
543
- await this.createHighlight(payload, "user");
854
+ const segments = this.selectionDraft.segments && this.selectionDraft.segments.length
855
+ ? this.selectionDraft.segments
856
+ : [
857
+ {
858
+ pageId: this.selectionDraft.pageId,
859
+ blockId: this.selectionDraft.blockId,
860
+ range: this.selectionDraft.range,
861
+ text: this.selectionDraft.text,
862
+ },
863
+ ];
864
+ for (const segment of segments) {
865
+ const payload = {
866
+ pageId: segment.pageId,
867
+ blockId: segment.blockId,
868
+ range: segment.range,
869
+ ...(segment.text ? { selectedText: segment.text } : {}),
870
+ ...(this.selectionOptions.highlightColor
871
+ ? { color: this.selectionOptions.highlightColor }
872
+ : {}),
873
+ };
874
+ await this.createHighlight(payload, "user");
875
+ }
544
876
  this.clearSelection();
545
877
  this.hideSelectionToolbar();
546
878
  }
@@ -548,24 +880,34 @@ export class EBookPlayer {
548
880
  if (!this.selectionDraft) {
549
881
  return;
550
882
  }
551
- const defaultText = this.selectionDraft.text || "";
883
+ const defaultText = "";
552
884
  const content = this.promptTextWithLimit("请输入笔记内容", defaultText, this.inputLimits.noteMaxLength);
553
885
  if (content === null) {
554
886
  return;
555
887
  }
556
- const payload = {
557
- pageId: this.selectionDraft.pageId,
558
- blockId: this.selectionDraft.blockId,
559
- range: this.selectionDraft.range,
560
- content,
561
- ...(this.selectionDraft.text
562
- ? { selectedText: this.selectionDraft.text }
563
- : {}),
564
- ...(this.selectionOptions.noteColor
565
- ? { color: this.selectionOptions.noteColor }
566
- : {}),
567
- };
568
- await this.createNote(payload, "user");
888
+ const segments = this.selectionDraft.segments && this.selectionDraft.segments.length
889
+ ? this.selectionDraft.segments
890
+ : [
891
+ {
892
+ pageId: this.selectionDraft.pageId,
893
+ blockId: this.selectionDraft.blockId,
894
+ range: this.selectionDraft.range,
895
+ text: this.selectionDraft.text,
896
+ },
897
+ ];
898
+ for (const segment of segments) {
899
+ const payload = {
900
+ pageId: segment.pageId,
901
+ blockId: segment.blockId,
902
+ range: segment.range,
903
+ content,
904
+ ...(segment.text ? { selectedText: segment.text } : {}),
905
+ ...(this.selectionOptions.noteColor
906
+ ? { color: this.selectionOptions.noteColor }
907
+ : {}),
908
+ };
909
+ await this.createNote(payload, "user");
910
+ }
569
911
  this.clearSelection();
570
912
  this.hideSelectionToolbar();
571
913
  }
@@ -748,3 +1090,14 @@ function createRuntimeProvider(provider, getRuntimeDocument) {
748
1090
  function cloneEbookDoc(doc) {
749
1091
  return JSON.parse(JSON.stringify(doc));
750
1092
  }
1093
+ function escapeHtml(value) {
1094
+ return value
1095
+ .replace(/&/g, "&amp;")
1096
+ .replace(/</g, "&lt;")
1097
+ .replace(/>/g, "&gt;")
1098
+ .replace(/\"/g, "&quot;")
1099
+ .replace(/'/g, "&#39;");
1100
+ }
1101
+ function escapeAttribute(value) {
1102
+ return escapeHtml(value);
1103
+ }
@@ -41,9 +41,13 @@ export interface EditorWorkbenchExtensionActionButton {
41
41
  export interface EditorWorkbenchExtensionOptions {
42
42
  actions?: EditorWorkbenchExtensionActionButton[];
43
43
  }
44
+ export type EditorWorkbenchDebugLevel = "info" | "warn" | "error";
44
45
  export interface EditorWorkbenchDebugOptions {
45
46
  enabled?: boolean;
46
47
  prefix?: string;
48
+ level?: EditorWorkbenchDebugLevel;
49
+ groups?: string[];
50
+ includeWordImportSource?: boolean;
47
51
  }
48
52
  export interface EditorWorkbenchPreviewAnnotationActions {
49
53
  canDelete?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"editor-workbench.d.ts","sourceRoot":"","sources":["../../../../../core/src/workbench/editor-workbench.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor-workbench.d.ts","sourceRoot":"","sources":["../../../../../core/src/workbench/editor-workbench.ts"],"names":[],"mappings":"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"}
@@ -4,12 +4,12 @@ const WORKBENCH_STYLE_ID = "hy-ebook-workbench-style";
4
4
  const WORKBENCH_STYLE_VERSION = "0.3.0";
5
5
  const WORKBENCH_CSS = `
6
6
  .hyewb-root{font-family:"Noto Sans SC","PingFang SC","Microsoft YaHei",sans-serif;color:#0f172a;background:#f8fbff;border:1px solid #d8e0ea;border-radius:12px;padding:12px;display:grid;gap:10px;position:relative;--hyewb-top-shield-height:0px}
7
- .hyewb-root::before{content:"";position:absolute;left:0;right:0;top:0;height:var(--hyewb-top-shield-height);background:#f8fbff;z-index:119500;pointer-events:none}
7
+ .hyewb-root::before{content:"";position:absolute;left:0;right:0;top:0;height:var(--hyewb-top-shield-height);background:#f8fbff;z-index:10030;pointer-events:none}
8
8
  .hyewb-header{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap}
9
9
  .hyewb-title{font-size:14px;font-weight:600}
10
10
  .hyewb-header-actions{margin-left:auto;display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}
11
11
  .hyewb-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
12
- .hyewb-top-control{position:relative;z-index:120000;background:#f8fbff;isolation:isolate}
12
+ .hyewb-top-control{position:relative;z-index:10040;background:#f8fbff;isolation:isolate}
13
13
  .hyewb-btn{border:1px solid #94a3b8;background:#fff;color:#0f172a;border-radius:8px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;width:34px;height:34px;flex:0 0 auto}
14
14
  .hyewb-btn.hyewb-btn-text{width:auto;min-width:96px;padding:0 12px}
15
15
  .hyewb-header-action-btn{height:34px}
@@ -33,7 +33,7 @@ const WORKBENCH_CSS = `
33
33
  .hyewb-preview-layout.with-annotation-panel{grid-template-columns:minmax(0,1fr) 300px}
34
34
  .hyewb-canvas{position:relative;background:#fff;border:1px solid #d9e3ee;border-radius:8px;min-height:420px;padding:20px 24px;box-shadow:0 6px 16px rgba(15,23,42,.08);margin:16px auto;max-width:100%;box-sizing:border-box;}
35
35
  .hyewb-editor{min-height:360px;outline:none;line-height:1.7;font-size:16px;color:#1e293b}
36
- .hyewb-float{position:fixed;z-index:9999;display:none;align-items:center;gap:6px;padding:6px 8px;border-radius:10px;border:1px solid #0f172a;background:rgba(15,23,42,.96);box-shadow:0 10px 24px rgba(15,23,42,.22)}
36
+ .hyewb-float{position:fixed;z-index:10070;display:none;align-items:center;gap:6px;padding:6px 8px;border-radius:10px;border:1px solid #0f172a;background:rgba(15,23,42,.96);box-shadow:0 10px 24px rgba(15,23,42,.22)}
37
37
  .hyewb-float.show{display:inline-flex}
38
38
  .hyewb-float .hyewb-btn{border-color:#334155;background:#1e293b;color:#f8fafc;width:30px;height:30px}
39
39
  .hyewb-float .hyewb-btn:hover{background:#334155}
@@ -138,7 +138,7 @@ const WORKBENCH_CSS = `
138
138
  .hyewb-media-handle[data-handle="w"]{left:-6px;top:calc(50% - 5px);cursor:ew-resize}
139
139
  .hyewb-media-list{margin:0;padding-left:18px;color:#334155;font-size:13px;display:grid;gap:4px}
140
140
  .hyewb-status{font-size:12px;color:#475569}
141
- .hyewb-upload-backdrop{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(15,23,42,.45);z-index:10020;padding:16px}
141
+ .hyewb-upload-backdrop{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(15,23,42,.45);z-index:10100;padding:16px}
142
142
  .hyewb-upload-backdrop.show{display:flex}
143
143
  .hyewb-upload-dialog{position:relative;width:min(520px,100%);background:#fff;border:1px solid #cbd5e1;border-radius:12px;padding:14px;display:grid;gap:10px;box-shadow:0 16px 34px rgba(15,23,42,.28)}
144
144
  .hyewb-upload-title{font-size:14px;font-weight:600;color:#0f172a}
@@ -147,7 +147,7 @@ const WORKBENCH_CSS = `
147
147
  .hyewb-upload-progress{height:8px;background:#e2e8f0;border-radius:999px;overflow:hidden}
148
148
  .hyewb-upload-progress > span{display:block;height:100%;width:0;background:#0b7285;transition:width .18s ease}
149
149
  .hyewb-upload-error{min-height:18px;font-size:12px;color:#b91c1c;margin:0}
150
- .hyewb-preview-note-backdrop{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(15,23,42,.45);z-index:10080;padding:16px}
150
+ .hyewb-preview-note-backdrop{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(15,23,42,.45);z-index:10110;padding:16px}
151
151
  .hyewb-preview-note-backdrop.show{display:flex}
152
152
  .hyewb-preview-note-dialog{width:min(520px,100%);background:#fff;border:1px solid #cbd5e1;border-radius:12px;padding:14px;display:grid;gap:10px;box-shadow:0 16px 34px rgba(15,23,42,.28)}
153
153
  .hyewb-preview-note-title{margin:0;font-size:14px;font-weight:600;color:#0f172a}
@@ -171,7 +171,7 @@ const WORKBENCH_CSS = `
171
171
  .hyewb-preview-annotation-item:hover .hyewb-preview-annotation-delete{opacity:1;pointer-events:auto}
172
172
  .hyewb-preview-annotation-delete svg{width:14px;height:14px}
173
173
  .hyewb-preview-annotation-empty{margin:0;color:#64748b;font-size:13px}
174
- .hyewb-preview-selection-toolbar{position:fixed;z-index:10060;display:none;align-items:center;gap:8px;padding:6px 8px;border-radius:10px;border:1px solid #0f172a;background:rgba(15,23,42,.96);box-shadow:0 10px 24px rgba(15,23,42,.22);transform:translate(-50%,-100%)}
174
+ .hyewb-preview-selection-toolbar{position:fixed;z-index:10070;display:none;align-items:center;gap:8px;padding:6px 8px;border-radius:10px;border:1px solid #0f172a;background:rgba(15,23,42,.96);box-shadow:0 10px 24px rgba(15,23,42,.22);transform:translate(-50%,-100%)}
175
175
  .hyewb-preview-selection-toolbar.show{display:inline-flex}
176
176
  .hyewb-preview-selection-btn{width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid #334155;background:#1e293b;color:#f8fafc;border-radius:8px;cursor:pointer}
177
177
  .hyewb-preview-selection-btn:hover{background:#334155}
@@ -572,11 +572,11 @@ export function mountEditorWorkbench(container, options = {}) {
572
572
  bgColorInput.append(bgColorChip);
573
573
  const lineHeightSelect = document.createElement("select");
574
574
  lineHeightSelect.className = "hyewb-select";
575
- ["1.2", "1.4", "1.6", "1.8", "2"].forEach((value) => {
575
+ ["1.0", "1.15", "1.5", "2.0", "2.5", "3.0"].forEach((value) => {
576
576
  const optionNode = document.createElement("option");
577
577
  optionNode.value = value;
578
578
  optionNode.textContent = value;
579
- if (value === "1.6") {
579
+ if (value === "1.5") {
580
580
  optionNode.selected = true;
581
581
  }
582
582
  lineHeightSelect.append(optionNode);
@@ -897,20 +897,66 @@ export function mountEditorWorkbench(container, options = {}) {
897
897
  const status = document.createElement("p");
898
898
  status.className = "hyewb-status";
899
899
  status.textContent = "已加载默认编辑器能力";
900
+ const debugConfig = typeof options.debug === "object" && options.debug !== null
901
+ ? options.debug
902
+ : undefined;
900
903
  const debugEnabled = options.debug === true ||
901
- (typeof options.debug === "object" &&
902
- options.debug !== null &&
903
- options.debug.enabled !== false);
904
- const debugPrefix = typeof options.debug === "object" &&
905
- options.debug !== null &&
906
- options.debug.prefix
907
- ? options.debug.prefix
908
- : "[hyebook:workbench]";
909
- const debugLog = (message) => {
904
+ Boolean(debugConfig && debugConfig.enabled !== false);
905
+ const debugPrefix = debugConfig?.prefix || "[hyebook:workbench]";
906
+ const normalizeDebugLevel = (level) => {
907
+ if (level === "warn" || level === "error") {
908
+ return level;
909
+ }
910
+ return "info";
911
+ };
912
+ const debugLevel = normalizeDebugLevel(debugConfig?.level);
913
+ const debugLevelRank = {
914
+ info: 1,
915
+ warn: 2,
916
+ error: 3,
917
+ };
918
+ const debugGroups = Array.isArray(debugConfig?.groups) && debugConfig.groups.length
919
+ ? new Set(debugConfig.groups
920
+ .map((group) => String(group || "").trim())
921
+ .filter(Boolean))
922
+ : null;
923
+ const shouldLogDebugGroup = (group) => {
924
+ if (!debugGroups || !debugGroups.size || !group) {
925
+ return true;
926
+ }
927
+ return debugGroups.has(group);
928
+ };
929
+ const debugLog = (message, logOptions) => {
910
930
  if (!debugEnabled) {
911
931
  return;
912
932
  }
913
- console.log(`${debugPrefix} ${message}`);
933
+ const level = normalizeDebugLevel(logOptions?.level);
934
+ if (debugLevelRank[level] < debugLevelRank[debugLevel]) {
935
+ return;
936
+ }
937
+ if (!shouldLogDebugGroup(logOptions?.group)) {
938
+ return;
939
+ }
940
+ const scopedPrefix = logOptions?.group
941
+ ? `${debugPrefix}:${logOptions.group}`
942
+ : debugPrefix;
943
+ const messageText = `${scopedPrefix} ${message}`;
944
+ if (logOptions &&
945
+ Object.prototype.hasOwnProperty.call(logOptions, "payload")) {
946
+ console[level](messageText, logOptions.payload);
947
+ return;
948
+ }
949
+ console[level](messageText);
950
+ };
951
+ const wordImportSourceLoggingEnabled = debugEnabled && (debugConfig?.includeWordImportSource ?? true);
952
+ const debugWordImport = (message, logOptions) => {
953
+ if (!wordImportSourceLoggingEnabled) {
954
+ return;
955
+ }
956
+ debugLog(message, {
957
+ ...logOptions,
958
+ group: logOptions?.group || "word-import",
959
+ });
914
960
  };
915
961
  let lastDebugStatusMessage = "";
916
962
  const flushDebugStatus = () => {
@@ -919,7 +965,7 @@ export function mountEditorWorkbench(container, options = {}) {
919
965
  return;
920
966
  }
921
967
  lastDebugStatusMessage = nextMessage;
922
- debugLog(nextMessage);
968
+ debugLog(nextMessage, { group: "status" });
923
969
  };
924
970
  const statusObserver = debugEnabled && typeof MutationObserver !== "undefined"
925
971
  ? new MutationObserver(() => {
@@ -1356,28 +1402,77 @@ export function mountEditorWorkbench(container, options = {}) {
1356
1402
  }
1357
1403
  };
1358
1404
  const importDocxFile = async (file) => {
1405
+ const maxSize = options.importDocx?.maxSizeBytes;
1406
+ debugWordImport("收到 Word 导入请求", {
1407
+ group: "word-import-file",
1408
+ payload: {
1409
+ fileName: file.name,
1410
+ mimeType: file.type || "",
1411
+ sizeBytes: file.size,
1412
+ maxSizeBytes: maxSize ?? null,
1413
+ },
1414
+ });
1359
1415
  const isDocx = isDocxMime(file.type) || file.name.toLowerCase().endsWith(".docx");
1360
1416
  if (!isDocx) {
1417
+ debugWordImport("文件校验失败:非 docx", {
1418
+ level: "warn",
1419
+ group: "word-import-file",
1420
+ });
1361
1421
  status.textContent = "仅支持导入 .docx 文件";
1362
1422
  return;
1363
1423
  }
1364
- const maxSize = options.importDocx?.maxSizeBytes;
1365
1424
  if (maxSize && file.size > maxSize) {
1425
+ debugWordImport("文件校验失败:超过大小限制", {
1426
+ level: "warn",
1427
+ group: "word-import-file",
1428
+ payload: {
1429
+ sizeBytes: file.size,
1430
+ maxSizeBytes: maxSize,
1431
+ },
1432
+ });
1366
1433
  status.textContent = `Word 文件大小不能超过 ${Math.round(maxSize / 1024 / 1024)}MB`;
1367
1434
  return;
1368
1435
  }
1369
1436
  status.textContent = `正在导入 Word:${file.name}`;
1370
1437
  let imageUploadIndex = 0;
1438
+ let importRoute = "ooxml";
1439
+ const xmlSourceInfo = createDocxXmlParseDebugInfo();
1371
1440
  try {
1372
1441
  const mammothNamespace = await import("mammoth");
1373
1442
  const mammothModule = resolveMammothModule(mammothNamespace);
1374
1443
  const arrayBuffer = await file.arrayBuffer();
1375
- const xmlPreferredFlowBlocks = await parseDocxFlowBlocksFromXml(arrayBuffer, resolveDocxImportMaxFlowBlockWidth(state.doc.settings.page, paperWidth));
1444
+ debugWordImport("文件已读取为 ArrayBuffer", {
1445
+ group: "word-import-file",
1446
+ payload: {
1447
+ byteLength: arrayBuffer.byteLength,
1448
+ },
1449
+ });
1450
+ const xmlPreferredFlowBlocks = await parseDocxFlowBlocksFromXml(arrayBuffer, resolveDocxImportMaxFlowBlockWidth(state.doc.settings.page, paperWidth), xmlSourceInfo);
1451
+ debugWordImport("OOXML 源信息摘要", {
1452
+ group: "word-import-xml",
1453
+ payload: xmlSourceInfo,
1454
+ });
1376
1455
  if (xmlPreferredFlowBlocks?.length) {
1456
+ debugWordImport("命中 OOXML 高保真解析路径", {
1457
+ group: "word-import-result",
1458
+ payload: {
1459
+ route: "ooxml",
1460
+ flowBlockCount: xmlPreferredFlowBlocks.length,
1461
+ paragraphCount: xmlSourceInfo.paragraphCount,
1462
+ tableCount: xmlSourceInfo.tableCount,
1463
+ },
1464
+ });
1377
1465
  syncEditorToDoc();
1378
1466
  const nextDoc = clone(state.doc);
1379
1467
  const page = getCurrentPage(nextDoc, state.pageIndex);
1380
1468
  if (!page) {
1469
+ debugWordImport("导入失败:当前页不存在", {
1470
+ level: "error",
1471
+ group: "word-import-result",
1472
+ payload: {
1473
+ route: "ooxml",
1474
+ },
1475
+ });
1381
1476
  status.textContent = "当前页面不存在,导入失败";
1382
1477
  return;
1383
1478
  }
@@ -1385,9 +1480,31 @@ export function mountEditorWorkbench(container, options = {}) {
1385
1480
  nextDoc.meta.updatedAt = new Date().toISOString();
1386
1481
  editorRenderKey = "";
1387
1482
  updateStateDoc(nextDoc, "Word 导入成功(高保真文本样式)");
1483
+ debugWordImport("Word 导入成功", {
1484
+ group: "word-import-result",
1485
+ payload: {
1486
+ route: "ooxml",
1487
+ flowBlockCount: xmlPreferredFlowBlocks.length,
1488
+ },
1489
+ });
1388
1490
  return;
1389
1491
  }
1492
+ importRoute = "mammoth";
1493
+ debugWordImport("OOXML 结果为空,回退到 Mammoth 路径", {
1494
+ level: "warn",
1495
+ group: "word-import-xml",
1496
+ payload: {
1497
+ reason: xmlSourceInfo.error || "OOXML parser returned empty result",
1498
+ },
1499
+ });
1390
1500
  const defaultTextStyle = await extractDocxDefaultTextStyle(arrayBuffer);
1501
+ debugWordImport("默认文本样式提取结果", {
1502
+ group: "word-import-mammoth",
1503
+ payload: {
1504
+ hasDefaultTextStyle: Boolean(defaultTextStyle),
1505
+ defaultTextStyle: defaultTextStyle || null,
1506
+ },
1507
+ });
1391
1508
  const result = await mammothModule.convertToHtml({ arrayBuffer }, {
1392
1509
  convertImage: mammothModule.images.imgElement(async (image) => {
1393
1510
  const imageUploader = ensureMediaUploader("image");
@@ -1400,23 +1517,72 @@ export function mountEditorWorkbench(container, options = {}) {
1400
1517
  const contentType = normalizeDocxImageMime(image.contentType) || "image/png";
1401
1518
  const extension = fileExtensionByMime(contentType);
1402
1519
  const imageFile = base64ToFile(base64, contentType, `docx-image-${Date.now()}-${imageUploadIndex}.${extension}`);
1520
+ debugWordImport("开始上传内嵌图片", {
1521
+ group: "word-import-mammoth",
1522
+ payload: {
1523
+ index: imageUploadIndex,
1524
+ contentType,
1525
+ fileName: imageFile.name,
1526
+ sizeBytes: imageFile.size,
1527
+ },
1528
+ });
1403
1529
  const uploadResult = await uploadMediaFile(imageFile, "image", (percent) => {
1404
1530
  status.textContent = `第 ${imageUploadIndex} 张图片上传中:${formatUploadProgress(percent)}%`;
1405
1531
  });
1406
1532
  if (!uploadResult?.url) {
1407
1533
  throw new Error(`第 ${imageUploadIndex} 张图片上传成功但未返回可用地址`);
1408
1534
  }
1535
+ debugWordImport("内嵌图片上传完成", {
1536
+ group: "word-import-mammoth",
1537
+ payload: {
1538
+ index: imageUploadIndex,
1539
+ url: uploadResult.url,
1540
+ },
1541
+ });
1409
1542
  return {
1410
1543
  src: uploadResult.url,
1411
1544
  alt: uploadResult.alt || imageFile.name,
1412
1545
  };
1413
1546
  }),
1414
1547
  });
1548
+ const mammothMessages = result.messages || [];
1549
+ if (mammothMessages.length) {
1550
+ debugWordImport("Mammoth 兼容性提示", {
1551
+ level: "warn",
1552
+ group: "word-import-mammoth",
1553
+ payload: mammothMessages.map((item, index) => ({
1554
+ index: index + 1,
1555
+ type: item.type,
1556
+ message: item.message,
1557
+ })),
1558
+ });
1559
+ }
1560
+ else {
1561
+ debugWordImport("Mammoth 未返回兼容性提示", {
1562
+ group: "word-import-mammoth",
1563
+ });
1564
+ }
1415
1565
  const flowBlocks = parseRichHTMLToFlowBlocks(result.value || "", defaultTextStyle);
1566
+ debugWordImport("Mammoth HTML 已转换为 FlowBlocks", {
1567
+ group: "word-import-result",
1568
+ payload: {
1569
+ route: importRoute,
1570
+ flowBlockCount: flowBlocks.length,
1571
+ compatibilityMessageCount: mammothMessages.length,
1572
+ embeddedImageCount: imageUploadIndex,
1573
+ },
1574
+ });
1416
1575
  syncEditorToDoc();
1417
1576
  const nextDoc = clone(state.doc);
1418
1577
  const page = getCurrentPage(nextDoc, state.pageIndex);
1419
1578
  if (!page) {
1579
+ debugWordImport("导入失败:当前页不存在", {
1580
+ level: "error",
1581
+ group: "word-import-result",
1582
+ payload: {
1583
+ route: importRoute,
1584
+ },
1585
+ });
1420
1586
  status.textContent = "当前页面不存在,导入失败";
1421
1587
  return;
1422
1588
  }
@@ -1424,11 +1590,31 @@ export function mountEditorWorkbench(container, options = {}) {
1424
1590
  nextDoc.meta.updatedAt = new Date().toISOString();
1425
1591
  editorRenderKey = "";
1426
1592
  updateStateDoc(nextDoc, "Word 导入成功");
1427
- if (result.messages?.length) {
1428
- status.textContent = `Word 导入成功(${result.messages.length} 条兼容性提示)`;
1429
- }
1593
+ if (mammothMessages.length) {
1594
+ status.textContent = `Word 导入成功(${mammothMessages.length} 条兼容性提示)`;
1595
+ }
1596
+ debugWordImport("Word 导入成功", {
1597
+ group: "word-import-result",
1598
+ payload: {
1599
+ route: importRoute,
1600
+ flowBlockCount: flowBlocks.length,
1601
+ compatibilityMessageCount: mammothMessages.length,
1602
+ embeddedImageCount: imageUploadIndex,
1603
+ },
1604
+ });
1430
1605
  }
1431
1606
  catch (error) {
1607
+ const errorMessage = error instanceof Error ? error.message : String(error);
1608
+ debugWordImport("Word 导入失败", {
1609
+ level: "error",
1610
+ group: "word-import-result",
1611
+ payload: {
1612
+ route: importRoute,
1613
+ embeddedImageCount: imageUploadIndex,
1614
+ error: errorMessage,
1615
+ xmlSourceInfo,
1616
+ },
1617
+ });
1432
1618
  status.textContent =
1433
1619
  error instanceof Error
1434
1620
  ? `Word 导入失败:${error.message}`
@@ -5716,25 +5902,89 @@ function resolveMammothModule(namespace) {
5716
5902
  const candidate = namespace?.default ?? namespace;
5717
5903
  return candidate;
5718
5904
  }
5719
- async function parseDocxFlowBlocksFromXml(arrayBuffer, maxFlowBlockWidth) {
5905
+ function createDocxXmlParseDebugInfo() {
5906
+ return {
5907
+ archiveLoaded: false,
5908
+ hasDocumentXml: false,
5909
+ hasStylesXml: false,
5910
+ hasThemeXml: false,
5911
+ paragraphCount: 0,
5912
+ tableCount: 0,
5913
+ blockCount: 0,
5914
+ };
5915
+ }
5916
+ function countDocxBodyNodeKinds(documentXml) {
5917
+ const parser = new DOMParser();
5918
+ const documentDoc = parser.parseFromString(documentXml, "application/xml");
5919
+ const body = findDescendantByLocalName(documentDoc.documentElement, "body");
5920
+ if (!body) {
5921
+ return {
5922
+ paragraphCount: 0,
5923
+ tableCount: 0,
5924
+ };
5925
+ }
5926
+ let paragraphCount = 0;
5927
+ let tableCount = 0;
5928
+ for (const child of Array.from(body.children)) {
5929
+ const name = xmlLocalName(child);
5930
+ if (name === "p") {
5931
+ paragraphCount += 1;
5932
+ continue;
5933
+ }
5934
+ if (name === "tbl") {
5935
+ tableCount += 1;
5936
+ }
5937
+ }
5938
+ return {
5939
+ paragraphCount,
5940
+ tableCount,
5941
+ };
5942
+ }
5943
+ async function parseDocxFlowBlocksFromXml(arrayBuffer, maxFlowBlockWidth, debugInfo) {
5720
5944
  try {
5721
5945
  const archive = await loadDocxArchive(arrayBuffer);
5722
5946
  if (!archive) {
5947
+ if (debugInfo) {
5948
+ debugInfo.error = "DOCX archive load failed";
5949
+ }
5723
5950
  return undefined;
5724
5951
  }
5725
- const documentXml = await archive
5726
- .file("word/document.xml")
5727
- ?.async("string");
5952
+ const documentEntry = archive.file("word/document.xml");
5953
+ const stylesEntry = archive.file("word/styles.xml");
5954
+ const themeEntry = archive.file("word/theme/theme1.xml");
5955
+ if (debugInfo) {
5956
+ debugInfo.archiveLoaded = true;
5957
+ debugInfo.hasDocumentXml = Boolean(documentEntry);
5958
+ debugInfo.hasStylesXml = Boolean(stylesEntry);
5959
+ debugInfo.hasThemeXml = Boolean(themeEntry);
5960
+ }
5961
+ const documentXml = await documentEntry?.async("string");
5728
5962
  if (!documentXml) {
5963
+ if (debugInfo) {
5964
+ debugInfo.error = "word/document.xml missing or empty";
5965
+ }
5729
5966
  return undefined;
5730
5967
  }
5731
- const stylesXml = await archive.file("word/styles.xml")?.async("string");
5732
- const themeXml = await archive
5733
- .file("word/theme/theme1.xml")
5734
- ?.async("string");
5735
- return parseDocxBodyToFlowBlocks(documentXml, stylesXml, themeXml, maxFlowBlockWidth);
5968
+ if (debugInfo) {
5969
+ const counts = countDocxBodyNodeKinds(documentXml);
5970
+ debugInfo.paragraphCount = counts.paragraphCount;
5971
+ debugInfo.tableCount = counts.tableCount;
5972
+ }
5973
+ const stylesXml = await stylesEntry?.async("string");
5974
+ const themeXml = await themeEntry?.async("string");
5975
+ const blocks = parseDocxBodyToFlowBlocks(documentXml, stylesXml, themeXml, maxFlowBlockWidth);
5976
+ if (debugInfo) {
5977
+ debugInfo.blockCount = blocks?.length || 0;
5978
+ if (!blocks?.length && !debugInfo.error) {
5979
+ debugInfo.error = "OOXML parser returned no flow blocks";
5980
+ }
5981
+ }
5982
+ return blocks;
5736
5983
  }
5737
- catch {
5984
+ catch (error) {
5985
+ if (debugInfo) {
5986
+ debugInfo.error = error instanceof Error ? error.message : String(error);
5987
+ }
5738
5988
  return undefined;
5739
5989
  }
5740
5990
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyebook/vue3-adapter",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "description": "Vue3 adapter for hy-ebook core",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,7 @@
17
17
  "dist"
18
18
  ],
19
19
  "dependencies": {
20
- "@hyebook/core": "^2.3.2"
20
+ "@hyebook/core": "^2.3.3"
21
21
  },
22
22
  "scripts": {
23
23
  "build": "tsc -p tsconfig.json",