@hyebook/vue3-adapter 2.3.2 → 2.3.4
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/core/src/player/ebook-player.d.ts +13 -0
- package/dist/core/src/player/ebook-player.d.ts.map +1 -1
- package/dist/core/src/player/ebook-player.js +475 -54
- package/dist/core/src/player/engine.d.ts +1 -0
- package/dist/core/src/player/engine.d.ts.map +1 -1
- package/dist/core/src/player/engine.js +38 -8
- package/dist/core/src/types/player.d.ts +9 -0
- package/dist/core/src/types/player.d.ts.map +1 -1
- package/dist/core/src/workbench/editor-workbench.d.ts +4 -0
- package/dist/core/src/workbench/editor-workbench.d.ts.map +1 -1
- package/dist/core/src/workbench/editor-workbench.js +284 -48
- package/package.json +2 -2
|
@@ -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.
|
|
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;
|
|
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:
|
|
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.
|
|
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
|
-
|
|
268
|
-
return node;
|
|
283
|
+
return this.renderImageBlock(block);
|
|
269
284
|
}
|
|
270
285
|
if (block.type === "video") {
|
|
271
|
-
|
|
272
|
-
return node;
|
|
286
|
+
return this.renderVideoBlock(block);
|
|
273
287
|
}
|
|
274
288
|
if (block.type === "table") {
|
|
275
|
-
|
|
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,21 +300,248 @@ 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();
|
|
291
522
|
const bookmarksByBlock = new Map();
|
|
292
523
|
annotations.highlights.forEach((item) => {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
524
|
+
this.resolveAnnotationSegments(item.pageId, item.blockId, item.range, item.segments).forEach((segment) => {
|
|
525
|
+
const key = this.toBlockKey(segment.pageId, segment.blockId);
|
|
526
|
+
const current = highlightsByBlock.get(key) || [];
|
|
527
|
+
current.push({
|
|
528
|
+
id: item.id,
|
|
529
|
+
range: segment.range,
|
|
530
|
+
...(item.color ? { color: item.color } : {}),
|
|
531
|
+
});
|
|
532
|
+
highlightsByBlock.set(key, current);
|
|
533
|
+
});
|
|
297
534
|
});
|
|
298
535
|
annotations.notes.forEach((item) => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
536
|
+
this.resolveAnnotationSegments(item.pageId, item.blockId, item.range, item.segments).forEach((segment) => {
|
|
537
|
+
const key = this.toBlockKey(segment.pageId, segment.blockId);
|
|
538
|
+
const current = notesByBlock.get(key) || [];
|
|
539
|
+
current.push({
|
|
540
|
+
id: item.id,
|
|
541
|
+
range: segment.range,
|
|
542
|
+
});
|
|
543
|
+
notesByBlock.set(key, current);
|
|
544
|
+
});
|
|
303
545
|
});
|
|
304
546
|
const bookmarks = Array.isArray(annotations.bookmarks)
|
|
305
547
|
? annotations.bookmarks
|
|
@@ -313,6 +555,39 @@ export class EBookPlayer {
|
|
|
313
555
|
toBlockKey(pageId, blockId) {
|
|
314
556
|
return `${pageId}::${blockId}`;
|
|
315
557
|
}
|
|
558
|
+
resolveAnnotationSegments(pageId, blockId, range, segments) {
|
|
559
|
+
const resolvedSegments = Array.isArray(segments)
|
|
560
|
+
? segments
|
|
561
|
+
.map((segment) => {
|
|
562
|
+
const segmentPageId = typeof segment?.pageId === "string" ? segment.pageId : "";
|
|
563
|
+
const segmentBlockId = typeof segment?.blockId === "string" ? segment.blockId : "";
|
|
564
|
+
const normalizedRange = this.normalizeOffsetRange(segment?.range?.start || 0, segment?.range?.end || 0);
|
|
565
|
+
if (!segmentPageId || !segmentBlockId || !normalizedRange) {
|
|
566
|
+
return null;
|
|
567
|
+
}
|
|
568
|
+
return {
|
|
569
|
+
pageId: segmentPageId,
|
|
570
|
+
blockId: segmentBlockId,
|
|
571
|
+
range: normalizedRange,
|
|
572
|
+
...(segment?.selectedText
|
|
573
|
+
? { selectedText: segment.selectedText }
|
|
574
|
+
: {}),
|
|
575
|
+
};
|
|
576
|
+
})
|
|
577
|
+
.filter((segment) => segment !== null)
|
|
578
|
+
: [];
|
|
579
|
+
if (resolvedSegments.length) {
|
|
580
|
+
return resolvedSegments;
|
|
581
|
+
}
|
|
582
|
+
if (!pageId || !blockId || !range) {
|
|
583
|
+
return [];
|
|
584
|
+
}
|
|
585
|
+
const normalizedRange = this.normalizeOffsetRange(range.start, range.end);
|
|
586
|
+
if (!normalizedRange) {
|
|
587
|
+
return [];
|
|
588
|
+
}
|
|
589
|
+
return [{ pageId, blockId, range: normalizedRange }];
|
|
590
|
+
}
|
|
316
591
|
applyHighlightMarks(container, highlights) {
|
|
317
592
|
[...highlights]
|
|
318
593
|
.filter((item) => Number.isFinite(item.range.start) && Number.isFinite(item.range.end))
|
|
@@ -332,16 +607,12 @@ export class EBookPlayer {
|
|
|
332
607
|
}
|
|
333
608
|
applyNoteMarks(container, notes) {
|
|
334
609
|
[...notes]
|
|
335
|
-
.filter((item) => !!item.range)
|
|
336
610
|
.sort((a, b) => {
|
|
337
|
-
const startA = a.range
|
|
338
|
-
const startB = b.range
|
|
611
|
+
const startA = a.range.start || 0;
|
|
612
|
+
const startB = b.range.start || 0;
|
|
339
613
|
return startB - startA;
|
|
340
614
|
})
|
|
341
615
|
.forEach((item) => {
|
|
342
|
-
if (!item.range) {
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
616
|
const range = this.createRangeFromOffsets(container, item.range.start, item.range.end);
|
|
346
617
|
if (!range || range.collapsed) {
|
|
347
618
|
return;
|
|
@@ -438,20 +709,13 @@ export class EBookPlayer {
|
|
|
438
709
|
return;
|
|
439
710
|
}
|
|
440
711
|
const range = selection.getRangeAt(0);
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
if (!startContainer || !endContainer || startContainer !== endContainer) {
|
|
444
|
-
this.hideSelectionToolbar();
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
const offsets = this.getSelectionOffsets(startContainer, selection);
|
|
448
|
-
if (!offsets) {
|
|
712
|
+
const segments = this.collectSelectionSegments(selection, range);
|
|
713
|
+
if (!segments?.length) {
|
|
449
714
|
this.hideSelectionToolbar();
|
|
450
715
|
return;
|
|
451
716
|
}
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
if (!pageId || !blockId) {
|
|
717
|
+
const firstSegment = segments[0];
|
|
718
|
+
if (!firstSegment) {
|
|
455
719
|
this.hideSelectionToolbar();
|
|
456
720
|
return;
|
|
457
721
|
}
|
|
@@ -461,10 +725,11 @@ export class EBookPlayer {
|
|
|
461
725
|
return;
|
|
462
726
|
}
|
|
463
727
|
this.selectionDraft = {
|
|
464
|
-
pageId,
|
|
465
|
-
blockId,
|
|
466
|
-
range:
|
|
728
|
+
pageId: firstSegment.pageId,
|
|
729
|
+
blockId: firstSegment.blockId,
|
|
730
|
+
range: firstSegment.range,
|
|
467
731
|
text: selection.toString().trim(),
|
|
732
|
+
segments,
|
|
468
733
|
};
|
|
469
734
|
this.selectionToolbar.style.left = `${Math.round(rect.left + rect.width / 2)}px`;
|
|
470
735
|
this.selectionToolbar.style.top = `${Math.round(rect.top - 20)}px`;
|
|
@@ -501,6 +766,103 @@ export class EBookPlayer {
|
|
|
501
766
|
const end = endRange.toString().length;
|
|
502
767
|
return this.normalizeOffsetRange(start, end);
|
|
503
768
|
}
|
|
769
|
+
collectSelectionSegments(selection, range) {
|
|
770
|
+
const startContainer = this.resolveTextContainer(range.startContainer);
|
|
771
|
+
const endContainer = this.resolveTextContainer(range.endContainer);
|
|
772
|
+
if (!startContainer || !endContainer) {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
const textContainers = Array.from(this.content.querySelectorAll(".hyepl-block-text"));
|
|
776
|
+
const startIndex = textContainers.indexOf(startContainer);
|
|
777
|
+
const endIndex = textContainers.indexOf(endContainer);
|
|
778
|
+
if (startIndex < 0 || endIndex < 0) {
|
|
779
|
+
return null;
|
|
780
|
+
}
|
|
781
|
+
const from = Math.min(startIndex, endIndex);
|
|
782
|
+
const to = Math.max(startIndex, endIndex);
|
|
783
|
+
const segments = [];
|
|
784
|
+
for (let index = from; index <= to; index += 1) {
|
|
785
|
+
const container = textContainers[index];
|
|
786
|
+
if (!container) {
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
const pageId = container.dataset.pageId;
|
|
790
|
+
const blockId = container.dataset.blockId;
|
|
791
|
+
if (!pageId || !blockId) {
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
794
|
+
let start = 0;
|
|
795
|
+
let end = this.getContainerTextLength(container);
|
|
796
|
+
if (container === startContainer) {
|
|
797
|
+
const boundaryOffset = this.getBoundaryOffsetInContainer(container, range.startContainer, range.startOffset);
|
|
798
|
+
if (boundaryOffset === null) {
|
|
799
|
+
continue;
|
|
800
|
+
}
|
|
801
|
+
start = boundaryOffset;
|
|
802
|
+
}
|
|
803
|
+
if (container === endContainer) {
|
|
804
|
+
const boundaryOffset = this.getBoundaryOffsetInContainer(container, range.endContainer, range.endOffset);
|
|
805
|
+
if (boundaryOffset === null) {
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
end = boundaryOffset;
|
|
809
|
+
}
|
|
810
|
+
const normalized = this.normalizeOffsetRange(start, end);
|
|
811
|
+
if (!normalized) {
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
const text = this.getRangeTextByOffsets(container, normalized);
|
|
815
|
+
segments.push({
|
|
816
|
+
pageId,
|
|
817
|
+
blockId,
|
|
818
|
+
range: normalized,
|
|
819
|
+
text,
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
if (!segments.length) {
|
|
823
|
+
const fallback = this.getSelectionOffsets(startContainer, selection);
|
|
824
|
+
if (!fallback) {
|
|
825
|
+
return null;
|
|
826
|
+
}
|
|
827
|
+
const pageId = startContainer.dataset.pageId;
|
|
828
|
+
const blockId = startContainer.dataset.blockId;
|
|
829
|
+
if (!pageId || !blockId) {
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
return [
|
|
833
|
+
{
|
|
834
|
+
pageId,
|
|
835
|
+
blockId,
|
|
836
|
+
range: fallback,
|
|
837
|
+
text: selection.toString().trim(),
|
|
838
|
+
},
|
|
839
|
+
];
|
|
840
|
+
}
|
|
841
|
+
return segments;
|
|
842
|
+
}
|
|
843
|
+
getContainerTextLength(container) {
|
|
844
|
+
const range = document.createRange();
|
|
845
|
+
range.selectNodeContents(container);
|
|
846
|
+
return range.toString().length;
|
|
847
|
+
}
|
|
848
|
+
getBoundaryOffsetInContainer(container, boundaryNode, boundaryOffset) {
|
|
849
|
+
if (!container.contains(boundaryNode) && container !== boundaryNode) {
|
|
850
|
+
return null;
|
|
851
|
+
}
|
|
852
|
+
const range = document.createRange();
|
|
853
|
+
range.selectNodeContents(container);
|
|
854
|
+
try {
|
|
855
|
+
range.setEnd(boundaryNode, boundaryOffset);
|
|
856
|
+
}
|
|
857
|
+
catch {
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
860
|
+
return range.toString().length;
|
|
861
|
+
}
|
|
862
|
+
getRangeTextByOffsets(container, offsets) {
|
|
863
|
+
const range = this.createRangeFromOffsets(container, offsets.start, offsets.end);
|
|
864
|
+
return range ? range.toString().trim() : "";
|
|
865
|
+
}
|
|
504
866
|
hideSelectionToolbar() {
|
|
505
867
|
this.selectionToolbar.classList.remove("show");
|
|
506
868
|
this.selectionDraft = null;
|
|
@@ -529,16 +891,40 @@ export class EBookPlayer {
|
|
|
529
891
|
if (!this.selectionDraft) {
|
|
530
892
|
return;
|
|
531
893
|
}
|
|
894
|
+
const segments = this.selectionDraft.segments && this.selectionDraft.segments.length
|
|
895
|
+
? this.selectionDraft.segments
|
|
896
|
+
: [
|
|
897
|
+
{
|
|
898
|
+
pageId: this.selectionDraft.pageId,
|
|
899
|
+
blockId: this.selectionDraft.blockId,
|
|
900
|
+
range: this.selectionDraft.range,
|
|
901
|
+
text: this.selectionDraft.text,
|
|
902
|
+
},
|
|
903
|
+
];
|
|
904
|
+
const firstSegment = segments[0];
|
|
905
|
+
if (!firstSegment) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
const mergedSelectedText = this.selectionDraft.text ||
|
|
909
|
+
segments
|
|
910
|
+
.map((segment) => segment.text)
|
|
911
|
+
.filter(Boolean)
|
|
912
|
+
.join("\n")
|
|
913
|
+
.trim();
|
|
532
914
|
const payload = {
|
|
533
|
-
pageId:
|
|
534
|
-
blockId:
|
|
535
|
-
range:
|
|
536
|
-
...(
|
|
537
|
-
? { selectedText: this.selectionDraft.text }
|
|
538
|
-
: {}),
|
|
915
|
+
pageId: firstSegment.pageId,
|
|
916
|
+
blockId: firstSegment.blockId,
|
|
917
|
+
range: firstSegment.range,
|
|
918
|
+
...(mergedSelectedText ? { selectedText: mergedSelectedText } : {}),
|
|
539
919
|
...(this.selectionOptions.highlightColor
|
|
540
920
|
? { color: this.selectionOptions.highlightColor }
|
|
541
921
|
: {}),
|
|
922
|
+
segments: segments.map((segment) => ({
|
|
923
|
+
pageId: segment.pageId,
|
|
924
|
+
blockId: segment.blockId,
|
|
925
|
+
range: segment.range,
|
|
926
|
+
...(segment.text ? { selectedText: segment.text } : {}),
|
|
927
|
+
})),
|
|
542
928
|
};
|
|
543
929
|
await this.createHighlight(payload, "user");
|
|
544
930
|
this.clearSelection();
|
|
@@ -548,22 +934,46 @@ export class EBookPlayer {
|
|
|
548
934
|
if (!this.selectionDraft) {
|
|
549
935
|
return;
|
|
550
936
|
}
|
|
551
|
-
const defaultText =
|
|
937
|
+
const defaultText = "";
|
|
552
938
|
const content = this.promptTextWithLimit("请输入笔记内容", defaultText, this.inputLimits.noteMaxLength);
|
|
553
939
|
if (content === null) {
|
|
554
940
|
return;
|
|
555
941
|
}
|
|
942
|
+
const segments = this.selectionDraft.segments && this.selectionDraft.segments.length
|
|
943
|
+
? this.selectionDraft.segments
|
|
944
|
+
: [
|
|
945
|
+
{
|
|
946
|
+
pageId: this.selectionDraft.pageId,
|
|
947
|
+
blockId: this.selectionDraft.blockId,
|
|
948
|
+
range: this.selectionDraft.range,
|
|
949
|
+
text: this.selectionDraft.text,
|
|
950
|
+
},
|
|
951
|
+
];
|
|
952
|
+
const firstSegment = segments[0];
|
|
953
|
+
if (!firstSegment) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const mergedSelectedText = this.selectionDraft.text ||
|
|
957
|
+
segments
|
|
958
|
+
.map((segment) => segment.text)
|
|
959
|
+
.filter(Boolean)
|
|
960
|
+
.join("\n")
|
|
961
|
+
.trim();
|
|
556
962
|
const payload = {
|
|
557
|
-
pageId:
|
|
558
|
-
blockId:
|
|
559
|
-
range:
|
|
963
|
+
pageId: firstSegment.pageId,
|
|
964
|
+
blockId: firstSegment.blockId,
|
|
965
|
+
range: firstSegment.range,
|
|
560
966
|
content,
|
|
561
|
-
...(
|
|
562
|
-
? { selectedText: this.selectionDraft.text }
|
|
563
|
-
: {}),
|
|
967
|
+
...(mergedSelectedText ? { selectedText: mergedSelectedText } : {}),
|
|
564
968
|
...(this.selectionOptions.noteColor
|
|
565
969
|
? { color: this.selectionOptions.noteColor }
|
|
566
970
|
: {}),
|
|
971
|
+
segments: segments.map((segment) => ({
|
|
972
|
+
pageId: segment.pageId,
|
|
973
|
+
blockId: segment.blockId,
|
|
974
|
+
range: segment.range,
|
|
975
|
+
...(segment.text ? { selectedText: segment.text } : {}),
|
|
976
|
+
})),
|
|
567
977
|
};
|
|
568
978
|
await this.createNote(payload, "user");
|
|
569
979
|
this.clearSelection();
|
|
@@ -748,3 +1158,14 @@ function createRuntimeProvider(provider, getRuntimeDocument) {
|
|
|
748
1158
|
function cloneEbookDoc(doc) {
|
|
749
1159
|
return JSON.parse(JSON.stringify(doc));
|
|
750
1160
|
}
|
|
1161
|
+
function escapeHtml(value) {
|
|
1162
|
+
return value
|
|
1163
|
+
.replace(/&/g, "&")
|
|
1164
|
+
.replace(/</g, "<")
|
|
1165
|
+
.replace(/>/g, ">")
|
|
1166
|
+
.replace(/\"/g, """)
|
|
1167
|
+
.replace(/'/g, "'");
|
|
1168
|
+
}
|
|
1169
|
+
function escapeAttribute(value) {
|
|
1170
|
+
return escapeHtml(value);
|
|
1171
|
+
}
|
|
@@ -58,6 +58,7 @@ export declare class PlayerEngine {
|
|
|
58
58
|
private loadAnnotationsState;
|
|
59
59
|
private findPageIndexByPageId;
|
|
60
60
|
private normalizeRange;
|
|
61
|
+
private normalizeSegments;
|
|
61
62
|
private normalizeAnnotations;
|
|
62
63
|
private mapPreviewAnnotationsToReader;
|
|
63
64
|
private persistAnnotations;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/engine.ts"],"names":[],"mappings":"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"}
|