joshuatz / vscode-do-co-authoring

VSCode extension to assist with editing DigitalOcean Community articles

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Dynamic / Conditional CSS Enabling / Disabling

joshuatz opened this issue · comments

Since users might not want the custom styling and DO-specific rules applied to every markdown file that gets opened, I've created rules for when the extension applies - right now, it's when (in user specified settings) either a global boolean setting is true, or the file matches a user provided glob array.

This is working out well for the Markdown processing / Markdown-it side of things, because VSCode APIs made it (somewhat) easy to code a plugin that disables itself under certain conditions, but this is potentially more complicated for the CSS side of things, which needs to be addressed.

Currently, the main way to inject CSS into the preview pane is though the package.json contribution point, but that is, by definition, not dynamic.

A couple of ideas spring to mind when considering possible routes for dynamic CSS injection.

  • A) Use JavaScript injected into the WebView to check matching status for current doc, and inject CSS (inline or via link) if there is a match. My concern with this route would be jank; haven't tested yet, but I'm worried there could be delay / FOUC, perhaps even on every keystroke.
  • B) Always inject the same CSS, but start conditionally injecting a top level CSS class to allow for scoped targeting. Prefix all selectors in CSS file with that conditional class. This is my priority for testing out.
  • C) Switch to a custom WebView. I would have to further evaluate downsides to this, but I have a feeling it would require extra work to recreate features provided out-of-the-box by the default Markdown preview view.

Opened issue in VSCode repo - #128827, feature request for dynamic contribution points and/or "soft-disabling", since this is rather hard to do without either.

Implemented in 31d8376.

This was actually pretty tricky to implement (I have a feeling there are not many extensions doing this...) due to issues outlined above (again, see issue I opened in VSCode repo) - mainly the lack of a "soft-disable" and/or dynamic contribution points for Markdown extensions.

I basically ended up with option 1 (JS that conditionally loads the CSS). The way I got this working is worthy of its own blog post, but a quick summary:

  • On activation, extension resolves the path of the CSS file to conditionally load. Computes URI that is compatible with MD preview Webview to inject later.
  • Above CSS URI is passed to wrapper around extendMarkdownIt dynamic contribution point / callback. If extension is not soft-disabled, then a special <div> is injected into the preview DOM, via the Markdown-it token array, and the CSS URI is also passed into the DOM, through a data-* HTML attribute
  • A tiny bit of JS code is loaded into the MD preview Webview 100% of the time - checks if special injected <div> is there, and if it is, dynamically inserts the CSS with the passed CSS URI

Although this works great (no noticeable lag or FOUC, at least not any more than usual), I'm not thrilled that this is the best option available, and I would really like to see some VSCode APIs / contribution points that would make alternative approaches possible.