🚀 Harness AI to execute your million-dollar ideas 10x faster, with 1/10th the effort.Get Started

JS solution for hiding an Obsidian Publish Sidebar

9/26/2022

This snippet should be added to your publish.js.

Info

If this is the first part of your publish.js, I recommend uncommenting the commented out (function() { and })(); lines so that you isolate the scope of this function

JS Snippet for publish.js

//(function () {
  function maybeSetFocusMode() {
    const noteContainer = document.getElementsByClassName("markdown-rendered")[0];
    const hideSidebarClassname = "focus";
  
    const rightSidebarClassname = "site-body-right-column";
    const rightSidebar = document.getElementsByClassName(
      rightSidebarClassname
    )[0];
  
    // if you want to also do the left sidebar, uncomment all of the commented out code that starts with leftSidebar
    const leftSidebarClassname = "site-body-left-column";
    const leftSidebar = document.getElementsByClassName(leftSidebarClassname)[0];
  
    if (noteContainer.className.includes(hideSidebarClassname)) {
      rightSidebar.style = "visibility: hidden; flex: 0; width: 0;";
      leftSidebar.style = "visibility: hidden; flex: 0; width: 0;";
    } else {
      rightSidebar.style = "";
      leftSidebar.style = "";
    }
  }
  
  function initializeRendererObserver() {
    // run on page transition
    new MutationObserver(maybeSetFocusMode).observe(
      document.getElementsByClassName("markdown-rendered")[0],
      {
        attributes: true,
      }
    );
	// run on page render
    maybeSetFocusMode();
  }
  
  initializeRendererObserver();
  
  //})();

This sets up a MutationObserver that observes the element with the markdown-renderer class of your site. Anytime that element changes (ie, when you visit a different page), it runs the callback function (the first argument passed to MutationObserver).

The function...

  • gets the markdown-renderer again so that it has a non-stale instance to check from
  • hideSidebarClassname should be whatever your classname needs to be based on the cssclass property in your metadata of the filei
  • gets the sidebar by classname
  • if the cssclass you want to use to hide the sidebar is present, it will hide the sidebar
  • if it's not present, it will make it visible

An alternative based on frontmatter

It's possible you want to use frontmatter instead of the cssclass to decide whether to do something in this observer. 1

Here's an alternative script that you can use to check the .frontmatter element for the presence of a field (in this example, I'll use mode: focus):

//(function () {
function maybeSetFocusMode() {
  const noteContainer = document.getElementsByClassName("markdown-rendered")[0];

  const rightSidebarClassname = "site-body-right-column";
  const rightSidebar = document.getElementsByClassName(
    rightSidebarClassname
  )[0];

  // if you want to also do the left sidebar, uncomment all of the commented out code that starts with leftSidebar
  const leftSidebarClassname = "site-body-left-column";
  const leftSidebar = document.getElementsByClassName(leftSidebarClassname)[0];

  if (meetsCriteria()) {
    rightSidebar.style = "visibility: hidden; flex: 0; width: 0;";
    leftSidebar.style = "visibility: hidden; flex: 0; width: 0;";
  } else {
    rightSidebar.style = "";
    leftSidebar.style = "";
  }
}

function meetsCriteria() {
  var yamlContainer = document.querySelector(".frontmatter.language-yaml");
  if (!yamlContainer) return false;

  return yamlContainer.textContent.includes("mode: focus");
}

function initializeRendererObserver() {
  // run on page transition
  new MutationObserver(maybeSetFocusMode).observe(
    document.getElementsByClassName("markdown-rendered")[0],
    {
      childList: true,
      subtree: true,
    }
  );
  // run on page render
  maybeSetFocusMode();
}

initializeRendererObserver();

//})();

Some important distinctions about what changed...

  • In the MutationObserver, instead of only running on attributes change, we need to check an element that's a child of the markdown-rendered element, so we set childList and subtree to true.
  • Instead of checking that the className includes something, we need to get the .frontmatter element and if it exists, check if it contains mode: focus (which we verify by running the meetsCriteria function), then we set the styles.

A loom walking through how it works...

Final Notes

  • This solution is not durable. What I mean by that is that if either of the two classes we use to select the renderer or the sidebar change, they'll need to be updated accordingly.

Footnotes

  1. (thanks to Jenna of polyrain.dev for the tip on finding the .frontmatter, I had no idea that element was present!)

Chase Adams