skip to Main Content

This is my first Obsidian Plugin, and I haven’t been able to figure out how all things work. What I would like my plugin to do is embed the WGo.js SGF player. The WGo.js package has been published on NPM but I’ve never been able to make it work for some reason — the docs seem outdated, you can see it in action on my website here.

This is what I have so far for this project.

I’ve also posted about this on Obsidian Discourse.

If using the <script> method, I imagine the necessary steps as:

  1. An SGF file is linked with custom syntax, e.g. !![game1.sgf].
  2. Under the hood, this is replaced by its respective WGo.js <div> by the plugin.
  3. The plugin will use <script> tags to bring WGo.js into showing an embedded viewer with the game.

How do I do this through an Obsidian plugin?

<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"
/>

<!-- This would be the replacement of a custom syntax, e.g. `!![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>

2

Answers


  1. Chosen as BEST ANSWER

    Incomplete answer over here, but I thought I would share the progress I've had so far.

    I've managed to make WGo.js work imperatively through JS while also adding the <div> element to the document's body:

    import { SimplePlayer } from "wgo";
    
    ...
    
    async onload() {
        await this.loadSettings();
    
        this.addSettingTab(new SgfViewerSettingTab(this.app, this));
    
        this.addCommand({
            id: "add-sgf-game-viewer",
            name: "Add SGF Game Viewer",
            editorCallback: (editor: Editor, view: MarkdownView) => {
                const div = document.createElement("div");
    
                const simplePlayer = new SimplePlayer(div, {
                    sgf: "(;SZ[19];B[pc];W[pe]C[You have many choices - for example: R13];B[qg]C[Click on a letter to select a variation](;W[of]C[Old joseki];B[mc];W[qc];B[qb];W[qd];B[qj];W[ob];B[pb];W[oc];B[od];W[pd];B[oa];W[nd];B[nb];W[oe];B[jc])(;W[qc];B[qb];W[qd];B[mc](;W[og];B[pg];W[oh];B[pi];W[ob];B[pb];W[oc];B[pd];W[od];B[qe];W[re];B[qf];W[rb];B[oe];W[ne];B[pf];W[md]TR[rb][qc][qd][re]C[Marked stones are not dead yet.])(;W[pg];B[ph];W[ob];B[pb];W[oc];B[od];W[pd];B[nc];W[nd]MA[og]C[White can play at X as well.];B[oe];W[nf];B[oa];W[of];B[nb];W[qh];B[qf];W[pi];B[oh];W[ri];B[rh];W[qi];B[pf];W[nh];B[re];W[oc];B[ob];W[ne];B[oc];W[rg];B[rf];W[sh];B[rc]C[Interesting joseki])))",
                });
    
                const workspace = document.body.querySelectorAll(
                    ".workspace-tab-container"
                )[1];
    
                workspace!.append(div);
            },
        });
    }
    

    I don't know yet how to properly place this in Obsidian's editor, and I doubt this is supposed to be how plugins should interact with it. And there's also the problem of customizing WGo.js a little bit more, not to mention that the SGF is hardcoded so far. But overall this is a solid direction, I think.


  2. As per Obsidian docs, you shouldn’t fixate on building a plugin, lest you might need an extension instead for your use case.

    Pro Solution

    If you’re looking to build a full-blown plugin, which when encounters the markdown !![game1.sgf], it should show the WGo.js SGF player, in the reading view and live preview, you’ll have to write an extension (registered with an Obsidian plugin) to extend CodeMirror’s capability to process the markdown. CodeMirror, under the hood uses @codemirror/lang-markdown package for this, which in-turn makes use of @lezer/markdown. The latter (@lezer/markdown) can be extended using it’s own extensions, to add a particular processor for some markdown. For e.g., the package by default includes an extension to parse GitHub flavored strike-through markdown, which is what you’ll need to do for showing a live preview for an SGF player, but then a little issue that ensues is that it’s not apparent, as to how to register this with the CodeMirror instance used by obsidian. For that you’ll have to use unexposed Obisidian API.

    Just Get By Solution

    For having the Obisdian show an SGF player in the reading view only (not live preview), you can simply register a markdown post processor, with that you’ll have to manipulate already html converted markdown for !![game1.sgf] to show the SGF player.

    Better Than Just Get By Solution

    Instead of muddling your way to "Pro Solution", to get everything right, you can consider changing the syntax for SGF player to use a code fence block, and register a markdown code block processor, then you’ll be able to get this in reading mode and live preview. For e.g., you can use this syntax –

    ```sgf
     https://www.gamesource.com/game1.sgf
    ```
    

    get the source of the game, load it in the element provided by obsidian. Ideally, you should allow only one link in an sgf code fence.

    Something to consider

    Instead of loading the wgo through script tags, just bundle it with your plugin. In the onload callback, add it to Window object and remove it from Window object in the onunload callback. Obsidian itself adds many functions and objects on Window object.

    NOTE: If you need to get some elaboration on a particular part or clarification, add a comment and I’ll update the answer.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search