【已解决】【obsidian插件开发】svg图标路径不正确
想插入一个svg图片作为图标,但老是遇到这个错误:
GET app://obsidian.md/.obsidian/plugins/pomodoro-kanban/assets/icons/tomato.svg net::ERR_FILE_NOT_FOUND
看起来原因是obsidain找文件是基于vault里面文件存放的位置找的,但我插件开发要用的图片在.obsidian/plugins/我正在开发的插件
文件夹下。
尝试getAbstractFileByPath
const pluginAssetPath = '.obsidian/plugins/pomodoro-kanban/assets/icons/tomato.svg';
const file = stateManager.app.vault.getAbstractFileByPath(pluginAssetPath);
同样的错误
尝试url拼接
// 1. 获取当前插件的目录路径
const pluginDir = (app as any).plugins.getPlugin("pomodoro-kanban").manifest.dir;
// 2. 拼接到 assets/icons/tomato.svg
const fullPath = `${pluginDir}/assets/icons/tomato.svg`;
同样的错误
尝试new URL
new URL("assets/icons/tomato.svg", import.meta.url).toString()
同样的错误
最后的解决方法是先把svg转成base64
base64 -i "/Users/yixuan/workspace/pomodoro-kanban/.obsidian/plugins/pomodoro-kanban/assets/icons/tomato.svg" | tr -d "\n"
然后拼接
const tomatoIconSrc = useMemo(() => {// Inline data URL to avoid filesystem path resolution issues inside Obsidian sandboxconst b64 = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAtOTYwIDk2MCA5NjAiIHdpZHRoPSIyNHB4IiBmaWxsPSIjMWYxZjFmIj48cGF0aCBkPSJNNDgwLTY3NXEtMTgtMTMtMzguNS0xOXQtNDEuNS02cS0yNyAwLTUzIDEwLjVUMzAxLTY1OXEtMjAgMjAtMzAuNSA0NlQyNjAtNTYwcTAgMjEgNiA0MS41dDE5IDM4LjVxLTEzIDE4LTE5IDM4LjV0LTYgNDEuNXEwIDI3IDEwLjUgNTN0MzAuNSA0NnEyMCAyMCA0NiAzMC41dDUzIDEwLjVxMjEgMCA0MS41LTZ0MzguNS0xOXExOCAxMyAzOC41IDE5dDQxLjUgNnEyNyAwIDUzLTEwLjV0NDYtMzAuNXEyMC0yMCAzMC41LTQ2dDEwLjUtNTNxMC0yMS02LTQxLjVUNjc1LTQ4MHExMy0xOCAxOS0zOC41dDYtNDEuNXEwLTI3LTEwLjUtNTNUNjU5LTY1OXEtMjAtMjAtNDYtMzAuNVQ1NjAtNzAwcS0yMSAwLTQxLjUgNlQ0ODAtNjc1Wm0wIDI5Mi00NiAzMnEtOCA1LTE2LjUgOHQtMTcuNSAzcS0xMSAwLTIyLTQuNVQzNTgtMzU4cS05LTktMTMuNS0yMHQtNC41LTIycTAtOSAzLTE3LjV0OC0xNi41bDMyLTQ2LTMyLTQ2cS01LTgtOC0xNi41dC0zLTE3LjVxMC0xMSA0LjUtMjJ0MTMuNS0yMHE5LTkgMjAtMTMuNXQyMi00LjVxOSAwIDE3LjUgM3QxNi41IDhsNDYgMzIgNDYtMzJxOC01IDE2LjUtOHQxNy41LTNxMTEgMCAyMiA0LjV0MjAgMTMuNXE5IDkgMTMuNSAyMHQ0LjUgMjJxMCA5LTMgMTcuNXQtOCAxNi41bC0zMiA0NiAzMiA0NnE1IDggOCAxNi41dDMgMTcuNXEwIDExLTQuNSAyMlQ2MDItMzU4cS05IDktMjAgMTMuNXQtMjIgNC41cS05IDAtMTcuNS0zdC0xNi41LThsLTQ2LTMyWm0wLTQ3cTIxIDAgMzUuNS0xNC41VDUzMC00ODBxMC0yMS0xNC41LTM1LjVUNDgwLTUzMHEtMjEgMC0zNS41IDE0LjVUNDMwLTQ4MHEwIDIxIDE0LjUgMzUuNVQ0ODAtNDMwWm0wIDM1MHEtODMgMC0xNTYtMzEuNVQxOTctMTk3cS01NC01NC04NS41LTEyN1Q4MC00ODBxMC04MyAzMS41LTE1NlQxOTctNzYzcTU0LTU0IDEyNy04NS41VDQ4MC04ODBxODMgMCAxNTYgMzEuNVQ3NjMtNzYzcTU0IDU0IDg1LjUgMTI3VDg4MC00ODBxMCA4My0zMS41IDE1NlQ3NjMtMTk3cS01NCA1NC0xMjcgODUuNVQ0ODAtODBabTAtODBxMTM0IDAgMjI3LTkzdDkzLTIyN3EwLTEzNC05My0yMjd0LTIyNy05M3EtMTM0IDAtMjI3IDkzdC05MyAyMjdxMCAxMzQgOTMgMjI3dDIyNyA5M1ptMC0zMjBaIi8+PC9zdmc+%'const clean = b64.replace(/\s+/g, '').replace(/%+$/, '');return `data:image/svg+xml;base64,${clean}`;}, []);
成功了
但后面插入其他图标的时候内联svg也成功了
const HOURGLASS_PAUSE_SVG = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M452-160ZM160-80v-80h80v-120q0-61 28.5-114.5T348-480q-51-32-79.5-85.5T240-680v-120h-80v-80h640v80h-80v120q0 48-18 92t-51 77q-38 10-71 29t-60 47q-10-2-19.5-3.5T480-440q-66 0-113 47t-47 113v120h132q7 22 16.5 42T491-80H160Zm320-440q66 0 113-47t47-113v-120H320v120q0 66 47 113t113 47Zm270 360h40v-160h-40v160Zm-100 0h40v-160h-40v160Zm70 120q-83 0-141.5-58.5T520-240q0-83 58.5-141.5T720-440q83 0 141.5 58.5T920-240q0 83-58.5 141.5T720-40ZM480-800Z"/></svg>';
const TIMER_PAUSE_SVG = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M360-840v-80h240v80H360ZM480-80q-74 0-139.5-28.5T226-186q-49-49-77.5-114.5T120-440q0-74 28.5-139.5T226-694q49-49 114.5-77.5T480-800q62 0 119 20t107 58l56-56 56 56-56 56q38 50 58 107t20 119q0 74-28.5 139.5T734-186q-49 49-114.5 77.5T480-80Zm0-80q116 0 198-82t82-198q0-116-82-198t-198-82q-116 0-198 82t-82 198q0 116 82 198t198 82Zm0-280ZM360-280h80v-320h-80v320Zm160 0h80v-320h-80v320Z"/></svg>';
const REST_SVG = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M160-120v-80h640v80H160Zm160-160q-66 0-113-47t-47-113v-400h640q33 0 56.5 23.5T880-760v120q0 33-23.5 56.5T800-560h-80v120q0 66-47 113t-113 47H320Zm0-480h320-400 80Zm400 120h80v-120h-80v120ZM560-360q33 0 56.5-23.5T640-440v-320H400v16l72 58q2 2 8 16v170q0 8-6 14t-14 6H300q-8 0-14-6t-6-14v-170q0-2 8-16l72-58v-16H240v320q0 33 23.5 56.5T320-360h240ZM360-760h40-40Z"/></svg>';
const TIMER_PLAY_SVG = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M360-840v-80h240v80H360ZM480-80q-74 0-139.5-28.5T226-186q-49-49-77.5-114.5T120-440q0-74 28.5-139.5T226-694q49-49 114.5-77.5T480-800q62 0 119 20t107 58l56-56 56 56-56 56q38 50 58 107t20 119q0 74-28.5 139.5T734-186q-49 49-114.5 77.5T480-80Zm0-80q116 0 198-82t82-198q0-116-82-198t-198-82q-116 0-198 82t-82 198q0 116 82 198t198 82Zm0-280Zm-80 160 240-160-240-160v320Z"/></svg>';const iconSpan = btn.createSpan({ cls: 'kanban-plugin__icon-timer' });
if (!timerManager.state.running) {iconSpan.innerHTML = TIMER_PLAY_SVG;
} else if (mode === 'pomodoro') {iconSpan.innerHTML = HOURGLASS_PAUSE_SVG;
} else if (mode === 'stopwatch') {iconSpan.innerHTML = TIMER_PAUSE_SVG;
} else {iconSpan.innerHTML = REST_SVG;
}