Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature-request: Support passing hProperties to renderers #384

Closed
bj00rn opened this issue Jan 23, 2020 · 10 comments · Fixed by #563
Closed

feature-request: Support passing hProperties to renderers #384

bj00rn opened this issue Jan 23, 2020 · 10 comments · Fixed by #563
Labels
🦋 type/enhancement This is great to have

Comments

@bj00rn
Copy link

bj00rn commented Jan 23, 2020

I was hoping to be able to use the remark-attr plugin in order to pass attributes from markdown.

remark-attr plugin supports declaring attributes on elements like so:

### This is a title
{id="maintitle" style="color:red;"}

These properties are parsed correctly by the plugin into node.data.hProperties However, properties are not passed on by react-markdown to the renderers.

ast-to-react.js

image

Passing on hProperties would be nice, but maybe it has some security implications.

@bj00rn bj00rn changed the title feature-request: Support passing hProperties to renderers plugin-support: remark-attr - Support passing hProperties to renderers Jan 23, 2020
@bj00rn bj00rn changed the title plugin-support: remark-attr - Support passing hProperties to renderers feature-request: Support passing hProperties to renderers Jan 23, 2020
@arobase-che
Copy link

arobase-che commented Jan 23, 2020

About the security aspect. remark-attr handle a lot of that part. It uses a whitelist approach.

By default, only standard attributes not event based(onclick, on...) are allowed.

@mrm007
Copy link

mrm007 commented Jan 23, 2020

In the meantime, if you like hacks (and who doesn't?) I have this workaround in my project:

  • pass rawSourcePos={true} to ReactMarkdown
  • create a map imageNodes to store references to your image nodes (see code below)
  • pass a function to allowNodes that saves references to image nodes
  • have a custom image renderer which looks up the corresponding node in imageNodes (the node contains data.hProperties)
function MyMarkdown(props) {
  const imageNodes = new Map();
  const nodeKey = position => JSON.stringify(position.start); // or use your own hash function

  function allowNodes(node) {
    if (node.type === "image") imageNodes.set(nodeKey(node.position), node);
    return true;
  }

  const renderers = {
    image: ({ sourcePosition, alt, src, title }) => {
      const node = imageNodes.get(nodeKey(sourcePosition));
      return (
        <img alt={alt} src={src} title={title} {...node.data.hProperties} />
      );
    }
  };

  return (
    <ReactMarkdown
      {...props}
      allowNodes={allowNodes}
      renderers={renderers}
      rawSourcePos
    />
  );
}

You don't need to clean up imageNodes because it will be recreated and disposed on every render.

@bostrom
Copy link

bostrom commented May 19, 2020

Yes, remark-attr support would be great!

@jacobwicks
Copy link

In the meantime, if you like hacks (and who doesn't?) I have this workaround in my project:
...

I used this code to resize images in a project I'm making. I did a short writeup of it on my blog here:

https://jacobwicks.github.io/2020/06/19/rendering-markdown-and-resizing-images-with-react-markdown.html

Thanks for the example!

@ChristianMurphy
Copy link
Member

this will be resolved by #428 which leverages remark-rehype which handles hProperties

@ChristianMurphy ChristianMurphy added the 🦋 type/enhancement This is great to have label Oct 8, 2020
wooorm added a commit that referenced this issue Apr 12, 2021
* Replace `renderers` w/ `components`
* Replace `allowNode` w/ `allowElement`, which is now given a hast element (as
  the first parameter)
* Replace `allowedTypes` w/ `allowedElements`
* Replace `disallowedTypes` w/ `disallowedElements`
* Change signature of `linkTarget` and `transformLinkUri`, which are now given
  hast children (as the second parameter)
* Change signature of `transformImageUri`, which is now given the `alt` string
  as the second parameter (instead of the fourth)
* Replace `plugins` w/ `remarkPlugins` (backwards compatible change)
* Add `rehypePlugins`
* Change `includeNodeIndex` to `includeElementIndex`: it still sets an `index`,
  but that value now represents the number of preceding elements, it also sets a
  `siblingCount` (instead of `parentChildCount`) with the number of sibling
  elements in the parent
* The `columnAlignment` prop is no longer given to table elements: it’s
  available as `style` on `th` and `td` elements instead
* The `spread` prop is no longer given to list elements: it’s already handled

Remove buggy HTML parsers from core

* If you want HTML, add [`rehype-raw`](https://github.com/rehypejs/rehype-raw)
  to `rehypePlugins` and it’ll work without bugs!
* Remove `allowDangerousHtml` (previously called `escapeHtml`) option: pass
  `rehype-raw` in `rehypePlugins` to allow HTML instead
* Remove `with-html.js`, `plugins/html-parser.js` entries from library
* Remove naïve HTML parser too: either use `rehype-raw` to properly support
  HTML, or don’t allow it at all

Closes GH-549.
Closes GH-563.

The following issues are solved as rehype is now available:

Closes GH-522.
Closes GH-465.
Closes GH-427.
Closes GH-384.
Closes GH-356.

The following issues are solved as a proper HTML parser (`rehype-raw`) is now
available:

Closes GH-562.
Closes GH-460.
Closes GH-454.
Closes GH-452.
Closes GH-433.
Closes GH-386.
Closes GH-385.
Closes GH-345.
Closes GH-320.
Closes GH-302.
Closes GH-267.
Closes GH-259.

The following issues are solved as docs are improved:

Closes GH-251.
@wooorm
Copy link
Member

wooorm commented Apr 12, 2021

This should be solved by landing GH-563 today, which will soon be released in v6.0.0!

@colophonemes
Copy link

Is there a trick to using this (other than passing remark-attr to the remarkPlugins array? The following isn't working for me:

import React from 'react'
import ReactMarkdown from 'react-markdown'
import attributes from 'remark-attr'
import behead from 'remark-behead'
import slug from 'remark-slug'

const REMARK_PLUGINS = [
  [behead, { depth: 1 }],
  [slug],
  [attributes],
]

const Markdown = ({ children }) => {
	<ReactMarkdown
      remarkPlugins={REMARK_PLUGINS}
    >
        {children}
      </ReactMarkdown>
}

But this results in the following error:

Error: Missing parser to attach `remark-attr` [link] (to)

This looks like it's caused by this check in remark-attr, which calls the following function:

function isRemarkParser(parser) {
  return Boolean(
    parser &&
    parser.prototype &&
    parser.prototype.inlineTokenizers &&
    parser.prototype.inlineTokenizers.link &&
    parser.prototype.inlineTokenizers.link.locator,
  );
}

(This might be an issue with the remark-attr implementation, so let me know if this is the case and I'll open an issue there)

@wooorm
Copy link
Member

wooorm commented Apr 19, 2021

remark-attr has not updated to the latest parser. See status indications for plugins in the list of plugins. And the issue tracker on that project.

@colophonemes
Copy link

@wooorm thanks so much for the quick response, will keep an eye on that page!

@arobase-che
Copy link

I plan to update remark-attr before September. No guarantee.
As it's need for my use case.

If someone wants deadline or support. We may find a monetary arrangement. Otherwise,I think @wooorm has pretty good alternatives. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🦋 type/enhancement This is great to have
Development

Successfully merging a pull request may close this issue.

8 participants