docnest 0.1.14 → 0.1.15
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/package.json
CHANGED
|
@@ -179,13 +179,26 @@ body {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
.doc-pdf-export-root {
|
|
182
|
+
/* PDF pages use a light paper palette, independently of the live reading mode. */
|
|
183
|
+
--linear-bg: #ffffff;
|
|
184
|
+
--linear-bg-subtle: #fafafa;
|
|
185
|
+
--linear-border: #e5e5e5;
|
|
186
|
+
--linear-text: #111111;
|
|
187
|
+
--linear-text-muted: #6b6b6b;
|
|
188
|
+
--linear-accent: #5e6ad2;
|
|
189
|
+
--linear-accent-hover: #4c57b8;
|
|
190
|
+
--doc-surface-raised: #ffffff;
|
|
191
|
+
--doc-rule-strong: #bfc0c5;
|
|
192
|
+
--doc-accent-soft: rgba(94, 106, 210, 0.12);
|
|
193
|
+
--doc-code-bg: #f6f7f8;
|
|
194
|
+
--doc-code-text: #24262b;
|
|
182
195
|
position: absolute;
|
|
183
196
|
left: 0;
|
|
184
197
|
top: 0;
|
|
185
198
|
width: 960px;
|
|
186
199
|
padding: 24px 32px;
|
|
187
|
-
background:
|
|
188
|
-
color:
|
|
200
|
+
background: var(--doc-surface-raised);
|
|
201
|
+
color: var(--linear-text);
|
|
189
202
|
z-index: -1;
|
|
190
203
|
pointer-events: none;
|
|
191
204
|
overflow: visible;
|
|
@@ -379,7 +379,8 @@ body[data-doc-theme][data-theme="dark"] .pdf-export-modal__btn {
|
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
/* Theme 01: Slate Modern — the package's original visual language. */
|
|
382
|
-
body[data-doc-theme="slate-modern"]
|
|
382
|
+
body[data-doc-theme="slate-modern"],
|
|
383
|
+
.doc-pdf-export-root[data-doc-theme="slate-modern"] {
|
|
383
384
|
--doc-font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
|
384
385
|
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
385
386
|
--doc-font-reading: var(--doc-font-ui);
|
|
@@ -387,7 +388,8 @@ body[data-doc-theme="slate-modern"] {
|
|
|
387
388
|
}
|
|
388
389
|
|
|
389
390
|
/* Theme 02: Editorial Atlas */
|
|
390
|
-
body[data-doc-theme="editorial-atlas"]
|
|
391
|
+
body[data-doc-theme="editorial-atlas"],
|
|
392
|
+
.doc-pdf-export-root[data-doc-theme="editorial-atlas"] {
|
|
391
393
|
--linear-bg: #f3f0e7;
|
|
392
394
|
--linear-bg-subtle: #ebe6da;
|
|
393
395
|
--linear-sidebar: #eee9dd;
|
|
@@ -490,7 +492,8 @@ body[data-doc-theme="editorial-atlas"] .doc-toc {
|
|
|
490
492
|
}
|
|
491
493
|
|
|
492
494
|
/* Theme 03: Precision Index */
|
|
493
|
-
body[data-doc-theme="precision-index"]
|
|
495
|
+
body[data-doc-theme="precision-index"],
|
|
496
|
+
.doc-pdf-export-root[data-doc-theme="precision-index"] {
|
|
494
497
|
--linear-bg: #eef2f3;
|
|
495
498
|
--linear-bg-subtle: #e4eaec;
|
|
496
499
|
--linear-sidebar: #e9eef0;
|
|
@@ -640,7 +643,8 @@ body[data-doc-theme="precision-index"] .doc-toc-title {
|
|
|
640
643
|
}
|
|
641
644
|
|
|
642
645
|
/* Theme 04: Archive Room */
|
|
643
|
-
body[data-doc-theme="archive-room"]
|
|
646
|
+
body[data-doc-theme="archive-room"],
|
|
647
|
+
.doc-pdf-export-root[data-doc-theme="archive-room"] {
|
|
644
648
|
--linear-bg: #f3efe4;
|
|
645
649
|
--linear-bg-subtle: #e9e2d3;
|
|
646
650
|
--linear-sidebar: #ebe5d8;
|
|
@@ -775,7 +779,8 @@ body[data-doc-theme="archive-room"] .doc-toc {
|
|
|
775
779
|
}
|
|
776
780
|
|
|
777
781
|
/* Theme 05: Swiss Manual */
|
|
778
|
-
body[data-doc-theme="swiss-manual"]
|
|
782
|
+
body[data-doc-theme="swiss-manual"],
|
|
783
|
+
.doc-pdf-export-root[data-doc-theme="swiss-manual"] {
|
|
779
784
|
--linear-bg: #f4f3ef;
|
|
780
785
|
--linear-bg-subtle: #e9e7e0;
|
|
781
786
|
--linear-sidebar: #eeece6;
|
|
@@ -93,9 +93,40 @@
|
|
|
93
93
|
function createExportRoot(article) {
|
|
94
94
|
var root = document.createElement('div');
|
|
95
95
|
root.className = EXPORT_CLASS;
|
|
96
|
+
root.setAttribute('data-doc-theme', document.body.getAttribute('data-doc-theme') || 'slate-modern');
|
|
97
|
+
root.setAttribute('data-theme', 'light');
|
|
96
98
|
|
|
97
99
|
var clone = article.cloneNode(true);
|
|
98
100
|
removeTransientNodes(clone);
|
|
101
|
+
// html2canvas may paint closed <details> descendants without reserving their
|
|
102
|
+
// height. Export static, expanded sections while leaving the live page alone.
|
|
103
|
+
Array.prototype.slice.call(clone.querySelectorAll('details')).reverse().forEach(function(details) {
|
|
104
|
+
var section = document.createElement('section');
|
|
105
|
+
Array.prototype.slice.call(details.attributes).forEach(function(attribute) {
|
|
106
|
+
if (attribute.name !== 'open') section.setAttribute(attribute.name, attribute.value);
|
|
107
|
+
});
|
|
108
|
+
section.style.display = 'block';
|
|
109
|
+
section.style.height = 'auto';
|
|
110
|
+
section.style.maxHeight = 'none';
|
|
111
|
+
section.style.overflow = 'visible';
|
|
112
|
+
section.style.margin = '1em 0';
|
|
113
|
+
while (details.firstChild) {
|
|
114
|
+
var child = details.firstChild;
|
|
115
|
+
if (child.tagName === 'SUMMARY') {
|
|
116
|
+
var heading = document.createElement('div');
|
|
117
|
+
heading.className = 'doc-pdf-section-title';
|
|
118
|
+
heading.style.fontWeight = '700';
|
|
119
|
+
heading.style.marginBottom = '12px';
|
|
120
|
+
while (child.firstChild) heading.appendChild(child.firstChild);
|
|
121
|
+
section.appendChild(heading);
|
|
122
|
+
details.removeChild(child);
|
|
123
|
+
} else {
|
|
124
|
+
section.appendChild(child);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
details.parentNode.replaceChild(section, details);
|
|
128
|
+
});
|
|
129
|
+
clone.querySelectorAll('img').forEach(function(img) { img.loading = 'eager'; });
|
|
99
130
|
root.appendChild(clone);
|
|
100
131
|
document.body.appendChild(root);
|
|
101
132
|
|
|
@@ -137,18 +168,60 @@
|
|
|
137
168
|
return breakpoints;
|
|
138
169
|
}
|
|
139
170
|
|
|
171
|
+
function collectProtectedRegions(root, canvasScale) {
|
|
172
|
+
var rootRect = root.getBoundingClientRect();
|
|
173
|
+
var regions = [];
|
|
174
|
+
root.querySelectorAll('img, svg, canvas, figure, .mermaid').forEach(function(node) {
|
|
175
|
+
var rect = node.getBoundingClientRect();
|
|
176
|
+
if (rect.width <= 0 || rect.height <= 0) return;
|
|
177
|
+
regions.push({
|
|
178
|
+
top: Math.max(0, Math.floor((rect.top - rootRect.top) * canvasScale)),
|
|
179
|
+
bottom: Math.max(0, Math.ceil((rect.bottom - rootRect.top) * canvasScale)),
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
regions.sort(function(a, b) { return a.top - b.top || b.bottom - a.bottom; });
|
|
183
|
+
var merged = [];
|
|
184
|
+
regions.forEach(function(region) {
|
|
185
|
+
var last = merged[merged.length - 1];
|
|
186
|
+
if (last && region.top < last.bottom) {
|
|
187
|
+
last.bottom = Math.max(last.bottom, region.bottom);
|
|
188
|
+
} else {
|
|
189
|
+
merged.push(region);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return merged;
|
|
193
|
+
}
|
|
194
|
+
|
|
140
195
|
function cleanupExportRoot(root) {
|
|
141
196
|
if (root && root.parentNode) {
|
|
142
197
|
root.parentNode.removeChild(root);
|
|
143
198
|
}
|
|
144
199
|
}
|
|
145
200
|
|
|
146
|
-
function waitForExportReady() {
|
|
201
|
+
function waitForExportReady(root) {
|
|
147
202
|
var fontReady = document.fonts && document.fonts.ready
|
|
148
203
|
? document.fonts.ready.catch(function() {})
|
|
149
204
|
: Promise.resolve();
|
|
150
205
|
|
|
151
|
-
|
|
206
|
+
var imagesReady = Promise.all(Array.prototype.map.call(root.querySelectorAll('img'), function(img) {
|
|
207
|
+
if (img.complete) {
|
|
208
|
+
return img.naturalWidth > 0 ? Promise.resolve() : Promise.reject(new Error('文档图片加载失败'));
|
|
209
|
+
}
|
|
210
|
+
return new Promise(function(resolve, reject) {
|
|
211
|
+
var timer = setTimeout(function() { finish(new Error('等待文档图片超时')); }, 15000);
|
|
212
|
+
function finish(error) {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
img.removeEventListener('load', loaded);
|
|
215
|
+
img.removeEventListener('error', failed);
|
|
216
|
+
if (error) reject(error); else resolve();
|
|
217
|
+
}
|
|
218
|
+
function loaded() { finish(); }
|
|
219
|
+
function failed() { finish(new Error('文档图片加载失败')); }
|
|
220
|
+
img.addEventListener('load', loaded, { once: true });
|
|
221
|
+
img.addEventListener('error', failed, { once: true });
|
|
222
|
+
});
|
|
223
|
+
}));
|
|
224
|
+
return Promise.all([fontReady, imagesReady]).then(function() {
|
|
152
225
|
return new Promise(function(resolve) {
|
|
153
226
|
requestAnimationFrame(function() {
|
|
154
227
|
requestAnimationFrame(resolve);
|
|
@@ -169,8 +242,9 @@
|
|
|
169
242
|
logging: false,
|
|
170
243
|
width: width,
|
|
171
244
|
height: height,
|
|
172
|
-
|
|
173
|
-
|
|
245
|
+
// Keep vw/vh styles and media queries identical to the measured DOM.
|
|
246
|
+
windowWidth: window.innerWidth,
|
|
247
|
+
windowHeight: window.innerHeight,
|
|
174
248
|
scrollX: 0,
|
|
175
249
|
scrollY: 0,
|
|
176
250
|
});
|
|
@@ -313,7 +387,7 @@
|
|
|
313
387
|
return Math.max(minBreakY - startY, searchStartY + bestRow - startY);
|
|
314
388
|
}
|
|
315
389
|
|
|
316
|
-
function addCanvasToPdf(pdf, canvas, margin, blockBreakpoints, watermark) {
|
|
390
|
+
function addCanvasToPdf(pdf, canvas, margin, blockBreakpoints, watermark, protectedRegions) {
|
|
317
391
|
var pageWidth = pdf.internal.pageSize.getWidth();
|
|
318
392
|
var pageHeight = pdf.internal.pageSize.getHeight();
|
|
319
393
|
var usableWidth = pageWidth - margin * 2;
|
|
@@ -338,6 +412,16 @@
|
|
|
338
412
|
sliceHeight = findBestPageBreak(canvas, sourceCtx, offsetY, pageCanvasHeight);
|
|
339
413
|
}
|
|
340
414
|
}
|
|
415
|
+
sliceHeight = Math.min(sliceHeight, remainingHeight, pageCanvasHeight);
|
|
416
|
+
var sliceEnd = offsetY + sliceHeight;
|
|
417
|
+
(protectedRegions || []).forEach(function(region) {
|
|
418
|
+
if (region.top < sliceEnd && region.bottom > sliceEnd) {
|
|
419
|
+
// Move a fitting image to the next page even if this leaves whitespace.
|
|
420
|
+
// A taller-than-page image receives one whole, scaled PDF page.
|
|
421
|
+
sliceEnd = region.top > offsetY ? region.top : Math.min(region.bottom, canvas.height);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
sliceHeight = Math.max(1, sliceEnd - offsetY);
|
|
341
425
|
var pageCanvas = document.createElement('canvas');
|
|
342
426
|
pageCanvas.width = canvas.width;
|
|
343
427
|
pageCanvas.height = sliceHeight;
|
|
@@ -362,7 +446,7 @@
|
|
|
362
446
|
context,
|
|
363
447
|
pageCanvas.width,
|
|
364
448
|
pageCanvas.height,
|
|
365
|
-
pageCanvasHeight,
|
|
449
|
+
Math.max(pageCanvasHeight, sliceHeight),
|
|
366
450
|
watermark.text,
|
|
367
451
|
);
|
|
368
452
|
}
|
|
@@ -371,13 +455,14 @@
|
|
|
371
455
|
pdf.addPage();
|
|
372
456
|
}
|
|
373
457
|
|
|
374
|
-
var
|
|
458
|
+
var imageWidth = Math.min(usableWidth, (usableHeight * canvas.width) / sliceHeight);
|
|
459
|
+
var imageHeight = (sliceHeight * imageWidth) / canvas.width;
|
|
375
460
|
pdf.addImage(
|
|
376
461
|
pageCanvas.toDataURL('image/png'),
|
|
377
462
|
'PNG',
|
|
463
|
+
margin + (usableWidth - imageWidth) / 2,
|
|
378
464
|
margin,
|
|
379
|
-
|
|
380
|
-
usableWidth,
|
|
465
|
+
imageWidth,
|
|
381
466
|
imageHeight,
|
|
382
467
|
undefined,
|
|
383
468
|
'FAST'
|
|
@@ -586,13 +671,15 @@
|
|
|
586
671
|
format: 'a4',
|
|
587
672
|
compress: true,
|
|
588
673
|
});
|
|
589
|
-
return waitForExportReady()
|
|
674
|
+
return waitForExportReady(exportRoot)
|
|
590
675
|
.then(function() {
|
|
591
676
|
return renderCanvas(exportRoot);
|
|
592
677
|
})
|
|
593
678
|
.then(function(canvas) {
|
|
594
|
-
var
|
|
595
|
-
|
|
679
|
+
var canvasScale = canvas.height / Math.max(exportRoot.scrollHeight, 1);
|
|
680
|
+
var blockBreakpoints = collectBlockBreakpoints(exportRoot, canvasScale);
|
|
681
|
+
var protectedRegions = collectProtectedRegions(exportRoot, canvasScale);
|
|
682
|
+
addCanvasToPdf(pdf, canvas, margin, blockBreakpoints, watermark, protectedRegions);
|
|
596
683
|
pdf.save(getExportFileName() + '.pdf');
|
|
597
684
|
})
|
|
598
685
|
.finally(function() {
|