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

Support custom link attributes through markdown #540

Closed
codler opened this issue Feb 3, 2021 · 4 comments
Closed

Support custom link attributes through markdown #540

codler opened this issue Feb 3, 2021 · 4 comments
Labels
👀 no/external This makes more sense somewhere else 🙋 no/question This does not need any changes

Comments

@codler
Copy link

codler commented Feb 3, 2021

Subject of the feature

Support custom attributes through markdown

Example syntax

[link](url){:target="_blank"}

Problem

https://stackoverflow.com/a/4705645/304894
Im my case I want to be able to set different rel attribute from markdown

Expected behavior

I would get the attributes from renderers

@codler codler added 🙉 open/needs-info This needs some more info 🦋 type/enhancement This is great to have labels Feb 3, 2021
@ChristianMurphy
Copy link
Member

By default react-markdown supports CommonMark only.
However, syntax extensions/plugins can be used to add new syntax features https://github.com/remarkjs/remark/blob/main/doc/plugins.md
The particular syntax you are looking for appears to be https://github.com/arobase-che/remark-attr, which can work with react-markdown but needs an update to do so arobase-che/remark-attr#22

@ChristianMurphy ChristianMurphy added 👀 no/external This makes more sense somewhere else 🙋 no/question This does not need any changes and removed 🙉 open/needs-info This needs some more info 🦋 type/enhancement This is great to have labels Feb 3, 2021
@david-sharer
Copy link

david-sharer commented May 9, 2021

For anyone else who runs into this, I got this working with a custom component for my scenario (I needed call-to-action button-links). All buttons that have <strong> as the first-child [**text here**](... "custom:attribute title text") are rendered as buttons and their title text is parsed for custom attribute strings. Highly limited, but worked for me!
image

// typescript component rendering
import React, { ReactElement } from "react";
import ReactMarkdown from "react-markdown";
import { Components, ReactBaseProps, ReactMarkdownProps } from "react-markdown/src/ast-to-react";
import remarkGfm from "remark-gfm";
import { first, fromPairs } from "lodash";
import { Button } from "@material-ui/core";

const components: Components = {
  a: ({
    node,
    children,
    href,
    title,
    ...props
  }: ReactBaseProps & ReactMarkdownProps & { href: string; title: string }) => {
    // if the first child of the button is a bold element, make this a CTA button
    if ((first(children) as ReactElement)?.type === "strong") {
      const splitTitle = title.split(' ');
      const titleAttrEntries = splitTitle.filter(t => t.includes(':'));
      const remainingTitleEntries = splitTitle.filter(t => !t.includes(':'));
      const finalTitle = remainingTitleEntries.join(' ');
      const titleAttrPairs = titleAttrEntries.map(te => te.split(':'))
      const titleAttrs = fromPairs(titleAttrPairs);
      return (
        <Button variant="contained" href={href} title={finalTitle} {...props} {...titleAttrs}>
          {children}
        </Button>
      );
    }

    return <a href={href} title={title} children={children} {...props}></a>;
  },
};

export function renderMarkdown(markdown: string) {
  return (
    <ReactMarkdown
      plugins={[remarkGfm]}
      children={markdown}
      components={components}/>
  );
}
<!-- markdown -->
[Regular Link](/where_to_go/)

[**CTA Button Link**](/where_to_go/ "color:primary any:attribute things without colons will be treated as the title")

output
image

@Ram-sys179
Copy link

@david-sharer Looks like the ReactBaseProps is deprecated??

@yuri2peter
Copy link

{:target="_blank"}

For anyone else who runs into this, I got this working with a custom component for my scenario (I needed call-to-action button-links). All buttons that have <strong> as the first-child [**text here**](... "custom:attribute title text") are rendered as buttons and their title text is parsed for custom attribute strings. Highly limited, but worked for me! image

// typescript component rendering
import React, { ReactElement } from "react";
import ReactMarkdown from "react-markdown";
import { Components, ReactBaseProps, ReactMarkdownProps } from "react-markdown/src/ast-to-react";
import remarkGfm from "remark-gfm";
import { first, fromPairs } from "lodash";
import { Button } from "@material-ui/core";

const components: Components = {
  a: ({
    node,
    children,
    href,
    title,
    ...props
  }: ReactBaseProps & ReactMarkdownProps & { href: string; title: string }) => {
    // if the first child of the button is a bold element, make this a CTA button
    if ((first(children) as ReactElement)?.type === "strong") {
      const splitTitle = title.split(' ');
      const titleAttrEntries = splitTitle.filter(t => t.includes(':'));
      const remainingTitleEntries = splitTitle.filter(t => !t.includes(':'));
      const finalTitle = remainingTitleEntries.join(' ');
      const titleAttrPairs = titleAttrEntries.map(te => te.split(':'))
      const titleAttrs = fromPairs(titleAttrPairs);
      return (
        <Button variant="contained" href={href} title={finalTitle} {...props} {...titleAttrs}>
          {children}
        </Button>
      );
    }

    return <a href={href} title={title} children={children} {...props}></a>;
  },
};

export function renderMarkdown(markdown: string) {
  return (
    <ReactMarkdown
      plugins={[remarkGfm]}
      children={markdown}
      components={components}/>
  );
}
<!-- markdown -->
[Regular Link](/where_to_go/)

[**CTA Button Link**](/where_to_go/ "color:primary any:attribute things without colons will be treated as the title")

output image

Very useful, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👀 no/external This makes more sense somewhere else 🙋 no/question This does not need any changes
Development

No branches or pull requests

5 participants