rockchalkwushock/rehype-code-titles

Re-apply test suite after ESM support is fixed

Closed this issue ยท 4 comments

The Problem

At the time of writing ESM is not supported natively in jest or ts-jest.

What was attempted?

I followed along with the guide here to no avail and also used the following but could not get jest to play nice with the ESM. The package was manually tested locally and works in a current project on my machine with no issues as a symlink.

What is being done?

  • I have subscribed to jestjs/jest#10025.
  • ts-jest is waiting for jest@27 to drop, which must be fixing this issue, as it's docs allude to.

Found this worth refactoring as described for the package being purely ESM.

I wonder, what's the point of keeping tests in TS? As Mr. Dodds said,

The more your tests resemble the way your software is used, the more confidence they can give you.
โ€”Testing Library guiding principles

It feels like unit tests should be in JS and target transpiled dist/ contents, in JS too. Personally, I don't see any benefits from unit tests being in TS โ€” on the contrary, it slows down everything, adds unnecessary infra and sometimes "type safety" actually stands in the way because we still need to unit test weird inputs, those that fall outside of .d.ts "wishes".

I came here investigating why this plugin is not working for me; I thought I'll fork and snoop around unit tests first...

Hi @revelt thanks for the input, perhaps this weekend I can get around to updating this package. I've been very busy with clients. I know it has many dependencies that are our of date and I have really wanted to get a test suite in place for it.

I made this package when I ran into problems using the remark version with mdx-bundler. At the time Kent was using xdm under the hood but in v9 Kent removed that as an underlying dependency. The whole reason the package existed was after some inspection the order in which the default plugins were being applied by xdm were causing problems for remark-code-titles.

You might not need this package and be able to use the remark-code-titles plugin instead.

Can you elaborate on what problems you are running into?

hi! Yesterday I tried this plugin, but titles didn't get injected. It's a Remix.js setup, and I have other plugins wired up already.

It turns out, even a local function can be passed as a plugin! So, in couple hours last night I made a tiny tree walker to add div to wrap pre-code pairs, also to extract language code from code and add as data-syntax onto pre.

function rehypeRelCodeBlockTitles() {
  return (tree) => {
    visit(tree, "element", (node, i, parent) => {
      let retrieved;
      if (
        node.tagName === "pre" &&
        Array.isArray(node.children) &&
        node.children.length &&
        typeof node.children[0] === "object" &&
        node.children[0].tagName === "code" &&
        Array.isArray(node.children[0]?.properties?.className) &&
        node.children[0]?.properties?.className.some((className) => {
          if (
            !retrieved &&
            className.startsWith("language-") &&
            className.length > 9
          ) {
            retrieved = className;
            return true;
          }
          return false;
        })
      ) {
        const extractedName = retrieved.slice(9);
        node.properties["data-syntax"] =
          mappings[extractedName] || extractedName;

        const replacement = {
          type: "element",
          tagName: "div",
          properties: {
            class: "syntax-container",
          },
          children: [node],
        };
        parent.children[i] = replacement;
      }
    });
  };
}

css then renders data-syntax attribute value on top of pre, but the wrapper div is relative, not usual pre, so the syntax label is fixed on overflow scrolls:

pre[data-syntax]:before {
  font-size: 1.5rem;
  content: attr(data-syntax);
  position: absolute;
  top: -0.3rem;
  right: 0.6rem;
  color: var(--c-color-semantic-svg-yellow);
  z-index: 3;
}

result HTML:

<div class="syntax-container">
  <pre data-syntax="jinja">
    <code class="hljs language-jinja">
      &lt;td <span class="hljs-attr">class</span>=<span class="hljs-string">"db{% if module_on || oodles %}on{% else %}off{% endif %} pt10"</span>&gt;&lt;/td&gt;
    </code>
  </pre>
</div>

visually โ€” it's this yellow "jinja" label (coming from pre), plus fade effect on overflow (coming from wrapper div):

Screenshot 2022-05-11 at 18 15 55

Originally I saw this on css-tricks, they use rel attribute on pre (JSX types don't like that though) and inject via css content.

It ended up slightly different, more minimalistic syntax code titles.