Initial commit: vitepress-exporter plugin

This commit is contained in:
2026-04-20 12:00:50 +08:00
commit e54a8a3b05
15 changed files with 6761 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
// 尝试捕获 Obsidian 原生 Canvas 渲染(通过临时调整视口大小)
async tryNativeCanvasCapture(canvasFile: TFile): Promise<Uint8Array | null> {
let uiStyleElement: HTMLStyleElement | null = null;
let sizeStyleElement: HTMLStyleElement | null = null;
let activeLeaf: any = null;
let canvasWrapper: HTMLElement | null = null;
let originalScrollLeft = 0;
let originalScrollTop = 0;
try {
console.log('🔍 Step 1: Getting active workspace leaf...');
// 获取当前活动的 leaf(不创建新窗口)
activeLeaf = this.app.workspace.activeLeaf;
if (!activeLeaf) {
console.log('❌ No active leaf found');
return null;
}
console.log('🔍 Step 2: Opening canvas file...');
await activeLeaf.openFile(canvasFile);
console.log('⏳ Step 3: Waiting for canvas render...');
await this.waitForCanvasRender();
console.log('🔍 Step 4: Finding canvas DOM...');
const canvasDom = this.findCanvasDomElement();
if (!canvasDom) {
console.log('❌ Could not find canvas DOM element');
return null;
}
console.log('✅ Found canvas DOM:', canvasDom.className, 'Size:', (canvasDom as any).offsetWidth, 'x', (canvasDom as any).offsetHeight);
console.log('🎨 Step 5: Hiding Canvas UI elements...');
uiStyleElement = this.hideCanvasUIElements();
console.log('📐 Step 6: Calculating canvas content size...');
const contentSize = this.getCanvasContentSize(canvasDom);
// 获取 canvasWrapper
if ((canvasDom as HTMLElement).classList.contains('canvas-wrapper')) {
canvasWrapper = canvasDom as HTMLElement;
} else {
canvasWrapper = canvasDom.querySelector('.canvas-wrapper') as HTMLElement;
}
if (!canvasWrapper) {
console.log('❌ Could not find canvas wrapper');
return null;
}
// 保存原始滚动位置
originalScrollLeft = canvasWrapper.scrollLeft;
originalScrollTop = canvasWrapper.scrollTop;
console.log(`📏 Original wrapper size: ${(canvasDom as any).offsetWidth}x${(canvasDom as any).offsetHeight}`);
console.log(`📏 Content size: ${contentSize.width}x${contentSize.height}`);
// 临时调整 canvas wrapper 大小以适应所有内容
console.log('🔧 Temporarily resizing canvas wrapper to fit all content...');
sizeStyleElement = document.createElement('style');
sizeStyleElement.id = 'canvas-export-resize';
sizeStyleElement.textContent = `
/* 临时调整 canvas wrapper 大小 */
.canvas-wrapper {
width: ${contentSize.width + 100}px !important;
height: ${contentSize.height + 100}px !important;
max-width: ${contentSize.width + 100}px !important;
max-height: ${contentSize.height + 100}px !important;
overflow: visible !important;
}
/* 确保画布内容区域也扩展 */
.canvas-view-content {
width: ${contentSize.width + 100}px !important;
height: ${contentSize.height + 100}px !important;
}
`;
document.head.appendChild(sizeStyleElement);
// 等待样式应用
await new Promise(resolve => setTimeout(resolve, 100));
// 重置滚动位置
canvasWrapper.scrollLeft = 0;
canvasWrapper.scrollTop = 0;
// 等待布局更新
await new Promise(resolve => setTimeout(resolve, 200));
console.log('📸 Step 7: Capturing canvas...');
// @ts-ignore
const domToImage = require('dom-to-image-more');
const dataUrl = await domToImage.toPng(canvasDom, {
backgroundColor: '#ffffff',
quality: 1,
width: contentSize.width,
height: contentSize.height,
cacheBust: true
});
const imageData = this.dataUrlToUint8Array(dataUrl);
console.log('✅ Capture successful!');
return imageData;
} catch (error) {
console.error('❌ Native canvas capture failed:', error);
return null;
} finally {
// 清理临时调整大小的样式
if (sizeStyleElement && sizeStyleElement.parentNode) {
sizeStyleElement.parentNode.removeChild(sizeStyleElement);
console.log('🧹 Removed temporary resize styles');
}
if (uiStyleElement && uiStyleElement.parentNode) {
uiStyleElement.parentNode.removeChild(uiStyleElement);
console.log('🧹 Cleaned up UI hiding styles');
}
// 恢复滚动位置
if (canvasWrapper) {
canvasWrapper.scrollLeft = originalScrollLeft;
canvasWrapper.scrollTop = originalScrollTop;
console.log('🔄 Restored original scroll position');
}
console.log('🧹 Cleanup complete');
}
}