remark icon indicating copy to clipboard operation
remark copied to clipboard

add remark-embed-tag plugins.md

Open Reimirno opened this issue 1 year ago • 3 comments

Initial checklist

  • [x] I read the support docs
  • [x] I read the contributing guide
  • [x] I agree to follow the code of conduct
  • [x] I searched issues and couldn’t find anything (or linked relevant results below)
  • [x] If applicable, I’ve added docs and tests

Description of changes

Add remark-embed-tag to the plugin list.

Reimirno avatar Apr 08 '24 07:04 Reimirno

Thanks @Reimirno!

Some tips:

  1. Your goal is to emit HTML. This is generally best done in a rehype plugin, not a remark plugin.
  2. Regardless what you think of the former suggestion, I suggest adding a test for emitting with rehype.
  3. Jest has issues when used with ESM. I strongly suggest using another test runner, for example node:test.
  4. Change the type of ast to Root. This way you get full type safety within visit.
  5. You’re missing a dependey on @types/mdast.
  6. You’re not supposed to change a node’s type. Instead, replace it with a new node.
  7. Your transformer does not need to be async. In some contexts only synchronous plugins can be used.
import type { Root } from "mdast"
import { visit } from "unist-util-visit";
// …

export default function remarkTagEmbed(configs: Config = {} as Config) {
  configs = { ...defaultConfig, ...configs };
  const transformer = (ast: Root) => {
    visit(ast, "text", (node, index, parent) => {
      if (index == null || !parent) {
        return
      }
      const { value } = node;
      if (configs.youtube) {
        const youtube = parseYouTube(value);
        if (youtube) {
          parent[index] = {
            type: 'html',
            value: createsYouTubeWidget(youtube)
          }
        }
      }
      // …
    });
  };
  return transformer;
}

Or you could use unified’s Plugin type to get full TypeScript support based on one type annotation. This is what I generally recommend.

import type { Root } from "mdast"
import type { Plugin } from "unified"
import { visit } from "unist-util-visit";
// …

const remarkTagEmbed: Plugin<[Configs?], Root> = (configs) => {
  configs = { ...defaultConfig, ...configs };
  return (ast) => {
    visit(ast, "text", (node, index, parent) => {
      if (index == null || !parent) {
        return
      }
      const { value } = node;
      if (configs.youtube) {
        const youtube = parseYouTube(value);
        if (youtube) {
          parent[index] = {
            type: 'html',
            value: createsYouTubeWidget(youtube)
          }
        }
      }
      // …
    });
  };
}

export default remarkTagEmbed

remcohaszing avatar Apr 08 '24 08:04 remcohaszing

@remcohaszing Thank you so much for the detailed and prompt review!

  1. I see... I was searching through remark plugins for html embeds and didn't come across anything suits my need and hence I made this though. I saw many plugins that transform md->html too so I just assumed that is the intended use case :) Plus, I thought rehype is for transformation from html->html, while remark is md->md or md->html.
  2. Ah ok. Any example I could refer to?
  3. Yeah Jest is ESM hell... but I made it work for this project. Will consider switching if situation demands.
  4. Yes.
  5. @types/mdast is a dependency of remark and I already have remark. I think that is ok?
  6. Okie.
  7. Okie. I now use the Plugin type as you recommended. This is indeed a lot more cleaner.

Reimirno avatar Apr 09 '24 01:04 Reimirno

  1. I see... I was searching through remark plugins for html embeds and didn't come across anything suits my need and hence I made this though. I saw many plugins that transform md->html too so I just assumed that is the intended use case :) Plus, I thought rehype is for transformation from html->html, while remark is md->md or md->html.

remark is for mdast (markdown) to mdast. remark-rehype does mdast → hast (HTML). rehype is for hast to hast.

export default remarkTagEmbed

  1. Ah ok. Any example I could refer to?

Just like in the remark plugin, you will probably need to iterate over all text nodes. But instead of creating a string of HTML, you should create hast elements.

You can have a look at the rehype plugins list. If you’re interested in a TypeScript implementation specifically, you can have a look at rehype-mermaid.

  1. @types/mdast is a dependency of remark and I already have remark. I think that is ok?

npm does not guarantee transitive dependencies are available or the same version unless they are in dependencies. pnpm explicitly makes sure it doesn’t work. Everything you import in your generated output, should be in your dependencies. So this includes @types/mdast and unified, but not remark.

remcohaszing avatar Apr 09 '24 08:04 remcohaszing

Closing this, it’s better as a rehype plugin

wooorm avatar Sep 23 '24 09:09 wooorm

Hi! This was closed. Team: If this was merged, please describe when this is likely to be released. Otherwise, please add one of the no/* labels.

github-actions[bot] avatar Sep 23 '24 09:09 github-actions[bot]