Giter Club home page Giter Club logo

core's Introduction

@remark-embedder/core ๐Ÿ”—

Remark plugin to convert URLs to embed code in markdown.


Build Status Code Coverage version downloads MIT License All Contributors PRs Welcome Code of Conduct

The problem

I used to write blog posts on Medium. When I moved on to my own site, I started writing my blog posts in markdown and I missed the ability to just copy a URL (like for a tweet), paste it in the blog post, and have Medium auto-embed it for me.

This solution

This allows you to transform a link in your markdown into the embedded version of that link. It's a remark plugin (the de-facto standard markdown parser). You provide a "transformer" the plugin does the rest.

Table of Contents

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's dependencies:

npm install @remark-embedder/core

Usage

Here's the most complete, simplest, practical example I can offer:

import remarkEmbedder from '@remark-embedder/core'
// or, if you're using CJS:
// const {default: remarkEmbedder} = require('@remark-embedder/core')
import remark from 'remark'
import html from 'remark-html'

const CodeSandboxTransformer = {
  name: 'CodeSandbox',
  // shouldTransform can also be async
  shouldTransform(url) {
    const {host, pathname} = new URL(url)

    return (
      ['codesandbox.io', 'www.codesandbox.io'].includes(host) &&
      pathname.includes('/s/')
    )
  },
  // getHTML can also be async
  getHTML(url) {
    const iframeUrl = url.replace('/s/', '/embed/')

    return `<iframe src="${iframeUrl}" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>`
  },
}

const exampleMarkdown = `
This is a CodeSandbox:

https://codesandbox.io/s/css-variables-vs-themeprovider-df90h
`

async function go() {
  const result = await remark()
    .use(remarkEmbedder, {
      transformers: [CodeSandboxTransformer],
    })
    .use(html)
    .process(exampleMarkdown)

  console.log(result.toString())
  // logs:
  // <p>This is a CodeSandbox:</p>
  // <iframe src="https://codesandbox.io/embed/css-variables-vs-themeprovider-df90h" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>
}

go()

Options

The transformers option is required (otherwise the plugin won't do anything), but there are a few optional options as well.

transformers: Array<Transformer | [Transformer, unknown]>

Take a look at @remark-embedder/transformer-oembed which should cover you for most things you'll want to convert to embeds.

The transformer objects are where you convert a link to it's HTML embed representation.

name: string

This is the name of your transformer. It's required because it's used in error messages. I suggest you use your module name if you're publishing this transformer as a package so people know where to open issues if there's a problem.

shouldTransform: (url: string) => boolean | Promise<boolean>

Only URLs on their own line will be transformed, but for your transformer to be called, you must first determine whether a given URL should be transformed by your transformer. The shouldTransform function accepts the URL string and returns a boolean. true if you want to transform, and false if not.

Typically this will involve checking whether the URL has all the requisite information for the transformation (it's the right host and has the right query params etc.).

You might also consider doing some basic checking, for example, if it looks a lot like the kind of URL that you would handle, but is missing important information and you're confident that's a mistake, you could log helpful information using console.log.

getHTML: (url: string, config?: unknown) => string | null | Promise<string | null>

The getHTML function accepts the url string and a config option (learn more from the services option). It returns a string of HTML or a promise that resolves to that HTML. This HTML will be used to replace the link.

It's important that the HTML you return only has a single root element.

// This is ok โœ…
return `<iframe src="..."></iframe>`

// This is not ok โŒ
return `<blockquote>...</blockquote><a href="...">...</a>`

// But this would be ok โœ…
return `<div><blockquote>...</blockquote><a href="...">...</a></div>`

Some services have endpoints that you can use to get the embed HTML (like twitter for example).

handleHTML?: (html: GottenHTML, info: TransformerInfo) => GottenHTML | Promise<GottenHTML>

Add optional HTML around what is returned by the transformer. This is useful for surrounding the returned HTML with custom HTML and classes.

Here's a quick example of an HTML handler that would handle adding TailwindCSS aspect ratio classes to YouTube videos:

import remark from 'remark'
import remarkEmbedder, {TransformerInfo} from '@remark-embedder/core'
import oembedTransformer from '@remark-embedder/transformer-oembed'
import remarkHtml from 'remark-html'

const exampleMarkdown = `
Check out this video:

https://www.youtube.com/watch?v=dQw4w9WgXcQ
`

function handleHTML(html: string, info: TransformerInfo) {
  const {url, transformer} = info
  if (
    transformer.name === '@remark-embedder/transformer-oembed' ||
    url.includes('youtube.com')
  ) {
    return `<div class="embed-youtube aspect-w-16 aspect-h-9">${html}</div>`
  }
  return html
}

const result = await remark()
  .use(remarkEmbedder, {
    transformers: [oembedTransformer],
    handleHTML,
  })
  .use(remarkHtml)
  .process(exampleMarkdown)

// This should return:
// <p>Check out this video:</p>
// <div class="embedded-youtube aspect-w-16 aspect-h-9"><iframe width="200" height="113" src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>

handleError?: (errorInfo: ErrorInfo) => GottenHTML | Promise<GottenHTML>

type ErrorInfo = {
  error: Error
  url: string
  transformer: Transformer<unknown>
  config: TransformerConfig
}

If remark-embedder encounters an error with any transformer, then compilation will fail. I've found this to be problematic when using @remark-embedder/transformer-oembed for tweets and the tweet author deletes their tweet. It'll prevent you from building and that's annoying.

So handleError allows you to handle any error that's thrown by a transformer. This way you can gracefully fallback to something rather than crashing everything. Even if you provide a handleError, we'll log to the console so you can fix the problem in the future.

Here's a quick example of an error handler that would handle deleted tweets:

function handleError({error, url, transformer}) {
  if (
    transformer.name !== '@remark-embedder/transformer-oembed' ||
    !url.includes('twitter.com')
  ) {
    // we're only handling errors from this specific transformer and the twitter URL
    // so we'll rethrow errors from any other transformer/url
    throw error
  }
  return `<p>Unable to embed <a href="${url}">this tweet</a>.</p>`
}

const result = await remark()
  .use(remarkEmbedder, {
    transformers: [oembedTransformer],
    handleError,
  })
  .use(html)
  .process(exampleMarkdown)

You'll get an error logged, but it won't break your build. It also won't be cached (if you're using the cache option).

cache?: Map<string, string | null>

You'll mostly likely want to use @remark-embedder/cache

Because some of your transforms may make network requests to retrieve the HTML, we support providing a cache. You could pass new Map(), but that would only be useful during the life of your process (which means it probably wouldn't be all that helpful). You'll want to make sure to persist this to the file system (so it works across compilations), which is why you should probably use @remark-embedder/cache.

The cache key is set to remark-embedder:${transformerName}:${urlString} and the value is the resulting HTML.

Also, while technically we treat the cache as a Map, all we really care about is that the cache has a get and a set and we await both of those calls to support async caches (like @remark-embedder/cache or Gatsby's built-in plugin cache).

Configuration

You can provide configuration for your transformer by specifying the transformer as an array. This may not seem very relevant if you're creating your own custom transformer where you can simply edit the code directly, but if the transformer is published to npm then allowing users to configure your transformer externally can be quite useful (especially if your transformer requires an API token to request the embed information like with instagram).

Here's a simple example:

const CodeSandboxTransformer = {
  name: 'CodeSandbox',
  shouldTransform(url) {
    // ...
  },
  getHTML(url, config) {
    // ...
  },
}

const getCodeSandboxConfig = url => ({height: '600px'})

const result = await remark()
  .use(remarkEmbedder, {
    transformers: [
      someUnconfiguredTransformer, // remember, not all transforms need/accept configuration
      [codesandboxTransformer, getCodeSandboxConfig],
    ],
  })
  .use(html)
  .process(exampleMarkdown)

The config is typed as unknown so transformer authors have the liberty to set it as anything they like. The example above uses a function, but you could easily only offer an object. Personally, I think using the function gives the most flexibility for folks to configure the transform. In fact, I think a good pattern could be something like the following:

const CodeSandboxTransformer = {
  name: 'CodeSandbox',
  shouldTransform(url) {
    // ...
  },
  // default config function returns what it's given
  getHTML(url, config = html => html) {
    const html = '... embed html here ...'
    return config({url, html})
  },
}

const getCodeSandboxConfig = ({url, html}) =>
  hasSomeSpecialQueryParam(url) ? modifyHTMLBasedOnQueryParam(html) : html

const result = await remark()
  .use(remarkEmbedder, {
    transformers: [
      someUnconfiguredTransformer, // remember, not all transforms need/accept configuration
      [CodeSandboxTransformer, getCodeSandboxConfig],
    ],
  })
  .use(html)
  .process(exampleMarkdown)

This pattern inverts control for folks who like what your transform does, but want to modify it slightly. If written like above (return config(...)) it could even allow the config function to be async.

Making a transformer module

Here's what our simple example would look like as a transformer module:

import type {Transformer} from '@remark-embedder/core'

type Config = (url: string) => {height: string}
const getDefaultConfig = () => ({some: 'defaultConfig'})

const transformer: Transformer<Config> = {
  // this should be the name of your module:
  name: '@remark-embedder/transformer-codesandbox',
  shouldTransform(url) {
    // do your thing and return true/false
    return false
  },
  getHTML(url, getConfig = getDefaultConfig) {
    // get the config...
    const config = getConfig(url)
    // do your thing and return the HTML
    return '<iframe>...</iframe>'
  },
}

export default transformer
export type {Config}

If you're not using TypeScript, simply remove the type import and the : Transformer bit.

If you're using CommonJS, then you'd also swap export default transformer for module.exports = transformer

NOTE: If you're using export default then CommonJS consumers will need to add a .default to get your transformer with require.

To take advantage of the config type you export, the user of your transform would need to cast their config when running it through remark. For example:

// ...
import transformer from '@remark-embedder/transformer-codesandbox'
import type {Config as CodesandboxConfig} from '@remark-embedder/transformer-codesandbox'

// ...

remark().use(remarkEmbedder, {
  transformers: [codesandboxTransformer, config as CodesandboxConfig],
})
// ...

Inspiration

This whole plugin was extracted out of Kent C. Dodds' Gatsby website into gatsby-remark-embedder by Michaรซl De Boey and then Kent extracted the remark plugin into this core package.

Other Solutions

  • MDX Embed: Allows you to use components in MDX files for common services. A pretty different approach to solving a similar problem.

Issues

Looking to contribute? Look for the Good First Issue label.

๐Ÿ› Bugs

Please file an issue for bugs, missing documentation, or unexpected behavior.

See Bugs

๐Ÿ’ก Feature Requests

Please file an issue to suggest new features. Vote on feature requests by adding a ๐Ÿ‘. This helps maintainers prioritize what to work on.

See Feature Requests

Contributors โœจ

Thanks goes to these people (emoji key):

Kent C. Dodds
Kent C. Dodds

๐Ÿ’ป ๐Ÿ“– ๐Ÿš‡ โš ๏ธ
Michaรซl De Boey
Michaรซl De Boey

๐Ÿ› ๐Ÿ’ป ๐Ÿ“– โš ๏ธ ๐Ÿ‘€
Matt Johnston
Matt Johnston

๐Ÿ“–
Eduardo Reveles
Eduardo Reveles

๐Ÿ’ป
Titus
Titus

๐Ÿ‘€
Brad Garropy
Brad Garropy

๐Ÿ’ป ๐Ÿ›
Mike Stecker
Mike Stecker

๐Ÿ’ป โš ๏ธ ๐Ÿ“–
mono
mono

๐Ÿ’ป โš ๏ธ

This project follows the all-contributors specification. Contributions of any kind welcome!

LICENSE

MIT

core's People

Contributors

allcontributors[bot] avatar bradgarropy avatar dependabot[bot] avatar johnstonmatt avatar kentcdodds avatar michaeldeboey avatar mikestecker avatar mono0x avatar osiux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

core's Issues

CI is failing

I'm actually experiencing errors on a fresh clone:

~/Desktop ๐Ÿฆ
$ git clone https://github.com/remark-embedder/core.git
Cloning into 'core'...
remote: Enumerating objects: 186, done.
remote: Counting objects: 100% (63/63), done.
remote: Compressing objects: 100% (48/48), done.
remote: Total 186 (delta 30), reused 26 (delta 10), pack-reused 123
Receiving objects: 100% (186/186), 65.03 KiB | 924.00 KiB/s, done.
Resolving deltas: 100% (92/92), done.
~/Desktop ๐Ÿฆ
$ cd core 
~/Desktop/core (main) ๐Ÿฆ
$ npm run setup
running command with prefix "setup"

> @remark-embedder/[email protected] setup
> npm install && npm run validate -s

npm WARN deprecated [email protected]: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated [email protected]: Please update to the latest object-keys
npm WARN deprecated [email protected]: https://github.com/lydell/resolve-url#deprecated

added 1189 packages, and audited 1190 packages in 20s

165 packages are looking for funding
  run `npm fund` for details

12 vulnerabilities (6 moderate, 6 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
[build] Successfully compiled 1 file with Babel (645ms).
[build] Generating TypeScript definitions
[typecheck] src/index.ts(92,26): error TS2339: Property 'value' does not exist on type 'StaticPhrasingContent'.
[typecheck]   Property 'value' does not exist on type 'Emphasis'.
[typecheck] src/index.ts(97,19): error TS2339: Property 'value' does not exist on type 'Link'.
[typecheck] src/index.ts(163,32): error TS2339: Property 'tagName' does not exist on type 'Parent'.
[typecheck] src/index.ts(164,38): error TS2339: Property 'properties' does not exist on type 'Parent'.
[typecheck] npm run typecheck --silent exited with code 1
--> Sending SIGTERM to other processes..
[test] npm run test --silent -- --coverage exited with code SIGTERM
--> Sending SIGTERM to other processes..
[build] npm run build --silent exited with code SIGTERM
--> Sending SIGTERM to other processes..
[lint] npm run lint --silent exited with code SIGTERM
NPM command npm run setup -- failed with code 1

Originally posted by @kentcdodds in #30 (comment)

Update dependencies to function with updated Remark/Unified

  • remark-embedder-core version: ^1.4.2
  • node version: 14.17.6
  • npm version: 6.14.15

No longer works after upgrading:

unified: ^9.2.2 --> ^10.1.0
remark-rehype: ^8.1.0 --> ^9.1.0
remark-gfm: ^1.0.0 --> ^2.0.0
plus a few others...

my full transformer is:

// TODO: @mapbox/rehype-prism does not have typescript definition
// @ts-ignore
import rehypePrism from '@mapbox/rehype-prism';
import remarkEmbedder, { TransformerInfo } from '@remark-embedder/core';
import oembedTransformer from '@remark-embedder/transformer-oembed';
import rehypeExternalLinks from 'rehype-external-links';
import rehypeStringify from 'rehype-stringify';
import remarkGfm from 'remark-gfm';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import { unified } from 'unified';

type GottenHTML = string | null;

function handleHTML(html: GottenHTML, info: TransformerInfo) {
  const { url, transformer } = info;
  if (transformer.name === '@remark-embedder/transformer-oembed' || url.includes('youtube.com')) {
    return `<div class="embedded-youtube aspect-w-16 aspect-h-9">${html}</div>`;
  }
  return html;
}

export async function markdownToHtml(markdown: string) {
  const result = await unified()
    .use(remarkParse)
    .use(remarkEmbedder, {
      transformers: [oembedTransformer],
      handleHTML,
    })
    .use(remarkGfm)
    .use(remarkRehype)
    .use(rehypeExternalLinks, { target: '_blank' })
    .use(rehypePrism)
    .use(rehypeStringify)
    .process(markdown);
  return result.toString().replace(/@@baseUrl@@/g, process.env.baseUrl || '');
}

What I've tried:

I have attempted to fork and update the base packages, however I'm seeing the following errors with Jest and I don't know how to resolve it:

    Details:

    /Volumes/Sandisk SSD/Development/remark-embedder-core/node_modules/remark/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import {unified} from 'unified'
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import {remark} from 'remark'
        | ^
      2 | import remarkHTML from 'remark-html'
      3 |
      4 | import remarkEmbedder from '../'

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1723:14)
      at Object.<anonymous> (src/__tests__/index.ts:1:1)

Problem with embedding inside react-markdown due to async / await

  • remark-embedder-core version: 3.0.1
  • node version: v16.19.0
  • yarn version: 1.22.19

Relevant code or config

    <ReactMarkdown
        remarkPlugins={[
          remarkGfm,
          [remarkEmbedder, { transformers: [CodeSandboxTransformer] }],
        ]}
      >
        {content}
      </ReactMarkdown>

What you did: I embedded remarkEmbedder in react-markdown.

What happened:

It fails with error:

Uncaught (in promise) Error: `runSync` finished async. Use `run` instead

Problem description:

This happens because react-markdown does not support async plugins.

Suggested solution:

For the basic functionality of remarkEmbedder it doesn't look like it's necessary to do async. Is there a way to set this up so that it's not required?

When I strip the async functionality from the code in my own local copy of index.js it works fine.

htmlToHast returning empty value

  • remark-embedder-core version: 1.2.1
  • node version: 12.18.0
  • npm version: 6.14.4

Relevant code or config

Markdown processing code.

const html = await remark()
    .use(remarkGFM)
    .use(remarkSlug)
    .use(remarkAutolinkHeadings)
    .use(remarkExternalLinks)
    .use(remarkEmbedder, {
        transformers: [twitch, youtube],
    })
    .use(remarkPrism, {transformInlineCode: true})
    .use(remarkHTML)
    .process(content)

YouTube transformer.

const name = "YouTube"

const shouldTransform = url => {
    return url.includes("youtu.be")
}

const getHTML = string => {
    const {pathname, searchParams} = new URL(string)
    const id = pathname.slice(1)
    const start = searchParams.get("t")

    let src = `https://www.youtube-nocookie.com/embed/${id}`

    if (start) {
        src = `${src}?start=${start}`
    }

    const html = `
        <div class="youtube">
            <iframe
                title=${id}
                src=${src}
                frameBorder="0"
                allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
                allowFullScreen
            >
            </iframe>
        </div>
    `

    return html
}

export default {name, shouldTransform, getHTML}

Markdown link.

https://youtu.be/W7y03fsqHJw?t=2503

What you did

Added the @remark-embedder/core package into my markdown parsing workflow and included a custom youtube transformer (which worked in gatsby).

What happened

I can see my transformers being run and returning the appropriate html. However, the node is never updated with the transformed html.

Reproduction repository

https://github.com/bradgarropy/bradgarropy.com/tree/next

Working on a minimal reproduction repository right now.

Problem description

After adding some logs to the module, I've confirmed that the proper html is being returned from the transformer, but the htmlToHast function isn't working as expected.

Here is the return from htmlToHast.

{
  "type": "text",
  "value": "\n        ",
}

Suggested solution

Not sure just yet.

Release

We need to add remark-embedder-bot to the remark-embedder org on npm. Once that's done, then we just need to kick off the most recent action and it should auto-release without trouble (I've already set the npm token).

CI is failing because of updated `unist` types

Due to DefinitelyTyped/DefinitelyTyped#54413, CI is now failing with

Error: [typecheck] src/index.ts(90,14): error TS2339: Property 'title' does not exist on type 'Literal<unknown, Data> & Parent<Node<Data>, Data>'.
Error: [typecheck] src/index.ts(92,26): error TS2339: Property 'value' does not exist on type 'Node<Data>'.
Error: [typecheck] src/index.ts(92,41): error TS2339: Property 'url' does not exist on type 'Literal<unknown, Data> & Parent<Node<Data>, Data>'.
Error: [typecheck] src/index.ts(97,14): error TS2339: Property 'url' does not exist on type 'Literal<unknown, Data> & Parent<Node<Data>, Data>'.
Error: [typecheck] src/index.ts(163,32): error TS2339: Property 'tagName' does not exist on type 'Parent<Node<Data>, Data>'.
Error: [typecheck] src/index.ts(164,38): error TS2339: Property 'properties' does not exist on type 'Parent<Node<Data>, Data>'.

@wooorm Can you point me into the right direction of fixing this please?
I don't have a clue tbh. ๐Ÿค”

Example doesn't work

  • remark-embedder-core version: 3.0.1
  • node version: 18.4.0
  • npm version: 8.13.0

Relevant code or config

Example in the README.

What you did:
Ran the code.

What happened:

Got an error:

import remark from 'remark'
       ^^^^^^
SyntaxError: The requested module 'remark' does not provide an export named 'default'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:128:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:194:5)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:409:24)
    at async loadESM (node:internal/process/esm_loader:85:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12)

Node.js v18.4.0

After fixing this, it runs but does not embed properly.

After fixing that, the URL is completely removed.

Suggested solution:

For the first issue, you must wrap remark in brackets.

For the second, you need to add a .default when using remarkEmbedder.

For the third, you need to add { sanitize: false } when using the remark-html plugin, since otherwise it's sanitization will remove the iframe.

attacher.call is not a function when used in a solid-start/vinxi project

  • remark-embedder-core version: 3.0.2
  • node version: 22.0.0
  • pnpm version: 9.1.1

Relevant code or config

// file: app.config.ts

import { defineConfig } from "@solidjs/start/config";

import mdx from "@vinxi/plugin-mdx";

import remarkEmbedder from "@remark-embedder/core";
import oembedTransformer from "@remark-embedder/transformer-oembed";

export default defineConfig({
  extensions: ["tsx", "mdx", "md"],
  server: {
    preset: "aws-amplify",
  },
  vite: {
    plugins: [
      mdx.default.withImports({})({
        jsx: true,
        jsxImportSource: "solid-js",
        providerImportSource: "solid-mdx",
        remarkPlugins: [
          [
            remarkEmbedder.default,
            { transformers: [oembedTransformer.default] },
          ],
        ],
        enforce: "pre",
      }),
    ],
  },
});

Trying to use this plugin in a SolidStart 1.0 RC project. SolidStart uses vinxi as a build system which provides a wrapper for the vite mdx processor.

When trying to use the plugin, this error occurs when processing an md/mdx file:

  file: src/routes/.../index.md
  at Function.freeze (node_modules/.pnpm/[email protected]/node_modules/unified/lib/index.js:636:36)
  at Function.process (node_modules/.pnpm/[email protected]/node_modules/unified/lib/index.js:716:10)
  at Module.compile (node_modules/.pnpm/@[email protected]/node_modules/@mdx-js/mdx/lib/compile.js:40:35)
  at transform2 (node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@vinxi/plugin-mdx/dist/index.cjs:1535:30)
  at async Object.transform (node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@vinxi/plugin-mdx/dist/index.cjs:2171:16)
  at async transform (node_modules/.pnpm/[email protected]/node_modules/rollup/dist/es/shared/node-entry.js:18680:16)
  at async ModuleLoader.addModuleSource (node_modules/.pnpm/[email protected]/node_modules/rollup/dist/es/shared/node-entry.js:18896:36) 

This issue is the same as the one encountered here and it has an easy workaround.

Just use remarkEmbedder.default instead of remarkEmbedder directly, like I do in the config above. The same goes for the Oembed transformer.

I solved this issue with the debugger but wanted to save someone else the trouble by writing about it here. I'm not sure which piece of the stack is responsible for the problem but the workaround is easy so it's no biggie.

Add class or wrapping div to iframe?

Would it be possible to add a config setting that would allow for class names on the iFrame, or, better yet, a wrapping div with a custom className?

Compiled code causes unexpected issues with ESMs

  • remark-embedder-core version: 3.0.1
  • node version: 18.4.0
  • npm version: 8.13.0

Relevant code or config

Copied directly from example, except added braces around the remark import.

What you did:
Ran the code.

What happened:
Nothing. The output simply created two <p> tags, rather than the embed.

Problem description:
When doing import remarkEmbedder from '@remark-embedder/core' you actually get an object with a single property: default, which then actually contains the function. When passed to unified, this does nothing. In order to use it, you must instead write remarkEmbedder.default, which is rather counterintuitive.

Suggested solution:
Change the build system to include ESM code, for importing.

Plans to update unified dependencies?

  • remark-embedder-core version: 3.0.2
  • node version: 20
  • npm version: 10

What happened:

Most of unified packages have a new version, so it would be nice that this package update it's dependencies.
image

Suggested solution:
Update the packages. I can do it if you can provide me the instructions for it. (updating the package.json?)

Thanks for this package โค๏ธ, it's been really helpful on our project.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.