3

I'm building a component library of just HTML snippet and corresponding js/css and I'm using Docusaurus to document those compoents. I have a document page for each component. On the document page there is an example of each component. I'd like to make the components functional (click events, keyboard nav, etc.) so I have attached the component javascript via a plugin:

module.exports = function (context, options) {
  return {
    name: 'docusaurus-plugin-component-assets',
    injectHtmlTags() {
      return {
        headTags: [
          {
            tagName: 'link',
            attributes: {
              rel: 'stylesheet',
              href: 'https://example.com/css/component.min.css',
            },
          },
        ],
        postBodyTags: [
          {
            tagName: 'script',
            attributes: {
              src: 'https://example.com/js/component.min.js',
            },
          },
        ],
      };
    },
  };
};

In my docusaurus.config.js I've added my plugin:

...

plugins: [
  'docusaurus-plugin-sass',
  path.resolve(__dirname, 'src/plugins/docusaurus-plugin-component-assets.js')
],

...

This successfully adds the stylesheet and javascript in the correct locations. However the javascript never executes. It appears that my component javascript fires before the documentation app loads.

What am I missing? What is the correct way to add external javascript to documentation pages?

EDIT: I'm using "@docusaurus/core": "2.0.0-beta.0",

evans863
  • 63
  • 4

2 Answers2

3

I struggled with this too (on Docusaurus v2). Eventually I understood what the Client Modules documentation was saying and did the following, which worked for me both for the initial page load and the page loaded after a navigation event. (Since this is a single-page app, it's not a full page load when you're just navigating around the documentation, and I had to handle that case separately.)

  1. Create a new file at plugins/my-script.js (or whatever you want to call it).
  2. Add clientModules: [require.resolve('./plugins/my-script')], to your config in docusaurus.config.js.
  3. Insert code like this into your new file:
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';

const doYourCustomStuff = () => {
  // your JS code goes here
}

export function onRouteDidUpdate({location, previousLocation}) {
  // Don't execute if we are still on the same page; the lifecycle may be fired
  // because the hash changes (e.g. when navigating between headings)
  if (location.pathname === previousLocation?.pathname) return;
  doYourCustomStuff();
}

if (ExecutionEnvironment.canUseDOM) {
  // We also need to setCodeRevealTriggers when the page first loads; otherwise,
  // after reloading the page, these triggers will not be set until the user
  // navigates somewhere.
  window.addEventListener('load', () => {
    setTimeout(doYourCustomStuff, 1000);
  });
}

Then put your JS code inside the given function.

Caveat: your effects will still be broken when hot-loading changes from a yarn start dev environment. The not-too-painful workaround is to manually reload in such cases.

Jeff Terrell Ph.D.
  • 2,563
  • 26
  • 39
-2

You can embed your components in Live Code block Docusaurus V2.

You will need to install the package using npm or yarn.

npm install --save @docusaurus/theme-live-codeblock
module.exports = {
  plugins: ['@docusaurus/theme-live-codeblock'],
  themeConfig: {
    liveCodeBlock: {
      /**
       * The position of the live playground, above or under the editor
       * Possible values: "top" | "bottom"
       */
      playgroundPosition: 'bottom',
    },
  },
};

You can find detailed information about this process by using the link below.

https://docusaurus.io/docs/markdown-features/code-blocks#interactive-code-editor

It should be noted that this only works with react components.

Elugens
  • 12
  • 2