@papyrus-sdk/ui-react-native 0.2.35 → 0.2.37
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.js +322 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +323 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -8
- package/runtime/epubAnnotations.js +280 -6
- package/runtime/epubReader.js +1 -1
- package/runtime/index.html +293 -8
- package/runtime/runtime.js +293 -8
- package/runtime/comicRuntime.test.ts +0 -241
- package/runtime/documentLoadRuntime.test.ts +0 -172
- package/runtime/epubAnnotations.test.ts +0 -35
- package/runtime/epubReader.test.ts +0 -74
- package/runtime/epubRuntime.test.ts +0 -48
- package/runtime/epubScrollDiagnostics.test.ts +0 -107
- package/runtime/epubSelectionMenu.test.ts +0 -39
package/runtime/index.html
CHANGED
|
@@ -20530,7 +20530,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20530
20530
|
var doc=contents.document,win=contents.window,start=null,blocked=false;
|
|
20531
20531
|
function point(e){var t=e.changedTouches&&e.changedTouches[0]||e.touches&&e.touches[0];return t?{x:t.clientX,y:t.clientY,time:Date.now()}:null;}
|
|
20532
20532
|
function selected(){return Boolean(String(win.getSelection()||'').trim()) || config.blocked();}
|
|
20533
|
-
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay]'));}
|
|
20533
|
+
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay],[data-papyrus-ink-capture]'));}
|
|
20534
20534
|
function begin(e){start=point(e);blocked=e.touches.length!==1 || selected() || interactive(e.target);}
|
|
20535
20535
|
function invalidateScroll(finish){if(config.current() && start && finish && config.mode()==='chapter-scroll' && !blocked && !selected() && Math.abs(finish.y-start.y)>12 && Math.abs(finish.y-start.y)>Math.abs(finish.x-start.x) && config.interact)config.interact();}
|
|
20536
20536
|
function move(e){if(e.touches.length!==1)blocked=true;invalidateScroll(point(e));}
|
|
@@ -20555,6 +20555,84 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20555
20555
|
typeof anchor.href === 'string' && !/^(javascript|data):/i.test(anchor.href) &&
|
|
20556
20556
|
typeof anchor.quote === 'string' && anchor.quote.length > 0 && anchor.quote.length <= 100000;
|
|
20557
20557
|
}
|
|
20558
|
+
function simplifyPath(points, tolerance, maxPoints) {
|
|
20559
|
+
if (!Array.isArray(points) || points.length <= 2) return Array.isArray(points) ? points.slice() : [];
|
|
20560
|
+
tolerance = Number.isFinite(tolerance) ? Math.max(0, tolerance) : 1.5;
|
|
20561
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20562
|
+
var keep = new Uint8Array(points.length); keep[0] = 1; keep[points.length - 1] = 1;
|
|
20563
|
+
var stack = [[0, points.length - 1]], toleranceSquared = tolerance * tolerance;
|
|
20564
|
+
while (stack.length) {
|
|
20565
|
+
var interval = stack.pop(), first = interval[0], last = interval[1], a = points[first], b = points[last];
|
|
20566
|
+
var dx = b.x - a.x, dy = b.y - a.y, lengthSquared = dx * dx + dy * dy, maxDistance = toleranceSquared, split = -1;
|
|
20567
|
+
for (var i = first + 1; i < last; i++) {
|
|
20568
|
+
var p = points[i], ratio = lengthSquared ? Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared)) : 0;
|
|
20569
|
+
var px = a.x + ratio * dx, py = a.y + ratio * dy, ox = p.x - px, oy = p.y - py, distance = ox * ox + oy * oy;
|
|
20570
|
+
if (distance > maxDistance) { maxDistance = distance; split = i; }
|
|
20571
|
+
}
|
|
20572
|
+
if (split >= 0) { keep[split] = 1; stack.push([first, split], [split, last]); }
|
|
20573
|
+
}
|
|
20574
|
+
var result = []; for (var j = 0; j < points.length; j++) if (keep[j]) result.push(points[j]);
|
|
20575
|
+
if (result.length <= maxPoints) return result;
|
|
20576
|
+
var capped = []; for (var k = 0; k < maxPoints; k++) capped.push(result[Math.round(k * (result.length - 1) / (maxPoints - 1))]);
|
|
20577
|
+
return capped;
|
|
20578
|
+
}
|
|
20579
|
+
function compactGesturePoints(points, maxPoints) {
|
|
20580
|
+
if (!Array.isArray(points)) return [];
|
|
20581
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 1024;
|
|
20582
|
+
if (points.length <= maxPoints) return points.slice();
|
|
20583
|
+
var compacted = [];
|
|
20584
|
+
for (var i = 0; i < maxPoints; i++) compacted.push(points[Math.round(i * (points.length - 1) / (maxPoints - 1))]);
|
|
20585
|
+
return compacted;
|
|
20586
|
+
}
|
|
20587
|
+
function densifyPath(points, maxStep, maxPoints) {
|
|
20588
|
+
if (!Array.isArray(points) || !points.length) return [];
|
|
20589
|
+
if (points.length === 1) return points.slice();
|
|
20590
|
+
maxStep = Number.isFinite(maxStep) ? Math.max(1, maxStep) : 12;
|
|
20591
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20592
|
+
var cumulative = [0], total = 0;
|
|
20593
|
+
for (var i = 1; i < points.length; i++) {
|
|
20594
|
+
if (![points[i-1].x,points[i-1].y,points[i].x,points[i].y].every(Number.isFinite)) return [];
|
|
20595
|
+
total += Math.hypot(points[i].x-points[i-1].x, points[i].y-points[i-1].y);
|
|
20596
|
+
cumulative.push(total);
|
|
20597
|
+
}
|
|
20598
|
+
if (!total) return [points[0], points[points.length-1]];
|
|
20599
|
+
var intervals = Math.min(maxPoints-1, Math.max(1, Math.ceil(total/maxStep))), result = [], segment = 1;
|
|
20600
|
+
for (var sample = 0; sample <= intervals; sample++) {
|
|
20601
|
+
var distance = total*sample/intervals;
|
|
20602
|
+
while (segment < cumulative.length-1 && cumulative[segment] < distance) segment++;
|
|
20603
|
+
var start = points[segment-1], end = points[segment], span = cumulative[segment]-cumulative[segment-1];
|
|
20604
|
+
var ratio = span ? (distance-cumulative[segment-1])/span : 0;
|
|
20605
|
+
result.push({x:start.x+(end.x-start.x)*ratio,y:start.y+(end.y-start.y)*ratio});
|
|
20606
|
+
}
|
|
20607
|
+
return result;
|
|
20608
|
+
}
|
|
20609
|
+
function createSpatialIndex(entries, cellSize) {
|
|
20610
|
+
cellSize = Number.isFinite(cellSize) ? Math.max(8, cellSize) : 64;
|
|
20611
|
+
var cells = new Map();
|
|
20612
|
+
entries.forEach(function(entry) {
|
|
20613
|
+
var left = Math.floor(entry.left / cellSize), right = Math.floor(entry.right / cellSize);
|
|
20614
|
+
var top = Math.floor(entry.top / cellSize), bottom = Math.floor(entry.bottom / cellSize);
|
|
20615
|
+
for (var x = left; x <= right; x++) for (var y = top; y <= bottom; y++) {
|
|
20616
|
+
var key = x + ':' + y, bucket = cells.get(key); if (!bucket) { bucket = []; cells.set(key, bucket); } bucket.push(entry);
|
|
20617
|
+
}
|
|
20618
|
+
});
|
|
20619
|
+
return {cells:cells,cellSize:cellSize};
|
|
20620
|
+
}
|
|
20621
|
+
function queryNearestTextRect(index, x, y, maxDistance) {
|
|
20622
|
+
if (!index || !Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(maxDistance) || maxDistance < 0) return null;
|
|
20623
|
+
var size = index.cellSize, minX = Math.floor((x-maxDistance)/size), maxX = Math.floor((x+maxDistance)/size);
|
|
20624
|
+
var minY = Math.floor((y-maxDistance)/size), maxY = Math.floor((y+maxDistance)/size), seen = new Set(), best = null;
|
|
20625
|
+
for (var cx=minX; cx<=maxX; cx++) for (var cy=minY; cy<=maxY; cy++) {
|
|
20626
|
+
var bucket = index.cells.get(cx+':'+cy); if (!bucket) continue;
|
|
20627
|
+
bucket.forEach(function(entry) {
|
|
20628
|
+
if (seen.has(entry)) return; seen.add(entry);
|
|
20629
|
+
var nearestX = Math.max(entry.left,Math.min(entry.right,x)), nearestY = Math.max(entry.top,Math.min(entry.bottom,y));
|
|
20630
|
+
var dx=x-nearestX,dy=y-nearestY,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20631
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={entry:entry,distance:distance,x:nearestX,y:nearestY};
|
|
20632
|
+
});
|
|
20633
|
+
}
|
|
20634
|
+
return best;
|
|
20635
|
+
}
|
|
20558
20636
|
function textNodes(document) {
|
|
20559
20637
|
var walker = document.createTreeWalker(document.body, 4);
|
|
20560
20638
|
var nodes = [], text = '', node;
|
|
@@ -20604,13 +20682,205 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20604
20682
|
if(win.getComputedStyle(doc.body).position==='static')doc.body.style.position='relative';
|
|
20605
20683
|
doc.body.appendChild(overlay);
|
|
20606
20684
|
var registry = new Map(), hitRegions = [];
|
|
20685
|
+
var inkRegistry = new Map(), rangeCache = new Map(), spatialIndex = null, activeGesture = null, inkConfig = {enabled:false,preset:'ink'};
|
|
20686
|
+
var inkSvg = doc.createElementNS('http://www.w3.org/2000/svg','svg');
|
|
20687
|
+
inkSvg.setAttribute('data-papyrus-ink-overlay','');
|
|
20688
|
+
inkSvg.style.cssText = 'position:absolute;left:0;top:0;overflow:visible;pointer-events:none;z-index:1';
|
|
20689
|
+
overlay.appendChild(inkSvg);
|
|
20690
|
+
var previewSvg = doc.createElementNS('http://www.w3.org/2000/svg','svg');
|
|
20691
|
+
previewSvg.setAttribute('data-papyrus-ink-preview-overlay','');
|
|
20692
|
+
previewSvg.style.cssText = 'position:fixed;left:0;top:0;overflow:hidden;pointer-events:none;z-index:2147482999';
|
|
20693
|
+
doc.documentElement.appendChild(previewSvg);
|
|
20694
|
+
var inkCanvas = doc.createElement('canvas');
|
|
20695
|
+
inkCanvas.dataset.papyrusInkCapture = '';
|
|
20696
|
+
inkCanvas.style.cssText = 'position:fixed;left:0;top:0;width:1px;height:1px;z-index:2147483000;background:transparent;pointer-events:none;touch-action:none';
|
|
20697
|
+
doc.documentElement.appendChild(inkCanvas);
|
|
20698
|
+
var inkContext = null; try { if(typeof win.CanvasRenderingContext2D==='function')inkContext = inkCanvas.getContext('2d'); } catch (_) {}
|
|
20699
|
+
function resizeCanvas() {
|
|
20700
|
+
var ratio = Math.max(1,Math.min(3,win.devicePixelRatio || 1));
|
|
20701
|
+
var width=Math.max(1,Math.min(4096,win.innerWidth||1));
|
|
20702
|
+
var height=Math.max(1,Math.min(4096,win.innerHeight||1));
|
|
20703
|
+
inkCanvas.style.width=width+'px';inkCanvas.style.height=height+'px';
|
|
20704
|
+
previewSvg.setAttribute('width',String(width));previewSvg.setAttribute('height',String(height));
|
|
20705
|
+
previewSvg.setAttribute('viewBox','0 0 '+width+' '+height);
|
|
20706
|
+
inkCanvas.width = Math.round(width*ratio); inkCanvas.height = Math.round(height*ratio);
|
|
20707
|
+
if (inkContext) { inkContext.setTransform(ratio,0,0,ratio,0,0); inkContext.clearRect(0,0,width,height); }
|
|
20708
|
+
}
|
|
20709
|
+
function collectTextRects() {
|
|
20710
|
+
var walker = doc.createTreeWalker(doc.body,4), node, entries=[];
|
|
20711
|
+
while ((node=walker.nextNode())) {
|
|
20712
|
+
var parent=node.parentElement;
|
|
20713
|
+
if (!parent || parent.closest('script,style,noscript,textarea,[data-papyrus-overlay],[data-papyrus-ink-capture]')) continue;
|
|
20714
|
+
var text=node.nodeValue || '', style=win.getComputedStyle(parent), computed=parseFloat(style.lineHeight);
|
|
20715
|
+
for (var start=0; start<text.length;) {
|
|
20716
|
+
var end=Math.min(text.length,start+24), last=text.charCodeAt(end-1), next=text.charCodeAt(end);
|
|
20717
|
+
if(end<text.length&&last>=0xD800&&last<=0xDBFF&&next>=0xDC00&&next<=0xDFFF)end++;
|
|
20718
|
+
var range=doc.createRange(); range.setStart(node,start); range.setEnd(node,end);
|
|
20719
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20720
|
+
rects.forEach(function(rect) {
|
|
20721
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20722
|
+
entries.push({left:rect.left+win.scrollX,top:rect.top+win.scrollY,right:rect.right+win.scrollX,bottom:rect.bottom+win.scrollY,width:rect.width,height:rect.height,
|
|
20723
|
+
node:node,start:start,end:end,lineHeight:Number.isFinite(computed)&&computed>0?computed:rect.height});
|
|
20724
|
+
});
|
|
20725
|
+
start=end;
|
|
20726
|
+
}
|
|
20727
|
+
}
|
|
20728
|
+
return entries;
|
|
20729
|
+
}
|
|
20730
|
+
function rebuildSpatialIndex() { spatialIndex=createSpatialIndex(collectTextRects(),64); rangeCache.clear(); }
|
|
20731
|
+
function inkViewportExtent() {
|
|
20732
|
+
var root=doc.documentElement,body=doc.body,bodyRect=body.getBoundingClientRect();
|
|
20733
|
+
var width=root.clientWidth||body.clientWidth||bodyRect.width||win.innerWidth||1;
|
|
20734
|
+
var height=root.clientHeight||body.clientHeight||bodyRect.height||win.innerHeight||1;
|
|
20735
|
+
return Math.max(1,Math.min(4096,width),Math.min(4096,height));
|
|
20736
|
+
}
|
|
20737
|
+
function inkStrokeWidthPx(width,preset) {
|
|
20738
|
+
var scale=preset==='highlight'?0.8:preset==='underline'?0.1:0.15;
|
|
20739
|
+
return Math.max(1,Math.min(24,(Number.isFinite(width)?width:0.006)*inkViewportExtent()*scale));
|
|
20740
|
+
}
|
|
20741
|
+
function closestGlyph(entry,x,y,maxDistance) {
|
|
20742
|
+
var source=(entry.node.nodeValue || '').slice(entry.start,entry.end), best=null, offset=0;
|
|
20743
|
+
for (var glyph of source) {
|
|
20744
|
+
var range=doc.createRange(); range.setStart(entry.node,entry.start+offset); range.setEnd(entry.node,entry.start+offset+glyph.length); offset+=glyph.length;
|
|
20745
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20746
|
+
rects.forEach(function(rect) {
|
|
20747
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20748
|
+
var nx=Math.max(rect.left+win.scrollX,Math.min(rect.right+win.scrollX,x)), ny=Math.max(rect.top+win.scrollY,Math.min(rect.bottom+win.scrollY,y));
|
|
20749
|
+
var dx=x-nx,dy=y-ny,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20750
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={range:range,rect:rect,distance:distance};
|
|
20751
|
+
});
|
|
20752
|
+
}
|
|
20753
|
+
if (!best || typeof contents.cfiFromRange!=='function') return null;
|
|
20754
|
+
var quote=best.range.toString(), cfiRange; try { cfiRange=contents.cfiFromRange(best.range); } catch (_) { return null; }
|
|
20755
|
+
if (!quote || typeof cfiRange!=='string' || !/^epubcfi\([^\n<>]+\)$/.test(cfiRange)) return null;
|
|
20756
|
+
var lineHeight=Math.max(1,entry.lineHeight || best.rect.height), px=x-(best.rect.left+win.scrollX), py=y-(best.rect.top+win.scrollY);
|
|
20757
|
+
return {cfiRange:cfiRange,quote:quote,x:Math.max(-3,Math.min(3,px/lineHeight)),y:Math.max(-3,Math.min(3,py/lineHeight))};
|
|
20758
|
+
}
|
|
20759
|
+
function renderInkAnnotation(annotation,keep,bodyRect) {
|
|
20760
|
+
var baseRect=bodyRect || doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20761
|
+
var data=annotation.epubInk;
|
|
20762
|
+
if (!data || data.version!==1 || data.kind!=='epub-ink' || !Array.isArray(data.segments)) return;
|
|
20763
|
+
keep.add(annotation.id);
|
|
20764
|
+
var group=inkRegistry.get(annotation.id);
|
|
20765
|
+
if (!group) { group=doc.createElementNS('http://www.w3.org/2000/svg','g'); group.setAttribute('data-epub-ink-id',annotation.id); inkSvg.appendChild(group); inkRegistry.set(annotation.id,group); }
|
|
20766
|
+
group.replaceChildren();
|
|
20767
|
+
var color=/^#[0-9a-f]{6}$/i.test(annotation.color)?annotation.color:'#2563eb';
|
|
20768
|
+
var opacity=Number.isFinite(annotation.opacity)?Math.max(0,Math.min(1,annotation.opacity)):1;
|
|
20769
|
+
var preset=['ink','highlight','underline'].indexOf(data.preset)>=0?data.preset:'ink';
|
|
20770
|
+
var stroke=inkStrokeWidthPx(annotation.strokeWidth,preset);
|
|
20771
|
+
data.segments.forEach(function(segment) {
|
|
20772
|
+
if (segment.href!==options.href || !Array.isArray(segment.points)) return;
|
|
20773
|
+
var paths=[], current=[];
|
|
20774
|
+
segment.points.forEach(function(point) {
|
|
20775
|
+
var range=rangeCache.get(point.cfiRange);
|
|
20776
|
+
if (!range) { try { range=contents.range(point.cfiRange); } catch (_) { range=null; } if (range) rangeCache.set(point.cfiRange,range); }
|
|
20777
|
+
if (!range || range.toString()!==point.quote) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20778
|
+
var rect; try { rect=range.getBoundingClientRect(); } catch (_) { rect=null; }
|
|
20779
|
+
if (!rect || !(rect.width>0 && rect.height>0)) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20780
|
+
var lineHeight=Math.max(1,rect.height), x=rect.left-baseRect.left+point.x*lineHeight, y=rect.top-baseRect.top+point.y*lineHeight;
|
|
20781
|
+
var previous=current[current.length-1], jumpLimit=Math.max(24,lineHeight*2.5);
|
|
20782
|
+
if (previous && Math.hypot(x-previous.x,y-previous.y)>jumpLimit) { if(current.length>1)paths.push(current);current=[]; }
|
|
20783
|
+
current.push({x:x,y:y,lineHeight:lineHeight});
|
|
20784
|
+
});
|
|
20785
|
+
if(current.length>1)paths.push(current);
|
|
20786
|
+
paths.forEach(function(points) {
|
|
20787
|
+
var d='M '+points[0].x.toFixed(1)+' '+points[0].y.toFixed(1);
|
|
20788
|
+
for(var i=1;i<points.length;i++){var prev=points[i-1],point=points[i],mx=(prev.x+point.x)/2,my=(prev.y+point.y)/2;d+=' Q '+prev.x.toFixed(1)+' '+prev.y.toFixed(1)+' '+mx.toFixed(1)+' '+my.toFixed(1);}
|
|
20789
|
+
var last=points[points.length-1];d+=' L '+last.x.toFixed(1)+' '+last.y.toFixed(1);
|
|
20790
|
+
var path=doc.createElementNS('http://www.w3.org/2000/svg','path');path.setAttribute('d',d);path.setAttribute('fill','none');path.setAttribute('stroke',color);path.setAttribute('stroke-width',String(stroke));path.setAttribute('stroke-linecap','round');path.setAttribute('stroke-linejoin','round');path.setAttribute('opacity',String(opacity));group.appendChild(path);
|
|
20791
|
+
});
|
|
20792
|
+
});
|
|
20793
|
+
}
|
|
20794
|
+
function clearPreview() {
|
|
20795
|
+
if(inkContext)inkContext.clearRect(0,0,inkCanvas.width,inkCanvas.height);
|
|
20796
|
+
previewSvg.replaceChildren();
|
|
20797
|
+
}
|
|
20798
|
+
function createPreviewPath(x,y) {
|
|
20799
|
+
var path=doc.createElementNS('http://www.w3.org/2000/svg','path');
|
|
20800
|
+
path.setAttribute('data-papyrus-ink-preview','');path.setAttribute('d','M '+x.toFixed(1)+' '+y.toFixed(1));path.setAttribute('fill','none');
|
|
20801
|
+
path.setAttribute('stroke',inkConfig.color);path.setAttribute('stroke-width',String(inkStrokeWidthPx(inkConfig.strokeWidth,inkConfig.preset)));
|
|
20802
|
+
path.setAttribute('stroke-linecap','round');path.setAttribute('stroke-linejoin','round');path.setAttribute('opacity',String(inkConfig.opacity));
|
|
20803
|
+
path.style.pointerEvents='none';previewSvg.appendChild(path);return path;
|
|
20804
|
+
}
|
|
20805
|
+
function updatePreviewPath(clientX,clientY) {
|
|
20806
|
+
var x=clientX,y=clientY;
|
|
20807
|
+
var gesture=activeGesture;
|
|
20808
|
+
var startsSegment=!gesture.previewPath||gesture.previewPathPoints>=32;
|
|
20809
|
+
if(startsSegment){
|
|
20810
|
+
gesture.previewPath=createPreviewPath(gesture.previewLast?gesture.previewLast.x:x,gesture.previewLast?gesture.previewLast.y:y);
|
|
20811
|
+
gesture.previewPathPoints=1;
|
|
20812
|
+
}
|
|
20813
|
+
if(!startsSegment||gesture.previewLast){
|
|
20814
|
+
var pathData=gesture.previewPath.getAttribute('d')||'';
|
|
20815
|
+
gesture.previewPath.setAttribute('d',pathData+' L '+x.toFixed(1)+' '+y.toFixed(1));
|
|
20816
|
+
gesture.previewPathPoints++;
|
|
20817
|
+
}
|
|
20818
|
+
gesture.previewLast={x:x,y:y};
|
|
20819
|
+
}
|
|
20820
|
+
function cancelGesture() {
|
|
20821
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20822
|
+
if(gesture)try{inkCanvas.releasePointerCapture(gesture.pointerId);}catch(_){}
|
|
20823
|
+
}
|
|
20824
|
+
function commitGesture() {
|
|
20825
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20826
|
+
if(!gesture || !alive || !options.isCurrent() || !inkConfig.enabled || !spatialIndex) return;
|
|
20827
|
+
var simplified=simplifyPath(gesture.points,1.5,512), anchorSamples=densifyPath(simplified,12,512), segments=[], current=[];
|
|
20828
|
+
anchorSamples.forEach(function(point) {
|
|
20829
|
+
var coarse=queryNearestTextRect(spatialIndex,point.x,point.y,28);
|
|
20830
|
+
var cutoff=coarse?Math.max(12,Math.min(28,0.8*coarse.entry.lineHeight)):12;
|
|
20831
|
+
var anchored=coarse && closestGlyph(coarse.entry,point.x,point.y,cutoff);
|
|
20832
|
+
if(!anchored){if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});current=[];return;}
|
|
20833
|
+
current.push(anchored);
|
|
20834
|
+
});
|
|
20835
|
+
if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});
|
|
20836
|
+
segments=segments.slice(0,64);
|
|
20837
|
+
var pointCount=segments.reduce(function(total,segment){return total+segment.points.length;},0);
|
|
20838
|
+
if(!pointCount)return;
|
|
20839
|
+
var width=Math.max(1,doc.documentElement.scrollWidth,win.innerWidth),height=Math.max(1,doc.documentElement.scrollHeight,win.innerHeight);
|
|
20840
|
+
var normalized=simplified.map(function(p){return {x:Math.max(0,Math.min(1,p.x/width)),y:Math.max(0,Math.min(1,p.y/height))};});
|
|
20841
|
+
var minX=Math.min.apply(null,normalized.map(function(p){return p.x;})),maxX=Math.max.apply(null,normalized.map(function(p){return p.x;}));
|
|
20842
|
+
var minY=Math.min.apply(null,normalized.map(function(p){return p.y;})),maxY=Math.max.apply(null,normalized.map(function(p){return p.y;}));
|
|
20843
|
+
var first=segments[0].points[0], href=segments[0].href, documentId=typeof options.documentId==='function'?options.documentId():options.documentId;
|
|
20844
|
+
var annotation={id:'epub-ink-'+Date.now()+'-'+Math.random().toString(36).slice(2,9),type:'ink',pageIndex:(options.spineIndex||0)+1,
|
|
20845
|
+
rect:{x:minX,y:minY,width:Math.min(1-minX,Math.max(0.001,maxX-minX)),height:Math.min(1-minY,Math.max(0.001,maxY-minY))},path:normalized,color:inkConfig.color,opacity:inkConfig.opacity,strokeWidth:inkConfig.strokeWidth,createdAt:Date.now(),content:first.quote,
|
|
20846
|
+
anchor:{version:1,kind:'epub-cfi',cfiRange:first.cfiRange,href:href,spineIndex:options.spineIndex,documentId:documentId,quote:first.quote},
|
|
20847
|
+
epubInk:{version:1,kind:'epub-ink',documentId:documentId,preset:inkConfig.preset,segments:segments}};
|
|
20848
|
+
if(typeof options.onInkCommit==='function')options.onInkCommit(annotation);
|
|
20849
|
+
}
|
|
20850
|
+
function pointerDown(event) {
|
|
20851
|
+
if(!inkConfig.enabled || !alive || !options.isCurrent() || event.button!==undefined && event.button!==0)return;
|
|
20852
|
+
if(activeGesture){cancelGesture();return;}
|
|
20853
|
+
event.preventDefault();event.stopPropagation();
|
|
20854
|
+
activeGesture={pointerId:event.pointerId,points:[{x:event.clientX+win.scrollX,y:event.clientY+win.scrollY}],last:{x:event.clientX,y:event.clientY},previewPath:null,previewPathPoints:0,previewLast:null};
|
|
20855
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20856
|
+
try{inkCanvas.setPointerCapture(event.pointerId);}catch(_){}
|
|
20857
|
+
}
|
|
20858
|
+
function pointerMove(event) {
|
|
20859
|
+
if(!activeGesture || activeGesture.pointerId!==event.pointerId)return;
|
|
20860
|
+
if(!options.isCurrent()||!inkConfig.enabled){cancelGesture();return;}
|
|
20861
|
+
event.preventDefault();event.stopPropagation();
|
|
20862
|
+
var point={x:event.clientX+win.scrollX,y:event.clientY+win.scrollY};activeGesture.points.push(point);
|
|
20863
|
+
if(activeGesture.points.length>2048)activeGesture.points=compactGesturePoints(activeGesture.points,1024);
|
|
20864
|
+
if(inkContext){inkContext.beginPath();inkContext.moveTo(activeGesture.last.x,activeGesture.last.y);inkContext.lineTo(event.clientX,event.clientY);inkContext.strokeStyle=inkConfig.color;inkContext.globalAlpha=inkConfig.opacity;inkContext.lineWidth=inkStrokeWidthPx(inkConfig.strokeWidth,inkConfig.preset);inkContext.lineCap='round';inkContext.lineJoin='round';inkContext.stroke();}
|
|
20865
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20866
|
+
activeGesture.last={x:event.clientX,y:event.clientY};
|
|
20867
|
+
}
|
|
20868
|
+
function pointerUp(event) {if(!activeGesture || activeGesture.pointerId!==event.pointerId)return;event.preventDefault();event.stopPropagation();var end={x:event.clientX+win.scrollX,y:event.clientY+win.scrollY},last=activeGesture.points[activeGesture.points.length-1];if(Math.hypot(end.x-last.x,end.y-last.y)>0.5){activeGesture.points.push(end);updatePreviewPath(event.clientX,event.clientY);}commitGesture();}
|
|
20869
|
+
function pointerCancel(event) {if(activeGesture && (event.pointerId===undefined || activeGesture.pointerId===event.pointerId))cancelGesture();}
|
|
20870
|
+
resizeCanvas();rebuildSpatialIndex();
|
|
20871
|
+
inkCanvas.addEventListener('pointerdown',pointerDown);inkCanvas.addEventListener('pointermove',pointerMove);inkCanvas.addEventListener('pointerup',pointerUp);inkCanvas.addEventListener('pointercancel',pointerCancel);inkCanvas.addEventListener('lostpointercapture',pointerCancel);
|
|
20872
|
+
win.addEventListener('blur',pointerCancel);
|
|
20607
20873
|
function render() {
|
|
20608
20874
|
frame = 0; if (!alive || !options.isCurrent()) return;
|
|
20609
|
-
var keep = new Set(), noteGroups = new Map();
|
|
20875
|
+
var keep = new Set(), keepInk = new Set(), noteGroups = new Map();
|
|
20610
20876
|
hitRegions = [];
|
|
20877
|
+
var bodyRect=doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20878
|
+
inkSvg.setAttribute('width',String(Math.max(doc.documentElement.scrollWidth,win.innerWidth)));
|
|
20879
|
+
inkSvg.setAttribute('height',String(Math.max(doc.documentElement.scrollHeight,win.innerHeight)));
|
|
20611
20880
|
options.annotations().forEach(function(annotation) {
|
|
20612
20881
|
var anchor = annotation.anchor;
|
|
20613
20882
|
if (!validAnchor(anchor) || anchor.href !== options.href || anchor.documentId && options.documentId && anchor.documentId !== options.documentId) return;
|
|
20883
|
+
if(annotation.type==='ink' && annotation.epubInk){renderInkAnnotation(annotation,keepInk,bodyRect);return;}
|
|
20614
20884
|
var range = resolveRange(contents,anchor); if (!range) return;
|
|
20615
20885
|
var rects = Array.from(range.getClientRects()).filter(function(r){return r.width>0 && r.height>0;});
|
|
20616
20886
|
if (!rects.length) return;
|
|
@@ -20649,22 +20919,26 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20649
20919
|
group.button.addEventListener('click',function(e){e.stopPropagation();if(options.isCurrent())options.onTap(group.ids[0],group.ids);});
|
|
20650
20920
|
});
|
|
20651
20921
|
registry.forEach(function(group,id){if (!keep.has(id)) {group.remove();registry.delete(id);}});
|
|
20922
|
+
inkRegistry.forEach(function(group,id){if (!keepInk.has(id)) {group.remove();inkRegistry.delete(id);}});
|
|
20652
20923
|
}
|
|
20653
20924
|
function schedule() { if (alive && !frame) frame = win.requestAnimationFrame(render); }
|
|
20925
|
+
function rebuildAndSchedule(){if(!alive)return;rebuildSpatialIndex();schedule();}
|
|
20926
|
+
function handleResize(){resizeCanvas();rebuildAndSchedule();}
|
|
20927
|
+
function handleDocumentLoad(){rebuildAndSchedule();}
|
|
20654
20928
|
function tapMarkup(event) {
|
|
20655
20929
|
if(!alive || !options.isCurrent() || String(win.getSelection() || '').length || event.target.closest('[data-papyrus-overlay]'))return;
|
|
20656
20930
|
var hit=hitRegions.find(function(item){return item.rects.some(function(r){return event.clientX>=r.left && event.clientX<=r.right && event.clientY>=r.top && event.clientY<=r.bottom;});});
|
|
20657
20931
|
if(hit) {event.stopPropagation();options.onTap(hit.id);}
|
|
20658
20932
|
}
|
|
20659
20933
|
doc.addEventListener('click',tapMarkup);
|
|
20660
|
-
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(
|
|
20934
|
+
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(rebuildAndSchedule) : null;
|
|
20661
20935
|
if (observer) observer.observe(doc.body);
|
|
20662
|
-
win.addEventListener('resize',
|
|
20663
|
-
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(schedule);
|
|
20936
|
+
win.addEventListener('resize',handleResize);win.addEventListener('scroll',schedule); doc.addEventListener('load',handleDocumentLoad,true);
|
|
20937
|
+
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(function(){if(alive){rebuildSpatialIndex();schedule();}});
|
|
20664
20938
|
schedule();
|
|
20665
|
-
return {schedule:schedule, hit:function(x,y){return hitRegions.some(function(item){return item.rects.some(function(r){return x>=r.left && x<=r.right && y>=r.top && y<=r.bottom;});});}, range:function(anchor){return resolveRange(contents,anchor);}, destroy:function(){alive=false;if(frame)win.cancelAnimationFrame(frame);if(observer)observer.disconnect();win.removeEventListener('resize',
|
|
20939
|
+
return {schedule:schedule, setInkMode:function(config){var preset=['ink','highlight','underline'].indexOf(config?.preset)>=0?config.preset:'ink';inkConfig={enabled:!!config?.enabled,preset:preset,color:/^#[0-9a-f]{6}$/i.test(config?.color)?config.color:'#2563eb',opacity:Number.isFinite(config?.opacity)?Math.max(0,Math.min(1,config.opacity)):1,strokeWidth:Number.isFinite(config?.strokeWidth)?Math.max(0.0025,Math.min(0.02,config.strokeWidth)):0.006};inkCanvas.style.pointerEvents=inkConfig.enabled?'auto':'none';if(!inkConfig.enabled)cancelGesture();}, invalidateLayout:rebuildAndSchedule, hit:function(x,y){return hitRegions.some(function(item){return item.rects.some(function(r){return x>=r.left && x<=r.right && y>=r.top && y<=r.bottom;});});}, range:function(anchor){return resolveRange(contents,anchor);}, destroy:function(){alive=false;cancelGesture();if(frame)win.cancelAnimationFrame(frame);if(observer)observer.disconnect();win.removeEventListener('resize',handleResize);win.removeEventListener('scroll',schedule);win.removeEventListener('blur',pointerCancel);doc.removeEventListener('load',handleDocumentLoad,true);doc.removeEventListener('click',tapMarkup);inkCanvas.removeEventListener('pointerdown',pointerDown);inkCanvas.removeEventListener('pointermove',pointerMove);inkCanvas.removeEventListener('pointerup',pointerUp);inkCanvas.removeEventListener('pointercancel',pointerCancel);inkCanvas.removeEventListener('lostpointercapture',pointerCancel);inkCanvas.remove();previewSvg.remove();overlay.remove();doc.body.style.position=originalPosition;registry.clear();inkRegistry.clear();rangeCache.clear();}};
|
|
20666
20940
|
}
|
|
20667
|
-
return {validAnchor:validAnchor,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20941
|
+
return {validAnchor:validAnchor,simplifyPath:simplifyPath,compactGesturePoints:compactGesturePoints,densifyPath:densifyPath,createSpatialIndex:createSpatialIndex,queryNearestTextRect:queryNearestTextRect,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20668
20942
|
});
|
|
20669
20943
|
|
|
20670
20944
|
/* @papyrus-epub-annotations:end */
|
|
@@ -20680,6 +20954,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20680
20954
|
let annotationDocumentId;
|
|
20681
20955
|
let annotationLabels = {};
|
|
20682
20956
|
let epubAnnotations = [];
|
|
20957
|
+
let epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
20683
20958
|
const epubAnnotationRenderers = new Map();
|
|
20684
20959
|
let spineItems = [];
|
|
20685
20960
|
let textPages = [];
|
|
@@ -21794,11 +22069,14 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21794
22069
|
if (href && window.PapyrusEpubAnnotations) {
|
|
21795
22070
|
const renderer = window.PapyrusEpubAnnotations.install(contents, {
|
|
21796
22071
|
href, get documentId() { return annotationDocumentId; },
|
|
22072
|
+
spineIndex:contents.sectionIndex,
|
|
21797
22073
|
isCurrent: () => session === documentSessionId && activeRendition === rendition,
|
|
21798
22074
|
pageWidth: () => activeRendition.layout?.width || viewer.clientWidth,
|
|
21799
22075
|
annotations: () => epubAnnotations, labels: () => annotationLabels,
|
|
22076
|
+
onInkCommit: annotation => sendEvent('EPUB_INK_CREATED',{documentSessionId:session,annotation}),
|
|
21800
22077
|
onTap: (id, ids) => sendEvent("EPUB_ANNOTATION_TAP", {documentSessionId: session, id, ids}),
|
|
21801
22078
|
});
|
|
22079
|
+
renderer.setInkMode(epubInkMode);
|
|
21802
22080
|
epubAnnotationRenderers.set(contents,renderer);
|
|
21803
22081
|
}
|
|
21804
22082
|
const frame = contents && contents.document ? contents.document.defaultView.frameElement : null;
|
|
@@ -21890,7 +22168,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21890
22168
|
sendEvent('EPUB_TEXT_SELECTED', payload);
|
|
21891
22169
|
});
|
|
21892
22170
|
['rendered','resized','layout','relocated'].forEach(name => rendition.on(name, () => {
|
|
21893
|
-
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
22171
|
+
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => name==='relocated'?renderer.schedule():renderer.invalidateLayout());
|
|
21894
22172
|
}));
|
|
21895
22173
|
rendition.on('relocated', (location) => {
|
|
21896
22174
|
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
@@ -22187,6 +22465,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22187
22465
|
documentSessionId = payload.documentSessionId || null;
|
|
22188
22466
|
epubAnnotations = [];
|
|
22189
22467
|
annotationDocumentId = undefined;
|
|
22468
|
+
epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
22190
22469
|
zoom = 1.0;
|
|
22191
22470
|
epubViewMode = payload.epubMode === "chapter-scroll" ? "continuous" : "single";
|
|
22192
22471
|
epubLocation = null;
|
|
@@ -22318,6 +22597,12 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22318
22597
|
}
|
|
22319
22598
|
sendResponse(id,true,null);return;
|
|
22320
22599
|
}
|
|
22600
|
+
if (kind === 'set-epub-ink-mode') {
|
|
22601
|
+
if(currentType!=='epub'||!documentSessionId||payload.documentSessionId!==documentSessionId)throw new Error('Stale EPUB ink session');
|
|
22602
|
+
epubInkMode={enabled:payload.enabled===true,preset:['ink','highlight','underline'].indexOf(payload.preset)>=0?payload.preset:'ink',color:/^#[0-9a-f]{6}$/i.test(payload.color||'')?payload.color:'#2563eb',opacity:Number.isFinite(payload.opacity)?Math.max(0,Math.min(1,payload.opacity)):1,strokeWidth:Number.isFinite(payload.strokeWidth)?Math.max(0.0025,Math.min(0.02,payload.strokeWidth)):0.006};
|
|
22603
|
+
epubAnnotationRenderers.forEach(renderer=>renderer.setInkMode(epubInkMode));
|
|
22604
|
+
sendResponse(id,true,null);return;
|
|
22605
|
+
}
|
|
22321
22606
|
if(kind === 'epub-go-to-location'){
|
|
22322
22607
|
if(currentType!=='epub' || payload.documentSessionId!==documentSessionId || !window.PapyrusEpubReader.validCfi(payload.cfi))throw new Error('Invalid EPUB location');
|
|
22323
22608
|
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(()=>{if(payload.documentSessionId!==documentSessionId)return;epubResizeAnchor?.invalidate();return rendition.display(payload.cfi);});
|