如何在Obsidian插件中嵌入并使用<script>引入WGo.js
Obsidian插件嵌入WGo.js SGF播放器实现方案
我正在开发首个Obsidian插件,目标是嵌入WGo.js SGF围棋对局播放器。WGo.js虽已发布至NPM,但因文档过时无法直接正常使用,目前已有项目雏形,也在Obsidian论坛发布了相关讨论帖。我设想通过以下步骤实现:
- 自定义语法
!![game1.sgf]链接本地SGF文件 - 插件将该语法替换为WGo.js所需的
<div>容器 - 加载WGo.js相关资源,渲染内嵌对局查看器
以下是具体实现方法:
1. 自定义语法解析与替换(Markdown后置处理)
Obsidian插件可通过注册Markdown后置处理器,识别自定义语法并替换为目标DOM结构:
import { Plugin } from 'obsidian'; export default class SGFViewerPlugin extends Plugin { async onload() { // 注册Markdown后置处理器 this.registerMarkdownPostProcessor((element, context) => { // 匹配自定义语法 `!![filename.sgf]` const regex = /!!\[([^\]]+\.sgf)\]/g; const codeBlocks = element.querySelectorAll('code'); codeBlocks.forEach(block => { const content = block.textContent; if (content && regex.test(content)) { const match = content.match(regex); if (match) { match.forEach(m => { const filename = m.replace(/!!\[|\]/g, ''); // 创建WGo播放器容器 const wgoDiv = document.createElement('div'); wgoDiv.className = 'SGF'; wgoDiv.setAttribute('data-wgo', filename); wgoDiv.setAttribute('data-wgo-board', `stoneHandler: WGo.Board.drawHandlers.NORMAL, background: '${this.getResourcePath('assets/wgo/textures/wood2.jpg')}'`); // 添加降级提示 const fallbackP = document.createElement('p'); fallbackP.textContent = '你的浏览器不支持WGo.js播放器,请使用Chrome、Firefox等现代浏览器。'; wgoDiv.appendChild(fallbackP); // 替换原code块 block.replaceWith(wgoDiv); }); } } }); }); } // 获取插件内资源的绝对路径 getResourcePath(relativePath: string): string { return this.app.vault.getResourcePath(this.addResource(relativePath)); } }
2. 加载WGo.js依赖资源
将WGo.js的所有JS/CSS文件打包到插件的assets/wgo目录下,通过动态加载方式导入,避免直接插入<script>标签的兼容性问题:
async loadWGoResources() { const jsFiles = [ 'wgo.js', 'kifu.js', 'sgfparser.js', 'player.js', 'basicplayer.js', 'basicplayer.component.js', 'basicplayer.infobox.js', 'basicplayer.commentbox.js', 'basicplayer.control.js', 'player.editable.js', 'scoremode.js', 'player.permalink.js' ]; // 加载JS文件 for (const file of jsFiles) { await this.loadScript(`assets/wgo/${file}`); } // 加载CSS文件 await this.loadStylesheet(`assets/wgo/wgo.player.css`); } // 封装加载脚本方法 async loadScript(path: string) { const script = document.createElement('script'); script.src = this.getResourcePath(path); document.head.appendChild(script); await new Promise(resolve => script.onload = resolve); } // 封装加载样式方法 async loadStylesheet(path: string) { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = this.getResourcePath(path); document.head.appendChild(link); await new Promise(resolve => link.onload = resolve); }
在插件onload方法中调用loadWGoResources(),确保依赖加载完成后再处理DOM。
3. 初始化WGo播放器
由于是动态生成的DOM,需要手动触发WGo的初始化逻辑。可在后置处理器替换DOM后立即初始化,或在依赖加载完成后批量初始化:
// 方式1:替换DOM后立即初始化 if (window.WGo?.Player) { WGo.Player.init(wgoDiv); } // 方式2:资源加载完成后批量初始化 this.loadWGoResources().then(() => { WGo.Player.init(document.querySelectorAll('.SGF')); });
4. SGF文件路径处理
Obsidian中的文件路径需转换为WGo可访问的路径,可通过以下方式获取SGF文件的绝对路径:
async getSGFPath(filename: string) { const file = this.app.vault.getAbstractFileByPath(filename); if (file) { return this.app.vault.getResourcePath(file); } return ''; }
将data-wgo属性的值替换为该方法返回的路径,确保WGo能正确读取SGF文件。
参考示例HTML结构:
<script type="text/javascript" src="../../assets/wgo/wgo.js"></script> <script type="text/javascript" src="../../assets/wgo/kifu.js"></script> <script type="text/javascript" src="../../assets/wgo/sgfparser.js"></script> <script type="text/javascript" src="../../assets/wgo/player.js"></script> <script type="text/javascript" src="../../assets/wgo/basicplayer.js" ></script> <script type="text/javascript" src="../../assets/wgo/basicplayer.component.js" ></script> <script type="text/javascript" src="../../assets/wgo/basicplayer.infobox.js" ></script> <script type="text/javascript" src="../../assets/wgo/basicplayer.commentbox.js" ></script> <script type="text/javascript" src="../../assets/wgo/basicplayer.control.js" ></script> <script type="text/javascript" src="../../assets/wgo/player.editable.js" ></script> <script type="text/javascript" src="../../assets/wgo/scoremode.js"></script> <script type="text/javascript" src="../../assets/wgo/player.permalink.js" ></script> <link rel="stylesheet" type="text/css" href="../../assets/wgo/wgo.player.css" /> <!-- 自定义语法`!![AncientGame.sgf]`替换后的结构 --> <div data-wgo="AncientGame.sgf" data-wgo-board="stoneHandler: WGo.Board.drawHandlers.NORMAL, background: '../../assets/wgo/textures/wood2.jpg'" class="SGF" > <p> Your browser doesn't support the WGo.js Player. Please use a more modern browser, like Brave, Chrome, Firefox or Edge. </p> </div>
内容的提问来源于stack exchange,提问作者psygo
相关产品推荐
相关产品推荐

